@toa.io/userland 1.0.0-alpha.31 → 1.0.0-alpha.310

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 (59) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/example/components/echo/manifest.toa.yaml +15 -5
  3. package/example/components/echo/operations/get.js +1 -5
  4. package/example/components/echo/operations/resolve.js +1 -5
  5. package/example/components/echo/operations/signal.js +3 -7
  6. package/example/components/math.calculations/manifest.toa.yaml +19 -6
  7. package/example/components/math.calculations/operations/add.js +1 -5
  8. package/example/components/math.calculations/operations/increment.js +1 -5
  9. package/example/components/math.proxy/manifest.toa.yaml +8 -3
  10. package/example/components/math.proxy/operations/add.js +1 -5
  11. package/example/components/tea.pots/manifest.toa.yaml +29 -9
  12. package/example/components/tea.pots/operations/same.js +1 -5
  13. package/example/components/tea.pots/receivers/store.orders.created.js +1 -5
  14. package/example/components/web/manifest.toa.yaml +2 -4
  15. package/example/components/web/operations/get.js +3 -8
  16. package/example/context.toa.yaml +2 -7
  17. package/example/stage/call.test.js +17 -10
  18. package/example/stage/events.test.js +63 -16
  19. package/example/stage/invoke.test.js +12 -9
  20. package/package.json +18 -13
  21. package/stage/package.json +1 -0
  22. package/stage/src/component.js +3 -12
  23. package/stage/src/composition.js +3 -11
  24. package/stage/src/index.js +9 -18
  25. package/stage/src/manifest.js +2 -6
  26. package/stage/src/map.js +15 -0
  27. package/stage/src/quiescence.js +16 -0
  28. package/stage/src/remote.js +11 -8
  29. package/stage/src/service.js +11 -10
  30. package/stage/src/shutdown.js +16 -8
  31. package/stage/src/state.js +2 -4
  32. package/stage/src/workload.js +55 -0
  33. package/stage/test/boot.mock.js +10 -11
  34. package/stage/test/component.test.js +20 -10
  35. package/stage/test/composition.test.js +11 -20
  36. package/stage/test/manifest.test.js +15 -8
  37. package/stage/test/remote.test.js +14 -12
  38. package/stage/test/shutdown.test.js +26 -22
  39. package/stage/test/state.mock.js +5 -6
  40. package/stage/test/state.test.js +13 -12
  41. package/stage/types/index.d.ts +20 -9
  42. package/stage/types/state.d.ts +3 -4
  43. package/stage/src/binding/binding.js +0 -50
  44. package/stage/src/binding/consumer.js +0 -32
  45. package/stage/src/binding/emitter.js +0 -27
  46. package/stage/src/binding/factory.js +0 -49
  47. package/stage/src/binding/index.js +0 -10
  48. package/stage/src/binding/label.js +0 -12
  49. package/stage/src/binding/producer.js +0 -43
  50. package/stage/src/binding/receiver.js +0 -34
  51. package/stage/test/binding/binding.test.js +0 -15
  52. package/stage/test/binding/consumer.test.js +0 -52
  53. package/stage/test/binding/emitter.test.js +0 -78
  54. package/stage/test/binding/producer.fixtures.js +0 -10
  55. package/stage/test/binding/producer.test.js +0 -49
  56. package/stage/test/binding/receiver.fixtures.js +0 -7
  57. package/stage/test/binding/receiver.test.js +0 -54
  58. package/stage/test/binding.mock.js +0 -8
  59. package/stage/types/binding.d.ts +0 -20
