DEV Community

Cover image for Cypress Boilerplate
Darko Riđić
Darko Riđić

Posted on • Edited on

Cypress Boilerplate

Github repo

Quickly generate new projects, and start coding immediately with an already pre-configured project. While using this boilerplate you and your team can focus more on coding, and less wory about configuration. This boilerplate is full of useful plugins already configured, and much more! Good luck!

If you like this article, don’t forget to click on that heart button to show your appreciation.

Template for one or multiple products.
cypress-boilerplate saves you from all of the trouble when configuring.

Installation

npx @optimumqa/cypress-boilerplate my-cypress-app
Enter fullscreen mode Exit fullscreen mode

Install dependencies:

cd my-cypress-app
npm install
Enter fullscreen mode Exit fullscreen mode

Add a new product

product refers to your project.

$ npm run add-project
Enter fullscreen mode Exit fullscreen mode

It will ask you for your:

  • product name
  • baseUrl

The command from above would create the following structure and inject new scripts in package.json.

- configs/
  - foo/
    default.ts
- fixtures/
  - foo/
    - routes.json
    - users.json
- e2e/
  - foo/
    - default.cy.ts
- support/
  - foo/
    - commands.ts
    - index.ts
Enter fullscreen mode Exit fullscreen mode

Run

$ npm run foo-staging
Enter fullscreen mode Exit fullscreen mode

You can see that the generator has injected 3 default scripts into package.json

{
  ...
  "scripts": {
    "foo-staging": "cypress run -e product=foo,env=staging",
    "foo-release": "cypress run -e product=foo,env=release",
    "foo-production": "cypress run -e product=foo,env=production",
  }
  ...
}
Enter fullscreen mode Exit fullscreen mode

When run, it will specify only the test files in cypress/e2e/foo.

How we use it

Follow all the steps above then:

Add a new command to scripts

// package.json
{
  ...
  "scripts": {
    ...
    "test": "npm run foo-staging"
    ...
  }
  ...
}
Enter fullscreen mode Exit fullscreen mode

Then simply run:

$ npm test
Enter fullscreen mode Exit fullscreen mode

When tests is finished, your reports will be generated also. Keeps the command line clean and simple.

Structure explained

configs/product

Here you can have different cypress configs per product. Which config is used is determined by the type argument while running cypress in the CLI.

For example if we add the following command to our package.json

{
  ...
  "foo-staging-daily: cypress open --env product=foo,env=staging,type=daily"
  ...
}
Enter fullscreen mode Exit fullscreen mode

and then run it

$ npm run foo-staging-daily
Enter fullscreen mode Exit fullscreen mode

then configs/foo/daily.ts is used and merged with ./cypress.config.ts.

This gives you an extra level of configuration for different test types where you need to target only specific spec files, all while keeping the package.json scripts part clean

fixtures/foo/routes.json

Here is the place to define your baseUrl and other URLs per each environment.

Preview

