diff --git a/bin/main.test.js b/bin/main.test.js index 6d613284a..e200b6fda 100644 --- a/bin/main.test.js +++ b/bin/main.test.js @@ -58,7 +58,7 @@ jest.mock('node-fetch', () => paymentRequired: false, }, }, - snapshots: [ + tests: [ { spec: { name: 'name', component: { displayName: 'component' } }, parameters: { viewport: 320, viewportIsDefault: false }, @@ -72,7 +72,7 @@ jest.mock('node-fetch', () => if (query.match('TesterBuildQuery')) { return { data: { - app: { build: { status: 'BUILD_PENDING', changeCount: 1 } }, + app: { build: { status: 'PENDING', changeCount: 1 } }, }, }; } diff --git a/bin/tasks/report.js b/bin/tasks/report.js index e7bf5f767..55d2ecc0c 100644 --- a/bin/tasks/report.js +++ b/bin/tasks/report.js @@ -11,13 +11,14 @@ const ReportQuery = ` app { build(number: $buildNumber) { number - status + status(legacy: false) webUrl cachedUrl createdAt completedAt - snapshots { + tests { status + result spec { name component { @@ -43,12 +44,13 @@ export const generateReport = async (ctx) => { const file = junitReport === true ? 'chromatic-build-{buildNumber}.xml' : junitReport; ctx.reportPath = path.resolve(file.replace(/{buildNumber}/g, buildNumber)); - const result = await client.runQuery( + const { + app: { build }, + } = await client.runQuery( ReportQuery, { buildNumber }, { Authorization: `Bearer ${reportToken}` } ); - const { build } = result.app; const buildTime = (build.completedAt || Date.now()) - build.createdAt; const suite = reportBuilder @@ -61,7 +63,7 @@ export const generateReport = async (ctx) => { .property('buildUrl', build.webUrl) .property('storybookUrl', baseStorybookUrl(build.cachedUrl)); - build.snapshots.forEach(({ status, spec, parameters }) => { + build.tests.forEach(({ status, result, spec, parameters }) => { const suffix = parameters.viewportIsDefault ? '' : ` [${parameters.viewport}px]`; const testCase = suite .testCase() @@ -69,22 +71,23 @@ export const generateReport = async (ctx) => { .name(`${spec.name}${suffix}`); switch (status) { - case 'SNAPSHOT_ERROR': + case 'FAILED': testCase.error('Server error while taking snapshot, please try again', status); break; - case 'SNAPSHOT_CAPTURE_ERROR': + case 'BROKEN': testCase.error('Snapshot is broken due to an error in your Storybook', status); break; - case 'SNAPSHOT_DENIED': + case 'DENIED': testCase.failure('Snapshot was denied by a user', status); break; - case 'SNAPSHOT_PENDING': + case 'PENDING': testCase.failure('Snapshot contains visual changes and must be reviewed', status); break; - case 'SNAPSHOT_NO_CAPTURE': - testCase.skipped(); - break; - default: + default: { + if (['SKIPPED', 'PRESERVED'].includes(result)) { + testCase.skipped(); + } + } } }); diff --git a/bin/tasks/snapshot.js b/bin/tasks/snapshot.js index 3fd857c79..acddc193d 100644 --- a/bin/tasks/snapshot.js +++ b/bin/tasks/snapshot.js @@ -20,12 +20,12 @@ const TesterBuildQuery = ` app { build(number: $buildNumber) { id - status + status(legacy: false) autoAcceptChanges - inProgressCount: snapshotCount(statuses: [SNAPSHOT_IN_PROGRESS]) - snapshotCount + inProgressCount: testCount(statuses: [IN_PROGRESS]) + testCount changeCount - errorCount: snapshotCount(statuses: [SNAPSHOT_CAPTURE_ERROR]) + errorCount: testCount(statuses: [BROKEN]) } } } @@ -33,15 +33,15 @@ const TesterBuildQuery = ` export const takeSnapshots = async (ctx, task) => { const { client, log, options } = ctx; - const { number: buildNumber, snapshots } = ctx.build; + const { number: buildNumber, tests } = ctx.build; if (ctx.build.app.repository && ctx.uploadedBytes && !options.junitReport) { log.info(speedUpCI(ctx.build.app.repository.provider)); } - const snapshotLabels = + const testLabels = options.interactive && - snapshots.map(({ spec, parameters }) => { + tests.map(({ spec, parameters }) => { const suffix = parameters.viewportIsDefault ? '' : ` [${parameters.viewport}px]`; return `${spec.component.displayName} › ${spec.name}${suffix}`; }); @@ -50,14 +50,14 @@ export const takeSnapshots = async (ctx, task) => { const { app } = await client.runQuery(TesterBuildQuery, { buildNumber }); ctx.build = { ...ctx.build, ...app.build }; - if (app.build.status !== 'BUILD_IN_PROGRESS') { + if (app.build.status !== 'IN_PROGRESS') { return ctx.build; } if (options.interactive) { - const { inProgressCount, snapshotCount } = ctx.build; - const cursor = snapshotCount - inProgressCount + 1; - const label = snapshotLabels[cursor - 1] || ''; + const { inProgressCount, testCount } = ctx.build; + const cursor = testCount - inProgressCount + 1; + const label = testLabels[cursor - 1] || ''; task.output = pending({ ...ctx, cursor, label }).output; } @@ -68,16 +68,16 @@ export const takeSnapshots = async (ctx, task) => { const build = await waitForBuild(); switch (build.status) { - case 'BUILD_PASSED': + case 'PASSED': ctx.exitCode = 0; ctx.log.info(buildPassedMessage(ctx)); transitionTo(buildPassed, true)(ctx, task); break; // They may have sneakily looked at the build while we were waiting - case 'BUILD_ACCEPTED': - case 'BUILD_PENDING': - case 'BUILD_DENIED': { + case 'ACCEPTED': + case 'PENDING': + case 'DENIED': { if (build.autoAcceptChanges || ctx.git.matchesBranch(options.exitZeroOnChanges)) { ctx.exitCode = 0; ctx.log.info(buildPassedMessage(ctx)); @@ -89,14 +89,14 @@ export const takeSnapshots = async (ctx, task) => { break; } - case 'BUILD_FAILED': + case 'BROKEN': ctx.exitCode = 2; ctx.log.error(buildHasErrors(ctx)); transitionTo(buildFailed, true)(ctx, task); break; - case 'BUILD_TIMED_OUT': - case 'BUILD_ERROR': + case 'FAILED': + case 'CANCELLED': ctx.exitCode = 3; transitionTo(buildError, true)(ctx, task); break; diff --git a/bin/tasks/snapshot.test.js b/bin/tasks/snapshot.test.js index acb9149a5..787c7cb4b 100644 --- a/bin/tasks/snapshot.test.js +++ b/bin/tasks/snapshot.test.js @@ -10,9 +10,9 @@ describe('takeSnapshots', () => { const build = { app: { repository: { provider: 'github' } }, number: 1, features: {} }; const ctx = { client, env, git: { matchesBranch }, log, options: {}, build }; - client.runQuery.mockReturnValueOnce({ app: { build: { status: 'BUILD_IN_PROGRESS' } } }); + client.runQuery.mockReturnValueOnce({ app: { build: { status: 'IN_PROGRESS' } } }); client.runQuery.mockReturnValueOnce({ - app: { build: { changeCount: 0, status: 'BUILD_PASSED' } }, + app: { build: { changeCount: 0, status: 'PASSED' } }, }); await takeSnapshots(ctx, {}); @@ -20,7 +20,7 @@ describe('takeSnapshots', () => { expect(client.runQuery).toHaveBeenCalledWith(expect.stringMatching(/TesterBuildQuery/), { buildNumber: 1, }); - expect(ctx.build).toEqual({ ...build, changeCount: 0, status: 'BUILD_PASSED' }); + expect(ctx.build).toEqual({ ...build, changeCount: 0, status: 'PASSED' }); expect(ctx.exitCode).toBe(0); }); @@ -29,43 +29,43 @@ describe('takeSnapshots', () => { const build = { app: { repository: { provider: 'github' } }, number: 1, features: {} }; const ctx = { client, env, git: { matchesBranch }, log, options: {}, build }; - client.runQuery.mockReturnValueOnce({ app: { build: { status: 'BUILD_IN_PROGRESS' } } }); + client.runQuery.mockReturnValueOnce({ app: { build: { status: 'IN_PROGRESS' } } }); client.runQuery.mockReturnValueOnce({ - app: { build: { changeCount: 2, status: 'BUILD_PENDING' } }, + app: { build: { changeCount: 2, status: 'PENDING' } }, }); await takeSnapshots(ctx, {}); - expect(ctx.build).toEqual({ ...build, changeCount: 2, status: 'BUILD_PENDING' }); + expect(ctx.build).toEqual({ ...build, changeCount: 2, status: 'PENDING' }); expect(ctx.exitCode).toBe(1); }); - it('sets exitCode to 2 when build fails', async () => { + it('sets exitCode to 2 when build is broken (capture error)', async () => { const client = { runQuery: jest.fn(), setAuthorization: jest.fn() }; const build = { app: { repository: { provider: 'github' } }, number: 1, features: {} }; const ctx = { client, env, git: { matchesBranch }, log, options: {}, build }; - client.runQuery.mockReturnValueOnce({ app: { build: { status: 'BUILD_IN_PROGRESS' } } }); + client.runQuery.mockReturnValueOnce({ app: { build: { status: 'IN_PROGRESS' } } }); client.runQuery.mockReturnValueOnce({ - app: { build: { changeCount: 2, status: 'BUILD_FAILED' } }, + app: { build: { changeCount: 2, status: 'BROKEN' } }, }); await takeSnapshots(ctx, {}); - expect(ctx.build).toEqual({ ...build, changeCount: 2, status: 'BUILD_FAILED' }); + expect(ctx.build).toEqual({ ...build, changeCount: 2, status: 'BROKEN' }); expect(ctx.exitCode).toBe(2); }); - it('sets exitCode to 3 when build errors', async () => { + it('sets exitCode to 3 when build fails (system error)', async () => { const client = { runQuery: jest.fn(), setAuthorization: jest.fn() }; const build = { app: { repository: { provider: 'github' } }, number: 1, features: {} }; const ctx = { client, env, git: { matchesBranch }, log, options: {}, build }; - client.runQuery.mockReturnValueOnce({ app: { build: { status: 'BUILD_IN_PROGRESS' } } }); + client.runQuery.mockReturnValueOnce({ app: { build: { status: 'IN_PROGRESS' } } }); client.runQuery.mockReturnValueOnce({ - app: { build: { changeCount: 2, status: 'BUILD_ERROR' } }, + app: { build: { changeCount: 2, status: 'FAILED' } }, }); await takeSnapshots(ctx, {}); - expect(ctx.build).toEqual({ ...build, changeCount: 2, status: 'BUILD_ERROR' }); + expect(ctx.build).toEqual({ ...build, changeCount: 2, status: 'FAILED' }); expect(ctx.exitCode).toBe(3); }); }); diff --git a/bin/tasks/verify.js b/bin/tasks/verify.js index e92292786..b048d2475 100644 --- a/bin/tasks/verify.js +++ b/bin/tasks/verify.js @@ -12,7 +12,7 @@ const TesterCreateBuildMutation = ` id number specCount - snapshotCount + testCount componentCount webUrl cachedUrl @@ -33,7 +33,7 @@ const TesterCreateBuildMutation = ` } setupUrl } - snapshots { + tests { spec { name component { @@ -99,7 +99,7 @@ export const createBuild = async (ctx, task) => { ctx.isOnboarding = build.number === 1 || (build.autoAcceptChanges && !autoAcceptChanges); if (list) { - log.info(listingStories(build.snapshots)); + log.info(listingStories(build.tests)); } if (build.wasLimited) { diff --git a/bin/ui/messages/info/buildPassed.stories.js b/bin/ui/messages/info/buildPassed.stories.js index 37dd99d9e..4f67c1bb8 100644 --- a/bin/ui/messages/info/buildPassed.stories.js +++ b/bin/ui/messages/info/buildPassed.stories.js @@ -17,7 +17,7 @@ export const FirstBuildPassed = () => isOnboarding: true, build: { number: 1, - snapshotCount: 10, + testCount: 10, componentCount: 5, specCount: 8, app: { setupUrl: 'https://www.chromatic.com/setup?appId=59c59bd0183bd100364e1d57' }, diff --git a/bin/ui/tasks/snapshot.js b/bin/ui/tasks/snapshot.js index 2d1addbb3..23c6a7e37 100644 --- a/bin/ui/tasks/snapshot.js +++ b/bin/ui/tasks/snapshot.js @@ -11,7 +11,7 @@ export const initial = { export const stats = (ctx) => ({ errors: pluralize('error', ctx.build.errorCount, true), changes: pluralize('change', ctx.build.changeCount, true), - snapshots: pluralize('snapshot', ctx.build.snapshotCount, true), + snapshots: pluralize('snapshot', ctx.build.testCount, true), components: pluralize('component', ctx.build.componentCount, true), specs: pluralize('story', ctx.build.specCount, true), }); @@ -20,8 +20,8 @@ export const pending = (ctx) => { const { build, options, cursor = 0, label = '' } = ctx; const { errors, snapshots, components, specs } = stats(ctx); const only = options.only ? ` for stories matching '${options.only}'` : ''; - const percentage = Math.round((cursor / build.snapshotCount) * 100); - const counts = `${cursor}/${build.snapshotCount}`; + const percentage = Math.round((cursor / build.testCount) * 100); + const counts = `${cursor}/${build.testCount}`; const errs = build.errorCount ? `(${errors}) ` : ''; return { status: 'pending', diff --git a/bin/ui/tasks/snapshot.stories.js b/bin/ui/tasks/snapshot.stories.js index 7de1b9f79..0e803b5bb 100644 --- a/bin/ui/tasks/snapshot.stories.js +++ b/bin/ui/tasks/snapshot.stories.js @@ -18,7 +18,7 @@ const build = { number: 42, errorCount: 1, changeCount: 2, - snapshotCount: 10, + testCount: 10, componentCount: 5, specCount: 8, features: { uiTests: true },