diff --git a/packages/playwright/src/runner/loadUtils.ts b/packages/playwright/src/runner/loadUtils.ts index 946731b4a3..fe0088cac0 100644 --- a/packages/playwright/src/runner/loadUtils.ts +++ b/packages/playwright/src/runner/loadUtils.ts @@ -36,7 +36,7 @@ export async function collectProjectsAndTestFiles(testRun: TestRun, doNotRunTest const config = testRun.config; const fsCache = new Map(); const sourceMapCache = new Map(); - const cliFileMatcher = (config.cliArgs.length || config.cliOnlyChanged) ? await createFileMatcherFromArguments(config.cliArgs, config.cliOnlyChanged) : null; + const cliFileMatcher = config.cliArgs.length ? await createFileMatcherFromArguments(config.cliArgs, undefined) : null; // First collect all files for the projects in the command line, don't apply any file filters. const allFilesForProject = new Map(); diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index ce20dcb39d..cbc072445b 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -26,6 +26,7 @@ import type { TestInfoError } from './../types/test'; import type { Location } from './../types/testReporter'; import { calculateSha1, isRegExp, isString, sanitizeForFilePath, stringifyStackFrames } from 'playwright-core/lib/utils'; import type { RawStack } from 'playwright-core/lib/utils'; +import { affectedTestFiles } from './transform/compilationCache'; const PLAYWRIGHT_TEST_PATH = path.join(__dirname, '..'); const PLAYWRIGHT_CORE_PATH = path.dirname(require.resolve('playwright-core/package.json')); @@ -84,7 +85,7 @@ export async function detectChangedFiles(baseCommit: string): Promise const untrackedFiles = childProcess.execSync('git ls-files --others --exclude-standard', { encoding: 'utf-8' }).split('\n').filter(Boolean); const changedFiles = childProcess.execSync(`git diff ${baseCommit} --name-only`, { encoding: 'utf-8' }).split('\n').filter(Boolean); - return [...untrackedFiles, ...changedFiles]; + return [...untrackedFiles, ...changedFiles, ...affectedTestFiles([...untrackedFiles, ...changedFiles].map(file => path.resolve(file)))]; } export async function createFileFiltersFromArguments(args: string[], onlyChanged: string | undefined): Promise { diff --git a/tests/playwright-test/only-changed.spec.ts b/tests/playwright-test/only-changed.spec.ts index 476391d245..ad8b23c5e1 100644 --- a/tests/playwright-test/only-changed.spec.ts +++ b/tests/playwright-test/only-changed.spec.ts @@ -27,11 +27,17 @@ const test = baseTest.extend({ await writeFiles({ 'a.spec.ts': ` import { test, expect } from '@playwright/test'; - test('fails', () => { expect(1).toBe(2); }); + import { answer, question } from './utils'; + test('fails', () => { expect(question).toBe(answer); }); `, 'b.spec.ts': ` import { test, expect } from '@playwright/test'; - test('fails', () => { expect(1).toBe(2); }); + import { answer, question } from './utils'; + test('fails', () => { expect(question).toBe(answer); }); + `, + 'utils.ts': ` + export const answer = 42; + export const question = "???"; `, }); git(`init --initial-branch=main`); @@ -110,3 +116,19 @@ test.describe('should be smart about PR base reference from CI', () => { testCIEnvironment('Github Actions', 'GITHUB_BASE_REF'); testCIEnvironment('Azure DevOps', 'Build.PullRequest.TargetBranch'); }); + +test('should understand dependency structure', async ({ runInlineTest, setupRepository, writeFiles }) => { + await setupRepository(); + await writeFiles({ + 'utils.ts': ` + export const answer = 42; + export const question = "what is the answer to life the universe and everything"; + `, + }); + const result = await runInlineTest({}, { 'only-changed': true }); + + expect(result.exitCode).toBe(1); + expect(result.failed).toBe(2); + expect(result.output).toContain('a.spec.ts'); + expect(result.output).toContain('b.spec.ts'); +});