@featurevisor/core 1.2.0 → 1.2.2

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 (40) hide show
  1. package/.eslintcache +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/coverage/clover.xml +2 -2
  4. package/coverage/coverage-final.json +1 -1
  5. package/coverage/lcov-report/index.html +1 -1
  6. package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
  7. package/coverage/lcov-report/lib/builder/index.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 +1 -1
  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/traffic.ts.html +1 -1
  15. package/coverage/lcov-report/src/tester/checkIfObjectsAreEqual.ts.html +1 -1
  16. package/coverage/lcov-report/src/tester/index.html +1 -1
  17. package/coverage/lcov-report/src/tester/matrix.ts.html +5 -5
  18. package/lib/tester/matrix.js +4 -4
  19. package/lib/tester/matrix.js.map +1 -1
  20. package/lib/tester/prettyDuration.d.ts +1 -0
  21. package/lib/tester/prettyDuration.js +31 -0
  22. package/lib/tester/prettyDuration.js.map +1 -0
  23. package/lib/tester/printTestResult.d.ts +2 -0
  24. package/lib/tester/printTestResult.js +41 -0
  25. package/lib/tester/printTestResult.js.map +1 -0
  26. package/lib/tester/testFeature.d.ts +2 -2
  27. package/lib/tester/testFeature.js +78 -31
  28. package/lib/tester/testFeature.js.map +1 -1
  29. package/lib/tester/testProject.js +37 -11
  30. package/lib/tester/testProject.js.map +1 -1
  31. package/lib/tester/testSegment.d.ts +2 -2
  32. package/lib/tester/testSegment.js +35 -12
  33. package/lib/tester/testSegment.js.map +1 -1
  34. package/package.json +5 -5
  35. package/src/tester/matrix.ts +4 -4
  36. package/src/tester/prettyDuration.ts +34 -0
  37. package/src/tester/printTestResult.ts +53 -0
  38. package/src/tester/testFeature.ts +87 -48
  39. package/src/tester/testProject.ts +44 -12
  40. package/src/tester/testSegment.ts +48 -20
@@ -41,10 +41,12 @@ var fs = require("fs");
41
41
  var testSegment_1 = require("./testSegment");
42
42
  var testFeature_1 = require("./testFeature");
43
43
  var cliFormat_1 = require("./cliFormat");
