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

feat: skip perfect scores in stdout summary #833

Merged
merged 2 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions packages/core/src/lib/collect-and-persist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import {
type PersistConfig,
pluginReportSchema,
} from '@code-pushup/models';
import { verboseUtils } from '@code-pushup/utils';
import {
logStdoutSummary,
scoreReport,
sortReport,
verboseUtils,
} from '@code-pushup/utils';
import { collect } from './implementation/collect';
import { logPersistedResults, persistReport } from './implementation/persist';
import type { GlobalOptions } from './types';
Expand All @@ -18,7 +23,16 @@ export async function collectAndPersistReports(
const { exec } = verboseUtils(options.verbose);

const report = await collect(options);
const persistResults = await persistReport(report, options.persist);
const sortedScoredReport = sortReport(scoreReport(report));
const persistResults = await persistReport(
report,
sortedScoredReport,
options.persist,
);

// terminal output
logStdoutSummary(sortedScoredReport, options.verbose);

exec(() => {
logPersistedResults(persistResults);
});
Expand Down
38 changes: 37 additions & 1 deletion packages/core/src/lib/collect-and-persist.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { describe } from 'vitest';
import { type MockInstance, describe } from 'vitest';
import {
ISO_STRING_REGEXP,
MINIMAL_CONFIG_MOCK,
MINIMAL_REPORT_MOCK,
getLogMessages,
} from '@code-pushup/test-utils';
import {
type ScoredReport,
logStdoutSummary,
scoreReport,
sortReport,
ui,
} from '@code-pushup/utils';
import * as utils from '@code-pushup/utils';
import {
type CollectAndPersistReportsOptions,
collectAndPersistReports,
Expand All @@ -21,7 +30,21 @@ vi.mock('./implementation/persist', () => ({
}));

describe('collectAndPersistReports', () => {
let logStdoutSpy: MockInstance<
[report: ScoredReport, verbose?: boolean],
void
>;

beforeEach(() => {
logStdoutSpy = vi.spyOn(utils, 'logStdoutSummary');
});

afterAll(() => {
logStdoutSpy.mockRestore();
});

it('should call collect and persistReport with correct parameters in non-verbose mode', async () => {
const sortedScoredReport = sortReport(scoreReport(MINIMAL_REPORT_MOCK));
const nonVerboseConfig: CollectAndPersistReportsOptions = {
categories: [],
...MINIMAL_CONFIG_MOCK,
Expand Down Expand Up @@ -49,17 +72,20 @@ describe('collectAndPersistReports', () => {
categories: expect.any(Array),
plugins: expect.any(Array),
},
sortedScoredReport,
{
outputDir: 'output',
filename: 'report',
format: ['md'],
},
);

expect(logStdoutSummary).toHaveBeenCalledWith(sortedScoredReport, false);
expect(logPersistedResults).not.toHaveBeenCalled();
});

it('should call collect and persistReport with correct parameters in verbose mode', async () => {
const sortedScoredReport = sortReport(scoreReport(MINIMAL_REPORT_MOCK));
const verboseConfig: CollectAndPersistReportsOptions = {
categories: [],
...MINIMAL_CONFIG_MOCK,
Expand All @@ -77,9 +103,19 @@ describe('collectAndPersistReports', () => {

expect(persistReport).toHaveBeenCalledWith(
MINIMAL_REPORT_MOCK,
sortedScoredReport,
verboseConfig.persist,
);

expect(logStdoutSummary).toHaveBeenCalledWith(sortedScoredReport, true);
expect(logPersistedResults).toHaveBeenCalled();
});

it('should print a summary to stdout', async () => {
await collectAndPersistReports(
MINIMAL_CONFIG_MOCK as CollectAndPersistReportsOptions,
);
const logs = getLogMessages(ui().logger);
expect(logs.at(-2)).toContain('Made with ❤ by code-pushup.dev');
});
});
9 changes: 2 additions & 7 deletions packages/core/src/lib/implementation/persist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { join } from 'node:path';
import type { PersistConfig, Report } from '@code-pushup/models';
import {
type MultipleFileResults,
type ScoredReport,
directoryExists,
generateMdReport,
logMultipleFileResults,
logStdoutSummary,
scoreReport,
sortReport,
ui,
} from '@code-pushup/utils';

Expand All @@ -26,14 +24,11 @@ export class PersistError extends Error {

export async function persistReport(
report: Report,
sortedScoredReport: ScoredReport,
options: Required<PersistConfig>,
): Promise<MultipleFileResults> {
const { outputDir, filename, format } = options;

const sortedScoredReport = sortReport(scoreReport(report));
// terminal output
logStdoutSummary(sortedScoredReport);

// collect physical format outputs
const results = format.map(reportType => {
switch (reportType) {
Expand Down
31 changes: 7 additions & 24 deletions packages/core/src/lib/implementation/persist.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,17 @@ import {
REPORT_MOCK,
getLogMessages,
} from '@code-pushup/test-utils';
import { ui } from '@code-pushup/utils';
import { scoreReport, sortReport, ui } from '@code-pushup/utils';
import { logPersistedResults, persistReport } from './persist';

describe('persistReport', () => {
beforeEach(() => {
vol.fromJSON({}, MEMFS_VOLUME);
});

it('should print a summary to stdout when no format is specified`', async () => {
await persistReport(MINIMAL_REPORT_MOCK, {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: [],
});
const logs = getLogMessages(ui().logger);
expect(logs.at(-2)).toContain('Made with ❤ by code-pushup.dev');
});

it('should print a summary to stdout when all formats are specified`', async () => {
await persistReport(MINIMAL_REPORT_MOCK, {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: ['md', 'json'],
});
const logs = getLogMessages(ui().logger);
expect(logs.at(-2)).toContain('Made with ❤ by code-pushup.dev');
});

it('should create a report in json format', async () => {
await persistReport(MINIMAL_REPORT_MOCK, {
const sortedScoredReport = sortReport(scoreReport(MINIMAL_REPORT_MOCK));
await persistReport(MINIMAL_REPORT_MOCK, sortedScoredReport, {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: ['json'],
Expand All @@ -60,7 +41,8 @@ describe('persistReport', () => {
});

it('should create a report in md format', async () => {
await persistReport(MINIMAL_REPORT_MOCK, {
const sortedScoredReport = sortReport(scoreReport(MINIMAL_REPORT_MOCK));
await persistReport(MINIMAL_REPORT_MOCK, sortedScoredReport, {
outputDir: MEMFS_VOLUME,
filename: 'report',
format: ['md'],
Expand All @@ -75,7 +57,8 @@ describe('persistReport', () => {
});

it('should create a report with categories section in all formats', async () => {
await persistReport(REPORT_MOCK, {
const sortedScoredReport = sortReport(scoreReport(REPORT_MOCK));
await persistReport(REPORT_MOCK, sortedScoredReport, {
outputDir: MEMFS_VOLUME,
format: ['md', 'json'],
filename: 'report',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Code PushUp Report - @code-pushup/[email protected]


ESLint audits

● ... All 47 audits have perfect scores ...


Lighthouse audits

● Minimize third-party usage Third-party code
blocked the main
thread for 6,850 ms
● First Contentful Paint 1.2 s
● Largest Contentful Paint 1.5 s
● Speed Index 1.2 s
● ... 2 audits with perfect scores omitted for brevity ...

Categories

┌─────────────────────────────────────────────────────────┬─────────┬──────────┐
│ Category │ Score │ Audits │
├─────────────────────────────────────────────────────────┼─────────┼──────────┤
│ Performance │ 92 │ 8 │
├─────────────────────────────────────────────────────────┼─────────┼──────────┤
│ Bug prevention │ 100 │ 16 │
├─────────────────────────────────────────────────────────┼─────────┼──────────┤
│ Code style │ 100 │ 13 │
└─────────────────────────────────────────────────────────┴─────────┴──────────┘

Made with ❤ by code-pushup.dev
Original file line number Diff line number Diff line change
Expand Up @@ -19,59 +19,7 @@ ESLint audits
never reassigned after declared
● Require braces around arrow function bodies 1 warning
● Require the use of `===` and `!==` 1 warning
● Disallow `target="_blank"` attribute without passed
`rel="noreferrer"`
● Disallow assignment operators in conditional passed
expressions
● Disallow comments from being inserted as text nodes passed
● Disallow direct mutation of this.state passed
● Disallow duplicate properties in JSX passed
● Disallow invalid regular expression strings in `RegExp` passed
constructors
● Disallow loops with a body that allows only one passed
iteration
● Disallow missing displayName in a React component passed
definition
● Disallow missing React when using JSX passed
● Disallow negating the left operand of relational passed
operators
● Disallow passing of children as props passed
● Disallow React to be incorrectly marked as unused passed
● Disallow reassigning `const` variables passed
● Disallow the use of `debugger` passed
● Disallow the use of undeclared variables unless passed
mentioned in `/*global */` comments
● Disallow undeclared variables in JSX passed
● Disallow unescaped HTML entities from appearing in passed
markup
● Disallow usage of deprecated methods passed
● Disallow usage of findDOMNode passed
● Disallow usage of isMounted passed
● Disallow usage of the return value of ReactDOM.render passed
● Disallow usage of unknown DOM property passed
● Disallow use of optional chaining in contexts where the passed
`undefined` value is not allowed
● Disallow using Object.assign with an object literal as passed
the first argument and prefer the use of object spread
instead
● Disallow using string references passed
● Disallow variables used in JSX to be incorrectly marked passed
as unused
● Disallow when a DOM element is using both children and passed
dangerouslySetInnerHTML
● Enforce a maximum number of lines per file passed
● Enforce camelcase naming convention passed
● Enforce comparing `typeof` expressions against valid passed
strings
● Enforce consistent brace style for all control passed
statements
● Enforce ES5 or ES6 class for returning value in render passed
function
● enforces the Rules of Hooks passed
● Require `let` or `const` instead of `var` passed
● Require calls to `isNaN()` when checking for `NaN` passed
● Require or disallow "Yoda" conditions passed
● Require using arrow functions for callbacks passed
● ... 37 audits with perfect scores omitted for brevity ...


Lighthouse audits
Expand All @@ -82,7 +30,6 @@ Lighthouse audits
● First Contentful Paint 1.2 s
● Largest Contentful Paint 1.5 s
● Speed Index 1.2 s
● Cumulative Layout Shift 0
● Total Blocking Time 0 ms
● ... 2 audits with perfect scores omitted for brevity ...

Made with ❤ by code-pushup.dev
Loading
Loading