Skip to content

Commit 0d6feb2

Browse files
authored
docs(examples-plugins): add example plugin file-size (#315)
1 parent 3079d2e commit 0d6feb2

20 files changed

+881
-3
lines changed

code-pushup.config.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ import nx from '@nx/devkit';
22
import 'dotenv/config';
33
import type { ESLint } from 'eslint';
44
import { stat } from 'node:fs/promises';
5+
import { join } from 'path';
56
import { z } from 'zod';
67
import eslintPlugin from './dist/packages/plugin-eslint';
8+
import {
9+
fileSizePlugin,
10+
fileSizeRecommendedRefs,
11+
} from './examples/plugins/src';
712
import type { CoreConfig } from './packages/models/src';
813

914
const exists = (path: string) =>
@@ -58,7 +63,14 @@ const config: CoreConfig = {
5863
project: env.CP_PROJECT,
5964
},
6065

61-
plugins: [await eslintPlugin({ eslintrc: eslintConfig, patterns })],
66+
plugins: [
67+
await eslintPlugin({ eslintrc: eslintConfig, patterns }),
68+
await fileSizePlugin({
69+
directory: './dist/packages',
70+
pattern: /\.js$/,
71+
budget: 42000,
72+
}),
73+
],
6274

6375
categories: [
6476
{
@@ -73,6 +85,11 @@ const config: CoreConfig = {
7385
{ type: 'group', plugin: 'eslint', slug: 'suggestions', weight: 1 },
7486
],
7587
},
88+
{
89+
slug: 'performance',
90+
title: 'Performance',
91+
refs: [...fileSizeRecommendedRefs],
92+
},
7693
],
7794
};
7895

examples/plugins/.eslintrc.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {
8+
"@nx/enforce-module-boundaries": ["off"]
9+
}
10+
},
11+
{
12+
"files": ["*.ts", "*.tsx"],
13+
"parserOptions": {
14+
"project": ["examples/plugins/tsconfig.*?.json"]
15+
},
16+
"rules": {}
17+
},
18+
{
19+
"files": ["*.test.ts", "*.test.tsx"],
20+
"parserOptions": {
21+
"project": ["examples/plugins/tsconfig.*?.json"]
22+
},
23+
"rules": {
24+
"max-lines": "off"
25+
}
26+
},
27+
{
28+
"files": ["*.js", "*.jsx"],
29+
"rules": {}
30+
},
31+
{
32+
"files": ["*.json"],
33+
"parser": "jsonc-eslint-parser",
34+
"rules": {
35+
"@nx/dependency-checks": ["error"]
36+
}
37+
}
38+
]
39+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {
2+
create as fileSizePlugin,
3+
recommendedRefs as fileSizeRecommendedRefs,
4+
} from './src/file-size/file-size.plugin';
5+
6+
/**
7+
* Run it with:
8+
* `nx run-collect examples-plugins`
9+
*
10+
* - For all formats use `--persist.format=md,json`
11+
* - For better debugging use `--verbose --no-progress`
12+
*
13+
*/
14+
15+
const outputDir = '.code-pushup';
16+
// eslint-disable-next-line unicorn/no-unreadable-iife
17+
const config = (() => ({
18+
persist: {
19+
outputDir,
20+
},
21+
plugins: [
22+
fileSizePlugin({
23+
directory: './dist',
24+
pattern: /\.js$/,
25+
// eslint-disable-next-line no-magic-numbers
26+
budget: 42_000,
27+
}),
28+
],
29+
categories: [
30+
{
31+
slug: 'performance',
32+
title: 'Performance',
33+
refs: [...fileSizeRecommendedRefs],
34+
},
35+
],
36+
}))();
37+
38+
export default config;

