Skip to content

Commit df5c5ac

Browse files
committed
refactor(cli): merge skip and only plugin filters
1 parent f6f82ed commit df5c5ac

7 files changed

+255
-291
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { filterItemRefsBy } from '@code-pushup/utils';
2+
import type { OnlyPluginsOptions } from './only-plugins.model';
3+
import type { SkipPluginsOptions } from './skip-plugins.model';
4+
import { validatePluginFilterOption } from './validate-plugin-filter-options.utils';
5+
6+
export function filterPluginsMiddleware<
7+
T extends SkipPluginsOptions & OnlyPluginsOptions,
8+
>(originalProcessArgs: T): T {
9+
const {
10+
plugins,
11+
categories = [],
12+
skipPlugins = [],
13+
onlyPlugins = [],
14+
verbose,
15+
} = originalProcessArgs;
16+
17+
if (skipPlugins.length === 0 && onlyPlugins.length === 0) {
18+
return { ...originalProcessArgs, categories };
19+
}
20+
21+
validatePluginFilterOption(
22+
'skipPlugins',
23+
{ plugins, categories },
24+
{ pluginsToFilter: skipPlugins, verbose },
25+
);
26+
validatePluginFilterOption(
27+
'onlyPlugins',
28+
{ plugins, categories },
29+
{ pluginsToFilter: onlyPlugins, verbose },
30+
);
31+
32+
const validSkipPlugins = new Set(
33+
skipPlugins.filter(sP => plugins.some(p => p.slug === sP)),
34+
);
35+
const pluginsAfterSkip = plugins.filter(
36+
({ slug }) => !validSkipPlugins.has(slug),
37+
);
38+
39+
const validOnlyPlugins = new Set(
40+
onlyPlugins.filter(oP => pluginsAfterSkip.some(p => p.slug === oP)),
41+
);
42+
const filteredPlugins =
43+
validOnlyPlugins.size > 0
44+
? pluginsAfterSkip.filter(({ slug }) => validOnlyPlugins.has(slug))
45+
: pluginsAfterSkip;
46+
47+
const filteredCategories =
48+
filteredPlugins.length > 0
49+
? filterItemRefsBy(categories, ({ plugin }) =>
50+
filteredPlugins.some(({ slug }) => slug === plugin),
51+
)
52+
: categories;
53+
54+
return {
55+
...originalProcessArgs,
56+
plugins: filteredPlugins,
57+
categories: filteredCategories,
58+
};
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
import { describe, expect, vi } from 'vitest';
2+
import type { CategoryConfig, PluginConfig } from '@code-pushup/models';
3+
import { ui } from '@code-pushup/utils';
4+
import { filterPluginsMiddleware } from './filter-plugins.middleware';
5+
6+
vi.mock('@code-pushup/core', async () => {
7+
const { CORE_CONFIG_MOCK }: typeof import('@code-pushup/test-utils') =
8+
await vi.importActual('@code-pushup/test-utils');
9+
const core: object = await vi.importActual('@code-pushup/core');
10+
return {
11+
...core,
12+
readRcByPath: vi.fn().mockResolvedValue(CORE_CONFIG_MOCK),
13+
autoloadRc: vi.fn().mockResolvedValue(CORE_CONFIG_MOCK),
14+
};
15+
});
16+
17+
describe('filterPluginsMiddleware', () => {
18+
it('should fill undefined categories with empty array', () => {
19+
expect(
20+
filterPluginsMiddleware({
21+
plugins: [{ slug: 'p1' } as PluginConfig],
22+
}),
23+
).toStrictEqual({
24+
plugins: [{ slug: 'p1' }],
25+
categories: [],
26+
});
27+
});
28+
29+
it('should forward equal values when neither skipPlugins nor onlyPlugins is set', () => {
30+
expect(
31+
filterPluginsMiddleware({
32+
plugins: [{ slug: 'p1' } as PluginConfig],
33+
categories: [
34+
{ slug: 'c1', refs: [{ plugin: 'p1' }] } as CategoryConfig,
35+
],
36+
}),
37+
).toStrictEqual({
38+
plugins: [{ slug: 'p1' }],
39+
categories: [{ slug: 'c1', refs: [{ plugin: 'p1' }] }],
40+
});
41+
});
42+
43+
it('should return original values when neither skipPlugins nor onlyPlugins is provided', () => {
44+
const originalPlugins = [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[];
45+
const originalCategories = [
46+
{
47+
slug: 'c1',
48+
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
49+
},
50+
] as CategoryConfig[];
51+
52+
const { plugins, categories } = filterPluginsMiddleware({
53+
plugins: originalPlugins,
54+
categories: originalCategories,
55+
});
56+
57+
expect(plugins).toStrictEqual(originalPlugins);
58+
expect(categories).toStrictEqual(originalCategories);
59+
});
60+
61+
it('should return original values when skipPlugins and onlyPlugins are empty', () => {
62+
const originalPlugins = [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[];
63+
const originalCategories = [
64+
{
65+
slug: 'c1',
66+
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
67+
},
68+
] as CategoryConfig[];
69+
70+
const { plugins, categories } = filterPluginsMiddleware({
71+
plugins: originalPlugins,
72+
categories: originalCategories,
73+
skipPlugins: [],
74+
onlyPlugins: [],
75+
});
76+
77+
expect(plugins).toStrictEqual(originalPlugins);
78+
expect(categories).toStrictEqual(originalCategories);
79+
});
80+
81+
it('should filter plugins for slug "p1" in onlyPlugins', () => {
82+
const { plugins } = filterPluginsMiddleware({
83+
onlyPlugins: ['p1'],
84+
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
85+
categories: [],
86+
});
87+
expect(plugins).toStrictEqual([expect.objectContaining({ slug: 'p1' })]);
88+
});
89+
90+
it('should filter plugins for slug "p2" in skipPlugins', () => {
91+
const { plugins, categories } = filterPluginsMiddleware({
92+
skipPlugins: ['p2'],
93+
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
94+
categories: [
95+
{
96+
slug: 'c1',
97+
refs: [
98+
{ plugin: 'p1', slug: 'a1-p1' },
99+
{ plugin: 'p2', slug: 'a2-p1' },
100+
],
101+
},
102+
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
103+
] as CategoryConfig[],
104+
});
105+
106+
expect(plugins).toStrictEqual([expect.objectContaining({ slug: 'p1' })]);
107+
expect(categories).toStrictEqual([
108+
expect.objectContaining({
109+
slug: 'c1',
110+
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
111+
}),
112+
]);
113+
});
114+
115+
it('should forward plugins and categories for a slug not present in plugins', () => {
116+
const originalCategories = [
117+
{
118+
slug: 'c1',
119+
refs: [
120+
{ plugin: 'p1', slug: 'a1-p1' },
121+
{ plugin: 'p2', slug: 'a2-p1' },
122+
],
123+
},
124+
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
125+
] as CategoryConfig[];
126+
const originalPlugins = [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[];
127+
const { categories, plugins } = filterPluginsMiddleware({
128+
onlyPlugins: ['wrong-slug'],
129+
plugins: originalPlugins,
130+
categories: originalCategories,
131+
});
132+
expect(categories).toStrictEqual(originalCategories);
133+
expect(plugins).toStrictEqual(originalPlugins);
134+
});
135+
136+
it('should filter categories for slug "p1" in onlyPlugins', () => {
137+
const { categories } = filterPluginsMiddleware({
138+
onlyPlugins: ['p1'],
139+
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
140+
categories: [
141+
{
142+
slug: 'c1',
143+
refs: [
144+
{ plugin: 'p1', slug: 'a1-p1' },
145+
{ plugin: 'p2', slug: 'a2-p1' },
146+
],
147+
},
148+
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
149+
] as CategoryConfig[],
150+
});
151+
expect(categories).toStrictEqual([
152+
expect.objectContaining({
153+
slug: 'c1',
154+
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
155+
}),
156+
]);
157+
});
158+
159+
it('should filter plugins when both skipPlugins and onlyPlugins are provided', () => {
160+
const { plugins } = filterPluginsMiddleware({
161+
onlyPlugins: ['p1'],
162+
skipPlugins: ['p2'],
163+
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
164+
categories: [],
165+
});
166+
expect(plugins).toStrictEqual([expect.objectContaining({ slug: 'p1' })]);
167+
});
168+
169+
it('should trigger verbose logging when skipPlugins or onlyPlugins removes categories', () => {
170+
const loggerSpy = vi.spyOn(ui().logger, 'info');
171+
172+
filterPluginsMiddleware({
173+
onlyPlugins: ['p1'],
174+
skipPlugins: ['p2'],
175+
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
176+
categories: [
177+
{
178+
slug: 'c1',
179+
refs: [
180+
{ plugin: 'p1', slug: 'a1-p1' },
181+
{ plugin: 'p2', slug: 'a2-p1' },
182+
],
183+
},
184+
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
185+
] as CategoryConfig[],
186+
verbose: true,
187+
});
188+
189+
expect(loggerSpy).toHaveBeenCalledWith(
190+
expect.stringContaining('removed the following categories'),
191+
);
192+
});
193+
});

packages/cli/src/lib/implementation/only-plugins.middleware.ts

-45
This file was deleted.

packages/cli/src/lib/implementation/only-plugins.middleware.unit.test.ts

-94
This file was deleted.

0 commit comments

Comments
 (0)