@toa.io/core 1.0.0-alpha.28 → 1.0.0-alpha.283
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 +180 -0
- package/package.json +8 -10
- package/src/assignment.js +5 -8
- package/src/call.js +35 -9
- package/src/cascade.js +9 -11
- package/src/component.js +61 -21
- package/src/composition.js +3 -7
- package/src/connector.js +29 -22
- package/src/context.js +8 -6
- package/src/contract/contract.js +18 -0
- package/src/contract/index.js +2 -7
- package/src/contract/reply.js +39 -15
- package/src/contract/request.js +20 -10
- package/src/contract/schemas/index.js +9 -5
- package/src/contract/schemas/query.yaml +14 -1
- package/src/contract/schemas/source.yaml +23 -0
- package/src/discovery.js +15 -13
- package/src/effect.js +15 -0
- package/src/emission.js +2 -6
- package/src/entities/changeset.js +7 -14
- package/src/entities/entity.js +75 -29
- package/src/entities/factory.js +21 -14
- package/src/entities/index.js +1 -5
- package/src/entities/newid.js +9 -0
- package/src/entities/set.js +13 -4
- package/src/event.js +21 -7
- package/src/exceptions.js +53 -39
- package/src/exposition.js +5 -8
- package/src/guard.js +13 -0
- package/src/index.js +28 -47
- package/src/locator.js +2 -6
- package/src/observation.js +3 -15
- package/src/operation.js +40 -14
- package/src/outbox/index.js +1 -0
- package/src/outbox/outbox.js +296 -0
- package/src/query/criteria.js +3 -7
- package/src/query/options.js +5 -8
- package/src/query.js +36 -7
- package/src/receiver.js +76 -18
- package/src/reflection.js +2 -6
- package/src/remote.js +9 -12
- package/src/state.js +89 -50
- package/src/transition.js +13 -25
- package/src/transmission.js +15 -10
- package/src/unmanaged.js +7 -0
- package/test/call.fixtures.js +8 -12
- package/test/call.test.js +21 -9
- package/test/component.fixtures.js +5 -8
- package/test/component.test.js +22 -10
- package/test/connector.fixtures.js +10 -8
- package/test/connector.test.js +59 -38
- package/test/context.fixtures.js +8 -12
- package/test/context.test.js +18 -7
- package/test/contract/conditions.test.js +11 -9
- package/test/contract/contract.fixtures.js +12 -16
- package/test/contract/request.test.js +84 -34
- package/test/discovery.test.js +64 -0
- package/test/emission.fixtures.js +6 -10
- package/test/emission.test.js +29 -12
- package/test/entities/entity.fixtures.js +7 -11
- package/test/entities/entity.test.js +70 -49
- package/test/entities/factory.fixtures.js +22 -10
- package/test/entities/factory.test.js +29 -15
- package/test/entities/set.fixtures.js +6 -8
- package/test/entities/set.test.js +6 -5
- package/test/event.fixtures.js +9 -14
- package/test/event.test.js +57 -31
- package/test/locator.test.js +25 -24
- package/test/outbox.test.js +121 -0
- package/test/query.fixtures.js +1 -5
- package/test/query.test.js +42 -14
- package/test/receiver.fixtures.js +9 -12
- package/test/receiver.test.js +45 -22
- package/test/reflection.test.js +7 -6
- package/test/state.fixtures.js +25 -30
- package/test/state.test.js +72 -19
- package/test/transmission.fixtures.js +4 -6
- package/test/transmission.test.js +33 -15
- package/types/atomicity.d.ts +58 -0
- package/types/bindings.d.ts +8 -6
- package/types/bridges.ts +5 -2
- package/types/call.d.ts +13 -0
- package/types/component.d.ts +7 -4
- package/types/context.d.ts +6 -3
- package/types/entity.d.ts +4 -4
- package/types/event.d.ts +1 -1
- package/types/extensions.d.ts +54 -10
- package/types/guard.d.ts +5 -0
- package/types/index.ts +20 -13
- package/types/message.d.ts +1 -0
- package/types/operations.d.ts +6 -0
- package/types/outbox.d.ts +53 -0
- package/types/query.d.ts +2 -0
- package/types/receiver.d.ts +2 -2
- package/types/reflection.d.ts +1 -1
- package/types/remote.d.ts +18 -0
- package/types/request.d.ts +38 -6
- package/types/state.d.ts +14 -11
- package/types/storages.d.ts +36 -11
- package/src/contract/conditions.js +0 -21
package/test/call.test.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import { it, beforeEach, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
import * as fixtures from './call.fixtures.js'
|
|
6
|
+
import { Call } from '../src/call.js'
|
|
5
7
|
|
|
6
8
|
let call
|
|
7
9
|
|
|
8
10
|
beforeEach(() => {
|
|
9
|
-
|
|
11
|
+
resetCalls()
|
|
10
12
|
|
|
11
13
|
call = new Call(fixtures.transmission, fixtures.contract)
|
|
12
14
|
})
|
|
13
15
|
|
|
14
16
|
it('should depend on transmission', () => {
|
|
15
|
-
|
|
17
|
+
assert.ok(((invocation) => invocation.arguments.length === 1 && isDeepStrictEqual(invocation.arguments[0], call))(fixtures.transmission.link.mock.calls.at(-1) ?? { arguments: [] }))
|
|
16
18
|
})
|
|
17
19
|
|
|
18
20
|
it('should call transmission', async () => {
|
|
@@ -20,7 +22,7 @@ it('should call transmission', async () => {
|
|
|
20
22
|
|
|
21
23
|
await call.invoke(request)
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
assert.ok(fixtures.transmission.request.mock.calls.some((invocation) => invocation.arguments.length === 1 && isDeepStrictEqual(invocation.arguments[0], request)))
|
|
24
26
|
})
|
|
25
27
|
|
|
26
28
|
it('should fit request', async () => {
|
|
@@ -28,7 +30,7 @@ it('should fit request', async () => {
|
|
|
28
30
|
|
|
29
31
|
await call.invoke(request)
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
assert.ok(((invocation) => invocation.arguments.length === 1 && isDeepStrictEqual(invocation.arguments[0], request))(fixtures.contract.fit.mock.calls.at(-1) ?? { arguments: [] }))
|
|
32
34
|
})
|
|
33
35
|
|
|
34
36
|
it('should return reply', async () => {
|
|
@@ -36,11 +38,21 @@ it('should return reply', async () => {
|
|
|
36
38
|
|
|
37
39
|
const reply = await call.invoke(request)
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
assert.deepStrictEqual(reply, fixtures.transmission.request.mock.calls[0].result.output)
|
|
40
42
|
})
|
|
41
43
|
|
|
42
44
|
it('should throw received exceptions', async () => {
|
|
43
45
|
const request = fixtures.request().bad
|
|
44
46
|
|
|
45
|
-
await
|
|
47
|
+
await assert.rejects(call.invoke(request), (error) => { assert.notStrictEqual(error, undefined); return true })
|
|
46
48
|
})
|
|
49
|
+
|
|
50
|
+
function resetCalls (target = [assert, fixtures], seen = new Set()) {
|
|
51
|
+
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
52
|
+
|
|
53
|
+
seen.add(target)
|
|
54
|
+
|
|
55
|
+
for (const value of Object.values(target))
|
|
56
|
+
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
57
|
+
else resetCalls(value, seen)
|
|
58
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { mock } from 'node:test'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import randomstring from 'randomstring'
|
|
4
4
|
|
|
5
|
-
const invocation = () =>
|
|
5
|
+
const invocation = () => mock.fn(() => randomstring.generate())
|
|
6
6
|
|
|
7
|
-
const invocations = {
|
|
7
|
+
export const invocations = {
|
|
8
8
|
foo: {
|
|
9
9
|
invoke: invocation('foo'),
|
|
10
10
|
link: () => null
|
|
@@ -15,7 +15,4 @@ const invocations = {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const locator = {}
|
|
19
|
-
|
|
20
|
-
exports.invocations = invocations
|
|
21
|
-
exports.locator = locator
|
|
18
|
+
export const locator = {}
|
package/test/component.test.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, beforeEach, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
import { Component } from '../src/component.js'
|
|
6
|
+
import { codes } from '../src/exceptions.js'
|
|
7
|
+
import * as fixtures from './component.fixtures.js'
|
|
8
|
+
import { AssertionError } from 'node:assert'
|
|
6
9
|
|
|
7
10
|
describe('Invocations', () => {
|
|
8
11
|
const name = ['foo', 'bar'][Math.floor(2 * Math.random())]
|
|
@@ -10,18 +13,17 @@ describe('Invocations', () => {
|
|
|
10
13
|
const component = new Component(fixtures.locator, fixtures.invocations)
|
|
11
14
|
|
|
12
15
|
beforeEach(() => {
|
|
13
|
-
|
|
16
|
+
resetCalls()
|
|
14
17
|
})
|
|
15
18
|
|
|
16
19
|
it('should invoke', async () => {
|
|
17
20
|
await component.invoke(name)
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
assert.ok(invocation.invoke.mock.callCount() > 0)
|
|
20
23
|
})
|
|
21
24
|
|
|
22
25
|
it('should throw on unknown invocation name', async () => {
|
|
23
|
-
await
|
|
24
|
-
.rejects.toMatchObject({ code: codes.NotImplemented })
|
|
26
|
+
await assert.rejects(() => component.invoke('baz'), AssertionError)
|
|
25
27
|
})
|
|
26
28
|
|
|
27
29
|
it('should invoke input and query', async () => {
|
|
@@ -29,12 +31,22 @@ describe('Invocations', () => {
|
|
|
29
31
|
const query = { test: Math.random() }
|
|
30
32
|
await component.invoke(name, { input, query })
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
assert.ok(invocation.invoke.mock.calls.some((call) => call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], { input, query })))
|
|
33
35
|
})
|
|
34
36
|
|
|
35
37
|
it('should return io', async () => {
|
|
36
38
|
const io = await component.invoke(name)
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
assert.strictEqual(io, fixtures.invocations[name].invoke.mock.calls[0].result)
|
|
39
41
|
})
|
|
40
42
|
})
|
|
43
|
+
|
|
44
|
+
function resetCalls (target = [assert, fixtures], seen = new Set()) {
|
|
45
|
+
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
46
|
+
|
|
47
|
+
seen.add(target)
|
|
48
|
+
|
|
49
|
+
for (const value of Object.values(target))
|
|
50
|
+
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
51
|
+
else resetCalls(value, seen)
|
|
52
|
+
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { random, timeout } from '@toa.io/generic'
|
|
2
|
+
import { Connector } from '../src/connector.js'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const { Connector } = require('../src/connector')
|
|
5
|
-
|
|
6
|
-
class TestConnector extends Connector {
|
|
4
|
+
export class TestConnector extends Connector {
|
|
7
5
|
#label
|
|
8
6
|
#seq
|
|
9
7
|
|
|
@@ -29,12 +27,16 @@ class TestConnector extends Connector {
|
|
|
29
27
|
}
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
class FailingConnector extends Connector {
|
|
30
|
+
export class FailingConnector extends Connector {
|
|
33
31
|
async open () {
|
|
34
32
|
await timeout(random(10))
|
|
35
33
|
throw new Error('FailingConnector')
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
/** Stands for a connector waiting for something that never arrives. */
|
|
38
|
+
export class StuckConnector extends Connector {
|
|
39
|
+
async open () {
|
|
40
|
+
return new Promise(() => undefined)
|
|
41
|
+
}
|
|
42
|
+
}
|
package/test/connector.test.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import { timeout } from '@toa.io/generic'
|
|
5
|
+
|
|
6
|
+
import * as fixtures from './connector.fixtures.js'
|
|
4
7
|
|
|
5
8
|
let sequence
|
|
6
9
|
|
|
@@ -17,14 +20,14 @@ describe('callbacks', () => {
|
|
|
17
20
|
|
|
18
21
|
it('should call connection', async () => {
|
|
19
22
|
await a.connect()
|
|
20
|
-
|
|
23
|
+
assert.deepStrictEqual(sequence, ['+a'])
|
|
21
24
|
})
|
|
22
25
|
|
|
23
26
|
it('should call disconnection', async () => {
|
|
24
27
|
await a.connect()
|
|
25
28
|
await a.disconnect()
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
assert.ok(sequence.indexOf('+a') < sequence.indexOf('-a'))
|
|
28
31
|
})
|
|
29
32
|
|
|
30
33
|
it('should reconnect', async () => {
|
|
@@ -32,7 +35,7 @@ describe('callbacks', () => {
|
|
|
32
35
|
await a.reconnect()
|
|
33
36
|
await a.reconnect()
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
assert.deepStrictEqual(sequence, ['+a', '-a', '*a', '+a', '-a', '*a', '+a'])
|
|
36
39
|
})
|
|
37
40
|
})
|
|
38
41
|
|
|
@@ -55,9 +58,9 @@ describe('dependencies', () => {
|
|
|
55
58
|
|
|
56
59
|
await a.connect()
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+b'))
|
|
62
|
+
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
63
|
+
assert.ok(sequence.indexOf('+d') < sequence.indexOf('+a'))
|
|
61
64
|
})
|
|
62
65
|
|
|
63
66
|
it('should wait array of connectors', async () => {
|
|
@@ -67,10 +70,10 @@ describe('dependencies', () => {
|
|
|
67
70
|
|
|
68
71
|
await a.connect()
|
|
69
72
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+b'))
|
|
74
|
+
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+d'))
|
|
75
|
+
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
76
|
+
assert.ok(sequence.indexOf('+d') < sequence.indexOf('+a'))
|
|
74
77
|
})
|
|
75
78
|
|
|
76
79
|
it('should wait array(1) of connectors', async () => {
|
|
@@ -79,12 +82,12 @@ describe('dependencies', () => {
|
|
|
79
82
|
|
|
80
83
|
await a.connect()
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+b'))
|
|
86
|
+
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
84
87
|
})
|
|
85
88
|
|
|
86
89
|
it('should throw on empty array', async () => {
|
|
87
|
-
|
|
90
|
+
assert.throws(() => a.depends([]), (error) => /must not be empty/.test(error.message))
|
|
88
91
|
})
|
|
89
92
|
|
|
90
93
|
it('should await 2-way dependencies', async () => {
|
|
@@ -93,23 +96,24 @@ describe('dependencies', () => {
|
|
|
93
96
|
|
|
94
97
|
await a.connect()
|
|
95
98
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+a'))
|
|
100
|
+
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+a'))
|
|
101
|
+
assert.ok(sequence.indexOf('+d') < sequence.indexOf('+a'))
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
assert.ok(sequence.indexOf('+b') < sequence.indexOf('+d'))
|
|
104
|
+
assert.ok(sequence.indexOf('+c') < sequence.indexOf('+d'))
|
|
102
105
|
})
|
|
103
106
|
|
|
104
107
|
it('should disconnect before dependencies', async () => {
|
|
105
108
|
a.depends(b).depends(c)
|
|
106
109
|
b.depends(d)
|
|
107
110
|
|
|
111
|
+
await a.connect()
|
|
108
112
|
await a.disconnect()
|
|
109
113
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
assert.ok(sequence.indexOf('-a') < sequence.indexOf('-b'))
|
|
115
|
+
assert.ok(sequence.indexOf('-b') < sequence.indexOf('-c'))
|
|
116
|
+
assert.ok(sequence.indexOf('-b') < sequence.indexOf('-d'))
|
|
113
117
|
})
|
|
114
118
|
|
|
115
119
|
it('should call disconnected', async () => {
|
|
@@ -118,10 +122,10 @@ describe('dependencies', () => {
|
|
|
118
122
|
|
|
119
123
|
await a.disconnect()
|
|
120
124
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
assert.ok(sequence.indexOf('*c') < sequence.indexOf('*b'))
|
|
126
|
+
assert.ok(sequence.indexOf('*b') < sequence.indexOf('*a'))
|
|
127
|
+
assert.ok(sequence.indexOf('*d') < sequence.indexOf('*b'))
|
|
128
|
+
assert.strictEqual(sequence.indexOf('*a'), sequence.length - 1)
|
|
125
129
|
})
|
|
126
130
|
|
|
127
131
|
it('should disconnect if no parents left', async () => {
|
|
@@ -131,19 +135,36 @@ describe('dependencies', () => {
|
|
|
131
135
|
await a.connect()
|
|
132
136
|
await b.connect()
|
|
133
137
|
|
|
134
|
-
|
|
138
|
+
assert.deepStrictEqual(sequence, ['+c', '+a', '+b'])
|
|
135
139
|
|
|
136
140
|
await a.disconnect()
|
|
137
141
|
|
|
138
|
-
|
|
142
|
+
assert.deepStrictEqual(sequence, ['+c', '+a', '+b', '-a', '*a'])
|
|
139
143
|
|
|
140
144
|
await b.disconnect()
|
|
141
145
|
|
|
142
|
-
|
|
146
|
+
assert.deepStrictEqual(sequence, ['+c', '+a', '+b', '-a', '*a', '-b', '-c', '*c', '*b'])
|
|
143
147
|
})
|
|
144
148
|
|
|
145
149
|
it('should throw if depends not on Connector', async () => {
|
|
146
|
-
|
|
150
|
+
assert.throws(() => a.depends({}))
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('should disconnect while still connecting', async () => {
|
|
154
|
+
const stuck = new fixtures.StuckConnector()
|
|
155
|
+
|
|
156
|
+
a.depends(stuck).depends(b)
|
|
157
|
+
|
|
158
|
+
void a.connect()
|
|
159
|
+
|
|
160
|
+
while (b.connected !== true) await timeout(1)
|
|
161
|
+
|
|
162
|
+
// `a` never connects, and disconnecting must not wait for it to
|
|
163
|
+
assert.deepStrictEqual(a.connected, false)
|
|
164
|
+
|
|
165
|
+
await a.disconnect()
|
|
166
|
+
|
|
167
|
+
assert.deepStrictEqual(sequence, ['+b', '-b', '*b', '*a'])
|
|
147
168
|
})
|
|
148
169
|
|
|
149
170
|
describe('errors', () => {
|
|
@@ -156,21 +177,21 @@ describe('dependencies', () => {
|
|
|
156
177
|
it('should disconnect on fail', async () => {
|
|
157
178
|
f.depends(b).depends(c)
|
|
158
179
|
|
|
159
|
-
await
|
|
160
|
-
|
|
180
|
+
await assert.rejects(f.connect(), (error) => /FailingConnector/.test(error.message))
|
|
181
|
+
assert.deepStrictEqual(sequence, ['+c', '+b', '-b', '-c', '*c', '*b'])
|
|
161
182
|
})
|
|
162
183
|
|
|
163
184
|
it('should interrupt connection chain', async () => {
|
|
164
185
|
a.depends(f).depends(c)
|
|
165
186
|
f.depends(d)
|
|
166
187
|
|
|
167
|
-
await
|
|
188
|
+
await assert.rejects(a.connect(), (error) => /FailingConnector/.test(error.message))
|
|
168
189
|
|
|
169
|
-
|
|
170
|
-
|
|
190
|
+
assert.ok(sequence.indexOf('+c') < sequence.indexOf('-c'))
|
|
191
|
+
assert.ok(sequence.indexOf('+d') < sequence.indexOf('-d'))
|
|
171
192
|
|
|
172
|
-
|
|
173
|
-
|
|
193
|
+
assert.strictEqual(sequence.indexOf('+a'), -1)
|
|
194
|
+
assert.strictEqual(sequence.indexOf('-a'), -1)
|
|
174
195
|
})
|
|
175
196
|
})
|
|
176
197
|
})
|
package/test/context.fixtures.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import { mock } from 'node:test'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { Connector } from '../src/connector.js'
|
|
4
4
|
|
|
5
|
-
const local = {
|
|
6
|
-
link:
|
|
5
|
+
export const local = {
|
|
6
|
+
link: mock.fn()
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
const discover =
|
|
10
|
-
invoke:
|
|
11
|
-
link:
|
|
9
|
+
export const discover = mock.fn(() => ({
|
|
10
|
+
invoke: mock.fn(),
|
|
11
|
+
link: mock.fn()
|
|
12
12
|
}))
|
|
13
13
|
|
|
14
|
-
const aspects = [new Connector(), new Connector()]
|
|
15
|
-
|
|
16
|
-
exports.local = local
|
|
17
|
-
exports.discover = discover
|
|
18
|
-
exports.aspects = aspects
|
|
14
|
+
export const aspects = [new Connector(), new Connector()]
|
package/test/context.test.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, beforeEach, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import * as fixtures from './context.fixtures.js'
|
|
5
|
+
import { Context } from '../src/context.js'
|
|
5
6
|
|
|
6
7
|
/** @type {toa.core.Context} */
|
|
7
8
|
let context
|
|
8
9
|
|
|
9
10
|
beforeEach(() => {
|
|
10
|
-
|
|
11
|
+
resetCalls()
|
|
11
12
|
|
|
12
13
|
context = new Context(fixtures.local, fixtures.discover, fixtures.aspects)
|
|
13
14
|
})
|
|
14
15
|
|
|
15
16
|
it('should expose aspects', () => {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
assert.notStrictEqual(context.aspects, undefined)
|
|
18
|
+
assert.deepStrictEqual(context.aspects, fixtures.aspects)
|
|
18
19
|
})
|
|
19
20
|
|
|
20
21
|
describe('call', () => {
|
|
@@ -24,6 +25,16 @@ describe('call', () => {
|
|
|
24
25
|
await context.call('a', 'b', 'c', request)
|
|
25
26
|
await context.call('a', 'b', 'c', request)
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
assert.strictEqual(fixtures.discover.mock.callCount(), 1)
|
|
28
29
|
})
|
|
29
30
|
})
|
|
31
|
+
|
|
32
|
+
function resetCalls (target = [assert, fixtures], seen = new Set()) {
|
|
33
|
+
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
34
|
+
|
|
35
|
+
seen.add(target)
|
|
36
|
+
|
|
37
|
+
for (const value of Object.values(target))
|
|
38
|
+
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
39
|
+
else resetCalls(value, seen)
|
|
40
|
+
}
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
import { it, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util'
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
import { generate } from 'randomstring'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
import { Contract } from '../../src/contract/contract.js'
|
|
8
|
+
import * as fixtures from './contract.fixtures.js'
|
|
7
9
|
|
|
8
|
-
let
|
|
10
|
+
let contract
|
|
9
11
|
|
|
10
12
|
beforeEach(() => {
|
|
11
|
-
|
|
13
|
+
contract = new Contract(fixtures.schema)
|
|
12
14
|
})
|
|
13
15
|
|
|
14
16
|
it('should fit value', () => {
|
|
15
17
|
const value = { foo: generate() }
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
contract.fit(value)
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
assert.ok(fixtures.schema.fit.mock.calls.some((call) => call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], value)))
|
|
20
22
|
})
|
|
21
23
|
|
|
22
24
|
it('should throw on invalid value', () => {
|
|
23
25
|
const value = { invalid: true }
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
assert.throws(() => contract.fit(value))
|
|
26
28
|
})
|
|
@@ -1,33 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
import { mock } from 'node:test'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { generate } from 'randomstring'
|
|
4
|
+
import { readFileSync } from 'node:fs'
|
|
5
|
+
import { load as parseYAML } from 'js-yaml'
|
|
6
|
+
import { resolve } from 'path'
|
|
6
7
|
|
|
7
8
|
// noinspection JSCheckFunctionSignatures
|
|
8
|
-
const schema = {
|
|
9
|
-
fit:
|
|
9
|
+
export const schema = {
|
|
10
|
+
fit: mock.fn((input) => (input.invalid ? { message: generate() } : null))
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const query = {
|
|
13
|
-
parse:
|
|
13
|
+
export const query = {
|
|
14
|
+
parse: mock.fn(() => ({ [generate()]: generate() }))
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const declaration = {}
|
|
17
|
+
export const declaration = {}
|
|
17
18
|
|
|
18
|
-
const schemas = {
|
|
19
|
+
export const schemas = {
|
|
19
20
|
request: {
|
|
20
21
|
type: 'object',
|
|
21
22
|
properties: {
|
|
22
23
|
input: { type: 'null' },
|
|
23
|
-
query:
|
|
24
|
+
query: parseYAML(readFileSync(resolve(import.meta.dirname, '../../src/contract/schemas/query.yaml'), 'utf8')),
|
|
24
25
|
authentic: { type: 'boolean' }
|
|
25
26
|
},
|
|
26
27
|
additionalProperties: true
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
exports.schema = schema
|
|
31
|
-
exports.query = query
|
|
32
|
-
exports.declaration = declaration
|
|
33
|
-
exports.schemas = schemas
|