From 15d5d938a8f6b8809fabaa289cf7fd56ecbd2ae8 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Tue, 9 Jan 2024 22:49:47 +1100 Subject: [PATCH 01/11] Add a `--playwright` flag When set, build storybook by directly invoking the binary from `@chromaui/test-archiver`. This is a POC, we will move this binary into a `chromatic-playwright` package soon. --- node-src/lib/getConfiguration.ts | 1 + node-src/lib/getOptions.ts | 6 +++++ node-src/tasks/build.ts | 40 ++++++++++++++++++++++++-------- node-src/types.ts | 4 ++++ 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/node-src/lib/getConfiguration.ts b/node-src/lib/getConfiguration.ts index eff09345c..fb46ecc71 100644 --- a/node-src/lib/getConfiguration.ts +++ b/node-src/lib/getConfiguration.ts @@ -25,6 +25,7 @@ const configurationSchema = z ignoreLastBuildOnBranch: z.string(), buildScriptName: z.string(), + playwright: z.boolean(), outputDir: z.string(), skip: z.union([z.string(), z.boolean()]), diff --git a/node-src/lib/getOptions.ts b/node-src/lib/getOptions.ts index 7cacc9cfc..eecbc08cf 100644 --- a/node-src/lib/getOptions.ts +++ b/node-src/lib/getOptions.ts @@ -71,6 +71,7 @@ export default function getOptions({ preserveMissingSpecs: undefined, buildScriptName: undefined, + playwright: undefined, outputDir: undefined, allowConsoleErrors: undefined, storybookBuildDir: undefined, @@ -128,6 +129,7 @@ export default function getOptions({ flags.preserveMissing || typeof flags.only === 'string' ? true : undefined, buildScriptName: flags.buildScriptName, + playwright: trueIfSet(flags.playwright), outputDir: takeLast(flags.outputDir), allowConsoleErrors: flags.allowConsoleErrors, storybookBuildDir: takeLast(flags.storybookBuildDir), @@ -254,6 +256,10 @@ export default function getOptions({ return options; } + if (options.playwright) { + return options; + } + const { scripts } = packageJson; if (typeof buildScriptName !== 'string') { buildScriptName = 'build-storybook'; diff --git a/node-src/tasks/build.ts b/node-src/tasks/build.ts index 64a7236da..92793e387 100644 --- a/node-src/tasks/build.ts +++ b/node-src/tasks/build.ts @@ -1,6 +1,6 @@ import { execaCommand } from 'execa'; import { createWriteStream, readFileSync } from 'fs'; -import path from 'path'; +import path, { dirname, resolve } from 'path'; import semver from 'semver'; import tmp from 'tmp-promise'; @@ -34,15 +34,35 @@ export const setBuildCommand = async (ctx: Context) => { ctx.log.warn('Storybook version 6.2.0 or later is required to use the --only-changed flag'); } - ctx.buildCommand = await getPackageManagerRunCommand( - [ + const buildCommandOptions = [ + '--output-dir', + ctx.sourceDir, + ctx.git.changedFiles && webpackStatsSupported && '--webpack-stats-json', + ctx.git.changedFiles && webpackStatsSupported && ctx.sourceDir, + ].filter(Boolean); + + if (ctx.options.playwright) { + try { + const archiveSBLocation = dirname(require.resolve('@chromaui/archive-storybook/package.json')); + console.log(archiveSBLocation); + const binPath = resolve(archiveSBLocation, './dist/bin/build-archive-storybook'); + ctx.buildCommand = ['node', binPath, ...buildCommandOptions].join(' '); + console.log(ctx.buildCommand); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + // We should use a proper CLI error here. + throw new Error( + `It looks like you don't have '@chromaui/archive-storybook' installed, please install it!` + ); + } + throw err; + } + } else { + ctx.buildCommand = await getPackageManagerRunCommand([ ctx.options.buildScriptName, - '--output-dir', - ctx.sourceDir, - ctx.git.changedFiles && webpackStatsSupported && '--webpack-stats-json', - ctx.git.changedFiles && webpackStatsSupported && ctx.sourceDir, - ].filter(Boolean) - ); + ...buildCommandOptions, + ]); + } }; const timeoutAfter = (ms) => @@ -67,7 +87,7 @@ export const buildStorybook = async (ctx: Context) => { const subprocess = execaCommand(ctx.buildCommand, { stdio: [null, logFile, logFile], signal, - env: { NODE_ENV: ctx.env.STORYBOOK_NODE_ENV || 'production' }, + env: { NODE_ENV: ctx.env.STORYBOOK_NODE_ENV || 'production' }, }); await Promise.race([subprocess, timeoutAfter(ctx.env.STORYBOOK_BUILD_TIMEOUT)]); } catch (e) { diff --git a/node-src/types.ts b/node-src/types.ts index 7b3d6b285..119d9b188 100644 --- a/node-src/types.ts +++ b/node-src/types.ts @@ -14,6 +14,9 @@ export interface Flags { outputDir?: string[]; storybookBuildDir?: string[]; + // E2E options + playwright?: boolean; + // Chromatic options autoAcceptChanges?: string; branchName?: string; @@ -90,6 +93,7 @@ export interface Options extends Configuration { originalArgv: string[]; buildScriptName: Flags['buildScriptName']; + playwright: Flags['playwright'], outputDir: string; allowConsoleErrors: Flags['allowConsoleErrors']; url?: string; From dc7517f3261a1895ee4b8bbd9420612149f473db Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Sat, 13 Jan 2024 21:49:59 +1100 Subject: [PATCH 02/11] Add proper error and exit code --- node-src/lib/setExitCode.ts | 1 + node-src/tasks/build.ts | 19 +++++++++---------- .../errors/missingDependency.stories.ts | 8 ++++++++ .../ui/messages/errors/missingDependency.ts | 11 +++++++++++ 4 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 node-src/ui/messages/errors/missingDependency.stories.ts create mode 100644 node-src/ui/messages/errors/missingDependency.ts diff --git a/node-src/lib/setExitCode.ts b/node-src/lib/setExitCode.ts index 4c97a5030..976387f2d 100644 --- a/node-src/lib/setExitCode.ts +++ b/node-src/lib/setExitCode.ts @@ -35,6 +35,7 @@ export const exitCodes = { // I/O errors FETCH_ERROR: 201, GRAPHQL_ERROR: 202, + MISSING_DEPENDENCY: 210, INVALID_OPTIONS: 254, }; diff --git a/node-src/tasks/build.ts b/node-src/tasks/build.ts index 92793e387..74e080a64 100644 --- a/node-src/tasks/build.ts +++ b/node-src/tasks/build.ts @@ -1,6 +1,6 @@ import { execaCommand } from 'execa'; import { createWriteStream, readFileSync } from 'fs'; -import path, { dirname, resolve } from 'path'; +import path, { dirname } from 'path'; import semver from 'semver'; import tmp from 'tmp-promise'; @@ -11,6 +11,7 @@ import { endActivity, startActivity } from '../ui/components/activity'; import buildFailed from '../ui/messages/errors/buildFailed'; import { failed, initial, pending, skipped, success } from '../ui/tasks/build'; import { getPackageManagerRunCommand } from '../lib/getPackageManager'; +import missingDependency from '../ui/messages/errors/missingDependency'; export const setSourceDir = async (ctx: Context) => { if (ctx.options.outputDir) { @@ -41,19 +42,17 @@ export const setBuildCommand = async (ctx: Context) => { ctx.git.changedFiles && webpackStatsSupported && ctx.sourceDir, ].filter(Boolean); - if (ctx.options.playwright) { + if (ctx.options.playwright || ctx.options.cypress) { + const flag = ctx.options.playwright ? 'playwright' : 'cypress'; + const dependencyName = `chromatic-${flag}`; try { - const archiveSBLocation = dirname(require.resolve('@chromaui/archive-storybook/package.json')); - console.log(archiveSBLocation); - const binPath = resolve(archiveSBLocation, './dist/bin/build-archive-storybook'); + const binPath = dirname(require.resolve(`${dependencyName}/bin/build-archive-storybook`)); ctx.buildCommand = ['node', binPath, ...buildCommandOptions].join(' '); - console.log(ctx.buildCommand); } catch (err) { if (err.code === 'MODULE_NOT_FOUND') { - // We should use a proper CLI error here. - throw new Error( - `It looks like you don't have '@chromaui/archive-storybook' installed, please install it!` - ); + ctx.log.error(missingDependency({ dependencyName, flag })); + setExitCode(ctx, exitCodes.MISSING_DEPENDENCY, true); + throw new Error(failed(ctx).output); } throw err; } diff --git a/node-src/ui/messages/errors/missingDependency.stories.ts b/node-src/ui/messages/errors/missingDependency.stories.ts new file mode 100644 index 000000000..42ccfae2d --- /dev/null +++ b/node-src/ui/messages/errors/missingDependency.stories.ts @@ -0,0 +1,8 @@ +import missingDependency from './missingDependency'; + +export default { + title: 'CLI/Messages/Errors', +}; + +export const MissingDependency = () => + missingDependency({ dependencyName: 'chromatic-playwright', flag: 'playwright' }); diff --git a/node-src/ui/messages/errors/missingDependency.ts b/node-src/ui/messages/errors/missingDependency.ts new file mode 100644 index 000000000..dd563305a --- /dev/null +++ b/node-src/ui/messages/errors/missingDependency.ts @@ -0,0 +1,11 @@ +import chalk from 'chalk'; +import { dedent } from 'ts-dedent'; +import { error, info } from '../../components/icons'; + +export default ({ dependencyName, flag }: { dependencyName: string; flag: string }) => { + return dedent(chalk` + ${error} Failed to import \`${dependencyName}\`, is it installed in \`package.json\`? + + ${info} To run \`chromatic --${flag}\` you must have \`${dependencyName}\` installed. + `); +}; From 2d4ccbd6651bd0184295a47dfc493c9b2750edd5 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Sat, 13 Jan 2024 21:53:10 +1100 Subject: [PATCH 03/11] Add cypress flag --- action-src/main.ts | 4 ++++ action.yml | 5 +++++ node-src/types.ts | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/action-src/main.ts b/action-src/main.ts index 5357349a1..a14225a57 100755 --- a/action-src/main.ts +++ b/action-src/main.ts @@ -94,6 +94,7 @@ async function run() { const branchName = getInput('branchName'); const buildScriptName = getInput('buildScriptName'); const configFile = getInput('configFile'); + const cypress = getInput('cypress'); const debug = getInput('debug'); const diagnosticsFile = getInput('diagnosticsFile') || getInput('diagnostics'); const dryRun = getInput('dryRun'); @@ -107,6 +108,7 @@ async function run() { const onlyChanged = getInput('onlyChanged'); const onlyStoryFiles = getInput('onlyStoryFiles'); const onlyStoryNames = getInput('onlyStoryNames'); + const playwright = getInput('playwright'); const preserveMissing = getInput('preserveMissing'); const projectToken = getInput('projectToken') || getInput('appCode'); // backwards compatibility const repositorySlug = getInput('repositorySlug'); @@ -139,6 +141,7 @@ async function run() { branchName: maybe(branchName), buildScriptName: maybe(buildScriptName), configFile: maybe(configFile), + cypress: maybe(cypress), debug: maybe(debug), diagnosticsFile: maybe(diagnosticsFile), dryRun: maybe(dryRun), @@ -153,6 +156,7 @@ async function run() { onlyChanged: maybe(onlyChanged), onlyStoryFiles: maybe(onlyStoryFiles), onlyStoryNames: maybe(onlyStoryNames), + playwright: maybe(playwright), preserveMissing: maybe(preserveMissing), projectToken, repositorySlug: maybe(repositorySlug), diff --git a/action.yml b/action.yml index 654f1b47a..615354de5 100755 --- a/action.yml +++ b/action.yml @@ -23,6 +23,8 @@ inputs: required: false configFile: description: 'Path from where to load the Chromatic config JSON file.' + cypress: + description: 'Run build against `chromatic-cypress` test archives' required: false debug: description: 'Output verbose debugging information' @@ -66,6 +68,9 @@ inputs: onlyStoryFiles: description: 'Only run a single story or a subset of stories by their filename(s)' required: false + playwright: + description: 'Run build against `chromatic-playwright` test archives' + required: false preserveMissing: description: 'Deprecated, use onlyChanged, onlyStoryNames or onlyStoryFiles instead' required: false diff --git a/node-src/types.ts b/node-src/types.ts index 119d9b188..908d7951b 100644 --- a/node-src/types.ts +++ b/node-src/types.ts @@ -16,6 +16,7 @@ export interface Flags { // E2E options playwright?: boolean; + cypress?: boolean; // Chromatic options autoAcceptChanges?: string; @@ -93,7 +94,8 @@ export interface Options extends Configuration { originalArgv: string[]; buildScriptName: Flags['buildScriptName']; - playwright: Flags['playwright'], + playwright: Flags['playwright']; + cypress: Flags['cypress']; outputDir: string; allowConsoleErrors: Flags['allowConsoleErrors']; url?: string; From 60023f59ecc2066bbbb535e38cbddf988c31302b Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Sat, 13 Jan 2024 22:32:44 +1100 Subject: [PATCH 04/11] Only allow one of --playwright/--cypress --- node-src/lib/getConfiguration.ts | 1 + node-src/lib/getOptions.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/node-src/lib/getConfiguration.ts b/node-src/lib/getConfiguration.ts index fb46ecc71..275292182 100644 --- a/node-src/lib/getConfiguration.ts +++ b/node-src/lib/getConfiguration.ts @@ -26,6 +26,7 @@ const configurationSchema = z buildScriptName: z.string(), playwright: z.boolean(), + cypress: z.boolean(), outputDir: z.string(), skip: z.union([z.string(), z.boolean()]), diff --git a/node-src/lib/getOptions.ts b/node-src/lib/getOptions.ts index eecbc08cf..f958f738f 100644 --- a/node-src/lib/getOptions.ts +++ b/node-src/lib/getOptions.ts @@ -72,6 +72,7 @@ export default function getOptions({ buildScriptName: undefined, playwright: undefined, + cypress: undefined, outputDir: undefined, allowConsoleErrors: undefined, storybookBuildDir: undefined, @@ -130,6 +131,7 @@ export default function getOptions({ buildScriptName: flags.buildScriptName, playwright: trueIfSet(flags.playwright), + cypress: trueIfSet(flags.cypress), outputDir: takeLast(flags.outputDir), allowConsoleErrors: flags.allowConsoleErrors, storybookBuildDir: takeLast(flags.storybookBuildDir), @@ -204,6 +206,8 @@ export default function getOptions({ const singularOpts = { buildScriptName: '--build-script-name', storybookBuildDir: '--storybook-build-dir', + playwright: '--playwright', + cypress: '--cypress', }; const foundSingularOpts = Object.keys(singularOpts).filter((name) => !!options[name]); @@ -256,7 +260,7 @@ export default function getOptions({ return options; } - if (options.playwright) { + if (options.playwright || options.cypress) { return options; } From f87673aac45365a391224e9a32043561e527368c Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Sat, 13 Jan 2024 23:09:06 +1100 Subject: [PATCH 05/11] Added tests --- node-src/index.test.ts | 40 ++++++++++++++++++++++++++++++----- node-src/lib/getE2eBinPath.ts | 18 ++++++++++++++++ node-src/tasks/build.ts | 20 +++++------------- 3 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 node-src/lib/getE2eBinPath.ts diff --git a/node-src/index.test.ts b/node-src/index.test.ts index 04e59f2bf..6c973b881 100644 --- a/node-src/index.test.ts +++ b/node-src/index.test.ts @@ -1,5 +1,5 @@ import dns from 'dns'; -import { execa as execaDefault } from 'execa'; +import { execaCommand as execaDefault } from 'execa'; import jsonfile from 'jsonfile'; import { confirm } from 'node-ask'; import fetchDefault from 'node-fetch'; @@ -38,7 +38,11 @@ beforeEach(() => { vi.mock('dns'); vi.mock('execa'); -const execa = vi.mocked(execaDefault); +vi.mock('./lib/getE2eBinPath', () => ({ + getE2eBinPath: () => 'path/to/bin', +})); + +const execaCommand = vi.mocked(execaDefault); const fetch = vi.mocked(fetchDefault); const upload = vi.mocked(uploadFiles); @@ -334,8 +338,8 @@ beforeEach(() => { CHROMATIC_APP_CODE: undefined, CHROMATIC_PROJECT_TOKEN: undefined, }; - execa.mockReset(); - execa.mockResolvedValue({ stdout: '1.2.3' } as any); + execaCommand.mockReset(); + execaCommand.mockResolvedValue({ stdout: '1.2.3' } as any); getCommit.mockResolvedValue({ commit: 'commit', committedAt: 1234, @@ -466,6 +470,12 @@ it('should exit with code 6 and stop the build when abortSignal is aborted', asy it('calls out to npm build script passed and uploads files', async () => { const ctx = getContext(['--project-token=asdf1234', '--build-script-name=build-storybook']); await runAll(ctx); + + expect(execaCommand).toHaveBeenCalledWith( + expect.stringMatching(/build-storybook/), + expect.objectContaining({}) + ); + expect(ctx.exitCode).toBe(1); expect(uploadFiles).toHaveBeenCalledWith( expect.any(Object), @@ -501,7 +511,7 @@ it('skips building and uploads directly with storybook-build-dir', async () => { const ctx = getContext(['--project-token=asdf1234', '--storybook-build-dir=dirname']); await runAll(ctx); expect(ctx.exitCode).toBe(1); - expect(execa).not.toHaveBeenCalled(); + expect(execaCommand).not.toHaveBeenCalled(); expect(uploadFiles).toHaveBeenCalledWith( expect.any(Object), [ @@ -532,6 +542,26 @@ it('skips building and uploads directly with storybook-build-dir', async () => { ); }); +it('builds with playwright with --playwright', async () => { + const ctx = getContext(['--project-token=asdf1234', '--playwright']); + await runAll(ctx); + expect(execaCommand).toHaveBeenCalledWith( + expect.stringMatching(/path\/to\/bin/), + expect.objectContaining({}) + ); + expect(ctx.exitCode).toBe(1); +}); + +it('builds with cypress with --cypress', async () => { + const ctx = getContext(['--project-token=asdf1234', '--cypress']); + await runAll(ctx); + expect(execaCommand).toHaveBeenCalledWith( + expect.stringMatching(/path\/to\/bin/), + expect.objectContaining({}) + ); + expect(ctx.exitCode).toBe(1); +}); + it('passes autoAcceptChanges to the index', async () => { const ctx = getContext(['--project-token=asdf1234', '--auto-accept-changes']); await runAll(ctx); diff --git a/node-src/lib/getE2eBinPath.ts b/node-src/lib/getE2eBinPath.ts new file mode 100644 index 000000000..6f7ff6edf --- /dev/null +++ b/node-src/lib/getE2eBinPath.ts @@ -0,0 +1,18 @@ +import { Context } from '../types'; +import missingDependency from '../ui/messages/errors/missingDependency'; +import { exitCodes, setExitCode } from './setExitCode'; +import { failed } from '../ui/tasks/build'; + +export function getE2eBinPath(ctx: Context, flag: 'playwright' | 'cypress') { + const dependencyName = `chromatic-${flag}`; + try { + return require.resolve(`${dependencyName}/bin/build-archive-storybook`); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + ctx.log.error(missingDependency({ dependencyName, flag })); + setExitCode(ctx, exitCodes.MISSING_DEPENDENCY, true); + throw new Error(failed(ctx).output); + } + throw err; + } +} diff --git a/node-src/tasks/build.ts b/node-src/tasks/build.ts index 74e080a64..08fff1199 100644 --- a/node-src/tasks/build.ts +++ b/node-src/tasks/build.ts @@ -1,6 +1,6 @@ import { execaCommand } from 'execa'; import { createWriteStream, readFileSync } from 'fs'; -import path, { dirname } from 'path'; +import path from 'path'; import semver from 'semver'; import tmp from 'tmp-promise'; @@ -11,7 +11,7 @@ import { endActivity, startActivity } from '../ui/components/activity'; import buildFailed from '../ui/messages/errors/buildFailed'; import { failed, initial, pending, skipped, success } from '../ui/tasks/build'; import { getPackageManagerRunCommand } from '../lib/getPackageManager'; -import missingDependency from '../ui/messages/errors/missingDependency'; +import { getE2eBinPath } from '../lib/getE2eBinPath'; export const setSourceDir = async (ctx: Context) => { if (ctx.options.outputDir) { @@ -43,19 +43,8 @@ export const setBuildCommand = async (ctx: Context) => { ].filter(Boolean); if (ctx.options.playwright || ctx.options.cypress) { - const flag = ctx.options.playwright ? 'playwright' : 'cypress'; - const dependencyName = `chromatic-${flag}`; - try { - const binPath = dirname(require.resolve(`${dependencyName}/bin/build-archive-storybook`)); - ctx.buildCommand = ['node', binPath, ...buildCommandOptions].join(' '); - } catch (err) { - if (err.code === 'MODULE_NOT_FOUND') { - ctx.log.error(missingDependency({ dependencyName, flag })); - setExitCode(ctx, exitCodes.MISSING_DEPENDENCY, true); - throw new Error(failed(ctx).output); - } - throw err; - } + const binPath = getE2eBinPath(ctx, ctx.options.playwright ? 'playwright' : 'cypress'); + ctx.buildCommand = ['node', binPath, ...buildCommandOptions].join(' '); } else { ctx.buildCommand = await getPackageManagerRunCommand([ ctx.options.buildScriptName, @@ -83,6 +72,7 @@ export const buildStorybook = async (ctx: Context) => { ctx.log.debug('Running build command:', ctx.buildCommand); ctx.log.debug('Runtime metadata:', JSON.stringify(ctx.runtimeMetadata, null, 2)); + console.log(ctx.buildCommand); const subprocess = execaCommand(ctx.buildCommand, { stdio: [null, logFile, logFile], signal, From 413e631a573cbc6b332bcd8125f0b2455aeb0e17 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Tue, 23 Jan 2024 21:27:17 +1100 Subject: [PATCH 06/11] Add (optional) peer deps --- package.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/package.json b/package.json index 5c17ea078..f540ab5b1 100644 --- a/package.json +++ b/package.json @@ -195,6 +195,18 @@ "zen-observable": "^0.8.15", "zod": "^3.22.2" }, + "peerDependencies": { + "chromatic-playwright": "^0.3.1", + "chromatic-cypress": "^0.3.2" + }, + "peerDependenciesMeta": { + "chromatic-playwright": { + "optional": true + }, + "chromatic-cypress": { + "optional": true + } + }, "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" From faec08c6d9491e796934eea8174d28926959d982 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 24 Jan 2024 11:26:17 +1100 Subject: [PATCH 07/11] Keep peer deps to 1.0.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f540ab5b1..4993c8b14 100644 --- a/package.json +++ b/package.json @@ -196,8 +196,8 @@ "zod": "^3.22.2" }, "peerDependencies": { - "chromatic-playwright": "^0.3.1", - "chromatic-cypress": "^0.3.2" + "chromatic-playwright": "^1.0.0", + "chromatic-cypress": "^1.0.0" }, "peerDependenciesMeta": { "chromatic-playwright": { From 4442b566bbe54af934536b3bab6bc5a795a385f4 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 24 Jan 2024 11:28:22 +1100 Subject: [PATCH 08/11] Allow current versions and 1.0.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4993c8b14..c18f71f92 100644 --- a/package.json +++ b/package.json @@ -196,8 +196,8 @@ "zod": "^3.22.2" }, "peerDependencies": { - "chromatic-playwright": "^1.0.0", - "chromatic-cypress": "^1.0.0" + "chromatic-playwright": "^0.3.1 || ^1.0.0", + "chromatic-cypress": "^0.3.2 || ^1.0.0" }, "peerDependenciesMeta": { "chromatic-playwright": { From 17f0ada02e56249e0230c4b2b20d8731ac3db34e Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 24 Jan 2024 11:31:59 +1100 Subject: [PATCH 09/11] Actually we added the exports we need in 0.4.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c18f71f92..77d959215 100644 --- a/package.json +++ b/package.json @@ -196,8 +196,8 @@ "zod": "^3.22.2" }, "peerDependencies": { - "chromatic-playwright": "^0.3.1 || ^1.0.0", - "chromatic-cypress": "^0.3.2 || ^1.0.0" + "chromatic-playwright": "^0.4.0 || ^1.0.0", + "chromatic-cypress": "^0.4.0 || ^1.0.0" }, "peerDependenciesMeta": { "chromatic-playwright": { From 42d2d2bdf5668fd48e18d22b76bb5b5a007923ba Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 24 Jan 2024 13:00:00 +1100 Subject: [PATCH 10/11] Move `package.json` check to after we parse options And only check scripts if we aren't in E2E mode. --- node-src/index.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/node-src/index.ts b/node-src/index.ts index 8b7e49193..f2c743db2 100644 --- a/node-src/index.ts +++ b/node-src/index.ts @@ -97,11 +97,6 @@ export async function run({ } const { path: packagePath, packageJson } = pkgInfo; - if (typeof packageJson !== 'object' || typeof packageJson.scripts !== 'object') { - log.error(invalidPackageJson(packagePath)); - process.exit(252); - } - const ctx: InitialContext = { ...parseArgs(argv), ...(flags && { flags }), @@ -164,6 +159,16 @@ export async function runAll(ctx: InitialContext) { const options = getOptions(ctx); (ctx as Context).options = options; ctx.log.setLogFile(options.logFile); + + const needsScripts = !options.playwright && !options.cypress; + if ( + typeof ctx.packageJson !== 'object' || + (needsScripts && typeof ctx.packageJson.scripts !== 'object') + ) { + ctx.log.error(invalidPackageJson(ctx.packagePath)); + process.exit(252); + } + setExitCode(ctx, exitCodes.OK); } catch (e) { return onError(e); From 943d4325d469ade1d5cbe7838f87e26e65d16528 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 24 Jan 2024 14:09:49 +1100 Subject: [PATCH 11/11] Move package json check to where we need it --- node-src/index.ts | 10 ---------- node-src/lib/getOptions.ts | 7 +++++++ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/node-src/index.ts b/node-src/index.ts index f2c743db2..418cd5ae0 100644 --- a/node-src/index.ts +++ b/node-src/index.ts @@ -27,7 +27,6 @@ import buildCanceled from './ui/messages/errors/buildCanceled'; import { default as fatalError } from './ui/messages/errors/fatalError'; import fetchError from './ui/messages/errors/fetchError'; import graphqlError from './ui/messages/errors/graphqlError'; -import invalidPackageJson from './ui/messages/errors/invalidPackageJson'; import missingStories from './ui/messages/errors/missingStories'; import noPackageJson from './ui/messages/errors/noPackageJson'; import runtimeError from './ui/messages/errors/runtimeError'; @@ -160,15 +159,6 @@ export async function runAll(ctx: InitialContext) { (ctx as Context).options = options; ctx.log.setLogFile(options.logFile); - const needsScripts = !options.playwright && !options.cypress; - if ( - typeof ctx.packageJson !== 'object' || - (needsScripts && typeof ctx.packageJson.scripts !== 'object') - ) { - ctx.log.error(invalidPackageJson(ctx.packagePath)); - process.exit(252); - } - setExitCode(ctx, exitCodes.OK); } catch (e) { return onError(e); diff --git a/node-src/lib/getOptions.ts b/node-src/lib/getOptions.ts index f958f738f..79ca0ba57 100644 --- a/node-src/lib/getOptions.ts +++ b/node-src/lib/getOptions.ts @@ -13,6 +13,7 @@ import invalidSingularOptions from '../ui/messages/errors/invalidSingularOptions import missingBuildScriptName from '../ui/messages/errors/missingBuildScriptName'; import missingProjectToken from '../ui/messages/errors/missingProjectToken'; import deprecatedOption from '../ui/messages/warnings/deprecatedOption'; +import invalidPackageJson from '../ui/messages/errors/invalidPackageJson'; const takeLast = (input: string | string[]) => Array.isArray(input) ? input[input.length - 1] : input; @@ -39,6 +40,7 @@ export default function getOptions({ configuration, log, packageJson, + packagePath, }: InitialContext): Options { const defaultOptions = { projectToken: env.CHROMATIC_PROJECT_TOKEN, @@ -264,6 +266,11 @@ export default function getOptions({ return options; } + if (typeof packageJson !== 'object' || typeof packageJson.scripts !== 'object') { + log.error(invalidPackageJson(packagePath)); + process.exit(252); + } + const { scripts } = packageJson; if (typeof buildScriptName !== 'string') { buildScriptName = 'build-storybook';