@featurevisor/core 0.52.1 → 0.53.1
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/.eslintcache +1 -1
- package/CHANGELOG.md +19 -0
- package/coverage/clover.xml +2 -2
- package/coverage/lcov-report/index.html +1 -1
- package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
- package/coverage/lcov-report/lib/builder/index.html +1 -1
- package/coverage/lcov-report/lib/builder/traffic.js.html +1 -1
- package/coverage/lcov-report/src/builder/allocator.ts.html +1 -1
- package/coverage/lcov-report/src/builder/index.html +1 -1
- package/coverage/lcov-report/src/builder/traffic.ts.html +1 -1
- package/lib/find-duplicate-segments/findDuplicateSegments.d.ts +3 -0
- package/lib/find-duplicate-segments/findDuplicateSegments.js +27 -0
- package/lib/find-duplicate-segments/findDuplicateSegments.js.map +1 -0
- package/lib/find-duplicate-segments/index.d.ts +2 -0
- package/lib/find-duplicate-segments/index.js +19 -0
- package/lib/find-duplicate-segments/index.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/tester/checkIfArraysAreEqual.d.ts +1 -0
- package/lib/tester/checkIfArraysAreEqual.js +19 -0
- package/lib/tester/checkIfArraysAreEqual.js.map +1 -0
- package/lib/tester/checkIfObjectsAreEqual.d.ts +1 -0
- package/lib/tester/checkIfObjectsAreEqual.js +22 -0
- package/lib/tester/checkIfObjectsAreEqual.js.map +1 -0
- package/lib/tester/index.d.ts +1 -0
- package/lib/tester/index.js +18 -0
- package/lib/tester/index.js.map +1 -0
- package/lib/tester/testFeature.d.ts +4 -0
- package/lib/tester/testFeature.js +74 -0
- package/lib/tester/testFeature.js.map +1 -0
- package/lib/tester/testProject.d.ts +2 -0
- package/lib/tester/testProject.js +51 -0
- package/lib/tester/testProject.js.map +1 -0
- package/lib/tester/testSegment.d.ts +3 -0
- package/lib/tester/testSegment.js +30 -0
- package/lib/tester/testSegment.js.map +1 -0
- package/package.json +5 -5
- package/src/find-duplicate-segments/findDuplicateSegments.ts +33 -0
- package/src/find-duplicate-segments/index.ts +21 -0
- package/src/index.ts +1 -0
- package/src/tester/checkIfArraysAreEqual.ts +16 -0
- package/src/tester/checkIfObjectsAreEqual.ts +21 -0
- package/src/tester/index.ts +1 -0
- package/src/tester/testFeature.ts +112 -0
- package/src/tester/testProject.ts +63 -0
- package/src/tester/testSegment.ts +41 -0
- package/lib/tester.d.ts +0 -4
- package/lib/tester.js +0 -159
- package/lib/tester.js.map +0 -1
- package/src/tester.ts +0 -213
package/src/tester.ts
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
|
|
3
|
-
import { Condition, ExistingState, TestSegment, TestFeature } from "@featurevisor/types";
|
|
4
|
-
import { createInstance, allConditionsAreMatched, MAX_BUCKETED_NUMBER } from "@featurevisor/sdk";
|
|
5
|
-
|
|
6
|
-
import { ProjectConfig, SCHEMA_VERSION } from "./config";
|
|
7
|
-
import { getExistingStateFilePath, buildDatafile } from "./builder";
|
|
8
|
-
import { Datasource } from "./datasource";
|
|
9
|
-
|
|
10
|
-
// @TODO: make it better
|
|
11
|
-
export function checkIfArraysAreEqual(a, b) {
|
|
12
|
-
if (!Array.isArray(a) || !Array.isArray(b)) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (a.length !== b.length) return false;
|
|
17
|
-
|
|
18
|
-
for (let i = 0; i < a.length; ++i) {
|
|
19
|
-
if (a[i] !== b[i]) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function checkIfObjectsAreEqual(a, b) {
|
|
28
|
-
if (typeof a !== "object" || typeof b !== "object") {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (a === null || b === null) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (Object.keys(a).length !== Object.keys(b).length) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
for (const key in a) {
|
|
41
|
-
if (a[key] !== b[key]) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function testProject(rootDirectoryPath: string, projectConfig: ProjectConfig): boolean {
|
|
50
|
-
let hasError = false;
|
|
51
|
-
const datasource = new Datasource(projectConfig);
|
|
52
|
-
|
|
53
|
-
if (!fs.existsSync(projectConfig.testsDirectoryPath)) {
|
|
54
|
-
console.error(`Tests directory does not exist: ${projectConfig.testsDirectoryPath}`);
|
|
55
|
-
hasError = true;
|
|
56
|
-
|
|
57
|
-
return hasError;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const testFiles = datasource.listTests();
|
|
61
|
-
|
|
62
|
-
if (testFiles.length === 0) {
|
|
63
|
-
console.error(`No tests found in: ${projectConfig.testsDirectoryPath}`);
|
|
64
|
-
hasError = true;
|
|
65
|
-
|
|
66
|
-
return hasError;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
for (const testFile of testFiles) {
|
|
70
|
-
const testFilePath = datasource.getEntityPath("test", testFile);
|
|
71
|
-
|
|
72
|
-
console.log(` => Testing: ${testFilePath.replace(rootDirectoryPath, "")}`);
|
|
73
|
-
|
|
74
|
-
const test = datasource.readTest(testFile);
|
|
75
|
-
|
|
76
|
-
if ((test as TestSegment).segment) {
|
|
77
|
-
// segment testing
|
|
78
|
-
const testSegment = test as TestSegment;
|
|
79
|
-
const segmentKey = testSegment.segment;
|
|
80
|
-
|
|
81
|
-
console.log(` => Segment "${segmentKey}":`);
|
|
82
|
-
|
|
83
|
-
const segmentExists = datasource.entityExists("segment", segmentKey);
|
|
84
|
-
|
|
85
|
-
if (!segmentExists) {
|
|
86
|
-
console.error(` => Segment does not exist: ${segmentKey}`);
|
|
87
|
-
hasError = true;
|
|
88
|
-
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const parsedSegment = datasource.readSegment(segmentKey);
|
|
93
|
-
const conditions = parsedSegment.conditions as Condition | Condition[];
|
|
94
|
-
|
|
95
|
-
testSegment.assertions.forEach(function (assertion, aIndex) {
|
|
96
|
-
const description = assertion.description || `#${aIndex + 1}`;
|
|
97
|
-
|
|
98
|
-
console.log(` => Assertion #${aIndex + 1}: ${description}`);
|
|
99
|
-
|
|
100
|
-
const expected = assertion.expectedToMatch;
|
|
101
|
-
const actual = allConditionsAreMatched(conditions, assertion.context);
|
|
102
|
-
|
|
103
|
-
if (actual !== expected) {
|
|
104
|
-
hasError = true;
|
|
105
|
-
|
|
106
|
-
console.error(` Segment failed: expected "${expected}", got "${actual}"`);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
} else if ((test as TestFeature).feature) {
|
|
110
|
-
// feature testing
|
|
111
|
-
const testFeature = test as TestFeature;
|
|
112
|
-
const featureKey = testFeature.feature;
|
|
113
|
-
|
|
114
|
-
console.log(` => Feature "${featureKey}":`);
|
|
115
|
-
|
|
116
|
-
testFeature.assertions.forEach(function (assertion, aIndex) {
|
|
117
|
-
const description = assertion.description || `at ${assertion.at}%`;
|
|
118
|
-
|
|
119
|
-
console.log(
|
|
120
|
-
` => Assertion #${aIndex + 1}: (${assertion.environment}) ${description}`,
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
const featuresToInclude = Array.from(
|
|
124
|
-
datasource.getRequiredFeaturesChain(testFeature.feature),
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
const datafileContent = buildDatafile(
|
|
128
|
-
projectConfig,
|
|
129
|
-
datasource,
|
|
130
|
-
{
|
|
131
|
-
schemaVersion: SCHEMA_VERSION,
|
|
132
|
-
revision: "testing",
|
|
133
|
-
environment: assertion.environment,
|
|
134
|
-
features: featuresToInclude,
|
|
135
|
-
},
|
|
136
|
-
JSON.parse(
|
|
137
|
-
fs.readFileSync(getExistingStateFilePath(projectConfig, assertion.environment), "utf8"),
|
|
138
|
-
) as ExistingState,
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
const sdk = createInstance({
|
|
142
|
-
datafile: datafileContent,
|
|
143
|
-
configureBucketValue: () => {
|
|
144
|
-
return assertion.at * (MAX_BUCKETED_NUMBER / 100);
|
|
145
|
-
},
|
|
146
|
-
// logger: createLogger({
|
|
147
|
-
// levels: ["debug", "info", "warn", "error"],
|
|
148
|
-
// }),
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// isEnabled
|
|
152
|
-
if ("expectedToBeEnabled" in assertion) {
|
|
153
|
-
const isEnabled = sdk.isEnabled(featureKey, assertion.context);
|
|
154
|
-
|
|
155
|
-
if (isEnabled !== assertion.expectedToBeEnabled) {
|
|
156
|
-
hasError = true;
|
|
157
|
-
|
|
158
|
-
console.error(
|
|
159
|
-
` isEnabled failed: expected "${assertion.expectedToBeEnabled}", got "${isEnabled}"`,
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// variation
|
|
165
|
-
if ("expectedVariation" in assertion) {
|
|
166
|
-
const variation = sdk.getVariation(featureKey, assertion.context);
|
|
167
|
-
|
|
168
|
-
if (variation !== assertion.expectedVariation) {
|
|
169
|
-
hasError = true;
|
|
170
|
-
|
|
171
|
-
console.error(
|
|
172
|
-
` Variation failed: expected "${assertion.expectedVariation}", got "${variation}"`,
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// variables
|
|
178
|
-
if (typeof assertion.expectedVariables === "object") {
|
|
179
|
-
Object.keys(assertion.expectedVariables).forEach(function (variableKey) {
|
|
180
|
-
const expectedValue =
|
|
181
|
-
assertion.expectedVariables && assertion.expectedVariables[variableKey];
|
|
182
|
-
const actualValue = sdk.getVariable(featureKey, variableKey, assertion.context);
|
|
183
|
-
|
|
184
|
-
let passed;
|
|
185
|
-
|
|
186
|
-
if (typeof expectedValue === "object") {
|
|
187
|
-
passed = checkIfObjectsAreEqual(expectedValue, actualValue);
|
|
188
|
-
} else if (Array.isArray(expectedValue)) {
|
|
189
|
-
passed = checkIfArraysAreEqual(expectedValue, actualValue);
|
|
190
|
-
} else {
|
|
191
|
-
passed = expectedValue === actualValue;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (!passed) {
|
|
195
|
-
hasError = true;
|
|
196
|
-
|
|
197
|
-
console.error(
|
|
198
|
-
` Variable "${variableKey}" failed: expected ${JSON.stringify(
|
|
199
|
-
expectedValue,
|
|
200
|
-
)}, got "${JSON.stringify(actualValue)}"`,
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
} else {
|
|
207
|
-
console.error(` => Invalid test: ${JSON.stringify(test)}`);
|
|
208
|
-
hasError = true;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return hasError;
|
|
213
|
-
}
|