DEV Community 👩‍💻👨‍💻

Juan Pablo
Juan Pablo

Posted on

Extended "run all specs" feature for Cypress 10

Required node packages:

rimraf

As probably all Cypress fans know already, Cypress 10 was shipped without the "run all tests" feature due to "technical limitations" (they are apparently working on a solution, and here is where you can read all about why they removed it, what are the technical limitations, and all the complaints about it too)

I was, as most of us, in desperate need for the ability to run all tests from the test runner interface, and I stumbled upon this great post from Gleb Bahmutov regarding a workaround/hack to be able to do it until Cypress decides what to do.

The solution that Gleb proposes involves manually importing every new spec to the "all.spec.cy/ts", and then run "all.spec.cy/ts" in Cypress (read the post for more details).

So I saw an opportunity to adapt this to my particular need. In my scenario, I had many tests grouped by folder/feature under e2e. And I knew many people were eventually going to be involved in adding tests to each folder, and that at some point someone was going to forget to add the import statement, and we were going to be in trouble. Then I thought "What if... I can create a script that will, everytime Cypress is executed, navigate the e2e folder, find every spec, and then create the all.spec.cy/ts with the corresponding imports?" And then I went even crazyer "What if I can create a "groupspec" for each folder I have, in case I want to run all tests for a given feature"...

And this is what I came up with

  1. Create the "generateGroups.js" file in your root
/* eslint-disable */
const fs = require('fs');
const folders = fs.readdirSync('cypress/e2e', { withFileTypes: true })

/* Create and populate all.cy.ts with all existing tests imports */
writeFile("all")

addAllImports("all")

/* Create and populate a "group" cy.ts file per folder with corresponding imports */
folders.filter(dirent => dirent.isDirectory())
  .map(dirent => dirent.name).forEach(folder => {
    writeFile(folder);
    addGroupImports(folder)
  })

function addGroupImports(spec) {
  readImports(spec, spec);
}

/* Add all imports to all.cy.ts file */
function addAllImports(spec) {
  folders.filter(dirent => dirent.isDirectory())
    .map(dirent => dirent.name).forEach(folder => {
      readImports("all", folder);
    })
}

/* Build the "import" commands and insert it
in each corresponding cy.ts file */

function readImports(spec, folder) {
  let files = fs.readdirSync(`cypress/e2e/${folder}`)
  let newImport = "";
  files.forEach(file => {
    newImport = `import "./${folder}/${file}";\n`;
    appendImport(spec, newImport);
  })
}

/* Insert the import lines in each corresponding file */
function appendImport(fileName, newImport) {
  fs.appendFile(`cypress/e2e/${fileName}.cy.ts`, newImport, function (err) {
    if (err) throw err;
  })
}

/* Create group cy.ts file */
function writeFile(file) {
  fs.writeFile(`cypress/e2e/${file}.cy.ts`, "", function (err) {
    if (err) throw err;
    console.log(`${file} Group Spec file was created successfully.`);
  })
}

Enter fullscreen mode Exit fullscreen mode

And then this would be your scripts section in the package.json file:

"scripts": {
    "open": "npm run groups && cypress open --browser chrome --e2e",
    "test": "npm run cleangroups && cypress run --e2e",           
    "groups": "node generateGroups.js",
    "cleangroups": "npx rimraf cypress/e2e/*.cy.ts",
  },
Enter fullscreen mode Exit fullscreen mode

where:

"open" will create the group files and then open cypress, where you will have a .cy.ts file for each folder, and the all.cy.ts file

"test" will use rimraf (a node package that will allow you to delete files/folder cross platform) to delete all group files, so when you run "cypress run" it will run all tests (if you don't delete the group files, all tests will be executed twice)

"groups" executes generateGroups to create the group cy.ts files

"cleangroups" to delete the files when needed

This is how my folder structure looks normally (without group files)

Folder structure prior to running the script

This is how it looks when I run "npm run open"

Folder structure after the script ran, new group files created

And this is Cypress:

Cypress with all folders and group files

This is what my all.cy.ts file looks like:

all.cy.ts file

Again, I love the flexibility I have to adapt stuff to fit my needs... :D

Hope this is useful for anyone... Have a great day and...

Happy testing!

Top comments (0)

🌚 Life is too short to browse without dark mode