Skip to content

Commit

Permalink
Add support for CT using Vite as bundler
Browse files Browse the repository at this point in the history
This currently relies on a small patch of @cypress/vite-dev-server [1].
Hopefully this patch can be submitted and accepted upstream.

This fixes #698 [2].

[2] https://github.com/cypress-io/cypress/tree/develop/npm/vite-dev-server
[1] #698
  • Loading branch information
badeball committed May 10, 2023
1 parent a25d389 commit 94a02c3
Show file tree
Hide file tree
Showing 16 changed files with 151 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file.

- Add support for (testing) type-specific configuration, fixes [#700](https://github.com/badeball/cypress-cucumber-preprocessor/issues/700).

- Add support for component testing using Vite as bundler, fixes [#698](https://github.com/badeball/cypress-cucumber-preprocessor/issues/698).

## v17.0.0

Breaking changes:
Expand Down
1 change: 1 addition & 0 deletions examples/ct-vite-react-ts/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
32 changes: 32 additions & 0 deletions examples/ct-vite-react-ts/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { defineConfig } from "cypress";
import { devServer } from "@cypress/vite-dev-server";
import react from "@vitejs/plugin-react";
import { viteCommonjs } from "@originjs/vite-plugin-commonjs";
import { addCucumberPreprocessorPlugin } from "@badeball/cypress-cucumber-preprocessor";
import { createRollupPlugin } from "@badeball/cypress-cucumber-preprocessor/rollup";

export default defineConfig({
component: {
specPattern: "**/*.feature",
devServer(devServerConfig) {
return devServer({
...devServerConfig,
framework: "react",
viteConfig: {
plugins: [
react(),
createRollupPlugin(devServerConfig.cypressConfig),
viteCommonjs(),
],
},
});
},
async setupNodeEvents(on, config) {
// This is required for the preprocessor to be able to generate JSON reports after each run, and more.
await addCucumberPreprocessorPlugin(on, config);

// Make sure to return the config object as it might have been modified by the plugin.
return config;
},
},
});
4 changes: 4 additions & 0 deletions examples/ct-vite-react-ts/cypress/component/App.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Feature: App
Scenario: render
Given I render the component
Then I should see the text "Hello world!"
15 changes: 15 additions & 0 deletions examples/ct-vite-react-ts/cypress/component/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as preprocessor from "@badeball/cypress-cucumber-preprocessor";

import { mount } from "cypress/react18"

import App from "../../src/App";

const { Given, Then } = preprocessor

Given("I render the component", () => {
mount(<App />);
});

Then("I should see the text {string}", (text: string) => {
cy.contains(text).should("exist");
});
14 changes: 14 additions & 0 deletions examples/ct-vite-react-ts/cypress/support/component-index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>

</head>
<body>

<div data-cy-root></div>
</body>
</html>
Empty file.
16 changes: 16 additions & 0 deletions examples/ct-vite-react-ts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"scripts": {
"postinstall": "patch-package"
},
"dependencies": {
"@badeball/cypress-cucumber-preprocessor": "latest",
"@cypress/vite-dev-server": "latest",
"@originjs/vite-plugin-commonjs": "latest",
"@vitejs/plugin-react": "latest",
"cypress": "latest",
"patch-package": "latest",
"react": "latest",
"react-dom": "latest",
"typescript": "latest"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/node_modules/@cypress/vite-dev-server/client/initCypressTests.js b/node_modules/@cypress/vite-dev-server/client/initCypressTests.js
index f0602c1..d7f05a0 100644
--- a/node_modules/@cypress/vite-dev-server/client/initCypressTests.js
+++ b/node_modules/@cypress/vite-dev-server/client/initCypressTests.js
@@ -36,7 +36,7 @@ if (supportFile) {
// So we use the "@fs" bit to load the test file using its absolute path
// Normalize path to not include a leading slash (different on Win32 vs Unix)
const normalizedAbsolutePath = CypressInstance.spec.absolute.replace(/^\//, '')
-const testFileAbsolutePathRoute = `${devServerPublicPathRoute}/@fs/${normalizedAbsolutePath}`
+const testFileAbsolutePathRoute = `${devServerPublicPathRoute}/@fs/${normalizedAbsolutePath}?import`

/* Spec file import logic */
// We need a slash before /src/my-spec.js, this does not happen by default.
3 changes: 3 additions & 0 deletions examples/ct-vite-react-ts/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function App () {
return <p>Hello world!</p>
}
7 changes: 7 additions & 0 deletions examples/ct-vite-react-ts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"esModuleInterop": true,
"moduleResolution": "node16",
"jsx": "react-jsx"
}
}
6 changes: 5 additions & 1 deletion examples/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ The examples illustrates using each bundler in each language flavor.

## Component testing

Only a single example illustrating component testing exist so far.
Component testing works with both Webpack and Vite[^1] as a bundler.

| | CJS | ESM | TS |
|-----------------|------------------------|------------------------|-----------------------------|
| React + Webpack | | | [Link](ct-webpack-react-ts) |
| React + Vite | | | [Link](ct-vite-react-ts) |

[patch-package]: https://github.com/ds300/patch-package
[^1]: Using Vite requires patching `@cypress/vite-dev-server`, something which is easily achieved using [`patch-package`][patch-package] as the example illustrates.
21 changes: 21 additions & 0 deletions lib/bundler-utils/rollup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Plugin } from "rollup";

import { ICypressConfiguration } from "@badeball/cypress-configuration";

import { compile } from "../template";

export function createRollupPlugin(config: ICypressConfiguration): Plugin {
return {
name: "transform-feature",
async transform(src: string, id: string) {
if (/\.feature$/.test(id)) {
return {
code: await compile(config, src, id),
map: null,
};
}
},
};
}

export default createRollupPlugin;
10 changes: 10 additions & 0 deletions lib/helpers/prepare-registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Registry, assignRegistry, freeRegistry } from "../registry";

const registry = new Registry(false);

assignRegistry(registry);

export function getAndFreeRegistry() {
freeRegistry();
return registry;
}
18 changes: 7 additions & 11 deletions lib/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export async function compile(

const createTestsPath = prepareLibPath("browser-runtime");

const registryPath = prepareLibPath("registry");
const prepareRegistryPath = prepareLibPath("helpers", "prepare-registry");

const ensureRelativeToProjectRoot = (path: string) =>
ensureIsRelative(configuration.projectRoot, path);
Expand All @@ -152,17 +152,13 @@ export async function compile(
];

return `
const { getAndFreeRegistry } = require(${prepareRegistryPath});
const { default: createTests } = require(${createTestsPath});
const { withRegistry } = require(${registryPath});
const registry = withRegistry(
false,
() => {
${stepDefinitionPaths
.map((stepDefintion) => `require(${stringify(stepDefintion)});`)
.join("\n ")}
}
);
${stepDefinitionPaths
.map((stepDefintion) => `require(${stringify(stepDefintion)});`)
.join("\n ")}
const registry = getAndFreeRegistry();
registry.finalize();
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"pngjs": "^7.0.0",
"prettier": "^2.8.8",
"recast": "^0.22.0",
"rollup": "^3.21.5",
"stream-buffers": "^3.0.2",
"strip-ansi": "^6.0.1",
"strip-indent": "^3.0.0",
Expand Down

0 comments on commit 94a02c3

Please sign in to comment.