Cypress is a next generation front end testing tool built for the modern web
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
System for defining custom component testing frameworks beyond the built-in React, Vue, and Angular support. This allows you to create component testing support for any JavaScript framework or custom component system.
Creates a definition for a custom third-party component framework that can be used with Cypress component testing.
/**
* Provides automatic code completion for Component Frameworks Definitions
* @param config - Component framework definition configuration
* @returns The configuration passed in parameter (for type safety)
*/
function defineComponentFramework(
config: ThirdPartyComponentFrameworkDefinition
): ThirdPartyComponentFrameworkDefinition;
interface ThirdPartyComponentFrameworkDefinition {
/** Unique identifier for the framework */
type: string;
/** Human-readable name of the framework */
name: string;
/** List of supported bundlers (webpack, vite, etc.) */
supportedBundlers: string[];
/** Functions to detect if this framework is being used in a project */
detectors: FrameworkDetector[];
/** Function to determine required dependencies for this framework */
dependencies: (installer: DependencyInstaller) => PackageManagerType[];
}Usage Examples:
// cypress.config.js
const { defineConfig, defineComponentFramework } = require('cypress');
const solidJsFramework = defineComponentFramework({
type: 'cypress-ct-solid-js',
name: 'Solid.js',
supportedBundlers: ['vite', 'webpack'],
detectors: [
{
file: 'package.json',
matcher: /solid-js/
}
],
dependencies: (installer) => [
installer.packageJson({
dependency: 'solid-js',
minVersion: '^1.0.0'
}),
installer.packageJson({
dependency: 'vite-plugin-solid',
minVersion: '^2.0.0'
})
]
});
module.exports = defineConfig({
component: {
devServer: solidJsFramework,
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}'
}
});Define how Cypress should detect when your custom framework is being used in a project.
interface FrameworkDetector {
/** File to check for framework presence */
file: string;
/** Pattern to match in the file content */
matcher: RegExp | string;
}
// Alternative detector interface for package.json dependencies
interface PackageJsonDetector {
file: 'package.json';
matcher: RegExp;
}
// Alternative detector interface for config files
interface ConfigFileDetector {
file: string;
matcher: (content: string) => boolean;
}Framework Detection Examples:
// Detect Svelte framework
const svelteDetectors = [
{
file: 'package.json',
matcher: /svelte/
},
{
file: 'svelte.config.js',
matcher: /export.*svelte/
}
];
// Detect Lit framework
const litDetectors = [
{
file: 'package.json',
matcher: /lit|@lit/
}
];
// Detect Stencil framework
const stencilDetectors = [
{
file: 'stencil.config.ts',
matcher: /stencil/
},
{
file: 'package.json',
matcher: /@stencil\/core/
}
];Define the dependencies required for your custom framework to work with Cypress component testing.
interface DependencyInstaller {
/** Specify a package.json dependency requirement */
packageJson(requirement: PackageRequirement): PackageManagerType;
/** Specify a custom installation script */
custom(script: string): PackageManagerType;
}
interface PackageRequirement {
/** Package name */
dependency: string;
/** Minimum version required */
minVersion?: string;
/** Whether this is a dev dependency */
dev?: boolean;
}
interface PackageManagerType {
/** Package manager type */
type: 'npm' | 'yarn' | 'pnpm';
/** Installation command */
command: string;
}Dependency Examples:
// Solid.js framework dependencies
const solidDependencies = (installer) => [
installer.packageJson({
dependency: 'solid-js',
minVersion: '^1.6.0'
}),
installer.packageJson({
dependency: 'vite-plugin-solid',
minVersion: '^2.5.0',
dev: true
}),
installer.packageJson({
dependency: '@cypress/mount-utils',
minVersion: '^1.0.0',
dev: true
})
];
// Lit framework dependencies
const litDependencies = (installer) => [
installer.packageJson({
dependency: 'lit',
minVersion: '^2.0.0'
}),
installer.packageJson({
dependency: '@web/dev-server-esbuild',
minVersion: '^0.3.0',
dev: true
})
];Here's a complete example of defining a custom framework for Solid.js:
// frameworks/solid.js
const { defineComponentFramework } = require('cypress');
module.exports = defineComponentFramework({
type: 'cypress-ct-solid-js',
name: 'Solid.js',
supportedBundlers: ['vite', 'webpack'],
detectors: [
{
file: 'package.json',
matcher: /solid-js/
},
{
file: 'vite.config.js',
matcher: /solidPlugin|vite-plugin-solid/
},
{
file: 'vite.config.ts',
matcher: /solidPlugin|vite-plugin-solid/
}
],
dependencies: (installer) => [
installer.packageJson({
dependency: 'solid-js',
minVersion: '^1.6.0'
}),
installer.packageJson({
dependency: 'vite-plugin-solid',
minVersion: '^2.5.0',
dev: true
}),
installer.packageJson({
dependency: '@cypress/mount-utils',
minVersion: '^1.0.0',
dev: true
})
]
});When creating a custom framework, you'll also need to implement a mount function:
// cypress/support/solid-mount.js
import { render } from 'solid-js/web';
import { getContainerEl, setupHooks } from '@cypress/mount-utils';
let dispose;
function cleanup() {
if (dispose) {
dispose();
dispose = null;
}
}
export function mount(component, options = {}) {
return cy.then(() => {
// Clean up previous mount
cleanup();
// Get the container element
const root = getContainerEl();
// Render the Solid component
dispose = render(() => component, root);
// Log the mount operation
if (options.log !== false) {
Cypress.log({
name: 'mount',
message: 'Solid.js component'
});
}
return cy.wrap({ component }).then(() => ({ component }));
});
}
// Set up cleanup hooks
setupHooks(cleanup);Once your custom framework is defined and the mount function is implemented:
// cypress/component/SolidButton.cy.js
import { mount } from '../support/solid-mount';
import Button from './Button'; // Solid.js component
describe('Solid Button', () => {
it('renders and responds to clicks', () => {
let clicked = false;
const handleClick = () => { clicked = true; };
mount(() => <Button onClick={handleClick}>Click me</Button>);
cy.contains('Click me').should('be.visible');
cy.contains('Click me').click().then(() => {
expect(clicked).to.be.true;
});
});
});Integrate your custom framework with Cypress configuration:
// cypress.config.js
const { defineConfig } = require('cypress');
const solidFramework = require('./frameworks/solid');
module.exports = defineConfig({
component: {
devServer: {
framework: solidFramework.type,
bundler: 'vite',
viteConfig: {
plugins: [solidPlugin()]
}
},
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
supportFile: 'cypress/support/component.js'
}
});For more sophisticated frameworks, you can implement additional features:
// cypress/support/solid-commands.js
Cypress.Commands.add('solidComponent', { prevSubject: true }, (subject) => {
// Custom assertions for Solid.js components
return cy.wrap(subject).should('exist');
});
// Usage
cy.get('[data-cy=my-component]').solidComponent();// cypress/support/solid-utils.js
export function createSignal(initialValue) {
// Utility functions specific to your framework
return { value: initialValue };
}
export function waitForReactivity() {
// Wait for framework's reactivity system to update
return cy.wait(0); // or more sophisticated waiting logic
}Test your custom framework implementation:
// cypress/component/framework-test.cy.js
import { mount } from '../support/solid-mount';
describe('Custom Framework Integration', () => {
it('mounts components correctly', () => {
const TestComponent = () => <div data-cy="test">Framework works!</div>;
mount(TestComponent);
cy.get('[data-cy=test]').should('contain', 'Framework works!');
});
it('handles props and state', () => {
const Counter = (props) => {
const [count, setCount] = createSignal(props.initial || 0);
return (
<div>
<span data-cy="count">{count()}</span>
<button data-cy="increment" onClick={() => setCount(c => c + 1)}>
+1
</button>
</div>
);
};
mount(() => <Counter initial={5} />);
cy.get('[data-cy=count]').should('contain', '5');
cy.get('[data-cy=increment]').click();
cy.get('[data-cy=count]').should('contain', '6');
});
});This custom framework system allows you to extend Cypress component testing to any JavaScript framework, providing the same powerful testing capabilities that are available for React, Vue, and Angular components.
Install with Tessl CLI
npx tessl i tessl/npm-cypress