Skip to main content

Component Testing Configuration

info
What you'll learn​
  • How to configure Cypress for component testing
  • How to use a custom index file
  • How to use a custom dev server
  • How to set a custom spec pattern for component tests

When you launch Cypress for the first time in a project, the app will automatically guide you through setup and configuration. You don't need to do anything additional to get started.

Refer to the "Framework Configuration" guide in each UI framework's overview guide for a list of supported development servers and how they are configured.

Below are more advanced configuration options you can customize to fit your project.

Custom Index File​

By default, Cypress renders your components into an HTML file located at cypress/support/component-index.html.

The index file allows you to add in global assets, such as styles, fonts, and external scripts.

You can provide an alternative path to the file using the indexHtmlFile option in the component config options:

{
component: {
devServer,
indexHtmlFile: '/custom/path/to/component-index.html'
}
}

Custom Dev Server​

A custom function can be passed into the devServer option, which allows the use of build systems not provided by Cypress out of the box. These can be from the Cypress community, preview builds not included with the app, or a custom one you create.

The function's signature takes in an object with the following properties as its only parameter and needs to resolve an object containing the port of your dev server and a callback to shut it down.

interface DevServerOptions {
specs: Cypress.Spec[]
cypressConfig: Cypress.PluginConfigOptions
devServerEvents: NodeJS.EventEmitter
}
const { defineConfig } = require('cypress')

module.exports = defineConfig({
component: {
async devServer({ specs, cypressConfig, devServerEvents }) {
const { port, close } = await startDevServer(
specs,
cypressConfig,
devServerEvents
)

return {
port,
close,
}
},
},
})

Any requests triggered during a test using the devServerPublicPathRoute as defined in the cypressConfig will be forwarded to your server. Cypress will trigger a request for [devServerPublicPathRoute]/index.html when a test is started. Your server needs to reply with the html-file referenced in cypressConfig.indexHtmlFile and inject a script to load the support files and the actual test.

function createServer(cypressConfig, bundleDir, port = 1234) {
const app = express()

// read kickstart script - see below for an example
const clientScript = readFileSync(
path.join(__dirname, './client-script.js'),
'utf8'
)

app.get(
cypressConfig.devServerPublicPathRoute + '/index.html',
async (_req, res) => {
// read custom index.html file
const html = await fs.readFile(
path.join(cypressConfig.repoRoot, cypressConfig.indexHtmlFile),
{ encoding: 'utf8' }
)

// inject kickstart-script
const output = html.replace(
'</head>',
`<script type="module">${clientScript}</script></head>`
)
res.send(output)
}
)

// you need to establish some url-to-path-mapping, if your bundler outputs
// the full directory structure you can map this one to one
app.use(cypressConfig.devServerPublicPathRoute, express.static(bundleDir))

app.listen(port)
}

For a real-world example, you can refer to this loader used by the Vite Dev Server.

The client script must retrieve information on the currently active test from the Cypress instance of the parent frame and load the corresponding bundle. If a support file is defined, it should be injected at the top of your test bundle or loaded before the test script.

const CypressInstance = (window.Cypress = parent.Cypress)
const devServerPublicPathRoute = CypressInstance.config(
'devServerPublicPathRoute'
)

let importPromise = Promise.resolve()

// If you do not bundle your support file along with the tests,
// you need to add a separate import statement for the support file.
const supportFilePath = CypressInstance.config('supportFile')
if (supportFilePath) {
const relative = supportFilePath.replace(
CypressInstance.config('projectRoot'),
''
)
importPromise = importPromise.then(
() => import(`${devServerPublicPathRoute}${relative}`)
)
}

// load the spec - you can extend the load function to also load css
const { relative } = CypressInstance.spec
importPromise = importPromise.then(
() => import(`${devServerPublicPathRoute}/${relative}`)
)

// trigger loading the imports
CypressInstance.onSpecWindow(window, importPromise)

// then start the test process
CypressInstance.action('app:window:before:load', window)

For a more complete example you can check out the kickstart script used in the vite-devserver.

The devServerEvents event emitter should be used to notify cypress about finished builds by emitting a dev-server:compile:success event and to listen for the dev-server:specs:changed event that will notify you about changed entry points.

Spec Pattern for Component Tests​

By default, Cypress looks for spec files anywhere in your project with an extension of .cy.js, .cy.jsx, .cy.ts, or .cy.tsx. However, you can change this behavior for component tests with a custom specPattern value. In the following example, we've configured Cypress to look for spec files with those same extensions, but only in the src folder or any of its subdirectories.

{
component: {
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}'
}
}

Additional Config​

For more information on all the available configuration options, see the configuration reference.