diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress.config.ts b/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress.config.ts new file mode 100644 index 000000000..1ba1a06a8 --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress.config.ts @@ -0,0 +1,15 @@ +import { nxE2EPreset } from '@nrwl/cypress/plugins/cypress-preset'; +import { defineConfig } from 'cypress'; + +const cypressJsonConfig = {}; + +export default defineConfig({ + reporter: "cypress-multi-reporters", + reporterOptions: { + configFile: 'reporter-config.json', + }, + e2e: { + ...nxE2EPreset(__dirname, {}), + ...cypressJsonConfig, + }, +}); diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress/support/commands.ts b/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress/support/commands.ts new file mode 100644 index 000000000..6bb5e9b42 --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress/support/commands.ts @@ -0,0 +1,7 @@ +import { faker } from '@faker-js/faker'; + +function login() { + return faker; +} + +Cypress.Commands.add('login', login); diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress/support/e2e.ts b/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress/support/e2e.ts new file mode 100644 index 000000000..2648ab502 --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/cypress/support/e2e.ts @@ -0,0 +1,2 @@ +import '@testing-library/cypress/add-commands'; +import './commands'; diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/@nrwl/cypress/plugins/cypress-preset.js b/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/@nrwl/cypress/plugins/cypress-preset.js new file mode 100644 index 000000000..fe28e5a9e --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/@nrwl/cypress/plugins/cypress-preset.js @@ -0,0 +1 @@ +export const nxE2EPreset = (p, c) => ({}); diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/cypress/index.js b/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/cypress/index.js new file mode 100644 index 000000000..3ba0c71a6 --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/cypress/index.js @@ -0,0 +1 @@ +export const defineConfig = c => c; diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/cypress/package.json b/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/cypress/package.json new file mode 100644 index 000000000..7dcf54370 --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/node_modules/cypress/package.json @@ -0,0 +1,3 @@ +{ + "name": "cypress" +} diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/package.json b/packages/knip/fixtures/plugins/cypress-multi-reporter/package.json new file mode 100644 index 000000000..02389829f --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/package.json @@ -0,0 +1,9 @@ +{ + "name": "@fixtures/cypress", + "devDependencies": { + "cypress": "*", + "cypress-multi-reporters": "*", + "mocha-junit-reporter": "*", + "mochawesome": "*" + } +} diff --git a/packages/knip/fixtures/plugins/cypress-multi-reporter/reporter-config.json b/packages/knip/fixtures/plugins/cypress-multi-reporter/reporter-config.json new file mode 100644 index 000000000..5b77b2335 --- /dev/null +++ b/packages/knip/fixtures/plugins/cypress-multi-reporter/reporter-config.json @@ -0,0 +1,4 @@ +{ + "reporterEnabled": "mochawesome, mocha-junit-reporter , @testing-library/my-fake-reporter" +} + \ No newline at end of file diff --git a/packages/knip/src/plugins/cypress/helpers.ts b/packages/knip/src/plugins/cypress/helpers.ts new file mode 100644 index 000000000..10b8598b5 --- /dev/null +++ b/packages/knip/src/plugins/cypress/helpers.ts @@ -0,0 +1,37 @@ +import type { PluginOptions } from '#p/types/plugins.js'; +import { isInternal, toAbsolute } from '#p/util/path.js'; +import { load, resolveEntry } from '#p/util/plugin.js'; +import type { CypressConfig } from './types.js'; + +interface ReporterConfig { + reporterEnabled: string; +} + +export const resolveDependencies = async (config: CypressConfig, options: PluginOptions) => { + const { reporter } = config; + const { configFileDir } = options; + + const resolve = (specifier: string) => resolveEntry(options, specifier); + + // Initialize the array of reporters with the initial reporter if present. + const reporters: Set = reporter ? new Set([reporter]) : new Set(); + // https://github.com/YOU54F/cypress-plugins/tree/master/cypress-multi-reporters#configuring-reporters + if (reporter === 'cypress-multi-reporters' && config.reporterOptions?.configFile) { + // Try to resolve the config file if present and attach the reporters listed in it. + const { configFile } = config.reporterOptions; + const configFilePath = toAbsolute(configFile, configFileDir); + if (isInternal(configFilePath)) { + const reporterConfig: ReporterConfig = await load(configFilePath); + if (typeof reporterConfig === 'object' && reporterConfig.reporterEnabled) { + const { reporterEnabled: reporterConcatenatedNames } = reporterConfig; + // Pulled from the reporter source code, https://github.com/YOU54F/cypress-plugins/blob/master/cypress-multi-reporters/lib/MultiReporters.js#L50-L58 + // Not sure why they allow for extra whitespace characters, but let's handle it the same as them. + const reporterNames = reporterConcatenatedNames.split(','); + for (const reporterName of reporterNames) { + reporters.add(resolve(reporterName.trim())); + } + } + } + } + return [...reporters]; +}; diff --git a/packages/knip/src/plugins/cypress/index.ts b/packages/knip/src/plugins/cypress/index.ts index b7e72f10c..35fec0c10 100644 --- a/packages/knip/src/plugins/cypress/index.ts +++ b/packages/knip/src/plugins/cypress/index.ts @@ -1,6 +1,8 @@ -import type { IsPluginEnabled, Plugin, ResolveEntryPaths } from '#p/types/plugins.js'; +import type { IsPluginEnabled, Plugin, ResolveConfig, ResolveEntryPaths } from '#p/types/plugins.js'; import { hasDependency } from '#p/util/plugin.js'; import { toEntryPattern } from '../../util/protocols.js'; +import { resolveDependencies } from './helpers.js'; +import type { CypressConfig } from './types.js'; // https://docs.cypress.io/guides/references/configuration @@ -31,6 +33,10 @@ const resolveEntryPaths: ResolveEntryPaths = async localConfig => { ].map(toEntryPattern); }; +const resolveConfig: ResolveConfig = (config, options) => { + return resolveDependencies(config, options); +}; + export default { title, enablers, @@ -38,4 +44,5 @@ export default { config, entry, resolveEntryPaths, + resolveConfig, } satisfies Plugin; diff --git a/packages/knip/src/plugins/cypress/types.ts b/packages/knip/src/plugins/cypress/types.ts new file mode 100644 index 000000000..11de5bfd7 --- /dev/null +++ b/packages/knip/src/plugins/cypress/types.ts @@ -0,0 +1,4 @@ +export interface CypressConfig { + reporter: string; + reporterOptions?: { configFile?: string }; +} diff --git a/packages/knip/test/plugins/cypress-multi-reporter.test.ts b/packages/knip/test/plugins/cypress-multi-reporter.test.ts new file mode 100644 index 000000000..584b749cf --- /dev/null +++ b/packages/knip/test/plugins/cypress-multi-reporter.test.ts @@ -0,0 +1,28 @@ +import { test } from 'bun:test'; +import assert from 'node:assert/strict'; +import { main } from '../../src/index.js'; +import { resolve } from '../../src/util/path.js'; +import baseArguments from '../helpers/baseArguments.js'; +import baseCounters from '../helpers/baseCounters.js'; + +const cwd = resolve('fixtures/plugins/cypress-multi-reporter'); + +test('Find dependencies with the cypress-multi-reporter plugin', async () => { + const { issues, counters } = await main({ + ...baseArguments, + cwd, + }); + + assert(issues.unlisted['cypress.config.ts']['@nrwl/cypress/plugins/cypress-preset']); + assert(issues.unlisted['cypress/support/commands.ts']['@faker-js/faker']); + assert(issues.unlisted['cypress/support/e2e.ts']['@testing-library/cypress/add-commands']); + assert(issues.unlisted['cypress.config.ts']['@testing-library/my-fake-reporter']); + + assert.deepEqual(counters, { + ...baseCounters, + devDependencies: 0, + unlisted: 4, + processed: 3, + total: 3, + }); +});