Component Testing Configuration
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
}
- cypress.config.js
- cypress.config.ts
const { defineConfig } = require('cypress')
module.exports = defineConfig({
component: {
async devServer({ specs, cypressConfig, devServerEvents }) {
const { port, close } = await startDevServer(
specs,
cypressConfig,
devServerEvents
)
return {
port,
close,
}
},
},
})
import { defineConfig } from 'cypress'
export default defineConfig({
component: {
async devServer({
specs,
cypressConfig,
devServerEvents,
}: DevServerOptions) {
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.