Cypress Hosts Option

How to test an HTTPS site locally using Cypress and a custom domain name.

Problem: you have a local HTTPS site (for example using Create-React-App) and want to access it locally using https://<domain name>:3000. How do you do it? Here is my solution that probably the simplest way of accessing domains using self-signed certificates. You can find the source code in the repo bahmutov/cypress-local-https.

Local self-signed certificate

Let's say I want to test my own (non-existent) domain "my-secure-site". I will create a self-signed certificate on Mac (other operating systems have their own quirks)

1
2
3
4
$ brew install mkcert
$ mkcert -install
$ mkdir .cert
$ mkcert -key-file ./.cert/key.pem -cert-file ./.cert/cert.pem "my-secure-site"

Now I have two text files in the folder .cert

1
2
3
4
5
6
7
8
$ cat .cert/key.pem
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFA...

$ cat .cert/perm.pem
-----BEGIN CERTIFICATE-----
MIIEVzCCAr+gAwIBAgIQL
...

The application

I have scaffolded a new React application using Create-React-App v5. I have set the following options in the .env.development file.

.env.development
1
2
3
4
5
HTTPS=true
BROWSER=none
# load the local certificate
SSL_CRT_FILE=./.cert/cert.pem
SSL_KEY_FILE=./.cert/key.pem

Let's start the local app

1
2
3
4
5
6
7
8
$ npm start

Compiled successfully!

You can now view cypress-local-https in the browser.

Local: https://localhost:3000
On Your Network: https://10.0.0.187:3000

If we try to access the local site at https://localhost:3000 we get a problem: our self-signed certificate is for domain "my-secure-site", not for "localhost".

HTTPS localhost error

If we try to access https://my-secure-site:3000 the browser does not know what to do. The browser asks the network stack to look up the IP address for domain name "my-secure-site", which hits the DNS server, which returns "UNKNOWN" error. We are stuck.

Hosts option

Typically at this point, you would modify your local hosts file and add the following line to it to map the name "my-secure-site" to the local IP address 127.0.0.1:

1
2
# my local testing for cypress-hosts-option
127.0.0.1 my-secure-site

You might need to clear the local network DNS cache, restart the browser. Who knows.

There is an easier way if all you plan to do is to run end-to-end tests against the local application. You can specify the local domain mapping using the (absolutely undocumented) hosts Cypress configuration option:

cypress.json
1
2
3
4
5
6
{
"baseUrl": "https://my-secure-site:3000",
"hosts": {
"my-secure-site": "127.0.0.1"
}
}

Note: the "hosts" resolution only maps the domain name to an IP address, it does nothing to the port number.

Start Cypress and enjoy the cy.visit('/') correctly loading your local HTTPS site.

Visit the local HTTPS site from the test

Other uses for locally mapped hosts in Cypress: tricking single sing-on flows (see the cypress-example-recipes repo) and blocking resources from some domains.