Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(test-setup): add custom matchers for ui logger #923

Merged
merged 10 commits into from
Jan 21, 2025
4 changes: 2 additions & 2 deletions packages/cli/src/lib/compare/compare-command.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
DEFAULT_PERSIST_FORMAT,
DEFAULT_PERSIST_OUTPUT_DIR,
} from '@code-pushup/models';
import { getLogMessages } from '@code-pushup/test-utils';
import { ui } from '@code-pushup/utils';
import { DEFAULT_CLI_CONFIGURATION } from '../../../mocks/constants.js';
import { yargsCli } from '../yargs-cli.js';
Expand Down Expand Up @@ -75,7 +74,8 @@ describe('compare-command', () => {
{ ...DEFAULT_CLI_CONFIGURATION, commands: [yargsCompareCommandObject()] },
).parseAsync();

expect(getLogMessages(ui().logger).at(-1)).toContain(
expect(ui()).toHaveLogged(
'info',
`Reports diff written to ${bold(
'.code-pushup/report-diff.json',
)} and ${bold('.code-pushup/report-diff.md')}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,6 @@ describe('filterMiddleware', () => {
);

it('should trigger verbose logging when skipPlugins or onlyPlugins removes categories', () => {
const loggerSpy = vi.spyOn(ui().logger, 'info');

filterMiddleware({
onlyPlugins: ['p1'],
skipPlugins: ['p2'],
Expand All @@ -316,8 +314,15 @@ describe('filterMiddleware', () => {
verbose: true,
});

expect(loggerSpy).toHaveBeenCalledWith(
expect.stringContaining('removed the following categories'),
expect(ui()).toHaveNthLogged(
1,
'info',
'The --skipPlugins argument removed the following categories: c1, c2.',
);
expect(ui()).toHaveNthLogged(
2,
'info',
'The --onlyPlugins argument removed the following categories: c1, c2.',
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@ describe('logErrorBeforeThrow', () => {
});

it('should log a custom error when OptionValidationError is thrown', async () => {
const loggerSpy = vi.spyOn(ui().logger, 'error').mockImplementation(() => {
/* empty */
});

const errorFn = vi
.fn()
.mockRejectedValue(new OptionValidationError('Option validation failed'));
Expand All @@ -68,8 +64,7 @@ describe('logErrorBeforeThrow', () => {
} catch {
/* suppress */
}

expect(loggerSpy).toHaveBeenCalledWith('Option validation failed');
expect(ui()).toHaveLogged('error', 'Option validation failed');
});

it('should rethrow errors other than OptionValidationError', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { describe, expect } from 'vitest';
import type { CategoryConfig, PluginConfig } from '@code-pushup/models';
import { getLogMessages } from '@code-pushup/test-utils';
import { ui } from '@code-pushup/utils';
import type { FilterOptionType, Filterables } from './filter.model.js';
import {
Expand All @@ -19,22 +18,22 @@ describe('validateFilterOption', () => {
[
'onlyPlugins',
['p1', 'p3', 'p4'],
'The --onlyPlugins argument references plugins that do not exist: p3, p4.',
'The --onlyPlugins argument references plugins that do not exist: p3, p4. The only valid plugin is p1.',
],
[
'onlyPlugins',
['p1', 'p3'],
'The --onlyPlugins argument references a plugin that does not exist: p3.',
'The --onlyPlugins argument references a plugin that does not exist: p3. The only valid plugin is p1.',
],
[
'onlyCategories',
['c1', 'c3', 'c4'],
'The --onlyCategories argument references categories that do not exist: c3, c4.',
'The --onlyCategories argument references categories that do not exist: c3, c4. The only valid category is c1.',
],
[
'onlyCategories',
['c1', 'c3'],
'The --onlyCategories argument references a category that does not exist: c3.',
'The --onlyCategories argument references a category that does not exist: c3. The only valid category is c1.',
],
])(
'should log a warning if the only argument %s references nonexistent slugs %o along with valid ones',
Expand All @@ -51,31 +50,30 @@ describe('validateFilterOption', () => {
},
{ itemsToFilter, skippedItems: [], verbose: false },
);
const logs = getLogMessages(ui().logger);
expect(logs[0]).toContain(expected);
expect(ui()).toHaveLogged('warn', expected);
},
);

it.each([
[
'skipPlugins',
['p3', 'p4'],
'The --skipPlugins argument references plugins that do not exist: p3, p4.',
'The --skipPlugins argument references plugins that do not exist: p3, p4. The only valid plugin is p1.',
],
[
'skipPlugins',
['p3'],
'The --skipPlugins argument references a plugin that does not exist: p3.',
'The --skipPlugins argument references a plugin that does not exist: p3. The only valid plugin is p1.',
],
[
'skipCategories',
['c3', 'c4'],
'The --skipCategories argument references categories that do not exist: c3, c4.',
'The --skipCategories argument references categories that do not exist: c3, c4. The only valid category is c1.',
],
[
'skipCategories',
['c3'],
'The --skipCategories argument references a category that does not exist: c3.',
'The --skipCategories argument references a category that does not exist: c3. The only valid category is c1.',
],
])(
'should log a warning if the skip argument %s references nonexistent slugs %o',
Expand All @@ -95,8 +93,7 @@ describe('validateFilterOption', () => {
},
{ itemsToFilter, skippedItems: [], verbose: false },
);
const logs = getLogMessages(ui().logger);
expect(logs[0]).toContain(expected);
expect(ui()).toHaveLogged('warn', expected);
},
);

Expand All @@ -111,7 +108,7 @@ describe('validateFilterOption', () => {
},
{ itemsToFilter: ['p1'], skippedItems: [], verbose: false },
);
expect(getLogMessages(ui().logger)).toHaveLength(0);
expect(ui()).not.toHaveLogs();
});

it('should log a category ignored as a result of plugin filtering', () => {
Expand All @@ -130,9 +127,10 @@ describe('validateFilterOption', () => {
},
{ itemsToFilter: ['p1'], skippedItems: [], verbose: true },
);
expect(getLogMessages(ui().logger)).toHaveLength(1);
expect(getLogMessages(ui().logger)[0]).toContain(
'The --onlyPlugins argument removed the following categories: c1, c3',
expect(ui()).toHaveLoggedTimes(1);
expect(ui()).toHaveLogged(
'info',
'The --onlyPlugins argument removed the following categories: c1, c3.',
);
});

Expand Down Expand Up @@ -221,10 +219,16 @@ describe('validateFilterOption', () => {
{ plugins, categories },
{ itemsToFilter: ['p1'], skippedItems: ['p1'], verbose: true },
);
const logs = getLogMessages(ui().logger);
expect(logs[0]).toContain(
expect(ui()).toHaveNthLogged(
1,
'warn',
'The --skipPlugins argument references a skipped plugin: p1.',
);
expect(ui()).toHaveNthLogged(
2,
'info',
'The --skipPlugins argument removed the following categories: c1.',
);
});
});

Expand Down Expand Up @@ -446,7 +450,6 @@ describe('validateSkippedCategories', () => {
] as NonNullable<Filterables['categories']>;

it('should log info when categories are removed', () => {
const loggerSpy = vi.spyOn(ui().logger, 'info');
validateSkippedCategories(
categories,
[
Expand All @@ -457,7 +460,8 @@ describe('validateSkippedCategories', () => {
] as NonNullable<Filterables['categories']>,
true,
);
expect(loggerSpy).toHaveBeenCalledWith(
expect(ui()).toHaveLogged(
'info',
'Category c1 was removed because all its refs were skipped. Affected refs: g1 (group)',
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
DEFAULT_PERSIST_FORMAT,
DEFAULT_PERSIST_OUTPUT_DIR,
} from '@code-pushup/models';
import { getLogMessages } from '@code-pushup/test-utils';
import { ui } from '@code-pushup/utils';
import { DEFAULT_CLI_CONFIGURATION } from '../../../mocks/constants.js';
import { yargsCli } from '../yargs-cli.js';
Expand Down Expand Up @@ -65,7 +64,8 @@ describe('merge-diffs-command', () => {
},
).parseAsync();

expect(getLogMessages(ui().logger).at(-1)).toContain(
expect(ui()).toHaveLogged(
'info',
`Reports diff written to ${bold('.code-pushup/report-diff.md')}`,
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { describe, expect, vi } from 'vitest';
import { getLogMessages } from '@code-pushup/test-utils';
import { ui } from '@code-pushup/utils';
import { DEFAULT_CLI_CONFIGURATION } from '../../../mocks/constants.js';
import { yargsCli } from '../yargs-cli.js';
Expand Down Expand Up @@ -27,11 +26,16 @@ describe('print-config-command', () => {
{ ...DEFAULT_CLI_CONFIGURATION, commands: [yargsConfigCommandObject()] },
).parseAsync();

const log = getLogMessages(ui().logger)[0];
expect(log).not.toContain('"$0":');
expect(log).not.toContain('"_":');
expect(ui()).not.toHaveLogged('log', expect.stringContaining('"$0":'));
expect(ui()).not.toHaveLogged('log', expect.stringContaining('"_":'));

expect(log).toContain('"outputDir": "destinationDir"');
expect(log).not.toContain('"output-dir":');
expect(ui()).toHaveLogged(
'log',
expect.stringContaining('"outputDir": "destinationDir"'),
);
expect(ui()).not.toHaveLogged(
'log',
expect.stringContaining('"output-dir":'),
);
});
});
3 changes: 2 additions & 1 deletion packages/cli/tsconfig.test.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"src/**/*.test.tsx",
"src/**/*.test.js",
"src/**/*.test.jsx",
"src/**/*.d.ts"
"src/**/*.d.ts",
"../../testing/test-setup/src/vitest.d.ts"
]
}
1 change: 1 addition & 0 deletions packages/cli/vite.config.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default defineConfig({
'../../testing/test-setup/src/lib/console.mock.ts',
'../../testing/test-setup/src/lib/portal-client.mock.ts',
'../../testing/test-setup/src/lib/reset.mocks.ts',
'../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts',
],
},
});
4 changes: 1 addition & 3 deletions packages/core/src/lib/collect-and-persist.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
ISO_STRING_REGEXP,
MINIMAL_CONFIG_MOCK,
MINIMAL_REPORT_MOCK,
getLogMessages,
} from '@code-pushup/test-utils';
import {
type ScoredReport,
Expand Down Expand Up @@ -115,7 +114,6 @@ describe('collectAndPersistReports', () => {
await collectAndPersistReports(
MINIMAL_CONFIG_MOCK as CollectAndPersistReportsOptions,
);
const logs = getLogMessages(ui().logger);
expect(logs.at(-2)).toContain('Made with ❤ by code-pushup.dev');
expect(ui()).toHaveLogged('log', 'Made with ❤ by code-pushup.dev');
});
});
53 changes: 38 additions & 15 deletions packages/core/src/lib/implementation/persist.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
MEMFS_VOLUME,
MINIMAL_REPORT_MOCK,
REPORT_MOCK,
getLogMessages,
} from '@code-pushup/test-utils';
import { scoreReport, sortReport, ui } from '@code-pushup/utils';
import { logPersistedResults, persistReport } from './persist.js';
Expand Down Expand Up @@ -91,30 +90,54 @@ describe('persistReport', () => {
describe('logPersistedResults', () => {
it('should log report sizes correctly`', () => {
logPersistedResults([{ status: 'fulfilled', value: ['out.json', 10_000] }]);
const logs = getLogMessages(ui().logger);
expect(logs[0]).toBe('[ green(success) ] Generated reports successfully: ');
expect(logs[1]).toContain('9.77 kB');
expect(logs[1]).toContain('out.json');
expect(ui()).toHaveNthLogged(
1,
'success',
expect.stringContaining('Generated reports successfully: '),
);
expect(ui()).toHaveNthLogged(
2,
'success',
expect.stringContaining('9.77 kB'),
);
expect(ui()).toHaveNthLogged(
2,
'success',
expect.stringContaining('out.json'),
);
});

it('should log fails correctly`', () => {
logPersistedResults([{ status: 'rejected', reason: 'fail' }]);
const logs = getLogMessages(ui().logger);
expect(logs[0]).toBe('[ yellow(warn) ] Generated reports failed: ');
expect(logs[1]).toContain('fail');
expect(ui()).toHaveNthLogged(1, 'warn', 'Generated reports failed: ');
expect(ui()).toHaveNthLogged(2, 'warn', expect.stringContaining('fail'));
});

it('should log report sizes and fails correctly`', () => {
logPersistedResults([
{ status: 'fulfilled', value: ['out.json', 10_000] },
{ status: 'rejected', reason: 'fail' },
]);
const logs = getLogMessages(ui().logger);
expect(logs[0]).toBe('[ green(success) ] Generated reports successfully: ');
expect(logs[1]).toContain('out.json');
expect(logs[1]).toContain('9.77 kB');

expect(logs[2]).toContain('Generated reports failed: ');
expect(logs[2]).toContain('fail');
expect(ui()).toHaveNthLogged(
1,
'success',
'Generated reports successfully: ',
);
expect(ui()).toHaveNthLogged(
2,
'success',
expect.stringContaining('out.json'),
);
expect(ui()).toHaveNthLogged(
2,
'success',
expect.stringContaining('9.77 kB'),
);
expect(ui()).toHaveNthLogged(
3,
'warn',
expect.stringContaining('Generated reports failed: '),
);
expect(ui()).toHaveNthLogged(3, 'warn', expect.stringContaining('fail'));
});
});
11 changes: 8 additions & 3 deletions packages/core/src/lib/merge-diffs.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import path from 'node:path';
import type { PersistConfig } from '@code-pushup/models';
import {
MEMFS_VOLUME,
getLogMessages,
reportsDiffAddedPluginMock,
reportsDiffAltMock,
reportsDiffMock,
Expand Down Expand Up @@ -64,13 +63,19 @@ describe('mergeDiffs', () => {
),
).resolves.toBe(path.join(MEMFS_VOLUME, 'report-diff.md'));

expect(getLogMessages(ui().logger)).toEqual([
expect(ui()).toHaveNthLogged(
1,
'warn',
expect.stringContaining(
'Skipped invalid report diff - Failed to read JSON file missing-report-diff.json',
),
);
expect(ui()).toHaveNthLogged(
2,
'warn',
expect.stringContaining(
'Skipped invalid report diff - Invalid reports diff in invalid-report-diff.json',
),
]);
);
});
});
Loading
Loading