Skip to content

Commit

Permalink
refactor(cli): merge skip and only plugin filters
Browse files Browse the repository at this point in the history
  • Loading branch information
hanna-skryl committed Sep 25, 2024
1 parent f6f82ed commit df5c5ac
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 291 deletions.
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';
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),
)
: categories;

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

0 comments on commit df5c5ac

Please sign in to comment.