Skip to content

Commit

Permalink
Merge pull request #30063 from storybookjs/version-non-patch-from-8.5…
Browse files Browse the repository at this point in the history
….0-alpha.22

Release: Prerelease beta 8.5.0-beta.0
  • Loading branch information
vanessayuenn authored Dec 16, 2024
2 parents d821e7f + 70bfeb2 commit 6cda454
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 120 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/tests-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Set node version
uses: actions/setup-node@v4
with:
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 8.5.0-beta.0

- Automigration: Improve setup file transformation and version range handling for a11y migration - [#30060](https://github.com/storybookjs/storybook/pull/30060), thanks @valentinpalkovic!
- Next.js: Support v15.1.1 - [#30068](https://github.com/storybookjs/storybook/pull/30068), thanks @valentinpalkovic!

## 8.5.0-alpha.22

- Addon Docs: Dynamically import rehype - [#29544](https://github.com/storybookjs/storybook/pull/29544), thanks @valentinpalkovic!
Expand Down
8 changes: 6 additions & 2 deletions code/e2e-tests/composition.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ test.describe('composition', () => {

await page.locator('[id="storybook\\@7\\.6\\.18_components-badge"]').click();
await expect(
page.locator('[id="storybook\\@7\\.6\\.18_components-badge--default"]')
).toBeVisible();
page
.locator('iframe[title="storybook-ref-storybook\\@7\\.6\\.18"]')
.contentFrame()
.locator('#storybook-root')
.getByText('Default')
).toBeVisible({ timeout: 15000 });

// Expect composed stories `to be available in the search
await page.getByPlaceholder('Find components').fill('Button');
Expand Down
48 changes: 47 additions & 1 deletion code/e2e-tests/util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable local-rules/no-uncategorized-errors */
import { toId } from '@storybook/csf';

import type { Expect, Page } from '@playwright/test';
Expand Down Expand Up @@ -61,6 +62,7 @@ export class SbPage {
await this.expect(selected).toHaveAttribute('data-selected', 'true');

await this.previewRoot();
await this.waitUntilLoaded();
}

async navigateToUnattachedDocs(title: string, name = 'docs') {
Expand All @@ -80,7 +82,25 @@ export class SbPage {
const selected = storyLink;
await this.expect(selected).toHaveAttribute('data-selected', 'true');

await this.previewRoot();
await this.waitForStoryLoaded();
}

async waitForStoryLoaded() {
try {
const root = this.previewRoot();
// Wait until there is at least one child (a story element) in the preview iframe
await root.locator(':scope > *').first().waitFor({
state: 'attached',
timeout: 10000,
});
} catch (error: any) {
if (error.name === 'TimeoutError') {
throw new Error(
'The Storybook iframe did not have children within the specified timeout. Did the story load correctly?'
);
}
throw error;
}
}

async waitUntilLoaded() {
Expand Down Expand Up @@ -112,6 +132,8 @@ export class SbPage {
const storyLoadingPage = root.locator('.sb-preparing-story');
await docsLoadingPage.waitFor({ state: 'hidden' });
await storyLoadingPage.waitFor({ state: 'hidden' });

await this.waitForStoryLoaded();
}

previewIframe() {
Expand Down Expand Up @@ -143,6 +165,30 @@ export class SbPage {
getCanvasBodyElement() {
return this.previewIframe().locator('body');
}

// utility to try and decrease flake
async retryTimes(
fn: () => Promise<void>,
options?: {
retries?: number;
delay?: number;
}
): Promise<void> {
let attempts = 0;
const { retries = 3, delay = 0 } = options || {};
while (attempts < retries) {
try {
await fn();
return;
} catch (error) {
attempts++;
if (attempts === retries) {
throw error;
}
await new Promise<void>((resolve) => setTimeout(resolve, delay));
}
}
}
}

const templateName: keyof typeof allTemplates = process.env.STORYBOOK_TEMPLATE_NAME || ('' as any);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ function getSelectedParams(currentTree: FlightRouterState, params: Params = {}):
continue;
}

// Ensure catchAll and optional catchall are turned into an array

// Ensure catchAll and optional catchall are turned into an array
const isCatchAll = isDynamicParameter && (segment[2] === 'c' || segment[2] === 'oc');

Expand Down Expand Up @@ -82,6 +80,16 @@ export const AppRouterProvider: React.FC<React.PropsWithChildren<AppRouterProvid
return getSelectedParams(tree);
}, [tree]);

const newLazyCacheNode = {
lazyData: null,
rsc: null,
prefetchRsc: null,
head: null,
prefetchHead: null,
parallelRoutes: new Map(),
loading: null,
};

// https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/app-router.tsx#L436
return (
<PathParamsContext.Provider value={pathParams}>
Expand All @@ -106,10 +114,18 @@ export const AppRouterProvider: React.FC<React.PropsWithChildren<AppRouterProvid
<AppRouterContext.Provider value={getRouter()}>
<LayoutRouterContext.Provider
value={{
// TODO Remove when dropping Next.js < v15.1.1
childNodes: new Map(),
loading: null,
tree,
// TODO END

// START Next.js v15.2 support
// @ts-expect-error Only available in Next.js >= v15.1.1
parentTree: tree,
parentCacheNode: newLazyCacheNode,
// END
url: pathname,
loading: null,
}}
>
{children}
Expand Down
18 changes: 18 additions & 0 deletions code/frameworks/nextjs/src/routing/app-router-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ export const AppRouterProvider: React.FC<React.PropsWithChildren<AppRouterProvid
return getSelectedParams(tree);
}, [tree]);

const newLazyCacheNode = {
lazyData: null,
rsc: null,
prefetchRsc: null,
head: null,
prefetchHead: null,
parallelRoutes: new Map(),
loading: null,
};

// https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/app-router.tsx#L436
return (
<PathParamsContext.Provider value={pathParams}>
Expand All @@ -104,8 +114,16 @@ export const AppRouterProvider: React.FC<React.PropsWithChildren<AppRouterProvid
<AppRouterContext.Provider value={getRouter()}>
<LayoutRouterContext.Provider
value={{
// TODO Remove when dropping Next.js < v15.1.1
childNodes: new Map(),
tree,
// TODO END

// START Next.js v15.2 support
// @ts-expect-error Only available in Next.js >= v15.1.1
parentTree: tree,
parentCacheNode: newLazyCacheNode,
// END
url: pathname,
loading: null,
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ describe('addonA11yAddonTest', () => {
`;
vi.mocked(readFileSync).mockReturnValue(source);

const transformedCode = transformSetupFile(setupFile);
const s = readFileSync(setupFile, 'utf8');
const transformedCode = transformSetupFile(s);
expect(transformedCode).toMatchInlineSnapshot(`
"import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
import { beforeAll } from 'vitest';
Expand Down Expand Up @@ -169,7 +170,35 @@ describe('addonA11yAddonTest', () => {
`;
vi.mocked(readFileSync).mockReturnValue(source);

const transformedCode = transformSetupFile(setupFile);
const s = readFileSync(setupFile, 'utf8');
const transformedCode = transformSetupFile(s);
expect(transformedCode).toMatchInlineSnapshot(`
"import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
import { beforeAll } from 'vitest';
import { setProjectAnnotations } from 'storybook';
import * as projectAnnotations from './preview';
const project = setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);
beforeAll(project.beforeAll);"
`);
});

it('should transform setup file correctly - project annotation is not an array', () => {
const setupFile = '/path/to/vitest.setup.ts';
const source = dedent`
import { beforeAll } from 'vitest';
import { setProjectAnnotations } from 'storybook';
import * as projectAnnotations from './preview';
const project = setProjectAnnotations(projectAnnotations);
beforeAll(project.beforeAll);
`;
vi.mocked(readFileSync).mockReturnValue(source);

const s = readFileSync(setupFile, 'utf8');
const transformedCode = transformSetupFile(s);
expect(transformedCode).toMatchInlineSnapshot(`
"import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
import { beforeAll } from 'vitest';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ interface AddonA11yAddonTestOptions {
*/
export const addonA11yAddonTest: Fix<AddonA11yAddonTestOptions> = {
id: 'addonA11yAddonTest',
// TODO: Change to the correct version after testing
versionRange: ['<8.5.0', '*'],
versionRange: ['<8.5.0', '>=8.5.0'],

promptType(result) {
if (result.setupFile === null) {
Expand Down Expand Up @@ -53,7 +52,11 @@ export const addonA11yAddonTest: Fix<AddonA11yAddonTestOptions> = {

try {
if (vitestSetupFile) {
const transformedSetupCode = transformSetupFile(vitestSetupFile);
const source = readFileSync(vitestSetupFile, 'utf8');
if (source.includes('@storybook/addon-a11y')) {
return null;
}
const transformedSetupCode = transformSetupFile(source);
return {
setupFile: vitestSetupFile,
transformedSetupCode,
Expand Down Expand Up @@ -124,8 +127,7 @@ export const addonA11yAddonTest: Fix<AddonA11yAddonTestOptions> = {
},
};

export function transformSetupFile(setupFile: string) {
const source = readFileSync(setupFile, 'utf8');
export function transformSetupFile(source: string) {
const j = jscodeshift.withParser('ts');

const root = j(source);
Expand All @@ -148,9 +150,14 @@ export function transformSetupFile(setupFile: string) {
throw new Error('Could not find setProjectAnnotations call in vitest.setup file');
}

// Add a11yAddonAnnotations to the annotations array
setProjectAnnotationsCall.find(j.ArrayExpression).forEach((p) => {
p.value.elements.unshift(j.identifier('a11yAddonAnnotations'));
// Add a11yAddonAnnotations to the annotations array or create a new array if argument is a string
setProjectAnnotationsCall.forEach((p) => {
if (p.value.arguments.length === 1 && p.value.arguments[0].type === 'ArrayExpression') {
p.value.arguments[0].elements.unshift(j.identifier('a11yAddonAnnotations'));
} else if (p.value.arguments.length === 1 && p.value.arguments[0].type === 'Identifier') {
const arg = p.value.arguments[0];
p.value.arguments[0] = j.arrayExpression([j.identifier('a11yAddonAnnotations'), arg]);
}
});

// Add the import declaration at the top
Expand Down
1 change: 1 addition & 0 deletions code/nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"extends": "nx/presets/npm.json",
"nxCloudAccessToken": "NGVmYTkxMmItYzY3OS00MjkxLTk1ZDktZDFmYTFmNmVlNGY4fHJlYWQ=",
"defaultBase": "next",
"useLegacyCache": true,
"parallel": 8,
"plugins": [
{
Expand Down
11 changes: 6 additions & 5 deletions code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@
"dependencies": {
"@chromatic-com/storybook": "^3.2.0",
"@happy-dom/global-registrator": "^14.12.0",
"@nx/eslint": "20.1.4",
"@nx/vite": "20.1.4",
"@nx/workspace": "20.1.4",
"@nx/eslint": "20.2.2",
"@nx/vite": "20.2.2",
"@nx/workspace": "20.2.2",
"@playwright/test": "1.48.1",
"@storybook/addon-a11y": "workspace:*",
"@storybook/addon-actions": "workspace:*",
Expand Down Expand Up @@ -202,7 +202,7 @@
"husky": "^4.3.7",
"lint-staged": "^13.2.2",
"mock-require": "^3.0.3",
"nx": "20.1.4",
"nx": "20.2.2",
"prettier": "^3.1.1",
"prettier-plugin-brace-style": "^0.6.2",
"prettier-plugin-css-order": "^2.1.2",
Expand Down Expand Up @@ -294,5 +294,6 @@
"Dependency Upgrades"
]
]
}
},
"deferredNextVersion": "8.5.0-beta.0"
}
Loading

0 comments on commit 6cda454

Please sign in to comment.