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
12 changes: 12 additions & 0 deletions e2e/plugin-js-benchmark-e2e/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import tseslint from 'typescript-eslint';
import baseConfig from '../../eslint.config.js';

export default tseslint.config(...baseConfig, {
files: ['**/*.ts'],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { arrayForLoop, arrayMap } from '../index.js';

const testData = Array.from({ length: 1000 }, (_, i) => i);

export default {
suiteName: 'array-operations',
targetImplementation: 'array-map',
cases: [
['array-map', () => arrayMap(testData)],
['array-for-loop', () => arrayForLoop(testData)],
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { stringConcat, stringJoin } from '../index.js';

export default {
suiteName: 'string-operations',
targetImplementation: 'string-join',
cases: [
['string-concat', () => stringConcat('test', 100)],
['string-join', () => stringJoin('test', 100)],
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import jsBenchmarkPlugin from '@code-pushup/js-benchmark-plugin';

export default {
plugins: [
await jsBenchmarkPlugin({
targets: ['benchmarks/*.bench.js'],
}),
],
};
24 changes: 24 additions & 0 deletions e2e/plugin-js-benchmark-e2e/mocks/fixtures/default-setup/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Utility functions to benchmark
export function arrayMap(arr) {
return arr.map((x) => x * 2);
}

export function arrayForLoop(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
result.push(arr[i] * 2);
}
return result;
}

export function stringConcat(str, count) {
let result = '';
for (let i = 0; i < count; i++) {
result += str;
}
return result;
}

export function stringJoin(str, count) {
return Array(count).fill(str).join('');
}
17 changes: 17 additions & 0 deletions e2e/plugin-js-benchmark-e2e/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "plugin-js-benchmark-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "e2e/plugin-js-benchmark-e2e/src",
"projectType": "application",
"targets": {
"lint": {},
"e2e": {
"executor": "@nx/vitest:test",
"options": {
"configFile": "{projectRoot}/vitest.e2e.config.ts"
}
}
},
"implicitDependencies": ["plugin-js-benchmark"],
"tags": ["scope:plugin", "type:e2e"]
}
53 changes: 53 additions & 0 deletions e2e/plugin-js-benchmark-e2e/tests/collect.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { cp } from 'node:fs/promises';
import path from 'node:path';
import { afterAll, beforeAll, expect } from 'vitest';
import { type Report, reportSchema } from '@code-pushup/models';
import { nxTargetProject } from '@code-pushup/test-nx-utils';
import {
E2E_ENVIRONMENTS_DIR,
TEST_OUTPUT_DIR,
omitVariableReportData,
restoreNxIgnoredFiles,
teardownTestFolder,
} from '@code-pushup/test-utils';
import { executeProcess, readJsonFile } from '@code-pushup/utils';

describe('PLUGIN collect report with js-benchmark-plugin NPM package', () => {
const envDir = path.join(E2E_ENVIRONMENTS_DIR, nxTargetProject());
const testFileDir = path.join(envDir, TEST_OUTPUT_DIR, 'collect');

const fixturesDir = path.join(
'e2e',
nxTargetProject(),
'mocks/fixtures/default-setup',
);

beforeAll(async () => {
await cp(fixturesDir, envDir, { recursive: true });
await restoreNxIgnoredFiles(envDir);
});

afterAll(async () => {
await teardownTestFolder(testFileDir);
});

it('should run plugin over CLI and creates report.json', async () => {
const { code, stdout } = await executeProcess({
command: 'npx',
// verbose exposes audits with perfect scores that are hidden in the default stdout
args: ['@code-pushup/cli', 'collect', '--verbose'],
cwd: envDir,
});

expect(code).toBe(0);
expect(stdout).toContain('JS Benchmark audits');

const report = await readJsonFile(
path.join(envDir, '.code-pushup', 'report.json'),
);
expect(() => reportSchema.parse(report)).not.toThrowError();
expect(
omitVariableReportData(report as Report, { omitAuditData: true }),
).toMatchSnapshot();
});
});
212 changes: 212 additions & 0 deletions e2e/plugin-js-benchmark-e2e/tests/suite-runners.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import { cp } from 'node:fs/promises';
import path from 'node:path';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { nxTargetProject } from '@code-pushup/test-nx-utils';
import {
E2E_ENVIRONMENTS_DIR,
TEST_OUTPUT_DIR,
restoreNxIgnoredFiles,
teardownTestFolder,
} from '@code-pushup/test-utils';

describe('suite-runners', () => {
const envDir = path.join(E2E_ENVIRONMENTS_DIR, nxTargetProject());
const testFileDir = path.join(envDir, TEST_OUTPUT_DIR, 'suite-runners');
const fixturesDir = path.join(
'e2e',
nxTargetProject(),
'mocks/fixtures/default-setup',
);

const cases = [
['fast-operation', () => 1 + 1],
[
'slow-operation',
() =>
Array.from({ length: 50_000 }, (_, i) =>
Math.sqrt(Math.log(i + 1) * Math.sin(i)),
).reduce((total, value) => total + value, 0),
],
];

beforeAll(async () => {
await cp(fixturesDir, testFileDir, { recursive: true });
await restoreNxIgnoredFiles(testFileDir);
});

afterAll(async () => {
await teardownTestFolder(testFileDir);
});

it('should be able to import and use tinybench suite runner', async () => {
const { tinybenchRunner, benchToBenchmarkResult } = await import(
path.resolve(
envDir,
'node_modules/@code-pushup/js-benchmark-plugin/src/plugins/tinybench.suite-runner.js',
)
);

expect(tinybenchRunner).toBeDefined();
expect(typeof tinybenchRunner.run).toBe('function');
expect(benchToBenchmarkResult).toBeDefined();
expect(typeof benchToBenchmarkResult).toBe('function');
});

it('should run tinybench suite with simple test cases', async () => {
const { tinybenchRunner } = await import(
path.resolve(
envDir,
'node_modules/@code-pushup/js-benchmark-plugin/src/plugins/tinybench.suite-runner.js',
)
);

const suiteConfig = {
suiteName: 'tinybench-simple-test',
targetImplementation: 'fast-operation',
cases,
time: 1000,
};

await expect(
tinybenchRunner.run(suiteConfig, {
outputDir: testFileDir,
outputFileName: 'tinybench-simple-test',
}),
).resolves.toStrictEqual(
expect.arrayContaining([
expect.objectContaining({
suiteName: 'tinybench-simple-test',
name: 'fast-operation',
hz: expect.any(Number),
rme: expect.any(Number),
samples: expect.any(Number),
isTarget: true,
isFastest: true,
}),
expect.objectContaining({
suiteName: 'tinybench-simple-test',
name: 'slow-operation',
hz: expect.any(Number),
rme: expect.any(Number),
samples: expect.any(Number),
isTarget: false,
isFastest: false,
}),
]),
);
});

it('should be able to import and use benchmark suite runner', async () => {
const { benchmarkRunner, benchToBenchmarkResult } = await import(
path.resolve(
envDir,
'node_modules/@code-pushup/js-benchmark-plugin/src/plugins/benchmark.suite-runner.js',
)
);

expect(benchmarkRunner).toBeDefined();
expect(typeof benchmarkRunner.run).toBe('function');
expect(benchToBenchmarkResult).toBeDefined();
expect(typeof benchToBenchmarkResult).toBe('function');
});

it('should run benchmark suite with simple test cases', async () => {
const { benchmarkRunner } = await import(
path.resolve(
envDir,
'node_modules/@code-pushup/js-benchmark-plugin/src/plugins/benchmark.suite-runner.js',
)
);

const suiteConfig = {
suiteName: 'benchmark-simple-test',
targetImplementation: 'fast-operation',
cases,
};

await expect(
benchmarkRunner.run(suiteConfig, {
outputDir: testFileDir,
outputFileName: 'benchmark-simple-test',
}),
).resolves.toStrictEqual(
expect.arrayContaining([
expect.objectContaining({
suiteName: 'benchmark-simple-test',
name: 'fast-operation',
hz: expect.any(Number),
rme: expect.any(Number),
samples: expect.any(Number),
isTarget: true,
isFastest: true,
}),
expect.objectContaining({
suiteName: 'benchmark-simple-test',
name: 'slow-operation',
hz: expect.any(Number),
rme: expect.any(Number),
samples: expect.any(Number),
isTarget: false,
isFastest: false,
}),
]),
);
});

it('should be able to import and use benny suite runner', async () => {
const { bennyRunner, benchToBenchmarkResult } = await import(
path.resolve(
envDir,
'node_modules/@code-pushup/js-benchmark-plugin/src/plugins/benny.suite-runner.js',
)
);

expect(bennyRunner).toBeDefined();
expect(typeof bennyRunner.run).toBe('function');
expect(benchToBenchmarkResult).toBeDefined();
expect(typeof benchToBenchmarkResult).toBe('function');
});

it('should run benny suite with simple test cases', async () => {
const { bennyRunner } = await import(
path.resolve(
envDir,
'node_modules/@code-pushup/js-benchmark-plugin/src/plugins/benny.suite-runner.js',
)
);

const suiteConfig = {
suiteName: 'benny-simple-test',
targetImplementation: 'fast-operation',
cases,
};

await expect(
bennyRunner.run(suiteConfig, {
outputDir: testFileDir,
outputFileName: 'benny-simple-test',
}),
).resolves.toStrictEqual(
expect.arrayContaining([
expect.objectContaining({
suiteName: 'benny-simple-test',
name: 'fast-operation',
hz: expect.any(Number),
rme: expect.any(Number),
samples: expect.any(Number),
isTarget: true,
isFastest: true,
}),
expect.objectContaining({
suiteName: 'benny-simple-test',
name: 'slow-operation',
hz: expect.any(Number),
rme: expect.any(Number),
samples: expect.any(Number),
isTarget: false,
isFastest: false,
}),
]),
);
});
});
20 changes: 20 additions & 0 deletions e2e/plugin-js-benchmark-e2e/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"types": ["vitest"]
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.test.json"
}
]
}
15 changes: 15 additions & 0 deletions e2e/plugin-js-benchmark-e2e/tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"],
"target": "ES2020"
},
"include": [
"vitest.e2e.config.ts",
"tests/**/*.e2e.test.ts",
"tests/**/*.d.ts",
"mocks/**/*.ts",
"../../testing/test-setup/src/vitest.d.ts"
]
}
5 changes: 5 additions & 0 deletions e2e/plugin-js-benchmark-e2e/vitest.e2e.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createE2ETestConfig } from '../../testing/test-setup-config/src/index.js';

export default createE2ETestConfig('plugin-js-benchmark-e2e', {
testTimeout: 80_000,
});
Loading
Loading