Skip to content

Commit

Permalink
fix(testing): prevent loop w/ Cypress watch & Vite processor (#16099)
Browse files Browse the repository at this point in the history
(cherry picked from commit 8b4e5f6)
  • Loading branch information
barbados-clemens authored and FrozenPandaz committed Apr 11, 2023
1 parent ac44887 commit f960776
Showing 1 changed file with 70 additions and 42 deletions.
112 changes: 70 additions & 42 deletions packages/cypress/src/plugins/preprocessor-vite.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,65 @@
// Adapted from: https://github.com/mammadataei/cypress-vite
/**
* https://github.com/mammadataei/cypress-vite
*
* MIT License
*
* Copyright (c) 2022 Mohammad Ataei
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**/

import * as path from 'path';
import { dirname, basename, extname } from 'path';
import type { RollupOutput, RollupWatcher, WatcherOptions } from 'rollup';
import type { InlineConfig } from 'vite';

type CypressPreprocessor = (
file: Record<string, any>
) => string | Promise<string>;

type BuildResult = RollupWatcher | RollupOutput | RollupOutput[];

const cache = new Map<string, string>();

/**
* Cypress preprocessor for running e2e tests using vite.
*
* @param {string} userConfigPath
* @example
* setupNodeEvents(on) {
* on(
* 'file:preprocessor',
* vitePreprocessor(path.resolve(__dirname, './vite.config.ts')),
* )
* },
* Use Vite as a file preprocess for Cypress test files.
* This preprocessor shouldn't be used directly.
* Instead, use the nxE2EPreset(__filename, { bundler: 'vite' }) function instead.
*/
function vitePreprocessor(userConfigPath?: string): CypressPreprocessor {
return async (file) => {
const { outputPath, filePath, shouldWatch } = file;

const fileName = path.basename(outputPath);
const filenameWithoutExtension = path.basename(
outputPath,
path.extname(outputPath)
);
if (cache.has(filePath)) {
return cache.get(filePath);
}

const fileName = basename(outputPath);
const filenameWithoutExtension = basename(outputPath, extname(outputPath));

const defaultConfig = {
const defaultConfig: InlineConfig = {
logLevel: 'silent',
define: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
},
build: {
emptyOutDir: false,
minify: false,
outDir: path.dirname(outputPath),
outDir: dirname(outputPath),
sourcemap: true,
write: true,
watch: getWatcherConfig(shouldWatch),
Expand All @@ -49,41 +71,47 @@ function vitePreprocessor(userConfigPath?: string): CypressPreprocessor {
},
},
};

cache.set(filePath, outputPath);

const { build } = require('vite');

const watcher = await build({
const watcher = (await build({
configFile: userConfigPath,
...defaultConfig,
});
})) as BuildResult;

if (shouldWatch && isWatcher(watcher)) {
watcher.on('event', (event) => {
if (event.code === 'END') {
file.emit('rerun');
}
return new Promise((resolve, reject) => {
if (shouldWatch && isWatcher(watcher)) {
watcher.on('event', (event) => {
if (event.code === 'END') {
resolve(outputPath);
file.emit('rerun');
}

if (event.code === 'ERROR') {
console.error(event);
}
});
if (event.code === 'ERROR') {
console.error(event);
reject(new Error(event.error.message));
}
});

file.on('close', () => {
watcher.close();
});
}

return outputPath;
file.on('close', () => {
cache.delete(filePath);
watcher.close();
});
} else {
resolve(outputPath);
}
});
};
}

function getWatcherConfig(shouldWatch: boolean): WatcherOptions | null {
return shouldWatch ? {} : null;
function isWatcher(maybeWatcher: any): maybeWatcher is RollupWatcher {
return maybeWatcher.on !== undefined;
}

type BuildResult = RollupWatcher | RollupOutput | RollupOutput[];

function isWatcher(watcher: BuildResult): watcher is RollupWatcher {
return (watcher as RollupWatcher).on !== undefined;
function getWatcherConfig(shouldWatch: boolean): WatcherOptions | null {
return shouldWatch ? {} : null;
}

export default vitePreprocessor;

0 comments on commit f960776

Please sign in to comment.