testeranto
Version:
the AI powered BDD test framework for typescript projects
135 lines (134 loc) • 5.3 kB
JavaScript
/* eslint-disable @typescript-eslint/no-unused-vars */
import { beforeAllProxy, afterAllProxy } from "./pmProxy";
export class BaseSuite {
addArtifact(path) {
if (typeof path !== "string") {
throw new Error(`[ARTIFACT ERROR] Expected string, got ${typeof path}: ${JSON.stringify(path)}`);
}
const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators
this.artifacts.push(normalizedPath);
}
constructor(name, index, givens = {}) {
this.artifacts = [];
const suiteName = name || "testSuite"; // Ensure name is never undefined
if (!suiteName) {
throw new Error("BaseSuite requires a non-empty name");
}
this.name = suiteName;
this.index = index;
this.givens = givens;
this.fails = 0;
}
features() {
try {
const features = Object.keys(this.givens)
.map((k) => this.givens[k].features)
.flat()
.filter((value, index, array) => {
return array.indexOf(value) === index;
});
// Convert all features to strings
const stringFeatures = features.map((feature) => {
if (typeof feature === "string") {
return feature;
}
else if (feature && typeof feature === "object") {
return feature.name || JSON.stringify(feature);
}
else {
return String(feature);
}
});
return stringFeatures || [];
}
catch (e) {
console.error("[ERROR] Failed to extract features:", JSON.stringify(e));
return [];
}
}
toObj() {
const givens = Object.keys(this.givens).map((k) => {
const givenObj = this.givens[k].toObj();
// Ensure given features are strings
// if (givenObj.features) {
// givenObj.features = givenObj.features.map(feature => {
// return feature;
// // if (typeof feature === 'string') {
// // return feature;
// // } else if (feature && typeof feature === 'object') {
// // return feature.name || JSON.stringify(feature);
// // } else {
// // return String(feature);
// // }
// });
// }
return givenObj;
});
return {
name: this.name,
givens,
fails: this.fails,
failed: this.failed,
features: this.features(),
artifacts: this.artifacts
? this.artifacts.filter((art) => typeof art === "string")
: [],
};
}
setup(s, artifactory, tr, pm) {
return new Promise((res) => res(s));
}
assertThat(t) {
return !!t;
}
afterAll(store, artifactory, pm) {
return store;
}
async run(input, testResourceConfiguration, artifactory, tLog, pm) {
this.testResourceConfiguration = testResourceConfiguration;
// tLog("test resources: ", JSON.stringify(testResourceConfiguration));
const suiteArtifactory = (fPath, value) => artifactory(`suite-${this.index}-${this.name}/${fPath}`, value);
// console.log("\nSuite:", this.index, this.name);
// tLog("\nSuite:", this.index, this.name);
const sNdx = this.index;
// Ensure addArtifact is properly bound to 'this'
const addArtifact = this.addArtifact.bind(this);
const proxiedPm = beforeAllProxy(pm, sNdx.toString(), addArtifact);
const subject = await this.setup(input, suiteArtifactory, testResourceConfiguration, proxiedPm);
for (const [gKey, g] of Object.entries(this.givens)) {
const giver = this.givens[gKey];
try {
this.store = await giver.give(subject, gKey, testResourceConfiguration, this.assertThat, suiteArtifactory, tLog, pm, sNdx);
// Add the number of failures from this given to the suite's total
this.fails += giver.fails || 0;
}
catch (e) {
this.failed = true;
// Add 1 to fails for the caught error
this.fails += 1;
// Also add any failures from the given itself
if (giver.fails) {
this.fails += giver.fails;
}
console.error(`Error in given ${gKey}:`, e);
// Don't re-throw to continue with other givens
}
}
// Mark the suite as failed if there are any failures
if (this.fails > 0) {
this.failed = true;
}
try {
// Ensure addArtifact is properly bound to 'this'
const addArtifact = this.addArtifact.bind(this);
const afterAllPm = afterAllProxy(pm, sNdx.toString(), addArtifact);
this.afterAll(this.store, artifactory, afterAllPm);
}
catch (e) {
console.error(JSON.stringify(e));
// this.fails.push(this);
// return this;
}
return this;
}
}