Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
444 views
in Technique[技术] by (71.8m points)

javascript - How to run unit tests with Cypress.io?

I have been using Cypress.io to run end-to-end tests. Recently, I have been using it to run unit tests as well. However, I have some issues with some small helper functions that I have built with NodeJs.

I have a create file called utils.spec.js in the following path <my-project-name>/cypress/integration/unit/utils.spec.js & I have written the following tests:

File: utils.spec.js

// Path to utils.js which holds the regular helper javascript functions
import { getTicketBySummary } from '../../path/to/utils';

describe('Unit Tests for utils.js methods', () => {
  /**
   * Array of objects mocking Tickets Object response
   */
  const mockedTickets = {
    data: {
      issues: [
        {
          id: 1,
          key: 'ticket-key-1',
          fields: {
            summary: 'This is ticket number 1',
          },
        },
        {
          id: 2,
          key: 'ticket-key-2',
          fields: {
            summary: 'This is ticket number 2',
          },
        },
      ],
    },
  };

  const mockedEmptyTicketsArray = [];
  it('returns an array containing a found ticket summary', () => {
    expect(
      getTicketBySummary({
        issues: mockedTickets,
        summaryTitle: 'This is ticket number 1',
      })
    ).eq(mockedTickets.data.issues[0]);
  });
  it('returns an empty array, when no ticket summary was found', () => {
    expect(
      getTicketBySummary({
        issues: mockedTickets,
        summaryTitle: 'This is ticket number 3',
      })
    ).eq(mockedEmptyTicketsArray);
  });
});

File: utils.js

const fs = require('fs');

/**
 * Method to search for an issue by its title
 * Saving the search result into an array
 *
 * @param {array} - issues - an array containing all existing issues.
 * @param {string} - summaryTitle - used to search an issue by title
 */
const getTicketBySummary = ({ issues, summaryTitle }) =>
  issues.data.issues.filter(issueData => {
    return issueData.fields.summary === summaryTitle ? issueData : null;
  });

/**
 * Method to read a file's content
 * Returns another string representing the file's content
 *
 * @param {str} - file - a passed string representing the file's path
 */
const readFileContent = file => {
  return new Promise((resolve, reject) => {
    fs.readFile(file, 'utf8', (err, data) => {
      if (err) return reject(err);
      return resolve(data);
    });
  });
};

module.exports = { getTicketBySummary, readFileContent };

However, when I run the command: npx cypress run --spec="cypress/integration/unit/utils.spec.js" --env mode=terminal, I get the error:Module not found: Error: Can't resolve 'fs'.

Also if I commented out the fs import & its function I get another error:

1) An uncaught error was detected outside of a test:
     TypeError: The following error originated from your test code, not from Cypress.

  > Cannot assign to read only property 'exports' of object '#<Object>'

When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.

Cypress could not associate this error to any specific test.

We dynamically generated a new test to display this failure

I did some digging on the second error & it seems the describe method is defined. How can I fix both issues? What am I doing wrong?

question from:https://stackoverflow.com/questions/66055150/how-to-run-unit-tests-with-cypress-io

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use tasks to execute node code. In your plugins.js create the task with the arguments you need, returning the calculated value:

  on('task', {
    // you can define and require this elsewhere
    getTicketBySummary('getTicketBySummary', { issues, summaryTitle }) {
      return issues.data.issues.filter(...);
    }
  })
}

In your test, execute the task via cy.task:

  it('returns an array containing a found ticket summary', () => {
    cy.task('getTicketBySummary', {
      issues: mockedTickets,
      summaryTitle: 'This is ticket number 1',
    }).then(result => {
      expect(result).eq(mockedTickets.data.issues[0]);
    })
  });

That being said, getTicketBySummary looks like a pure function that doesn't depend on fs. Perhaps separate helper functions that actually need node as that could avoid need cy.task. If you want to be able to import commonjs (require) via ES6 import/export you would usually need to setup build tools (babel/rollup/etc) to be able to resolve that effectively.

Hopefully that helps!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...