cypress-rspack-dev-server
Version:
Launches Rspack Dev Server for Component Testing
109 lines (108 loc) • 5.04 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CypressCTRspackPlugin = exports.normalizeError = void 0;
const tslib_1 = require("tslib");
const isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
const path_1 = tslib_1.__importDefault(require("path"));
const debug_1 = tslib_1.__importDefault(require("debug"));
const debug = (0, debug_1.default)('cypress-rspack-dev-server:rspackPlugin');
const normalizeError = (error) => {
return typeof error === 'string' ? error : error.message;
};
exports.normalizeError = normalizeError;
/**
* A rspack compatible Cypress Component Testing Plugin
*
* @internal
*/
class CypressCTRspackPlugin {
constructor(options) {
this.files = [];
this.compilation = null;
this.addLoaderContext = (loaderContext) => {
;
loaderContext._cypress = {
files: this.files,
projectRoot: this.projectRoot,
supportFile: this.supportFile,
indexHtmlFile: this.indexHtmlFile,
};
};
this.beforeCompile = async (_compilationParams, callback) => {
if (!this.compilation) {
callback();
return;
}
// Ensure we don't try to load files that have been removed from the file system
// but have not yet been detected by the onSpecsChange handler
const foundFiles = await Promise.all(this.files.map(async (file) => {
try {
const exists = await fs_extra_1.default.pathExists(file.absolute);
return exists ? file : null;
}
catch (e) {
return null;
}
}));
this.files = foundFiles.filter((file) => file !== null);
callback();
};
/*
* `rspack --watch` watches the existing specs and their dependencies for changes.
* When new specs are created, we need to trigger a recompilation to add the new specs
* as dependencies. This hook informs rspack that `component-index.html` has been "updated on disk",
* causing a recompilation (and pulling the new specs in as dependencies). We use the component
* index file because we know that it will be there since the project is using Component Testing.
*
* We were using `browser.js` before to cause a recompilation but we ran into an
* issue with MacOS Ventura that will not allow us to write to files inside of our application bundle.
*
* See https://github.com/cypress-io/cypress/issues/24398
*/
this.onSpecsChange = async (specs) => {
var _a;
if (!this.compilation || (0, isEqual_1.default)(specs.specs, this.files)) {
return;
}
this.files = specs.specs;
const inputFileSystem = this.compilation.inputFileSystem;
// TODO: don't use a sync fs method here
const utimesSync = (_a = inputFileSystem.fileSystem.utimesSync) !== null && _a !== void 0 ? _a : fs_extra_1.default.utimesSync;
utimesSync(path_1.default.join(this.projectRoot, this.indexHtmlFile), new Date(), new Date());
};
/**
* The rspack compiler generates a new `compilation` each time it compiles, so
* we have to apply hooks to it fresh each time
*
* @param compilation `RspackCompilation`
*/
this.addCompilationHooks = (compilation) => {
this.compilation = compilation;
// still use legacy `webpack` here since in version 0.x.x does not have rspack
const compiler = ('rspack' in this.compilation.compiler
? this.compilation.compiler.rspack
: this.compilation.compiler.webpack);
const loader = compiler.NormalModule.getCompilationHooks(compilation).loader;
loader.tap('CypressCTPlugin', this.addLoaderContext);
};
this.files = options.files;
this.supportFile = options.supportFile;
this.projectRoot = options.projectRoot;
this.devServerEvents = options.devServerEvents;
this.indexHtmlFile = options.indexHtmlFile;
}
/**
* The plugin's entrypoint, called once by rspack when the compiler is initialized.
*/
apply(compiler) {
const _compiler = compiler;
this.devServerEvents.on('dev-server:specs:changed', this.onSpecsChange);
_compiler.hooks.beforeCompile.tapAsync('CypressCTPlugin', this.beforeCompile);
_compiler.hooks.compilation.tap('CypressCTPlugin', (compilation) => this.addCompilationHooks(compilation));
_compiler.hooks.done.tap('CypressCTPlugin', () => {
this.devServerEvents.emit('dev-server:compile:success');
});
}
}
exports.CypressCTRspackPlugin = CypressCTRspackPlugin;