问题
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?
回答1:
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!
来源:https://stackoverflow.com/questions/66055150/how-to-run-unit-tests-with-cypress-io