{
  "staging": {
    "baseUrl": "https://example.com",
    "admin": "https://example.com/admin"
  },
  "release": {
    "baseUrl": "https://example.com"
  },
  "production": {
    "baseUrl": "https://example.com"
  }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

import { routes } from '../../../support/helpers'

describe('Should visit admin', () => {
  it('Visit', () => {
    cy.visit(routes.admin)
  })
})
Enter fullscreen mode Exit fullscreen mode

routes will always return routes from current set environment, which in this case, is staging.

fixtures/foo/users.json

Here is the place to define your primary, seconday, etc. users list for your tests.

By default, you can see

Preview

{
  "staging": {
    "primary": {
      "name": "User name",
      "email": "test@cypress_template_test.com",
      "password": "user password"
    }
  },
  "release": {
    "primary": {
      "name": "User name",
      "email": "test@cypress_template_test.com",
      "password": "user password"
    }
  },
  "production": {
    "primary": {
      "name": "User name",
      "email": "test@cypress_template_test.com",
      "password": "user password"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

import { routes, users } from '../../../support/helpers'

describe('Should visit admin', () => {
  it('Visit and log in with primary user', () => {
    cy.visit(routes.admin)
    cy.logIn(users.primary)
  })
})
Enter fullscreen mode Exit fullscreen mode

users will always return users from current set environment, which in this case, is staging.

cypress/e2e/foo/

Here are your spec files as usual.

cypress/support/e2e/foo/

Your projects commands are here.

If you have multiple projects, keep in mind that you will have access only to the commands from the project you've run in the CLI.
This is done so that commands from multiple products do not override each other if they're the same name.

cypress/support/e2e/commands.ts

Here are your global/shared commands.

cypress/support/helpers.ts

You can import current users or routes from this file. It will give you the routes from the specified product and from the specified environment.

import { users, routes } from '../../helpers'

describe('Example usage of helpers module', () => {
  it('Should log current main user and baseUrl', () => {
    cy.log(users.main) // object
    cy.log(users.main.email) // random email generated every time you run Cypress
    // This ensures your concurent jobs wont use the same user every run
  })
})
Enter fullscreen mode Exit fullscreen mode

You can also import other stuff like this:

import { product, env, type, baseUrl, getFixture, getUrl } from '../../helpers'

describe('Example usage of helpers module', () => {
  it('Should do something', () => {
    // These below helpers are pre-configured to look for directoris depending on your current setup/run
    // Below example shows what would be logged if you've run the project with "npm run foo-staging"
    // And you've set the baseUrl to "http://foo.example.com"

    cy.log(product) // foo
    cy.log(env) // staging
    cy.log(type) // default
    cy.log(baseUrl) // http://foo.example.com
    cy.log(getFixture('foo')) // JSON Object
    cy.log(getUrl('baseUrl')) // http://foo.example.com
  })
})
Enter fullscreen mode Exit fullscreen mode

Local config

Create a file cypress.local.ts inside ./cypress/configs/. Your local config will be then merged with the global config and product config.

Here you can place your overrides.

If you need to temporarily disable this file, just rename it.
Example: cypress.local.ts -> cypress.local-tmp.ts

It is ignored by GIT.

Project flow

Adding new custom commands to package.json

Arguments

name type default description
product String Product name
env String staging Any environment you support
type String default Used for targeting specific config inside configs/product/. Daily, weekly, smoke, you name it.

Follow the command naming convention

  • product+environment+type

Here are some example commands:

{
  "scripts": {
    "foo-staging": "cypress run -e product=foo,env=staging",
    "foo-staging.open": "cypress open -e product=foo,env=staging",
    "foo-master-daily": "cypress run -e product=foo,env=master,type=daily",
    "foo-staging-weekly": "cypress run -e product=foo,env=staging,type=weekly"
  }
}
Enter fullscreen mode Exit fullscreen mode

There is no need to specify specPattern. If they're are not specified they'll be automatically set(depending on the product from CLI).

Reporting

Two reporters are enabled

Mochawesome

Location: cypress/reports/mochawesome

Reports will only be generated with the command:

npm run mocha.combine-reports
npm run mocha.generate-reports
Enter fullscreen mode Exit fullscreen mode

Make sure to clear previous reports before running your tests with the command:

npm run mocha.clear
Enter fullscreen mode Exit fullscreen mode

Allure

Location: allure-results

Report will be created automatically if you have allure: true inside your cypress.config.js.

To view the latest report you can run

npm run allure.start
Enter fullscreen mode Exit fullscreen mode

To preserve the history trend, run:

Be careful not deleting the allure-results/history when preserving it.

npm run allure.report
npm run allure.history
Enter fullscreen mode Exit fullscreen mode

Then start the allure

npm run allure.start
Enter fullscreen mode Exit fullscreen mode

What's inside?

Here is a list of plugins and libraries that come with this boilerplate:

Prettier

Keeps the code clean and same style for everyone working on the project.
Make sure you have the prettier extension installed in VSCode for it to work.

Modify the config in ./.prettierrc

cypress-iframe

See the documentation.

You can use the commands like described here

cypress-localstorage-commands

See documentation.

Example usage:

beforeEach(() => {
  cy.restoreLocalStorage()
  cy.visit('/')
})

afterEach(() => {
  cy.saveLocalStorage()
})
Enter fullscreen mode Exit fullscreen mode

Benefits of using this boilerplate project

No configuring the project

With a clean, intuitive, and same project structure we keep everyone consistent across all projects.

Renovate

Delete renovate.json if you don't use it.

Hygen part

Hygen is used to generate templates and inject code into your structure when running npm run add-project.

You can modify the generator in ./_templates/project/with-prompt/.

If you need to change default environments, they're declared in these files:

  • ./_templates/project/with-prompt/fixtureRoutes.ejs.t
  • ./_templates/project/with-prompt/fixtureUsers.ejs.t
  • ./_templates/project/with-prompt/package.ejs.t

Summary

  • Project is dynamically set up based on the three arguments above
  • If you specify baseURL or specPattern in configs, they will not be overwritten.
  • We can't imagine to work without this template, and hope you will feel the same :)

🤝 Contributing

Contributions, issues and feature requests are welcome.

Feel free to check issues page if you want to contribute.

Show your support

Please ⭐️ this repository if this project helped you!

📝 License

This project is MIT licensed.

Hope this will help and save your time in the next projects!

Thank you for reading and feel free to add suggestions down bellow :)

Top comments (5)

Collapse
 
ktxxt profile image
Darko Riđić

We have a new documentation website for the Cypress Boilerplate.

Feel free to check it out and leave any feedback or suggestions! Thank you!

Collapse
 
royfrank profile image
RoyFrank

great concept you are sharing its really helpful for you . ادعية لجلب الحبيب

Collapse
 
jason_neb profile image
nebster • Edited

Thanks for sharing this great template. I am getting a config issue in trying to open the runner through npx cypress open command- here is the stack trace. What did I miss?

press\my-cypress-app\cypress\configs\undefined\default.ts'
Require stack:
- C:\Git\zcore-cypress\my-cypress-app\node_modules\@optimumqa\cypress-setup-utilities\src\plugins\Config.js
- C:\Git\zcore-cypress\my-cypress-app\node_modules\@optimumqa\cypress-setup-utilities\src\index.js
- C:\Git\zcore-cypress\my-cypress-app\cypress\plugins\index.ts
- C:\Git\zcore-cypress\my-cypress-app\cypress.config.ts
- C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@packages\server\lib\plugins\child\run_require_async_child.js
- C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@packages\server\lib\plugins\child\require_async_child.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1077:15)
    at Function.Module._resolveFilename (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\tsconfig-paths\lib\register.js:85:40)
    at Function.Module._resolveFilename.sharedData.moduleResolveFilenameHook.installedValue [as _resolveFilename] (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@cspotcode\source-map-support\source-map-support.js:811:30)
    at Function.Module._load (node:internal/modules/cjs/loader:922:27)
    at Module.require (node:internal/modules/cjs/loader:1143:19)
    at require (node:internal/modules/cjs/helpers:119:18)
    at Config.init (C:\Git\zcore-cypress\my-cypress-app\node_modules\@optimumqa\cypress-setup-utilities\src\plugins\Config.js:43:24)
    at new Config (C:\Git\zcore-cypress\my-cypress-app\node_modules\@optimumqa\cypress-setup-utilities\src\plugins\Config.js:20:10)
    at C:\Git\zcore-cypress\my-cypress-app\node_modules\@optimumqa\cypress-setup-utilities\src\index.js:9:25
    at Array.forEach ()
    at optimumqa_plugin (C:\Git\zcore-cypress\my-cypress-app\node_modules\@optimumqa\cypress-setup-utilities\src\index.js:6:11)
    at exports.default (C:\Git\zcore-cypress\my-cypress-app\cypress\plugins\index.ts:5:57)
    at setupNodeEvents (C:\Git\zcore-cypress\my-cypress-app\cypress.config.ts:24:23)
    at C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@packages\server\lib\plugins\child\run_plugins.js:122:14
    at tryCatcher (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\bluebird\js\release\util.js:16:23)
    at Function.Promise.attempt.Promise.try (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\bluebird\js\release\method.js:39:29)
    at RunPlugins.load (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@packages\server\lib\plugins\child\run_plugins.js:119:9)
    at RunPlugins.runSetupNodeEvents (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@packages\server\lib\plugins\child\run_plugins.js:59:17)
    at EventEmitter. (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@packages\server\lib\plugins\child\run_require_async_child.js:185:22)
    at EventEmitter.emit (node:events:517:28)
    at EventEmitter.emit (node:domain:489:12)
    at process. (C:\Users\ntesema\AppData\Local\Cypress\Cache\13.2.0\Cypress\resources\app\node_modules\@packages\server\lib\plugins\util.js:33:22)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ktxxt profile image
Darko Riđić

Sorry for the late answer :/

Did you run npm run add-project before running cypress?

Collapse
 
ntesema profile image
Nebyu

Thank you , I fixed the issue and tests were running inn in GitOps till few days. I think there is some change in boilerplate and Its not stable for me now would you send me your contact info. Here is mine. Nebyutesema@gmail.com