diff --git a/examples/plugins/src/lighthouse/src/lighthouse.plugin.ts b/examples/plugins/src/lighthouse/src/lighthouse.plugin.ts index e523b342e..41086e273 100644 --- a/examples/plugins/src/lighthouse/src/lighthouse.plugin.ts +++ b/examples/plugins/src/lighthouse/src/lighthouse.plugin.ts @@ -8,8 +8,7 @@ import { } from '@code-pushup/models'; import { ensureDirectoryExists, - filterAuditsBySlug, - filterGroupsByAuditSlug, + filterItemRefsBy, toArray, } from '@code-pushup/utils'; import { @@ -74,8 +73,10 @@ export async function create(options: PluginOptions) { onlyCategories: ['performance'], headless, }), - audits: filterAuditsBySlug(audits, onlyAudits), - groups: filterGroupsByAuditSlug([categoryCorePerfGroup], onlyAudits), + audits: audits.filter(({ slug }) => onlyAudits.includes(slug)), + groups: filterItemRefsBy([categoryCorePerfGroup], ({ slug }) => + onlyAudits.includes(slug), + ), } satisfies PluginConfig; } diff --git a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.integration.test.ts b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.integration.test.ts index f9bc59f69..cfa8b32b3 100644 --- a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.integration.test.ts +++ b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.integration.test.ts @@ -1,36 +1,12 @@ import { expect } from 'vitest'; -import { - auditSchema, - groupSchema, - pluginConfigSchema, -} from '@code-pushup/models'; -import { AUDITS, GROUPS } from './constants'; +import { pluginConfigSchema } from '@code-pushup/models'; import { lighthousePlugin } from './lighthouse-plugin'; describe('lighthousePlugin', () => { it('should create valid plugin config', () => { - const pluginConfig = lighthousePlugin({ - url: 'https://code-pushup-portal.com', - }); + const pluginConfig = lighthousePlugin('https://code-pushup-portal.com'); expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); expect(pluginConfig.audits).toHaveLength(168); expect(pluginConfig.groups).toHaveLength(5); }); }); - -describe('generated-constants', () => { - it.each(AUDITS.map(a => [a.slug, a]))( - 'should parse audit "%s" correctly', - (_, audit) => { - expect(() => auditSchema.parse(audit)).not.toThrow(); - expect(audit.description).toEqual(expect.any(String)); - }, - ); - - it.each(GROUPS.map(a => [a.slug, a]))( - 'should parse group "%s" correctly', - (_, group) => { - expect(() => groupSchema.parse(group)).not.toThrow(); - }, - ); -}); diff --git a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts index 86fc3da1f..741f3ee73 100644 --- a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts +++ b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts @@ -1,40 +1,28 @@ -import { Audit, AuditOutputs, Group, PluginConfig } from '@code-pushup/models'; import { - filterAuditsBySlug, - filterGroupsByAuditSlug, -} from '@code-pushup/utils'; + type Config as LighthouseConfig, + type CliFlags as LighthouseFlags, +} from 'lighthouse'; +import { PluginConfig } from '@code-pushup/models'; import { AUDITS, GROUPS, LIGHTHOUSE_PLUGIN_SLUG } from './constants'; -import { validateOnlyAudits } from './utils'; - -export type LighthousePluginOptions = { - url: string; - outputPath?: string; - onlyAudits?: string | string[]; - verbose?: boolean; - headless?: boolean; - userDataDir?: string; -}; +import { filterAuditsAndGroupsByOnlyOptions } from './utils'; export function lighthousePlugin( - options: LighthousePluginOptions, + url: string, + flags?: Partial, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + config?: Partial, ): PluginConfig { - const { onlyAudits = [] } = options; - - validateOnlyAudits(AUDITS, onlyAudits); - const audits: Audit[] = filterAuditsBySlug(AUDITS, onlyAudits); - const groups: Group[] = filterGroupsByAuditSlug(GROUPS, onlyAudits); - + const { audits, groups } = filterAuditsAndGroupsByOnlyOptions( + AUDITS, + GROUPS, + flags, + ); return { slug: LIGHTHOUSE_PLUGIN_SLUG, title: 'Lighthouse', icon: 'lighthouse', audits, groups, - runner: (): AuditOutputs => - audits.map(audit => ({ - ...audit, - score: 0, - value: 0, - })), + runner: () => audits.map(({ slug }) => ({ slug, value: 0, score: 0 })), }; } diff --git a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.unit.test.ts b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.unit.test.ts index 8811f85e3..5e73302ec 100644 --- a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.unit.test.ts +++ b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.unit.test.ts @@ -9,18 +9,15 @@ import { lighthousePlugin } from './lighthouse-plugin'; describe('lighthousePlugin-config-object', () => { it('should create valid plugin config', () => { - const pluginConfig = lighthousePlugin({ - url: 'https://code-pushup-portal.com', - }); + const pluginConfig = lighthousePlugin('https://code-pushup-portal.com'); expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); expect(pluginConfig.audits.length).toBeGreaterThan(0); expect(pluginConfig.groups?.length).toBeGreaterThan(0); }); it('should filter audits by onlyAudits string "first-contentful-paint"', () => { - const pluginConfig = lighthousePlugin({ - url: 'https://code-pushup-portal.com', - onlyAudits: 'first-contentful-paint', + const pluginConfig = lighthousePlugin('https://code-pushup-portal.com', { + onlyAudits: ['first-contentful-paint'], }); expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); @@ -33,9 +30,8 @@ describe('lighthousePlugin-config-object', () => { }); it('should filter groups by onlyAudits string "first-contentful-paint"', () => { - const pluginConfig = lighthousePlugin({ - url: 'https://code-pushup-portal.com', - onlyAudits: 'first-contentful-paint', + const pluginConfig = lighthousePlugin('https://code-pushup-portal.com', { + onlyAudits: ['first-contentful-paint'], }); expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); diff --git a/packages/plugin-lighthouse/src/lib/utils.ts b/packages/plugin-lighthouse/src/lib/utils.ts index bab510ed2..48956ef6c 100644 --- a/packages/plugin-lighthouse/src/lib/utils.ts +++ b/packages/plugin-lighthouse/src/lib/utils.ts @@ -1,14 +1,14 @@ -import type { CliFlags } from 'lighthouse'; -import { Audit } from '@code-pushup/models'; -import { objectToCliArgs, toArray } from '@code-pushup/utils'; +import type { CliFlags as LighthouseFlags } from 'lighthouse'; +import { Audit, Group } from '@code-pushup/models'; +import { filterItemRefsBy, objectToCliArgs, toArray } from '@code-pushup/utils'; import { LIGHTHOUSE_REPORT_NAME } from './constants'; type RefinedLighthouseOption = { - url: CliFlags['_']; - chromeFlags?: Record; + url: LighthouseFlags['_']; + chromeFlags?: Record; }; export type LighthouseCliOptions = RefinedLighthouseOption & - Partial>; + Partial>; export function getLighthouseCliArguments( options: LighthouseCliOptions, @@ -59,7 +59,7 @@ export class AuditsNotImplementedError extends Error { export function validateOnlyAudits( audits: Audit[], onlyAudits: string | string[], -): audits is Audit[] { +): boolean { const missingAudtis = toArray(onlyAudits).filter( slug => !audits.some(audit => audit.slug === slug), ); @@ -68,3 +68,64 @@ export function validateOnlyAudits( } return true; } + +export class CategoriesNotImplementedError extends Error { + constructor(categorySlugs: string[]) { + super(`categories: "${categorySlugs.join(', ')}" not implemented`); + } +} + +export function validateOnlyCategories( + groups: Group[], + onlyCategories: string | string[], +): boolean { + const missingCategories = toArray(onlyCategories).filter(slug => + groups.every(group => group.slug !== slug), + ); + if (missingCategories.length > 0) { + throw new CategoriesNotImplementedError(missingCategories); + } + return true; +} + +export function filterAuditsAndGroupsByOnlyOptions( + audits: Audit[], + groups: Group[], + options?: Pick, +): { + audits: Audit[]; + groups: Group[]; +} { + const { onlyAudits, onlyCategories } = options ?? {}; + + // category wins over audits + if (onlyCategories && onlyCategories.length > 0) { + validateOnlyCategories(groups, onlyCategories); + + const categorieSlugs = new Set(onlyCategories); + const filteredGroups: Group[] = groups.filter(({ slug }) => + categorieSlugs.has(slug), + ); + const auditSlugsFromRemainingGroups = new Set( + filteredGroups.flatMap(({ refs }) => refs.map(({ slug }) => slug)), + ); + return { + audits: audits.filter(({ slug }) => + auditSlugsFromRemainingGroups.has(slug), + ), + groups: filteredGroups, + }; + } else if (onlyAudits && onlyAudits.length > 0) { + validateOnlyAudits(audits, onlyAudits); + const auditSlugs = new Set(onlyAudits); + return { + audits: audits.filter(({ slug }) => auditSlugs.has(slug)), + groups: filterItemRefsBy(groups, ({ slug }) => auditSlugs.has(slug)), + }; + } + // return unchanged + return { + audits, + groups, + }; +} diff --git a/packages/plugin-lighthouse/src/lib/utils.unit.test.ts b/packages/plugin-lighthouse/src/lib/utils.unit.test.ts index 8b9e65b92..3173a5ec9 100644 --- a/packages/plugin-lighthouse/src/lib/utils.unit.test.ts +++ b/packages/plugin-lighthouse/src/lib/utils.unit.test.ts @@ -1,8 +1,17 @@ import { expect } from 'vitest'; +import { + Audit, + Group, + PluginConfig, + pluginConfigSchema, +} from '@code-pushup/models'; import { AuditsNotImplementedError, + CategoriesNotImplementedError, + filterAuditsAndGroupsByOnlyOptions, getLighthouseCliArguments, validateOnlyAudits, + validateOnlyCategories, } from './utils'; describe('getLighthouseCliArguments', () => { @@ -49,8 +58,304 @@ describe('validateOnlyAudits', () => { { slug: 'b', title: 'B' }, { slug: 'c', title: 'C' }, ], - 'd', + 'missing-audit', + ), + ).toThrow(new AuditsNotImplementedError(['missing-audit'])); + }); +}); + +describe('validateOnlyCategories', () => { + it('should not throw for category slugs existing in given categories', () => { + expect( + validateOnlyCategories( + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + { + slug: 'coverage', + title: 'Code coverage', + refs: [{ slug: 'function-coverage', weight: 1 }], + }, + ], + 'coverage', + ), + ).toBeTruthy(); + }); + + it('should throw if given onlyCategories do not exist', () => { + expect(() => + validateOnlyCategories( + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ], + 'missing-category', + ), + ).toThrow(new CategoriesNotImplementedError(['missing-category'])); + }); +}); + +describe('filterAuditsAndGroupsByOnlyOptions to be used in plugin config', () => { + it('should return given audits and groups if no only filter is set', () => { + const audits: Audit[] = [{ slug: 'speed-index', title: 'Speed Index' }]; + const groups: Group[] = [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ]; + const { audits: filteredAudits, groups: filteredGroups } = + filterAuditsAndGroupsByOnlyOptions(audits, groups, {}); + + expect(filteredAudits).toStrictEqual(audits); + expect(filteredGroups).toStrictEqual(groups); + + const pluginConfig: PluginConfig = { + slug: 'coverage', + title: 'Code Coverage', + icon: 'file', + description: 'Runs test coverage and created audits', + audits: filteredAudits, + groups: filteredGroups, + runner: { + command: 'node', + outputFile: 'out.json', + }, + }; + + expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); + }); + + it('should filter audits if onlyAudits is set', () => { + const { audits: filteredAudits, groups: filteredGroups } = + filterAuditsAndGroupsByOnlyOptions( + [ + { slug: 'speed-index', title: 'Speed Index' }, + { slug: 'first-contentful-paint', title: 'First Contentful Paint' }, + ], + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ], + { onlyAudits: ['speed-index'] }, + ); + + expect(filteredAudits).toStrictEqual([ + { slug: 'speed-index', title: 'Speed Index' }, + ]); + expect(filteredGroups).toStrictEqual([ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ]); + + const pluginConfig: PluginConfig = { + slug: 'coverage', + title: 'Code Coverage', + icon: 'file', + description: 'Runs test coverage and created audits', + audits: filteredAudits, + groups: filteredGroups, + runner: { + command: 'node', + outputFile: 'out.json', + }, + }; + + expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); + }); + + it('should throw if onlyAudits is set with a missing audit slug', () => { + const { audits: filteredAudits, groups: filteredGroups } = + filterAuditsAndGroupsByOnlyOptions( + [ + { slug: 'speed-index', title: 'Speed Index' }, + { slug: 'first-contentful-paint', title: 'First Contentful Paint' }, + ], + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ], + { onlyAudits: ['speed-index'] }, + ); + expect(filteredAudits).toStrictEqual([ + { slug: 'speed-index', title: 'Speed Index' }, + ]); + expect(filteredGroups).toStrictEqual([ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ]); + + const pluginConfig: PluginConfig = { + slug: 'coverage', + title: 'Code Coverage', + icon: 'file', + description: 'Runs test coverage and created audits', + audits: filteredAudits, + groups: filteredGroups, + runner: { + command: 'node', + outputFile: 'out.json', + }, + }; + + expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); + }); + + it('should filter categories if onlyCategories is set', () => { + const { audits: filteredAudits, groups: filteredGroups } = + filterAuditsAndGroupsByOnlyOptions( + [ + { slug: 'speed-index', title: 'Speed Index' }, + { slug: 'first-contentful-paint', title: 'First Contentful Paint' }, + { slug: 'function-coverage', title: 'Function Coverage' }, + ], + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + { + slug: 'coverage', + title: 'Code coverage', + refs: [{ slug: 'function-coverage', weight: 1 }], + }, + ], + { onlyCategories: ['coverage'] }, + ); + + expect(filteredAudits).toStrictEqual([ + { slug: 'function-coverage', title: 'Function Coverage' }, + ]); + expect(filteredGroups).toStrictEqual([ + { + slug: 'coverage', + title: 'Code coverage', + refs: [{ slug: 'function-coverage', weight: 1 }], + }, + ]); + + const pluginConfig: PluginConfig = { + slug: 'coverage', + title: 'Code Coverage', + icon: 'file', + description: 'Runs test coverage and created audits', + audits: filteredAudits, + groups: filteredGroups, + runner: { + command: 'node', + outputFile: 'out.json', + }, + }; + + expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); + }); + + it('should ignore onlyAudits and only filter categories if onlyCategories and onlyAudits is set', () => { + const { audits: filteredAudits, groups: filteredGroups } = + filterAuditsAndGroupsByOnlyOptions( + [ + { slug: 'speed-index', title: 'Speed Index' }, + { slug: 'first-contentful-paint', title: 'First Contentful Paint' }, + { slug: 'function-coverage', title: 'Function Coverage' }, + ], + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + { + slug: 'coverage', + title: 'Code coverage', + refs: [{ slug: 'function-coverage', weight: 1 }], + }, + ], + { + onlyAudits: ['speed-index'], + onlyCategories: ['coverage'], + }, + ); + + expect(filteredAudits).toStrictEqual([ + { slug: 'function-coverage', title: 'Function Coverage' }, + ]); + expect(filteredGroups).toStrictEqual([ + { + slug: 'coverage', + title: 'Code coverage', + refs: [{ slug: 'function-coverage', weight: 1 }], + }, + ]); + + const pluginConfig: PluginConfig = { + slug: 'coverage', + title: 'Code Coverage', + icon: 'file', + description: 'Runs test coverage and created audits', + audits: filteredAudits, + groups: filteredGroups, + runner: { + command: 'node', + outputFile: 'out.json', + }, + }; + + expect(() => pluginConfigSchema.parse(pluginConfig)).not.toThrow(); + }); + + it('should throw if onlyAudits is set with a audit slug that is not implemented', () => { + expect(() => + filterAuditsAndGroupsByOnlyOptions( + [{ slug: 'speed-index', title: 'Speed Index' }], + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ], + { + onlyAudits: ['missing-audit'], + }, + ), + ).toThrow(new AuditsNotImplementedError(['missing-audit'])); + }); + + it('should throw if onlyCategories is set with a category slug that is not implemented', () => { + expect(() => + filterAuditsAndGroupsByOnlyOptions( + [{ slug: 'speed-index', title: 'Speed Index' }], + [ + { + slug: 'performance', + title: 'Performance', + refs: [{ slug: 'speed-index', weight: 1 }], + }, + ], + { + onlyCategories: ['missing-category'], + }, ), - ).toThrow(new AuditsNotImplementedError(['d'])); + ).toThrow(new CategoriesNotImplementedError(['missing-category'])); }); }); diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index c3561ea5d..1d2609aa9 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -22,10 +22,7 @@ export { readTextFile, removeDirectoryIfExists, } from './lib/file-system'; -export { - filterAuditsBySlug, - filterGroupsByAuditSlug, -} from './lib/filter-by-slug'; +export { filterItemRefsBy } from './lib/filter'; export { formatBytes, formatDuration, diff --git a/packages/utils/src/lib/filter-by-slug.ts b/packages/utils/src/lib/filter-by-slug.ts deleted file mode 100644 index d6b221728..000000000 --- a/packages/utils/src/lib/filter-by-slug.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Audit, Group } from '@code-pushup/models'; -import { toArray } from './transform'; - -export function filterGroupsByAuditSlug( - groups: Group[], - auditSlugs: string | string[], -): Group[] { - const slugs = toArray(auditSlugs); - if (slugs.length === 0) { - return groups; - } - return ( - groups - .map(group => ({ - ...group, - refs: filterSlug(group.refs, slugs), - })) - // filter out groups that have no audits includes from onlyAudits (avoid empty groups) - .filter(group => group.refs.length) - ); -} - -export function filterAuditsBySlug( - list: Audit[], - auditSlugs: string[] | string, -): Audit[] { - const slugs = toArray(auditSlugs); - if (slugs.length === 0) { - return list; - } - return filterSlug(list, slugs); -} - -export function filterSlug( - refs: T[], - slugOrSlugs: string | string[], -): T[] { - const slugs = toArray(slugOrSlugs); - return refs.filter(({ slug }) => slugs.includes(slug)); -} diff --git a/packages/utils/src/lib/filter-by-slug.unit.test.ts b/packages/utils/src/lib/filter-by-slug.unit.test.ts deleted file mode 100644 index baa056051..000000000 --- a/packages/utils/src/lib/filter-by-slug.unit.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { - filterAuditsBySlug, - filterGroupsByAuditSlug, - filterSlug, -} from './filter-by-slug'; - -describe('filterSlug', () => { - it('should return an empty list if no slugs are given', () => { - const list = [{ slug: 'a' }, { slug: 'b' }, { slug: 'c' }]; - expect(filterSlug(list, [])).toEqual([]); - }); - - it('should return an empty list if no slugs are matching', () => { - const list = [{ slug: 'a' }, { slug: 'b' }, { slug: 'c' }]; - // test bad case: - // 'aa'.includes('a') // fail - // ['aa'].includes('a') // passes - expect(filterSlug(list, 'aa')).toEqual([]); - }); - - it('should filter if slugs is a string', () => { - const list = [{ slug: 'a' }, { slug: 'b' }, { slug: 'c' }]; - expect(filterSlug(list, 'a')).toEqual([{ slug: 'a' }]); - }); - - it('should filter if slugs is an array', () => { - const list = [{ slug: 'a' }, { slug: 'b' }, { slug: 'c' }]; - expect(filterSlug(list, ['a'])).toEqual([{ slug: 'a' }]); - }); -}); - -describe('filterAuditsBySlug', () => { - it('should return the given list if no slugs are given', () => { - const list = [ - { slug: 'a', title: 'A' }, - { slug: 'b', title: 'B' }, - { slug: 'c', title: 'C' }, - ]; - expect(filterAuditsBySlug(list, [])).toEqual(list); - }); - - it('should filter if slugs is a string', () => { - const list = [ - { slug: 'a', title: 'A' }, - { slug: 'b', title: 'B' }, - { slug: 'c', title: 'C' }, - ]; - expect(filterAuditsBySlug(list, 'a')).toEqual([{ slug: 'a', title: 'A' }]); - }); -}); - -describe('filterGroupsByAuditSlug', () => { - it('should return the given list if no slugs are given', () => { - const list = [ - { - slug: 'g', - title: 'G', - refs: [ - { slug: 'a', weight: 1 }, - { slug: 'b', weight: 1 }, - { slug: 'c', weight: 1 }, - ], - }, - ]; - expect(filterGroupsByAuditSlug(list, [])).toEqual(list); - }); - - it('should filter if slugs is a string', () => { - const list = [ - { - slug: 'g', - title: 'G', - refs: [ - { slug: 'a', weight: 1 }, - { slug: 'b', weight: 1 }, - { slug: 'c', weight: 1 }, - ], - }, - ]; - expect(filterGroupsByAuditSlug(list, 'a')).toEqual([ - { - slug: 'g', - title: 'G', - refs: [{ slug: 'a', weight: 1 }], - }, - ]); - }); -}); diff --git a/packages/utils/src/lib/filter.ts b/packages/utils/src/lib/filter.ts new file mode 100644 index 000000000..1493b87a7 --- /dev/null +++ b/packages/utils/src/lib/filter.ts @@ -0,0 +1,14 @@ +export function filterItemRefsBy( + items: T[], + refFilterFn: (item: T['refs'][number]) => boolean, +) { + return ( + items + .map(item => ({ + ...item, + refs: item.refs.filter(refFilterFn), + })) + // remove item with empty refs + .filter(item => item.refs.length) + ); +} diff --git a/packages/utils/src/lib/filter.unit.test.ts b/packages/utils/src/lib/filter.unit.test.ts new file mode 100644 index 000000000..edd914b10 --- /dev/null +++ b/packages/utils/src/lib/filter.unit.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from 'vitest'; +import { filterItemRefsBy } from './filter'; + +describe('filterItemsWithRefBy', () => { + it('should return the filtered list based on the given filterFn', () => { + const list = [ + { + refs: [ + { plugin: 'a', weight: 1 }, + { plugin: 'b', weight: 1 }, + { plugin: 'c', weight: 1 }, + ], + }, + ]; + expect( + filterItemRefsBy(list, ({ plugin }) => plugin === 'a'), + ).toStrictEqual([ + expect.objectContaining({ + refs: [{ plugin: 'a', weight: 1 }], + }), + ]); + }); +}); diff --git a/packages/utils/src/lib/log-results.unit.test.ts b/packages/utils/src/lib/log-results.unit.test.ts index 407d6b9d8..0162b0715 100644 --- a/packages/utils/src/lib/log-results.unit.test.ts +++ b/packages/utils/src/lib/log-results.unit.test.ts @@ -6,7 +6,7 @@ describe('logMultipleResults', () => { const succeededCallbackMock = vi.fn(); const failedCallbackMock = vi.fn(); - it('should call logPromiseResults with successfull plugin result', () => { + it('should call logPromiseResults with successful plugin result', () => { logMultipleResults( [ {