Skip to content

Commit

Permalink
feat(cli): implement compare command
Browse files Browse the repository at this point in the history
  • Loading branch information
matejchalk committed Mar 12, 2024
1 parent 10df94c commit 314e7ba
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/cli/src/lib/commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CommandModule } from 'yargs';
import { yargsAutorunCommandObject } from './autorun/autorun-command';
import { yargsCollectCommandObject } from './collect/collect-command';
import { yargsCompareCommandObject } from './compare/compare-command';
import { yargsConfigCommandObject } from './print-config/print-config-command';
import { yargsUploadCommandObject } from './upload/upload-command';

Expand All @@ -12,5 +13,6 @@ export const commands: CommandModule[] = [
yargsAutorunCommandObject(),
yargsCollectCommandObject(),
yargsUploadCommandObject(),
yargsCompareCommandObject(),
yargsConfigCommandObject(),
];
36 changes: 36 additions & 0 deletions packages/cli/src/lib/compare/compare-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import chalk from 'chalk';
import { join } from 'node:path';
import { CommandModule } from 'yargs';
import { compareReportFiles } from '@code-pushup/core';
import { PersistConfig } from '@code-pushup/models';
import { CLI_NAME } from '../constants';
import type { CompareOptions } from '../implementation/compare.model';
import { yargsCompareOptionsDefinition } from '../implementation/compare.options';
import { ui } from '../implementation/logging';

export function yargsCompareCommandObject() {
const command = 'compare';
return {
command,
describe: 'Compare 2 report files and create a diff file',
builder: yargsCompareOptionsDefinition(),
handler: async (args: unknown) => {
ui().logger.log(chalk.bold(CLI_NAME));
ui().logger.info(chalk.gray(`Run ${command}...`));

const options = args as CompareOptions & {
persist: Required<PersistConfig>;
};

const { before, after, persist } = options;
const outputPath = join(
persist.outputDir,
`${persist.filename}-diff.json`,
);

await compareReportFiles({ before, after }, outputPath);

ui().logger.info(`Reports diff written to ${chalk.bold(outputPath)}`);
},
} satisfies CommandModule;
}
33 changes: 33 additions & 0 deletions packages/cli/src/lib/compare/compare-command.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { join } from 'node:path';
import { compareReportFiles } from '@code-pushup/core';
import { PERSIST_FILENAME, PERSIST_OUTPUT_DIR } from '@code-pushup/models';
import { DEFAULT_CLI_CONFIGURATION } from '../../../mocks/constants';
import { yargsCli } from '../yargs-cli';
import { yargsCompareCommandObject } from './compare-command';

vi.mock('@code-pushup/core', async () => {
const core: object = await vi.importActual('@code-pushup/core');
const { CORE_CONFIG_MOCK }: typeof import('@code-pushup/test-utils') =
await vi.importActual('@code-pushup/test-utils');
return {
...core,
autoloadRc: vi.fn().mockResolvedValue(CORE_CONFIG_MOCK),
compareReportFiles: vi.fn(),
};
});

describe('compare-command', () => {
it('should parse input paths from command line and output path from persist config', async () => {
await yargsCli(
['compare', '--before=source-report.json', '--after=target-report.json'],
{ ...DEFAULT_CLI_CONFIGURATION, commands: [yargsCompareCommandObject()] },
).parseAsync();

expect(compareReportFiles).toHaveBeenCalledWith<
Parameters<typeof compareReportFiles>
>(
{ before: 'source-report.json', after: 'target-report.json' },
join(PERSIST_OUTPUT_DIR, `${PERSIST_FILENAME}-diff.json`),
);
});
});
3 changes: 3 additions & 0 deletions packages/cli/src/lib/implementation/compare.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Diff } from '@code-pushup/utils';

export type CompareOptions = Diff<string>;
20 changes: 20 additions & 0 deletions packages/cli/src/lib/implementation/compare.options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Options } from 'yargs';
import type { CompareOptions } from './compare.model';

export function yargsCompareOptionsDefinition(): Record<
keyof CompareOptions,
Options
> {
return {
before: {
describe: 'Path to source report.json',
type: 'string',
demandOption: true,
},
after: {
describe: 'Path to target report.json',
type: 'string',
demandOption: true,
},
};
}
22 changes: 22 additions & 0 deletions packages/cli/src/lib/yargs-cli.integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { describe, expect, it } from 'vitest';
import { CoreConfig, Format } from '@code-pushup/models';
import { CompareOptions } from './implementation/compare.model';
import { yargsCompareOptionsDefinition } from './implementation/compare.options';
import {
PersistConfigCliOptions,
UploadConfigCliOptions,
Expand Down Expand Up @@ -118,4 +120,24 @@ describe('yargsCli', () => {
}),
);
});

it('should parse compare options', async () => {
const parsedArgv = await yargsCli<GeneralCliOptions & CompareOptions>(
['--before=source-report.json', '--after', 'target-report.json'],
{
options: { ...options, ...yargsCompareOptionsDefinition() },
},
).parseAsync();
expect(parsedArgv.before).toBe('source-report.json');
expect(parsedArgv.after).toBe('target-report.json');
});

it('should error if required compare option is missing', () => {
expect(() =>
yargsCli<GeneralCliOptions & CompareOptions>([], {
options: { ...options, ...yargsCompareOptionsDefinition() },
noExitProcess: true,
}).parse(),
).toThrow('Missing required arguments: before, after');
});
});

0 comments on commit 314e7ba

Please sign in to comment.