UNPKG

testeranto

Version:

the AI powered BDD test framework for typescript projects

191 lines (190 loc) 7.25 kB
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { afterEachProxy, andWhenProxy, beforeEachProxy, butThenProxy, } from "./pmProxy.js"; export class BaseGiven { addArtifact(path) { const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators this.artifacts.push(normalizedPath); } constructor(name, features, whens, thens, givenCB, initialValues) { this.artifacts = []; this.name = name; this.features = features; this.whens = whens; this.thens = thens; this.givenCB = givenCB; this.initialValues = initialValues; } beforeAll(store) { return store; } toObj() { return { key: this.key, name: this.name, whens: this.whens.map((w) => { if (w && w.toObj) return w.toObj(); console.error("w is not as expected!", JSON.stringify(w)); return {}; }), thens: this.thens.map((t) => t.toObj()), error: this.error ? [this.error, this.error.stack] : null, failed: this.failed, features: this.features, artifacts: this.artifacts, }; } async afterEach(store, key, artifactory, pm) { return store; } async give(subject, key, testResourceConfiguration, tester, artifactory, tLog, pm, suiteNdx) { this.key = key; tLog(`\n ${this.key}`); tLog(`\n Given: ${this.name}`); const givenArtifactory = (fPath, value) => artifactory(`given-${key}/${fPath}`, value); this.uberCatcher((e) => { console.error(e.toString()); this.error = e.error; tLog(e.stack); }); try { // Ensure addArtifact is properly bound to 'this' const addArtifact = this.addArtifact.bind(this); const proxiedPm = beforeEachProxy(pm, suiteNdx.toString(), addArtifact); this.store = await this.givenThat(subject, testResourceConfiguration, givenArtifactory, this.givenCB, this.initialValues, proxiedPm); } catch (e) { // console.error("Given failure: ", e.stack); this.failed = true; this.error = e.stack; // throw e; } try { // tLog(`\n Given this.store`, this.store); for (const [whenNdx, whenStep] of this.whens.entries()) { await whenStep.test(this.store, testResourceConfiguration, tLog, pm, `suite-${suiteNdx}/given-${key}/when/${whenNdx}`); } for (const [thenNdx, thenStep] of this.thens.entries()) { const t = await thenStep.test(this.store, testResourceConfiguration, tLog, pm, `suite-${suiteNdx}/given-${key}/then-${thenNdx}`); tester(t); } } catch (e) { this.error = e.stack; this.failed = true; // tLog(e.stack); // throw e; } finally { try { // Ensure addArtifact is properly bound to 'this' const addArtifact = this.addArtifact.bind(this); const proxiedPm = afterEachProxy(pm, suiteNdx.toString(), key, addArtifact); // (proxiedPm as any).currentStep = this; await this.afterEach(this.store, this.key, givenArtifactory, proxiedPm); } catch (e) { this.failed = e; throw e; // this.error = e.message; } } return this.store; } } export class BaseWhen { addArtifact(path) { const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators this.artifacts.push(normalizedPath); } constructor(name, whenCB) { this.artifacts = []; this.name = name; this.whenCB = whenCB; } toObj() { const obj = { name: this.name, error: this.error ? `${this.error.name}: ${this.error.message}\n${this.error.stack}` : null, artifacts: this.artifacts || [], }; console.log(`[TOOBJ] Serializing ${this.constructor.name} with artifacts:`, obj.artifacts); return obj; } async test(store, testResourceConfiguration, tLog, pm, filepath) { try { // tLog(" When:", this.name); // Ensure addArtifact is properly bound to 'this' const addArtifact = this.addArtifact.bind(this); const proxiedPm = andWhenProxy(pm, filepath, addArtifact); // (proxiedPm as any).currentStep = this; const result = await this.andWhen(store, this.whenCB, testResourceConfiguration, proxiedPm); return result; } catch (e) { console.error("[ERROR] When step failed:", this.name.toString(), e.toString()); this.error = e; throw e; } } } export class BaseThen { constructor(name, thenCB) { this.artifacts = []; this.name = name; this.thenCB = thenCB; this.error = false; this.artifacts = []; } addArtifact(path) { const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators this.artifacts.push(normalizedPath); } toObj() { const obj = { name: this.name, error: this.error, artifacts: this.artifacts, }; return obj; } async test(store, testResourceConfiguration, tLog, pm, filepath) { // Ensure addArtifact is properly bound to 'this' const addArtifact = this.addArtifact.bind(this); const proxiedPm = butThenProxy(pm, filepath, addArtifact); return this.butThen(store, async (s) => { try { if (typeof this.thenCB === "function") { // Add debug logging to see what's being passed to thenCB // Check if the thenCB is spreading the arguments incorrectly // Wrap the proxy to see what's happening when writeFileSync is called const wrappedPm = new Proxy(proxiedPm, { get: (target, prop, receiver) => { if (prop === "writeFileSync") { return (...args) => { console.log(`[DEBUG] writeFileSync called with args:`, args); return target[prop](...args); }; } return target[prop]; }, }); const result = await this.thenCB(s, wrappedPm); return result; } else { return this.thenCB; } } catch (e) { console.error(e.stack); } }, testResourceConfiguration, proxiedPm).catch((e) => { this.error = e.stack; // throw e; }); } }