package/CHANGELOG.md ADDED
@@ -0,0 +1,189 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [1.0.0-alpha.310](https://github.com/toa-io/toa/compare/v1.0.0-alpha.309...v1.0.0-alpha.310) (2026-09-16)
7
+
8
+ **Note:** Version bump only for package @toa.io/userland
9
+
10
+
11
+
12
+
13
+
14
+ # [1.0.0-alpha.309](https://github.com/toa-io/toa/compare/v1.0.0-alpha.308...v1.0.0-alpha.309) (2026-09-16)
15
+
16
+ **Note:** Version bump only for package @toa.io/userland
17
+
18
+
19
+
20
+
21
+
22
+ # [1.0.0-alpha.308](https://github.com/toa-io/toa/compare/v1.0.0-alpha.307...v1.0.0-alpha.308) (2026-09-15)
23
+
24
+ **Note:** Version bump only for package @toa.io/userland
25
+
26
+
27
+
28
+
29
+
30
+ # [1.0.0-alpha.307](https://github.com/toa-io/toa/compare/v1.0.0-alpha.306...v1.0.0-alpha.307) (2026-09-15)
31
+
32
+ **Note:** Version bump only for package @toa.io/userland
33
+
34
+
35
+
36
+
37
+
38
+ # [1.0.0-alpha.306](https://github.com/toa-io/toa/compare/v1.0.0-alpha.305...v1.0.0-alpha.306) (2026-09-14)
39
+
40
+ * feat(boot)!: a process can be halted and come back ([7196fa5](https://github.com/toa-io/toa/commit/7196fa51a9c882e84c3767a4fdd329fd2df319f5))
41
+
42
+ ### BREAKING CHANGES
43
+
44
+ * `Host` gains `gate` and `halt`, and `Factory.service` may answer a gate. An
45
+ extension that gates nothing keeps its connections through a halt.
46
+
47
+
48
+ # [1.0.0-alpha.305](https://github.com/toa-io/toa/compare/v1.0.0-alpha.304...v1.0.0-alpha.305) (2026-09-13)
49
+
50
+ **Note:** Version bump only for package @toa.io/userland
51
+
52
+
53
+
54
+
55
+
56
+ # [1.0.0-alpha.304](https://github.com/toa-io/toa/compare/v1.0.0-alpha.303...v1.0.0-alpha.304) (2026-09-13)
57
+
58
+ **Note:** Version bump only for package @toa.io/userland
59
+
60
+
61
+
62
+
63
+
64
+ # [1.0.0-alpha.303](https://github.com/toa-io/toa/compare/v1.0.0-alpha.302...v1.0.0-alpha.303) (2026-09-12)
65
+
66
+ **Note:** Version bump only for package @toa.io/userland
67
+
68
+
69
+
70
+
71
+
72
+ # [1.0.0-alpha.302](https://github.com/toa-io/toa/compare/v1.0.0-alpha.301...v1.0.0-alpha.302) (2026-09-11)
73
+
74
+ **Note:** Version bump only for package @toa.io/userland
75
+
76
+
77
+
78
+
79
+
80
+ # [1.0.0-alpha.301](https://github.com/toa-io/toa/compare/v1.0.0-alpha.300...v1.0.0-alpha.301) (2026-09-11)
81
+
82
+ **Note:** Version bump only for package @toa.io/userland
83
+
84
+
85
+
86
+
87
+
88
+ # [1.0.0-alpha.300](https://github.com/toa-io/toa/compare/v1.0.0-alpha.299...v1.0.0-alpha.300) (2026-09-11)
89
+
90
+ * feat(boot)!: a process is a thing, and an extension may keep something in one ([528d6cd](https://github.com/toa-io/toa/commit/528d6cdd307b45a6c30b6a184d7e06b3328cecf8))
91
+
92
+ ### BREAKING CHANGES
93
+
94
+ * a composition booted directly has no readiness probe. Readiness is
95
+ the process's, and a composition is not a process. `stage.workload` boots one where a
96
+ suite needs it.
97
+
98
+
99
+ # [1.0.0-alpha.299](https://github.com/toa-io/toa/compare/v1.0.0-alpha.298...v1.0.0-alpha.299) (2026-09-10)
100
+
101
+ **Note:** Version bump only for package @toa.io/userland
102
+
103
+
104
+
105
+
106
+
107
+ # [1.0.0-alpha.298](https://github.com/toa-io/toa/compare/v1.0.0-alpha.297...v1.0.0-alpha.298) (2026-09-08)
108
+
109
+ **Note:** Version bump only for package @toa.io/userland
110
+
111
+
112
+
113
+
114
+
115
+ # [1.0.0-alpha.297](https://github.com/toa-io/toa/compare/v1.0.0-alpha.296...v1.0.0-alpha.297) (2026-09-08)
116
+
117
+ **Note:** Version bump only for package @toa.io/userland
118
+
119
+
120
+
121
+
122
+
123
+ # [1.0.0-alpha.296](https://github.com/toa-io/toa/compare/v1.0.0-alpha.295...v1.0.0-alpha.296) (2026-09-08)
124
+
125
+ **Note:** Version bump only for package @toa.io/userland
126
+
127
+
128
+
129
+
130
+
131
+ # [1.0.0-alpha.295](https://github.com/toa-io/toa/compare/v1.0.0-alpha.294...v1.0.0-alpha.295) (2026-09-07)
132
+
133
+ **Note:** Version bump only for package @toa.io/userland
134
+
135
+
136
+
137
+
138
+
139
+ # [1.0.0-alpha.294](https://github.com/toa-io/toa/compare/v1.0.0-alpha.293...v1.0.0-alpha.294) (2026-09-07)
140
+
141
+ **Note:** Version bump only for package @toa.io/userland
142
+
143
+
144
+
145
+
146
+
147
+ # [1.0.0-alpha.293](https://github.com/toa-io/toa/compare/v1.0.0-alpha.292...v1.0.0-alpha.293) (2026-09-07)
148
+
149
+ **Note:** Version bump only for package @toa.io/userland
150
+
151
+
152
+
153
+
154
+
155
+ # [1.0.0-alpha.292](https://github.com/toa-io/toa/compare/v1.0.0-alpha.291...v1.0.0-alpha.292) (2026-09-07)
156
+
157
+ **Note:** Version bump only for package @toa.io/userland
158
+
159
+
160
+
161
+
162
+
163
+ # [1.0.0-alpha.291](https://github.com/toa-io/toa/compare/v1.0.0-alpha.290...v1.0.0-alpha.291) (2026-09-07)
164
+
165
+ **Note:** Version bump only for package @toa.io/userland
166
+
167
+
168
+
169
+
170
+
171
+ # [1.0.0-alpha.289](https://github.com/toa-io/toa/compare/v1.0.0-alpha.288...v1.0.0-alpha.289) (2026-09-07)
172
+
173
+ **Note:** Version bump only for package @toa.io/userland
174
+
175
+
176
+
177
+
178
+
179
+ # [1.0.0-alpha.288](https://github.com/toa-io/toa/compare/v1.0.0-alpha.287...v1.0.0-alpha.288) (2026-09-06)
180
+
181
+ **Note:** Version bump only for package @toa.io/userland
182
+
183
+
184
+
185
+
186
+
187
+ # [1.0.0-alpha.287](https://github.com/toa-io/toa/compare/v1.0.0-alpha.286...v1.0.0-alpha.287) (2026-09-06)
188
+
189
+ **Note:** Version bump only for package @toa.io/userland
@@ -2,14 +2,24 @@ name: echo
2
2
 
3
3
  operations:
4
4
  signal:
5
- output: string
5
+ output:
6
+ type: string
6
7
  get:
7
- output: string
8
+ output:
9
+ type: string
8
10
  resolve:
9
- input: string
10
- output: string
11
+ input:
12
+ type: string
13
+ output:
14
+ type: string
11
15
 
12
16
  configuration:
13
- signal: quack
17
+ schema:
18
+ type: object
19
+ properties:
20
+ signal:
21
+ type: string
22
+ defaults:
23
+ signal: quack
14
24
 
15
25
  state: ~
@@ -1,7 +1,3 @@
1
- 'use strict'
2
-
3
- async function computation (_, context) {
1
+ export async function computation(_, context) {
4
2
  return context.state.value
5
3
  }
6
-
7
- exports.computation = computation
@@ -1,7 +1,3 @@
1
- 'use strict'
2
-
3
- async function computation (key, context) {
1
+ export async function computation(key, context) {
4
2
  return context.state.values.get(key)
5
3
  }
6
-
7
- exports.computation = computation
@@ -1,15 +1,11 @@
1
- 'use strict'
2
-
3
- class Computation {
1
+ export class Computation {
4
2
  #context
5
3
 
6
- async mount (context) {
4
+ async mount(context) {
7
5
  this.#context = context
8
6
  }
9
7
 
10
- async execute () {
8
+ async execute() {
11
9
  return this.#context.configuration.signal
12
10
  }
13
11
  }
14
-
15
- exports.Computation = Computation
@@ -4,11 +4,24 @@ namespace: math
4
4
  operations:
5
5
  add:
6
6
  input:
7
- a: number
8
- b: number
9
- output: number
7
+ properties:
8
+ a:
9
+ type: number
10
+ b:
11
+ type: number
12
+ type: object
13
+ output:
14
+ type: number
10
15
  increment:
11
16
  input:
12
- value: number
13
- times: 1
14
- output: number
17
+ properties:
18
+ value:
19
+ type: number
20
+ times:
21
+ type: number
22
+ type: object
23
+ required:
24
+ - value
25
+ - times
26
+ output:
27
+ type: number
@@ -1,7 +1,3 @@
1
- 'use strict'
2
-
3
- async function computation (input) {
1
+ export async function computation(input) {
4
2
  return input.a + input.b
5
3
  }
6
-
7
- exports.computation = computation
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- async function computation (input, context) {
1
+ export async function computation(input, context) {
4
2
  let value = input.value
5
3
 
6
4
  for (let i = 0; i < input.times; i++) {
@@ -9,5 +7,3 @@ async function computation (input, context) {
9
7
 
10
8
  return value
11
9
  }
12
-
13
- exports.computation = computation
@@ -4,6 +4,11 @@ namespace: math
4
4
  operations:
5
5
  add:
6
6
  input:
7
- a: number
8
- b: number
9
- output: number
7
+ properties:
8
+ a:
9
+ type: number
10
+ b:
11
+ type: number
12
+ type: object
13
+ output:
14
+ type: number
@@ -1,10 +1,6 @@
1
- 'use strict'
2
-
3
- async function computation (input, context) {
1
+ export async function computation(input, context) {
4
2
  const request = { input }
5
3
 
6
4
  // noinspection JSUnresolvedVariable
7
5
  return context.remote.math.calculations.add(request)
8
6
  }
9
-
10
- exports.computation = computation
@@ -3,21 +3,35 @@ namespace: tea
3
3
 
4
4
  entity:
5
5
  storage: mongodb
6
- schema:
7
- material*: [ glass, ceramic, steel ]
8
- volume: number
6
+ properties:
7
+ volume: &volume
8
+ type: number
9
+ booked: &booked
10
+ type: boolean
11
+ material: &material
12
+ type: string
13
+ enum:
14
+ - glass
15
+ - ceramic
16
+ - steel
17
+ required:
18
+ - material
19
+ blank:
9
20
  booked: false
10
21
 
11
22
  operations:
12
23
  transit:
13
24
  concurrency: none
14
25
  input:
15
- material: .
16
- volume: .
17
- booked: .
26
+ properties:
27
+ material: *material
28
+ volume: *volume
29
+ booked: *booked
30
+ type: object
18
31
  same:
19
- input: .material
20
- output: array
32
+ input: *material
33
+ output:
34
+ type: array
21
35
 
22
36
  receivers:
23
37
  store.orders.created:
@@ -25,4 +39,10 @@ receivers:
25
39
  binding: amqp # avoid discovery
26
40
 
27
41
  configuration:
28
- step: 0.5
42
+ schema:
43
+ type: object
44
+ properties:
45
+ step:
46
+ type: number
47
+ defaults:
48
+ step: 0.5
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- async function computation (input, context) {
1
+ export async function computation(input, context) {
4
2
  const criteria = `material==${input}`
5
3
  const query = { criteria, limit }
6
4
 
@@ -9,5 +7,3 @@ async function computation (input, context) {
9
7
  }
10
8
 
11
9
  const limit = 10
12
-
13
- exports.computation = computation
@@ -1,8 +1,4 @@
1
- 'use strict'
2
-
3
- const request = async (payload) => ({
1
+ export const request = async (payload) => ({
4
2
  input: { booked: true },
5
3
  query: { id: payload.pot }
6
4
  })
7
-
8
- exports.request = request
@@ -2,7 +2,5 @@ name: web
2
2
 
3
3
  operations:
4
4
  get:
5
- output: object
6
-
7
- origins:
8
- dev: http://api.example.com
5
+ output:
6
+ type: object
@@ -1,15 +1,10 @@
1
- 'use strict'
2
-
3
- async function computation (_, context) {
4
- const response = await context.http.dev.path.to.resource.get()
1
+ export async function computation(_, context) {
2
+ const response = await context.fetch('http://api.example.com/path/to/resource')
5
3
  const type = response.headers.get('content-type')
6
4
 
7
- if (type !== 'application/json')
8
- return ERR_UNSUPPORTED_MEDIA_TYPE
5
+ if (type !== 'application/json') return ERR_UNSUPPORTED_MEDIA_TYPE
9
6
 
10
7
  return await response.json()
11
8
  }
12
9
 
13
10
  const ERR_UNSUPPORTED_MEDIA_TYPE = new Error('UNSUPPORTED_MEDIA_TYPE')
14
-
15
- exports.computation = computation
@@ -1,10 +1,5 @@
1
1
  name: examples
2
- packages: components/*
3
2
  registry: example
4
3
 
5
- amqp: amqp://localhost
6
- mongodb: mongodb://localhost
7
-
8
- origins:
9
- default.web:
10
- dev: http://localhost
4
+ amqp: amqp://localhost:31010
5
+ mongodb: mongodb://localhost:31020
@@ -1,16 +1,21 @@
1
- 'use strict'
1
+ import { it, before, after } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { resolve } = require('node:path')
4
- const { exceptions: { RequestContractException } } = require('@toa.io/core')
5
- const stage = require('@toa.io/userland/stage')
4
+ import { resolve } from 'node:path'
5
+ import { exceptions } from '@toa.io/core'
6
+ import * as stage from '@toa.io/userland/stage'
6
7
 
7
- const root = resolve(__dirname, '../components')
8
+ const { RequestContractException } = exceptions
9
+
10
+ const root = resolve(import.meta.dirname, '../components')
8
11
 
9
12
  let echo
10
13
  let math
11
14
 
12
- beforeAll(async () => {
15
+ before(async () => {
13
16
  process.env.TOA_DEV = '1'
17
+ process.env.TOA_CONFIGURATION_DEFAULT_ECHO = '{}'
18
+ process.env.TOA_CONFIGURATION_TEA_POTS = '{}'
14
19
 
15
20
  const paths = ['echo', 'math.calculations'].map((rel) => resolve(root, rel))
16
21
 
@@ -20,7 +25,7 @@ beforeAll(async () => {
20
25
  math = await stage.remote('math.calculations')
21
26
  })
22
27
 
23
- afterAll(async () => {
28
+ after(async () => {
24
29
  await stage.shutdown()
25
30
 
26
31
  delete process.env.TOA_DEV
@@ -29,13 +34,15 @@ afterAll(async () => {
29
34
  it('should call endpoint', async () => {
30
35
  const reply = await echo.invoke('signal', {})
31
36
 
32
- expect(reply).toStrictEqual('quack')
37
+ assert.deepStrictEqual(reply, 'quack')
33
38
  })
34
39
 
35
40
  it('should throw on invalid input', async () => {
36
41
  const a = 'not a number'
37
42
  const b = 'neither'
38
43
 
39
- await expect(math.invoke('add', { input: { a, b } }))
40
- .rejects.toBeInstanceOf(RequestContractException)
44
+ await assert.rejects(math.invoke('add', { input: { a, b } }), (error) => {
45
+ assert.ok(error instanceof RequestContractException)
46
+ return true
47
+ })
41
48
  })
@@ -1,51 +1,98 @@
1
- 'use strict'
1
+ import { it, before, after } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { resolve } = require('node:path')
4
- const stage = require('@toa.io/userland/stage')
4
+ import { resolve } from 'node:path'
5
+ import * as boot from '@toa.io/boot'
6
+ import { Connector, Locator } from '@toa.io/core'
7
+ import { timeout } from '@toa.io/generic'
8
+ import * as stage from '@toa.io/userland/stage'
5
9
 
6
- const binding = stage.binding.binding
7
- const root = resolve(__dirname, '../components')
10
+ const root = resolve(import.meta.dirname, '../components')
8
11
 
9
12
  let remote
13
+ let emitter
14
+ let consumer
10
15
 
11
- beforeAll(async () => {
16
+ before(async () => {
12
17
  process.env.TOA_DEV = '1'
18
+ process.env.TOA_CONFIGURATION_TEA_POTS = '{}'
19
+
20
+ // the outbox pumps on a tick; at the default five seconds a test would end before it ran
21
+ process.env.TOA_OUTBOX_INTERVAL = '100'
13
22
 
14
23
  const path = resolve(root, 'tea.pots')
15
24
 
16
25
  await stage.composition([path])
17
26
 
18
27
  remote = await stage.remote('tea.pots')
28
+
29
+ // what `store.orders` would emit, sent the way it would send it
30
+ emitter = await boot.bindings.emit(AMQP, new Locator('orders', 'store'), 'created')
31
+
32
+ await emitter.connect()
19
33
  })
20
34
 
21
- afterAll(async () => {
35
+ after(async () => {
36
+ await consumer?.disconnect()
37
+ await emitter.disconnect()
22
38
  await stage.shutdown()
23
39
 
24
40
  delete process.env.TOA_DEV
41
+ delete process.env.TOA_CONFIGURATION_TEA_POTS
42
+ delete process.env.TOA_OUTBOX_INTERVAL
25
43
  })
26
44
 
27
45
  it('should receive event', async () => {
28
46
  const created = await remote.invoke('transit', { input: { material: 'glass' } })
29
47
  const id = created.id
30
- const payload = { pot: id }
31
- const message = { payload }
32
48
  const request = { query: { id } }
33
49
 
34
- await binding.emit('store.orders.created', message)
50
+ await emitter.emit({ payload: { pot: id } })
51
+
52
+ // the receiver books the pot on delivery, which is asynchronous
53
+ const deadline = Date.now() + 5000
35
54
 
36
- const reply = await remote.invoke('observe', request)
55
+ let reply
37
56
 
38
- expect(reply.booked).toStrictEqual(true)
57
+ do {
58
+ await timeout(50)
59
+
60
+ reply = await remote.invoke('observe', request)
61
+ } while (reply.booked !== true && Date.now() < deadline)
62
+
63
+ assert.deepStrictEqual(reply.booked, true)
39
64
  })
40
65
 
41
66
  it('should emit event', async () => {
42
- expect.assertions(1)
43
-
44
67
  const material = 'steel'
45
68
 
46
- await binding.subscribe('tea.pots.created', (pot) => {
47
- expect(pot.payload.material).toStrictEqual(material)
69
+ const received = new Promise((resolve) => {
70
+ consumer = boot.receive('tea.pots.created', new Subscriber(resolve))
48
71
  })
49
72
 
73
+ consumer = await consumer
74
+
75
+ await consumer.connect()
50
76
  await remote.invoke('transit', { input: { material } })
77
+
78
+ const payload = await received
79
+
80
+ assert.deepStrictEqual(payload.material, material)
51
81
  })
82
+
83
+ /** What the event consumer hands deliveries to. */
84
+ class Subscriber extends Connector {
85
+ #handler
86
+
87
+ constructor(handler) {
88
+ super()
89
+
90
+ this.#handler = handler
91
+ }
92
+
93
+ async receive(message) {
94
+ this.#handler(message.payload)
95
+ }
96
+ }
97
+
98
+ const AMQP = '@toa.io/bindings.amqp'
@@ -1,22 +1,25 @@
1
- 'use strict'
1
+ import { it, before, after } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { resolve } = require('node:path')
4
- const stage = require('@toa.io/userland/stage')
4
+ import { resolve } from 'node:path'
5
+ import * as stage from '@toa.io/userland/stage'
5
6
 
6
- const root = resolve(__dirname, '../components')
7
+ const root = resolve(import.meta.dirname, '../components')
7
8
 
8
- /** @type {toa.core.Component} */
9
+ /** @type {import('@toa.io/core').Component} */
9
10
  let component
10
11
 
11
- beforeAll(async () => {
12
+ before(async () => {
12
13
  process.env.TOA_DEV = '1'
14
+ process.env.TOA_CONFIGURATION_DEFAULT_ECHO = '{}'
15
+ process.env.TOA_CONFIGURATION_TEA_POTS = '{}'
13
16
 
14
17
  const path = resolve(root, 'math.calculations')
15
18
 
16
19
  component = await stage.component(path)
17
20
  })
18
21
 
19
- afterAll(async () => {
22
+ after(async () => {
20
23
  await stage.shutdown()
21
24
 
22
25
  delete process.env.TOA_DEV
@@ -28,6 +31,6 @@ it('should invoke', async () => {
28
31
 
29
32
  const reply = await component.invoke('add', { input: { a, b } })
30
33
 
31
- expect(reply.exception).toBeUndefined()
32
- expect(reply.output).toStrictEqual(a + b)
34
+ assert.strictEqual(reply.exception, undefined)
35
+ assert.deepStrictEqual(reply.output, a + b)
33
36
  })