{
  "doc": {
    "id": "app/component-testing/custom-frameworks",
    "title": "Custom Frameworks",
    "description": "Learn how to create a custom Framework Definition and Mount Adapter for your favorite library or framework.",
    "section": "app",
    "source_path": "/llm/markdown/app/component-testing/custom-frameworks.md",
    "version": "3cf5b86b3403f604bdf7f3e35025c3bc3865e02c",
    "updated_at": "2026-05-07T17:44:31.931Z",
    "headings": [
      {
        "id": "app/component-testing/custom-frameworks#custom-frameworks",
        "text": "Custom Frameworks",
        "level": 1
      },
      {
        "id": "app/component-testing/custom-frameworks#what-youll-learn",
        "text": "What you'll learn",
        "level": 5
      },
      {
        "id": "app/component-testing/custom-frameworks#concepts",
        "text": "Concepts",
        "level": 2
      },
      {
        "id": "app/component-testing/custom-frameworks#framework-definition",
        "text": "Framework Definition",
        "level": 2
      },
      {
        "id": "app/component-testing/custom-frameworks#mount-adapter",
        "text": "Mount Adapter",
        "level": 2
      },
      {
        "id": "app/component-testing/custom-frameworks#package-json",
        "text": "package.json",
        "level": 2
      },
      {
        "id": "app/component-testing/custom-frameworks#testing",
        "text": "Testing",
        "level": 2
      },
      {
        "id": "app/component-testing/custom-frameworks#publishing-on-npm",
        "text": "Publishing on npm",
        "level": 2
      },
      {
        "id": "app/component-testing/custom-frameworks#available-framework-definitions",
        "text": "Available Framework Definitions",
        "level": 2
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Custom Frameworks"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 5,
        "children": [
          {
            "type": "text",
            "value": "What you'll learn"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to customize Cypress to support your favorite framework"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to create a custom Framework Definition and Mount Adapter for your framework"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to test and publish your custom framework"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Cypress Component Testing includes "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/component-testing/get-started.md#Supported-Frameworks",
            "children": [
              {
                "type": "text",
                "value": "official support"
              }
            ]
          },
          {
            "type": "text",
            "value": " for many popular libraries and frameworks such as "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/component-testing/react/overview.md",
            "children": [
              {
                "type": "text",
                "value": "React"
              }
            ]
          },
          {
            "type": "text",
            "value": ", "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/component-testing/angular/overview.md",
            "children": [
              {
                "type": "text",
                "value": "Angular"
              }
            ]
          },
          {
            "type": "text",
            "value": ", and "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/component-testing/vue/overview.md",
            "children": [
              {
                "type": "text",
                "value": "Vue"
              }
            ]
          },
          {
            "type": "text",
            "value": ". All officially supported libraries feature a first class onboarding experience, where we detect and scaffold the correct files, and a framework-specific `mount` adapter to render your components. We call this collection of features a Framework Definition since it defines the requirements for a library or framework to work in Cypress."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If your favorite library isn't featured, don't worry - we expose the same API we use internally for the Cypress community to define their own Framework Definitions."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In this guide, you'll learn how to author a Framework Definition, which will enjoy the same polished onboarding experience as our officially supported frameworks."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Concepts"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "There are a few requirements for authoring a Framework Definition."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "#Framework-Definition",
                    "children": [
                      {
                        "type": "text",
                        "value": "Definition File"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " (we recommending naming this `definition.cjs`)"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "#Mount-Adapter",
                    "children": [
                      {
                        "type": "text",
                        "value": "Mount Adapter"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " (we recommending naming this `index.mjs`)"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "A "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "#packagejson",
                    "children": [
                      {
                        "type": "text",
                        "value": "`package.json`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " with the correct conventions"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The Definition is required when users configure Component Testing for the first time. The Mount adapter is used to render components when writing tests."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To simplify this process, we recommend starting development using "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-ct-definition-template",
            "children": [
              {
                "type": "text",
                "value": "our official template"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Framework Definition"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Below is a minimal Framework Definition. Note that `defineFrameworkDefinition` is purely for type safety, similar to `defineConfig` in `cypress.config`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "There is one important convention; the `type` key in `defineFrameworkDefinition` should match the name of your package on npm, and should be named using one of the following conventions:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress-ct-*`"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`@organization/cypress-ct-*`"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Some examples of valid names include:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress-ct-react-js`"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress-ct-svelte-testing`"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`@cypress/cypress-ct-react`"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`@angular/cypress-ct-angular`"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When configuring a project to use Component Testing, Cypress will load any dependencies following this naming convention from the project's `node_modules` and present them as framework options."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "A simple example of a Framework Definition for the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://www.solidjs.com/",
            "children": [
              {
                "type": "text",
                "value": "Solid.js"
              }
            ]
          },
          {
            "type": "text",
            "value": " library is shown below. We generally recommend naming this `definition.cjs`. In our "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-ct-definition-template",
            "children": [
              {
                "type": "text",
                "value": "official template"
              }
            ]
          },
          {
            "type": "text",
            "value": ", this file is at the root level of the package."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineFrameworkDefinition } = require('cypress')const solidDep = {  // Unique, semantic identifier.  type: 'solid-js',  // Human readable name.  name: 'Solid',  // Package name install from `npm`.  package: 'solid-js',  /**   * Similar to package, but can include a version or tag.   * Used during setup to generate an install command for users.   * Eg: `solid-js@next`   */  installer: 'solid-js',  // Human readable description.  description:    'A declarative, efficient, and flexible JavaScript library for building user interfaces.',  // Minimum supported version.  minVersion: '^1.6.0',}/** * Similar to above. Create an smooth, seamless setup experience * by ensuring the user has all the necessary dependencies. * @type {Cypress.CypressComponentDependency} */const solidVitePlugin = {  type: 'solid-js-vite-plugin',  name: 'Vite Plugin Solid',  package: 'vite-plugin-solid',  installer: 'vite-plugin-solid',  description: 'A simple integration to run solid-js with vite',  minVersion: '^1.6.0 || ^2.0.0',}/** * The actual definition. */module.exports = defineFrameworkDefinition({  /**   * This should match the `npm` package name.   * The convention required to ensure your Definition is processed   * by Cypress is `cypress-ct-*` for global packages, or   * `@org/cypress-ct-*` for organization level packages.   */  type: '@lmiller1990/cypress-ct-solid-js',  /**   * The label that shows up when configuring Component Testing   * for the first time.   */  name: 'Solid.js',  /**   * Supported bundlers. Can be \"webpack\" and/or \"vite\".   * In this example we only support Solid.js with Vite.   */  supportedBundlers: ['vite'],  /**   * Used by Cypress to automatically detect the correct Framework Definition   * based on the user's project.   * In this example, if a module matching `solidDep`   * is found in the user's project,   * Solid.js will automatically be selected when configuring Component Testing.   */  detectors: [solidDep],  /**   * Supply a set of dependencies a project should have to use this Framework Definition. The user will be prompted to install them if they are not found.   * Optionally, supply different dependencies based on the chosen bundler.   */  dependencies: (bundler) => {    return [solidDep, solidVitePlugin]  },  /**   * An SVG icon. Shown when configuring Component Testing for the first time.   * Optional, but good for branding your Framework Definition.   */  icon: `    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 166 155.3\"><path d=\"M163 35S110-4 69 5l-3 1c-6 2-11 5-14 9l-2 3-15 26 26 5c11 7 25 10 38 7l46 9 18-30z\" fill=\"#76b3e1\"/><linearGradient id=\"a\" gradientUnits=\"userSpaceOnUse\" x1=\"27.5\" y1=\"3\" x2=\"152\" y2=\"63.5\"><stop offset=\".1\" stop-color=\"#76b3e1\"/><stop offset=\".3\" stop-color=\"#dcf2fd\"/><stop offset=\"1\" stop-color=\"#76b3e1\"/></linearGradient><path d=\"M163 35S110-4 69 5l-3 1c-6 2-11 5-14 9l-2 3-15 26 26 5c11 7 25 10 38 7l46 9 18-30z\" opacity=\".3\" fill=\"url(#a)\"/><path d=\"M52 35l-4 1c-17 5-22 21-13 35 10 13 31 20 48 15l62-21S92 26 52 35z\" fill=\"#518ac8\"/><linearGradient id=\"b\" gradientUnits=\"userSpaceOnUse\" x1=\"95.8\" y1=\"32.6\" x2=\"74\" y2=\"105.2\"><stop offset=\"0\" stop-color=\"#76b3e1\"/><stop offset=\".5\" stop-color=\"#4377bb\"/><stop offset=\"1\" stop-color=\"#1f3b77\"/></linearGradient><path d=\"M52 35l-4 1c-17 5-22 21npm install https://cdn.cypress.io/beta/npm/12.6.0/darwin-arm64/feature/ct-public-api-ab820f062d313fbef51665bdd1d883c69d89b3be/cypress.tgz-13 35 10 13 31 20 48 15l62-21S92 26 52 35z\" opacity=\".3\" fill=\"url(#b)\"/><linearGradient id=\"c\" gradientUnits=\"userSpaceOnUse\" x1=\"18.4\" y1=\"64.2\" x2=\"144.3\" y2=\"149.8\"><stop offset=\"0\" stop-color=\"#315aa9\"/><stop offset=\".5\" stop-color=\"#518ac8\"/><stop offset=\"1\" stop-color=\"#315aa9\"/></linearGradient><path d=\"M134 80a45 45 0 00-48-15L24 85 4 120l112 19 20-36c4-7 3-15-2-23z\" fill=\"url(#c)\"/><linearGradient id=\"d\" gradientUnits=\"userSpaceOnUse\" x1=\"75.2\" y1=\"74.5\" x2=\"24.4\" y2=\"260.8\"><stop offset=\"0\" stop-color=\"#4377bb\"/><stop offset=\".5\" stop-color=\"#1a336b\"/><stop offset=\"1\" stop-color=\"#1a336b\"/></linearGradient><path d=\"M114 115a45 45 0 00-48-15L4 120s53 40 94 30l3-1c17-5 23-21 13-34z\" fill=\"url(#d)\"/></svg>  `,})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Our Framework Definition shows up in Cypress! It has the \"community\" label, indicating it's a third party definition."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We defined the `dependencies`, which are also correctly handled - we haven't installed them all, so Cypress is prompting us to do so:"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Mount Adapter"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The second part of defining a Framework Definition is the Mount Adapter. This is the function that renders the component in your tests using `cy.mount()`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "By default, Cypress will look for this as a `mount` function that is a named export from the package. This should be written in a `index.mjs` file. This example is for a "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://www.solidjs.com/",
            "children": [
              {
                "type": "text",
                "value": "Solid.js"
              }
            ]
          },
          {
            "type": "text",
            "value": " mount adapter:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { getContainerEl, setupHooks } from '@cypress/mount-utils'import { render } from 'solid-js/web'let disposefunction cleanup() {  dispose?.()}/** * @param {() => JSX.Element} - component to render */export function mount(component, options = {}) {  // Retrieve root DOM element that Cypress has prepared for this test  const root = getContainerEl()  dispose = render(() => component, root)  // Wait until next microtick to ensure any async render logic has executed  return cy.wait(0, { log: false }).then(() => {    if (options.log !== false) {      Cypress.log({        name: 'mount',        message: 'Mounted component',      })    }  })}// Cleanup between each testsetupHooks(cleanup)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This is different for each library, but the concept is the same - identify how to mount or render a component in your library, and implement it in a function named `mount` in `index.mjs`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When a user configures Component Testing with your Framework Definition we automatically configure a `cy.mount` command using your `mount` function in the Component Testing `supportFile`:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from '@lmiller1990/cypress-ct-solid-js'Cypress.Commands.add('mount', mount)"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "package.json"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The final thing you need is a correctly configured `package.json`. This example was created using "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-ct-definition-template",
            "children": [
              {
                "type": "text",
                "value": "our official template"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "There are two fields of note:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`name`: Your package name which must follow the `cypress-ct-*`/`@org/cypress-ct-*` convention"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`exports`: Object referencing the two files we created to comprise the Framework Definition. The `node` entry points to the Definition file, and the `default` entry points to the Mount Adapter:"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "{  \"name\": \"@lmiller1990/cypress-ct-solid-js\",  \"version\": \"0.0.4\",  \"description\": \"Example Framework Definition for Cypress and Solid.js\",  \"exports\": {    \"node\": \"./definition.cjs\",    \"default\": \"./index.mjs\"  },  \"files\": [    \"package.json\",    \"definition.cjs\",    \"index.mjs\"  ],  \"dependencies\": {    \"@cypress/mount-utils\": \"^4.0.0\"  },  \"devDependencies\": {    \"solid-js\": \"^1.6.0\"  },  \"peerDependencies\": {    \"solid-js\": \"^1.6.0\"    \"cypress\": \"^12.7.0\"  }}"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Testing"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you develop the Framework Definition file using TypeScript, for example by using "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-ct-definition-template",
            "children": [
              {
                "type": "text",
                "value": "our official template"
              }
            ]
          },
          {
            "type": "text",
            "value": ", as long as you don't have any compile time errors, everything should work as expected. If you do run into unexpected behavior, please "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress/issues",
            "children": [
              {
                "type": "text",
                "value": "file an issue"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Mount Adapters can be more complex to test. In general, we recommend testing them in the same way users consume them - using Cypress Component Testing. A minimal test suite for a simple Solid.js Mount Adapter can be found "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/lmiller1990/cypress-ct-solid-js/tree/main/example-project",
            "children": [
              {
                "type": "text",
                "value": "here"
              }
            ]
          },
          {
            "type": "text",
            "value": ". Alternatively, take a look at our official "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress/tree/develop/npm/react",
            "children": [
              {
                "type": "text",
                "value": "React"
              }
            ]
          },
          {
            "type": "text",
            "value": " and "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress/tree/develop/npm/angular",
            "children": [
              {
                "type": "text",
                "value": "Angular"
              }
            ]
          },
          {
            "type": "text",
            "value": " Mount Adapters, both of which have extensive test suites."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Publishing on npm"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "That's it! Publish your Framework Definition on npm and start using it."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Available Framework Definitions"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can find a list of available Framework Definitions "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/component-testing/get-started.md#Supported-Frameworks",
            "children": [
              {
                "type": "text",
                "value": "here"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you have created a Framework Definition we would be delighted to mention it in our documentation so other Cypress users on the same framework can find it. "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-documentation/blob/main/CONTRIBUTING.md",
            "children": [
              {
                "type": "text",
                "value": "Please submit a Pull Request"
              }
            ]
          },
          {
            "type": "text",
            "value": "!"
          }
        ]
      }
    ]
  },
  "token_estimate": 1865
}