@cucumber/query 14.7.0 → 15.0.0
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/dist/src/Lineage.d.ts +3 -1
- package/dist/src/Lineage.d.ts.map +1 -1
- package/dist/src/Lineage.js.map +1 -1
- package/dist/src/Query.d.ts +3 -37
- package/dist/src/Query.d.ts.map +1 -1
- package/dist/src/Query.js +37 -174
- package/dist/src/Query.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +7 -10
- package/src/Lineage.ts +3 -0
- package/src/Query.spec.ts +79 -584
- package/src/Query.ts +43 -196
- package/src/acceptance.spec.ts +28 -6
package/src/Query.spec.ts
CHANGED
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
import assert from 'node:assert'
|
|
2
|
+
import fs from 'node:fs/promises'
|
|
3
|
+
import path from 'node:path'
|
|
2
4
|
|
|
3
|
-
import {
|
|
4
|
-
IncrementClock,
|
|
5
|
-
IncrementStopwatch,
|
|
6
|
-
makeTestCase,
|
|
7
|
-
makeTestPlan,
|
|
8
|
-
RunOptions,
|
|
9
|
-
SupportCode,
|
|
10
|
-
withFullStackTrace,
|
|
11
|
-
} from '@cucumber/fake-cucumber'
|
|
12
|
-
import { GherkinStreams } from '@cucumber/gherkin-streams'
|
|
13
|
-
import { Query as GherkinQuery } from '@cucumber/gherkin-utils'
|
|
14
|
-
import * as messages from '@cucumber/messages'
|
|
15
|
-
import { TestCaseStarted } from '@cucumber/messages'
|
|
16
|
-
import { pipeline, Readable, Writable } from 'stream'
|
|
17
|
-
import { promisify } from 'util'
|
|
5
|
+
import { Envelope, TestCaseStarted } from '@cucumber/messages'
|
|
18
6
|
|
|
7
|
+
import { Lineage } from './Lineage'
|
|
19
8
|
import Query from './Query'
|
|
20
9
|
|
|
21
|
-
const pipelinePromise = promisify(pipeline)
|
|
22
|
-
|
|
23
10
|
describe('Query', () => {
|
|
24
|
-
let gherkinQuery: GherkinQuery
|
|
25
11
|
let cucumberQuery: Query
|
|
26
12
|
beforeEach(() => {
|
|
27
|
-
gherkinQuery = new GherkinQuery()
|
|
28
13
|
cucumberQuery = new Query()
|
|
29
14
|
})
|
|
30
15
|
|
|
@@ -103,578 +88,88 @@ describe('Query', () => {
|
|
|
103
88
|
})
|
|
104
89
|
})
|
|
105
90
|
|
|
106
|
-
describe('#
|
|
107
|
-
it('returns
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
)
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
it('looks up results for scenario steps', async () => {
|
|
116
|
-
const envelopes: messages.Envelope[] = []
|
|
117
|
-
|
|
118
|
-
await execute(
|
|
119
|
-
`Feature: hello
|
|
120
|
-
Scenario: ok
|
|
121
|
-
Given a passed step
|
|
122
|
-
`,
|
|
123
|
-
(envelope) => envelopes.push(envelope)
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
const scenario = findScenario(envelopes)
|
|
127
|
-
|
|
128
|
-
const pickleStepIds = gherkinQuery.getPickleStepIds(scenario.steps[0].id)
|
|
129
|
-
assert.strictEqual(pickleStepIds.length, 1)
|
|
130
|
-
|
|
131
|
-
const testStepResults = cucumberQuery.getPickleStepTestStepResults(pickleStepIds)
|
|
132
|
-
assert.strictEqual(testStepResults.length, 1)
|
|
133
|
-
|
|
134
|
-
assert.strictEqual(testStepResults[0].status, 'PASSED')
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('looks up results for background steps', async () => {
|
|
138
|
-
const envelopes: messages.Envelope[] = []
|
|
139
|
-
|
|
140
|
-
await execute(
|
|
141
|
-
`Feature: hello
|
|
142
|
-
Background:
|
|
143
|
-
Given a passed step
|
|
144
|
-
|
|
145
|
-
Scenario: ok
|
|
146
|
-
Given a passed step
|
|
147
|
-
|
|
148
|
-
Scenario: ko
|
|
149
|
-
Given a failed step
|
|
150
|
-
`,
|
|
151
|
-
(envelope) => envelopes.push(envelope)
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
const background = findBackground(envelopes)
|
|
155
|
-
const pickleStepIds = gherkinQuery.getPickleStepIds(background.steps[0].id)
|
|
156
|
-
assert.strictEqual(pickleStepIds.length, 2)
|
|
157
|
-
|
|
158
|
-
const testStepResults = cucumberQuery.getPickleStepTestStepResults(pickleStepIds)
|
|
159
|
-
|
|
160
|
-
assert.deepStrictEqual(
|
|
161
|
-
testStepResults.map((r) => r.status),
|
|
162
|
-
['PASSED', 'PASSED']
|
|
163
|
-
)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
it('looks up results for background steps when scenarios are empty', async () => {
|
|
167
|
-
const envelopes: messages.Envelope[] = []
|
|
168
|
-
|
|
169
|
-
await execute(
|
|
170
|
-
`Feature: hello
|
|
171
|
-
Background:
|
|
172
|
-
Given a passed step
|
|
173
|
-
|
|
174
|
-
Scenario: ok
|
|
175
|
-
|
|
176
|
-
Scenario: ok too
|
|
177
|
-
`,
|
|
178
|
-
(envelope) => envelopes.push(envelope)
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
const background = findBackground(envelopes)
|
|
182
|
-
const pickleStepIds = gherkinQuery.getPickleStepIds(background.steps[0].id)
|
|
183
|
-
assert.strictEqual(pickleStepIds.length, 0)
|
|
184
|
-
|
|
185
|
-
const testStepResults = cucumberQuery.getPickleStepTestStepResults(pickleStepIds)
|
|
186
|
-
assert.strictEqual(testStepResults.length, 1)
|
|
187
|
-
|
|
188
|
-
assert.strictEqual(testStepResults[0].status, 'UNKNOWN')
|
|
189
|
-
})
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
describe('#getPickleTestStepResults(pickleIds)', () => {
|
|
193
|
-
it('looks up results for scenarios', async () => {
|
|
194
|
-
const envelopes: messages.Envelope[] = []
|
|
195
|
-
await execute(
|
|
196
|
-
`Feature: hello
|
|
197
|
-
Scenario: ko
|
|
198
|
-
Given a passed step
|
|
199
|
-
Given a failed step
|
|
200
|
-
`,
|
|
201
|
-
(envelope) => envelopes.push(envelope)
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
const scenario = findScenario(envelopes)
|
|
205
|
-
const pickleIds = gherkinQuery.getPickleIds('test.feature', scenario.id)
|
|
206
|
-
assert.strictEqual(pickleIds.length, 1)
|
|
207
|
-
|
|
208
|
-
const testStepResults = cucumberQuery.getPickleTestStepResults(pickleIds)
|
|
209
|
-
|
|
210
|
-
assert.deepStrictEqual(
|
|
211
|
-
testStepResults.map((r) => r.status),
|
|
212
|
-
['PASSED', 'FAILED']
|
|
213
|
-
)
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
it('looks up results for scenario outlines', async () => {
|
|
217
|
-
const envelopes: messages.Envelope[] = []
|
|
218
|
-
await execute(
|
|
219
|
-
`Feature: hello
|
|
220
|
-
Scenario: hi <status1> and <status2>
|
|
221
|
-
Given a <status1> step
|
|
222
|
-
And a <status2> step
|
|
223
|
-
|
|
224
|
-
Examples:
|
|
225
|
-
| status1 | status2 |
|
|
226
|
-
| passed | passed |
|
|
227
|
-
| passed | failed |
|
|
228
|
-
`,
|
|
229
|
-
(envelope) => envelopes.push(envelope)
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
const scenario = findScenario(envelopes)
|
|
233
|
-
const pickleIds = gherkinQuery.getPickleIds('test.feature', scenario.id)
|
|
234
|
-
assert.strictEqual(pickleIds.length, 2)
|
|
235
|
-
|
|
236
|
-
assert.deepStrictEqual(
|
|
237
|
-
cucumberQuery.getPickleTestStepResults(pickleIds).map((r) => r.status),
|
|
238
|
-
['PASSED', 'PASSED', 'PASSED', 'FAILED']
|
|
239
|
-
)
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
it('looks up results for examples rows outlines', async () => {
|
|
243
|
-
const envelopes: messages.Envelope[] = []
|
|
244
|
-
|
|
245
|
-
await execute(
|
|
246
|
-
`Feature: hello
|
|
247
|
-
Scenario: hi <status1> and <status2>
|
|
248
|
-
Given a <status1> step
|
|
249
|
-
And a <status2> step
|
|
250
|
-
|
|
251
|
-
Examples:
|
|
252
|
-
| status1 | status2 |
|
|
253
|
-
| passed | passed |
|
|
254
|
-
| passed | failed |
|
|
255
|
-
`,
|
|
256
|
-
(envelope) => envelopes.push(envelope)
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
const scenario = findScenario(envelopes)
|
|
260
|
-
const exampleIds = scenario.examples[0].tableBody.map((row) => row.id)
|
|
261
|
-
|
|
262
|
-
assert.deepStrictEqual(
|
|
263
|
-
cucumberQuery
|
|
264
|
-
.getPickleTestStepResults(gherkinQuery.getPickleIds('test.feature', exampleIds[0]))
|
|
265
|
-
.map((r) => r.status),
|
|
266
|
-
['PASSED', 'PASSED']
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
assert.deepStrictEqual(
|
|
270
|
-
cucumberQuery
|
|
271
|
-
.getPickleTestStepResults(gherkinQuery.getPickleIds('test.feature', exampleIds[1]))
|
|
272
|
-
.map((r) => r.status),
|
|
273
|
-
['PASSED', 'FAILED']
|
|
274
|
-
)
|
|
275
|
-
})
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
describe('#getPickleStepAttachments(pickleIds)', () => {
|
|
279
|
-
it('looks up attachments', async () => {
|
|
280
|
-
const envelopes: messages.Envelope[] = []
|
|
281
|
-
await execute(
|
|
282
|
-
`Feature: hello
|
|
283
|
-
Scenario: ok
|
|
284
|
-
Given a passed step with attachment
|
|
285
|
-
`,
|
|
286
|
-
(envelope) => envelopes.push(envelope)
|
|
91
|
+
describe('#findLineageBy', () => {
|
|
92
|
+
it('returns correct lineage for a minimal scenario', async () => {
|
|
93
|
+
const envelopes: ReadonlyArray<Envelope> = (
|
|
94
|
+
await fs.readFile(path.join(__dirname, '../../testdata/src/minimal.ndjson'), {
|
|
95
|
+
encoding: 'utf-8',
|
|
96
|
+
})
|
|
287
97
|
)
|
|
98
|
+
.split('\n')
|
|
99
|
+
.filter((line) => !!line)
|
|
100
|
+
.map((line) => JSON.parse(line))
|
|
101
|
+
envelopes.forEach((envelope) => cucumberQuery.update(envelope))
|
|
288
102
|
|
|
289
|
-
const
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
const attachments = cucumberQuery.getPickleStepAttachments(pickleStepIds)
|
|
294
|
-
assert.strictEqual(attachments.length, 1)
|
|
103
|
+
const gherkinDocument = envelopes.find((envelope) => envelope.gherkinDocument).gherkinDocument
|
|
104
|
+
const feature = gherkinDocument.feature
|
|
105
|
+
const scenario = feature.children.find((child) => child.scenario).scenario
|
|
106
|
+
const pickle = envelopes.find((envelope) => envelope.pickle).pickle
|
|
295
107
|
|
|
296
|
-
assert.
|
|
108
|
+
assert.deepStrictEqual(cucumberQuery.findLineageBy(pickle), {
|
|
109
|
+
gherkinDocument,
|
|
110
|
+
feature,
|
|
111
|
+
scenario,
|
|
112
|
+
} satisfies Lineage)
|
|
297
113
|
})
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
describe('#getStepMatchArguments(uri, lineNumber)', () => {
|
|
301
|
-
it("looks up result for step's uri and line", async () => {
|
|
302
|
-
const envelopes: messages.Envelope[] = []
|
|
303
|
-
await execute(
|
|
304
|
-
`Feature: hello
|
|
305
|
-
Scenario: ok
|
|
306
|
-
Given a passed step
|
|
307
|
-
And I have 567 cukes in my belly
|
|
308
|
-
`,
|
|
309
|
-
(envelope) => envelopes.push(envelope)
|
|
310
|
-
)
|
|
311
114
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
.map((sal) => sal.stepMatchArguments.map((arg) => arg.parameterTypeName)),
|
|
318
|
-
[[]]
|
|
115
|
+
it('returns correct lineage for a pickle from an examples table', async () => {
|
|
116
|
+
const envelopes: ReadonlyArray<Envelope> = (
|
|
117
|
+
await fs.readFile(path.join(__dirname, '../../testdata/src/examples-tables.ndjson'), {
|
|
118
|
+
encoding: 'utf-8',
|
|
119
|
+
})
|
|
319
120
|
)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
121
|
+
.split('\n')
|
|
122
|
+
.filter((line) => !!line)
|
|
123
|
+
.map((line) => JSON.parse(line))
|
|
124
|
+
envelopes.forEach((envelope) => cucumberQuery.update(envelope))
|
|
125
|
+
|
|
126
|
+
const gherkinDocument = envelopes.find((envelope) => envelope.gherkinDocument).gherkinDocument
|
|
127
|
+
const feature = gherkinDocument.feature
|
|
128
|
+
const scenario = feature.children.find((child) => child.scenario).scenario
|
|
129
|
+
const pickle = envelopes.find((envelope) => envelope.pickle).pickle
|
|
130
|
+
const examples = scenario.examples[0]
|
|
131
|
+
const example = examples.tableBody[0]
|
|
132
|
+
|
|
133
|
+
assert.deepStrictEqual(cucumberQuery.findLineageBy(pickle), {
|
|
134
|
+
gherkinDocument,
|
|
135
|
+
feature,
|
|
136
|
+
scenario,
|
|
137
|
+
examples,
|
|
138
|
+
examplesIndex: 0,
|
|
139
|
+
example,
|
|
140
|
+
exampleIndex: 0,
|
|
141
|
+
} satisfies Lineage)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('returns correct lineage for a pickle with background-derived steps', async () => {
|
|
145
|
+
const envelopes: ReadonlyArray<Envelope> = (
|
|
146
|
+
await fs.readFile(path.join(__dirname, '../../testdata/src/rules-backgrounds.ndjson'), {
|
|
147
|
+
encoding: 'utf-8',
|
|
148
|
+
})
|
|
326
149
|
)
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
Scenario: hi
|
|
351
|
-
Given a passed step
|
|
352
|
-
`,
|
|
353
|
-
(envelope) => envelopes.push(envelope)
|
|
354
|
-
)
|
|
355
|
-
const scenarioId = findScenario(envelopes).id
|
|
356
|
-
const pickleId = gherkinQuery.getPickleIds('test.feature', scenarioId)[0]
|
|
357
|
-
|
|
358
|
-
assert.strictEqual(cucumberQuery.getBeforeHookSteps(pickleId).length, 1)
|
|
359
|
-
})
|
|
360
|
-
|
|
361
|
-
it('does not return after hook steps', async () => {
|
|
362
|
-
const envelopes: messages.Envelope[] = []
|
|
363
|
-
await execute(
|
|
364
|
-
`Feature: hello
|
|
365
|
-
@afterHook
|
|
366
|
-
Scenario: hi
|
|
367
|
-
Given a passed step
|
|
368
|
-
`,
|
|
369
|
-
(envelope) => envelopes.push(envelope)
|
|
370
|
-
)
|
|
371
|
-
const scenarioId = findScenario(envelopes).id
|
|
372
|
-
const pickleId = gherkinQuery.getPickleIds('test.feature', scenarioId)[0]
|
|
373
|
-
|
|
374
|
-
assert.deepStrictEqual(cucumberQuery.getBeforeHookSteps(pickleId), [])
|
|
375
|
-
})
|
|
376
|
-
})
|
|
377
|
-
|
|
378
|
-
describe('#getAfterHookSteps(pickleId: string)', () => {
|
|
379
|
-
it('returns an empty list when there is no hooks', async () => {
|
|
380
|
-
const envelopes: messages.Envelope[] = []
|
|
381
|
-
await execute(
|
|
382
|
-
`Feature: hello
|
|
383
|
-
Scenario: hi
|
|
384
|
-
Given a passed step
|
|
385
|
-
`,
|
|
386
|
-
(envelope) => envelopes.push(envelope)
|
|
387
|
-
)
|
|
388
|
-
const scenarioId = findScenario(envelopes).id
|
|
389
|
-
const pickleId = gherkinQuery.getPickleIds('test.feature', scenarioId)[0]
|
|
390
|
-
|
|
391
|
-
assert.deepStrictEqual(cucumberQuery.getAfterHookSteps(pickleId), [])
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
it('returns one after hook step', async () => {
|
|
395
|
-
const envelopes: messages.Envelope[] = []
|
|
396
|
-
await execute(
|
|
397
|
-
`Feature: hello
|
|
398
|
-
@afterHook
|
|
399
|
-
Scenario: hi
|
|
400
|
-
Given a passed step
|
|
401
|
-
`,
|
|
402
|
-
(envelope) => envelopes.push(envelope)
|
|
403
|
-
)
|
|
404
|
-
const scenarioId = findScenario(envelopes).id
|
|
405
|
-
const pickleId = gherkinQuery.getPickleIds('test.feature', scenarioId)[0]
|
|
406
|
-
|
|
407
|
-
assert.strictEqual(cucumberQuery.getAfterHookSteps(pickleId).length, 1)
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
it('does not return before hook steps', async () => {
|
|
411
|
-
const envelopes: messages.Envelope[] = []
|
|
412
|
-
await execute(
|
|
413
|
-
`Feature: hello
|
|
414
|
-
@beforeHook
|
|
415
|
-
Scenario: hi
|
|
416
|
-
Given a passed step
|
|
417
|
-
`,
|
|
418
|
-
(envelope) => envelopes.push(envelope)
|
|
419
|
-
)
|
|
420
|
-
const scenarioId = findScenario(envelopes).id
|
|
421
|
-
const pickleId = gherkinQuery.getPickleIds('test.feature', scenarioId)[0]
|
|
422
|
-
|
|
423
|
-
assert.deepStrictEqual(cucumberQuery.getAfterHookSteps(pickleId), [])
|
|
424
|
-
})
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
describe('#getTestStepResult', () => {
|
|
428
|
-
it('returns one test step result', async () => {
|
|
429
|
-
const emittedMessages: Array<messages.Envelope> = []
|
|
430
|
-
await execute(
|
|
431
|
-
`Feature: hello
|
|
432
|
-
Scenario: hi
|
|
433
|
-
Given a passed step
|
|
434
|
-
`,
|
|
435
|
-
(message) => emittedMessages.push(message)
|
|
436
|
-
)
|
|
437
|
-
const testCase = emittedMessages.find((child) => child.testCase).testCase
|
|
438
|
-
const testStep = testCase.testSteps[0]
|
|
439
|
-
const results = cucumberQuery.getTestStepResults(testStep.id)
|
|
440
|
-
|
|
441
|
-
assert.deepStrictEqual(results.length, 1)
|
|
442
|
-
assert.deepStrictEqual(results[0].status, 'PASSED')
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
it('returns a result for hook step', async () => {
|
|
446
|
-
const emittedMessages: Array<messages.Envelope> = []
|
|
447
|
-
await execute(
|
|
448
|
-
`Feature: hello
|
|
449
|
-
@beforeHook
|
|
450
|
-
Scenario: hi
|
|
451
|
-
Given a passed step
|
|
452
|
-
`,
|
|
453
|
-
(message) => emittedMessages.push(message)
|
|
454
|
-
)
|
|
455
|
-
const testCase = emittedMessages.find((child) => child.testCase).testCase
|
|
456
|
-
const testStep = testCase.testSteps[0]
|
|
457
|
-
const results = cucumberQuery.getTestStepResults(testStep.id)
|
|
458
|
-
|
|
459
|
-
assert.deepStrictEqual(results.length, 1)
|
|
460
|
-
assert.deepStrictEqual(results[0].status, 'PASSED')
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
it('returns the result from the last attempt only where retry has been used', async () => {
|
|
464
|
-
const emittedMessages: Array<messages.Envelope> = []
|
|
465
|
-
await execute(
|
|
466
|
-
`Feature: hello
|
|
467
|
-
Scenario: hi
|
|
468
|
-
Given a step that passes the second time
|
|
469
|
-
`,
|
|
470
|
-
(message) => emittedMessages.push(message),
|
|
471
|
-
{ allowedRetries: 1 }
|
|
472
|
-
)
|
|
473
|
-
const testCase = emittedMessages.find((child) => child.testCase).testCase
|
|
474
|
-
const testStep = testCase.testSteps[0]
|
|
475
|
-
const results = cucumberQuery.getTestStepResults(testStep.id)
|
|
476
|
-
|
|
477
|
-
assert.deepStrictEqual(results.length, 1)
|
|
478
|
-
assert.deepStrictEqual(results[0].status, 'PASSED')
|
|
479
|
-
})
|
|
480
|
-
})
|
|
481
|
-
|
|
482
|
-
describe('#getHook(HookId)', () => {
|
|
483
|
-
it('returns undefined if the id does not match any hook', () => {
|
|
484
|
-
assert.strictEqual(cucumberQuery.getHook('tralala'), undefined)
|
|
485
|
-
})
|
|
486
|
-
|
|
487
|
-
it('returns the matching hook', () => {
|
|
488
|
-
const hook: messages.Hook = {
|
|
489
|
-
id: 'tralala',
|
|
490
|
-
sourceReference: {},
|
|
491
|
-
}
|
|
492
|
-
const envelope: messages.Envelope = {
|
|
493
|
-
hook,
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
cucumberQuery.update(envelope)
|
|
497
|
-
|
|
498
|
-
assert.deepStrictEqual(cucumberQuery.getHook('tralala'), hook)
|
|
499
|
-
})
|
|
500
|
-
})
|
|
501
|
-
|
|
502
|
-
describe('#getAttachmentByTestStepId', () => {
|
|
503
|
-
it('looks up attachments', async () => {
|
|
504
|
-
const testCases: messages.TestCase[] = []
|
|
505
|
-
await execute(
|
|
506
|
-
`Feature: hello
|
|
507
|
-
Scenario: ok
|
|
508
|
-
Given a passed step with attachment
|
|
509
|
-
`,
|
|
510
|
-
(envelope) => {
|
|
511
|
-
if (envelope.testCase) {
|
|
512
|
-
testCases.push(envelope.testCase)
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
)
|
|
516
|
-
|
|
517
|
-
const attachments = cucumberQuery.getTestStepsAttachments([testCases[0].testSteps[0].id])
|
|
518
|
-
assert.strictEqual(attachments.length, 1)
|
|
519
|
-
|
|
520
|
-
assert.strictEqual(attachments[0].body, 'Hello')
|
|
521
|
-
})
|
|
522
|
-
|
|
523
|
-
it('returns attachments from the last attempt only where retry has been used', async () => {
|
|
524
|
-
const testCases: messages.TestCase[] = []
|
|
525
|
-
await execute(
|
|
526
|
-
`Feature: hello
|
|
527
|
-
Scenario: ok
|
|
528
|
-
Given a passed step with attachment
|
|
529
|
-
And a step that passes the second time
|
|
530
|
-
`,
|
|
531
|
-
(envelope) => {
|
|
532
|
-
if (envelope.testCase) {
|
|
533
|
-
testCases.push(envelope.testCase)
|
|
534
|
-
}
|
|
535
|
-
},
|
|
536
|
-
{ allowedRetries: 1 }
|
|
537
|
-
)
|
|
538
|
-
|
|
539
|
-
const attachments = cucumberQuery.getTestStepsAttachments([testCases[0].testSteps[0].id])
|
|
540
|
-
assert.strictEqual(attachments.length, 1)
|
|
541
|
-
|
|
542
|
-
assert.strictEqual(attachments[0].body, 'Hello')
|
|
543
|
-
})
|
|
544
|
-
})
|
|
545
|
-
|
|
546
|
-
describe('#getStatusCounts', () => {
|
|
547
|
-
it('returns the number of pickles for each status', async () => {
|
|
548
|
-
await execute(
|
|
549
|
-
`Feature: hello
|
|
550
|
-
Scenario: ok
|
|
551
|
-
Given a passed step
|
|
552
|
-
`,
|
|
553
|
-
() => undefined
|
|
554
|
-
)
|
|
555
|
-
|
|
556
|
-
await execute(
|
|
557
|
-
`Feature: hello
|
|
558
|
-
Scenario: ok
|
|
559
|
-
Given a passed step
|
|
560
|
-
`,
|
|
561
|
-
() => undefined
|
|
562
|
-
)
|
|
563
|
-
|
|
564
|
-
await execute(
|
|
565
|
-
`Feature: hello
|
|
566
|
-
Scenario: ok
|
|
567
|
-
Given a failed step
|
|
568
|
-
`,
|
|
569
|
-
() => undefined
|
|
570
|
-
)
|
|
571
|
-
|
|
572
|
-
await execute(
|
|
573
|
-
`Feature: hello
|
|
574
|
-
Scenario: ok
|
|
575
|
-
Given an undefined step
|
|
576
|
-
`,
|
|
577
|
-
() => undefined
|
|
578
|
-
)
|
|
579
|
-
|
|
580
|
-
const statuses = cucumberQuery.getStatusCounts(
|
|
581
|
-
gherkinQuery.getPickles().map((pickle) => pickle.id)
|
|
582
|
-
)
|
|
583
|
-
|
|
584
|
-
const expectedStatuses: Partial<Record<messages.TestStepResultStatus, number>> = {
|
|
585
|
-
PASSED: 2,
|
|
586
|
-
FAILED: 1,
|
|
587
|
-
UNDEFINED: 1,
|
|
588
|
-
}
|
|
589
|
-
assert.deepStrictEqual(statuses, expectedStatuses)
|
|
590
|
-
})
|
|
150
|
+
.split('\n')
|
|
151
|
+
.filter((line) => !!line)
|
|
152
|
+
.map((line) => JSON.parse(line))
|
|
153
|
+
envelopes.forEach((envelope) => cucumberQuery.update(envelope))
|
|
154
|
+
|
|
155
|
+
const gherkinDocument = envelopes.find((envelope) => envelope.gherkinDocument).gherkinDocument
|
|
156
|
+
const feature = gherkinDocument.feature
|
|
157
|
+
const background = gherkinDocument.feature.children.find(
|
|
158
|
+
(child) => child.background
|
|
159
|
+
).background
|
|
160
|
+
const rule = feature.children.find((child) => child.rule).rule
|
|
161
|
+
const ruleBackground = rule.children.find((child) => child.background).background
|
|
162
|
+
const scenario = rule.children.find((child) => child.scenario).scenario
|
|
163
|
+
const pickle = envelopes.find((envelope) => envelope.pickle).pickle
|
|
164
|
+
|
|
165
|
+
assert.deepStrictEqual(cucumberQuery.findLineageBy(pickle), {
|
|
166
|
+
gherkinDocument,
|
|
167
|
+
feature,
|
|
168
|
+
background,
|
|
169
|
+
rule,
|
|
170
|
+
ruleBackground,
|
|
171
|
+
scenario,
|
|
172
|
+
} satisfies Lineage)
|
|
591
173
|
})
|
|
592
174
|
})
|
|
593
|
-
|
|
594
|
-
async function execute(
|
|
595
|
-
gherkinSource: string,
|
|
596
|
-
messagesHandler: (envelope: messages.Envelope) => void = () => null,
|
|
597
|
-
runOptions: RunOptions = { allowedRetries: 0 }
|
|
598
|
-
): Promise<void> {
|
|
599
|
-
const newId = messages.IdGenerator.uuid()
|
|
600
|
-
const clock = new IncrementClock()
|
|
601
|
-
const stopwatch = new IncrementStopwatch()
|
|
602
|
-
const makeErrorMessage = withFullStackTrace()
|
|
603
|
-
const supportCode = new SupportCode(newId, clock, stopwatch, makeErrorMessage)
|
|
604
|
-
supportCode.defineBeforeHook(null, '@beforeHook', () => {
|
|
605
|
-
// no-op
|
|
606
|
-
})
|
|
607
|
-
supportCode.defineAfterHook(null, '@afterHook', () => {
|
|
608
|
-
// no-op
|
|
609
|
-
})
|
|
610
|
-
supportCode.defineStepDefinition(null, 'a passed step', () => {
|
|
611
|
-
// no-op
|
|
612
|
-
})
|
|
613
|
-
supportCode.defineStepDefinition(null, 'a passed step with attachment', function () {
|
|
614
|
-
this.attach('Hello', 'text/plain')
|
|
615
|
-
})
|
|
616
|
-
supportCode.defineStepDefinition(null, 'a failed step', () => {
|
|
617
|
-
throw new Error(`This step failed.`)
|
|
618
|
-
})
|
|
619
|
-
supportCode.defineStepDefinition(null, 'I have {int} cukes in my {word}', (cukes: number) => {
|
|
620
|
-
assert.ok(cukes)
|
|
621
|
-
})
|
|
622
|
-
let passesSecondTime = 0
|
|
623
|
-
supportCode.defineStepDefinition(null, 'a step that passes the second time', () => {
|
|
624
|
-
passesSecondTime++
|
|
625
|
-
if (passesSecondTime < 2) {
|
|
626
|
-
throw new Error(`This step failed.`)
|
|
627
|
-
}
|
|
628
|
-
})
|
|
629
|
-
|
|
630
|
-
const queryUpdateStream = new Writable({
|
|
631
|
-
objectMode: true,
|
|
632
|
-
write(
|
|
633
|
-
envelope: messages.Envelope,
|
|
634
|
-
encoding: string,
|
|
635
|
-
callback: (error?: Error | null) => void
|
|
636
|
-
): void {
|
|
637
|
-
try {
|
|
638
|
-
messagesHandler(envelope)
|
|
639
|
-
gherkinQuery.update(envelope)
|
|
640
|
-
cucumberQuery.update(envelope)
|
|
641
|
-
callback()
|
|
642
|
-
} catch (err) {
|
|
643
|
-
callback(err)
|
|
644
|
-
}
|
|
645
|
-
},
|
|
646
|
-
})
|
|
647
|
-
await pipelinePromise(gherkinMessages(gherkinSource, 'test.feature', newId), queryUpdateStream)
|
|
648
|
-
|
|
649
|
-
const testPlan = makeTestPlan(gherkinQuery, supportCode, runOptions, makeTestCase)
|
|
650
|
-
await testPlan.execute((envelope: messages.Envelope) => {
|
|
651
|
-
messagesHandler(envelope)
|
|
652
|
-
cucumberQuery.update(envelope)
|
|
653
|
-
})
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
function gherkinMessages(
|
|
657
|
-
gherkinSource: string,
|
|
658
|
-
uri: string,
|
|
659
|
-
newId: messages.IdGenerator.NewId
|
|
660
|
-
): Readable {
|
|
661
|
-
const source: messages.Envelope = {
|
|
662
|
-
source: {
|
|
663
|
-
uri,
|
|
664
|
-
data: gherkinSource,
|
|
665
|
-
mediaType: messages.SourceMediaType.TEXT_X_CUCUMBER_GHERKIN_PLAIN,
|
|
666
|
-
},
|
|
667
|
-
}
|
|
668
|
-
return GherkinStreams.fromSources([source], { newId })
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
function findScenario(envelopes: messages.Envelope[]): messages.Scenario {
|
|
672
|
-
const gherkinDocument = envelopes.find((envelope) => envelope.gherkinDocument).gherkinDocument
|
|
673
|
-
return gherkinDocument.feature.children.find((child) => child.scenario).scenario
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
function findBackground(envelopes: messages.Envelope[]): messages.Background {
|
|
677
|
-
const gherkinDocument = envelopes.find((envelope) => envelope.gherkinDocument).gherkinDocument
|
|
678
|
-
return gherkinDocument.feature.children.find((child) => child.background).background
|
|
679
|
-
}
|
|
680
175
|
})
|