Skip to content

Commit

Permalink
Ensure we don't show the error when prepare aborts.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmeasday committed Mar 9, 2022
1 parent 07e73ad commit 539c868
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
34 changes: 23 additions & 11 deletions lib/preview-web/src/PreviewWeb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1326,12 +1326,20 @@ describe('PreviewWeb', () => {
document.location.search = '?id=component-one--a';

const [gate, openGate] = createGate();
importFn.mockImplementationOnce(async (...args) => {
await gate;
return importFn(...args);
});
const preview = new PreviewWeb();
const [importedGate, openImportedGate] = createGate();
importFn
.mockImplementationOnce(async (...args) => {
await gate;
return importFn(...args);
})
.mockImplementationOnce(async (...args) => {
// The second time we `import()` we open the "imported" gate
openImportedGate();
await gate;
return importFn(...args);
});

const preview = new PreviewWeb();
// We can't wait for the initialize function, as it waits for `renderSelection()`
// which prepares, but it does emit `CURRENT_STORY_WAS_SET` right before that
preview.initialize({ importFn, getProjectAnnotations });
Expand All @@ -1343,15 +1351,19 @@ describe('PreviewWeb', () => {
storyId: 'component-one--a',
viewMode: 'story',
});
await waitForRender();
expect(projectAnnotations.renderToDOM).toHaveBeenCalledTimes(1);
await importedGate;
// We are blocking import so this won't render yet
expect(projectAnnotations.renderToDOM).not.toHaveBeenCalled();

mockChannel.emit.mockClear();
projectAnnotations.renderToDOM.mockClear();
openGate();
// The renderToDOM would have been async so we need to wait a tick.
await waitForQuiescence();
expect(projectAnnotations.renderToDOM).not.toHaveBeenCalled();
await waitForRender();

// We should only render *once*
expect(projectAnnotations.renderToDOM).toHaveBeenCalledTimes(1);

// We should not show an error either
expect(preview.view.showErrorDisplay).not.toHaveBeenCalled();
});
});

Expand Down
19 changes: 12 additions & 7 deletions lib/preview-web/src/PreviewWeb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { WebProjectAnnotations } from './types';

import { UrlStore } from './UrlStore';
import { WebView } from './WebView';
import { StoryRender } from './StoryRender';
import { PREPARE_ABORTED, StoryRender } from './StoryRender';
import { DocsRender } from './DocsRender';

const { window: globalWindow, fetch } = global;
Expand All @@ -36,7 +36,6 @@ type StoryCleanupFn = () => MaybePromise<void>;
const STORY_INDEX_PATH = './stories.json';

type HTMLStoryRender<TFramework extends AnyFramework> = StoryRender<HTMLElement, TFramework>;
type HTMLDocsRender<TFramework extends AnyFramework> = DocsRender<TFramework>;

export class PreviewWeb<TFramework extends AnyFramework> {
channel: Channel;
Expand All @@ -59,7 +58,7 @@ export class PreviewWeb<TFramework extends AnyFramework> {

currentSelection: Selection;

currentRender: HTMLStoryRender<TFramework> | HTMLDocsRender<TFramework>;
currentRender: HTMLStoryRender<TFramework> | DocsRender<TFramework>;

storyRenders: HTMLStoryRender<TFramework>[] = [];

Expand Down Expand Up @@ -435,7 +434,8 @@ export class PreviewWeb<TFramework extends AnyFramework> {
this.view.showPreparingDocs();
}

const { currentSelection: lastSelection, currentRender: lastRender } = this;
const lastSelection = this.currentSelection;
let lastRender = this.currentRender;

// If the last render is still preparing, let's drop it right now. Either
// (a) it is a different story, which means we would drop it later, OR
Expand All @@ -445,6 +445,7 @@ export class PreviewWeb<TFramework extends AnyFramework> {
// even though the storyId is the same, the story itself is not).
if (lastRender?.isPreparing()) {
await this.teardownRender(lastRender);
lastRender = null;
}

const storyRender: PreviewWeb<TFramework>['currentRender'] = new StoryRender<
Expand All @@ -467,8 +468,12 @@ export class PreviewWeb<TFramework extends AnyFramework> {
try {
await storyRender.prepare();
} catch (err) {
await this.teardownRender(lastRender);
this.renderStoryLoadingException(storyId, err);
if (err !== PREPARE_ABORTED) {
// We are about to render an error so make sure the previous story is
// no longer rendered.
await this.teardownRender(lastRender);
this.renderStoryLoadingException(storyId, err);
}
return;
}
const implementationChanged = !storyIdChanged && !storyRender.isEqual(lastRender);
Expand Down Expand Up @@ -545,7 +550,7 @@ export class PreviewWeb<TFramework extends AnyFramework> {
}

async teardownRender(
render: HTMLStoryRender<TFramework> | HTMLDocsRender<TFramework>,
render: HTMLStoryRender<TFramework> | DocsRender<TFramework>,
{ viewModeChanged }: { viewModeChanged?: boolean } = {}
) {
this.storyRenders = this.storyRenders.filter((r) => r !== render);
Expand Down
4 changes: 3 additions & 1 deletion lib/preview-web/src/StoryRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export type RenderContextCallbacks<TFramework extends AnyFramework> = Pick<
'showMain' | 'showError' | 'showException'
>;

export const PREPARE_ABORTED = new Error('prepareAborted');

export class StoryRender<
CanvasElement extends HTMLElement | void,
TFramework extends AnyFramework
Expand Down Expand Up @@ -97,7 +99,7 @@ export class StoryRender<

if (this.abortController.signal.aborted) {
this.store.cleanupStory(this.story);
throw new Error('Story render aborted during preparation');
throw PREPARE_ABORTED;
}
}

Expand Down

0 comments on commit 539c868

Please sign in to comment.