comq 0.10.1 → 0.10.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/.github/workflows/release.yaml +1 -1
- package/features/steps/broker.js +3 -5
- package/features/steps/events.js +2 -1
- package/features/steps/rpc.js +1 -1
- package/lerna.json +1 -1
- package/package.json +10 -9
- package/readme.md +0 -9
- package/source/.io/ReplyStream.js +8 -8
- package/source/channel.js +11 -10
- package/source/connection.js +7 -14
- package/source/io.js +7 -6
- package/source/shards/channel.js +6 -6
- package/features/steps/.test/backpressure.test.js +0 -79
- package/features/steps/.test/broker.test.js +0 -101
- package/features/steps/.test/command.mock.js +0 -5
- package/features/steps/.test/comq.mock.js +0 -10
- package/features/steps/.test/connection.test.js +0 -285
- package/features/steps/.test/context.mock.js +0 -14
- package/features/steps/.test/context.test.js +0 -74
- package/features/steps/.test/events.test.js +0 -279
- package/features/steps/.test/io.mock.js +0 -14
- package/features/steps/.test/poison.test.js +0 -40
- package/features/steps/.test/rpc.test.js +0 -261
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { AssertionError } = require('node:assert')
|
|
4
|
-
const { generate } = require('randomstring')
|
|
5
|
-
const { random, promex } = require('@toa.io/generic')
|
|
6
|
-
const tomato = require('@toa.io/tomato')
|
|
7
|
-
const { comq } = require('./comq.mock')
|
|
8
|
-
const world = require('./context.mock')
|
|
9
|
-
const mock = { tomato, comq }
|
|
10
|
-
|
|
11
|
-
jest.mock('@cucumber/cucumber', () => mock.tomato)
|
|
12
|
-
jest.mock('comq', () => mock.comq)
|
|
13
|
-
|
|
14
|
-
require('../connection')
|
|
15
|
-
|
|
16
|
-
/** @type {jest.MockedObject<comq.features.Context>} */
|
|
17
|
-
let context
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
jest.clearAllMocks()
|
|
21
|
-
|
|
22
|
-
context = world.context()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
describe('Given an active connection to the broker', () => {
|
|
26
|
-
const step = tomato.steps.Gi('an active connection to the broker')
|
|
27
|
-
|
|
28
|
-
it('should be', async () => undefined)
|
|
29
|
-
|
|
30
|
-
beforeEach(async () => {
|
|
31
|
-
await step.call(context)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('should connect', async () => {
|
|
35
|
-
expect(context.connect).toHaveBeenCalled()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('should store promise', async () => {
|
|
39
|
-
expect(context.connecting).toBeInstanceOf(Promise)
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
describe('Given an active sharded connection', () => {
|
|
44
|
-
const step = tomato.steps.Gi('an active sharded connection')
|
|
45
|
-
|
|
46
|
-
it('should be', async () => undefined)
|
|
47
|
-
|
|
48
|
-
beforeEach(async () => {
|
|
49
|
-
await step.call(context)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('should set sharded to true', async () => {
|
|
53
|
-
expect(context.sharded).toStrictEqual(true)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('should connect', async () => {
|
|
57
|
-
expect(context.connect).toHaveBeenCalled()
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('should store promise', async () => {
|
|
61
|
-
expect(context.connecting).toStrictEqual(expect.any(Promise))
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
describe('When I attempt to connect to the broker for {number} second(s)', () => {
|
|
66
|
-
const step = tomato.steps.Wh('I attempt to connect to the broker for {number} second(s)')
|
|
67
|
-
|
|
68
|
-
it('should be', async () => undefined)
|
|
69
|
-
|
|
70
|
-
const interval = (random(2) + 1) / 10
|
|
71
|
-
|
|
72
|
-
describe('broker available', () => {
|
|
73
|
-
beforeEach(async () => {
|
|
74
|
-
await step.call(context, interval)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('should call connect', async () => {
|
|
78
|
-
expect(context.connect).toHaveBeenCalled()
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
describe('broker unavailable', () => {
|
|
83
|
-
/** @type {toa.generic.Promex} */
|
|
84
|
-
let connection
|
|
85
|
-
|
|
86
|
-
beforeEach(() => {
|
|
87
|
-
connection = promex()
|
|
88
|
-
|
|
89
|
-
context.connect.mockImplementationOnce(async () => connection)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('should quit after given interval', async () => {
|
|
93
|
-
const start = new Date().getTime()
|
|
94
|
-
|
|
95
|
-
await step.call(context, interval)
|
|
96
|
-
|
|
97
|
-
const end = new Date().getTime()
|
|
98
|
-
const inaccuracy = 1 // setTimeout is inaccurate
|
|
99
|
-
|
|
100
|
-
expect(end - start + inaccuracy).toBeGreaterThanOrEqual(interval * 1000)
|
|
101
|
-
})
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
describe('exceptions', () => {
|
|
105
|
-
it('should catch exception', async () => {
|
|
106
|
-
const exception = new Error(generate())
|
|
107
|
-
|
|
108
|
-
context.connect.mockImplementationOnce(async () => { throw exception })
|
|
109
|
-
|
|
110
|
-
await step.call(context, interval)
|
|
111
|
-
|
|
112
|
-
expect(context.exception).toStrictEqual(exception)
|
|
113
|
-
})
|
|
114
|
-
})
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
describe('When I attempt to connect to the broker', () => {
|
|
118
|
-
const step = tomato.steps.Wh('I attempt to connect to the broker')
|
|
119
|
-
|
|
120
|
-
it('should be', async () => undefined)
|
|
121
|
-
|
|
122
|
-
it('should connect', async () => {
|
|
123
|
-
await step.call(context)
|
|
124
|
-
|
|
125
|
-
expect(context.connect).toHaveBeenCalled()
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
it('should store exception', async () => {
|
|
129
|
-
const exception = new Error(generate())
|
|
130
|
-
|
|
131
|
-
context.connect.mockImplementationOnce(async () => { throw exception })
|
|
132
|
-
|
|
133
|
-
await step.call(context)
|
|
134
|
-
|
|
135
|
-
expect(context.exception).toStrictEqual(exception)
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
describe('When I attempt to connect to the broker as {string} with password {string}', () => {
|
|
140
|
-
const step = tomato.steps.Wh('I attempt to connect to the broker as {string} with password {string}')
|
|
141
|
-
|
|
142
|
-
it('should be', async () => undefined)
|
|
143
|
-
|
|
144
|
-
const user = generate()
|
|
145
|
-
const password = generate()
|
|
146
|
-
|
|
147
|
-
it('should connect with credentials', async () => {
|
|
148
|
-
await step.call(context, user, password)
|
|
149
|
-
|
|
150
|
-
expect(context.connect).toHaveBeenCalledWith(user, password)
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
describe('When I attempt to establish sharded connection', () => {
|
|
155
|
-
const step = tomato.steps.Wh('I attempt to establish sharded connection')
|
|
156
|
-
|
|
157
|
-
it('should be', async () => undefined)
|
|
158
|
-
|
|
159
|
-
it('should set context.sharded to true', async () => {
|
|
160
|
-
await step.call(context)
|
|
161
|
-
|
|
162
|
-
expect(context.sharded).toStrictEqual(true)
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
it('should connect', async () => {
|
|
166
|
-
await step.call(context)
|
|
167
|
-
|
|
168
|
-
expect(context.connect).toHaveBeenCalled()
|
|
169
|
-
})
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
describe('When I attempt to establish a sharded connection as {string} with password {string}', () => {
|
|
173
|
-
const step = tomato.steps.Wh('I attempt to establish a sharded connection as {string} with password {string}')
|
|
174
|
-
|
|
175
|
-
it('should be', async () => undefined)
|
|
176
|
-
|
|
177
|
-
const user = generate()
|
|
178
|
-
const password = generate()
|
|
179
|
-
|
|
180
|
-
it('should connect with credentials', async () => {
|
|
181
|
-
await step.call(context, user, password)
|
|
182
|
-
|
|
183
|
-
expect(context.sharded).toStrictEqual(true)
|
|
184
|
-
expect(context.connect).toHaveBeenCalledWith(user, password)
|
|
185
|
-
})
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
describe.each([['', true], [' not', false]])('Then the connection is%s established',
|
|
189
|
-
(not, connected) => {
|
|
190
|
-
const step = tomato.steps.Th(`the connection is${not} established`)
|
|
191
|
-
|
|
192
|
-
it('should be', async () => undefined)
|
|
193
|
-
|
|
194
|
-
it(`should fail if is${connected ? 'n\'t' : ''} connected`, async () => {
|
|
195
|
-
context.connected = !connected
|
|
196
|
-
|
|
197
|
-
await expect(step.call(context)).rejects.toThrow(AssertionError)
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
it(`should pass if is${connected ? '' : 'n\'t'} connected`, async () => {
|
|
201
|
-
context.connected = connected
|
|
202
|
-
|
|
203
|
-
await expect(step.call(context)).resolves.not.toThrow()
|
|
204
|
-
})
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
describe('Then no exceptions are thrown', () => {
|
|
208
|
-
const step = tomato.steps.Th('no exceptions are thrown')
|
|
209
|
-
|
|
210
|
-
it('should be', async () => undefined)
|
|
211
|
-
|
|
212
|
-
it(`should fail if exception is defined`, async () => {
|
|
213
|
-
context.exception = new Error()
|
|
214
|
-
|
|
215
|
-
expect(() => step.call(context)).toThrow(AssertionError)
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
it(`should pass if exception isn't defined`, async () => {
|
|
219
|
-
expect(() => step.call(context)).not.toThrow()
|
|
220
|
-
})
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
describe('Then an exception is thrown: {string}', () => {
|
|
224
|
-
const step = tomato.steps.Th('an exception is thrown: {string}')
|
|
225
|
-
|
|
226
|
-
const message = generate()
|
|
227
|
-
|
|
228
|
-
it('should be', async () => undefined)
|
|
229
|
-
|
|
230
|
-
it(`should pass if exception is defined and message matches`, async () => {
|
|
231
|
-
context.exception = new Error(message)
|
|
232
|
-
|
|
233
|
-
const slice = message.slice(2, 6)
|
|
234
|
-
|
|
235
|
-
expect(() => step.call(context, slice)).not.toThrow()
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
it(`should fail if exception isn't defined`, async () => {
|
|
239
|
-
expect(() => step.call(context)).toThrow(AssertionError)
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
it('should fail if message doesn\'t match', async () => {
|
|
243
|
-
context.exception = new Error(generate())
|
|
244
|
-
|
|
245
|
-
expect(() => step.call(context)).toThrow(AssertionError)
|
|
246
|
-
})
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
describe('Given the connection has started sealing', () => {
|
|
250
|
-
const step = tomato.steps.Gi('the connection has started sealing')
|
|
251
|
-
|
|
252
|
-
it('should be', async () => undefined)
|
|
253
|
-
|
|
254
|
-
it('should seal the connection', async () => {
|
|
255
|
-
context.io = /** @type {jest.MockedObject<comq.IO>} */ {
|
|
256
|
-
seal: jest.fn(async () => undefined)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
await step.call(context)
|
|
260
|
-
|
|
261
|
-
expect(context.io.seal).toHaveBeenCalled()
|
|
262
|
-
expect(context.sealing).toBeInstanceOf(Promise)
|
|
263
|
-
})
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
describe('Then the connection is sealed', () => {
|
|
267
|
-
const step = tomato.steps.Th('the connection is sealed')
|
|
268
|
-
|
|
269
|
-
it('should be', async () => undefined)
|
|
270
|
-
|
|
271
|
-
it('should await for sealing', async () => {
|
|
272
|
-
context.sealing = promex()
|
|
273
|
-
|
|
274
|
-
let sealed = false
|
|
275
|
-
|
|
276
|
-
setImmediate(() => {
|
|
277
|
-
context.sealing.resolve()
|
|
278
|
-
sealed = true
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
await step.call(context)
|
|
282
|
-
|
|
283
|
-
expect(sealed).toStrictEqual(true)
|
|
284
|
-
})
|
|
285
|
-
})
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { comq } = require('./comq.mock')
|
|
4
|
-
|
|
5
|
-
const connect = jest.fn(() => comq.connect())
|
|
6
|
-
const disconnect = jest.fn(async () => undefined)
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @return {jest.MockedObject<comq.features.Context>}
|
|
10
|
-
*/
|
|
11
|
-
exports.context = () => (/** @type {jest.MockedObject<comq.features.Context>} */{
|
|
12
|
-
connect,
|
|
13
|
-
disconnect
|
|
14
|
-
})
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { generate } = require('randomstring')
|
|
4
|
-
const { comq } = require('./comq.mock')
|
|
5
|
-
const mock = { comq }
|
|
6
|
-
|
|
7
|
-
jest.mock('comq', () => mock.comq)
|
|
8
|
-
|
|
9
|
-
const { Context } = require('../context')
|
|
10
|
-
|
|
11
|
-
it('should be', async () => {
|
|
12
|
-
expect(Context).toBeDefined()
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
/** @type {comq.features.Context} */
|
|
16
|
-
let context
|
|
17
|
-
|
|
18
|
-
beforeAll(async () => {
|
|
19
|
-
const _ = {}
|
|
20
|
-
|
|
21
|
-
// noinspection JSValidateTypes
|
|
22
|
-
context = new Context(_)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
describe.each([false, true])('connect (shards: %s)', (sharded) => {
|
|
26
|
-
it('should be', async () => {
|
|
27
|
-
expect(context.connect).toBeDefined()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
/** @type {jest.MockedObject<comq.IO>} */
|
|
31
|
-
let io
|
|
32
|
-
|
|
33
|
-
beforeEach(async () => {
|
|
34
|
-
context.sharded = sharded
|
|
35
|
-
|
|
36
|
-
await context.connect()
|
|
37
|
-
|
|
38
|
-
io = await comq.connect.mock.results[0].value
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('should connect', async () => {
|
|
42
|
-
const shards = ['amqp://developer:secret@localhost:5673', 'amqp://developer:secret@localhost:5674']
|
|
43
|
-
|
|
44
|
-
if (sharded) expect(comq.connect).toHaveBeenCalledWith(...shards)
|
|
45
|
-
else expect(comq.connect).toHaveBeenCalledWith(shards[0])
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('should connect with credentials', async () => {
|
|
49
|
-
const user = generate()
|
|
50
|
-
const password = generate()
|
|
51
|
-
|
|
52
|
-
await context.connect(user, password)
|
|
53
|
-
|
|
54
|
-
const shards = [`amqp://${user}:${password}@localhost:5673`, `amqp://${user}:${password}@localhost:5674`]
|
|
55
|
-
|
|
56
|
-
if (sharded) expect(comq.connect).toHaveBeenCalledWith(...shards)
|
|
57
|
-
else expect(comq.connect).toHaveBeenCalledWith(shards[0])
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it.each(['open', 'close', 'flow', 'discard'])('should store %s event',
|
|
61
|
-
/**
|
|
62
|
-
* @param {comq.diagnostics.Event} event
|
|
63
|
-
*/
|
|
64
|
-
async (event) => {
|
|
65
|
-
expect(io.diagnose).toHaveBeenCalledWith(event, expect.any(Function))
|
|
66
|
-
expect(context.events[event]).not.toStrictEqual(true)
|
|
67
|
-
|
|
68
|
-
const listener = io.diagnose.mock.calls.find((call) => call[0] === event)[1]
|
|
69
|
-
|
|
70
|
-
listener()
|
|
71
|
-
|
|
72
|
-
expect(context.events[event]).toStrictEqual(true)
|
|
73
|
-
})
|
|
74
|
-
})
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { AssertionError } = require('node:assert')
|
|
4
|
-
const { randomBytes } = require('node:crypto')
|
|
5
|
-
const { generate } = require('randomstring')
|
|
6
|
-
const { promex, timeout, random } = require('@toa.io/generic')
|
|
7
|
-
const tomato = require('@toa.io/tomato')
|
|
8
|
-
const { dump } = require('@toa.io/yaml')
|
|
9
|
-
const { io } = require('./io.mock')
|
|
10
|
-
const mock = { tomato }
|
|
11
|
-
|
|
12
|
-
jest.mock('@cucumber/cucumber', () => mock.tomato)
|
|
13
|
-
|
|
14
|
-
require('../events')
|
|
15
|
-
|
|
16
|
-
/** @type {comq.features.Context} */
|
|
17
|
-
let context
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
jest.clearAllMocks()
|
|
21
|
-
|
|
22
|
-
context = /** @type {comq.features.Context} */ { io }
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
describe('Given (that ){token} is consuming events from the {token} exchange', () => {
|
|
26
|
-
const step = tomato.steps.Gi('(that ){token} is consuming events from the {token} exchange')
|
|
27
|
-
|
|
28
|
-
it('should be', async () => undefined)
|
|
29
|
-
|
|
30
|
-
const exchange = generate()
|
|
31
|
-
const group = generate()
|
|
32
|
-
|
|
33
|
-
let consumer
|
|
34
|
-
|
|
35
|
-
beforeEach(async () => {
|
|
36
|
-
await step.call(context, group, exchange)
|
|
37
|
-
|
|
38
|
-
consumer = io.consume.mock.calls[0]?.[2]
|
|
39
|
-
|
|
40
|
-
expect(consumer).toBeInstanceOf(Function)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
it('should consume', async () => {
|
|
44
|
-
expect(io.consume).toHaveBeenCalledTimes(1)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('should store event in context', async () => {
|
|
48
|
-
const payload = generate()
|
|
49
|
-
|
|
50
|
-
await consumer(payload)
|
|
51
|
-
|
|
52
|
-
expect(context.consumed[group]).toStrictEqual(expect.objectContaining({ payload }))
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should store event properties', async () => {
|
|
56
|
-
const payload = generate()
|
|
57
|
-
const properties = generate()
|
|
58
|
-
|
|
59
|
-
await consumer(payload, properties)
|
|
60
|
-
|
|
61
|
-
expect(context.consumed[group]).toStrictEqual({ payload, properties })
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
describe('Given {token} consuming events from the {token} exchange is expected', () => {
|
|
66
|
-
tomato.steps.Gi('{token} consuming events from the {token} exchange is expected')
|
|
67
|
-
|
|
68
|
-
it('should be', async () => undefined)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
describe('Given (that )events are exclusively consumed from the {token} exchange', () => {
|
|
72
|
-
tomato.steps.Gi('(that )events are exclusively consumed from the {token} exchange')
|
|
73
|
-
|
|
74
|
-
it('should be', async () => undefined)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
describe('When an event is emitted to the {token} exchange', () => {
|
|
78
|
-
const step = tomato.steps.Wh('an event is emitted to the {token} exchange')
|
|
79
|
-
|
|
80
|
-
it('should be', async () => undefined)
|
|
81
|
-
|
|
82
|
-
const exchange = generate()
|
|
83
|
-
|
|
84
|
-
beforeEach(async () => {
|
|
85
|
-
await step.call(context, exchange)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('should store event', async () => {
|
|
89
|
-
expect(context.published).toBeDefined()
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('should emit event', async () => {
|
|
93
|
-
expect(io.emit.mock.calls[0][0]).toStrictEqual(exchange)
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('should wait for context.expected', async () => {
|
|
97
|
-
jest.clearAllMocks()
|
|
98
|
-
|
|
99
|
-
context.consumptionPromise = promex()
|
|
100
|
-
|
|
101
|
-
let resolved = false
|
|
102
|
-
|
|
103
|
-
setImmediate(() => {
|
|
104
|
-
expect(io.emit).not.toHaveBeenCalled()
|
|
105
|
-
|
|
106
|
-
resolved = true
|
|
107
|
-
context.consumptionPromise.resolve()
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
await step.call(context, exchange)
|
|
111
|
-
|
|
112
|
-
expect(io.emit).toHaveBeenCalled()
|
|
113
|
-
expect(resolved).toStrictEqual(true)
|
|
114
|
-
})
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
describe('When an event is emitted to the {token} exchange with properties:', () => {
|
|
118
|
-
const step = tomato.steps.Wh('an event is emitted to the {token} exchange with properties:')
|
|
119
|
-
|
|
120
|
-
it('should be', async () => undefined)
|
|
121
|
-
|
|
122
|
-
const exchange = generate()
|
|
123
|
-
const properties = { [generate()]: generate() }
|
|
124
|
-
const yaml = dump(properties)
|
|
125
|
-
|
|
126
|
-
beforeEach(async () => {
|
|
127
|
-
await step.call(context, exchange, yaml)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('should store event', async () => {
|
|
131
|
-
expect(context.published).toBeDefined()
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
it('should emit event', async () => {
|
|
135
|
-
expect(io.emit).toHaveBeenCalledWith(exchange, expect.anything(), properties)
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
describe('Then {token} receives the event', () => {
|
|
140
|
-
const step = tomato.steps.Th('{token} receives the event')
|
|
141
|
-
|
|
142
|
-
const payload = randomBytes(8)
|
|
143
|
-
const group = generate()
|
|
144
|
-
|
|
145
|
-
beforeEach(() => {
|
|
146
|
-
context.consumed = { [group]: { payload } }
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
it('should be', async () => undefined)
|
|
150
|
-
|
|
151
|
-
it('should throw if not consumed', async () => {
|
|
152
|
-
context.published = randomBytes(8)
|
|
153
|
-
|
|
154
|
-
await expect(step.call(context, group)).rejects.toThrow(AssertionError)
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('should pass if consumed', async () => {
|
|
158
|
-
context.published = payload
|
|
159
|
-
|
|
160
|
-
await expect(step.call(context, group)).resolves.not.toThrow()
|
|
161
|
-
})
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
describe('Then {token} receives the event with properties:', () => {
|
|
165
|
-
const step = tomato.steps.Th('{token} receives the event with properties:')
|
|
166
|
-
|
|
167
|
-
it('should be', async () => undefined)
|
|
168
|
-
|
|
169
|
-
const payload = randomBytes(8)
|
|
170
|
-
const properties = { headers: { [generate()]: generate() } }
|
|
171
|
-
const yaml = dump(properties)
|
|
172
|
-
const group = generate()
|
|
173
|
-
|
|
174
|
-
beforeEach(() => {
|
|
175
|
-
context.consumed = { [group]: { payload, properties } }
|
|
176
|
-
context.published = payload
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
it('should throw if does not match', async () => {
|
|
180
|
-
const properties = { headers: { [generate()]: generate() } }
|
|
181
|
-
const yaml = dump(properties)
|
|
182
|
-
|
|
183
|
-
await expect(step.call(context, group, yaml)).rejects.toThrow(AssertionError)
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
it('should pass if matches', async () => {
|
|
187
|
-
await expect(step.call(context, group, yaml)).resolves.not.toThrow()
|
|
188
|
-
})
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
describe('Then the event is received', () => {
|
|
192
|
-
const step = tomato.steps.Th('the event is received')
|
|
193
|
-
|
|
194
|
-
const payload = randomBytes(8)
|
|
195
|
-
const group = undefined
|
|
196
|
-
|
|
197
|
-
beforeEach(() => {
|
|
198
|
-
context.consumed = { [group]: { payload } }
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
it('should be', async () => undefined)
|
|
202
|
-
|
|
203
|
-
it('should throw if not consumed', async () => {
|
|
204
|
-
context.published = randomBytes(8)
|
|
205
|
-
|
|
206
|
-
await expect(step.call(context, group)).rejects.toThrow(AssertionError)
|
|
207
|
-
})
|
|
208
|
-
|
|
209
|
-
it('should pass if consumed', async () => {
|
|
210
|
-
context.published = payload
|
|
211
|
-
|
|
212
|
-
await expect(step.call(context, group)).resolves.not.toThrow()
|
|
213
|
-
})
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
describe('Given I\'m publishing {quantity}B events to the {token} exchange at {quantity}Hz', () => {
|
|
218
|
-
const step = tomato.steps.Gi('I\'m publishing {quantity}B events to the {token} exchange at {quantity}Hz')
|
|
219
|
-
|
|
220
|
-
it('should be', async () => undefined)
|
|
221
|
-
|
|
222
|
-
it('should publish events continuously', async () => {
|
|
223
|
-
context = /** @type {comq.features.Context} */ {
|
|
224
|
-
io: /** @type {jest.MockedObject<comq.IO>} */ { emit: jest.fn() },
|
|
225
|
-
requestsSent: [],
|
|
226
|
-
eventsPublishedCount: 0
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const bytesQ = '1k'
|
|
230
|
-
const exchange = generate()
|
|
231
|
-
const frequencyQ = '100'
|
|
232
|
-
|
|
233
|
-
step.call(context, bytesQ, exchange, frequencyQ)
|
|
234
|
-
|
|
235
|
-
await timeout(100)
|
|
236
|
-
|
|
237
|
-
const callsAmountExpected = [8, 9, 10, 11]
|
|
238
|
-
|
|
239
|
-
expect(callsAmountExpected).toContain(context.io.emit.mock.calls.length)
|
|
240
|
-
expect(context.publishing).toBeDefined()
|
|
241
|
-
expect(callsAmountExpected).toContain(context.eventsPublishedCount)
|
|
242
|
-
|
|
243
|
-
clearInterval(context.publishing)
|
|
244
|
-
})
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
describe('Then all events have been received', () => {
|
|
248
|
-
const step = tomato.steps.Th('all events have been received')
|
|
249
|
-
|
|
250
|
-
/** @type {jest.MockedObject<comq.features.Context>} */
|
|
251
|
-
let context
|
|
252
|
-
|
|
253
|
-
it('should be', async () => undefined)
|
|
254
|
-
|
|
255
|
-
beforeEach(async () => {
|
|
256
|
-
context = /** @type {jest.MockedObject<comq.features.Context>} */ {
|
|
257
|
-
eventsPublishedCount: random(100),
|
|
258
|
-
eventsConsumedCount: 100 + random()
|
|
259
|
-
}
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
it('should pass if events received', async () => {
|
|
263
|
-
context.eventsConsumedCount = context.eventsPublishedCount
|
|
264
|
-
|
|
265
|
-
await expect(step.call(context)).resolves.not.toThrow()
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
it('should fail if events are not received', async () => {
|
|
269
|
-
await expect(step.call(context)).rejects.toThrow(AssertionError)
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
it('should wait for last events (50ms)', async () => {
|
|
273
|
-
setTimeout(() => {
|
|
274
|
-
context.eventsConsumedCount = context.eventsPublishedCount
|
|
275
|
-
}, 49)
|
|
276
|
-
|
|
277
|
-
await expect(step.call(context)).resolves.not.toThrow()
|
|
278
|
-
})
|
|
279
|
-
})
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { generate } = require('randomstring')
|
|
4
|
-
|
|
5
|
-
const io = /** @type {jest.MockedObject<comq.IO>} */ {
|
|
6
|
-
reply: jest.fn(async () => undefined),
|
|
7
|
-
request: jest.fn(async () => generate()),
|
|
8
|
-
consume: jest.fn(async () => generate()),
|
|
9
|
-
emit: jest.fn(async () => generate()),
|
|
10
|
-
close: jest.fn(async () => undefined),
|
|
11
|
-
diagnose: jest.fn(() => undefined)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
exports.io = io
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { AssertionError } = require('node:assert')
|
|
4
|
-
const tomato = require('@toa.io/tomato')
|
|
5
|
-
const mock = { tomato }
|
|
6
|
-
|
|
7
|
-
jest.mock('@cucumber/cucumber', () => mock.tomato)
|
|
8
|
-
|
|
9
|
-
require('../poison')
|
|
10
|
-
|
|
11
|
-
/** @type {comq.features.Context} */
|
|
12
|
-
let context
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
context = /** @type {comq.features.Context} */ { events: {} }
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
describe('Then the message is discarded', () => {
|
|
19
|
-
const step = tomato.steps.Th('the message is discarded')
|
|
20
|
-
|
|
21
|
-
it('should be', async () => undefined)
|
|
22
|
-
|
|
23
|
-
it('should throw if not discarded', async () => {
|
|
24
|
-
await expect(step.call(context)).rejects.toThrow(AssertionError)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('should not throw if discarded', async () => {
|
|
28
|
-
context.events.discard = true
|
|
29
|
-
|
|
30
|
-
await expect(step.call(context)).resolves.not.toThrow()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should wait for discard event', async () => {
|
|
34
|
-
setTimeout(() => {
|
|
35
|
-
context.events.discard = true
|
|
36
|
-
}, 10)
|
|
37
|
-
|
|
38
|
-
await expect(step.call(context)).resolves.not.toThrow()
|
|
39
|
-
})
|
|
40
|
-
})
|