Skip to content

Commit

Permalink
Merge pull request #24345 from storybookjs/norbert/fix-24292
Browse files Browse the repository at this point in the history
ManagerAPI: Fix bug with story redirection when URL has partial storyId
  • Loading branch information
ndelangen authored Oct 5, 2023
2 parents 7823426 + 4c49a5a commit a1963a3
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
18 changes: 18 additions & 0 deletions code/e2e-tests/navigation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { test, expect } from '@playwright/test';
import process from 'process';
import { SbPage } from './util';

const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001';

test.describe('navigating', () => {
test('a URL with a partial storyId will redirect to the first story', async ({ page }) => {
// this is purposefully not using the SbPage class, and the URL is a partial (it does not contain the full storyId)
await page.goto(`${storybookUrl}?path=/story/example-button`);

const sbPage = new SbPage(page);

await sbPage.waitUntilLoaded();

await expect(sbPage.page.url()).toContain('/docs/example-button--docs');
});
});
7 changes: 5 additions & 2 deletions code/lib/manager-api/src/modules/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,15 +637,18 @@ export const init: ModuleFn<SubAPI, SubState> = ({
state.path === '/' || state.viewMode === 'story' || state.viewMode === 'docs';
const stateHasSelection = state.viewMode && state.storyId;
const stateSelectionDifferent = state.viewMode !== viewMode || state.storyId !== storyId;
const { type } = state.index[state.storyId] || {};
const isStory = !(type === 'root' || type === 'component' || type === 'group');

/**
* When storybook starts, we want to navigate to the first story.
* But there are a few exceptions:
* - If the current storyId and viewMode are already set/correct.
* - If the current storyId and viewMode are already set/correct AND the url section is a leaf-type.
* - If the user has navigated away already.
* - If the user started storybook with a specific page-URL like "/settings/about"
*/
if (isCanvasRoute) {
if (stateHasSelection && stateSelectionDifferent) {
if (stateHasSelection && stateSelectionDifferent && isStory) {
// The manager state is correct, the preview state is lagging behind
provider.channel.emit(SET_CURRENT_STORY, {
storyId: state.storyId,
Expand Down
12 changes: 8 additions & 4 deletions code/lib/manager-api/src/tests/stories.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,31 +542,35 @@ describe('stories API', () => {

describe('STORY_SPECIFIED event', () => {
it('navigates to the story', async () => {
const moduleArgs = createMockModuleArgs({ initialState: { path: '/' } });
const moduleArgs = createMockModuleArgs({ initialState: { path: '/', index: {} } });
initStories(moduleArgs as unknown as ModuleArgs);
const { navigate, provider } = moduleArgs;

provider.channel.emit(STORY_SPECIFIED, { storyId: 'a--1', viewMode: 'story' });
expect(navigate).toHaveBeenCalledWith('/story/a--1');
});
it('DOES not navigate if the story was already selected', async () => {
const moduleArgs = createMockModuleArgs({ initialState: { path: '/story/a--1' } });
const moduleArgs = createMockModuleArgs({ initialState: { path: '/story/a--1', index: {} } });
initStories(moduleArgs as unknown as ModuleArgs);
const { navigate, provider } = moduleArgs;

provider.channel.emit(STORY_SPECIFIED, { storyId: 'a--1', viewMode: 'story' });
expect(navigate).not.toHaveBeenCalled();
});
it('DOES not navigate if a settings page was selected', async () => {
const moduleArgs = createMockModuleArgs({ initialState: { path: '/settings/about' } });
const moduleArgs = createMockModuleArgs({
initialState: { path: '/settings/about', index: {} },
});
initStories(moduleArgs as unknown as ModuleArgs);
const { navigate, provider } = moduleArgs;

provider.channel.emit(STORY_SPECIFIED, { storyId: 'a--1', viewMode: 'story' });
expect(navigate).not.toHaveBeenCalled();
});
it('DOES not navigate if a custom page was selected', async () => {
const moduleArgs = createMockModuleArgs({ initialState: { path: '/custom/page' } });
const moduleArgs = createMockModuleArgs({
initialState: { path: '/custom/page', index: {} },
});
initStories(moduleArgs as unknown as ModuleArgs);
const { navigate, provider } = moduleArgs;

Expand Down

0 comments on commit a1963a3

Please sign in to comment.