examples/plugins/project.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "examples-plugins",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "examples/plugins/src",
5+
"projectType": "library",
6+
"implicitDependencies": ["cli"],
7+
"targets": {
8+
"lint": {
9+
"executor": "@nx/linter:eslint",
10+
"outputs": ["{options.outputFile}"],
11+
"options": {
12+
"lintFilePatterns": ["examples/plugins/**/*.ts"]
13+
},
14+
"dependsOn": ["^build"]
15+
},
16+
"unit-test": {
17+
"executor": "@nx/vite:test",
18+
"outputs": ["{options.reportsDirectory}"],
19+
"options": {
20+
"config": "examples/plugins/vite.config.unit.ts",
21+
"reportsDirectory": "../../coverage/examples-plugins/unit-tests"
22+
},
23+
"dependsOn": ["^build"]
24+
},
25+
"integration-test": {
26+
"executor": "@nx/vite:test",
27+
"outputs": ["{options.reportsDirectory}"],
28+
"options": {
29+
"config": "examples/plugins/vite.config.integration.ts",
30+
"reportsDirectory": "../../coverage/examples-plugins/integration-tests"
31+
},
32+
"dependsOn": ["^build"]
33+
},
34+
"run-collect": {
35+
"command": "npx dist/packages/cli collect --config=examples/plugins/code-pushup.config.ts --persist.format=md",
36+
"dependsOn": ["^build"]
37+
}
38+
},
39+
"tags": []
40+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { vol } from 'memfs';
2+
import { beforeEach, describe, expect, it } from 'vitest';
3+
import { executePlugin } from '@code-pushup/core';
4+
import {
5+
auditSchema,
6+
categoryRefSchema,
7+
pluginConfigSchema,
8+
} from '@code-pushup/models';
9+
import { MEMFS_VOLUME } from '@code-pushup/testing-utils';
10+
import {
11+
PluginOptions,
12+
audits,
13+
create,
14+
recommendedRefs,
15+
pluginSlug as slug,
16+
} from './file-size.plugin';
17+
18+
const projectJson = JSON.stringify(
19+
{
20+
test: 42,
21+
arr: [1, 2, 3],
22+
obj: {
23+
test: 42,
24+
},
25+
},
26+
null,
27+
2,
28+
);
29+
const testJs = `
30+
const str = 'Hello World'
31+
const num = 42;
32+
const obj = ${projectJson};
33+
`;
34+
35+
describe('create', () => {
36+
const baseOptions: PluginOptions = {
37+
directory: '/',
38+
};
39+
40+
beforeEach(() => {
41+
vol.fromJSON(
42+
{
43+
'project.json': projectJson,
44+
'src/test.js': testJs,
45+
},
46+
MEMFS_VOLUME,
47+
);
48+
});
49+
50+
it('should return valid PluginConfig', () => {
51+
const pluginConfig = create(baseOptions);
52+
expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow();
53+
expect(pluginConfig).toEqual({
54+
audits,
55+
description:
56+
'A plugin to measure and assert filesize of files in a directory.',
57+
icon: 'javascript',
58+
runner: expect.any(Function),
59+
slug,
60+
title: 'File Size',
61+
});
62+
});
63+
64+
it('should return PluginConfig that executes correctly', async () => {
65+
const pluginConfig = create(baseOptions);
66+
await expect(executePlugin(pluginConfig)).resolves.toMatchObject({
67+
description:
68+
'A plugin to measure and assert filesize of files in a directory.',
69+
slug,
70+
title: 'File Size',
71+
duration: expect.any(Number),
72+
date: expect.any(String),
73+
audits: expect.any(Array),
74+
});
75+
});
76+
77+
it('should use pattern', async () => {
78+
const pluginConfig = create({
79+
...baseOptions,
80+
pattern: /\.js$/,
81+
});
82+
const { audits: auditOutputs } = await executePlugin(pluginConfig);
83+
84+
expect(auditOutputs).toHaveLength(1);
85+
expect(auditOutputs[0]?.score).toBe(1);
86+
expect(auditOutputs[0]?.details?.issues).toHaveLength(1);
87+
});
88+
89+
it('should use budget', async () => {
90+
const pluginConfig = create({
91+
...baseOptions,
92+
budget: 0,
93+
});
94+
const { audits: auditOutputs } = await executePlugin(pluginConfig);
95+
96+
expect(auditOutputs).toHaveLength(1);
97+
expect(auditOutputs[0]?.score).toBe(0);
98+
expect(auditOutputs[0]?.details?.issues).toHaveLength(2);
99+
});
100+
});
101+
102+
describe('audits', () => {
103+
it.each(audits)('should be a valid audit meta info', audit => {
104+
expect(() => auditSchema.parse(audit)).not.toThrow();
105+
});
106+
});
107+
108+
describe('recommendedRefs', () => {
109+
it.each(recommendedRefs)(
110+
'should be a valid category reference',
111+
categoryRef => {
112+
expect(() => categoryRefSchema.parse(categoryRef)).not.toThrow();
113+
},
114+
);
115+
});

0 commit comments

Comments
 (0)