Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(cli): merge skip and only plugin filters #822

Merged
merged 2 commits into from
Sep 25, 2024
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
59 changes: 59 additions & 0 deletions packages/cli/src/lib/implementation/filter-plugins.middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { filterItemRefsBy } from '@code-pushup/utils';

Check failure on line 1 in packages/cli/src/lib/implementation/filter-plugins.middleware.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<✓> Code coverage | Branch coverage

1st branch is not taken in any test case.
import type { OnlyPluginsOptions } from './only-plugins.model';
import type { SkipPluginsOptions } from './skip-plugins.model';
import { validatePluginFilterOption } from './validate-plugin-filter-options.utils';

export function filterPluginsMiddleware<
T extends SkipPluginsOptions & OnlyPluginsOptions,
>(originalProcessArgs: T): T {
const {
plugins,
categories = [],
skipPlugins = [],
onlyPlugins = [],
verbose,
} = originalProcessArgs;

if (skipPlugins.length === 0 && onlyPlugins.length === 0) {
return { ...originalProcessArgs, categories };
}

validatePluginFilterOption(
'skipPlugins',
{ plugins, categories },
{ pluginsToFilter: skipPlugins, verbose },
);
validatePluginFilterOption(
'onlyPlugins',
{ plugins, categories },
{ pluginsToFilter: onlyPlugins, verbose },
);

const validSkipPlugins = new Set(
skipPlugins.filter(sP => plugins.some(p => p.slug === sP)),
);
const pluginsAfterSkip = plugins.filter(
({ slug }) => !validSkipPlugins.has(slug),
);

const validOnlyPlugins = new Set(
onlyPlugins.filter(oP => pluginsAfterSkip.some(p => p.slug === oP)),
);
const filteredPlugins =
validOnlyPlugins.size > 0
? pluginsAfterSkip.filter(({ slug }) => validOnlyPlugins.has(slug))
: pluginsAfterSkip;

const filteredCategories =
filteredPlugins.length > 0
? filterItemRefsBy(categories, ({ plugin }) =>
filteredPlugins.some(({ slug }) => slug === plugin),
)

Check failure on line 51 in packages/cli/src/lib/implementation/filter-plugins.middleware.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<✓> Code coverage | Branch coverage

1st branch is not taken in any test case.
: categories;

Check warning on line 52 in packages/cli/src/lib/implementation/filter-plugins.middleware.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<✓> Code coverage | Line coverage

Line 52 is not covered in any test case.

return {
...originalProcessArgs,
plugins: filteredPlugins,
categories: filteredCategories,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import { describe, expect, vi } from 'vitest';
import type { CategoryConfig, PluginConfig } from '@code-pushup/models';
import { ui } from '@code-pushup/utils';
import { filterPluginsMiddleware } from './filter-plugins.middleware';

vi.mock('@code-pushup/core', async () => {
const { CORE_CONFIG_MOCK }: typeof import('@code-pushup/test-utils') =
await vi.importActual('@code-pushup/test-utils');
const core: object = await vi.importActual('@code-pushup/core');
return {
...core,
readRcByPath: vi.fn().mockResolvedValue(CORE_CONFIG_MOCK),
autoloadRc: vi.fn().mockResolvedValue(CORE_CONFIG_MOCK),
};
});

describe('filterPluginsMiddleware', () => {
it('should fill undefined categories with empty array', () => {
expect(
filterPluginsMiddleware({
plugins: [{ slug: 'p1' } as PluginConfig],
}),
).toStrictEqual({
plugins: [{ slug: 'p1' }],
categories: [],
});
});

it('should forward equal values when neither skipPlugins nor onlyPlugins is set', () => {
expect(
filterPluginsMiddleware({
plugins: [{ slug: 'p1' } as PluginConfig],
categories: [
{ slug: 'c1', refs: [{ plugin: 'p1' }] } as CategoryConfig,
],
}),
).toStrictEqual({
plugins: [{ slug: 'p1' }],
categories: [{ slug: 'c1', refs: [{ plugin: 'p1' }] }],
});
});

it('should return original values when neither skipPlugins nor onlyPlugins is provided', () => {
const originalPlugins = [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[];
const originalCategories = [
{
slug: 'c1',
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
},
] as CategoryConfig[];

const { plugins, categories } = filterPluginsMiddleware({
plugins: originalPlugins,
categories: originalCategories,
});

expect(plugins).toStrictEqual(originalPlugins);
expect(categories).toStrictEqual(originalCategories);
});

it('should return original values when skipPlugins and onlyPlugins are empty', () => {
const originalPlugins = [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[];
const originalCategories = [
{
slug: 'c1',
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
},
] as CategoryConfig[];

const { plugins, categories } = filterPluginsMiddleware({
plugins: originalPlugins,
categories: originalCategories,
skipPlugins: [],
onlyPlugins: [],
});

expect(plugins).toStrictEqual(originalPlugins);
expect(categories).toStrictEqual(originalCategories);
});

it('should filter plugins for slug "p1" in onlyPlugins', () => {
const { plugins } = filterPluginsMiddleware({
onlyPlugins: ['p1'],
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
categories: [],
});
expect(plugins).toStrictEqual([expect.objectContaining({ slug: 'p1' })]);
});

it('should filter plugins for slug "p2" in skipPlugins', () => {
const { plugins, categories } = filterPluginsMiddleware({
skipPlugins: ['p2'],
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
categories: [
{
slug: 'c1',
refs: [
{ plugin: 'p1', slug: 'a1-p1' },
{ plugin: 'p2', slug: 'a2-p1' },
],
},
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
] as CategoryConfig[],
});

expect(plugins).toStrictEqual([expect.objectContaining({ slug: 'p1' })]);
expect(categories).toStrictEqual([
expect.objectContaining({
slug: 'c1',
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
}),
]);
});

it('should forward plugins and categories for a slug not present in plugins', () => {
const originalCategories = [
{
slug: 'c1',
refs: [
{ plugin: 'p1', slug: 'a1-p1' },
{ plugin: 'p2', slug: 'a2-p1' },
],
},
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
] as CategoryConfig[];
const originalPlugins = [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[];
const { categories, plugins } = filterPluginsMiddleware({
onlyPlugins: ['wrong-slug'],
plugins: originalPlugins,
categories: originalCategories,
});
expect(categories).toStrictEqual(originalCategories);
expect(plugins).toStrictEqual(originalPlugins);
});

it('should filter categories for slug "p1" in onlyPlugins', () => {
const { categories } = filterPluginsMiddleware({
onlyPlugins: ['p1'],
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
categories: [
{
slug: 'c1',
refs: [
{ plugin: 'p1', slug: 'a1-p1' },
{ plugin: 'p2', slug: 'a2-p1' },
],
},
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
] as CategoryConfig[],
});
expect(categories).toStrictEqual([
expect.objectContaining({
slug: 'c1',
refs: [{ plugin: 'p1', slug: 'a1-p1' }],
}),
]);
});

it('should filter plugins when both skipPlugins and onlyPlugins are provided', () => {
const { plugins } = filterPluginsMiddleware({
onlyPlugins: ['p1'],
skipPlugins: ['p2'],
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
categories: [],
});
expect(plugins).toStrictEqual([expect.objectContaining({ slug: 'p1' })]);
});

it('should trigger verbose logging when skipPlugins or onlyPlugins removes categories', () => {
const loggerSpy = vi.spyOn(ui().logger, 'info');

filterPluginsMiddleware({
onlyPlugins: ['p1'],
skipPlugins: ['p2'],
plugins: [{ slug: 'p1' }, { slug: 'p2' }] as PluginConfig[],
categories: [
{
slug: 'c1',
refs: [
{ plugin: 'p1', slug: 'a1-p1' },
{ plugin: 'p2', slug: 'a2-p1' },
],
},
{ slug: 'c2', refs: [{ plugin: 'p2', slug: 'a1-p2' }] },
] as CategoryConfig[],
verbose: true,
});

expect(loggerSpy).toHaveBeenCalledWith(
expect.stringContaining('removed the following categories'),
);
});
});
45 changes: 0 additions & 45 deletions packages/cli/src/lib/implementation/only-plugins.middleware.ts

This file was deleted.

This file was deleted.

Loading