testeranto.tiposkripto 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/Types.js +2 -0
- package/dist/common/lib/tiposkripto/src/BaseGiven.js +96 -0
- package/dist/common/lib/tiposkripto/src/BaseSuite.js +134 -0
- package/dist/common/lib/tiposkripto/src/BaseThen.js +65 -0
- package/dist/common/lib/tiposkripto/src/BaseTiposkripto.js +192 -0
- package/dist/common/lib/tiposkripto/src/BaseWhen.js +46 -0
- package/dist/common/lib/tiposkripto/src/CoreTypes.js +2 -0
- package/dist/common/lib/tiposkripto/src/Node.js +37 -0
- package/dist/common/lib/tiposkripto/src/Web.js +62 -0
- package/dist/common/lib/tiposkripto/src/index.js +86 -0
- package/dist/common/lib/tiposkripto/src/types.js +6 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/MockGiven.js +22 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/MockThen.js +16 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/MockWhen.js +18 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/adapter.js +24 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/implementation.js +38 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/index.js +17 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/specification.js +19 -0
- package/dist/common/lib/tiposkripto/tests/abstractBase.test/types.js +2 -0
- package/dist/common/package.json +3 -0
- package/dist/common/tsconfig.common.tsbuildinfo +1 -0
- package/dist/module/Types.js +1 -0
- package/dist/module/index.js +689 -0
- package/dist/module/lib/tiposkripto/src/BaseGiven.js +92 -0
- package/dist/module/lib/tiposkripto/src/BaseSuite.js +130 -0
- package/dist/module/lib/tiposkripto/src/BaseThen.js +61 -0
- package/dist/module/lib/tiposkripto/src/BaseTiposkripto.js +189 -0
- package/dist/module/lib/tiposkripto/src/BaseWhen.js +42 -0
- package/dist/module/lib/tiposkripto/src/CoreTypes.js +1 -0
- package/dist/module/lib/tiposkripto/src/Node.js +30 -0
- package/dist/module/lib/tiposkripto/src/Web.js +55 -0
- package/dist/module/lib/tiposkripto/src/index.js +48 -0
- package/dist/module/lib/tiposkripto/src/types.js +3 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/MockGiven.js +18 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/MockThen.js +12 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/MockWhen.js +14 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/adapter.js +21 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/implementation.js +35 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/index.js +12 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/specification.js +15 -0
- package/dist/module/lib/tiposkripto/tests/abstractBase.test/types.js +1 -0
- package/dist/module/package.json +3 -0
- package/dist/module/tsconfig.module.tsbuildinfo +1 -0
- package/dist/types/Types.d.ts +68 -0
- package/dist/types/lib/tiposkripto/src/BaseGiven.d.ts +42 -0
- package/dist/types/lib/tiposkripto/src/BaseSuite.d.ts +46 -0
- package/dist/types/lib/tiposkripto/src/BaseThen.d.ts +28 -0
- package/dist/types/lib/tiposkripto/src/BaseTiposkripto.d.ts +36 -0
- package/dist/types/lib/tiposkripto/src/BaseWhen.d.ts +27 -0
- package/dist/types/lib/tiposkripto/src/CoreTypes.d.ts +55 -0
- package/dist/types/lib/tiposkripto/src/Node.d.ts +9 -0
- package/dist/types/lib/tiposkripto/src/Web.d.ts +9 -0
- package/dist/types/lib/tiposkripto/src/index.d.ts +8 -0
- package/dist/types/lib/tiposkripto/src/types.d.ts +60 -0
- package/dist/types/tsconfig.types.tsbuildinfo +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export class BaseGiven {
|
|
2
|
+
addArtifact(path) {
|
|
3
|
+
if (typeof path !== "string") {
|
|
4
|
+
throw new Error(`[ARTIFACT ERROR] Expected string, got ${typeof path}: ${JSON.stringify(path)}`);
|
|
5
|
+
}
|
|
6
|
+
const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators
|
|
7
|
+
this.artifacts.push(normalizedPath);
|
|
8
|
+
}
|
|
9
|
+
constructor(features, whens, thens, givenCB, initialValues) {
|
|
10
|
+
this.artifacts = [];
|
|
11
|
+
this.features = features;
|
|
12
|
+
this.whens = whens;
|
|
13
|
+
this.thens = thens;
|
|
14
|
+
this.givenCB = givenCB;
|
|
15
|
+
this.initialValues = initialValues;
|
|
16
|
+
this.fails = 0; // Initialize fail count
|
|
17
|
+
}
|
|
18
|
+
beforeAll(store) {
|
|
19
|
+
return store;
|
|
20
|
+
}
|
|
21
|
+
toObj() {
|
|
22
|
+
return {
|
|
23
|
+
key: this.key,
|
|
24
|
+
whens: (this.whens || []).map((w) => {
|
|
25
|
+
if (w && w.toObj)
|
|
26
|
+
return w.toObj();
|
|
27
|
+
console.error("When step is not as expected!", JSON.stringify(w));
|
|
28
|
+
return {};
|
|
29
|
+
}),
|
|
30
|
+
thens: (this.thens || []).map((t) => (t && t.toObj ? t.toObj() : {})),
|
|
31
|
+
error: this.error ? [this.error, this.error.stack] : null,
|
|
32
|
+
failed: this.failed,
|
|
33
|
+
features: this.features || [],
|
|
34
|
+
artifacts: this.artifacts,
|
|
35
|
+
status: this.status,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async afterEach(store, key, artifactory) {
|
|
39
|
+
return store;
|
|
40
|
+
}
|
|
41
|
+
async give(subject, key, testResourceConfiguration, tester, artifactory, suiteNdx) {
|
|
42
|
+
this.key = key;
|
|
43
|
+
this.fails = 0; // Initialize fail count for this given
|
|
44
|
+
const givenArtifactory = (fPath, value) => artifactory(`given-${key}/${fPath}`, value);
|
|
45
|
+
try {
|
|
46
|
+
// Ensure addArtifact is properly bound to 'this'
|
|
47
|
+
const addArtifact = this.addArtifact.bind(this);
|
|
48
|
+
this.store = await this.givenThat(subject, testResourceConfiguration, givenArtifactory, this.givenCB, this.initialValues);
|
|
49
|
+
this.status = true;
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
this.status = false;
|
|
53
|
+
this.failed = true;
|
|
54
|
+
this.fails++; // Increment fail count
|
|
55
|
+
this.error = e.stack;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const whens = this.whens || [];
|
|
59
|
+
for (const [thenNdx, thenStep] of this.thens.entries()) {
|
|
60
|
+
try {
|
|
61
|
+
const t = await thenStep.test(this.store, testResourceConfiguration, `suite-${suiteNdx}/given-${key}/then-${thenNdx}`);
|
|
62
|
+
// If the test doesn't throw, it passed
|
|
63
|
+
tester(t);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
// Mark the given as failed if any then step fails
|
|
67
|
+
this.failed = true;
|
|
68
|
+
this.fails++; // Increment fail count
|
|
69
|
+
// Re-throw to propagate the error
|
|
70
|
+
throw e;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
this.error = e.stack;
|
|
76
|
+
this.failed = true;
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
try {
|
|
80
|
+
const addArtifact = this.addArtifact.bind(this);
|
|
81
|
+
await this.afterEach(this.store, this.key);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
this.failed = true;
|
|
85
|
+
this.fails++; // Increment fail count
|
|
86
|
+
throw e;
|
|
87
|
+
// this.error = e.message;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return this.store;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
export class BaseSuite {
|
|
2
|
+
addArtifact(path) {
|
|
3
|
+
if (typeof path !== "string") {
|
|
4
|
+
throw new Error(`[ARTIFACT ERROR] Expected string, got ${typeof path}: ${JSON.stringify(path)}`);
|
|
5
|
+
}
|
|
6
|
+
const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators
|
|
7
|
+
this.artifacts.push(normalizedPath);
|
|
8
|
+
}
|
|
9
|
+
constructor(name, index, givens = {}) {
|
|
10
|
+
this.artifacts = [];
|
|
11
|
+
const suiteName = name || "testSuite"; // Ensure name is never undefined
|
|
12
|
+
if (!suiteName) {
|
|
13
|
+
throw new Error("BaseSuite requires a non-empty name");
|
|
14
|
+
}
|
|
15
|
+
this.name = suiteName;
|
|
16
|
+
this.index = index;
|
|
17
|
+
this.givens = givens;
|
|
18
|
+
this.fails = 0;
|
|
19
|
+
}
|
|
20
|
+
features() {
|
|
21
|
+
try {
|
|
22
|
+
const features = Object.keys(this.givens)
|
|
23
|
+
.map((k) => this.givens[k].features)
|
|
24
|
+
.flat()
|
|
25
|
+
.filter((value, index, array) => {
|
|
26
|
+
return array.indexOf(value) === index;
|
|
27
|
+
});
|
|
28
|
+
// Convert all features to strings
|
|
29
|
+
const stringFeatures = features.map((feature) => {
|
|
30
|
+
if (typeof feature === "string") {
|
|
31
|
+
return feature;
|
|
32
|
+
}
|
|
33
|
+
else if (feature && typeof feature === "object") {
|
|
34
|
+
return feature.name || JSON.stringify(feature);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return String(feature);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return stringFeatures || [];
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
console.error("[ERROR] Failed to extract features:", JSON.stringify(e));
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
toObj() {
|
|
48
|
+
const givens = Object.keys(this.givens).map((k) => {
|
|
49
|
+
const givenObj = this.givens[k].toObj();
|
|
50
|
+
// Ensure given features are strings
|
|
51
|
+
// if (givenObj.features) {
|
|
52
|
+
// givenObj.features = givenObj.features.map(feature => {
|
|
53
|
+
// return feature;
|
|
54
|
+
// // if (typeof feature === 'string') {
|
|
55
|
+
// // return feature;
|
|
56
|
+
// // } else if (feature && typeof feature === 'object') {
|
|
57
|
+
// // return feature.name || JSON.stringify(feature);
|
|
58
|
+
// // } else {
|
|
59
|
+
// // return String(feature);
|
|
60
|
+
// // }
|
|
61
|
+
// });
|
|
62
|
+
// }
|
|
63
|
+
return givenObj;
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
name: this.name,
|
|
67
|
+
givens,
|
|
68
|
+
fails: this.fails,
|
|
69
|
+
failed: this.failed,
|
|
70
|
+
features: this.features(),
|
|
71
|
+
artifacts: this.artifacts
|
|
72
|
+
? this.artifacts.filter((art) => typeof art === "string")
|
|
73
|
+
: [],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
setup(s, artifactory, tr
|
|
77
|
+
// pm: IPM
|
|
78
|
+
) {
|
|
79
|
+
console.log("mark9");
|
|
80
|
+
return new Promise((res) => res(s));
|
|
81
|
+
}
|
|
82
|
+
assertThat(t) {
|
|
83
|
+
return !!t;
|
|
84
|
+
}
|
|
85
|
+
afterAll(store, artifactory) {
|
|
86
|
+
return store;
|
|
87
|
+
}
|
|
88
|
+
async run(input, testResourceConfiguration) {
|
|
89
|
+
this.testResourceConfiguration = testResourceConfiguration;
|
|
90
|
+
const sNdx = this.index;
|
|
91
|
+
const subject = await this.setup(input,
|
|
92
|
+
// suiteArtifactory,
|
|
93
|
+
testResourceConfiguration
|
|
94
|
+
// proxiedPm
|
|
95
|
+
);
|
|
96
|
+
for (const [gKey, g] of Object.entries(this.givens)) {
|
|
97
|
+
const giver = this.givens[gKey];
|
|
98
|
+
try {
|
|
99
|
+
this.store = await giver.give(subject, gKey, testResourceConfiguration, this.assertThat, sNdx);
|
|
100
|
+
// Add the number of failures from this given to the suite's total
|
|
101
|
+
this.fails += giver.fails || 0;
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
this.failed = true;
|
|
105
|
+
// Add 1 to fails for the caught error
|
|
106
|
+
this.fails += 1;
|
|
107
|
+
// Also add any failures from the given itself
|
|
108
|
+
if (giver.fails) {
|
|
109
|
+
this.fails += giver.fails;
|
|
110
|
+
}
|
|
111
|
+
console.error(`Error in given ${gKey}:`, e);
|
|
112
|
+
// Don't re-throw to continue with other givens
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Mark the suite as failed if there are any failures
|
|
116
|
+
if (this.fails > 0) {
|
|
117
|
+
this.failed = true;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
// Ensure addArtifact is properly bound to 'this'
|
|
121
|
+
this.afterAll(this.store);
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
console.error(JSON.stringify(e));
|
|
125
|
+
// this.fails.push(this);
|
|
126
|
+
// return this;
|
|
127
|
+
}
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export class BaseThen {
|
|
2
|
+
constructor(name, thenCB) {
|
|
3
|
+
this.artifacts = [];
|
|
4
|
+
this.name = name;
|
|
5
|
+
this.thenCB = thenCB;
|
|
6
|
+
this.error = false;
|
|
7
|
+
this.artifacts = [];
|
|
8
|
+
}
|
|
9
|
+
addArtifact(path) {
|
|
10
|
+
if (typeof path !== "string") {
|
|
11
|
+
throw new Error(`[ARTIFACT ERROR] Expected string, got ${typeof path}: ${JSON.stringify(path)}`);
|
|
12
|
+
}
|
|
13
|
+
const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators
|
|
14
|
+
this.artifacts.push(normalizedPath);
|
|
15
|
+
}
|
|
16
|
+
toObj() {
|
|
17
|
+
const obj = {
|
|
18
|
+
name: this.name,
|
|
19
|
+
error: this.error,
|
|
20
|
+
artifacts: this.artifacts,
|
|
21
|
+
status: this.status,
|
|
22
|
+
};
|
|
23
|
+
return obj;
|
|
24
|
+
}
|
|
25
|
+
async test(store, testResourceConfiguration,
|
|
26
|
+
// tLog: ITLog,
|
|
27
|
+
// pm: IPM,
|
|
28
|
+
filepath) {
|
|
29
|
+
// Ensure addArtifact is properly bound to 'this'
|
|
30
|
+
const addArtifact = this.addArtifact.bind(this);
|
|
31
|
+
// const proxiedPm = butThenProxy(pm, filepath, addArtifact);
|
|
32
|
+
try {
|
|
33
|
+
const x = await this.butThen(store, async (s) => {
|
|
34
|
+
try {
|
|
35
|
+
if (typeof this.thenCB === "function") {
|
|
36
|
+
const result = await this.thenCB(s);
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return this.thenCB;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
// Mark this then step as failed
|
|
45
|
+
this.error = true;
|
|
46
|
+
// Re-throw to be caught by the outer catch block
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
49
|
+
}, testResourceConfiguration
|
|
50
|
+
// proxiedPm
|
|
51
|
+
);
|
|
52
|
+
this.status = true;
|
|
53
|
+
return x;
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
this.status = false;
|
|
57
|
+
this.error = true;
|
|
58
|
+
throw e;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { DefaultAdapter } from "./index.js";
|
|
2
|
+
import { BaseGiven } from "./BaseGiven";
|
|
3
|
+
import { BaseSuite } from "./BaseSuite";
|
|
4
|
+
import { BaseThen } from "./BaseThen";
|
|
5
|
+
import { BaseWhen } from "./BaseWhen";
|
|
6
|
+
import { defaultTestResourceRequirement } from "./types.js";
|
|
7
|
+
export default class BaseTiposkripto {
|
|
8
|
+
constructor(webOrNode, input, testSpecification, testImplementation, testResourceRequirement = defaultTestResourceRequirement, testAdapter = {}, testResourceConfiguration, wsPort = "3456", wsHost = "localhost") {
|
|
9
|
+
this.totalTests = 0;
|
|
10
|
+
this.artifacts = [];
|
|
11
|
+
this.testResourceConfiguration = testResourceConfiguration;
|
|
12
|
+
const fullAdapter = DefaultAdapter(testAdapter);
|
|
13
|
+
if (!testImplementation.suites ||
|
|
14
|
+
typeof testImplementation.suites !== "object") {
|
|
15
|
+
throw new Error(`testImplementation.suites must be an object, got ${typeof testImplementation.suites}: ${JSON.stringify(testImplementation.suites)}`);
|
|
16
|
+
}
|
|
17
|
+
const classySuites = Object.entries(testImplementation.suites).reduce((a, [key], index) => {
|
|
18
|
+
a[key] = (somestring, givens) => {
|
|
19
|
+
return new (class extends BaseSuite {
|
|
20
|
+
afterAll(store) {
|
|
21
|
+
return fullAdapter.afterAll(store);
|
|
22
|
+
}
|
|
23
|
+
assertThat(t) {
|
|
24
|
+
return fullAdapter.assertThis(t);
|
|
25
|
+
}
|
|
26
|
+
async setup(s, tr) {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
return ((_b = (_a = fullAdapter.beforeAll) === null || _a === void 0 ? void 0 : _a.call(fullAdapter, s, tr)) !== null && _b !== void 0 ? _b : s);
|
|
29
|
+
}
|
|
30
|
+
})(somestring, index, givens);
|
|
31
|
+
};
|
|
32
|
+
return a;
|
|
33
|
+
}, {});
|
|
34
|
+
const classyGivens = Object.entries(testImplementation.givens).reduce((a, [key, g]) => {
|
|
35
|
+
a[key] = (features, whens, thens, gcb, initialValues) => {
|
|
36
|
+
// WTF
|
|
37
|
+
// Ensure parameters are arrays and create copies to avoid reference issues
|
|
38
|
+
const safeFeatures = Array.isArray(features) ? [...features] : [];
|
|
39
|
+
const safeWhens = Array.isArray(whens) ? [...whens] : [];
|
|
40
|
+
const safeThens = Array.isArray(thens) ? [...thens] : [];
|
|
41
|
+
return new (class extends BaseGiven {
|
|
42
|
+
async givenThat(subject, testResource, initializer, initialValues) {
|
|
43
|
+
return fullAdapter.beforeEach(subject, initializer, testResource, initialValues);
|
|
44
|
+
}
|
|
45
|
+
afterEach(store, key) {
|
|
46
|
+
return Promise.resolve(fullAdapter.afterEach(store, key));
|
|
47
|
+
}
|
|
48
|
+
})(safeFeatures, safeWhens, safeThens, testImplementation.givens[key], initialValues);
|
|
49
|
+
};
|
|
50
|
+
return a;
|
|
51
|
+
}, {});
|
|
52
|
+
const classyWhens = Object.entries(testImplementation.whens).reduce((a, [key, whEn]) => {
|
|
53
|
+
a[key] = (...payload) => {
|
|
54
|
+
const whenInstance = new (class extends BaseWhen {
|
|
55
|
+
async andWhen(store, whenCB, testResource) {
|
|
56
|
+
return await fullAdapter.andWhen(store, whenCB, testResource);
|
|
57
|
+
}
|
|
58
|
+
})(`${key}: ${payload && payload.toString()}`, whEn(...payload));
|
|
59
|
+
return whenInstance;
|
|
60
|
+
};
|
|
61
|
+
return a;
|
|
62
|
+
}, {});
|
|
63
|
+
const classyThens = Object.entries(testImplementation.thens).reduce((a, [key, thEn]) => {
|
|
64
|
+
a[key] = (...args) => {
|
|
65
|
+
const thenInstance = new (class extends BaseThen {
|
|
66
|
+
async butThen(store, thenCB, testResource) {
|
|
67
|
+
return await fullAdapter.butThen(store, thenCB, testResource);
|
|
68
|
+
}
|
|
69
|
+
})(`${key}: ${args && args.toString()}`, thEn(...args));
|
|
70
|
+
return thenInstance;
|
|
71
|
+
};
|
|
72
|
+
return a;
|
|
73
|
+
}, {});
|
|
74
|
+
this.suitesOverrides = classySuites;
|
|
75
|
+
this.givenOverrides = classyGivens;
|
|
76
|
+
this.whenOverrides = classyWhens;
|
|
77
|
+
this.thenOverrides = classyThens;
|
|
78
|
+
this.testResourceRequirement = testResourceRequirement;
|
|
79
|
+
this.testSpecification = testSpecification;
|
|
80
|
+
this.specs = testSpecification(this.Suites(), this.Given(), this.When(), this.Then());
|
|
81
|
+
this.totalTests = this.calculateTotalTests();
|
|
82
|
+
this.testJobs = this.specs.map((suite) => {
|
|
83
|
+
const suiteRunner = (suite) => async (testResourceConfiguration) => {
|
|
84
|
+
try {
|
|
85
|
+
const x = await suite.run(input, testResourceConfiguration || {
|
|
86
|
+
name: suite.name,
|
|
87
|
+
fs: process.cwd(),
|
|
88
|
+
ports: [],
|
|
89
|
+
timeout: 30000,
|
|
90
|
+
retries: 3,
|
|
91
|
+
environment: {},
|
|
92
|
+
files: []
|
|
93
|
+
});
|
|
94
|
+
return x;
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
console.error(e.stack);
|
|
98
|
+
throw e;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const runner = suiteRunner(suite);
|
|
102
|
+
const totalTests = this.totalTests;
|
|
103
|
+
const testJob = {
|
|
104
|
+
test: suite,
|
|
105
|
+
toObj: () => {
|
|
106
|
+
return suite.toObj();
|
|
107
|
+
},
|
|
108
|
+
runner,
|
|
109
|
+
receiveTestResourceConfig: async (testResourceConfiguration) => {
|
|
110
|
+
try {
|
|
111
|
+
const suiteDone = await runner(testResourceConfiguration);
|
|
112
|
+
const fails = suiteDone.fails;
|
|
113
|
+
return {
|
|
114
|
+
failed: fails > 0,
|
|
115
|
+
fails,
|
|
116
|
+
artifacts: [], // this.artifacts is not accessible here
|
|
117
|
+
features: suiteDone.features(),
|
|
118
|
+
tests: 0,
|
|
119
|
+
runTimeTests: totalTests,
|
|
120
|
+
testJob: testJob.toObj(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
console.error(e.stack);
|
|
125
|
+
return {
|
|
126
|
+
failed: true,
|
|
127
|
+
fails: -1,
|
|
128
|
+
artifacts: [],
|
|
129
|
+
features: [],
|
|
130
|
+
tests: 0,
|
|
131
|
+
runTimeTests: -1,
|
|
132
|
+
testJob: testJob.toObj(),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
return testJob;
|
|
138
|
+
});
|
|
139
|
+
this.testJobs[0].receiveTestResourceConfig(testResourceConfiguration).then((results) => {
|
|
140
|
+
this.writeFileSync(`testeranto/reports/${this.testResourceConfiguration.fs}`, JSON.stringify(results));
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async receiveTestResourceConfig(testResourceConfig) {
|
|
144
|
+
if (this.testJobs && this.testJobs.length > 0) {
|
|
145
|
+
return this.testJobs[0].receiveTestResourceConfig(testResourceConfig);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
throw new Error("No test jobs available");
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
Specs() {
|
|
152
|
+
return this.specs;
|
|
153
|
+
}
|
|
154
|
+
Suites() {
|
|
155
|
+
if (!this.suitesOverrides) {
|
|
156
|
+
throw new Error(`suitesOverrides is undefined. classySuites: ${JSON.stringify(Object.keys(this.suitesOverrides || {}))}`);
|
|
157
|
+
}
|
|
158
|
+
return this.suitesOverrides;
|
|
159
|
+
}
|
|
160
|
+
Given() {
|
|
161
|
+
return this.givenOverrides;
|
|
162
|
+
}
|
|
163
|
+
When() {
|
|
164
|
+
return this.whenOverrides;
|
|
165
|
+
}
|
|
166
|
+
Then() {
|
|
167
|
+
return this.thenOverrides;
|
|
168
|
+
}
|
|
169
|
+
// Add a method to access test jobs which can be used by receiveTestResourceConfig
|
|
170
|
+
getTestJobs() {
|
|
171
|
+
return this.testJobs;
|
|
172
|
+
}
|
|
173
|
+
calculateTotalTests() {
|
|
174
|
+
let total = 0;
|
|
175
|
+
for (const suite of this.specs) {
|
|
176
|
+
if (suite && typeof suite === "object") {
|
|
177
|
+
// Access the givens property which should be a record of test names to BaseGiven instances
|
|
178
|
+
// The givens property is typically on the suite instance
|
|
179
|
+
if ("givens" in suite) {
|
|
180
|
+
const givens = suite.givens;
|
|
181
|
+
if (givens && typeof givens === "object") {
|
|
182
|
+
total += Object.keys(givens).length;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return total;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export class BaseWhen {
|
|
2
|
+
addArtifact(path) {
|
|
3
|
+
if (typeof path !== "string") {
|
|
4
|
+
throw new Error(`[ARTIFACT ERROR] Expected string, got ${typeof path}: ${JSON.stringify(path)}`);
|
|
5
|
+
}
|
|
6
|
+
const normalizedPath = path.replace(/\\/g, "/"); // Normalize path separators
|
|
7
|
+
this.artifacts.push(normalizedPath);
|
|
8
|
+
}
|
|
9
|
+
constructor(name, whenCB) {
|
|
10
|
+
this.artifacts = [];
|
|
11
|
+
this.name = name;
|
|
12
|
+
this.whenCB = whenCB;
|
|
13
|
+
}
|
|
14
|
+
toObj() {
|
|
15
|
+
const obj = {
|
|
16
|
+
name: this.name,
|
|
17
|
+
status: this.status,
|
|
18
|
+
error: this.error
|
|
19
|
+
? `${this.error.name}: ${this.error.message}\n${this.error.stack}`
|
|
20
|
+
: null,
|
|
21
|
+
artifacts: this.artifacts,
|
|
22
|
+
};
|
|
23
|
+
return obj;
|
|
24
|
+
}
|
|
25
|
+
async test(store, testResourceConfiguration) {
|
|
26
|
+
try {
|
|
27
|
+
// Ensure addArtifact is properly bound to 'this'
|
|
28
|
+
// const addArtifact = this.addArtifact.bind(this);
|
|
29
|
+
// const proxiedPm = andWhenProxy(pm, filepath, addArtifact);
|
|
30
|
+
const result = await this.andWhen(store, this.whenCB, testResourceConfiguration
|
|
31
|
+
// proxiedPm
|
|
32
|
+
);
|
|
33
|
+
this.status = true;
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
this.status = false;
|
|
38
|
+
this.error = e;
|
|
39
|
+
throw e;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import BaseTiposkripto from "./BaseTiposkripto";
|
|
3
|
+
import { defaultTestResourceRequirement } from "./types";
|
|
4
|
+
console.log(`[NodeTiposkripto] ${process.argv}`);
|
|
5
|
+
const config = process.argv0[2];
|
|
6
|
+
export class NodeTiposkripto extends BaseTiposkripto {
|
|
7
|
+
constructor(input, testSpecification, testImplementation, testResourceRequirement, testAdapter) {
|
|
8
|
+
super("node", input, testSpecification, testImplementation, testResourceRequirement, testAdapter, config);
|
|
9
|
+
}
|
|
10
|
+
writeFileSync(filename, payload) {
|
|
11
|
+
// console.log('writeFileSync', filename)
|
|
12
|
+
// const dir = `testeranto/reports/${this.testResourceConfiguration.fs}`;
|
|
13
|
+
// if (!fs.existsSync(dir)) {
|
|
14
|
+
// fs.mkdirSync(dir, { recursive: true });
|
|
15
|
+
// }
|
|
16
|
+
fs.writeFileSync(filename, payload);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const tiposkripto = async (input, testSpecification, testImplementation, testAdapter, testResourceRequirement = defaultTestResourceRequirement) => {
|
|
20
|
+
try {
|
|
21
|
+
const t = new NodeTiposkripto(input, testSpecification, testImplementation, testResourceRequirement, testAdapter);
|
|
22
|
+
return t;
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
console.error(`[Node] Error creating Tiposkripto:`, e);
|
|
26
|
+
console.error(e.stack);
|
|
27
|
+
process.exit(-1);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export default tiposkripto;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import BaseTiposkripto from "./BaseTiposkripto.js";
|
|
2
|
+
import { defaultTestResourceRequirement } from "./types.js";
|
|
3
|
+
const config = process.argv0[2];
|
|
4
|
+
export class WebTiposkripto extends BaseTiposkripto {
|
|
5
|
+
constructor(input, testSpecification, testImplementation, testResourceRequirement, testAdapter) {
|
|
6
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
7
|
+
const encodedConfig = urlParams.get("config");
|
|
8
|
+
const testResourceConfig = encodedConfig
|
|
9
|
+
? decodeURIComponent(encodedConfig)
|
|
10
|
+
: "{}";
|
|
11
|
+
super("web", input, testSpecification, testImplementation, testResourceRequirement, testAdapter,
|
|
12
|
+
// JSON.parse(testResourceConfig)
|
|
13
|
+
config);
|
|
14
|
+
}
|
|
15
|
+
writeFileSync(filename, payload) {
|
|
16
|
+
// Store files in a global object that can be accessed via Puppeteer
|
|
17
|
+
if (!window.__testeranto_files__) {
|
|
18
|
+
window.__testeranto_files__ = {};
|
|
19
|
+
}
|
|
20
|
+
window.__testeranto_files__[filename] = payload;
|
|
21
|
+
// Also try to use the File System Access API if available
|
|
22
|
+
if (navigator.storage && navigator.storage.getDirectory) {
|
|
23
|
+
(async () => {
|
|
24
|
+
try {
|
|
25
|
+
const root = await navigator.storage.getDirectory();
|
|
26
|
+
const fileHandle = await root.getFileHandle(filename, { create: true });
|
|
27
|
+
const writable = await fileHandle.createWritable();
|
|
28
|
+
await writable.write(payload);
|
|
29
|
+
await writable.close();
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
console.warn('Could not write to browser storage:', e);
|
|
33
|
+
}
|
|
34
|
+
})();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const tiposkripto = async (input, testSpecification, testImplementation, testAdapter, testResourceRequirement = defaultTestResourceRequirement) => {
|
|
39
|
+
try {
|
|
40
|
+
const t = new WebTiposkripto(input, testSpecification, testImplementation, testResourceRequirement, testAdapter);
|
|
41
|
+
// const data = navigator.storage.
|
|
42
|
+
const root = await navigator.storage.getDirectory();
|
|
43
|
+
// 1. Create (or get) a file handle
|
|
44
|
+
const fileHandle = await root.getFileHandle(`${config.fs}/tests.json`);
|
|
45
|
+
return t;
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
console.error(e);
|
|
49
|
+
// Dispatch an error event
|
|
50
|
+
const errorEvent = new CustomEvent("test-error", { detail: e });
|
|
51
|
+
window.dispatchEvent(errorEvent);
|
|
52
|
+
throw e;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
export default tiposkripto;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { defaultTestResourceRequirement } from "./types";
|
|
2
|
+
// let tpskrt;
|
|
3
|
+
// // Use esbuild define to distinguish environments
|
|
4
|
+
// declare const ENV: "node" | "web";
|
|
5
|
+
// if (ENV === "node") {
|
|
6
|
+
// tpskrt = await import("./Node");
|
|
7
|
+
// } else if (ENV === "web") {
|
|
8
|
+
// tpskrt = await import("./Web");
|
|
9
|
+
// } else {
|
|
10
|
+
// throw `Unknown ENV ${ENV}`;
|
|
11
|
+
// }
|
|
12
|
+
let tpskrt;
|
|
13
|
+
const tpskrtNode = await import("./Node");
|
|
14
|
+
// const tpskrtWeb = await import("./Web");
|
|
15
|
+
tpskrt = tpskrtNode;
|
|
16
|
+
// Use esbuild define to distinguish environments
|
|
17
|
+
// declare const ENV: "node" | "web";
|
|
18
|
+
// if (ENV === "node") {
|
|
19
|
+
// tpskrt = tpskrtNode
|
|
20
|
+
// } else if (ENV === "web") {
|
|
21
|
+
// tpskrt = tpskrtWeb
|
|
22
|
+
// } else {
|
|
23
|
+
// throw `Unknown ENV ${ENV}`;
|
|
24
|
+
// }
|
|
25
|
+
export default async (input, testSpecification, testImplementation, testAdapter, testResourceRequirement = defaultTestResourceRequirement, testResourceConfiguration) => {
|
|
26
|
+
return (await tpskrt.default)(input, testSpecification, testImplementation, testResourceRequirement, testAdapter, testResourceConfiguration);
|
|
27
|
+
};
|
|
28
|
+
export const BaseAdapter = () => ({
|
|
29
|
+
beforeAll: async (input, testResource) => {
|
|
30
|
+
return input;
|
|
31
|
+
},
|
|
32
|
+
beforeEach: async function (subject, initializer, testResource, initialValues) {
|
|
33
|
+
return subject;
|
|
34
|
+
},
|
|
35
|
+
afterEach: async (store, key) => Promise.resolve(store),
|
|
36
|
+
afterAll: (store) => undefined,
|
|
37
|
+
butThen: async (store, thenCb, testResource) => {
|
|
38
|
+
return thenCb(store);
|
|
39
|
+
},
|
|
40
|
+
andWhen: async (store, whenCB, testResource) => {
|
|
41
|
+
return whenCB(store);
|
|
42
|
+
},
|
|
43
|
+
assertThis: (x) => x,
|
|
44
|
+
});
|
|
45
|
+
export const DefaultAdapter = (p) => {
|
|
46
|
+
const base = BaseAdapter();
|
|
47
|
+
return Object.assign(Object.assign({}, base), p);
|
|
48
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseGiven } from "../BaseGiven";
|
|
2
|
+
export class MockGiven extends BaseGiven {
|
|
3
|
+
constructor(name, features, whens, thens, givenCB, initialValues) {
|
|
4
|
+
super(name, features, whens, thens, givenCB, initialValues);
|
|
5
|
+
}
|
|
6
|
+
async givenThat(subject, testResourceConfiguration, artifactory, givenCB, initialValues) {
|
|
7
|
+
// Call the givenCB which is a function that returns the store
|
|
8
|
+
const result = givenCB();
|
|
9
|
+
if (typeof result === "function") {
|
|
10
|
+
return result();
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
uberCatcher(e) {
|
|
15
|
+
console.error("MockGiven error:", e);
|
|
16
|
+
this.error = e;
|
|
17
|
+
}
|
|
18
|
+
}
|