add E2E tests for beforeAll hook and HMR

This commit is contained in:
Yann Braga 2024-06-18 15:03:00 +02:00
parent ee0653d65d
commit 012c28fb8b
3 changed files with 98 additions and 1 deletions

View File

@ -0,0 +1,77 @@
/* eslint-disable no-underscore-dangle */
import { join } from 'node:path';
import { promises as fs } from 'node:fs';
import { test } from '@playwright/test';
import { SbPage } from './util';
declare global {
interface Window {
__STORYBOOK_BEFORE_ALL_CALLS__: number;
__STORYBOOK_BEFORE_ALL_CLEANUP_CALLS__: number;
}
}
const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:8001';
const templateName = process.env.STORYBOOK_TEMPLATE_NAME || '';
const sandboxDir =
process.env.STORYBOOK_SANDBOX_DIR ||
join(__dirname, '..', '..', 'sandbox', 'react-vite-default-ts');
const previewFilePath = join(sandboxDir, '.storybook', 'preview.ts');
const isStorybookDev = process.env.STORYBOOK_TYPE === 'dev';
test.describe('Storybook hooks', () => {
test.skip(
!templateName?.includes('react-vite/default-ts'),
'Only run this test for react-vite sandbox'
);
test.beforeEach(async ({ page }) => {
await page.goto(storybookUrl);
await new SbPage(page).waitUntilLoaded();
});
test('should call beforeAll upon loading Storybook', async ({ page }, { titlePath }) => {
const sbPage = new SbPage(page);
await sbPage.navigateToStory('example/button', 'primary');
await page.waitForFunction(
() =>
window.__STORYBOOK_BEFORE_ALL_CALLS__ === 1 &&
window.__STORYBOOK_BEFORE_ALL_CLEANUP_CALLS__ === 0,
undefined,
{ timeout: 2000 }
);
});
test('should call beforeAll and cleanup on HMR', async ({ page }, { titlePath }) => {
test.skip(!isStorybookDev, 'HMR is only applicable in dev mode');
const sbPage = new SbPage(page);
await sbPage.navigateToStory('example/button', 'primary');
const originalContent = await fs.readFile(previewFilePath, 'utf8');
const newContent = `${originalContent}\nconsole.log('Written from E2E test: ${titlePath}');`;
await page.waitForFunction(
() =>
window.__STORYBOOK_BEFORE_ALL_CALLS__ === 1 &&
window.__STORYBOOK_BEFORE_ALL_CLEANUP_CALLS__ === 0,
undefined,
{ timeout: 2000 }
);
// Save the file to trigger HMR, then wait for it
await fs.writeFile(previewFilePath, newContent);
await page.waitForFunction(
() =>
window.__STORYBOOK_BEFORE_ALL_CALLS__ === 2 &&
window.__STORYBOOK_BEFORE_ALL_CLEANUP_CALLS__ === 1,
undefined,
{ timeout: 2000 }
);
// Restore the original content of the preview file
await fs.writeFile(previewFilePath, originalContent);
});
});

View File

@ -1,5 +1,24 @@
/* eslint-disable no-underscore-dangle */
import type { PartialStoryFn, StoryContext } from '@storybook/types';
declare global {
interface Window {
__STORYBOOK_BEFORE_ALL_CALLS__: number;
__STORYBOOK_BEFORE_ALL_CLEANUP_CALLS__: number;
}
}
// This is used to test the hooks in our E2E tests (look for storybook-hooks.spec.ts)
globalThis.parent.__STORYBOOK_BEFORE_ALL_CALLS__ = 0;
globalThis.parent.__STORYBOOK_BEFORE_ALL_CLEANUP_CALLS__ = 0;
export const beforeAll = async () => {
globalThis.parent.__STORYBOOK_BEFORE_ALL_CALLS__ += 1;
return () => {
globalThis.parent.__STORYBOOK_BEFORE_ALL_CLEANUP_CALLS__ += 1;
};
};
export const parameters = {
projectParameter: 'projectParameter',
storyObject: {

View File

@ -12,7 +12,7 @@ export const e2eTestsBuild: Task & { port: number; type: 'build' | 'dev' } = {
async ready() {
return false;
},
async run({ codeDir, junitFilename, key }, { dryRun, debug }) {
async run({ codeDir, junitFilename, key, sandboxDir }, { dryRun, debug }) {
if (process.env.DEBUG) {
console.log(dedent`
Running e2e tests in Playwright's ui mode for chromium only (for brevity sake).
@ -31,6 +31,7 @@ export const e2eTestsBuild: Task & { port: number; type: 'build' | 'dev' } = {
STORYBOOK_URL: `http://localhost:${this.port}`,
STORYBOOK_TYPE: this.type,
STORYBOOK_TEMPLATE_NAME: key,
STORYBOOK_SANDBOX_DIR: sandboxDir,
...(junitFilename && {
PLAYWRIGHT_JUNIT_OUTPUT_NAME: junitFilename,
}),