196 lines
4.2 KiB
JavaScript
196 lines
4.2 KiB
JavaScript
![]() |
// @ts-check
|
||
|
|
||
|
// Universal code - should run in Node or in the browser
|
||
|
|
||
|
/**
|
||
|
* Parses test title grep string.
|
||
|
* The string can have "-" in front of it to invert the match.
|
||
|
* @param {string} s Input substring of the test title
|
||
|
*/
|
||
|
function parseTitleGrep(s) {
|
||
|
if (!s || typeof s !== "string") {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
s = s.trim();
|
||
|
if (s.startsWith("-")) {
|
||
|
return {
|
||
|
title: s.substring(1),
|
||
|
invert: true
|
||
|
};
|
||
|
}
|
||
|
return {
|
||
|
title: s,
|
||
|
invert: false
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function parseFullTitleGrep(s) {
|
||
|
if (!s || typeof s !== "string") {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
// separate each title
|
||
|
return s.split(";").map(parseTitleGrep);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parses tags to grep for.
|
||
|
* @param {string} s Tags string like "@tag1+@tag2"
|
||
|
*/
|
||
|
function parseTagsGrep(s) {
|
||
|
if (!s) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
const explicitNotTags = [];
|
||
|
|
||
|
// top level split - using space or comma, each part is OR
|
||
|
const ORS = s
|
||
|
.split(/[ ,]/)
|
||
|
// remove any empty tags
|
||
|
.filter(Boolean)
|
||
|
.map(part => {
|
||
|
// now every part is an AND
|
||
|
if (part.startsWith("--")) {
|
||
|
explicitNotTags.push({
|
||
|
tag: part.slice(2),
|
||
|
invert: true
|
||
|
});
|
||
|
return;
|
||
|
}
|
||
|
const parsed = part.split("+").map(tag => {
|
||
|
if (tag.startsWith("-")) {
|
||
|
return {
|
||
|
tag: tag.slice(1),
|
||
|
invert: true
|
||
|
};
|
||
|
} else {
|
||
|
return {
|
||
|
tag,
|
||
|
invert: false
|
||
|
};
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return parsed;
|
||
|
});
|
||
|
|
||
|
// filter out undefined from explicit not tags
|
||
|
const ORS_filtered = ORS.filter(x => x !== undefined);
|
||
|
if (explicitNotTags.length > 0) {
|
||
|
ORS_filtered.forEach((OR, index) => {
|
||
|
ORS_filtered[index] = OR.concat(explicitNotTags);
|
||
|
});
|
||
|
}
|
||
|
return ORS_filtered;
|
||
|
}
|
||
|
|
||
|
function shouldTestRunTags(parsedGrepTags, tags = []) {
|
||
|
if (!parsedGrepTags.length) {
|
||
|
// there are no parsed tags to search for, the test should run
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// now the test has tags and the parsed tags are present
|
||
|
|
||
|
// top levels are OR
|
||
|
const onePartMatched = parsedGrepTags.some(orPart => {
|
||
|
const everyAndPartMatched = orPart.every(p => {
|
||
|
if (p.invert) {
|
||
|
return !tags.includes(p.tag);
|
||
|
}
|
||
|
|
||
|
return tags.includes(p.tag);
|
||
|
});
|
||
|
// console.log('every part matched %o?', orPart, everyAndPartMatched)
|
||
|
|
||
|
return everyAndPartMatched;
|
||
|
});
|
||
|
|
||
|
// console.log('onePartMatched', onePartMatched)
|
||
|
return onePartMatched;
|
||
|
}
|
||
|
|
||
|
function shouldTestRunTitle(parsedGrep, testName) {
|
||
|
if (!testName) {
|
||
|
// if there is no title, let it run
|
||
|
return true;
|
||
|
}
|
||
|
if (!parsedGrep) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (!Array.isArray(parsedGrep)) {
|
||
|
console.error("Invalid parsed title grep");
|
||
|
console.error(parsedGrep);
|
||
|
throw new Error("Expected title grep to be an array");
|
||
|
}
|
||
|
|
||
|
if (!parsedGrep.length) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
const inverted = parsedGrep.filter(g => g.invert);
|
||
|
const straight = parsedGrep.filter(g => !g.invert);
|
||
|
|
||
|
return (
|
||
|
inverted.every(titleGrep => !testName.includes(titleGrep.title)) &&
|
||
|
(!straight.length ||
|
||
|
straight.some(titleGrep => testName.includes(titleGrep.title)))
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// note: tags take precedence over the test name
|
||
|
function shouldTestRun(parsedGrep, testName, tags = [], grepUntagged = false) {
|
||
|
if (grepUntagged) {
|
||
|
return !tags.length;
|
||
|
}
|
||
|
|
||
|
if (Array.isArray(testName)) {
|
||
|
// the caller passed tags only, no test name
|
||
|
tags = testName;
|
||
|
testName = undefined;
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
shouldTestRunTitle(parsedGrep.title, testName) &&
|
||
|
shouldTestRunTags(parsedGrep.tags, tags)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function parseGrep(titlePart, tags) {
|
||
|
return {
|
||
|
title: parseFullTitleGrep(titlePart),
|
||
|
tags: parseTagsGrep(tags)
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function resolveConfig(config) {
|
||
|
const specPattern = config.specPattern || "";
|
||
|
let excludeSpecPattern = config.excludeSpecPattern || "";
|
||
|
if (typeof excludeSpecPattern === "string") {
|
||
|
excludeSpecPattern = [excludeSpecPattern];
|
||
|
}
|
||
|
const integrationFolder = config.env.grepIntegrationFolder || process.cwd();
|
||
|
|
||
|
return {
|
||
|
resolvedConfig: {
|
||
|
specPattern,
|
||
|
excludeSpecPattern,
|
||
|
integrationFolder
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
parseGrep,
|
||
|
parseTitleGrep,
|
||
|
parseFullTitleGrep,
|
||
|
parseTagsGrep,
|
||
|
resolveConfig,
|
||
|
shouldTestRun,
|
||
|
shouldTestRunTags,
|
||
|
shouldTestRunTitle
|
||
|
};
|