test(docs-infra): allow excluding certain docs examples from tests (#42660)

This commit adds support for excluding certain docs examples from the
command used to run tests. This is useful to run extra tests on CI that
might not be compatible with all examples (for example, run tests with
different versions of a dependency).

In a subsequent commit, this will be used to run tests against RxJS v7
as a quick way to catch potential regressions.

PR Close #42660
This commit is contained in:
George Kalpakas 2021-06-29 18:59:35 +03:00 committed by Jessica Janiuk
parent 2c490d5c6c
commit 188a73852e

View File

@ -25,9 +25,15 @@ const IGNORED_EXAMPLES = [];
* Run Protractor End-to-End Tests for Doc Samples * Run Protractor End-to-End Tests for Doc Samples
* *
* Flags * Flags
* --filter to filter/select _example app subdir names * --filter to filter/select example app subdir names
* Can be used multiple times to include multiple patterns.
* e.g. --filter=foo // all example apps with 'foo' in their folder names. * e.g. --filter=foo // all example apps with 'foo' in their folder names.
* *
* --exclude to exclude example app subdir names
* Can be used multiple times to exclude multiple patterns.
* NOTE: `--exclude` is always cosidered after `--filter`.
* e.g. --exclude=bar // Exclude all example apps with 'bar' in their folder names.
*
* --setup to run yarn install, copy boilerplate and update webdriver * --setup to run yarn install, copy boilerplate and update webdriver
* e.g. --setup * e.g. --setup
* *
@ -60,7 +66,7 @@ function runE2e() {
return Promise.resolve() return Promise.resolve()
.then( .then(
() => findAndRunE2eTests( () => findAndRunE2eTests(
argv.filter, outputFile, argv.shard, argv.filter, argv.exclude, outputFile, argv.shard,
argv.cliSpecsConcurrency || DEFAULT_CLI_SPECS_CONCURRENCY, argv.retry || 1)) argv.cliSpecsConcurrency || DEFAULT_CLI_SPECS_CONCURRENCY, argv.retry || 1))
.then((status) => { .then((status) => {
reportStatus(status, outputFile); reportStatus(status, outputFile);
@ -76,7 +82,9 @@ function runE2e() {
// Finds all of the *e2e-spec.tests under the examples folder along with the corresponding apps // Finds all of the *e2e-spec.tests under the examples folder along with the corresponding apps
// that they should run under. Then run each app/spec collection sequentially. // that they should run under. Then run each app/spec collection sequentially.
function findAndRunE2eTests(filter, outputFile, shard, cliSpecsConcurrency, maxAttempts) { function findAndRunE2eTests(
includeFilter, excludeFilter, outputFile, shard, cliSpecsConcurrency, maxAttempts) {
const filter = {include: includeFilter, exclude: excludeFilter};
const shardParts = shard ? shard.split('/') : [0, 1]; const shardParts = shard ? shard.split('/') : [0, 1];
const shardModulo = parseInt(shardParts[0], 10); const shardModulo = parseInt(shardParts[0], 10);
const shardDivider = parseInt(shardParts[1], 10); const shardDivider = parseInt(shardParts[1], 10);
@ -84,7 +92,8 @@ function findAndRunE2eTests(filter, outputFile, shard, cliSpecsConcurrency, maxA
// create an output file with header. // create an output file with header.
const startTime = new Date().getTime(); const startTime = new Date().getTime();
let header = `Doc Sample Protractor Results on ${new Date().toLocaleString()}\n`; let header = `Doc Sample Protractor Results on ${new Date().toLocaleString()}\n`;
header += ` Filter: ${filter ? filter : 'All tests'}\n\n`; header += ` Include: ${filter.include || 'All tests'}\n`;
header += ` Exclude: ${filter.exclude || 'No tests'}\n\n`;
fs.writeFileSync(outputFile, header); fs.writeFileSync(outputFile, header);
const status = {passed: [], failed: []}; const status = {passed: [], failed: []};
@ -378,16 +387,23 @@ function getE2eSpecs(basePath, filter) {
// Find all e2e specs in a given example folder. // Find all e2e specs in a given example folder.
function getE2eSpecsFor(basePath, specFile, filter) { function getE2eSpecsFor(basePath, specFile, filter) {
// Only get spec file at the example root. // Only get spec file at the example root.
// The formatter doesn't understand nested template string expressions (honestly, neither do I). const e2eSpecGlob = [
// clang-format off `${filter.include ? filterToGlob(filter.include) : '*'}/${specFile}`,
const e2eSpecGlob = `${filter ? `*${filter}*` : '*'}/${specFile}`; `!${filter.exclude ? filterToGlob(filter.exclude) : ''}/${specFile}`,
// clang-format on ];
return globby(e2eSpecGlob, {cwd: basePath, nodir: true}) return globby(e2eSpecGlob, {cwd: basePath, nodir: true})
.then( .then(
paths => paths.filter(file => !IGNORED_EXAMPLES.some(ignored => file.startsWith(ignored))) paths => paths.filter(file => !IGNORED_EXAMPLES.some(ignored => file.startsWith(ignored)))
.map(file => path.join(basePath, file))); .map(file => path.join(basePath, file)));
} }
function filterToGlob(filter) {
// `filter` can be either a string (if there is one occurrence of the corresponding option) or an
// array (if there are two or more occurrences of the corresponding option). In other words, if
// `filter` is an array, it will have more than one element.
return Array.isArray(filter) ? `*{${filter.join(',')}}*` : `*${filter}*`;
}
// Load configuration for an example. Used for SystemJS // Load configuration for an example. Used for SystemJS
function loadExampleConfig(exampleFolder) { function loadExampleConfig(exampleFolder) {
// Default config. // Default config.