From c8f179d2d2f35db585163b64b49d6c608f6ce37d Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Wed, 10 Apr 2024 18:12:44 -0400 Subject: [PATCH] feat(testing): add metadata to playwright targets (#22768) --- .../playwright/src/plugins/plugin.spec.ts | 65 +++++++++++++++++++ packages/playwright/src/plugins/plugin.ts | 55 ++++++++++------ 2 files changed, 100 insertions(+), 20 deletions(-) diff --git a/packages/playwright/src/plugins/plugin.spec.ts b/packages/playwright/src/plugins/plugin.spec.ts index 94471ba4bb..4c83d5ab39 100644 --- a/packages/playwright/src/plugins/plugin.spec.ts +++ b/packages/playwright/src/plugins/plugin.spec.ts @@ -46,6 +46,13 @@ describe('@nx/playwright/plugin', () => { expect(projects).toMatchInlineSnapshot(` { ".": { + "metadata": { + "targetGroups": { + "E2E (CI)": [ + "e2e-ci", + ], + }, + }, "root": ".", "targets": { "e2e": { @@ -55,6 +62,12 @@ describe('@nx/playwright/plugin', () => { "default", "^production", ], + "metadata": { + "description": "Runs Playwright Tests", + "technologies": [ + "playwright", + ], + }, "options": { "cwd": "{projectRoot}", }, @@ -70,6 +83,12 @@ describe('@nx/playwright/plugin', () => { "default", "^production", ], + "metadata": { + "description": "Runs Playwright Tests in CI", + "technologies": [ + "playwright", + ], + }, "outputs": [ "{projectRoot}/test-results", ], @@ -99,6 +118,13 @@ describe('@nx/playwright/plugin', () => { expect(projects).toMatchInlineSnapshot(` { ".": { + "metadata": { + "targetGroups": { + "E2E (CI)": [ + "e2e-ci", + ], + }, + }, "root": ".", "targets": { "e2e": { @@ -108,6 +134,12 @@ describe('@nx/playwright/plugin', () => { "default", "^production", ], + "metadata": { + "description": "Runs Playwright Tests", + "technologies": [ + "playwright", + ], + }, "options": { "cwd": "{projectRoot}", }, @@ -126,6 +158,12 @@ describe('@nx/playwright/plugin', () => { "default", "^production", ], + "metadata": { + "description": "Runs Playwright Tests in CI", + "technologies": [ + "playwright", + ], + }, "outputs": [ "{projectRoot}/playwright-report", "{projectRoot}/test-results/report.json", @@ -164,6 +202,15 @@ describe('@nx/playwright/plugin', () => { context ); const { targets } = projects['.']; + expect(projects['.'].metadata.targetGroups).toMatchInlineSnapshot(` + { + "E2E (CI)": [ + "e2e-ci--tests/run-me-2.spec.ts", + "e2e-ci--tests/run-me.spec.ts", + "e2e-ci", + ], + } + `); expect(targets['e2e-ci']).toMatchInlineSnapshot(` { "cache": true, @@ -184,6 +231,12 @@ describe('@nx/playwright/plugin', () => { "default", "^production", ], + "metadata": { + "description": "Runs Playwright Tests in CI", + "technologies": [ + "playwright", + ], + }, "outputs": [ "{projectRoot}/test-results", ], @@ -197,6 +250,12 @@ describe('@nx/playwright/plugin', () => { "default", "^production", ], + "metadata": { + "description": "Runs Playwright Tests in tests/run-me.spec.ts in CI", + "technologies": [ + "playwright", + ], + }, "options": { "cwd": "{projectRoot}", }, @@ -213,6 +272,12 @@ describe('@nx/playwright/plugin', () => { "default", "^production", ], + "metadata": { + "description": "Runs Playwright Tests in tests/run-me-2.spec.ts in CI", + "technologies": [ + "playwright", + ], + }, "options": { "cwd": "{projectRoot}", }, diff --git a/packages/playwright/src/plugins/plugin.ts b/packages/playwright/src/plugins/plugin.ts index ed57c3a215..861be3897a 100644 --- a/packages/playwright/src/plugins/plugin.ts +++ b/packages/playwright/src/plugins/plugin.ts @@ -8,6 +8,7 @@ import { detectPackageManager, joinPathFragments, normalizePath, + ProjectConfiguration, readJsonFile, TargetConfiguration, writeJsonFile, @@ -36,21 +37,15 @@ const cachePath = join(projectGraphCacheDirectory, 'playwright.hash'); const targetsCache = existsSync(cachePath) ? readTargetsCache() : {}; -const calculatedTargets: Record< - string, - Record -> = {}; +type PlaywrightTargets = Pick; -function readTargetsCache(): Record< - string, - Record -> { +const calculatedTargets: Record = {}; + +function readTargetsCache(): Record { return readJsonFile(cachePath); } -function writeTargetsToCache( - targets: Record> -) { +function writeTargetsToCache(targets: Record) { writeJsonFile(cachePath, targets); } @@ -79,7 +74,7 @@ export const createNodes: CreateNodes = [ getLockFileName(detectPackageManager(context.workspaceRoot)), ]); - const targets = + const { targets, metadata } = targetsCache[hash] ?? (await buildPlaywrightTargets( configFilePath, @@ -88,13 +83,14 @@ export const createNodes: CreateNodes = [ context )); - calculatedTargets[hash] = targets; + calculatedTargets[hash] = { targets, metadata }; return { projects: { [projectRoot]: { root: projectRoot, targets, + metadata, }, }, }; @@ -106,7 +102,7 @@ async function buildPlaywrightTargets( projectRoot: string, options: NormalizedOptions, context: CreateNodesContext -) { +): Promise { // Playwright forbids importing the `@playwright/test` module twice. This would affect running the tests, // but we're just reading the config so let's delete the variable they are using to detect this. // See: https://github.com/microsoft/playwright/pull/11218/files @@ -118,13 +114,18 @@ async function buildPlaywrightTargets( const namedInputs = getNamedInputs(projectRoot, context); - const targets: Record> = {}; + const targets: ProjectConfiguration['targets'] = {}; + let metadata: ProjectConfiguration['metadata']; const baseTargetConfig: TargetConfiguration = { command: 'playwright test', options: { cwd: '{projectRoot}', }, + metadata: { + technologies: ['playwright'], + description: 'Runs Playwright Tests', + }, }; targets[options.targetName] = { @@ -148,6 +149,10 @@ async function buildPlaywrightTargets( outputs: getOutputs(projectRoot, playwrightConfig), }; + const groupName = 'E2E (CI)'; + metadata = { targetGroups: { [groupName]: [] } }; + const ciTargetGroup = metadata.targetGroups[groupName]; + const testDir = playwrightConfig.testDir ? joinPathFragments(projectRoot, playwrightConfig.testDir) : projectRoot; @@ -158,13 +163,18 @@ async function buildPlaywrightTargets( const dependsOn: TargetConfiguration['dependsOn'] = []; forEachTestFile( (testFile) => { - const relativeToProjectRoot = normalizePath( + const relativeSpecFilePath = normalizePath( relative(projectRoot, testFile) ); - const targetName = `${options.ciTargetName}--${relativeToProjectRoot}`; + const targetName = `${options.ciTargetName}--${relativeSpecFilePath}`; + ciTargetGroup.push(targetName); targets[targetName] = { ...ciBaseTargetConfig, - command: `${baseTargetConfig.command} ${relativeToProjectRoot}`, + command: `${baseTargetConfig.command} ${relativeSpecFilePath}`, + metadata: { + technologies: ['playwright'], + description: `Runs Playwright Tests in ${relativeSpecFilePath} in CI`, + }, }; dependsOn.push({ target: targetName, @@ -187,13 +197,18 @@ async function buildPlaywrightTargets( inputs: ciBaseTargetConfig.inputs, outputs: ciBaseTargetConfig.outputs, dependsOn, + metadata: { + technologies: ['playwright'], + description: 'Runs Playwright Tests in CI', + }, }; + ciTargetGroup.push(options.ciTargetName); } - return targets; + return { targets, metadata }; } -async function forEachTestFile( +function forEachTestFile( cb: (path: string) => void, opts: { context: CreateNodesContext;