Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { type CoreConfig } from '@code-pushup/models';

export default {
upload: {
organization: 'code-pushup',
Expand Down Expand Up @@ -42,4 +40,4 @@ export default {
icon: 'javascript',
},
],
} satisfies CoreConfig;
};
12 changes: 12 additions & 0 deletions packages/cli/mocks/configs/code-pushup.needs-tsconfig.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// the point is to test runtime import which requires tsconfig for path aliases

/* eslint-disable import/no-unresolved */
// @ts-expect-error - test tsconfig paths missing in config
import customPlugin from '@example/custom-plugin';

/* eslint-enable import/no-unresolved */
const config = {
plugins: [customPlugin],
};

export default config;
11 changes: 11 additions & 0 deletions packages/cli/mocks/configs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"baseUrl": ".",
"allowImportingTsExtensions": true,
"moduleResolution": "node",
"paths": {
"@example/custom-plugin": ["./custom-plugin.ts"]
}
},
"include": ["*.ts"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ const configDirPath = path.join(
'..',
'..',
'..',
'..',
'testing',
'test-fixtures',
'src',
'lib',
'fixtures',
'cli',
'mocks',
'configs',
);

Expand All @@ -24,22 +20,13 @@ describe('coreConfigMiddleware', () => {
skipPlugins: [],
};

it.each(['ts', 'mjs', 'js'])(
'should load a valid .%s config',
async extension => {
const config = await coreConfigMiddleware({
config: path.join(configDirPath, `code-pushup.config.${extension}`),
...CLI_DEFAULTS,
});
expect(config.config).toContain(`code-pushup.config.${extension}`);
expect(config.upload?.project).toContain(extension);
},
);

it('should throw with invalid config path', async () => {
await expect(
coreConfigMiddleware({ config: 'wrong/path/to/config', ...CLI_DEFAULTS }),
).rejects.toThrow(/File '.*' does not exist/);
it('should load a valid .%s config', async () => {
const config = await coreConfigMiddleware({
config: path.join(configDirPath, `code-pushup.config.ts`),
...CLI_DEFAULTS,
});
expect(config.config).toContain(`code-pushup.config.ts`);
expect(config.upload?.project).toContain('ts');
Comment on lines +23 to +29
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test description still uses the it.each placeholder syntax (.%s), but it's now a plain it(). Was the intent to remove the .mjs and .js cases, or was this an accidental leftover from the refactor? If they were intentionally removed, what covers those formats now?

});

it('should load config which relies on provided --tsconfig', async () => {
Expand All @@ -54,16 +41,4 @@ describe('coreConfigMiddleware', () => {
}),
).resolves.toBeTruthy();
});

it('should throw if --tsconfig is missing but needed to resolve import', async () => {
await expect(
coreConfigMiddleware({
config: path.join(
configDirPath,
'code-pushup.needs-tsconfig.config.ts',
),
...CLI_DEFAULTS,
}),
).rejects.toThrow("Cannot find package '@example/custom-plugin'");
});
});
File renamed without changes.
24 changes: 24 additions & 0 deletions packages/core/mocks/fixtures/configs/custom-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const customPluginConfig = {
slug: 'good-feels',
title: 'Good feels',
icon: 'javascript',
audits: [
{
slug: 'always-perfect',
title: 'Always perfect',
},
],
runner: () => [
{
slug: 'always-perfect',
score: 1,
value: 100,
displayValue: '✅ Perfect! 👌',
},
],
};

export function customPlugin() {
return customPluginConfig;
}
export default customPluginConfig;
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@ describe('readRcByPath', () => {
'..',
'..',
'..',
'..',
'..',
'testing',
'test-fixtures',
'src',
'lib',
'mocks',
'fixtures',
'configs',
);
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/lib/implementation/read-rc-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export async function readRcByPath(
const result = await importModule({
filepath: filePath,
tsconfig,
format: 'esm',
});
return { result, message: `Imported config from ${formattedTarget}` };
},
Expand Down
27 changes: 14 additions & 13 deletions packages/core/src/lib/implementation/read-rc-file.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,33 @@ import { CONFIG_FILE_NAME, type CoreConfig } from '@code-pushup/models';
import { MEMFS_VOLUME } from '@code-pushup/test-utils';
import { autoloadRc } from './read-rc-file.js';

// mock bundleRequire inside importEsmModule used for fetching config
vi.mock('bundle-require', async () => {
// mock importModule from @code-pushup/utils used for fetching config
vi.mock('@code-pushup/utils', async () => {
const utils =
await vi.importActual<typeof import('@code-pushup/utils')>(
'@code-pushup/utils',
);
const { CORE_CONFIG_MOCK }: Record<string, CoreConfig> =
await vi.importActual('@code-pushup/test-fixtures');

return {
bundleRequire: vi
...utils,
importModule: vi
.fn()
.mockImplementation((options: { filepath: string }) => {
.mockImplementation(async (options: { filepath: string }) => {
const extension = options.filepath.split('.').at(-1);
return {
mod: {
default: {
...CORE_CONFIG_MOCK,
upload: {
...CORE_CONFIG_MOCK?.upload,
project: extension, // returns loaded file extension to check format precedence
},
},
...CORE_CONFIG_MOCK,
upload: {
...CORE_CONFIG_MOCK?.upload,
project: extension, // returns loaded file extension to check format precedence
},
};
}),
};
});

// Note: memfs files are only listed to satisfy a system check, value is used from bundle-require mock
// Note: memfs files are only listed to satisfy a system check, value is used from importModule mock
describe('autoloadRc', () => {
it('prioritise a .ts configuration file', async () => {
vol.fromJSON(
Expand Down
1 change: 0 additions & 1 deletion packages/plugin-coverage/src/lib/nx/coverage-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ export async function getCoveragePathForVitest(

const vitestConfig = await importModule<VitestCoverageConfig>({
filepath: config,
format: 'esm',
});

const reportsDirectory =
Expand Down
132 changes: 69 additions & 63 deletions packages/plugin-coverage/src/lib/nx/coverage-paths.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,80 +13,86 @@ import {
getCoveragePathsForTarget,
} from './coverage-paths.js';

vi.mock('bundle-require', () => ({
bundleRequire: vi.fn().mockImplementation((options: { filepath: string }) => {
const VITEST_VALID: VitestCoverageConfig = {
test: {
coverage: {
reporter: ['lcov'],
reportsDirectory: path.join('coverage', 'cli'),
},
},
};
vi.mock('@code-pushup/utils', async () => {
const utils =
await vi.importActual<typeof import('@code-pushup/utils')>(
'@code-pushup/utils',
);

const VITEST_NO_DIR: VitestCoverageConfig = {
test: { coverage: { reporter: ['lcov'] } },
};
return {
...utils,
importModule: vi
.fn()
.mockImplementation(async (options: { filepath: string }) => {
const VITEST_VALID: VitestCoverageConfig = {
test: {
coverage: {
reporter: ['lcov'],
reportsDirectory: path.join('coverage', 'cli'),
},
},
};

const VITEST_NO_LCOV: VitestCoverageConfig = {
test: {
coverage: {
reporter: ['json'],
reportsDirectory: 'coverage',
},
},
};
const VITEST_NO_DIR: VitestCoverageConfig = {
test: { coverage: { reporter: ['lcov'] } },
};

const JEST_VALID: JestCoverageConfig = {
coverageReporters: ['lcov'],
coverageDirectory: path.join('coverage', 'core'),
};
const VITEST_NO_LCOV: VitestCoverageConfig = {
test: {
coverage: {
reporter: ['json'],
reportsDirectory: 'coverage',
},
},
};

const JEST_NO_DIR: JestCoverageConfig = {
coverageReporters: ['lcov'],
};
const JEST_VALID: JestCoverageConfig = {
coverageReporters: ['lcov'],
coverageDirectory: path.join('coverage', 'core'),
};

const JEST_NO_LCOV: JestCoverageConfig = {
coverageReporters: ['json'],
coverageDirectory: 'coverage',
};
const JEST_NO_DIR: JestCoverageConfig = {
coverageReporters: ['lcov'],
};

const JEST_PRESET: JestCoverageConfig & { preset?: string } = {
preset: '../../jest.preset.ts',
coverageDirectory: 'coverage',
};
const JEST_NO_LCOV: JestCoverageConfig = {
coverageReporters: ['json'],
coverageDirectory: 'coverage',
};

const wrapReturnValue = (
value: VitestCoverageConfig | JestCoverageConfig,
) => ({ mod: { default: value } });
const JEST_PRESET: JestCoverageConfig & { preset?: string } = {
preset: '../../jest.preset.ts',
coverageDirectory: 'coverage',
};

const config = options.filepath.split('.')[0];
switch (config) {
case 'vitest-valid':
return wrapReturnValue(VITEST_VALID);
case 'vitest-no-lcov':
return wrapReturnValue(VITEST_NO_LCOV);
case 'vitest-no-dir':
return wrapReturnValue(VITEST_NO_DIR);
case 'jest-valid':
return wrapReturnValue(JEST_VALID);
case 'jest-no-lcov':
return wrapReturnValue(JEST_NO_LCOV);
case 'jest-no-dir':
return wrapReturnValue(JEST_NO_DIR);
case 'jest-preset':
return wrapReturnValue(JEST_PRESET);
default:
return wrapReturnValue({});
}
}),
}));
const config = options.filepath.split('.')[0];
switch (config) {
case 'vitest-valid':
return VITEST_VALID;
case 'vitest-no-lcov':
return VITEST_NO_LCOV;
case 'vitest-no-dir':
return VITEST_NO_DIR;
case 'jest-valid':
return JEST_VALID;
case 'jest-no-lcov':
return JEST_NO_LCOV;
case 'jest-no-dir':
return JEST_NO_DIR;
case 'jest-preset':
return JEST_PRESET;
default:
return {};
}
}),
};
});

describe('getCoveragePathForTarget', () => {
beforeEach(() => {
vol.fromJSON(
{
// values come from bundle-require mock above
// values come from importModule mock above
'vitest-valid.config.ts': '',
'jest-valid.config.ts': '',
},
Expand Down Expand Up @@ -162,7 +168,7 @@ describe('getCoveragePathForVitest', () => {
beforeEach(() => {
vol.fromJSON(
{
// values come from bundle-require mock above
// values come from importModule mock above
'vitest-valid.config.unit.ts': '',
'vitest-no-dir.config.integration.ts': '',
'vitest-no-lcov.config.integration.ts': '',
Expand Down Expand Up @@ -260,7 +266,7 @@ describe('getCoveragePathForJest', () => {
beforeEach(() => {
vol.fromJSON(
{
// values come from bundle-require mock above
// values come from importModule mock above
'jest-preset.config.ts': '',
'jest-valid.config.unit.ts': '',
'jest-valid.config.integration.ts': '',
Expand Down
1 change: 0 additions & 1 deletion packages/plugin-lighthouse/src/lib/runner/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ export async function getConfig(
message,
result: await importModule<Config>({
filepath: configPath,
format: 'esm',
}),
};
}
Expand Down
Loading