import { CB, Result } from 'vest-utils'; import { IsolateSerializer } from 'vestjs-runtime'; import { TestStatus } from '../core/StateMachines/IsolateTestStateMachine'; import { TIsolateSuite } from '../core/isolate/IsolateSuite/IsolateSuite'; import { Suite } from '../suite/SuiteTypes'; import { TFieldName, TGroupName, TSchema, } from '../suiteResult/SuiteResultTypes'; type Dumpable = { dump: CB; }; export class SuiteSerializer { static serialize(suite: Dumpable) { const dump = stripMessagesExceptFailedAndWarning(suite.dump()); return IsolateSerializer.serialize(dump, suiteSerializerReplacer); } static safeDeserialize( serialized: string | TIsolateSuite | Record, ): Result { return IsolateSerializer.safeDeserialize(serialized).map( isolate => isolate as TIsolateSuite, ); } static deserialize( serialized: string | TIsolateSuite | Record, ): TIsolateSuite { return SuiteSerializer.safeDeserialize(serialized).unwrap(); } static resume< F extends TFieldName, G extends TGroupName, T extends CB, S extends TSchema, >( suite: Suite, root: string | TIsolateSuite | Record, ): void { const suiteRoot = SuiteSerializer.deserialize(root); suite.resume(suiteRoot); } } function stripMessagesExceptFailedAndWarning(node: T): T { const visited = new WeakMap(); return strip(node, visited); } // eslint-disable-next-line complexity, max-statements function strip(node: T, visited: WeakMap): T { if (!node || typeof node !== 'object') { return node; } if (visited.has(node as object)) { return visited.get(node as object); } if (Array.isArray(node)) { const arr: any[] = []; visited.set(node, arr); node.forEach(value => { arr.push(strip(value, visited)); }); return arr as T; } const root = node as Record; const shouldKeepMessage = root.testStatus === TestStatus.FAILED || root.testStatus === TestStatus.WARNING; const clonedNode: Record = {}; visited.set(node, clonedNode); for (const [key, value] of Object.entries(root)) { if (SkipTraversalKeys.has(key)) { continue; } if (!shouldKeepMessage && key === 'message') { continue; } clonedNode[key] = strip(value, visited); } return clonedNode as T; } function suiteSerializerReplacer(value: any, key: string) { if (isStatusKey(key)) { return getAllowedStatus(value); } if (DisallowedKeys.has(key)) { return undefined; } return value; } function isStatusKey(key: string): boolean { return key === 'testStatus'; } function getAllowedStatus(value: any): any { return AllowedStatuses.has(value) ? value : undefined; } const DisallowedKeys = new Set([ 'focusMode', 'match', 'matchAll', 'output', 'severity', 'tests', ]); const SkipTraversalKeys = new Set([ 'parent', 'abortController', 'keys', ...DisallowedKeys, ]); const AllowedStatuses = new Set([ TestStatus.FAILED, TestStatus.PASSING, TestStatus.WARNING, ]);