mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
93 lines
4.0 KiB
TypeScript
93 lines
4.0 KiB
TypeScript
![]() |
/**
|
||
|
* Copyright (c) Microsoft Corporation.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
import fs from 'fs';
|
||
|
import path from 'path';
|
||
|
import type { FullConfigInternal } from 'playwright/lib/common/config';
|
||
|
import { ConfigLoader, resolveConfigFile } from 'playwright/lib/common/configLoader';
|
||
|
import { Watcher } from 'playwright/lib/fsWatcher';
|
||
|
import { restartWithExperimentalTsEsm } from 'playwright/lib/program';
|
||
|
import { Runner } from 'playwright/lib/runner/runner';
|
||
|
import type { PluginContext } from 'rollup';
|
||
|
import { source as injectedSource } from './generated/indexSource';
|
||
|
import { createConfig, populateComponentsFromTests, resolveDirs, transformIndexFile } from './viteUtils';
|
||
|
import type { ComponentRegistry } from './viteUtils';
|
||
|
|
||
|
export async function runDevServer(configFile: string, registerSourceFile: string, frameworkPluginFactory: () => Promise<any>) {
|
||
|
const configFileOrDirectory = configFile ? path.resolve(process.cwd(), configFile) : process.cwd();
|
||
|
const resolvedConfigFile = resolveConfigFile(configFileOrDirectory);
|
||
|
if (restartWithExperimentalTsEsm(resolvedConfigFile))
|
||
|
return;
|
||
|
|
||
|
const configLoader = new ConfigLoader();
|
||
|
let config: FullConfigInternal;
|
||
|
if (resolvedConfigFile)
|
||
|
config = await configLoader.loadConfigFile(resolvedConfigFile);
|
||
|
else
|
||
|
config = await configLoader.loadEmptyConfig(configFileOrDirectory);
|
||
|
|
||
|
const runner = new Runner(config);
|
||
|
await runner.loadAllTests(true);
|
||
|
const componentRegistry: ComponentRegistry = new Map();
|
||
|
await populateComponentsFromTests(componentRegistry);
|
||
|
|
||
|
const dirs = resolveDirs(config.configDir, config.config);
|
||
|
const registerSource = injectedSource + '\n' + await fs.promises.readFile(registerSourceFile, 'utf-8');
|
||
|
const viteConfig = await createConfig(dirs, config.config, frameworkPluginFactory, false);
|
||
|
viteConfig.plugins.push({
|
||
|
name: 'playwright:component-index',
|
||
|
|
||
|
async transform(this: PluginContext, content: string, id: string) {
|
||
|
return transformIndexFile(id, content, dirs.templateDir, registerSource, componentRegistry);
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const { createServer } = await import('vite');
|
||
|
const devServer = await createServer(viteConfig);
|
||
|
await devServer.listen();
|
||
|
const protocol = viteConfig.server.https ? 'https:' : 'http:';
|
||
|
// eslint-disable-next-line no-console
|
||
|
console.log(`Test Server listening on ${protocol}//${viteConfig.server.host || 'localhost'}:${viteConfig.server.port}`);
|
||
|
|
||
|
const projectDirs = new Set<string>();
|
||
|
const projectOutputs = new Set<string>();
|
||
|
for (const p of config.projects) {
|
||
|
projectDirs.add(p.project.testDir);
|
||
|
projectOutputs.add(p.project.outputDir);
|
||
|
}
|
||
|
|
||
|
const globalWatcher = new Watcher('deep', async () => {
|
||
|
const registry: ComponentRegistry = new Map();
|
||
|
await populateComponentsFromTests(registry);
|
||
|
// compare componentRegistry to registry key sets.
|
||
|
if (componentRegistry.size === registry.size && [...componentRegistry.keys()].every(k => registry.has(k)))
|
||
|
return;
|
||
|
|
||
|
// eslint-disable-next-line no-console
|
||
|
console.log('List of components changed');
|
||
|
componentRegistry.clear();
|
||
|
for (const [k, v] of registry)
|
||
|
componentRegistry.set(k, v);
|
||
|
|
||
|
const id = path.join(dirs.templateDir, 'index');
|
||
|
const modules = [...devServer.moduleGraph.urlToModuleMap.values()];
|
||
|
const rootModule = modules.find(m => m.file?.startsWith(id + '.ts') || m.file?.startsWith(id + '.js'));
|
||
|
if (rootModule)
|
||
|
devServer.moduleGraph.onFileChange(rootModule.file!);
|
||
|
});
|
||
|
globalWatcher.update([...projectDirs], [...projectOutputs], false);
|
||
|
}
|