refactor
This commit is contained in:
parent
a11e7fb071
commit
76e63c4bc6
|
|
@ -14,6 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import childProcess from 'child_process';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { FullConfig, Reporter, TestError } from '../../types/testReporter';
|
import type { FullConfig, Reporter, TestError } from '../../types/testReporter';
|
||||||
import { InProcessLoaderHost, OutOfProcessLoaderHost } from './loaderHost';
|
import { InProcessLoaderHost, OutOfProcessLoaderHost } from './loaderHost';
|
||||||
|
|
@ -28,7 +29,7 @@ import type { TestRun } from './tasks';
|
||||||
import { requireOrImport } from '../transform/transform';
|
import { requireOrImport } from '../transform/transform';
|
||||||
import { applyRepeatEachIndex, bindFileSuiteToProject, filterByFocusedLine, filterByTestIds, filterOnly, filterTestsRemoveEmptySuites } from '../common/suiteUtils';
|
import { applyRepeatEachIndex, bindFileSuiteToProject, filterByFocusedLine, filterByTestIds, filterOnly, filterTestsRemoveEmptySuites } from '../common/suiteUtils';
|
||||||
import { createTestGroups, filterForShard, type TestGroup } from './testGroups';
|
import { createTestGroups, filterForShard, type TestGroup } from './testGroups';
|
||||||
import { dependenciesForTestFile } from '../transform/compilationCache';
|
import { affectedTestFiles, dependenciesForTestFile } from '../transform/compilationCache';
|
||||||
import { sourceMapSupport } from '../utilsBundle';
|
import { sourceMapSupport } from '../utilsBundle';
|
||||||
import type { RawSourceMap } from 'source-map';
|
import type { RawSourceMap } from 'source-map';
|
||||||
|
|
||||||
|
|
@ -36,7 +37,7 @@ export async function collectProjectsAndTestFiles(testRun: TestRun, doNotRunTest
|
||||||
const config = testRun.config;
|
const config = testRun.config;
|
||||||
const fsCache = new Map();
|
const fsCache = new Map();
|
||||||
const sourceMapCache = new Map();
|
const sourceMapCache = new Map();
|
||||||
const cliFileMatcher = config.cliArgs.length ? await createFileMatcherFromArguments(config.cliArgs, undefined) : null;
|
const cliFileMatcher = config.cliArgs.length ? createFileMatcherFromArguments(config.cliArgs) : null;
|
||||||
|
|
||||||
// First collect all files for the projects in the command line, don't apply any file filters.
|
// First collect all files for the projects in the command line, don't apply any file filters.
|
||||||
const allFilesForProject = new Map<FullProjectInternal, string[]>();
|
const allFilesForProject = new Map<FullProjectInternal, string[]>();
|
||||||
|
|
@ -118,7 +119,43 @@ export async function loadFileSuites(testRun: TestRun, mode: 'out-of-process' |
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createRootSuite(testRun: TestRun, errors: TestError[], shouldFilterOnly: boolean): Promise<Suite> {
|
export async function detectChangedFiles(baseCommit: string): Promise<string[]> {
|
||||||
|
function gitFileList(command: string) {
|
||||||
|
try {
|
||||||
|
return childProcess.execSync(
|
||||||
|
`git ${command}`,
|
||||||
|
{ encoding: 'utf-8', stdio: 'pipe' }
|
||||||
|
).split('\n').filter(Boolean);
|
||||||
|
} catch (_error) {
|
||||||
|
const error = _error as childProcess.SpawnSyncReturns<string>;
|
||||||
|
throw new Error([
|
||||||
|
`Encountered error while detecting changed files.`,
|
||||||
|
`--only-changed only works with Git repositories.`,
|
||||||
|
`Make sure that:`,
|
||||||
|
` - You are running the test in a Git repository.`,
|
||||||
|
` - The Git binary is in your PATH.`,
|
||||||
|
` - The passed Git Ref exists in the repository. You passed '${baseCommit}'.`,
|
||||||
|
``,
|
||||||
|
`Command Output:`,
|
||||||
|
``,
|
||||||
|
...error.output,
|
||||||
|
].join('\n'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const untrackedFiles = gitFileList(`ls-files --others --exclude-standard`).map(file => path.join(process.cwd(), file));
|
||||||
|
|
||||||
|
const [gitRoot] = gitFileList('rev-parse --show-toplevel');
|
||||||
|
const trackedFilesWithChanges = gitFileList(`diff ${baseCommit} --name-only`).map(file => path.join(gitRoot, file));
|
||||||
|
|
||||||
|
const filesWithChanges = [...untrackedFiles, ...trackedFilesWithChanges];
|
||||||
|
return [
|
||||||
|
...filesWithChanges,
|
||||||
|
...affectedTestFiles(filesWithChanges),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createRootSuite(testRun: TestRun, errors: TestError[], shouldFilterOnly: boolean, onlyChangedFiles?: string[]): Promise<Suite> {
|
||||||
const config = testRun.config;
|
const config = testRun.config;
|
||||||
// Create root suite, where each child will be a project suite with cloned file suites inside it.
|
// Create root suite, where each child will be a project suite with cloned file suites inside it.
|
||||||
const rootSuite = new Suite('', 'root');
|
const rootSuite = new Suite('', 'root');
|
||||||
|
|
@ -128,7 +165,8 @@ export async function createRootSuite(testRun: TestRun, errors: TestError[], sho
|
||||||
// Filter all the projects using grep, testId, file names.
|
// Filter all the projects using grep, testId, file names.
|
||||||
{
|
{
|
||||||
// Interpret cli parameters.
|
// Interpret cli parameters.
|
||||||
const cliFileFilters = await createFileFiltersFromArguments(config.cliArgs, config.cliOnlyChanged);
|
const cliFileFilters = createFileFiltersFromArguments(config.cliArgs);
|
||||||
|
const onlyChangedFilters = onlyChangedFiles ? createFileFiltersFromArguments(onlyChangedFiles) : undefined;
|
||||||
const grepMatcher = config.cliGrep ? createTitleMatcher(forceRegExp(config.cliGrep)) : () => true;
|
const grepMatcher = config.cliGrep ? createTitleMatcher(forceRegExp(config.cliGrep)) : () => true;
|
||||||
const grepInvertMatcher = config.cliGrepInvert ? createTitleMatcher(forceRegExp(config.cliGrepInvert)) : () => false;
|
const grepInvertMatcher = config.cliGrepInvert ? createTitleMatcher(forceRegExp(config.cliGrepInvert)) : () => false;
|
||||||
const cliTitleMatcher = (title: string) => !grepInvertMatcher(title) && grepMatcher(title);
|
const cliTitleMatcher = (title: string) => !grepInvertMatcher(title) && grepMatcher(title);
|
||||||
|
|
@ -137,7 +175,7 @@ export async function createRootSuite(testRun: TestRun, errors: TestError[], sho
|
||||||
for (const [project, fileSuites] of testRun.projectSuites) {
|
for (const [project, fileSuites] of testRun.projectSuites) {
|
||||||
const projectSuite = createProjectSuite(project, fileSuites);
|
const projectSuite = createProjectSuite(project, fileSuites);
|
||||||
projectSuites.set(project, projectSuite);
|
projectSuites.set(project, projectSuite);
|
||||||
const filteredProjectSuite = filterProjectSuite(projectSuite, { cliFileFilters, cliTitleMatcher, testIdMatcher: config.testIdMatcher });
|
const filteredProjectSuite = filterProjectSuite(projectSuite, { cliFileFilters, cliTitleMatcher, testIdMatcher: config.testIdMatcher, onlyChangedFilters });
|
||||||
filteredProjectSuites.set(project, filteredProjectSuite);
|
filteredProjectSuites.set(project, filteredProjectSuite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,14 +261,16 @@ function createProjectSuite(project: FullProjectInternal, fileSuites: Suite[]):
|
||||||
return projectSuite;
|
return projectSuite;
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterProjectSuite(projectSuite: Suite, options: { cliFileFilters: TestFileFilter[], cliTitleMatcher?: Matcher, testIdMatcher?: Matcher }): Suite {
|
function filterProjectSuite(projectSuite: Suite, options: { cliFileFilters: TestFileFilter[], cliTitleMatcher?: Matcher, testIdMatcher?: Matcher, onlyChangedFilters?: TestFileFilter[] }): Suite {
|
||||||
// Fast path.
|
// Fast path.
|
||||||
if (!options.cliFileFilters.length && !options.cliTitleMatcher && !options.testIdMatcher)
|
if (!options.cliFileFilters.length && !options.cliTitleMatcher && !options.testIdMatcher && !options.onlyChangedFilters?.length)
|
||||||
return projectSuite;
|
return projectSuite;
|
||||||
|
|
||||||
const result = projectSuite._deepClone();
|
const result = projectSuite._deepClone();
|
||||||
if (options.cliFileFilters.length)
|
if (options.cliFileFilters.length)
|
||||||
filterByFocusedLine(result, options.cliFileFilters);
|
filterByFocusedLine(result, options.cliFileFilters);
|
||||||
|
if (options.onlyChangedFilters?.length)
|
||||||
|
filterByFocusedLine(result, options.onlyChangedFilters);
|
||||||
if (options.testIdMatcher)
|
if (options.testIdMatcher)
|
||||||
filterByTestIds(result, options.testIdMatcher);
|
filterByTestIds(result, options.testIdMatcher);
|
||||||
filterTestsRemoveEmptySuites(result, (test: TestCase) => {
|
filterTestsRemoveEmptySuites(result, (test: TestCase) => {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import { createTestGroups, type TestGroup } from '../runner/testGroups';
|
||||||
import type { Task } from './taskRunner';
|
import type { Task } from './taskRunner';
|
||||||
import { TaskRunner } from './taskRunner';
|
import { TaskRunner } from './taskRunner';
|
||||||
import type { FullConfigInternal, FullProjectInternal } from '../common/config';
|
import type { FullConfigInternal, FullProjectInternal } from '../common/config';
|
||||||
import { collectProjectsAndTestFiles, createRootSuite, loadFileSuites, loadGlobalHook } from './loadUtils';
|
import { collectProjectsAndTestFiles, createRootSuite, detectChangedFiles, loadFileSuites, loadGlobalHook } from './loadUtils';
|
||||||
import type { Matcher } from '../util';
|
import type { Matcher } from '../util';
|
||||||
import { Suite } from '../common/test';
|
import { Suite } from '../common/test';
|
||||||
import { buildDependentProjects, buildTeardownToSetupsMap, filterProjects } from './projectUtils';
|
import { buildDependentProjects, buildTeardownToSetupsMap, filterProjects } from './projectUtils';
|
||||||
|
|
@ -228,7 +228,8 @@ function createLoadTask(mode: 'out-of-process' | 'in-process', options: { filter
|
||||||
setup: async (testRun, errors, softErrors) => {
|
setup: async (testRun, errors, softErrors) => {
|
||||||
await collectProjectsAndTestFiles(testRun, !!options.doNotRunDepsOutsideProjectFilter, options.additionalFileMatcher);
|
await collectProjectsAndTestFiles(testRun, !!options.doNotRunDepsOutsideProjectFilter, options.additionalFileMatcher);
|
||||||
await loadFileSuites(testRun, mode, options.failOnLoadErrors ? errors : softErrors);
|
await loadFileSuites(testRun, mode, options.failOnLoadErrors ? errors : softErrors);
|
||||||
testRun.rootSuite = await createRootSuite(testRun, options.failOnLoadErrors ? errors : softErrors, !!options.filterOnly);
|
const changedFiles = testRun.config.cliOnlyChanged ? await detectChangedFiles(testRun.config.cliOnlyChanged) : undefined;
|
||||||
|
testRun.rootSuite = await createRootSuite(testRun, options.failOnLoadErrors ? errors : softErrors, !!options.filterOnly, changedFiles);
|
||||||
testRun.failureTracker.onRootSuite(testRun.rootSuite);
|
testRun.failureTracker.onRootSuite(testRun.rootSuite);
|
||||||
// Fail when no tests.
|
// Fail when no tests.
|
||||||
if (options.failOnLoadErrors && !testRun.rootSuite.allTests().length && !testRun.config.cliPassWithNoTests && !testRun.config.config.shard) {
|
if (options.failOnLoadErrors && !testRun.rootSuite.allTests().length && !testRun.config.cliPassWithNoTests && !testRun.config.config.shard) {
|
||||||
|
|
|
||||||
|
|
@ -81,46 +81,7 @@ export type TestFileFilter = {
|
||||||
column: number | null;
|
column: number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function detectChangedFiles(baseCommit: string): Promise<string[]> {
|
export function createFileFiltersFromArguments(args: string[]): TestFileFilter[] {
|
||||||
function gitFileList(command: string) {
|
|
||||||
try {
|
|
||||||
return childProcess.execSync(
|
|
||||||
`git ${command}`,
|
|
||||||
{ encoding: 'utf-8', stdio: 'pipe' }
|
|
||||||
).split('\n').filter(Boolean);
|
|
||||||
} catch (_error) {
|
|
||||||
const error = _error as childProcess.SpawnSyncReturns<string>;
|
|
||||||
throw new Error([
|
|
||||||
`Encountered error while detecting changed files.`,
|
|
||||||
`--only-changed only works with Git repositories.`,
|
|
||||||
`Make sure that:`,
|
|
||||||
` - You are running the test in a Git repository.`,
|
|
||||||
` - The Git binary is in your PATH.`,
|
|
||||||
` - The passed Git Ref exists in the repository. You passed '${baseCommit}'.`,
|
|
||||||
``,
|
|
||||||
`Command Output:`,
|
|
||||||
``,
|
|
||||||
...error.output,
|
|
||||||
].join('\n'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const untrackedFiles = gitFileList(`ls-files --others --exclude-standard`).map(file => path.join(process.cwd(), file));
|
|
||||||
|
|
||||||
const [gitRoot] = gitFileList('rev-parse --show-toplevel');
|
|
||||||
const trackedFilesWithChanges = gitFileList(`diff ${baseCommit} --name-only`).map(file => path.join(gitRoot, file));
|
|
||||||
|
|
||||||
const filesWithChanges = [...untrackedFiles, ...trackedFilesWithChanges];
|
|
||||||
return [
|
|
||||||
...filesWithChanges,
|
|
||||||
...affectedTestFiles(filesWithChanges),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createFileFiltersFromArguments(args: string[], onlyChanged: string | undefined): Promise<TestFileFilter[]> {
|
|
||||||
if (onlyChanged)
|
|
||||||
args = await detectChangedFiles(onlyChanged);
|
|
||||||
|
|
||||||
return args.map(arg => {
|
return args.map(arg => {
|
||||||
const match = /^(.*?):(\d+):?(\d+)?$/.exec(arg);
|
const match = /^(.*?):(\d+):?(\d+)?$/.exec(arg);
|
||||||
return {
|
return {
|
||||||
|
|
@ -131,8 +92,8 @@ export async function createFileFiltersFromArguments(args: string[], onlyChanged
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createFileMatcherFromArguments(args: string[], onlyChanged: string | undefined): Promise<Matcher> {
|
export function createFileMatcherFromArguments(args: string[]): Matcher {
|
||||||
const filters = await createFileFiltersFromArguments(args, onlyChanged);
|
const filters = createFileFiltersFromArguments(args);
|
||||||
return createFileMatcher(filters.map(filter => filter.re || filter.exact || ''));
|
return createFileMatcher(filters.map(filter => filter.re || filter.exact || ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ test('should throw nice error message if git doesnt work', async ({ setupReposit
|
||||||
expect(result.output).toContain('only works with Git repositories');
|
expect(result.output).toContain('only works with Git repositories');
|
||||||
});
|
});
|
||||||
|
|
||||||
test.only('should suppport component tests', async ({ runInlineTest, setupRepository, writeFiles }) => {
|
test.skip('should suppport component tests', async ({ runInlineTest, setupRepository, writeFiles }) => {
|
||||||
const git = await setupRepository();
|
const git = await setupRepository();
|
||||||
|
|
||||||
await writeFiles({
|
await writeFiles({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue