@featurevisor/core 1.31.0 → 1.32.0

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/coverage/clover.xml +11 -11
  3. package/coverage/coverage-final.json +2 -2
  4. package/coverage/lcov-report/index.html +7 -7
  5. package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
  6. package/coverage/lcov-report/lib/builder/index.html +1 -1
  7. package/coverage/lcov-report/lib/builder/revision.js.html +1 -1
  8. package/coverage/lcov-report/lib/builder/traffic.js.html +1 -1
  9. package/coverage/lcov-report/lib/tester/checkIfObjectsAreEqual.js.html +1 -1
  10. package/coverage/lcov-report/lib/tester/index.html +5 -5
  11. package/coverage/lcov-report/lib/tester/matrix.js.html +5 -5
  12. package/coverage/lcov-report/src/builder/allocator.ts.html +1 -1
  13. package/coverage/lcov-report/src/builder/index.html +1 -1
  14. package/coverage/lcov-report/src/builder/revision.ts.html +1 -1
  15. package/coverage/lcov-report/src/builder/traffic.ts.html +1 -1
  16. package/coverage/lcov-report/src/tester/checkIfObjectsAreEqual.ts.html +1 -1
  17. package/coverage/lcov-report/src/tester/index.html +5 -5
  18. package/coverage/lcov-report/src/tester/matrix.ts.html +5 -5
  19. package/coverage/lcov.info +30 -22
  20. package/lib/assess-distribution/index.d.ts +1 -1
  21. package/lib/assess-distribution/index.js +2 -2
  22. package/lib/assess-distribution/index.js.map +1 -1
  23. package/lib/benchmark/index.d.ts +1 -1
  24. package/lib/benchmark/index.js +2 -2
  25. package/lib/benchmark/index.js.map +1 -1
  26. package/lib/builder/buildDatafile.d.ts +1 -1
  27. package/lib/builder/buildDatafile.js +53 -40
  28. package/lib/builder/buildDatafile.js.map +1 -1
  29. package/lib/builder/buildProject.js +87 -50
  30. package/lib/builder/buildProject.js.map +1 -1
  31. package/lib/config/projectConfig.d.ts +1 -1
  32. package/lib/datasource/adapter.d.ts +3 -3
  33. package/lib/datasource/adapter.js.map +1 -1
  34. package/lib/datasource/datasource.d.ts +2 -2
  35. package/lib/datasource/datasource.js.map +1 -1
  36. package/lib/datasource/filesystemAdapter.d.ts +1 -1
  37. package/lib/datasource/filesystemAdapter.js +9 -3
  38. package/lib/datasource/filesystemAdapter.js.map +1 -1
  39. package/lib/evaluate/index.d.ts +1 -1
  40. package/lib/evaluate/index.js +2 -2
  41. package/lib/evaluate/index.js.map +1 -1
  42. package/lib/find-usage/index.js +60 -26
  43. package/lib/find-usage/index.js.map +1 -1
  44. package/lib/linter/featureSchema.d.ts +194 -5
  45. package/lib/linter/featureSchema.js +70 -60
  46. package/lib/linter/featureSchema.js.map +1 -1
  47. package/lib/linter/testSchema.d.ts +1 -1
  48. package/lib/linter/testSchema.js +16 -13
  49. package/lib/linter/testSchema.js.map +1 -1
  50. package/lib/site/generateSiteSearchIndex.js +65 -24
  51. package/lib/site/generateSiteSearchIndex.js.map +1 -1
  52. package/lib/tester/matrix.js +2 -2
  53. package/lib/tester/matrix.js.map +1 -1
  54. package/lib/tester/testFeature.d.ts +3 -4
  55. package/lib/tester/testFeature.js +1 -2
  56. package/lib/tester/testFeature.js.map +1 -1
  57. package/lib/tester/testProject.d.ts +1 -3
  58. package/lib/tester/testProject.js +28 -12
  59. package/lib/tester/testProject.js.map +1 -1
  60. package/package.json +5 -5
  61. package/src/assess-distribution/index.ts +3 -3
  62. package/src/benchmark/index.ts +3 -3
  63. package/src/builder/buildDatafile.ts +25 -8
  64. package/src/builder/buildProject.ts +72 -31
  65. package/src/config/projectConfig.ts +1 -1
  66. package/src/datasource/adapter.ts +6 -3
  67. package/src/datasource/datasource.ts +2 -2
  68. package/src/datasource/filesystemAdapter.ts +12 -4
  69. package/src/evaluate/index.ts +3 -3
  70. package/src/find-usage/index.ts +65 -29
  71. package/src/linter/featureSchema.ts +100 -82
  72. package/src/linter/testSchema.ts +21 -16
  73. package/src/site/generateSiteSearchIndex.ts +71 -24
  74. package/src/tester/matrix.ts +2 -2
  75. package/src/tester/testFeature.ts +3 -2
  76. package/src/tester/testProject.ts +27 -8
