@vitronai/themis 0.1.0-beta.4 → 0.1.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.
- package/CHANGELOG.md +17 -1
- package/README.md +42 -2
- package/docs/api.md +21 -2
- package/docs/migration.md +167 -0
- package/docs/publish.md +2 -0
- package/docs/release-checklist.md +28 -0
- package/docs/release-policy.md +11 -8
- package/docs/roadmap.md +18 -0
- package/docs/schemas/agent-result.v1.json +8 -2
- package/docs/schemas/contract-diff.v1.json +120 -0
- package/docs/showcases.md +117 -0
- package/docs/vscode-extension.md +13 -0
- package/docs/why-themis.md +34 -3
- package/globals.d.ts +1 -0
- package/index.d.ts +57 -0
- package/package.json +1 -1
- package/src/artifacts.js +63 -2
- package/src/assets/themisVerdictEngine.png +0 -0
- package/src/cli.js +16 -3
- package/src/contracts.js +330 -0
- package/src/migrate.js +104 -4
- package/src/reporter.js +79 -3
- package/src/runner.js +2 -0
- package/src/runtime.js +32 -3
- package/src/test-utils.js +13 -0
- package/src/worker.js +1 -0
package/src/runtime.js
CHANGED
|
@@ -3,6 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const { createExpect } = require('./expect');
|
|
4
4
|
const { createModuleLoader } = require('./module-loader');
|
|
5
5
|
const { installTestEnvironment } = require('./environment');
|
|
6
|
+
const { createContractHarness } = require('./contracts');
|
|
6
7
|
const { createTestUtils } = require('./test-utils');
|
|
7
8
|
|
|
8
9
|
const INTENT_PHASE_ALIASES = {
|
|
@@ -40,6 +41,11 @@ function collectAndRun(filePath, options = {}) {
|
|
|
40
41
|
const projectRoot = path.resolve(options.cwd || process.cwd());
|
|
41
42
|
const setupFiles = resolveSetupFiles(options.setupFiles, projectRoot);
|
|
42
43
|
const environment = installTestEnvironment(options.environment || 'node');
|
|
44
|
+
const currentTestRef = {
|
|
45
|
+
file: filePath,
|
|
46
|
+
name: '',
|
|
47
|
+
fullName: ''
|
|
48
|
+
};
|
|
43
49
|
const runtimeBindings = {
|
|
44
50
|
api: null,
|
|
45
51
|
testUtils: null
|
|
@@ -49,7 +55,14 @@ function collectAndRun(filePath, options = {}) {
|
|
|
49
55
|
tsconfigPath: options.tsconfigPath,
|
|
50
56
|
virtualModules: buildCompatibilityVirtualModules(runtimeBindings)
|
|
51
57
|
});
|
|
52
|
-
const
|
|
58
|
+
const contractHarness = createContractHarness({
|
|
59
|
+
cwd: projectRoot,
|
|
60
|
+
updateContracts: Boolean(options.updateContracts),
|
|
61
|
+
getCurrentTest() {
|
|
62
|
+
return currentTestRef;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const testUtils = createTestUtils({ moduleLoader, contractHarness });
|
|
53
66
|
const runtimeExpect = createExpect();
|
|
54
67
|
const runtimeApi = buildRuntimeApi({
|
|
55
68
|
root,
|
|
@@ -92,6 +105,7 @@ function collectAndRun(filePath, options = {}) {
|
|
|
92
105
|
moduleLoader.restore();
|
|
93
106
|
return {
|
|
94
107
|
file: filePath,
|
|
108
|
+
contracts: [],
|
|
95
109
|
tests: [
|
|
96
110
|
{
|
|
97
111
|
name: 'load',
|
|
@@ -107,11 +121,16 @@ function collectAndRun(filePath, options = {}) {
|
|
|
107
121
|
const results = [];
|
|
108
122
|
const runOptions = {
|
|
109
123
|
matchRegex: options.match ? new RegExp(options.match) : null,
|
|
110
|
-
allowedFullNames: toSet(options.allowedFullNames)
|
|
124
|
+
allowedFullNames: toSet(options.allowedFullNames),
|
|
125
|
+
currentTestRef
|
|
111
126
|
};
|
|
112
127
|
|
|
113
128
|
return runSuite(root, [root], results, runOptions)
|
|
114
|
-
.then(() => ({
|
|
129
|
+
.then(() => ({
|
|
130
|
+
file: filePath,
|
|
131
|
+
tests: results,
|
|
132
|
+
contracts: testUtils.getContractEvents()
|
|
133
|
+
}))
|
|
115
134
|
.finally(() => {
|
|
116
135
|
restoreGlobals(previousGlobals);
|
|
117
136
|
testUtils.restoreAllMocks();
|
|
@@ -286,6 +305,10 @@ async function runSuite(suite, lineage, results, options) {
|
|
|
286
305
|
}
|
|
287
306
|
|
|
288
307
|
try {
|
|
308
|
+
if (options.currentTestRef) {
|
|
309
|
+
options.currentTestRef.name = test.name;
|
|
310
|
+
options.currentTestRef.fullName = testName;
|
|
311
|
+
}
|
|
289
312
|
const beforeEachHooks = collectHooks(nextLineage, 'beforeEach', false);
|
|
290
313
|
for (const hook of beforeEachHooks) {
|
|
291
314
|
await hook();
|
|
@@ -297,6 +320,10 @@ async function runSuite(suite, lineage, results, options) {
|
|
|
297
320
|
status = 'failed';
|
|
298
321
|
error = normalizeError(err);
|
|
299
322
|
} finally {
|
|
323
|
+
if (options.currentTestRef) {
|
|
324
|
+
options.currentTestRef.name = '';
|
|
325
|
+
options.currentTestRef.fullName = '';
|
|
326
|
+
}
|
|
300
327
|
if (beforeEachSucceeded) {
|
|
301
328
|
const afterEachHooks = collectHooks(nextLineage, 'afterEach', true);
|
|
302
329
|
for (const hook of afterEachHooks) {
|
|
@@ -373,6 +400,7 @@ function installGlobals(api) {
|
|
|
373
400
|
'advanceTimersByTime',
|
|
374
401
|
'runAllTimers',
|
|
375
402
|
'flushMicrotasks',
|
|
403
|
+
'captureContract',
|
|
376
404
|
'mockFetch',
|
|
377
405
|
'restoreFetch',
|
|
378
406
|
'resetFetchMocks'
|
|
@@ -408,6 +436,7 @@ function installGlobals(api) {
|
|
|
408
436
|
global.advanceTimersByTime = api.advanceTimersByTime;
|
|
409
437
|
global.runAllTimers = api.runAllTimers;
|
|
410
438
|
global.flushMicrotasks = api.flushMicrotasks;
|
|
439
|
+
global.captureContract = api.captureContract;
|
|
411
440
|
global.mockFetch = api.mockFetch;
|
|
412
441
|
global.restoreFetch = api.restoreFetch;
|
|
413
442
|
global.resetFetchMocks = api.resetFetchMocks;
|
package/src/test-utils.js
CHANGED
|
@@ -5,6 +5,7 @@ function createTestUtils(options = {}) {
|
|
|
5
5
|
const activeMocks = new Set();
|
|
6
6
|
const activeSpies = new Set();
|
|
7
7
|
const moduleLoader = options.moduleLoader;
|
|
8
|
+
const contractHarness = options.contractHarness || null;
|
|
8
9
|
const renderedContainers = new Set();
|
|
9
10
|
let timerState = null;
|
|
10
11
|
let fetchState = null;
|
|
@@ -169,11 +170,23 @@ function createTestUtils(options = {}) {
|
|
|
169
170
|
mockFetch(handlerOrResponse) {
|
|
170
171
|
return getFetchState().mockFetch(handlerOrResponse);
|
|
171
172
|
},
|
|
173
|
+
captureContract(name, value, contractOptions) {
|
|
174
|
+
if (!contractHarness || typeof contractHarness.captureContract !== 'function') {
|
|
175
|
+
throw new Error('captureContract(...) is unavailable outside the Themis runtime');
|
|
176
|
+
}
|
|
177
|
+
return contractHarness.captureContract(name, value, contractOptions);
|
|
178
|
+
},
|
|
172
179
|
restoreFetch() {
|
|
173
180
|
return getFetchState().restore();
|
|
174
181
|
},
|
|
175
182
|
resetFetchMocks() {
|
|
176
183
|
return getFetchState().reset();
|
|
184
|
+
},
|
|
185
|
+
getContractEvents() {
|
|
186
|
+
if (!contractHarness || typeof contractHarness.getEvents !== 'function') {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
return contractHarness.getEvents();
|
|
177
190
|
}
|
|
178
191
|
};
|
|
179
192
|
|
package/src/worker.js
CHANGED
|
@@ -7,6 +7,7 @@ const { collectAndRun } = require('./runtime');
|
|
|
7
7
|
match: workerData.match,
|
|
8
8
|
allowedFullNames: workerData.allowedFullNames,
|
|
9
9
|
noMemes: workerData.noMemes,
|
|
10
|
+
updateContracts: workerData.updateContracts,
|
|
10
11
|
cwd: workerData.cwd,
|
|
11
12
|
environment: workerData.environment,
|
|
12
13
|
setupFiles: workerData.setupFiles,
|