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

export default {
upload: {
organization: 'code-pushup',
Expand DownExpand 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
Comment thread
BioPhoton marked this conversation as resolved.
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"baseUrl": ".",
"allowImportingTsExtensions": true,
"moduleResolution": "node",
"paths": {
"@example/custom-plugin": ["./custom-plugin.ts"]
}
},
"include": ["*.ts"]
}
Original file line numberDiff line numberDiff 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 .ts 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');
});

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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -144,7 +144,6 @@ export async function getConfig(
message,
result: await importModule<Config>({
filepath: configPath,
format: 'esm',
}),
};
}
Expand Down
Loading