aft-jest-reporter
Version:
Automated Functional Testing (AFT) Reporter for use with Jest Test Framework
104 lines (98 loc) • 4.06 kB
text/typescript
import { JestExpect } from "@jest/expect";
import { AftTest, AftTestFunction, AftTestOptions, Func, TestResult, TestStatus, rand } from "aft-core";
import { TestCaseResult } from "@jest/reporters";
/**
* expects to be passed a context scope from an executing Jest
* test. for Jest, the `JestExpect` type contains this so you
* can use an `expect` like follows:
*
* ```typescript
* test('perform some testing', () => {
* const t = new AftJestTest(expect, () => doStuff());
* })
* ```
* @param scope the `expect` object from within a Jest `test`
*/
export class AftJestTest extends AftTest {
/**
* reference to the Jest.TestCaseResult
* #### NOTE:
* > this is only set from inside the Jest
* Reporter plugin and not available within a
* Jest `test` function
*/
public readonly test: TestCaseResult;
/**
* expects to be passed a context scope from an executing Jest
* test. for Jest, the `JestExpect` type contains this so you
* can use an `expect` like follows:
*
* ```typescript
* test('perform some testing', () => {
* const t = new AftJestTest(expect, () => doStuff());
* })
* ```
* @param scope the `expect` object from within a Jest `test`
*/
constructor(scope?: any, testFunction?: AftTestFunction, options?: AftTestOptions) {
let test: TestCaseResult;
let description: string;
if (typeof scope === 'string') {
description = scope;
}else if (scope?.fullName) {
// 'scope' is a 'TestCaseResult'
test = scope;
description = test.fullName;
} else if (scope?.getState) {
// 'scope' is an 'expect' object
const state = scope.getState();
description = state.currentTestName;
} else {
description = `${AftJestTest.name}_${rand.getString(8, true, true)}`;
}
testFunction ??= () => null;
options ??= {};
options._cacheResultsToFile = true;
super(description, testFunction, options);
this.test = test;
}
/**
* see: `pending`
* @param reason the reason for skipping this test
*/
async skipped(reason?: string): Promise<void> {
return this.pending(reason);
}
protected override async _generateTestResult(status: TestStatus, resultMessage: string, testId?: string): Promise<TestResult> {
const result = await super._generateTestResult(status, resultMessage, testId);
if (result?.metadata?.['durationMs'] && this.test?.duration > 0) {
result.metadata['durationMs'] = this.test.duration;
}
return result;
}
}
/**
* creates a new `AftJestTest` instace to be used for executing some Functional
* Test Assertion and calls the `run` function to execute the `testFunction`.
*
* ex:
* ```typescript
* test('[C1234] example usage for AftTest', () => {
* await aftJestTest(expect, async (v: AftJestTest) => {
* await v.reporter.info('doing some testing...');
* const feature = new FeatureObj();
* await v.verify(() => feature.returnExpectedValueAsync(), equaling('expected value'));
* }); // if PolicyManager.shouldRun('C1234') returns `false` the assertion is not run
* })
* ```
* @param expect a `JestExpect` or `jest.Expect` containing a `fullName` property used
* as the test description or a `string` description
* @param testFunction the `Func<AftJestTest, void | PromiseLike<void>>` function to be
* executed by this `AftJestTest`
* @param options an optional `AftTestOptions` object containing overrides to internal
* configuration and settings
* @returns an async `Promise<void>` that runs the passed in `testFunction`
*/
export const aftJestTest = async (expect: JestExpect | jest.Expect | string, testFunction: Func<AftJestTest, void | PromiseLike<void>>, options?: AftTestOptions): Promise<AftJestTest> => { // eslint-disable-line no-undef
return new AftJestTest(expect, testFunction, options).run();
};