@@ -23,6 +23,10 @@ export async function generateSiteSearchIndex(
23
23
 
24
24
  const result: SearchIndex = {
25
25
  links: undefined,
26
+ projectConfig: {
27
+ tags: projectConfig.tags,
28
+ environments: projectConfig.environments,
29
+ },
26
30
  entities: {
27
31
  attributes: [],
28
32
  segments: [],
@@ -115,10 +119,52 @@ export async function generateSiteSearchIndex(
115
119
  });
116
120
  }
117
121
 
118
- Object.keys(parsed.environments).forEach((environmentKey) => {
119
- const env = parsed.environments[environmentKey];
122
+ // with environments
123
+ if (parsed.environments) {
124
+ Object.keys(parsed.environments).forEach((environmentKey) => {
125
+ const env = parsed.environments[environmentKey];
126
+
127
+ env.rules.forEach((rule) => {
128
+ if (rule.segments && rule.segments !== "*") {
129
+ extractSegmentKeysFromGroupSegments(rule.segments).forEach((segmentKey) => {
130
+ if (!segmentsUsedInFeatures[segmentKey]) {
131
+ segmentsUsedInFeatures[segmentKey] = new Set();
132
+ }
133
+
134
+ segmentsUsedInFeatures[segmentKey].add(entityName);
135
+ });
136
+ }
137
+ });
138
+
139
+ if (env.force) {
140
+ env.force.forEach((force) => {
141
+ if (force.segments && force.segments !== "*") {
142
+ extractSegmentKeysFromGroupSegments(force.segments).forEach((segmentKey) => {
143
+ if (!segmentsUsedInFeatures[segmentKey]) {
144
+ segmentsUsedInFeatures[segmentKey] = new Set();
145
+ }
120
146
 
121
- env.rules.forEach((rule) => {
147
+ segmentsUsedInFeatures[segmentKey].add(entityName);
148
+ });
149
+ }
150
+
151
+ if (force.conditions) {
152
+ extractAttributeKeysFromConditions(force.conditions).forEach((attributeKey) => {
153
+ if (!attributesUsedInFeatures[attributeKey]) {
154
+ attributesUsedInFeatures[attributeKey] = new Set();
155
+ }
156
+
157
+ attributesUsedInFeatures[attributeKey].add(entityName);
158
+ });
159
+ }
160
+ });
161
+ }
162
+ });
163
+ }
164
+
165
+ // no environments
166
+ if (parsed.rules) {
167
+ parsed.rules.forEach((rule) => {
122
168
  if (rule.segments && rule.segments !== "*") {
123
169
  extractSegmentKeysFromGroupSegments(rule.segments).forEach((segmentKey) => {
124
170
  if (!segmentsUsedInFeatures[segmentKey]) {
@@ -129,32 +175,33 @@ export async function generateSiteSearchIndex(
129
175
  });
130
176
  }
131
177
  });
178
+ }
132
179
 
133
- if (env.force) {
134
- env.force.forEach((force) => {
135
- if (force.segments && force.segments !== "*") {
136
- extractSegmentKeysFromGroupSegments(force.segments).forEach((segmentKey) => {
137
- if (!segmentsUsedInFeatures[segmentKey]) {
138
- segmentsUsedInFeatures[segmentKey] = new Set();
139
- }
180
+ if (parsed.force) {
181
+ parsed.force.forEach((force) => {
182
+ if (force.segments && force.segments !== "*") {
183
+ extractSegmentKeysFromGroupSegments(force.segments).forEach((segmentKey) => {
184
+ if (!segmentsUsedInFeatures[segmentKey]) {
185
+ segmentsUsedInFeatures[segmentKey] = new Set();
186
+ }
140
187
 
141
- segmentsUsedInFeatures[segmentKey].add(entityName);
142
- });
143
- }
188
+ segmentsUsedInFeatures[segmentKey].add(entityName);
189
+ });
190
+ }
144
191
 
145
- if (force.conditions) {
146
- extractAttributeKeysFromConditions(force.conditions).forEach((attributeKey) => {
147
- if (!attributesUsedInFeatures[attributeKey]) {
148
- attributesUsedInFeatures[attributeKey] = new Set();
149
- }
192
+ if (force.conditions) {
193
+ extractAttributeKeysFromConditions(force.conditions).forEach((attributeKey) => {
194
+ if (!attributesUsedInFeatures[attributeKey]) {
195
+ attributesUsedInFeatures[attributeKey] = new Set();
196
+ }
150
197
 
151
- attributesUsedInFeatures[attributeKey].add(entityName);
152
- });
153
- }
154
- });
155
- }
156
- });
198
+ attributesUsedInFeatures[attributeKey].add(entityName);
199
+ });
200
+ }
201
+ });
202
+ }
157
203
 
204
+ // push
158
205
  result.entities.features.push({
159
206
  ...parsed,
160
207
  key: entityName,
@@ -105,7 +105,7 @@ export function getFeatureAssertionsFromMatrix(
105
105
  ): FeatureAssertion[] {
106
106
  if (!assertionWithMatrix.matrix) {
107
107
  const assertion = { ...assertionWithMatrix };
108
- assertion.description = `Assertion #${aIndex + 1}: (${assertion.environment}) ${
108
+ assertion.description = `Assertion #${aIndex + 1}:${assertion.environment ? ` (${assertion.environment})` : ""} ${
109
109
  assertion.description || `at ${assertion.at}%`
110
110
  }`;
111
111
 
@@ -118,7 +118,7 @@ export function getFeatureAssertionsFromMatrix(
118
118
  for (let cIndex = 0; cIndex < combinations.length; cIndex++) {
119
119
  const combination = combinations[cIndex];
120
120
  const assertion = applyCombinationToFeatureAssertion(combination, assertionWithMatrix);
121
- assertion.description = `Assertion #${aIndex + 1}: (${assertion.environment}) ${
121
+ assertion.description = `Assertion #${aIndex + 1}:${assertion.environment ? ` (${assertion.environment})` : ""} ${
122
122
  assertion.description || `at ${assertion.at}%`
123
123
  }`;
124
124
 
@@ -13,6 +13,7 @@ import { ProjectConfig } from "../config";
13
13
  import { checkIfArraysAreEqual } from "./checkIfArraysAreEqual";
14
14
  import { checkIfObjectsAreEqual } from "./checkIfObjectsAreEqual";
15
15
  import { getFeatureAssertionsFromMatrix } from "./matrix";
16
+ import type { DatafileContentByEnvironment } from "./testProject";
16
17
 
17
18
  export async function testFeature(
18
19
  datasource: Datasource,
@@ -20,7 +21,7 @@ export async function testFeature(
20
21
  test: TestFeature,
21
22
  options: { verbose?: boolean; showDatafile?: boolean } = {},
22
23
  patterns,
23
- datafileContentByEnvironment: { [environment: string]: DatafileContent } = {},
24
+ datafileContentByEnvironment: DatafileContentByEnvironment,
24
25
  ): Promise<TestResult> {
25
26
  const testStartTime = Date.now();
26
27
  const featureKey = test.feature;
@@ -54,7 +55,7 @@ export async function testFeature(
54
55
  continue;
55
56
  }
56
57
 
57
- const datafileContent = datafileContentByEnvironment[assertion.environment];
58
+ const datafileContent = datafileContentByEnvironment.get(assertion.environment || false);
58
59
 
59
60
  if (options.showDatafile) {
60
61
  console.log("");
@@ -36,9 +36,7 @@ export interface ExecutionResult {
36
36
  };
37
37
  }
38
38
 
39
- export interface DatafileContentByEnvironment {
40
- [environment: string]: DatafileContent;
41
- }
39
+ export type DatafileContentByEnvironment = Map<string | false, DatafileContent>;
42
40
 
43
41
  export async function executeTest(
44
42
  testFile: string,
@@ -151,23 +149,44 @@ export async function testProject(
151
149
  let passedAssertionsCount = 0;
152
150
  let failedAssertionsCount = 0;
153
151
 
154
- const datafileContentByEnvironment: DatafileContentByEnvironment = {};
152
+ const datafileContentByEnvironment: DatafileContentByEnvironment = new Map();
153
+
154
+ // with environments
155
+ if (Array.isArray(projectConfig.environments)) {
156
+ for (const environment of projectConfig.environments) {
157
+ const existingState = await datasource.readState(environment);
158
+ const datafileContent = await buildDatafile(
159
+ projectConfig,
160
+ datasource,
161
+ {
162
+ schemaVersion: options.schemaVersion || SCHEMA_VERSION,
163
+ revision: "include-all-features",
164
+ environment: environment,
165
+ inflate: options.inflate,
166
+ },
167
+ existingState,
168
+ );
169
+
170
+ datafileContentByEnvironment.set(environment, datafileContent);
171
+ }
172
+ }
155
173
 
156
- for (const environment of projectConfig.environments) {
157
- const existingState = await datasource.readState(environment);
174
+ // no environments
175
+ if (projectConfig.environments === false) {
176
+ const existingState = await datasource.readState(false);
158
177
  const datafileContent = await buildDatafile(
159
178
  projectConfig,
160
179
  datasource,
161
180
  {
162
181
  schemaVersion: options.schemaVersion || SCHEMA_VERSION,
163
182
  revision: "include-all-features",
164
- environment: environment,
183
+ environment: false,
165
184
  inflate: options.inflate,
166
185
  },
167
186
  existingState,
168
187
  );
169
188
 
170
- datafileContentByEnvironment[environment] = datafileContent;
189
+ datafileContentByEnvironment.set(false, datafileContent);
171
190
  }
172
191
 
173
192
  for (const testFile of testFiles) {