From 5f91da86373bed6821f41b59d7ef5f541ee1f5ec Mon Sep 17 00:00:00 2001 From: Vojtech Masek Date: Sat, 21 Dec 2024 02:11:12 +0100 Subject: [PATCH] test(plugin-js-packages-e2e): create vulnerabilities e2e test --- e2e/plugin-js-packages-e2e/eslint.config.js | 12 +++ .../fixtures/npm-repo/code-pushup.config.ts | 32 ++++++ .../mocks/fixtures/npm-repo/package.json | 10 ++ e2e/plugin-js-packages-e2e/project.json | 23 +++++ .../tests/plugin-js-packages.e2e.test.ts | 99 +++++++++++++++++++ e2e/plugin-js-packages-e2e/tsconfig.json | 20 ++++ e2e/plugin-js-packages-e2e/tsconfig.test.json | 15 +++ e2e/plugin-js-packages-e2e/vite.config.e2e.ts | 21 ++++ 8 files changed, 232 insertions(+) create mode 100644 e2e/plugin-js-packages-e2e/eslint.config.js create mode 100644 e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/code-pushup.config.ts create mode 100644 e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/package.json create mode 100644 e2e/plugin-js-packages-e2e/project.json create mode 100644 e2e/plugin-js-packages-e2e/tests/plugin-js-packages.e2e.test.ts create mode 100644 e2e/plugin-js-packages-e2e/tsconfig.json create mode 100644 e2e/plugin-js-packages-e2e/tsconfig.test.json create mode 100644 e2e/plugin-js-packages-e2e/vite.config.e2e.ts diff --git a/e2e/plugin-js-packages-e2e/eslint.config.js b/e2e/plugin-js-packages-e2e/eslint.config.js new file mode 100644 index 000000000..2656b27cb --- /dev/null +++ b/e2e/plugin-js-packages-e2e/eslint.config.js @@ -0,0 +1,12 @@ +import tseslint from 'typescript-eslint'; +import baseConfig from '../../eslint.config.js'; + +export default tseslint.config(...baseConfig, { + files: ['**/*.ts'], + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, +}); diff --git a/e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/code-pushup.config.ts b/e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/code-pushup.config.ts new file mode 100644 index 000000000..7ce3a5b62 --- /dev/null +++ b/e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/code-pushup.config.ts @@ -0,0 +1,32 @@ +import jsPackagesPlugin from '@code-pushup/js-packages-plugin'; +import type { CoreConfig } from '@code-pushup/models'; + +export default { + persist: { + outputDir: './', + filename: 'report', + format: ['json'], + }, + plugins: [await jsPackagesPlugin({ packageManager: 'npm' })], + categories: [ + { + slug: 'security', + title: 'Security', + refs: [ + { type: 'group', plugin: 'js-packages', slug: 'npm-audit', weight: 1 }, + ], + }, + { + slug: 'updates', + title: 'Updates', + refs: [ + { + type: 'group', + plugin: 'js-packages', + slug: 'npm-outdated', + weight: 1, + }, + ], + }, + ], +} satisfies CoreConfig; diff --git a/e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/package.json b/e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/package.json new file mode 100644 index 000000000..cdfc9e578 --- /dev/null +++ b/e2e/plugin-js-packages-e2e/mocks/fixtures/npm-repo/package.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "express": "3.0.0" + }, + "devDependencies": { + "@code-pushup/cli": "latest", + "@code-pushup/js-packages-plugin": "latest", + "@code-pushup/models": "latest" + } +} diff --git a/e2e/plugin-js-packages-e2e/project.json b/e2e/plugin-js-packages-e2e/project.json new file mode 100644 index 000000000..edbd1594d --- /dev/null +++ b/e2e/plugin-js-packages-e2e/project.json @@ -0,0 +1,23 @@ +{ + "name": "plugin-js-packages-e2e", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "e2e/plugin-js-packages-e2e/src", + "implicitDependencies": ["cli", "plugin-js-packages"], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["e2e/plugin-eslint-e2e/**/*.ts"] + } + }, + "e2e": { + "executor": "@nx/vite:test", + "options": { + "configFile": "e2e/plugin-eslint-e2e/vite.config.e2e.ts" + } + } + }, + "tags": ["scope:plugin", "type:e2e"] +} diff --git a/e2e/plugin-js-packages-e2e/tests/plugin-js-packages.e2e.test.ts b/e2e/plugin-js-packages-e2e/tests/plugin-js-packages.e2e.test.ts new file mode 100644 index 000000000..0bd517e0b --- /dev/null +++ b/e2e/plugin-js-packages-e2e/tests/plugin-js-packages.e2e.test.ts @@ -0,0 +1,99 @@ +import { cp } from 'node:fs/promises'; +import path from 'node:path'; +import { afterAll, beforeAll, expect, it } from 'vitest'; +import { type Report, reportSchema } from '@code-pushup/models'; +import { nxTargetProject } from '@code-pushup/test-nx-utils'; +import { teardownTestFolder } from '@code-pushup/test-setup'; +import { + E2E_ENVIRONMENTS_DIR, + TEST_OUTPUT_DIR, + omitVariableReportData, +} from '@code-pushup/test-utils'; +import { executeProcess, readJsonFile } from '@code-pushup/utils'; + +describe('plugin-js-packages', () => { + const fixturesDir = path.join( + 'e2e', + 'plugin-js-packages-e2e', + 'mocks', + 'fixtures', + ); + const fixturesNPMDir = path.join(fixturesDir, 'npm-repo'); + + const envRoot = path.join( + E2E_ENVIRONMENTS_DIR, + nxTargetProject(), + TEST_OUTPUT_DIR, + ); + const npmRepoDir = path.join(envRoot, 'npm-repo'); + + beforeAll(async () => { + await cp(fixturesNPMDir, npmRepoDir, { recursive: true }); + }); + + afterAll(async () => { + await teardownTestFolder(npmRepoDir); + }); + + it('should run JS packages plugin for NPM and create report.json', async () => { + const { code: installCode } = await executeProcess({ + command: 'npm', + args: ['install'], + cwd: npmRepoDir, + }); + + expect(installCode).toBe(0); + + const { code, stderr } = await executeProcess({ + command: 'npx', + args: ['@code-pushup/cli', 'collect', '--no-progress'], + cwd: npmRepoDir, + }); + + expect(code).toBe(0); + expect(stderr).toBe(''); + + const report = await readJsonFile( + path.join(npmRepoDir, 'report.json'), + ); + + expect(() => reportSchema.parse(report)).not.toThrow(); + expect.objectContaining({ + categories: expect.arrayContaining([ + expect.objectContaining({ slug: 'security' }), + expect.objectContaining({ slug: 'updates' }), + ]), + plugins: expect.arrayContaining([ + expect.objectContaining({ + packageName: '@code-pushup/js-packages-plugin', + audits: expect.arrayContaining([ + expect.objectContaining({ + slug: 'npm-audit-prod', + displayValue: expect.stringMatching(/\d vulnerabilities/), + value: expect.closeTo(7, 10), // there are 7 vulnerabilities (6 high, 1 low) at the time + details: expect.objectContaining({ + issues: expect.any(Array), + }), + }), + expect.objectContaining({ + slug: 'npm-outdated-prod', + displayValue: '1 major outdated package version', + value: 1, + score: 0, + details: { + issues: expect.arrayContaining([ + expect.objectContaining({ + message: expect.stringMatching( + /Package \[`express`].*\*\*major\*\* update from \*\*\d+\.\d+\.\d+\*\* to \*\*\d+\.\d+\.\d+\*\*/, + ), + severity: 'error', + }), + ]), + }, + }), + ]), + }), + ]), + }); + }); +}); diff --git a/e2e/plugin-js-packages-e2e/tsconfig.json b/e2e/plugin-js-packages-e2e/tsconfig.json new file mode 100644 index 000000000..f5a2f890a --- /dev/null +++ b/e2e/plugin-js-packages-e2e/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "ESNext", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "types": ["vitest"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.test.json" + } + ] +} diff --git a/e2e/plugin-js-packages-e2e/tsconfig.test.json b/e2e/plugin-js-packages-e2e/tsconfig.test.json new file mode 100644 index 000000000..34f35e30f --- /dev/null +++ b/e2e/plugin-js-packages-e2e/tsconfig.test.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"], + "target": "ES2020" + }, + "exclude": ["__test-env__/**"], + "include": [ + "vite.config.e2e.ts", + "tests/**/*.e2e.test.ts", + "tests/**/*.d.ts", + "mocks/**/*.ts" + ] +} diff --git a/e2e/plugin-js-packages-e2e/vite.config.e2e.ts b/e2e/plugin-js-packages-e2e/vite.config.e2e.ts new file mode 100644 index 000000000..8b8475ed1 --- /dev/null +++ b/e2e/plugin-js-packages-e2e/vite.config.e2e.ts @@ -0,0 +1,21 @@ +/// +import { defineConfig } from 'vite'; +import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/plugin-js-packages-e2e', + test: { + reporters: ['basic'], + testTimeout: 120_000, + globals: true, + alias: tsconfigPathAliases(), + pool: 'threads', + poolOptions: { threads: { singleThread: true } }, + cache: { + dir: '../../node_modules/.vitest', + }, + environment: 'node', + include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], + }, +});