remove the watch mode concept, combine both watchers

This commit is contained in:
Simon Knott 2024-07-26 16:52:12 +02:00
parent c7b8a7b766
commit 52b0811c55
No known key found for this signature in database
GPG key ID: 8CEDC00028084AEC
3 changed files with 35 additions and 36 deletions

View file

@ -61,7 +61,7 @@ export async function runDevServer(config: FullConfigInternal): Promise<() => Pr
projectOutputs.add(p.project.outputDir);
}
const globalWatcher = new Watcher('deep', async () => {
const globalWatcher = new Watcher(async () => {
const registry: ComponentRegistry = new Map();
await populateComponentsFromTests(registry);
// compare componentRegistry to registry key sets.

View file

@ -21,26 +21,24 @@ export type FSEvent = { event: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkD
export class Watcher {
private _onChange: (events: FSEvent[]) => void;
private _watchedFiles: string[] = [];
private _watchedPaths: string[] = [];
private _ignoredFolders: string[] = [];
private _collector: FSEvent[] = [];
private _fsWatcher: FSWatcher | undefined;
private _throttleTimer: NodeJS.Timeout | undefined;
private _mode: 'flat' | 'deep';
constructor(mode: 'flat' | 'deep', onChange: (events: FSEvent[]) => void) {
this._mode = mode;
constructor(onChange: (events: FSEvent[]) => void) {
this._onChange = onChange;
}
update(watchedFiles: string[], ignoredFolders: string[], reportPending: boolean) {
if (JSON.stringify([this._watchedFiles, this._ignoredFolders]) === JSON.stringify(watchedFiles, ignoredFolders))
update(watchedPaths: string[], ignoredFolders: string[], reportPending: boolean) {
if (JSON.stringify([this._watchedPaths, this._ignoredFolders]) === JSON.stringify(watchedPaths, ignoredFolders))
return;
if (reportPending)
this._reportEventsIfAny();
this._watchedFiles = watchedFiles;
this._watchedPaths = watchedPaths;
this._ignoredFolders = ignoredFolders;
void this._fsWatcher?.close();
this._fsWatcher = undefined;
@ -48,17 +46,13 @@ export class Watcher {
clearTimeout(this._throttleTimer);
this._throttleTimer = undefined;
if (!this._watchedFiles.length)
if (!this._watchedPaths.length)
return;
const ignored = [...this._ignoredFolders, '**/node_modules/**'];
this._fsWatcher = chokidar.watch(watchedFiles, { ignoreInitial: true, ignored }).on('all', async (event, file) => {
this._fsWatcher = chokidar.watch(watchedPaths, { ignoreInitial: true, ignored }).on('all', async (event, file) => {
if (this._throttleTimer)
clearTimeout(this._throttleTimer);
if (this._mode === 'flat' && event !== 'add' && event !== 'change')
return;
if (this._mode === 'deep' && event !== 'add' && event !== 'change' && event !== 'unlink' && event !== 'addDir' && event !== 'unlinkDir')
return;
this._collector.push({ event, file });
this._throttleTimer = setTimeout(() => this._reportEventsIfAny(), 250);
});

View file

@ -27,7 +27,7 @@ import { TestRun, createTaskRunnerForList, createTaskRunnerForTestServer, create
import { open } from 'playwright-core/lib/utilsBundle';
import ListReporter from '../reporters/list';
import { SigIntWatcher } from './sigIntWatcher';
import { type FSEvent, Watcher } from '../fsWatcher';
import { Watcher } from '../fsWatcher';
import type { ReportEntry, TestServerInterface, TestServerInterfaceEventEmitters } from '../isomorphic/testServerInterface';
import { Runner } from './runner';
import type { ConfigCLIOverrides } from '../common/ipc';
@ -64,8 +64,12 @@ class TestServer {
class TestServerDispatcher implements TestServerInterface {
private _configLocation: ConfigLocation;
private _globalWatcher: Watcher;
private _testWatcher: Watcher;
private _watcher: Watcher;
private _watchedProjectDirs = new Set<string>();
private _ignoredProjectOutputs = new Set<string>();
private _watchedTestDependencies = new Set<string>();
private _testRun: { run: Promise<reporterTypes.FullResult['status']>, stop: ManualPromise<void> } | undefined;
readonly transport: Transport;
private _queue = Promise.resolve();
@ -86,17 +90,14 @@ class TestServerDispatcher implements TestServerInterface {
gracefullyProcessExitDoNotHang(0);
},
};
this._globalWatcher = new Watcher('deep', events => this._checkForChangedTestFiles(events));
this._testWatcher = new Watcher('flat', events => this._checkForChangedTestFiles(events));
this._watcher = new Watcher(events => {
const collector = new Set<string>();
events.forEach(f => collectAffectedTestFiles(f.file, collector));
this._dispatchEvent('testFilesChanged', { testFiles: [...collector] });
});
this._dispatchEvent = (method, params) => this.transport.sendEvent?.(method, params);
}
private _checkForChangedTestFiles(events: FSEvent[]) {
const collector = new Set<string>();
events.forEach(f => collectAffectedTestFiles(f.file, collector));
this._dispatchEvent('testFilesChanged', { testFiles: [...collector] });
}
private async _wireReporter(messageSink: (message: any) => void) {
return await createReporterForTestServer(this._serializer, messageSink);
}
@ -281,24 +282,28 @@ class TestServerDispatcher implements TestServerInterface {
await taskRunner.reporter.onEnd({ status });
await taskRunner.reporter.onExit();
const projectDirs = new Set<string>();
const projectOutputs = new Set<string>();
this._watchedProjectDirs = new Set();
this._ignoredProjectOutputs = new Set();
for (const p of config.projects) {
projectDirs.add(p.project.testDir);
projectOutputs.add(p.project.outputDir);
this._watchedProjectDirs.add(p.project.testDir);
this._ignoredProjectOutputs.add(p.project.outputDir);
}
const result = await resolveCtDirs(config);
if (result) {
projectDirs.add(result.templateDir);
projectOutputs.add(result.outDir);
this._watchedProjectDirs.add(result.templateDir);
this._ignoredProjectOutputs.add(result.outDir);
}
if (this._watchTestDirs)
this._globalWatcher.update([...projectDirs], [...projectOutputs], false);
this.updateWatcher(false);
return { report, status };
}
private updateWatcher(reportPending: boolean) {
this._watcher.update([...this._watchedProjectDirs, ...this._watchedTestDependencies], [...this._ignoredProjectOutputs], reportPending);
}
async runTests(params: Parameters<TestServerInterface['runTests']>[0]): ReturnType<TestServerInterface['runTests']> {
let result: Awaited<ReturnType<TestServerInterface['runTests']>> = { status: 'passed' };
this._queue = this._queue.then(async () => {
@ -366,12 +371,12 @@ class TestServerDispatcher implements TestServerInterface {
}
async watch(params: { fileNames: string[]; }) {
const files = new Set<string>();
this._watchedTestDependencies = new Set();
for (const fileName of params.fileNames) {
files.add(fileName);
dependenciesForTestFile(fileName).forEach(file => files.add(file));
this._watchedTestDependencies.add(fileName);
dependenciesForTestFile(fileName).forEach(file => this._watchedTestDependencies.add(file));
}
this._testWatcher.update([...files], [], true);
this.updateWatcher(true);
}
async findRelatedTestFiles(params: Parameters<TestServerInterface['findRelatedTestFiles']>[0]): ReturnType<TestServerInterface['findRelatedTestFiles']> {