218 lines
5.8 KiB
JavaScript
218 lines
5.8 KiB
JavaScript
![]() |
/* eslint-disable @typescript-eslint/no-var-requires */
|
||
|
|
||
|
const { parseGrep, shouldTestRun } = require("./utils");
|
||
|
const version = 10;
|
||
|
const debug = require("debug")("cypress-grep");
|
||
|
debug.log = console.info.bind(console);
|
||
|
|
||
|
// preserve the real "it" function
|
||
|
const _it = it;
|
||
|
const _describe = describe;
|
||
|
|
||
|
/**
|
||
|
* Wraps the "it" and "describe" functions that support tags.
|
||
|
* @see https://github.com/cypress-io/cypress-grep
|
||
|
*/
|
||
|
function cypressGrep() {
|
||
|
/** @type {string} Part of the test title go grep */
|
||
|
let grep = Cypress.env("grep");
|
||
|
if (grep) {
|
||
|
grep = String(grep).trim();
|
||
|
}
|
||
|
|
||
|
/** @type {string} Raw tags to grep string */
|
||
|
const grepTags = Cypress.env("grepTags") || Cypress.env("grep-tags");
|
||
|
|
||
|
const burnSpecified =
|
||
|
Cypress.env("grepBurn") || Cypress.env("grep-burn") || Cypress.env("burn");
|
||
|
|
||
|
const grepUntagged =
|
||
|
Cypress.env("grepUntagged") || Cypress.env("grep-untagged");
|
||
|
|
||
|
if (!grep && !grepTags && !burnSpecified && !grepUntagged) {
|
||
|
// nothing to do, the user has no specified the "grep" string
|
||
|
debug("Nothing to grep, version %s", version);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/** @type {number} Number of times to repeat each running test */
|
||
|
const grepBurn =
|
||
|
Cypress.env("grepBurn") ||
|
||
|
Cypress.env("grep-burn") ||
|
||
|
Cypress.env("burn") ||
|
||
|
1;
|
||
|
|
||
|
/** @type {boolean} Omit filtered tests completely */
|
||
|
const omitFiltered =
|
||
|
Cypress.env("grepOmitFiltered") || Cypress.env("grep-omit-filtered");
|
||
|
|
||
|
debug("grep %o", { grep, grepTags, grepBurn, omitFiltered, version });
|
||
|
if (!Cypress._.isInteger(grepBurn) || grepBurn < 1) {
|
||
|
throw new Error(`Invalid grep burn value: ${grepBurn}`);
|
||
|
}
|
||
|
|
||
|
const parsedGrep = parseGrep(grep, grepTags);
|
||
|
debug("parsed grep %o", parsedGrep);
|
||
|
|
||
|
// prevent multiple registrations
|
||
|
// https://github.com/cypress-io/cypress-grep/issues/59
|
||
|
if (it.name === "itGrep") {
|
||
|
debug("already registered cypress-grep");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
it = function itGrep(name, options, callback) {
|
||
|
if (typeof options === "function") {
|
||
|
// the test has format it('...', cb)
|
||
|
callback = options;
|
||
|
options = {};
|
||
|
}
|
||
|
|
||
|
if (!callback) {
|
||
|
// the pending test by itself
|
||
|
return _it(name, options);
|
||
|
}
|
||
|
|
||
|
let configTags = options && options.tags;
|
||
|
if (typeof configTags === "string") {
|
||
|
configTags = [configTags];
|
||
|
}
|
||
|
|
||
|
const nameToGrep = suiteStack
|
||
|
.map(item => item.name)
|
||
|
.concat(name)
|
||
|
.join(" ");
|
||
|
const tagsToGrep = suiteStack
|
||
|
.flatMap(item => item.tags)
|
||
|
.concat(configTags)
|
||
|
.filter(Boolean);
|
||
|
|
||
|
const shouldRun = shouldTestRun(
|
||
|
parsedGrep,
|
||
|
nameToGrep,
|
||
|
tagsToGrep,
|
||
|
grepUntagged
|
||
|
);
|
||
|
|
||
|
if (tagsToGrep && tagsToGrep.length) {
|
||
|
debug(
|
||
|
'should test "%s" with tags %s run? %s',
|
||
|
name,
|
||
|
tagsToGrep.join(","),
|
||
|
shouldRun
|
||
|
);
|
||
|
} else {
|
||
|
debug('should test "%s" run? %s', nameToGrep, shouldRun);
|
||
|
}
|
||
|
|
||
|
if (shouldRun) {
|
||
|
if (grepBurn > 1) {
|
||
|
// repeat the same test to make sure it is solid
|
||
|
return Cypress._.times(grepBurn, k => {
|
||
|
const fullName = `${name}: burning ${k + 1} of ${grepBurn}`;
|
||
|
_it(fullName, options, callback);
|
||
|
});
|
||
|
}
|
||
|
return _it(name, options, callback);
|
||
|
}
|
||
|
|
||
|
if (omitFiltered) {
|
||
|
// omit the filtered tests completely
|
||
|
return;
|
||
|
} else {
|
||
|
// skip tests without grep string in their names
|
||
|
return _it.skip(name, options, callback);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// list of "describe" suites for the current test
|
||
|
// when we encounter a new suite, we push it to the stack
|
||
|
// when the "describe" function exits, we pop it
|
||
|
// Thus a test can look up the tags from its parent suites
|
||
|
const suiteStack = [];
|
||
|
|
||
|
describe = function describeGrep(name, options, callback) {
|
||
|
if (typeof options === "function") {
|
||
|
// the block has format describe('...', cb)
|
||
|
callback = options;
|
||
|
options = {};
|
||
|
}
|
||
|
|
||
|
const stackItem = { name };
|
||
|
suiteStack.push(stackItem);
|
||
|
|
||
|
if (!callback) {
|
||
|
// the pending suite by itself
|
||
|
const result = _describe(name, options);
|
||
|
suiteStack.pop();
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
let configTags = options && options.tags;
|
||
|
if (typeof configTags === "string") {
|
||
|
configTags = [configTags];
|
||
|
}
|
||
|
|
||
|
if (!configTags || !configTags.length) {
|
||
|
// if the describe suite does not have explicit tags
|
||
|
// move on, since the tests inside can have their own tags
|
||
|
_describe(name, options, callback);
|
||
|
suiteStack.pop();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// when looking at the suite of the tests, I found
|
||
|
// that using the name is quickly becoming very confusing
|
||
|
// and thus we need to use the explicit tags
|
||
|
stackItem.tags = configTags;
|
||
|
_describe(name, options, callback);
|
||
|
suiteStack.pop();
|
||
|
|
||
|
return;
|
||
|
};
|
||
|
|
||
|
// overwrite "context" which is an alias to "describe"
|
||
|
context = describe;
|
||
|
|
||
|
// overwrite "specify" which is an alias to "it"
|
||
|
specify = it;
|
||
|
|
||
|
// keep the ".skip", ".only" methods the same as before
|
||
|
it.skip = _it.skip;
|
||
|
it.only = _it.only;
|
||
|
// preserve "it.each" method if found
|
||
|
// https://github.com/cypress-io/cypress-grep/issues/72
|
||
|
if (typeof _it.each === "function") {
|
||
|
it.each = _it.each;
|
||
|
}
|
||
|
|
||
|
describe.skip = _describe.skip;
|
||
|
describe.only = _describe.only;
|
||
|
if (typeof _describe.each === "function") {
|
||
|
describe.each = _describe.each;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function restartTests() {
|
||
|
setTimeout(() => {
|
||
|
window.top.document.querySelector(".reporter .restart").click();
|
||
|
}, 0);
|
||
|
}
|
||
|
|
||
|
if (!Cypress.grep) {
|
||
|
Cypress.grep = function grep(grep, tags, burn) {
|
||
|
Cypress.env("grep", grep);
|
||
|
Cypress.env("grepTags", tags);
|
||
|
Cypress.env("grepBurn", burn);
|
||
|
// remove any aliased values
|
||
|
Cypress.env("grep-tags", null);
|
||
|
Cypress.env("grep-burn", null);
|
||
|
Cypress.env("burn", null);
|
||
|
|
||
|
debug('set new grep to "%o" restarting tests', { grep, tags, burn });
|
||
|
restartTests();
|
||
|
};
|
||
|
}
|
||
|
|
||
|
module.exports = cypressGrep;
|