44
+ var prettyDuration_1 = require("./prettyDuration");
45
+ var printTestResult_1 = require("./printTestResult");
44
46
  function testProject(deps, options) {
45
47
  if (options === void 0) { options = {}; }
46
48
  return __awaiter(this, void 0, void 0, function () {
47
- var rootDirectoryPath, projectConfig, datasource, hasError, testFiles, patterns, _i, testFiles_1, testFile, testFilePath, t, test_1, segmentHasError, test_2, featureHasError;
49
+ var rootDirectoryPath, projectConfig, datasource, hasError, testFiles, startTime, patterns, passedTestsCount, failedTestsCount, passedAssertionsCount, failedAssertionsCount, _i, testFiles_1, testFile, testFilePath, t, test_1, testResult, test_2, testResult, diffInMs, testSpecsMessage, testAssertionsMessage;
48
50
  return __generator(this, function (_a) {
49
51
  switch (_a.label) {
50
52
  case 0:
@@ -63,10 +65,15 @@ function testProject(deps, options) {
63
65
  hasError = true;
64
66
  return [2 /*return*/, hasError];
65
67
  }
68
+ startTime = Date.now();
66
69
  patterns = {
67
70
  keyPattern: options.keyPattern ? new RegExp(options.keyPattern) : undefined,
68
71
  assertionPattern: options.assertionPattern ? new RegExp(options.assertionPattern) : undefined,
69
72
  };
73
+ passedTestsCount = 0;
74
+ failedTestsCount = 0;
75
+ passedAssertionsCount = 0;
76
+ failedAssertionsCount = 0;
70
77
  _i = 0, testFiles_1 = testFiles;
71
78
  _a.label = 2;
72
79
  case 2:
@@ -81,12 +88,19 @@ function testProject(deps, options) {
81
88
  if (patterns.keyPattern && !patterns.keyPattern.test(test_1.segment)) {
82
89
  return [3 /*break*/, 8];
83
90
  }
84
- console.log(cliFormat_1.CLI_FORMAT_BOLD, "\nTesting: ".concat(testFilePath.replace(rootDirectoryPath, "")));
85
91
  return [4 /*yield*/, (0, testSegment_1.testSegment)(datasource, test_1, patterns)];
86
92
  case 4:
87
- segmentHasError = _a.sent();
88
- if (segmentHasError) {
93
+ testResult = _a.sent();
94
+ (0, printTestResult_1.printTestResult)(testResult, testFilePath, rootDirectoryPath);
95
+ if (!testResult.passed) {
89
96
  hasError = true;
97
+ failedTestsCount++;
98
+ failedAssertionsCount += testResult.assertions.filter(function (a) { return !a.passed; }).length;
99
+ passedAssertionsCount += testResult.assertions.length - failedAssertionsCount;
100
+ }
101
+ else {
102
+ passedTestsCount++;
103
+ passedAssertionsCount += testResult.assertions.length;
90
104
  }
91
105
  return [3 /*break*/, 8];
92
106
  case 5:
@@ -95,12 +109,19 @@ function testProject(deps, options) {
95
109
  if (patterns.keyPattern && !patterns.keyPattern.test(test_2.feature)) {
96
110
  return [3 /*break*/, 8];
97
111
  }
98
- console.log(cliFormat_1.CLI_FORMAT_BOLD, "\nTesting: ".concat(testFilePath.replace(rootDirectoryPath, "")));
99
112
  return [4 /*yield*/, (0, testFeature_1.testFeature)(datasource, projectConfig, test_2, options, patterns)];
100
113
  case 6:
101
- featureHasError = _a.sent();
102
- if (featureHasError) {
114
+ testResult = _a.sent();
115
+ (0, printTestResult_1.printTestResult)(testResult, testFilePath, rootDirectoryPath);
116
+ if (!testResult.passed) {
103
117
  hasError = true;
118
+ failedTestsCount++;
119
+ failedAssertionsCount += testResult.assertions.filter(function (a) { return !a.passed; }).length;
120
+ passedAssertionsCount += testResult.assertions.length - failedAssertionsCount;
121
+ }
122
+ else {
123
+ passedTestsCount++;
124
+ passedAssertionsCount += testResult.assertions.length;
104
125
  }
105
126
  return [3 /*break*/, 8];
106
127
  case 7:
@@ -111,14 +132,19 @@ function testProject(deps, options) {
111
132
  _i++;
112
133
  return [3 /*break*/, 2];
113
134
  case 9:
114
- console.log("");
135
+ diffInMs = Date.now() - startTime;
136
+ console.log("\n---\n");
137
+ testSpecsMessage = "Test specs: ".concat(passedTestsCount, " passed, ").concat(failedTestsCount, " failed");
138
+ testAssertionsMessage = "Assertions: ".concat(passedAssertionsCount, " passed, ").concat(failedAssertionsCount, " failed");
115
139
  if (hasError) {
116
- console.log(cliFormat_1.CLI_FORMAT_RED, "Some tests failed");
140
+ console.log(cliFormat_1.CLI_FORMAT_RED, testSpecsMessage);
141
+ console.log(cliFormat_1.CLI_FORMAT_RED, testAssertionsMessage);
117
142
  }
118
143
  else {
119
- console.log(cliFormat_1.CLI_FORMAT_GREEN, "All tests passed");
144
+ console.log(cliFormat_1.CLI_FORMAT_GREEN, testSpecsMessage);
145
+ console.log(cliFormat_1.CLI_FORMAT_GREEN, testAssertionsMessage);
120
146
  }
121
- console.log("");
147
+ console.log(cliFormat_1.CLI_FORMAT_BOLD, "Time: ".concat((0, prettyDuration_1.prettyDuration)(diffInMs)));
122
148
  return [2 /*return*/, hasError];
123
149
  }
124
150
  });
@@ -1 +1 @@
1
- {"version":3,"file":"testProject.js","sourceRoot":"","sources":["../../src/tester/testProject.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testProject.js","sourceRoot":"","sources":["../../src/tester/testProject.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { TestSegment } from "@featurevisor/types";
1
+ import { TestSegment, TestResult } from "@featurevisor/types";
2
2
  import { Datasource } from "../datasource";
3
- export declare function testSegment(datasource: Datasource, test: TestSegment, patterns: any): Promise<boolean>;
3
+ export declare function testSegment(datasource: Datasource, test: TestSegment, patterns: any): Promise<TestResult>;
@@ -38,24 +38,31 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.testSegment = void 0;
40
40
  var sdk_1 = require("@featurevisor/sdk");
41
- var cliFormat_1 = require("./cliFormat");
42
41
  var matrix_1 = require("./matrix");
43
42
  function testSegment(datasource, test, patterns) {
44
43
  return __awaiter(this, void 0, void 0, function () {
45
- var hasError, segmentKey, segmentExists, parsedSegment, conditions;
44
+ var testStartTime, segmentKey, testResult, segmentExists, parsedSegment, conditions;
46
45
  return __generator(this, function (_a) {
47
46
  switch (_a.label) {
48
47
  case 0:
49
- hasError = false;
48
+ testStartTime = Date.now();
50
49
  segmentKey = test.segment;
51
- console.log(cliFormat_1.CLI_FORMAT_BOLD, " Segment \"".concat(segmentKey, "\":"));
50
+ testResult = {
51
+ type: "segment",
52
+ key: segmentKey,
53
+ // to be updated later
54
+ notFound: false,
55
+ duration: 0,
56
+ passed: true,
57
+ assertions: [],
58
+ };
52
59
  return [4 /*yield*/, datasource.segmentExists(segmentKey)];
53
60
  case 1:
54
61
  segmentExists = _a.sent();
55
62
  if (!segmentExists) {
56
- console.error(cliFormat_1.CLI_FORMAT_RED, " Segment does not exist: ".concat(segmentKey));
57
- hasError = true;
58
- return [2 /*return*/, hasError];
63
+ testResult.notFound = true;
64
+ testResult.passed = false;
65
+ return [2 /*return*/, testResult];
59
66
  }
60
67
  return [4 /*yield*/, datasource.readSegment(segmentKey)];
61
68
  case 2:
@@ -64,19 +71,35 @@ function testSegment(datasource, test, patterns) {
64
71
  test.assertions.forEach(function (assertion, aIndex) {
65
72
  var assertions = (0, matrix_1.getSegmentAssertionsFromMatrix)(aIndex, assertion);
66
73
  assertions.forEach(function (assertion) {
74
+ var assertionStartTime = Date.now();
75
+ var testResultAssertion = {
76
+ description: assertion.description,
77
+ duration: 0,
78
+ passed: true,
79
+ errors: [],
80
+ };
67
81
  if (patterns.assertionPattern && !patterns.assertionPattern.test(assertion.description)) {
68
82
  return;
69
83
  }
70
- console.log(assertion.description);
71
84
  var expected = assertion.expectedToMatch;
72
85
  var actual = (0, sdk_1.allConditionsAreMatched)(conditions, assertion.context);
73
- if (actual !== expected) {
74
- hasError = true;
75
- console.error(cliFormat_1.CLI_FORMAT_RED, " Segment failed: expected \"".concat(expected, "\", got \"").concat(actual, "\""));
86
+ var passed = actual === expected;
87
+ if (!passed) {
88
+ var testResultAssertionError = {
89
+ type: "segment",
90
+ expected: expected,
91
+ actual: actual,
92
+ };
93
+ testResultAssertion.errors.push(testResultAssertionError);
94
+ testResult.passed = false;
95
+ testResultAssertion.passed = passed;
76
96
  }
97
+ testResult.assertions.push(testResultAssertion);
98
+ testResultAssertion.duration = Date.now() - assertionStartTime;
77
99
  });
78
100
  });
79
- return [2 /*return*/, hasError];
101
+ testResult.duration = Date.now() - testStartTime;
102
+ return [2 /*return*/, testResult];
80
103
  }
81
104
  });
82
105
  });
@@ -1 +1 @@
1
- {"version":3,"file":"testSegment.js","sourceRoot":"","sources":["../../src/tester/testSegment.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,yCAA4D;AAI5D,yCAA8D;AAC9D,mCAA0D;AAE1D,SAAsB,WAAW,CAC/B,UAAsB,EACtB,IAAiB,EACjB,QAAQ;;;;;;oBAEJ,QAAQ,GAAG,KAAK,CAAC;oBAEf,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;oBAEhC,OAAO,CAAC,GAAG,CAAC,2BAAe,EAAE,sBAAc,UAAU,QAAI,CAAC,CAAC;oBAErC,qBAAM,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,EAAA;;oBAA1D,aAAa,GAAG,SAA0C;oBAEhE,IAAI,CAAC,aAAa,EAAE;wBAClB,OAAO,CAAC,KAAK,CAAC,0BAAc,EAAE,oCAA6B,UAAU,CAAE,CAAC,CAAC;wBACzE,QAAQ,GAAG,IAAI,CAAC;wBAEhB,sBAAO,QAAQ,EAAC;qBACjB;oBAEqB,qBAAM,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,EAAA;;oBAAxD,aAAa,GAAG,SAAwC;oBACxD,UAAU,GAAG,aAAa,CAAC,UAAqC,CAAC;oBAEvE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,SAAS,EAAE,MAAM;wBACjD,IAAM,UAAU,GAAG,IAAA,uCAA8B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC;wBAErE,UAAU,CAAC,OAAO,CAAC,UAAU,SAAS;4BACpC,IAAI,QAAQ,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;gCACvF,OAAO;6BACR;4BAED,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;4BAEnC,IAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC;4BAC3C,IAAM,MAAM,GAAG,IAAA,6BAAuB,EAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;4BAEtE,IAAI,MAAM,KAAK,QAAQ,EAAE;gCACvB,QAAQ,GAAG,IAAI,CAAC;gCAEhB,OAAO,CAAC,KAAK,CACX,0BAAc,EACd,yCAAiC,QAAQ,uBAAW,MAAM,OAAG,CAC9D,CAAC;6BACH;wBACH,CAAC,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;oBAEH,sBAAO,QAAQ,EAAC;;;;CACjB;AAhDD,kCAgDC"}
1
+ {"version":3,"file":"testSegment.js","sourceRoot":"","sources":["../../src/tester/testSegment.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,yCAA4D;AAI5D,mCAA0D;AAE1D,SAAsB,WAAW,CAC/B,UAAsB,EACtB,IAAiB,EACjB,QAAQ;;;;;;oBAEF,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBAC3B,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;oBAE1B,UAAU,GAAe;wBAC7B,IAAI,EAAE,SAAS;wBACf,GAAG,EAAE,UAAU;wBAEf,sBAAsB;wBACtB,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,CAAC;wBACX,MAAM,EAAE,IAAI;wBACZ,UAAU,EAAE,EAAE;qBACf,CAAC;oBAEoB,qBAAM,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,EAAA;;oBAA1D,aAAa,GAAG,SAA0C;oBAEhE,IAAI,CAAC,aAAa,EAAE;wBAClB,UAAU,CAAC,QAAQ,GAAG,IAAI,CAAC;wBAC3B,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC;wBAE1B,sBAAO,UAAU,EAAC;qBACnB;oBAEqB,qBAAM,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,EAAA;;oBAAxD,aAAa,GAAG,SAAwC;oBACxD,UAAU,GAAG,aAAa,CAAC,UAAqC,CAAC;oBAEvE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,SAAS,EAAE,MAAM;wBACjD,IAAM,UAAU,GAAG,IAAA,uCAA8B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAC;wBAErE,UAAU,CAAC,OAAO,CAAC,UAAU,SAAS;4BACpC,IAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;4BACtC,IAAM,mBAAmB,GAAwB;gCAC/C,WAAW,EAAE,SAAS,CAAC,WAAqB;gCAC5C,QAAQ,EAAE,CAAC;gCACX,MAAM,EAAE,IAAI;gCACZ,MAAM,EAAE,EAAE;6BACX,CAAC;4BAEF,IAAI,QAAQ,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE;gCACvF,OAAO;6BACR;4BAED,IAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC;4BAC3C,IAAM,MAAM,GAAG,IAAA,6BAAuB,EAAC,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;4BACtE,IAAM,MAAM,GAAG,MAAM,KAAK,QAAQ,CAAC;4BAEnC,IAAI,CAAC,MAAM,EAAE;gCACX,IAAM,wBAAwB,GAA6B;oCACzD,IAAI,EAAE,SAAS;oCACf,QAAQ,UAAA;oCACR,MAAM,QAAA;iCACP,CAAC;gCAED,mBAAmB,CAAC,MAAqC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;gCAC1F,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC;gCAC1B,mBAAmB,CAAC,MAAM,GAAG,MAAM,CAAC;6BACrC;4BAED,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;4BAChD,mBAAmB,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC;wBACjE,CAAC,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;oBAEH,UAAU,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC;oBAEjD,sBAAO,UAAU,EAAC;;;;CACnB;AAvED,kCAuEC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featurevisor/core",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Core package of Featurevisor for Node.js usage",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -44,9 +44,9 @@
44
44
  },
45
45
  "license": "MIT",
46
46
  "dependencies": {
47
- "@featurevisor/sdk": "^1.2.0",
48
- "@featurevisor/site": "^1.2.0",
49
- "@featurevisor/types": "^1.2.0",
47
+ "@featurevisor/sdk": "^1.2.2",
48
+ "@featurevisor/site": "^1.2.2",
49
+ "@featurevisor/types": "^1.2.2",
50
50
  "axios": "^1.3.4",
51
51
  "joi": "^17.8.3",
52
52
  "js-yaml": "^4.1.0",
@@ -57,5 +57,5 @@
57
57
  "@types/js-yaml": "^4.0.5",
58
58
  "@types/tar": "^6.1.4"
59
59
  },
60
- "gitHead": "e733c84d2fcdc6205df5ae75e5bbf73753141646"
60
+ "gitHead": "65f5422bceb755a6d6a2e5b0c025b41486612c73"
61
61
  }
@@ -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}) ${
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}) ${
122
122
  assertion.description || `at ${assertion.at}%`
123
123
  }`;
124
124
 
@@ -161,7 +161,7 @@ export function getSegmentAssertionsFromMatrix(
161
161
  ): SegmentAssertion[] {
162
162
  if (!assertionWithMatrix.matrix) {
163
163
  const assertion = { ...assertionWithMatrix };
164
- assertion.description = ` Assertion #${aIndex + 1}: ${
164
+ assertion.description = `Assertion #${aIndex + 1}: ${
165
165
  assertion.description || `#${aIndex + 1}`
166
166
  }`;
167
167
 
@@ -174,7 +174,7 @@ export function getSegmentAssertionsFromMatrix(
174
174
  for (let cIndex = 0; cIndex < combinations.length; cIndex++) {
175
175
  const combination = combinations[cIndex];
176
176
  const assertion = applyCombinationToSegmentAssertion(combination, assertionWithMatrix);
177
- assertion.description = ` Assertion #${aIndex + 1}: ${
177
+ assertion.description = `Assertion #${aIndex + 1}: ${
178
178
  assertion.description || `#${aIndex + 1}`
179
179
  }`;
180
180
 
@@ -0,0 +1,34 @@
1
+ export function prettyDuration(diffInMs) {
2
+ let diff = Math.abs(diffInMs);
3
+
4
+ if (diff === 0) {
5
+ return `0ms`;
6
+ }
7
+
8
+ const ms = diff % 1000;
9
+ diff = (diff - ms) / 1000;
10
+ const secs = diff % 60;
11
+ diff = (diff - secs) / 60;
12
+ const mins = diff % 60;
13
+ const hrs = (diff - mins) / 60;
14
+
15
+ let result = "";
16
+
17
+ if (hrs) {
18
+ result += ` ${hrs}h`;
19
+ }
20
+
21
+ if (mins) {
22
+ result += ` ${mins}m`;
23
+ }
24
+
25
+ if (secs) {
26
+ result += ` ${secs}s`;
27
+ }
28
+
29
+ if (ms) {
30
+ result += ` ${ms}ms`;
31
+ }
32
+
33
+ return result.trim();
34
+ }
@@ -0,0 +1,53 @@
1
+ import { TestResult } from "@featurevisor/types";
2
+
3
+ import { CLI_FORMAT_BOLD, CLI_FORMAT_RED } from "./cliFormat";
4
+ import { prettyDuration } from "./prettyDuration";
5
+
6
+ export function printTestResult(testResult: TestResult, testFilePath, rootDirectoryPath) {
7
+ console.log("");
8
+
9
+ const title = `Testing: ${testFilePath.replace(rootDirectoryPath, "")} (${prettyDuration(
10
+ testResult.duration,
11
+ )})`;
12
+ console.log(title);
13
+
14
+ if (testResult.notFound) {
15
+ console.log(CLI_FORMAT_RED, ` => ${testResult.type} ${testResult.key} not found`);
16
+
17
+ return;
18
+ }
19
+
20
+ console.log(CLI_FORMAT_BOLD, ` ${testResult.type} "${testResult.key}":`);
21
+
22
+ testResult.assertions.forEach(function (assertion) {
23
+ if (assertion.passed) {
24
+ console.log(` ✔ ${assertion.description} (${prettyDuration(assertion.duration)})`);
25
+ } else {
26
+ console.log(
27
+ CLI_FORMAT_RED,
28
+ ` ✘ ${assertion.description} (${prettyDuration(assertion.duration)})`,
29
+ );
30
+
31
+ assertion.errors?.forEach(function (error) {
32
+ if (error.message) {
33
+ console.log(CLI_FORMAT_RED, ` => ${error.message}`);
34
+
35
+ return;
36
+ }
37
+
38
+ if (error.type === "variable") {
39
+ const variableKey = (error.details as any).variableKey;
40
+
41
+ console.log(CLI_FORMAT_RED, ` => variable key: ${variableKey}`);
42
+ console.log(CLI_FORMAT_RED, ` => expected: ${error.expected}`);
43
+ console.log(CLI_FORMAT_RED, ` => received: ${error.actual}`);
44
+ } else {
45
+ console.log(
46
+ CLI_FORMAT_RED,
47
+ ` => ${error.type}: expected "${error.expected}", received "${error.actual}"`,
48
+ );
49
+ }
50
+ });
51
+ }
52
+ });
53
+ }
@@ -1,4 +1,9 @@
1
- import { TestFeature } from "@featurevisor/types";
1
+ import {
2
+ TestFeature,
3
+ TestResult,
4
+ TestResultAssertion,
5
+ TestResultAssertionError,
6
+ } from "@featurevisor/types";
2
7
  import { createInstance, MAX_BUCKETED_NUMBER } from "@featurevisor/sdk";
3
8
 
4
9
  import { Datasource } from "../datasource";
@@ -8,7 +13,6 @@ import { SCHEMA_VERSION } from "../config";
8
13
 
9
14
  import { checkIfArraysAreEqual } from "./checkIfArraysAreEqual";
10
15
  import { checkIfObjectsAreEqual } from "./checkIfObjectsAreEqual";
11
- import { CLI_FORMAT_BOLD, CLI_FORMAT_RED } from "./cliFormat";
12
16
  import { getFeatureAssertionsFromMatrix } from "./matrix";
13
17
 
14
18
  export async function testFeature(
@@ -17,24 +21,39 @@ export async function testFeature(
17
21
  test: TestFeature,
18
22
  options: { verbose?: boolean; showDatafile?: boolean } = {},
19
23
  patterns,
20
- ): Promise<boolean> {
21
- let hasError = false;
24
+ ): Promise<TestResult> {
25
+ const testStartTime = Date.now();
22
26
  const featureKey = test.feature;
23
27
 
24
- console.log(CLI_FORMAT_BOLD, ` Feature "${featureKey}":`);
28
+ const testResult: TestResult = {
29
+ type: "feature",
30
+ key: featureKey,
31
+
32
+ // to be updated later
33
+ notFound: false,
34
+ duration: 0,
35
+ passed: true,
36
+ assertions: [],
37
+ };
25
38
 
26
39
  for (let aIndex = 0; aIndex < test.assertions.length; aIndex++) {
27
40
  const assertions = getFeatureAssertionsFromMatrix(aIndex, test.assertions[aIndex]);
28
41
 
29
42
  for (let bIndex = 0; bIndex < assertions.length; bIndex++) {
43
+ const assertionStartTime = Date.now();
30
44
  const assertion = assertions[bIndex];
31
45
 
46
+ const testResultAssertion: TestResultAssertion = {
47
+ description: assertion.description as string,
48
+ duration: 0,
49
+ passed: true,
50
+ errors: [],
51
+ };
52
+
32
53
  if (patterns.assertionPattern && !patterns.assertionPattern.test(assertion.description)) {
33
54
  continue;
34
55
  }
35
56
 
36
- console.log(assertion.description);
37
-
38
57
  const requiredChain = await datasource.getRequiredFeaturesChain(test.feature);
39
58
  const featuresToInclude = Array.from(requiredChain);
40
59
 
@@ -68,17 +87,27 @@ export async function testFeature(
68
87
  sdk.setLogLevels(["debug", "info", "warn", "error"]);
69
88
  }
70
89
 
90
+ const feature = await datasource.readFeature(featureKey);
91
+ if (!feature) {
92
+ testResult.notFound = true;
93
+ testResult.passed = false;
94
+
95
+ return testResult;
96
+ }
97
+
71
98
  // isEnabled
72
99
  if ("expectedToBeEnabled" in assertion) {
73
100
  const isEnabled = sdk.isEnabled(featureKey, assertion.context);
74
101
 
75
102
  if (isEnabled !== assertion.expectedToBeEnabled) {
76
- hasError = true;
77
-
78
- console.error(
79
- CLI_FORMAT_RED,
80
- ` isEnabled failed: expected "${assertion.expectedToBeEnabled}", received "${isEnabled}"`,
81
- );
103
+ testResult.passed = false;
104
+ testResultAssertion.passed = false;
105
+
106
+ (testResultAssertion.errors as TestResultAssertionError[]).push({
107
+ type: "flag",
108
+ expected: assertion.expectedToBeEnabled,
109
+ actual: isEnabled,
110
+ });
82
111
  }
83
112
  }
84
113
 
@@ -87,26 +116,18 @@ export async function testFeature(
87
116
  const variation = sdk.getVariation(featureKey, assertion.context);
88
117
 
89
118
  if (variation !== assertion.expectedVariation) {
90
- hasError = true;
91
-
92
- console.error(
93
- CLI_FORMAT_RED,
94
- ` Variation failed: expected "${assertion.expectedVariation}", received "${variation}"`,
95
- );
119
+ testResult.passed = false;
120
+ testResultAssertion.passed = false;
121
+
122
+ (testResultAssertion.errors as TestResultAssertionError[]).push({
123
+ type: "variation",
124
+ expected: assertion.expectedVariation,
125
+ actual: variation,
126
+ });
96
127
  }
97
128
  }
98
129
 
99
130
  // variables
100
- const feature = await datasource.readFeature(featureKey);
101
-
102
- if (!feature) {
103
- hasError = true;
104
-
105
- console.error(CLI_FORMAT_RED, ` Feature "${featureKey}" failed: feature not found`);
106
-
107
- continue;
108
- }
109
-
110
131
  if (typeof assertion.expectedVariables === "object") {
111
132
  Object.keys(assertion.expectedVariables).forEach(function (variableKey) {
112
133
  const expectedValue =
@@ -118,12 +139,15 @@ export async function testFeature(
118
139
  const variableSchema = feature.variablesSchema?.find((v) => v.key === variableKey);
119
140
 
120
141
  if (!variableSchema) {
121
- hasError = true;
142
+ testResult.passed = false;
143
+ testResultAssertion.passed = false;
122
144
 
123
- console.error(
124
- CLI_FORMAT_RED,
125
- ` Variable "${variableKey}" failed: variable schema not found in feature`,
126
- );
145
+ (testResultAssertion.errors as TestResultAssertionError[]).push({
146
+ type: "variable",
147
+ expected: assertion.expectedVariation,
148
+ actual: undefined,
149
+ message: `schema for variable "${variableKey}" not found in feature`,
150
+ });
127
151
 
128
152
  return;
129
153
  }
@@ -144,12 +168,18 @@ export async function testFeature(
144
168
  }
145
169
 
146
170
  if (!passed) {
147
- console.error(CLI_FORMAT_RED, ` Variable "${variableKey}" failed:`);
148
- console.error(
149
- CLI_FORMAT_RED,
150
- ` expected: ${JSON.stringify(parsedExpectedValue)}`,
151
- );
152
- console.error(CLI_FORMAT_RED, ` received: ${JSON.stringify(actualValue)}`);
171
+ testResult.passed = false;
172
+ testResultAssertion.passed = false;
173
+
174
+ (testResultAssertion.errors as TestResultAssertionError[]).push({
175
+ type: "variable",
176
+ expected:
177
+ typeof expectedValue !== "string" ? JSON.stringify(expectedValue) : expectedValue,
178
+ actual: typeof actualValue !== "string" ? JSON.stringify(actualValue) : actualValue,
179
+ details: {
180
+ variableKey,
181
+ },
182
+ });
153
183
  }
154
184
  } else {
155
185
  // other types
@@ -162,19 +192,28 @@ export async function testFeature(
162
192
  }
163
193
 
164
194
  if (!passed) {
165
- console.error(CLI_FORMAT_RED, ` Variable "${variableKey}" failed:`);
166
- console.error(CLI_FORMAT_RED, ` expected: ${JSON.stringify(expectedValue)}`);
167
- console.error(CLI_FORMAT_RED, ` received: ${JSON.stringify(actualValue)}`);
195
+ testResult.passed = false;
196
+ testResultAssertion.passed = false;
197
+
198
+ (testResultAssertion.errors as TestResultAssertionError[]).push({
199
+ type: "variable",
200
+ expected: expectedValue as string,
201
+ actual: actualValue as string,
202
+ details: {
203
+ variableKey,
204
+ },
205
+ });
168
206
  }
169
207
  }
170
-
171
- if (!passed) {
172
- hasError = true;
173
- }
174
208
  });
175
209
  }
210
+
211
+ testResultAssertion.duration = Date.now() - assertionStartTime;
212
+ testResult.assertions.push(testResultAssertion);
176
213
  }
177
214
  }
178
215
 
179
- return hasError;
216
+ testResult.duration = Date.now() - testStartTime;
217
+
218
+ return testResult;
180
219
  }