@toa.io/core 0.1.0-alpha.12

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 (68) hide show
  1. package/LICENSE +22 -0
  2. package/package.json +28 -0
  3. package/src/assignment.js +22 -0
  4. package/src/call.js +29 -0
  5. package/src/cascade.js +32 -0
  6. package/src/composition.js +26 -0
  7. package/src/connector.js +122 -0
  8. package/src/context.js +43 -0
  9. package/src/contract/conditions.js +21 -0
  10. package/src/contract/index.js +7 -0
  11. package/src/contract/reply.js +22 -0
  12. package/src/contract/request.js +49 -0
  13. package/src/contract/schemas/error.yaml +7 -0
  14. package/src/contract/schemas/index.js +7 -0
  15. package/src/contract/schemas/query.yaml +31 -0
  16. package/src/discovery.js +33 -0
  17. package/src/emission.js +23 -0
  18. package/src/entities/changeset.js +46 -0
  19. package/src/entities/entity.js +48 -0
  20. package/src/entities/factory.js +33 -0
  21. package/src/entities/index.js +5 -0
  22. package/src/entities/set.js +15 -0
  23. package/src/event.js +33 -0
  24. package/src/exceptions.js +88 -0
  25. package/src/exposition.js +24 -0
  26. package/src/index.js +43 -0
  27. package/src/locator.js +49 -0
  28. package/src/observation.js +19 -0
  29. package/src/operation.js +61 -0
  30. package/src/query/criteria.js +41 -0
  31. package/src/query/options.js +40 -0
  32. package/src/query.js +36 -0
  33. package/src/receiver.js +36 -0
  34. package/src/remote.js +17 -0
  35. package/src/runtime.js +38 -0
  36. package/src/state.js +95 -0
  37. package/src/transition.js +50 -0
  38. package/src/transmission.js +33 -0
  39. package/test/call.fixtures.js +25 -0
  40. package/test/call.test.js +52 -0
  41. package/test/cascade.fixtures.js +11 -0
  42. package/test/cascade.test.js +42 -0
  43. package/test/connector.fixtures.js +40 -0
  44. package/test/connector.test.js +199 -0
  45. package/test/contract/conditions.test.js +26 -0
  46. package/test/contract/contract.fixtures.js +27 -0
  47. package/test/contract/request.test.js +99 -0
  48. package/test/emission.fixtures.js +16 -0
  49. package/test/emission.test.js +35 -0
  50. package/test/entities/entity.fixtures.js +26 -0
  51. package/test/entities/entity.test.js +64 -0
  52. package/test/entities/factory.fixtures.js +18 -0
  53. package/test/entities/factory.test.js +48 -0
  54. package/test/entities/set.fixtures.js +11 -0
  55. package/test/entities/set.test.js +12 -0
  56. package/test/event.fixtures.js +28 -0
  57. package/test/event.test.js +106 -0
  58. package/test/locator.test.js +34 -0
  59. package/test/query.fixtures.js +100 -0
  60. package/test/query.test.js +86 -0
  61. package/test/receiver.fixtures.js +22 -0
  62. package/test/receiver.test.js +66 -0
  63. package/test/runtime.fixtures.js +19 -0
  64. package/test/runtime.test.js +40 -0
  65. package/test/state.fixtures.js +46 -0
  66. package/test/state.test.js +54 -0
  67. package/test/transmission.fixtures.js +15 -0
  68. package/test/transmission.test.js +46 -0
