cypress: Cypress.spec is incorrect when running all specs, should contain actual current spec

Current behavior:

The contents of Cypress.spec are incorrect when I click on “Run all specs”.

It now contains:

{
  absolute: "__all",
  name: "All Specs",
  relative: "__all"
}

I use Cypress.spec in my cypress-plugin-snapshots plugin to determine snapshot filename. I found a very hard work around by using a preprocessor to store the latest processed file. But this breaks other stuff. It would be very useful if Cypress.spec would contain the actual current test.

Desired behavior:

It should contain the details of the spec that is running. Even when you clicked on “Run all specs”.

For example:

{
  name: 'filter.spec.js',
  relative: 'cypress/integration/filter.spec.js',
  absolute: '/Users/janelane/Dev/web-app/cypress/integration/filter.spec.js',
}

Steps to reproduce: (app code and test code)

Put code below in a Spec and see contents from Cypress.spec when running with “Run all tests” and by running test directly.

console.log(Cypress.spec);

Versions

All versions that have Cypress.spec.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 67
  • Comments: 19 (4 by maintainers)

Most upvoted comments

Cypress is great, but I wonder why snapshot testing looks so abandoned. The plugin is not maintained (e.g. https://github.com/meinaart/cypress-plugin-snapshots/issues/186) and Cypress itself contains this bug. I see a workaround, but why it cannot be fixed on Cypress or the plugin side? Two years passed.

I understand, that probably most developers or do not do snapshot testing, or use Jest. But jest + Vue setup is not easy and in any case, I don’t need yet another library (moreover, better to use a real browser instead of NodeJS). Because Cypress is awesome. Say, in my case I also want to grab a snapshot after some interaction.

Any updates? Not everyone can use the workaround because some people use 3rd party plugins instead of a custom internal plugin.

I am also having this issue and would like a solution. The workarounds are nice but it would be nicer to not have to use them.

👋 I’ve been battling with this issue too. I came up with a workaround, extending upon @bahmutov’s work in https://github.com/meinaart/cypress-plugin-snapshots/issues/10#issuecomment-514459554

In my case, I was copying the integration folders to another location anyway so I modified the file to include a fix for the spec:

const esprima = require('esprima');
const escodegen = require('escodegen');

/**
 * Workaround for incorrect Spec being set in `All Specs`.
 * @see https://github.com/cypress-io/cypress/issues/3090
 *
 * Parses all specs and inserts a before block in each describe block.
 * The before block sets the correct spec file which will be used in all
 * cases. To ensure consistency, we do this every time, even when not using
 * `All Specs`.
 *
 * @param {String} fileContents - Contents of spec file
 * @returns {String} - New spec file with added before block
 */
module.exports = (fileContents) => {
  const beforeBlock = esprima.parseScript(`
    before(() => {
      const path = require('path');
      const relative = __filename.substr(1);
      const integrationFolder = Cypress.config('integrationFolder');
      const absolute = path.join(Cypress.config('projectRoot'), __filename);
      const name = absolute.replace(integrationFolder + '/', '');

      Cypress.spec = { absolute, name, relative };
    });
  `).body[0];

  const parsed = esprima.parseScript(fileContents);

  const parsedFileWithInsert = {
    ...parsed,
    ...parsed.body.map((block) => {
      if (block.expression.callee.name === 'describe') {
        // eslint-disable-next-line no-param-reassign
        block.expression.arguments[1].body.body = [
          beforeBlock,
          ...block.expression.arguments[1].body.body,
        ];
      }
      return block;
    }),
  };

  return escodegen.generate(parsedFileWithInsert);
};

A little hacky, but works for my needs whilst we wait on this issue being fixed. Hope this saves someone the headache I had 😅

It seems we need to move to Playwright since Cypress plugins are usually not maintained

Cypress is great, but I wonder why snapshot testing looks so abandoned. The plugin is not maintained (e.g. meinaart/cypress-plugin-snapshots#186) and Cypress itself contains this bug. I see a workaround, but why it cannot be fixed on Cypress or the plugin side? Two years passed.

I understand, that probably most developers or do not do snapshot testing, or use Jest. But jest + Vue setup is not easy and in any case, I don’t need yet another library (moreover, better to use a real browser instead of NodeJS). Because Cypress is awesome. Say, in my case I also want to grab a snapshot after some interaction.

Any updates on this issue?

This solution works for me universally with TypeScript:

support/snapshotPatch.ts:

import { basename } from 'path';

declare global {
  // eslint-disable-next-line @typescript-eslint/no-namespace
  namespace Cypress {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    interface Chainable<Subject> {
      /**
       * Patch cypress-plugin-snapshots
       *
       * @returns {void}
       */
      fixCypressSpec(): void;
    }
  }
}

Cypress.Commands.add('fixCypressSpec', function () {
  const { absoluteFile, relativeFile } = this.test.invocationDetails;
  Cypress.spec = {
    ...Cypress.spec,
    absolute: absoluteFile,
    name: basename(absoluteFile),
    relative: relativeFile,
  };
});

support/index.ts:

import './support/snapshotPatch.ts';

beforeEach(() => {
  cy.fixCypressSpec();
});