diff --git a/change/monosize-25f1d2cd-899e-4aae-ac0f-b84f55d28f96.json b/change/monosize-25f1d2cd-899e-4aae-ac0f-b84f55d28f96.json new file mode 100644 index 0000000..9c8de29 --- /dev/null +++ b/change/monosize-25f1d2cd-899e-4aae-ac0f-b84f55d28f96.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "feat(monosize): unify reporters API and behaviours", + "packageName": "monosize", + "email": "hochelmartin@gmail.com", + "dependentChangeType": "patch" +} diff --git a/packages/monosize/src/commands/compareReports.mts b/packages/monosize/src/commands/compareReports.mts index da1ab8d..f9b0e7e 100644 --- a/packages/monosize/src/commands/compareReports.mts +++ b/packages/monosize/src/commands/compareReports.mts @@ -48,14 +48,18 @@ async function compareReports(options: CompareReportsOptions) { } } - const result = compareResultsInReports(localReport, remoteReport); + const reportsComparisonResult = compareResultsInReports(localReport, remoteReport); switch (output) { case 'cli': - await cliReporter(result); + cliReporter(reportsComparisonResult, { commitSHA, repository: config.repository, showUnchanged: false }); break; case 'markdown': - await markdownReporter(result, commitSHA, config.repository, quiet); + markdownReporter(reportsComparisonResult, { + commitSHA, + repository: config.repository, + showUnchanged: true, + }); break; } diff --git a/packages/monosize/src/commands/compareReports.test.mts b/packages/monosize/src/commands/compareReports.test.mts index a6add29..b06afcd 100644 --- a/packages/monosize/src/commands/compareReports.test.mts +++ b/packages/monosize/src/commands/compareReports.test.mts @@ -32,6 +32,10 @@ describe('compareReports', () => { expect(getRemoteReport).toHaveBeenCalledWith(branchName); expect(compareResultsInReports).toHaveBeenCalledWith(sampleReport, sampleReport); - expect(cliReporter).toHaveBeenCalledWith(sampleComparedReport); + expect(cliReporter).toHaveBeenCalledWith(sampleComparedReport, { + commitSHA: 'test', + repository: undefined, + showUnchanged: false, + }); }); }); diff --git a/packages/monosize/src/reporters/cliReporter.mts b/packages/monosize/src/reporters/cliReporter.mts index 3b34543..125dfa4 100644 --- a/packages/monosize/src/reporters/cliReporter.mts +++ b/packages/monosize/src/reporters/cliReporter.mts @@ -4,7 +4,7 @@ import pc from 'picocolors'; import { getChangedEntriesInReport } from '../utils/getChangedEntriesInReport.mjs'; import { formatBytes } from '../utils/helpers.mjs'; import type { DiffByMetric } from '../utils/calculateDiffByMetric.mjs'; -import type { ComparedReport } from '../utils/compareResultsInReports.mjs'; +import type { Reporter } from './shared.mjs'; function getDirectionSymbol(value: number): string { if (value < 0) { @@ -28,12 +28,21 @@ function formatDelta(diff: DiffByMetric): string { return colorFn(diff.percent + getDirectionSymbol(diff.delta)); } -export async function cliReporter(report: ComparedReport): Promise { - const result = new Table({ +export const cliReporter: Reporter = (report, options) => { + const { commitSHA, repository } = options; + const footer = `🤖 This report was generated against '${repository}/commit/${commitSHA}'`; + + const { changedEntries } = getChangedEntriesInReport(report); + + const reportOutput = new Table({ colAligns: ['left', 'right', 'right'], head: ['Fixture', 'Before', 'After (minified/GZIP)'], }); - const { changedEntries } = getChangedEntriesInReport(report); + + if (changedEntries.length === 0) { + console.log(`${pc.green('[✔]')} No changes found`); + return; + } changedEntries.forEach(entry => { const { diff, gzippedSize, minifiedSize, name, packageName } = entry; @@ -49,13 +58,10 @@ export async function cliReporter(report: ComparedReport): Promise { const afterColumn = formatDelta(diff.minified) + ' ' + minifiedAfter + '\n' + formatDelta(diff.gzip) + ' ' + gzippedAfter; - result.push([fixtureColumn, beforeColumn, afterColumn]); + reportOutput.push([fixtureColumn, beforeColumn, afterColumn]); }); - if (result.length > 0) { - console.log(result.toString()); - return; - } - - console.log(`${pc.green('[✔]')} No changes found`); -} + console.log(reportOutput.toString()); + console.log(''); + console.log(footer); +}; diff --git a/packages/monosize/src/reporters/cliReporter.test.mts b/packages/monosize/src/reporters/cliReporter.test.mts index 93a9975..413a98f 100644 --- a/packages/monosize/src/reporters/cliReporter.test.mts +++ b/packages/monosize/src/reporters/cliReporter.test.mts @@ -22,9 +22,24 @@ expect.addSnapshotSerializer({ }); describe('cliReporter', () => { - it('renders a report to CLI output', async () => { + const options = { + repository: 'https://github.com/microsoft/monosize', + commitSHA: 'commit-hash', + showUnchanged: false, + }; + + it('wont render anything if there is nothing to compare', () => { const log = vitest.spyOn(console, 'log').mockImplementation(noop); - await cliReporter(sampleComparedReport); + + cliReporter([], options); + + expect(log.mock.calls[0][0]).toMatchInlineSnapshot('[✔] No changes found'); + }); + + it('renders a report to CLI output', () => { + const log = vitest.spyOn(console, 'log').mockImplementation(noop); + + cliReporter(sampleComparedReport, options); expect(log.mock.calls[0][0]).toMatchInlineSnapshot(` ┌────────────────────┬────────┬───────────────────────┐ diff --git a/packages/monosize/src/reporters/markdownReporter.mts b/packages/monosize/src/reporters/markdownReporter.mts index bc10165..8743a58 100644 --- a/packages/monosize/src/reporters/markdownReporter.mts +++ b/packages/monosize/src/reporters/markdownReporter.mts @@ -3,8 +3,8 @@ import { findPackageRoot } from 'workspace-tools'; import { getChangedEntriesInReport } from '../utils/getChangedEntriesInReport.mjs'; import { formatBytes } from '../utils/helpers.mjs'; -import type { ComparedReport } from '../utils/compareResultsInReports.mjs'; import type { DiffByMetric } from '../utils/calculateDiffByMetric.mjs'; +import type { Reporter } from './shared.mjs'; const icons = { increase: 'increase.png', decrease: 'decrease.png' }; @@ -31,29 +31,25 @@ function formatDelta(diff: DiffByMetric): string { return `\`${formatBytes(diff.delta)}\` ${getDirectionSymbol(diff.delta)}`; } -export async function markdownReporter(result: ComparedReport, commitSHA: string, repository: string, quiet: boolean) { - const dirname = fileURLToPath(new URL('.', import.meta.url)); - const packageRoot = findPackageRoot(dirname); +export const markdownReporter: Reporter = (report, options) => { + const { commitSHA, repository, showUnchanged } = options; + const footer = `🤖 This report was generated against ${commitSHA}`; - if (!packageRoot) { - throw new Error( - [ - 'Failed to find a package root (directory that contains "package.json" file)', - `Lookup start in: ${dirname}`, - ].join('\n'), - ); - } + assertPackageRoot(); - const report = []; + const { changedEntries, unchangedEntries } = getChangedEntriesInReport(report); - report.push('## 📊 Bundle size report'); - report.push(''); + const reportOutput = ['## 📊 Bundle size report', '']; - const { changedEntries, unchangedEntries } = getChangedEntriesInReport(result); + if (changedEntries.length === 0) { + reportOutput.push(`✅ No changes found`); + console.log(reportOutput.join('\n')); + return; + } if (changedEntries.length > 0) { - report.push('| Package & Exports | Baseline (minified/GZIP) | PR | Change |'); - report.push('| :---------------- | -----------------------: | ----: | ---------: |'); + reportOutput.push('| Package & Exports | Baseline (minified/GZIP) | PR | Change |'); + reportOutput.push('| :---------------- | -----------------------: | ----: | ---------: |'); changedEntries.forEach(entry => { const title = `${entry.packageName}
${entry.name}`; @@ -71,19 +67,19 @@ export async function markdownReporter(result: ComparedReport, commitSHA: string ? '🆕 New entry' : [`${formatDelta(entry.diff.minified)}`, '
', `${formatDelta(entry.diff.gzip)}`].join(''); - report.push(`| ${title} | ${before} | ${after} | ${difference}|`); + reportOutput.push(`| ${title} | ${before} | ${after} | ${difference}|`); }); - report.push(''); + reportOutput.push(''); } - if (unchangedEntries.length > 0) { - report.push('
'); - report.push('Unchanged fixtures'); - report.push(''); + if (showUnchanged && unchangedEntries.length > 0) { + reportOutput.push('
'); + reportOutput.push('Unchanged fixtures'); + reportOutput.push(''); - report.push('| Package & Exports | Size (minified/GZIP) |'); - report.push('| ----------------- | -------------------: |'); + reportOutput.push('| Package & Exports | Size (minified/GZIP) |'); + reportOutput.push('| ----------------- | -------------------: |'); unchangedEntries.forEach(entry => { const title = `${entry.packageName}
${entry.name}`; @@ -91,16 +87,28 @@ export async function markdownReporter(result: ComparedReport, commitSHA: string '', ); - report.push(`| ${title} | ${size} |`); + reportOutput.push(`| ${title} | ${size} |`); }); - report.push('
'); + reportOutput.push('
'); } // TODO: use repo settings - report.push( - `🤖 This report was generated against ${commitSHA}`, - ); + reportOutput.push(footer); + + console.log(reportOutput.join('\n')); +}; - console.log(report.join('\n')); +function assertPackageRoot() { + const dirname = fileURLToPath(new URL('.', import.meta.url)); + const packageRoot = findPackageRoot(dirname); + + if (!packageRoot) { + throw new Error( + [ + 'Failed to find a package root (directory that contains "package.json" file)', + `Lookup start in: ${dirname}`, + ].join('\n'), + ); + } } diff --git a/packages/monosize/src/reporters/markdownReporter.test.mts b/packages/monosize/src/reporters/markdownReporter.test.mts index d808530..6e7ba07 100644 --- a/packages/monosize/src/reporters/markdownReporter.test.mts +++ b/packages/monosize/src/reporters/markdownReporter.test.mts @@ -4,16 +4,34 @@ import { describe, expect, it, vitest } from 'vitest'; import { markdownReporter } from './markdownReporter.mjs'; import { sampleComparedReport } from '../__fixture__/sampleComparedReport.mjs'; +// eslint-disable-next-line @typescript-eslint/no-empty-function +const noop = () => {}; + describe('markdownReporter', () => { - it('renders a report to a file', async () => { - const log = vitest.spyOn(console, 'log').mockImplementation(() => { - /* no op */ - }); + const options = { + repository: 'https://github.com/microsoft/monosize', + commitSHA: 'commit-hash', + showUnchanged: true, + }; + + it('wont render anything if there is nothing to compare', () => { + const log = vitest.spyOn(console, 'log').mockImplementation(noop); + + markdownReporter([], options); + + const output = prettier.format(log.mock.calls[0][0], { parser: 'markdown' }); + expect(output).toMatchInlineSnapshot(` + "## 📊 Bundle size report + + ✅ No changes found + " + `); + }); - const repository = 'https://github.com/microsoft/monosize'; - const commitSHA = 'commit-hash'; + it('renders a report to a file', () => { + const log = vitest.spyOn(console, 'log').mockImplementation(noop); - await markdownReporter(sampleComparedReport, commitSHA, repository, true); + markdownReporter(sampleComparedReport, options); const output = prettier.format(log.mock.calls[0][0], { parser: 'markdown' }); expect(output).toMatchSnapshot(); diff --git a/packages/monosize/src/reporters/shared.mts b/packages/monosize/src/reporters/shared.mts new file mode 100644 index 0000000..9622139 --- /dev/null +++ b/packages/monosize/src/reporters/shared.mts @@ -0,0 +1,6 @@ +import type { ComparedReport } from '../utils/compareResultsInReports.mjs'; + +export type Reporter = ( + report: ComparedReport, + options: { commitSHA: string; repository: string; showUnchanged: boolean }, +) => void;