@@ -0,0 +1,64 @@
1
+ 'use strict'
2
+
3
+ const { Entity } = require('../../src/entities/entity')
4
+ const fixtures = require('./entity.fixtures')
5
+
6
+ beforeEach(() => {
7
+ jest.clearAllMocks()
8
+ })
9
+
10
+ describe('new', () => {
11
+ it('should throw on schema error', () => {
12
+ const entity = new Entity(fixtures.schema)
13
+
14
+ expect(() => entity.set(fixtures.failed())).toThrow()
15
+ })
16
+
17
+ it('should provide state', () => {
18
+ const entity = new Entity(fixtures.schema)
19
+ const state = fixtures.state()
20
+
21
+ entity.set(state)
22
+
23
+ expect(entity.get()).toEqual(state)
24
+ })
25
+ })
26
+
27
+ describe('argument', () => {
28
+ it('should provide initial state if no argument passed', () => {
29
+ const entity = new Entity(fixtures.schema)
30
+
31
+ expect(entity.get()).toStrictEqual(fixtures.schema.defaults.mock.results[0].value)
32
+ })
33
+
34
+ it('should set provide origin state', () => {
35
+ const state = fixtures.state()
36
+ const entity = new Entity(fixtures.schema, state)
37
+
38
+ expect(entity.get()).toStrictEqual(state)
39
+ })
40
+
41
+ it('should not validate origin state', () => {
42
+ const state = fixtures.failed()
43
+ const entity = new Entity(fixtures.schema, state)
44
+
45
+ expect(entity.get()).toStrictEqual(state)
46
+ })
47
+ })
48
+
49
+ it('should provide event', () => {
50
+ const origin = fixtures.state()
51
+ const entity = new Entity(fixtures.schema, origin)
52
+ const state = entity.get()
53
+
54
+ state.foo = 'new value'
55
+ entity.set(state)
56
+
57
+ const event = entity.event()
58
+
59
+ expect(event).toStrictEqual({
60
+ state,
61
+ origin: origin,
62
+ changeset: { foo: 'new value' }
63
+ })
64
+ })
@@ -0,0 +1,18 @@
1
+ 'use strict'
2
+
3
+ const randomstring = require('randomstring')
4
+
5
+ const schema = { [randomstring.generate()]: randomstring.generate() }
6
+ const storage = { id: jest.fn(() => randomstring.generate()) }
7
+ const entity = { [randomstring.generate()]: randomstring.generate() }
8
+ const set = Array.from(Array(5))
9
+ .map((_, index) => ({ id: index, [randomstring.generate()]: randomstring.generate() }))
10
+
11
+ const Entity = jest.fn().mockImplementation(function () { this.id = randomstring.generate() })
12
+ const EntitySet = jest.fn().mockImplementation(function () {})
13
+
14
+ exports.schema = schema
15
+ exports.storage = storage
16
+ exports.entity = entity
17
+ exports.set = set
18
+ exports.mock = { Entity, EntitySet }
@@ -0,0 +1,48 @@
1
+ 'use strict'
2
+
3
+ const { generate } = require('randomstring')
4
+
5
+ const fixtures = require('./factory.fixtures')
6
+ const mock = fixtures.mock
7
+
8
+ jest.mock('../../src/entities/entity', () => ({ Entity: mock.Entity }))
9
+ jest.mock('../../src/entities/set', () => ({ EntitySet: mock.EntitySet }))
10
+
11
+ const { Factory } = require('../../src/entities/factory')
12
+
13
+ let factory
14
+
15
+ beforeEach(async () => {
16
+ jest.clearAllMocks()
17
+
18
+ factory = new Factory(fixtures.schema, () => fixtures.storage.id())
19
+ })
20
+
21
+ it('should create initial', () => {
22
+ const id = generate()
23
+ const initial = factory.init(id)
24
+
25
+ expect(initial).toBeInstanceOf(mock.Entity)
26
+ expect(initial.constructor).toHaveBeenCalledWith(fixtures.schema, id)
27
+ })
28
+
29
+ it('should create instance', () => {
30
+ const entity = factory.entity(fixtures.entity)
31
+
32
+ expect(entity).toBeInstanceOf(mock.Entity)
33
+ expect(entity.constructor).toHaveBeenCalledWith(fixtures.schema, fixtures.entity)
34
+ })
35
+
36
+ it('should create set', () => {
37
+ const set = factory.set(fixtures.set)
38
+
39
+ expect(set).toBeInstanceOf(mock.EntitySet)
40
+
41
+ const instances = fixtures.set.map((entity, index) => {
42
+ expect(mock.Entity).toHaveBeenNthCalledWith(index + 1, fixtures.schema, entity)
43
+
44
+ return mock.Entity.mock.instances[index]
45
+ })
46
+
47
+ expect(set.constructor).toHaveBeenCalledWith(instances)
48
+ })
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ const { generate } = require('randomstring')
4
+
5
+ const set = [
6
+ { get: jest.fn(() => ({ [generate()]: generate() })) },
7
+ { get: jest.fn(() => ({ [generate()]: generate() })) },
8
+ { get: jest.fn(() => ({ [generate()]: generate() })) }
9
+ ]
10
+
11
+ exports.set = set
@@ -0,0 +1,12 @@
1
+ 'use strict'
2
+
3
+ const { EntitySet } = require('../../src/entities/set')
4
+ const fixtures = require('./set.fixtures')
5
+
6
+ it('should provide state', () => {
7
+ const set = new EntitySet(fixtures.set)
8
+ const state = set.get()
9
+ const expected = fixtures.set.map((entity) => entity.get.mock.results[0].value)
10
+
11
+ expect(state).toStrictEqual(expected)
12
+ })
@@ -0,0 +1,28 @@
1
+ 'use strict'
2
+
3
+ const { generate } = require('randomstring')
4
+
5
+ const definition = {
6
+ conditioned: true,
7
+ subjective: true
8
+ }
9
+
10
+ const bridge = {
11
+ condition: jest.fn(async (origin) => !origin.falsy),
12
+ payload: jest.fn(async () => ({ [generate()]: generate() }))
13
+ }
14
+
15
+ const binding = {
16
+ emit: jest.fn()
17
+ }
18
+
19
+ const event = {
20
+ origin: { [generate()]: generate() },
21
+ state: { [generate()]: generate() },
22
+ changeset: { [generate()]: generate() }
23
+ }
24
+
25
+ exports.bridge = bridge
26
+ exports.binding = binding
27
+ exports.definition = definition
28
+ exports.event = event
@@ -0,0 +1,106 @@
1
+ 'use strict'
2
+
3
+ const clone = require('clone-deep')
4
+
5
+ jest.mock('../src/connector')
6
+
7
+ const { Connector } = require('../src/connector')
8
+ const { Event } = require('../src/event')
9
+ const fixtures = require('./event.fixtures')
10
+
11
+ let event, emit
12
+
13
+ beforeEach(() => {
14
+ jest.clearAllMocks()
15
+
16
+ event = new Event(fixtures.definition, fixtures.binding, fixtures.bridge)
17
+ emit = () => event.emit(fixtures.event)
18
+ })
19
+
20
+ it('should depend on binding', () => {
21
+ expect(event).toBeInstanceOf(Connector)
22
+ expect(Connector.mock.instances[0].depends).toHaveBeenCalledWith(fixtures.binding)
23
+ })
24
+
25
+ it('should depend on bridge if provided', () => {
26
+ expect(Connector.mock.instances[0].depends).toHaveBeenCalledWith(fixtures.bridge)
27
+
28
+ event = new Event(fixtures.definition, fixtures.binding)
29
+ expect(Connector.mock.instances[1].depends).not.toHaveBeenCalledWith(fixtures.bridge)
30
+ })
31
+
32
+ describe('condition', () => {
33
+ describe('conditioned', () => {
34
+ it('should call condition', async () => {
35
+ await emit()
36
+
37
+ expect(fixtures.bridge.condition).toHaveBeenCalledWith(fixtures.event)
38
+ })
39
+
40
+ it('should emit if condition returns true', async () => {
41
+ await emit()
42
+
43
+ expect(fixtures.binding.emit).toHaveBeenCalledWith(await fixtures.bridge.payload.mock.results[0].value)
44
+ })
45
+
46
+ it('should not emit if condition returns false', async () => {
47
+ const origin = clone(fixtures.event.origin)
48
+
49
+ origin.falsy = true
50
+
51
+ await event.emit(origin, fixtures.event.changeset, fixtures.event.state)
52
+
53
+ expect(fixtures.binding.emit).not.toHaveBeenCalled()
54
+ })
55
+ })
56
+
57
+ describe('unconditioned', () => {
58
+ beforeEach(() => {
59
+ const definition = clone(fixtures.definition)
60
+
61
+ definition.conditioned = false
62
+
63
+ event = new Event(definition, fixtures.binding, fixtures.bridge)
64
+ })
65
+
66
+ it('should not call condition', async () => {
67
+ await event.emit(fixtures.event.origin, fixtures.event.changeset, fixtures.event.state)
68
+
69
+ expect(fixtures.bridge.condition).not.toHaveBeenCalledWith()
70
+ expect(fixtures.binding.emit).toHaveBeenCalledWith(await fixtures.bridge.payload.mock.results[0].value)
71
+ })
72
+ })
73
+ })
74
+
75
+ describe('payload', () => {
76
+ describe('subjective', () => {
77
+ it('should emit payload', async () => {
78
+ await emit()
79
+
80
+ expect(fixtures.binding.emit).toHaveBeenCalledWith(await fixtures.bridge.payload.mock.results[0].value)
81
+ })
82
+ })
83
+
84
+ describe('objective', () => {
85
+ beforeEach(() => {
86
+ const definition = clone(fixtures.definition)
87
+
88
+ definition.subjective = false
89
+
90
+ event = new Event(definition, fixtures.binding, fixtures.bridge)
91
+ emit = () => event.emit(fixtures.event)
92
+ })
93
+
94
+ it('should not call payload', async () => {
95
+ await emit()
96
+
97
+ expect(fixtures.bridge.payload).not.toHaveBeenCalled()
98
+ })
99
+
100
+ it('should return state as payload', async () => {
101
+ await emit()
102
+
103
+ expect(fixtures.binding.emit).toHaveBeenCalledWith(fixtures.event.state)
104
+ })
105
+ })
106
+ })
@@ -0,0 +1,34 @@
1
+ 'use strict'
2
+
3
+ const { Locator } = require('../src/locator')
4
+
5
+ const manifest = {
6
+ domain: 'foo',
7
+ name: 'bar',
8
+ entity: { schema: { foo: 'bar' } },
9
+ operations: { add: { query: false }, get: { output: null } }
10
+ }
11
+
12
+ const nameless = {
13
+ domain: 'foo',
14
+ entity: { schema: { foo: 'bar' } },
15
+ operations: [{ name: 'add' }, { name: 'get' }]
16
+ }
17
+
18
+ const env = process.env.TOA_ENV
19
+
20
+ beforeAll(() => {
21
+ delete process.env.TOA_ENV
22
+ })
23
+
24
+ afterAll(() => {
25
+ process.env.TOA_ENV = env
26
+ })
27
+
28
+ it('should provide host', () => {
29
+ expect(new Locator(manifest).host('db')).toBe('foo-db')
30
+ expect(new Locator(nameless).host('db')).toBe('foo-db')
31
+ expect(new Locator(nameless).host('DB')).toBe('foo-db')
32
+ expect(new Locator(manifest).host('db', 1)).toBe('foo-bar-db')
33
+ expect(new Locator(nameless).host('db', 1)).toBe('foo-db')
34
+ })
@@ -0,0 +1,100 @@
1
+ 'use strict'
2
+
3
+ const samples = {
4
+ simple: {
5
+ query: {
6
+ criteria: 'name==Eddie'
7
+ },
8
+ parsed: {
9
+ criteria: {
10
+ type: 'COMPARISON',
11
+ left: { type: 'SELECTOR', selector: 'name' },
12
+ operator: '==',
13
+ right: { type: 'VALUE', value: 'Eddie' }
14
+ }
15
+ },
16
+ properties: {
17
+ name: {
18
+ type: 'string'
19
+ }
20
+ }
21
+ },
22
+
23
+ extended: {
24
+ query: {
25
+ criteria: 'flag==true;volume>2.1'
26
+ },
27
+ parsed: {
28
+ criteria: {
29
+ type: 'LOGIC',
30
+ left: {
31
+ type: 'COMPARISON',
32
+ left: { type: 'SELECTOR', selector: 'flag' },
33
+ operator: '==',
34
+ right: { type: 'VALUE', value: true }
35
+ },
36
+ operator: ';',
37
+ right: {
38
+ type: 'COMPARISON',
39
+ left: { type: 'SELECTOR', selector: 'volume' },
40
+ operator: '>',
41
+ right: { type: 'VALUE', value: 2.1 }
42
+ }
43
+ }
44
+ },
45
+ properties: {
46
+ flag: {
47
+ type: 'boolean'
48
+ },
49
+ volume: {
50
+ type: 'number'
51
+ }
52
+ }
53
+ },
54
+
55
+ abc: {
56
+ properties: {
57
+ a: {
58
+ type: 'string'
59
+ },
60
+ b: {
61
+ type: 'string'
62
+ },
63
+ c: {
64
+ type: 'string'
65
+ }
66
+ }
67
+ },
68
+
69
+ id: {
70
+ properties: {
71
+ id: {
72
+ type: 'string'
73
+ },
74
+ name: {
75
+ type: 'string'
76
+ }
77
+ },
78
+ query: {
79
+ id: '123',
80
+ criteria: 'name==Eddie'
81
+ },
82
+ parsed: {
83
+ id: '123',
84
+ criteria: {
85
+ type: 'COMPARISON',
86
+ left: {
87
+ type: 'SELECTOR',
88
+ selector: 'name'
89
+ },
90
+ operator: '==',
91
+ right: {
92
+ type: 'VALUE',
93
+ value: 'Eddie'
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ exports.samples = samples
@@ -0,0 +1,86 @@
1
+ 'use strict'
2
+
3
+ const { Query } = require('../src/query')
4
+ const fixtures = require('./query.fixtures')
5
+
6
+ beforeEach(() => {
7
+ jest.clearAllMocks()
8
+ })
9
+
10
+ describe('criteria', () => {
11
+ it('should not throw if no criteria', () => {
12
+ const instance = new Query(fixtures.samples.simple.properties)
13
+ const query = instance.parse({})
14
+
15
+ expect(query.criteria).toBeUndefined()
16
+ })
17
+
18
+ it('should parse criteria', () => {
19
+ const instance = new Query(fixtures.samples.simple.properties)
20
+ const query = instance.parse(fixtures.samples.simple.query)
21
+
22
+ expect(query.criteria).toEqual(fixtures.samples.simple.parsed.criteria)
23
+ })
24
+
25
+ it('should parse criteria with type coercion', () => {
26
+ const instance = new Query(fixtures.samples.extended.properties)
27
+ const query = instance.parse(fixtures.samples.extended.query)
28
+
29
+ expect(query.criteria).toEqual(fixtures.samples.extended.parsed.criteria)
30
+ })
31
+
32
+ it('should throw on unknown properties', () => {
33
+ const instance = new Query(fixtures.samples.simple.properties)
34
+
35
+ expect(() => instance.parse({ criteria: 'lastname==Johnson' })).toThrow(/not defined/)
36
+ })
37
+
38
+ it('should parse id', () => {
39
+ const instance = new Query(fixtures.samples.id.properties)
40
+ const query = instance.parse({ ...fixtures.samples.id.query })
41
+
42
+ expect(query).toStrictEqual(fixtures.samples.id.parsed)
43
+ })
44
+ })
45
+
46
+ describe('options', () => {
47
+ const instance = new Query(fixtures.samples.abc.properties)
48
+
49
+ it('should not throw if no options', () => {
50
+ const query = instance.parse({})
51
+
52
+ expect(query.options).toBeUndefined()
53
+ })
54
+
55
+ describe('omit, limit', () => {
56
+ it('should pass', () => {
57
+ const input = { omit: 1, limit: 1 }
58
+ const query = instance.parse(input)
59
+
60
+ expect(query.options).toStrictEqual(input)
61
+ })
62
+ })
63
+
64
+ describe('sort', () => {
65
+ it('should set default values', () => {
66
+ const sort = ['a', 'b:desc', 'c']
67
+ const query = instance.parse({ sort })
68
+
69
+ expect(query.options.sort).toStrictEqual([['a', 'asc'], ['b', 'desc'], ['c', 'asc']])
70
+ })
71
+
72
+ it('should throw on unknown properties', () => {
73
+ const sort = ['d:asc']
74
+
75
+ expect(() => instance.parse({ sort })).toThrow(/not defined/)
76
+ })
77
+ })
78
+
79
+ describe('projection', () => {
80
+ it('should throw on unknown properties', () => {
81
+ const projection = ['a', 'b', 'c', 'd']
82
+
83
+ expect(() => instance.parse({ projection })).toThrow(/not defined/)
84
+ })
85
+ })
86
+ })
@@ -0,0 +1,22 @@
1
+ 'use strict'
2
+
3
+ const { generate } = require('randomstring')
4
+
5
+ const definition = {
6
+ transition: generate(),
7
+ conditioned: false,
8
+ adaptive: false
9
+ }
10
+
11
+ const local = {
12
+ invoke: jest.fn()
13
+ }
14
+
15
+ const bridge = {
16
+ condition: jest.fn((payload) => !(payload.reject === true)),
17
+ request: jest.fn(() => generate())
18
+ }
19
+
20
+ exports.definition = definition
21
+ exports.local = local
22
+ exports.bridge = bridge
@@ -0,0 +1,66 @@
1
+ 'use strict'
2
+
3
+ const clone = require('clone-deep')
4
+
5
+ jest.mock('../src/connector')
6
+
7
+ const { Connector } = require('../src/connector')
8
+
9
+ const { Receiver } = require('../src/receiver')
10
+ const fixtures = require('./receiver.fixtures')
11
+
12
+ let receiver, definition
13
+
14
+ beforeEach(() => {
15
+ definition = clone(fixtures.definition)
16
+ receiver = new Receiver(fixtures.definition, fixtures.local, fixtures.bridge)
17
+ })
18
+
19
+ it('should depend on local, bridge', () => {
20
+ expect(Connector.mock.instances[0].depends).toHaveBeenCalledWith(fixtures.local)
21
+ expect(Connector.mock.instances[0].depends).toHaveBeenCalledWith(fixtures.bridge)
22
+ })
23
+
24
+ it('should apply', async () => {
25
+ const payload = { foo: 'bar' }
26
+ await receiver.receive(payload)
27
+
28
+ expect(fixtures.local.invoke).toHaveBeenCalledWith(definition.transition, payload)
29
+ })
30
+
31
+ describe('conditioned', () => {
32
+ beforeEach(() => {
33
+ definition.conditioned = true
34
+ receiver = new Receiver(definition, fixtures.local, fixtures.bridge)
35
+ })
36
+
37
+ it('should test condition', async () => {
38
+ const payload = { foo: 'bar' }
39
+ await receiver.receive(payload)
40
+
41
+ expect(fixtures.bridge.condition).toHaveBeenCalledWith(payload)
42
+ expect(fixtures.local.invoke).toHaveBeenCalledWith(definition.transition, payload)
43
+ })
44
+
45
+ it('should not apply if condition is false', async () => {
46
+ const payload = { reject: true }
47
+ await receiver.receive(payload)
48
+
49
+ expect(fixtures.local.invoke).not.toHaveBeenCalled()
50
+ })
51
+ })
52
+
53
+ describe('adaptive', () => {
54
+ beforeEach(() => {
55
+ definition.adaptive = true
56
+ receiver = new Receiver(definition, fixtures.local, fixtures.bridge)
57
+ })
58
+
59
+ it('should apply', async () => {
60
+ const payload = { reject: true }
61
+ await receiver.receive(payload)
62
+
63
+ expect(fixtures.local.invoke)
64
+ .toHaveBeenCalledWith(definition.transition, fixtures.bridge.request.mock.results[0].value)
65
+ })
66
+ })
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const randomstring = require('randomstring')
4
+
5
+ const invocation = () => jest.fn(() => randomstring.generate())
6
+
7
+ const invocations = {
8
+ foo: {
9
+ invoke: invocation('foo')
10
+ },
11
+ bar: {
12
+ invoke: invocation('bar')
13
+ }
14
+ }
15
+
16
+ const locator = {}
17
+
18
+ exports.invocations = invocations
19
+ exports.locator = locator
@@ -0,0 +1,40 @@
1
+ 'use strict'
2
+
3
+ const { Runtime } = require('../src/runtime')
4
+ const { codes } = require('../src/exceptions')
5
+ const fixtures = require('./runtime.fixtures')
6
+
7
+ describe('Invocations', () => {
8
+ const name = ['foo', 'bar'][Math.floor(2 * Math.random())]
9
+ const invocation = fixtures.invocations[name]
10
+ const runtime = new Runtime(fixtures.locator, fixtures.invocations)
11
+
12
+ beforeEach(() => {
13
+ jest.clearAllMocks()
14
+ })
15
+
16
+ it('should invoke', async () => {
17
+ await runtime.invoke(name)
18
+
19
+ expect(invocation.invoke).toBeCalled()
20
+ })
21
+
22
+ it('should throw on unknown invocation name', async () => {
23
+ await expect(() => runtime.invoke('baz'))
24
+ .rejects.toMatchObject({ code: codes.NotImplemented })
25
+ })
26
+
27
+ it('should invoke input and query', async () => {
28
+ const input = { test: Math.random() }
29
+ const query = { test: Math.random() }
30
+ await runtime.invoke(name, { input, query })
31
+
32
+ expect(invocation.invoke).toBeCalledWith({ input, query })
33
+ })
34
+
35
+ it('should return io', async () => {
36
+ const io = await runtime.invoke(name)
37
+
38
+ expect(io).toBe(fixtures.invocations[name].invoke.mock.results[0].value)
39
+ })
40
+ })