/** * Tree-structure of all POM classes. * Allows to guess correct fixture for decorator steps. */ /* eslint-disable @typescript-eslint/no-unsafe-function-type */ import { linkStepsWithPomNode } from './steps'; import { exit } from '../../utils/exit'; type PomClass = Function; // POM class with inherited children POMs: representation of classes inheritance. export type PomNode = { fixtureName: string; fixtureTags?: string; className: string; children: Set; }; const pomGraph = new Map(); export function createPomNode(Ctor: PomClass, fixtureName: string, fixtureTags?: string) { const pomNode: PomNode = { fixtureName, fixtureTags, className: Ctor.name, children: new Set(), }; ensureUniqueFixtureName(pomNode); pomGraph.set(Ctor, pomNode); linkStepsWithPomNode(Ctor, pomNode); linkParentWithPomNode(Ctor, pomNode); return pomNode; } function ensureUniqueFixtureName({ fixtureName, className }: PomNode) { if (!fixtureName) return; const existingPom = getPomNodeByFixtureName(fixtureName); if (existingPom) exit( `Duplicate fixture name "${fixtureName}"`, `defined for classes: ${existingPom.className}, ${className}`, ); } function linkParentWithPomNode(Ctor: PomClass, pomNode: PomNode) { const parentCtor = Object.getPrototypeOf(Ctor); if (!parentCtor) return; // if parentCtor is not in pomGraph, add it. // Case: parent class is not marked with @Fixture, but has decorator steps (base class) const parentPomNode = pomGraph.get(parentCtor) || createPomNode(parentCtor, ''); parentPomNode.children.add(pomNode); } export function getPomNodeByFixtureName(fixtureName: string) { for (const pomNode of pomGraph.values()) { if (pomNode.fixtureName === fixtureName) return pomNode; } }