diff --git a/packages/percy-storybook/src/__tests__/getMinimumHeight-tests.js b/packages/percy-storybook/src/__tests__/getMinimumHeight-tests.js index 34602a6d..33eee277 100644 --- a/packages/percy-storybook/src/__tests__/getMinimumHeight-tests.js +++ b/packages/percy-storybook/src/__tests__/getMinimumHeight-tests.js @@ -1,6 +1,6 @@ import getMinimumHeight from '../getMinimumHeight'; -it('returns number when passed a number ', () => { +it('returns number when passed a number', () => { expect(getMinimumHeight(100)).toEqual(100); }); diff --git a/packages/percy-storybook/src/__tests__/getOutputFormat-tests.js b/packages/percy-storybook/src/__tests__/getOutputFormat-tests.js new file mode 100644 index 00000000..966dcf26 --- /dev/null +++ b/packages/percy-storybook/src/__tests__/getOutputFormat-tests.js @@ -0,0 +1,18 @@ +import getOutputFormat from '../getOutputFormat'; + +it('returns text when passed text', () => { + expect(getOutputFormat('TEXT')).toEqual('text'); + expect(getOutputFormat('text')).toEqual('text'); +}); + +it('returns json when passed JSON', () => { + expect(getOutputFormat('JSON')).toEqual('json'); + expect(getOutputFormat('json')).toEqual('json'); +}); + +it('raises an error if called with an invalid value', () => { + expect(() => getOutputFormat()).toThrow(); + expect(() => getOutputFormat('xml')).toThrow(); + expect(() => getOutputFormat(7)).toThrow(); + expect(() => getOutputFormat('')).toThrow(); +}); diff --git a/packages/percy-storybook/src/args.js b/packages/percy-storybook/src/args.js index ff321c4b..77efef4c 100644 --- a/packages/percy-storybook/src/args.js +++ b/packages/percy-storybook/src/args.js @@ -20,6 +20,10 @@ export const options = { description: 'Directory to load the static storybook built by build-storybook from', requiresArg: true, }, + output_format: { + description: 'Specify JSON to log the build parameters in JSON. Note: --debug outputs non-JSON', + requiresArg: true, + }, rtl: { description: 'Runs stories a second time with a direction parameter set to rtl', requiresArg: false, diff --git a/packages/percy-storybook/src/cli.js b/packages/percy-storybook/src/cli.js index be0670ff..817683f4 100644 --- a/packages/percy-storybook/src/cli.js +++ b/packages/percy-storybook/src/cli.js @@ -4,6 +4,7 @@ import getStories from './getStories'; import getStaticAssets from './getStaticAssets'; import getWidths from './getWidths'; import getMinimumHeight from './getMinimumHeight'; +import getOutputFormat from './getOutputFormat'; import getRtlRegex from './getRtlRegex'; import selectStories from './selectStories'; import uploadStorybook from './uploadStorybook'; @@ -27,6 +28,7 @@ export async function run(argv) { .options(args.options) .epilogue(args.docs) .default('build_dir', 'storybook-static') + .default('output_format', 'text') .default('minimum_height', '800').argv; if (argv.help) { @@ -44,13 +46,23 @@ export async function run(argv) { const rtlRegex = getRtlRegex(argv.rtl, argv.rtl_regex); const options = { - debug: argv.debug, + // Configure debug logging if flag specified, or if it was already enabled via DEBUG env var + debug: argv.debug || debug.enabled, buildDir: argv.build_dir, + outputFormat: getOutputFormat(argv.output_format), }; + // Enable debug logging based on options. + debug.enabled = options.debug; + if (process.env.PERCY_ENABLE === '0') { - // eslint-disable-next-line no-console - console.log('The PERCY_ENABLE environment variable is set to 0. Exiting.'); + if (options.outputFormat == 'text') { + // eslint-disable-next-line no-console + console.log('The PERCY_ENABLE environment variable is set to 0. Exiting.'); + } else if (options.outputFormat == 'json') { + // eslint-disable-next-line no-console + console.log(`{'exitReason':'The PERCY_ENABLE environment variable is set to 0.'}`); + } return; } @@ -72,7 +84,13 @@ export async function run(argv) { debug('selectedStories %o', selectedStories); if (selectedStories.length === 0) { - console.log('WARNING: No stories were found.'); // eslint-disable-line no-console + if (options.outputFormat == 'text') { + // eslint-disable-next-line no-console + console.log('No stories were found.'); + } else if (options.outputFormat == 'json') { + // eslint-disable-next-line no-console + console.log(`{'exitReason':'No stories were found.'}`); + } return; } @@ -83,5 +101,13 @@ export async function run(argv) { `storybook/${storybookVersion()} react/${reactVersion()}`, ); - return uploadStorybook(client, selectedStories, widths, minimumHeight, storyHtml, assets); + return uploadStorybook( + client, + selectedStories, + widths, + minimumHeight, + storyHtml, + assets, + options.outputFormat, + ); } diff --git a/packages/percy-storybook/src/getOutputFormat.js b/packages/percy-storybook/src/getOutputFormat.js new file mode 100644 index 00000000..aff50bf9 --- /dev/null +++ b/packages/percy-storybook/src/getOutputFormat.js @@ -0,0 +1,11 @@ +export default function getOutputFormat(outputFormatString) { + const normalizedOutputFormat = outputFormatString.toLowerCase(); + + if (normalizedOutputFormat != 'text' && normalizedOutputFormat != 'json') { + throw new Error( + `Output format must be either 'text' or 'json'. Received: ${outputFormatString}`, + ); + } + + return normalizedOutputFormat; +} diff --git a/packages/percy-storybook/src/getStaticAssets.js b/packages/percy-storybook/src/getStaticAssets.js index 34b0f9d0..7ba8c480 100644 --- a/packages/percy-storybook/src/getStaticAssets.js +++ b/packages/percy-storybook/src/getStaticAssets.js @@ -33,7 +33,12 @@ function gatherBuildResources(buildDir) { resourceUrl = resourceUrl.replace(/\\/g, '/'); } - resourceUrl = resourceUrl.replace(buildDir, ''); + // Strip the buildDir from the start of the resourceUrl + if (buildDir.startsWith('./')) { + resourceUrl = resourceUrl.replace(buildDir.substr(2), ''); + } else { + resourceUrl = resourceUrl.replace(buildDir, ''); + } // Remove the leading / if (resourceUrl.charAt(0) === '/') { diff --git a/packages/percy-storybook/src/uploadStorybook.js b/packages/percy-storybook/src/uploadStorybook.js index 6d13bc00..6df90100 100644 --- a/packages/percy-storybook/src/uploadStorybook.js +++ b/packages/percy-storybook/src/uploadStorybook.js @@ -7,10 +7,14 @@ export default async function uploadStorybook( minimumHeight, storyHtml, assets, + outputFormat, ) { const snapshotPluralization = selectedStories.length === 1 ? 'snapshot' : 'snapshots'; - // eslint-disable-next-line no-console - console.log('\nUploading', selectedStories.length, snapshotPluralization, 'to Percy.'); + + if (outputFormat == 'text') { + // eslint-disable-next-line no-console + console.log('\nUploading', selectedStories.length, snapshotPluralization, 'to Percy.'); + } const resources = client.makeResources(assets); const build = await client.createBuild(resources); @@ -19,9 +23,14 @@ export default async function uploadStorybook( await uploadStories(client, build, selectedStories, widths, minimumHeight, assets, storyHtml); await client.finalizeBuild(build); - // eslint-disable-next-line no-console - console.log( - 'Percy snapshots uploaded. Visual diffs are now processing:', - build.attributes['web-url'], - ); + if (outputFormat == 'json') { + // eslint-disable-next-line no-console + console.log(JSON.stringify(build.attributes)); + } else if (outputFormat == 'text') { + // eslint-disable-next-line no-console + console.log( + 'Percy snapshots uploaded. Visual diffs are now processing:', + build.attributes['web-url'], + ); + } }