@mmisty/cypress-grep
Version:
Filters tests by tags/title using substring or regular expressions (can find dynamic tags)
189 lines (188 loc) • 8.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupSelectTests = exports.prepareTestTitle = exports.origins = void 0;
const functions_1 = require("../utils/functions");
const envVars_1 = require("../common/envVars");
const logs_1 = require("../common/logs");
const register_1 = require("@mmisty/cypress-tags/register");
const tags_1 = require("@mmisty/cypress-tags/utils/tags");
// todo rewrite
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const origins = () => ({
originIt: it,
originItOnly: it.only,
originItSkip: it.skip,
originDescribe: describe,
originOnly: describe.only,
originSkip: describe.skip,
});
exports.origins = origins;
// search by infoToo
const tagsSearchLine = (allTags) => {
const tagsLine = (tags) => tags.map(t => { var _a, _b; return (_b = t.tag + ((_a = t.info) === null || _a === void 0 ? void 0 : _a.map(x => x).join(''))) !== null && _b !== void 0 ? _b : ''; }).join(' ');
return allTags.length > 0 ? ` ${tagsLine(allTags)}` : '';
};
const prepareTestTitle = (test) => {
if (!test) {
return 'null';
}
return `${(0, tags_1.removeTagsFromTitle)(test.fullTitle())}${tagsSearchLine(test.tags || [])}`.replace(/\s\s*/g, ' ');
};
exports.prepareTestTitle = prepareTestTitle;
function filterTests(testRoot, suiteRoot, regexp, isPrerun, settings, onFilteredTest, onExcludedTest) {
// Remove filtered tests and their parent suites
suiteRoot.eachTest((test) => {
const isEqualTitleWithTags = (t1, t2) => {
const t1Full = (0, exports.prepareTestTitle)(t1);
const t2Full = (0, exports.prepareTestTitle)(t2);
return t1Full === t2Full;
};
// when root test we filter suites again, so we don't need to filter other tests than the root
if (testRoot && !isEqualTitleWithTags(testRoot, test)) {
return;
}
const fullTitleWithTags = (0, exports.prepareTestTitle)(test);
if (regexp.test(fullTitleWithTags)) {
onFilteredTest(test);
if (!isPrerun) {
return;
}
}
else {
onExcludedTest(test);
}
// Remove not matched test
if (test.parent) {
if (!isPrerun && settings.showExcludedTests) {
test.parent.tests.forEach(t => {
if (isEqualTitleWithTags(t, test)) {
t.pending = true;
}
});
}
else {
test.parent.tests = test.parent.tests.filter(t => !isEqualTitleWithTags(t, test));
}
}
// Remove empty parent suites recursively
let suite = test.parent;
while (suite && suite.tests.length === 0 && suite.suites.length === 0) {
if (suite.parent) {
suite.parent.suites = suite.parent.suites.filter(t => !isEqualTitleWithTags(t, suite));
}
suite = suite.parent;
}
});
}
const createOnExcluded = (isPrerun, list) => (test) => {
var _a;
list.push({ match: false, filteredTitle: (_a = (0, exports.prepareTestTitle)(test)) !== null && _a !== void 0 ? _a : '' });
};
const createOnFiltered = (isPrerun, list) => (test) => {
var _a, _b, _c;
if (!isPrerun) {
list.push({ match: true, filteredTitle: (_a = (0, exports.prepareTestTitle)(test)) !== null && _a !== void 0 ? _a : '' });
return;
}
// titlePath has the title path generated by concatenating the parent's title path with the title.
// 0 - is '' - root suite that is being created implicitly, 1 is what we need
// 1 will contain path to spec file
const filePath = (_b = test.titlePath()[1]) === null || _b === void 0 ? void 0 : _b.replace(/\/\/+/g, '/');
list.push({
match: true,
filteredTitle: (_c = (0, exports.prepareTestTitle)(test)) !== null && _c !== void 0 ? _c : '',
filePath,
tags: test.tags,
title: (0, tags_1.removeTagsFromTitle)(test.title),
});
};
const createFilterSuiteTests = (settings, isPrerun, onCount) =>
/**
*
* @param regexp
* @param filtered
* @param suite
* @param test - test when it is root
*/
(regexp, filtered, suite, test) => {
filterTests(test, suite, regexp, isPrerun, settings, createOnFiltered(isPrerun, filtered), createOnExcluded(isPrerun, filtered));
const count = (0, functions_1.uniq)(filtered.filter(t => t.match).map(t => t.filteredTitle)).length;
onCount(count);
if (settings.debugLog) {
const filteredUniq = (0, functions_1.uniq)(filtered.map(t => ` ${t.match ? ' + ' : ' - '}${t.filteredTitle}`));
const message = ['', `Filtered tests (${count})`, '', filteredUniq.join('\n')];
// eslint-disable-next-line no-console
console.log(message.join('\n'));
}
};
const turnOffBeforeHook = () => {
global.before = () => {
// ignore
};
};
const setupSelectTests = (selector, settings, onCount, isPrerun) => {
var _a;
const grep = (_a = Cypress.env(envVars_1.grepEnvVars.GREP)) !== null && _a !== void 0 ? _a : '';
if (settings.debugLog) {
// eslint-disable-next-line no-console
console.log(`${logs_1.pkgName} ----- Setup SELECT Tests --- ${selector().toString()} `);
}
if (isPrerun) {
settings.showTagsInTitle = true;
settings.showExcludedTests = false;
// some tests uses visit in before
turnOffBeforeHook();
}
Cypress.env('cyTagsShowTagsInTitle', settings.showTagsInTitle);
(0, register_1.registerTags)();
const originalSuites = (0, exports.origins)();
const filteredSuites = [];
const filteredTests = [];
const filterSuite = createFilterSuiteTests(settings, isPrerun, onCount);
function itWithTags(...args) {
var _a;
const regexp = selector();
const test = originalSuites.originIt(...args);
// for tests that doesn't have parent suite
if (test.parent && test.parent.title === '' && !((_a = test.parent) === null || _a === void 0 ? void 0 : _a.parent)) {
filterSuite(regexp, filteredTests, test.parent, test);
}
return test;
}
function descWithTags(...args) {
const regexp = selector();
const suite = originalSuites.originDescribe(...args);
if (suite && suite.parent && suite.parent.title === '' && !suite.parent.parent) {
// this will run for every parent suite in file
// current suite does not contain info about all suites before execution
filterSuite(regexp, filteredSuites, suite);
}
return suite;
}
if (isPrerun && grep) {
it(`${logs_1.pkgName} auto-generated test to write results`, () => {
const uniqTests = (arr) => arr.filter((obj, index, self) => self.map(s => s.filteredTitle).indexOf(obj.filteredTitle) === index);
const all = uniqTests([...filteredSuites, ...filteredTests]);
const match = all.filter(t => t.match);
const result = { total: all.length, filtered: match.length, grep, tests: match };
if (match.length === 0 && settings.failOnNotFound) {
const msg = [
`Not found any tests matching ${envVars_1.grepEnvVars.GREP} '${grep}' satisfying specPattern ${Cypress.env('originalSpecPattern')}`,
`To disable this error set environment variable \`${envVars_1.grepEnvVars.failOnNotFound}\` to false or set \`failOnNotFound\` to \`false\` in registerCypressGrep`,
];
throw new Error(msg.join('\n'));
}
// note: 'after' hook is not being called when there are no tests
// when no tests filtered and failOnNotFound is false -
// all tests would be executed after prerun since no file is created
cy.task('writeTempFileWithSelectedTests', result);
});
}
global.describe = descWithTags;
global.describe.only = originalSuites.originOnly;
global.describe.skip = originalSuites.originSkip;
global.it = itWithTags;
global.it.only = originalSuites.originItOnly;
global.it.skip = originalSuites.originItSkip;
};
exports.setupSelectTests = setupSelectTests;