or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

angular-testing.mdcli-integration.mdconfiguration.mdcustom-frameworks.mdindex.mdinteractive-testing.mdprogrammatic-execution.mdreact-testing.mdvue-testing.md
tile.json

custom-frameworks.mddocs/

Custom Component Frameworks

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.

Capabilities

Define Component Framework

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}'
  }
});

Framework Detection

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/
  }
];

Dependency Management

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
  })
];

Complete Custom Framework Example

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
    })
  ]
});

Mount Function Implementation

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);

Usage in Tests

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;
    });
  });
});

Framework Configuration Integration

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'
  }
});

Advanced Framework Features

For more sophisticated frameworks, you can implement additional features:

Custom Assertions

// 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();

Framework-Specific Utilities

// 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
}

Testing the Custom Framework

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.