@toa.io/core 1.0.0-alpha.273 → 1.0.0-alpha.277
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 +8 -0
- package/package.json +8 -7
- package/src/assignment.js +2 -6
- package/src/call.js +5 -7
- package/src/cascade.js +2 -6
- package/src/component.js +4 -8
- package/src/composition.js +3 -7
- package/src/connector.js +2 -6
- package/src/context.js +2 -6
- package/src/contract/contract.js +2 -6
- package/src/contract/index.js +2 -7
- package/src/contract/reply.js +4 -8
- package/src/contract/request.js +4 -8
- package/src/contract/schemas/index.js +7 -9
- package/src/discovery.js +3 -7
- package/src/effect.js +2 -6
- package/src/emission.js +2 -6
- package/src/entities/changeset.js +2 -6
- package/src/entities/entity.js +3 -7
- package/src/entities/factory.js +5 -9
- package/src/entities/index.js +1 -5
- package/src/entities/newid.js +2 -4
- package/src/entities/set.js +2 -6
- package/src/event.js +3 -7
- package/src/exceptions.js +37 -30
- package/src/exposition.js +2 -6
- package/src/guard.js +1 -5
- package/src/index.js +28 -55
- package/src/locator.js +2 -6
- package/src/observation.js +2 -6
- package/src/operation.js +4 -8
- package/src/outbox/index.js +1 -6
- package/src/outbox/outbox.js +5 -10
- package/src/query/criteria.js +3 -7
- package/src/query/options.js +2 -6
- package/src/query.js +5 -6
- package/src/receiver.js +4 -8
- package/src/reflection.js +2 -6
- package/src/remote.js +3 -7
- package/src/state.js +2 -6
- package/src/transition.js +4 -8
- package/src/transmission.js +3 -7
- package/src/unmanaged.js +2 -6
- 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 -11
- package/test/connector.fixtures.js +5 -11
- package/test/connector.test.js +42 -41
- package/test/context.fixtures.js +8 -12
- package/test/context.test.js +18 -7
- package/test/contract/conditions.test.js +8 -6
- package/test/contract/contract.fixtures.js +12 -17
- package/test/contract/request.test.js +51 -40
- package/test/discovery.test.js +25 -17
- package/test/emission.fixtures.js +5 -8
- package/test/emission.test.js +29 -12
- package/test/entities/entity.fixtures.js +7 -11
- package/test/entities/entity.test.js +30 -19
- package/test/entities/factory.fixtures.js +22 -10
- package/test/entities/factory.test.js +29 -17
- 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 +44 -37
- package/test/query.fixtures.js +1 -5
- package/test/query.test.js +28 -17
- package/test/receiver.fixtures.js +8 -12
- package/test/receiver.test.js +45 -22
- package/test/reflection.test.js +7 -6
- package/test/state.fixtures.js +24 -32
- package/test/state.test.js +35 -30
- package/test/transmission.fixtures.js +4 -6
- package/test/transmission.test.js +33 -15
- package/types/atomicity.d.ts +1 -1
- package/types/bindings.d.ts +1 -1
- package/types/bridges.ts +3 -3
- package/types/component.d.ts +4 -4
- package/types/context.d.ts +4 -4
- package/types/entity.d.ts +2 -2
- package/types/event.d.ts +1 -1
- package/types/extensions.d.ts +8 -7
- package/types/index.ts +16 -16
- package/types/operations.d.ts +1 -1
- package/types/outbox.d.ts +2 -2
- package/types/receiver.d.ts +2 -2
- package/types/reflection.d.ts +1 -1
- package/types/remote.d.ts +1 -1
- package/types/request.d.ts +1 -1
- package/types/state.d.ts +2 -2
- package/types/storages.d.ts +3 -3
package/test/emission.test.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
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
|
-
|
|
5
|
+
import clone from 'clone-deep'
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
import { Connector } from '../src/connector.js'
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
9
|
+
// the fixtures are not connectors, so a dependency is recorded rather than linked
|
|
10
|
+
const depends = mock.method(Connector.prototype, 'depends', () => undefined)
|
|
11
|
+
|
|
12
|
+
const dependencies = (instance) => depends.mock.calls
|
|
13
|
+
.filter((call) => call.this === instance)
|
|
14
|
+
.map((call) => call.arguments[0])
|
|
15
|
+
import { Emission } from '../src/emission.js'
|
|
16
|
+
import * as fixtures from './emission.fixtures.js'
|
|
10
17
|
|
|
11
18
|
let emission, event
|
|
12
19
|
|
|
13
20
|
beforeEach(async () => {
|
|
14
|
-
|
|
21
|
+
resetCalls()
|
|
22
|
+
depends.mock.resetCalls()
|
|
15
23
|
|
|
16
24
|
emission = new Emission(fixtures.events)
|
|
17
25
|
event = clone(fixtures.event)
|
|
@@ -20,16 +28,25 @@ beforeEach(async () => {
|
|
|
20
28
|
})
|
|
21
29
|
|
|
22
30
|
it('should depend on events', () => {
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
assert.ok(emission instanceof Connector)
|
|
32
|
+
assert.ok(dependencies(emission).some((one) => isDeepStrictEqual(one, fixtures.events)))
|
|
25
33
|
})
|
|
26
34
|
|
|
27
35
|
it('should emit events', async () => {
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
|
|
30
37
|
await emission.emit(event)
|
|
31
38
|
|
|
32
39
|
for (const evt of fixtures.events) {
|
|
33
|
-
|
|
40
|
+
assert.ok(evt.emit.mock.calls.some((call) => call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], event)))
|
|
34
41
|
}
|
|
35
42
|
})
|
|
43
|
+
|
|
44
|
+
function resetCalls (target = [assert, clone, depends, dependencies, 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,16 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import { mock } from 'node:test'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { generate } from 'randomstring'
|
|
4
4
|
|
|
5
5
|
// noinspection JSCheckFunctionSignatures
|
|
6
|
-
const schema = {
|
|
7
|
-
fit:
|
|
6
|
+
export const schema = {
|
|
7
|
+
fit: mock.fn((object) =>
|
|
8
8
|
(object.fail ? { [generate()]: generate() } : null)),
|
|
9
9
|
|
|
10
|
-
defaults:
|
|
10
|
+
defaults: mock.fn(() => ({ [generate()]: generate() }))
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const state = () => ({
|
|
13
|
+
export const state = () => ({
|
|
14
14
|
id: generate(),
|
|
15
15
|
foo: generate(),
|
|
16
16
|
_created: generate(),
|
|
@@ -19,11 +19,7 @@ const state = () => ({
|
|
|
19
19
|
_version: 0
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
const failed = () => ({
|
|
22
|
+
export const failed = () => ({
|
|
23
23
|
...state(),
|
|
24
24
|
fail: true
|
|
25
25
|
})
|
|
26
|
-
|
|
27
|
-
exports.schema = schema
|
|
28
|
-
exports.state = state
|
|
29
|
-
exports.failed = failed
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it, beforeEach, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import { Entity } from '../../src/entities/entity.js'
|
|
5
|
+
import * as fixtures from './entity.fixtures.js'
|
|
5
6
|
|
|
6
7
|
beforeEach(() => {
|
|
7
|
-
|
|
8
|
+
resetCalls()
|
|
8
9
|
})
|
|
9
10
|
|
|
10
11
|
describe('argument', () => {
|
|
@@ -12,15 +13,15 @@ describe('argument', () => {
|
|
|
12
13
|
const state = fixtures.state()
|
|
13
14
|
const entity = new Entity(fixtures.schema, state)
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
assert.deepStrictEqual(entity.get(), state)
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
it('should snapshot the record it may commit', () => {
|
|
19
20
|
const record = fixtures.state()
|
|
20
21
|
const entity = new Entity(fixtures.schema, record)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
assert.notStrictEqual(entity.get(), record)
|
|
24
|
+
assert.strictEqual(entity.event().origin, record)
|
|
24
25
|
})
|
|
25
26
|
})
|
|
26
27
|
|
|
@@ -30,20 +31,20 @@ describe('read-only', () => {
|
|
|
30
31
|
const entity = new Entity(fixtures.schema, record, undefined, false)
|
|
31
32
|
|
|
32
33
|
// no pre-image to diff against, hence no copy of it
|
|
33
|
-
|
|
34
|
+
assert.strictEqual(entity.get(), record)
|
|
34
35
|
})
|
|
35
36
|
|
|
36
37
|
it('should still report a tombstone', () => {
|
|
37
38
|
const record = { ...fixtures.state(), _deleted: Date.now() }
|
|
38
39
|
const entity = new Entity(fixtures.schema, record, undefined, false)
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
assert.strictEqual(entity.deleted, true)
|
|
41
42
|
})
|
|
42
43
|
|
|
43
44
|
it('should refuse to be modified', () => {
|
|
44
45
|
const entity = new Entity(fixtures.schema, fixtures.state(), undefined, false)
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
assert.throws(() => entity.set(entity.get()), (error) => /read-only/.test(error.message))
|
|
47
48
|
})
|
|
48
49
|
})
|
|
49
50
|
|
|
@@ -56,9 +57,9 @@ describe('tombstone', () => {
|
|
|
56
57
|
state.foo = 'revived'
|
|
57
58
|
entity.set(state)
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
assert.strictEqual(entity.get()._deleted, null)
|
|
61
|
+
assert.strictEqual(entity.deleted, false)
|
|
62
|
+
assert.strictEqual(entity.event().state._deleted, null)
|
|
62
63
|
})
|
|
63
64
|
|
|
64
65
|
it('should keep tombstone written by transition', () => {
|
|
@@ -70,8 +71,8 @@ describe('tombstone', () => {
|
|
|
70
71
|
state._deleted = timestamp
|
|
71
72
|
entity.set(state)
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
assert.strictEqual(entity.get()._deleted, timestamp)
|
|
75
|
+
assert.strictEqual(entity.deleted, true)
|
|
75
76
|
})
|
|
76
77
|
})
|
|
77
78
|
|
|
@@ -85,8 +86,18 @@ it('should provide event', () => {
|
|
|
85
86
|
|
|
86
87
|
const event = entity.event()
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
assert.partialDeepStrictEqual(event, { state, origin })
|
|
90
|
+
assert.strictEqual(event.state.foo, 'new value')
|
|
91
|
+
assert.strictEqual(event.state._version, 1)
|
|
92
|
+
assert.notStrictEqual(event.origin.foo, 'new value')
|
|
92
93
|
})
|
|
94
|
+
|
|
95
|
+
function resetCalls (target = [assert, fixtures], seen = new Set()) {
|
|
96
|
+
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
97
|
+
|
|
98
|
+
seen.add(target)
|
|
99
|
+
|
|
100
|
+
for (const value of Object.values(target))
|
|
101
|
+
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
102
|
+
else resetCalls(value, seen)
|
|
103
|
+
}
|
|
@@ -1,18 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
import { mock } from 'node:test'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import randomstring from 'randomstring'
|
|
4
4
|
|
|
5
5
|
const schema = { [randomstring.generate()]: randomstring.generate() }
|
|
6
|
-
const storage = { id:
|
|
6
|
+
const storage = { id: mock.fn(() => randomstring.generate()) }
|
|
7
7
|
const entity = { [randomstring.generate()]: randomstring.generate() }
|
|
8
8
|
const set = Array.from(Array(5))
|
|
9
9
|
.map((_, index) => ({ id: index, [randomstring.generate()]: randomstring.generate() }))
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
const
|
|
11
|
+
// node:test records a mock's calls but not the instances it constructed
|
|
12
|
+
const entities = []
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const Entity = mock.fn(function () {
|
|
15
|
+
this.id = randomstring.generate()
|
|
16
|
+
entities.push(this)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const EntitySet = mock.fn(function () {})
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
// named `mock` for its consumers, which is what node:test calls its own tracker
|
|
28
|
+
const mocks = { Entity, EntitySet }
|
|
29
|
+
|
|
30
|
+
export { schema, storage, entity, set, entities, mocks as mock }
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
import { it, beforeEach, mock as mocking } 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
|
-
|
|
7
|
+
import * as fixtures from './factory.fixtures.js'
|
|
6
8
|
const mock = fixtures.mock
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
mocking.module('../../src/entities/entity', { namedExports: ({ Entity: mock.Entity }) })
|
|
11
|
+
mocking.module('../../src/entities/set', { namedExports: ({ EntitySet: mock.EntitySet }) })
|
|
12
|
+
|
|
13
|
+
const { Factory } = await import('../../src/entities/factory.js')
|
|
10
14
|
|
|
11
|
-
const { Factory } = require('../../src/entities/factory')
|
|
12
15
|
|
|
13
16
|
let factory
|
|
14
17
|
|
|
15
18
|
beforeEach(async () => {
|
|
16
|
-
|
|
19
|
+
resetCalls()
|
|
20
|
+
fixtures.entities.length = 0
|
|
17
21
|
|
|
18
22
|
factory = new Factory(fixtures.schema, () => fixtures.storage.id())
|
|
19
23
|
})
|
|
@@ -22,29 +26,37 @@ it('should create initial', () => {
|
|
|
22
26
|
const id = generate()
|
|
23
27
|
const initial = factory.init(id)
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
assert.ok(initial instanceof mock.Entity)
|
|
30
|
+
assert.ok(mock.Entity.mock.calls.some((call) => call.arguments.length === 3 && isDeepStrictEqual(call.arguments[0], fixtures.schema) && isDeepStrictEqual(call.arguments[1], id) && typeof call.arguments[2] === 'function'))
|
|
27
31
|
})
|
|
28
32
|
|
|
29
33
|
it('should create instance', () => {
|
|
30
34
|
const object = factory.object(fixtures.entity)
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.toHaveBeenCalledWith(fixtures.schema, fixtures.entity, expect.any(Function), true)
|
|
36
|
+
assert.ok(object instanceof mock.Entity)
|
|
37
|
+
assert.ok(mock.Entity.mock.calls.some((call) => call.arguments.length === 4 && isDeepStrictEqual(call.arguments[0], fixtures.schema) && isDeepStrictEqual(call.arguments[1], fixtures.entity) && typeof call.arguments[2] === 'function' && isDeepStrictEqual(call.arguments[3], true)))
|
|
35
38
|
})
|
|
36
39
|
|
|
37
40
|
it('should create set', () => {
|
|
38
41
|
const objects = factory.objects(fixtures.set)
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
assert.ok(objects instanceof mock.EntitySet)
|
|
41
44
|
|
|
42
45
|
const instances = fixtures.set.map((entity, index) => {
|
|
43
|
-
|
|
44
|
-
.toHaveBeenNthCalledWith(index + 1, fixtures.schema, entity, expect.any(Function), true)
|
|
46
|
+
assert.ok(((call) => call.arguments.length === 4 && isDeepStrictEqual(call.arguments[0], fixtures.schema) && isDeepStrictEqual(call.arguments[1], entity) && typeof call.arguments[2] === 'function' && isDeepStrictEqual(call.arguments[3], true))(mock.Entity.mock.calls[index + 1 - 1] ?? { arguments: [] }))
|
|
45
47
|
|
|
46
|
-
return
|
|
48
|
+
return fixtures.entities[index]
|
|
47
49
|
})
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
assert.ok(mock.EntitySet.mock.calls.some((call) => call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], instances)))
|
|
50
52
|
})
|
|
53
|
+
|
|
54
|
+
function resetCalls (target = [assert, fixtures, mock], seen = new Set()) {
|
|
55
|
+
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
56
|
+
|
|
57
|
+
seen.add(target)
|
|
58
|
+
|
|
59
|
+
for (const value of Object.values(target))
|
|
60
|
+
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
61
|
+
else resetCalls(value, seen)
|
|
62
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { mock } from 'node:test'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { generate } from 'randomstring'
|
|
4
4
|
|
|
5
|
-
const set = [
|
|
6
|
-
{ get:
|
|
7
|
-
{ get:
|
|
8
|
-
{ get:
|
|
5
|
+
export const set = [
|
|
6
|
+
{ get: mock.fn(() => ({ [generate()]: generate() })) },
|
|
7
|
+
{ get: mock.fn(() => ({ [generate()]: generate() })) },
|
|
8
|
+
{ get: mock.fn(() => ({ [generate()]: generate() })) }
|
|
9
9
|
]
|
|
10
|
-
|
|
11
|
-
exports.set = set
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import { EntitySet } from '../../src/entities/set.js'
|
|
5
|
+
import * as fixtures from './set.fixtures.js'
|
|
5
6
|
|
|
6
7
|
it('should provide state', () => {
|
|
7
8
|
const set = new EntitySet(fixtures.set)
|
|
8
9
|
const state = set.get()
|
|
9
|
-
const expected = fixtures.set.map((entity) => entity.get.mock.
|
|
10
|
+
const expected = fixtures.set.map((entity) => entity.get.mock.calls[0].result)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
assert.deepStrictEqual(state, expected)
|
|
12
13
|
})
|
package/test/event.fixtures.js
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
import { mock } from 'node:test'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { generate } from 'randomstring'
|
|
4
4
|
|
|
5
|
-
const definition = {
|
|
5
|
+
export const definition = {
|
|
6
6
|
conditioned: true,
|
|
7
7
|
subjective: true
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
// noinspection JSCheckFunctionSignatures
|
|
11
|
-
const bridge = {
|
|
12
|
-
condition:
|
|
13
|
-
payload:
|
|
11
|
+
export const bridge = {
|
|
12
|
+
condition: mock.fn(async (origin) => !origin.falsy),
|
|
13
|
+
payload: mock.fn(async () => ({ [generate()]: generate() }))
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const binding = {
|
|
17
|
-
emit:
|
|
16
|
+
export const binding = {
|
|
17
|
+
emit: mock.fn()
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const event = {
|
|
20
|
+
export const event = {
|
|
21
21
|
origin: { [generate()]: generate() },
|
|
22
22
|
state: { [generate()]: generate() },
|
|
23
23
|
changeset: { [generate()]: generate() }
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
exports.bridge = bridge
|
|
27
|
-
exports.binding = binding
|
|
28
|
-
exports.definition = definition
|
|
29
|
-
exports.event = event
|
package/test/event.test.js
CHANGED
|
@@ -1,32 +1,41 @@
|
|
|
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
|
-
|
|
5
|
+
import clone from 'clone-deep'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const { Event } = require('../src/event')
|
|
9
|
-
const fixtures = require('./event.fixtures')
|
|
7
|
+
import { Connector } from '../src/connector.js'
|
|
8
|
+
import { Event } from '../src/event.js'
|
|
9
|
+
import * as fixtures from './event.fixtures.js'
|
|
10
10
|
|
|
11
11
|
let event, emit
|
|
12
12
|
|
|
13
|
+
// the fixtures are not connectors, so the dependency is recorded rather than linked
|
|
14
|
+
const depends = mock.method(Connector.prototype, 'depends', () => undefined)
|
|
15
|
+
|
|
16
|
+
const dependencies = (instance) => depends.mock.calls
|
|
17
|
+
.filter((call) => call.this === instance)
|
|
18
|
+
.map((call) => call.arguments[0])
|
|
19
|
+
|
|
13
20
|
beforeEach(() => {
|
|
14
|
-
|
|
21
|
+
resetCalls()
|
|
22
|
+
depends.mock.resetCalls()
|
|
15
23
|
|
|
16
24
|
event = new Event(fixtures.definition, fixtures.binding, fixtures.bridge)
|
|
17
25
|
emit = () => event.emit(fixtures.event)
|
|
18
26
|
})
|
|
19
27
|
|
|
20
28
|
it('should depend on binding', () => {
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
assert.ok(event instanceof Connector)
|
|
30
|
+
assert.ok(dependencies(event).some((one) => isDeepStrictEqual(one, fixtures.binding)))
|
|
23
31
|
})
|
|
24
32
|
|
|
25
33
|
it('should depend on bridge if provided', () => {
|
|
26
|
-
|
|
34
|
+
assert.ok(dependencies(event).some((one) => isDeepStrictEqual(one, fixtures.bridge)))
|
|
35
|
+
|
|
36
|
+
const bridgeless = new Event(fixtures.definition, fixtures.binding)
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
expect(Connector.mock.instances[1].depends).not.toHaveBeenCalledWith(fixtures.bridge)
|
|
38
|
+
assert.ok(!dependencies(bridgeless).some((one) => isDeepStrictEqual(one, fixtures.bridge)))
|
|
30
39
|
})
|
|
31
40
|
|
|
32
41
|
describe('condition', () => {
|
|
@@ -34,15 +43,14 @@ describe('condition', () => {
|
|
|
34
43
|
it('should call condition', async () => {
|
|
35
44
|
await emit()
|
|
36
45
|
|
|
37
|
-
|
|
46
|
+
assert.ok(fixtures.bridge.condition.mock.calls.some((call) => call.arguments.length === 1 && isDeepStrictEqual(call.arguments[0], fixtures.event)))
|
|
38
47
|
})
|
|
39
48
|
|
|
40
49
|
it('should emit if condition returns true', async () => {
|
|
41
50
|
await emit()
|
|
42
51
|
|
|
43
|
-
const payload = await fixtures.bridge.payload.mock.
|
|
44
|
-
|
|
45
|
-
expect(fixtures.binding.emit).toHaveBeenCalledWith(message)
|
|
52
|
+
const payload = await fixtures.bridge.payload.mock.calls[0].result
|
|
53
|
+
assertEmitted(payload)
|
|
46
54
|
})
|
|
47
55
|
|
|
48
56
|
it('should not emit if condition returns false', async () => {
|
|
@@ -52,7 +60,7 @@ describe('condition', () => {
|
|
|
52
60
|
|
|
53
61
|
await event.emit(origin, fixtures.event.changeset, fixtures.event.state)
|
|
54
62
|
|
|
55
|
-
|
|
63
|
+
assert.strictEqual(fixtures.binding.emit.mock.callCount(), 0)
|
|
56
64
|
})
|
|
57
65
|
})
|
|
58
66
|
|
|
@@ -68,12 +76,10 @@ describe('condition', () => {
|
|
|
68
76
|
it('should not call condition', async () => {
|
|
69
77
|
await event.emit(fixtures.event.origin, fixtures.event.changeset, fixtures.event.state)
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
assert.ok(!(fixtures.bridge.condition.mock.calls.some((call) => call.arguments.length === 0)))
|
|
72
80
|
|
|
73
|
-
const payload = await fixtures.bridge.payload.mock.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
expect(fixtures.binding.emit).toHaveBeenCalledWith(message)
|
|
81
|
+
const payload = await fixtures.bridge.payload.mock.calls[0].result
|
|
82
|
+
assertEmitted(payload)
|
|
77
83
|
})
|
|
78
84
|
})
|
|
79
85
|
})
|
|
@@ -83,10 +89,8 @@ describe('payload', () => {
|
|
|
83
89
|
it('should emit payload', async () => {
|
|
84
90
|
await emit()
|
|
85
91
|
|
|
86
|
-
const payload = await fixtures.bridge.payload.mock.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
expect(fixtures.binding.emit).toHaveBeenCalledWith(message)
|
|
92
|
+
const payload = await fixtures.bridge.payload.mock.calls[0].result
|
|
93
|
+
assertEmitted(payload)
|
|
90
94
|
})
|
|
91
95
|
})
|
|
92
96
|
|
|
@@ -103,16 +107,38 @@ describe('payload', () => {
|
|
|
103
107
|
it('should not call payload', async () => {
|
|
104
108
|
await emit()
|
|
105
109
|
|
|
106
|
-
|
|
110
|
+
assert.strictEqual(fixtures.bridge.payload.mock.callCount(), 0)
|
|
107
111
|
})
|
|
108
112
|
|
|
109
113
|
it('should return state as payload', async () => {
|
|
110
114
|
await emit()
|
|
111
115
|
|
|
112
116
|
const payload = fixtures.event.state
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
expect(fixtures.binding.emit).toHaveBeenCalledWith(message)
|
|
117
|
+
assertEmitted(payload)
|
|
116
118
|
})
|
|
117
119
|
})
|
|
118
120
|
})
|
|
121
|
+
|
|
122
|
+
function resetCalls (target = [assert, clone, fixtures, depends, dependencies], seen = new Set()) {
|
|
123
|
+
if (target === null || typeof target !== 'object' || seen.has(target)) return
|
|
124
|
+
|
|
125
|
+
seen.add(target)
|
|
126
|
+
|
|
127
|
+
for (const value of Object.values(target))
|
|
128
|
+
if (typeof value === 'function' && value.mock !== undefined) value.mock.resetCalls()
|
|
129
|
+
else resetCalls(value, seen)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** The message carries the payload and a telemetry token generated per emission. */
|
|
133
|
+
function assertEmitted (payload) {
|
|
134
|
+
const emitted = fixtures.binding.emit.mock.calls
|
|
135
|
+
.map((call) => call.arguments[0])
|
|
136
|
+
.filter((message) => isDeepStrictEqual(message.payload, payload))
|
|
137
|
+
|
|
138
|
+
assert.notStrictEqual(emitted.length, 0)
|
|
139
|
+
|
|
140
|
+
for (const message of emitted) {
|
|
141
|
+
assert.strictEqual(typeof message.telemetry, 'string')
|
|
142
|
+
assert.deepStrictEqual(Object.keys(message).sort(), ['payload', 'telemetry'])
|
|
143
|
+
}
|
|
144
|
+
}
|