2022-09-09 09:12:18 +00:00
|
|
|
/**
|
|
|
|
* Copyright 2022 Google Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2023-02-15 23:09:31 +00:00
|
|
|
import fs from 'fs';
|
|
|
|
import path from 'path';
|
|
|
|
|
2022-09-08 10:32:39 +00:00
|
|
|
import {
|
|
|
|
MochaTestResult,
|
|
|
|
TestExpectation,
|
|
|
|
MochaResults,
|
|
|
|
TestResult,
|
|
|
|
} from './types.js';
|
|
|
|
|
|
|
|
export function extendProcessEnv(envs: object[]): NodeJS.ProcessEnv {
|
|
|
|
return envs.reduce(
|
|
|
|
(acc: object, item: object) => {
|
|
|
|
Object.assign(acc, item);
|
|
|
|
return acc;
|
|
|
|
},
|
|
|
|
{
|
|
|
|
...process.env,
|
|
|
|
}
|
|
|
|
) as NodeJS.ProcessEnv;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getFilename(file: string): string {
|
|
|
|
return path.basename(file).replace(path.extname(file), '');
|
|
|
|
}
|
|
|
|
|
|
|
|
export function readJSON(path: string): unknown {
|
|
|
|
return JSON.parse(fs.readFileSync(path, 'utf-8'));
|
|
|
|
}
|
|
|
|
|
|
|
|
export function filterByPlatform<T extends {platforms: NodeJS.Platform[]}>(
|
|
|
|
items: T[],
|
|
|
|
platform: NodeJS.Platform
|
|
|
|
): T[] {
|
|
|
|
return items.filter(item => {
|
|
|
|
return item.platforms.includes(platform);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function prettyPrintJSON(json: unknown): void {
|
|
|
|
console.log(JSON.stringify(json, null, 2));
|
|
|
|
}
|
|
|
|
|
|
|
|
export function filterByParameters(
|
2023-01-13 15:14:37 +00:00
|
|
|
expectations: TestExpectation[],
|
2022-09-08 10:32:39 +00:00
|
|
|
parameters: string[]
|
|
|
|
): TestExpectation[] {
|
|
|
|
const querySet = new Set(parameters);
|
2023-01-13 15:14:37 +00:00
|
|
|
return expectations.filter(ex => {
|
2022-09-08 10:32:39 +00:00
|
|
|
return ex.parameters.every(param => {
|
|
|
|
return querySet.has(param);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-01-13 15:14:37 +00:00
|
|
|
* The last expectation that matches an empty string as all tests pattern
|
|
|
|
* or the name of the file or the whole name of the test the filter wins.
|
2022-09-08 10:32:39 +00:00
|
|
|
*/
|
2023-01-13 15:14:37 +00:00
|
|
|
export function findEffectiveExpectationForTest(
|
2022-09-08 10:32:39 +00:00
|
|
|
expectations: TestExpectation[],
|
|
|
|
result: MochaTestResult
|
|
|
|
): TestExpectation | undefined {
|
|
|
|
return expectations
|
2023-01-13 15:14:37 +00:00
|
|
|
.filter(expectation => {
|
|
|
|
return (
|
|
|
|
'' === expectation.testIdPattern ||
|
|
|
|
getTestId(result.file) === expectation.testIdPattern ||
|
|
|
|
getTestId(result.file, result.fullTitle) === expectation.testIdPattern
|
|
|
|
);
|
2022-09-08 10:32:39 +00:00
|
|
|
})
|
|
|
|
.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
type RecommendedExpecation = {
|
|
|
|
expectation: TestExpectation;
|
|
|
|
test: MochaTestResult;
|
|
|
|
action: 'remove' | 'add' | 'update';
|
|
|
|
};
|
|
|
|
|
|
|
|
export function getExpectationUpdates(
|
|
|
|
results: MochaResults,
|
|
|
|
expecations: TestExpectation[],
|
|
|
|
context: {
|
|
|
|
platforms: NodeJS.Platform[];
|
|
|
|
parameters: string[];
|
|
|
|
}
|
|
|
|
): RecommendedExpecation[] {
|
|
|
|
const output: RecommendedExpecation[] = [];
|
|
|
|
|
|
|
|
for (const pass of results.passes) {
|
2023-01-13 15:14:37 +00:00
|
|
|
const expectation = findEffectiveExpectationForTest(expecations, pass);
|
2022-09-08 10:32:39 +00:00
|
|
|
if (expectation && !expectation.expectations.includes('PASS')) {
|
|
|
|
output.push({
|
|
|
|
expectation,
|
|
|
|
test: pass,
|
|
|
|
action: 'remove',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const failure of results.failures) {
|
2023-01-13 15:14:37 +00:00
|
|
|
const expectation = findEffectiveExpectationForTest(expecations, failure);
|
2022-09-08 10:32:39 +00:00
|
|
|
if (expectation) {
|
|
|
|
if (
|
|
|
|
!expectation.expectations.includes(getTestResultForFailure(failure))
|
|
|
|
) {
|
|
|
|
output.push({
|
|
|
|
expectation: {
|
|
|
|
...expectation,
|
|
|
|
expectations: [
|
|
|
|
...expectation.expectations,
|
|
|
|
getTestResultForFailure(failure),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
test: failure,
|
|
|
|
action: 'update',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
output.push({
|
|
|
|
expectation: {
|
|
|
|
testIdPattern: getTestId(failure.file, failure.fullTitle),
|
|
|
|
platforms: context.platforms,
|
|
|
|
parameters: context.parameters,
|
|
|
|
expectations: [getTestResultForFailure(failure)],
|
|
|
|
},
|
|
|
|
test: failure,
|
|
|
|
action: 'add',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getTestResultForFailure(
|
|
|
|
test: Pick<MochaTestResult, 'err'>
|
|
|
|
): TestResult {
|
|
|
|
return test.err?.code === 'ERR_MOCHA_TIMEOUT' ? 'TIMEOUT' : 'FAIL';
|
|
|
|
}
|
|
|
|
|
2023-01-13 15:14:37 +00:00
|
|
|
export function getTestId(file: string, fullTitle?: string): string {
|
|
|
|
return fullTitle
|
|
|
|
? `[${getFilename(file)}] ${fullTitle}`
|
|
|
|
: `[${getFilename(file)}]`;
|
2022-09-08 10:32:39 +00:00
|
|
|
}
|