Skip to content

Commit 6a74c2d

Browse files
authored
fix: handle skipped audits and groups (#911)
1 parent 4777a83 commit 6a74c2d

15 files changed

+1148
-306
lines changed
Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,72 @@
1-
import type { CoreConfig } from '@code-pushup/models';
1+
import type {
2+
CategoryConfig,
3+
CoreConfig,
4+
PluginConfig,
5+
} from '@code-pushup/models';
26
import { filterItemRefsBy } from '@code-pushup/utils';
7+
import {
8+
applyFilters,
9+
extractSkippedItems,
10+
filterPluginsFromCategories,
11+
filterSkippedItems,
12+
isValidCategoryRef,
13+
} from './filter.middleware.utils.js';
314
import type { FilterOptions, Filterables } from './filter.model.js';
415
import {
516
handleConflictingOptions,
617
validateFilterOption,
718
validateFinalState,
19+
validateSkippedCategories,
820
} from './validate-filter-options.utils.js';
921

22+
// eslint-disable-next-line max-lines-per-function
1023
export function filterMiddleware<T extends FilterOptions>(
1124
originalProcessArgs: T,
1225
): T {
1326
const {
14-
plugins,
15-
categories,
27+
categories: rcCategories,
28+
plugins: rcPlugins,
1629
skipCategories = [],
1730
onlyCategories = [],
1831
skipPlugins = [],
1932
onlyPlugins = [],
2033
verbose = false,
2134
} = originalProcessArgs;
2235

36+
const plugins = filterSkippedInPlugins(rcPlugins);
37+
const categories = filterSkippedCategories(rcCategories, plugins);
38+
2339
if (
2440
skipCategories.length === 0 &&
2541
onlyCategories.length === 0 &&
2642
skipPlugins.length === 0 &&
2743
onlyPlugins.length === 0
2844
) {
29-
return originalProcessArgs;
45+
if (rcCategories && categories) {
46+
validateSkippedCategories(rcCategories, categories, verbose);
47+
}
48+
return {
49+
...originalProcessArgs,
50+
...(categories && { categories }),
51+
plugins,
52+
};
3053
}
3154

3255
handleConflictingOptions('categories', onlyCategories, skipCategories);
3356
handleConflictingOptions('plugins', onlyPlugins, skipPlugins);
3457

58+
const skippedPlugins = extractSkippedItems(rcPlugins, plugins);
59+
const skippedCategories = extractSkippedItems(rcCategories, categories);
60+
3561
const filteredCategories = applyCategoryFilters(
3662
{ categories, plugins },
37-
skipCategories,
38-
onlyCategories,
39-
verbose,
63+
skippedCategories,
64+
{ skipCategories, onlyCategories, verbose },
4065
);
4166
const filteredPlugins = applyPluginFilters(
4267
{ categories: filteredCategories, plugins },
43-
skipPlugins,
44-
onlyPlugins,
45-
verbose,
68+
skippedPlugins,
69+
{ skipPlugins, onlyPlugins, verbose },
4670
);
4771
const finalCategories = filteredCategories
4872
? filterItemRefsBy(filteredCategories, ref =>
@@ -52,7 +76,7 @@ export function filterMiddleware<T extends FilterOptions>(
5276

5377
validateFinalState(
5478
{ categories: finalCategories, plugins: filteredPlugins },
55-
{ categories, plugins },
79+
{ categories: rcCategories, plugins: rcPlugins },
5680
);
5781

5882
return {
@@ -62,53 +86,37 @@ export function filterMiddleware<T extends FilterOptions>(
6286
};
6387
}
6488

65-
function applyFilters<T>(
66-
items: T[],
67-
skipItems: string[],
68-
onlyItems: string[],
69-
key: keyof T,
70-
): T[] {
71-
return items.filter(item => {
72-
const itemKey = item[key] as unknown as string;
73-
return (
74-
!skipItems.includes(itemKey) &&
75-
(onlyItems.length === 0 || onlyItems.includes(itemKey))
76-
);
77-
});
78-
}
79-
8089
function applyCategoryFilters(
8190
{ categories, plugins }: Filterables,
82-
skipCategories: string[],
83-
onlyCategories: string[],
84-
verbose: boolean,
91+
skippedCategories: string[],
92+
options: Pick<FilterOptions, 'skipCategories' | 'onlyCategories' | 'verbose'>,
8593
): CoreConfig['categories'] {
94+
const { skipCategories = [], onlyCategories = [], verbose = false } = options;
8695
if (
8796
(skipCategories.length === 0 && onlyCategories.length === 0) ||
88-
!categories ||
89-
categories.length === 0
97+
((!categories || categories.length === 0) && skippedCategories.length === 0)
9098
) {
9199
return categories;
92100
}
93101
validateFilterOption(
94102
'skipCategories',
95103
{ plugins, categories },
96-
{ itemsToFilter: skipCategories, verbose },
104+
{ itemsToFilter: skipCategories, skippedItems: skippedCategories, verbose },
97105
);
98106
validateFilterOption(
99107
'onlyCategories',
100108
{ plugins, categories },
101-
{ itemsToFilter: onlyCategories, verbose },
109+
{ itemsToFilter: onlyCategories, skippedItems: skippedCategories, verbose },
102110
);
103-
return applyFilters(categories, skipCategories, onlyCategories, 'slug');
111+
return applyFilters(categories ?? [], skipCategories, onlyCategories, 'slug');
104112
}
105113

106114
function applyPluginFilters(
107115
{ categories, plugins }: Filterables,
108-
skipPlugins: string[],
109-
onlyPlugins: string[],
110-
verbose: boolean,
116+
skippedPlugins: string[],
117+
options: Pick<FilterOptions, 'skipPlugins' | 'onlyPlugins' | 'verbose'>,
111118
): CoreConfig['plugins'] {
119+
const { skipPlugins = [], onlyPlugins = [], verbose = false } = options;
112120
const filteredPlugins = filterPluginsFromCategories({
113121
categories,
114122
plugins,
@@ -119,25 +127,43 @@ function applyPluginFilters(
119127
validateFilterOption(
120128
'skipPlugins',
121129
{ plugins: filteredPlugins, categories },
122-
{ itemsToFilter: skipPlugins, verbose },
130+
{ itemsToFilter: skipPlugins, skippedItems: skippedPlugins, verbose },
123131
);
124132
validateFilterOption(
125133
'onlyPlugins',
126134
{ plugins: filteredPlugins, categories },
127-
{ itemsToFilter: onlyPlugins, verbose },
135+
{ itemsToFilter: onlyPlugins, skippedItems: skippedPlugins, verbose },
128136
);
129137
return applyFilters(filteredPlugins, skipPlugins, onlyPlugins, 'slug');
130138
}
131139

132-
function filterPluginsFromCategories({
133-
categories,
134-
plugins,
135-
}: Filterables): CoreConfig['plugins'] {
136-
if (!categories || categories.length === 0) {
137-
return plugins;
138-
}
139-
const validPluginSlugs = new Set(
140-
categories.flatMap(category => category.refs.map(ref => ref.plugin)),
141-
);
142-
return plugins.filter(plugin => validPluginSlugs.has(plugin.slug));
140+
export function filterSkippedInPlugins(
141+
plugins: PluginConfig[],
142+
): PluginConfig[] {
143+
return plugins.map((plugin: PluginConfig) => {
144+
const filteredAudits = filterSkippedItems(plugin.audits);
145+
return {
146+
...plugin,
147+
...(plugin.groups && {
148+
groups: filterItemRefsBy(filterSkippedItems(plugin.groups), ref =>
149+
filteredAudits.some(({ slug }) => slug === ref.slug),
150+
),
151+
}),
152+
audits: filteredAudits,
153+
};
154+
});
155+
}
156+
157+
export function filterSkippedCategories(
158+
categories: CoreConfig['categories'],
159+
plugins: CoreConfig['plugins'],
160+
): CoreConfig['categories'] {
161+
return categories
162+
?.map(category => {
163+
const validRefs = category.refs.filter(ref =>
164+
isValidCategoryRef(ref, plugins),
165+
);
166+
return validRefs.length > 0 ? { ...category, refs: validRefs } : null;
167+
})
168+
.filter((category): category is CategoryConfig => category != null);
143169
}

0 commit comments

Comments
 (0)