@autometa/test-builder 0.0.0 → 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # @autometa/test-builder
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 554b77e: Releasing packages
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [554b77e]
12
+ - @autometa/bind-decorator@0.5.0
13
+ - @autometa/dto-builder@0.10.0
14
+ - @autometa/app@0.1.0
15
+ - @autometa/asserters@0.1.0
16
+ - @autometa/errors@0.1.0
17
+ - @autometa/gherkin@0.4.0
18
+ - @autometa/phrases@0.1.0
19
+ - @autometa/scopes@0.2.0
20
+ - @autometa/types@0.4.0
package/dist/esm/index.js CHANGED
@@ -1,5 +1,638 @@
1
- // src/index.ts
2
- var src_default = {};
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result)
9
+ __defProp(target, key, result);
10
+ return result;
11
+ };
12
+ var __accessCheck = (obj, member, msg) => {
13
+ if (!member.has(obj))
14
+ throw TypeError("Cannot " + msg);
15
+ };
16
+ var __privateAdd = (obj, member, value) => {
17
+ if (member.has(obj))
18
+ throw TypeError("Cannot add the same private member more than once");
19
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
20
+ };
21
+ var __privateMethod = (obj, member, method) => {
22
+ __accessCheck(obj, member, "access private method");
23
+ return method;
24
+ };
25
+
26
+ // src/bridges/bridge.ts
27
+ var GherkinCodeBridge = class {
28
+ };
29
+ var FeatureBridge = class extends GherkinCodeBridge {
30
+ constructor() {
31
+ super(...arguments);
32
+ this.scenarios = [];
33
+ this.rules = [];
34
+ this.steps = [];
35
+ }
36
+ };
37
+ var BackgroundBridge = class extends GherkinCodeBridge {
38
+ constructor() {
39
+ super(...arguments);
40
+ this.steps = [];
41
+ }
42
+ };
43
+ var RuleBridge = class extends GherkinCodeBridge {
44
+ constructor() {
45
+ super(...arguments);
46
+ this.scenarios = [];
47
+ this.steps = [];
48
+ }
49
+ };
50
+ var ScenarioBridge = class extends GherkinCodeBridge {
51
+ constructor() {
52
+ super(...arguments);
53
+ this.steps = [];
54
+ this.report = {};
55
+ }
56
+ };
57
+ var ExampleBridge = class extends GherkinCodeBridge {
58
+ constructor() {
59
+ super(...arguments);
60
+ this.steps = [];
61
+ this.report = {};
62
+ }
63
+ };
64
+ var ScenarioOutlineBridge = class extends GherkinCodeBridge {
65
+ constructor() {
66
+ super(...arguments);
67
+ this.examples = [];
68
+ this.steps = [];
69
+ }
70
+ };
71
+ var ExamplesBridge = class extends GherkinCodeBridge {
72
+ constructor() {
73
+ super(...arguments);
74
+ this.scenarios = [];
75
+ this.steps = [];
76
+ }
77
+ };
78
+ var StepBridge = class extends GherkinCodeBridge {
79
+ };
80
+
81
+ // src/bridges/bridge-search.ts
82
+ import { AutomationError } from "@autometa/errors";
83
+ function find(bridge, testName) {
84
+ if (bridge instanceof FeatureBridge) {
85
+ return findByFeature(bridge, testName);
86
+ }
87
+ if (bridge instanceof RuleBridge) {
88
+ return findByRule(bridge, testName);
89
+ }
90
+ if (bridge instanceof ScenarioOutlineBridge) {
91
+ return findScenarioOutlineOrChild(bridge, testName);
92
+ }
93
+ throw new AutomationError(`Could not find test matching ${testName}`);
94
+ }
95
+ function findByFeature(feature, testName) {
96
+ const title = feature.data.scope.title(feature.data.gherkin);
97
+ const byScenario = findTestTypes(feature.scenarios, testName, title);
98
+ if (byScenario) {
99
+ return byScenario;
100
+ }
101
+ const byRule = findRuleTypes(feature.rules, testName, title);
102
+ if (byRule) {
103
+ return byRule;
104
+ }
105
+ }
106
+ function findByRule(rule, testName) {
107
+ const title = rule.data.scope.title(rule.data.gherkin);
108
+ const byScenario = findTestTypes(rule.scenarios, testName, title);
109
+ if (byScenario) {
110
+ return byScenario;
111
+ }
112
+ const byRule = findRuleOrChild(rule, testName, title);
113
+ if (byRule) {
114
+ return byRule;
115
+ }
116
+ }
117
+ function findTestTypes(scenarios, testName, from) {
118
+ for (const scenario of scenarios) {
119
+ if (scenario instanceof ScenarioOutlineBridge) {
120
+ const found = findScenarioOutlineOrChild(scenario, testName, from);
121
+ if (found) {
122
+ return found;
123
+ }
124
+ }
125
+ if (scenario instanceof ExamplesBridge) {
126
+ const found = findExamplesOrChild(scenario, testName, from);
127
+ if (found) {
128
+ return found;
129
+ }
130
+ }
131
+ if (scenario instanceof ScenarioBridge) {
132
+ const found = findScenario(scenario, testName, from);
133
+ if (found) {
134
+ return found;
135
+ }
136
+ }
137
+ }
138
+ }
139
+ function findRuleTypes(rules, testName, from) {
140
+ for (const rule of rules) {
141
+ const found = findRuleOrChild(rule, testName, from);
142
+ if (found) {
143
+ return found;
144
+ }
145
+ }
146
+ }
147
+ function findRuleOrChild(rule, testName, from) {
148
+ const {
149
+ data: { scope: scope2, gherkin }
150
+ } = rule;
151
+ const title = scope2.title(gherkin);
152
+ if (testName === title) {
153
+ return rule;
154
+ }
155
+ if (from) {
156
+ const fullTitle = `${from} ${title}`;
157
+ if (fullTitle === testName) {
158
+ return rule;
159
+ }
160
+ }
161
+ const newFrom = appendPath(from, title);
162
+ return findTestTypes(rule.scenarios, testName, newFrom);
163
+ }
164
+ function findScenarioOutlineOrChild(outline, testName, from) {
165
+ const {
166
+ data: { scope: scope2, gherkin }
167
+ } = outline;
168
+ const title = scope2.title(gherkin);
169
+ if (testName === title) {
170
+ return outline;
171
+ }
172
+ if (from) {
173
+ const fullTitle = `${from} ${title}`;
174
+ if (fullTitle === testName) {
175
+ return outline;
176
+ }
177
+ }
178
+ for (const example of outline.examples) {
179
+ const newFrom = appendPath(from, title);
180
+ const found = findExamplesOrChild(example, testName, newFrom);
181
+ if (found) {
182
+ return found;
183
+ }
184
+ }
185
+ }
186
+ function appendPath(from, title) {
187
+ return from ? `${from} ${title}` : title;
188
+ }
189
+ function findExamplesOrChild(example, testName, from) {
190
+ const {
191
+ data: { scope: scope2, gherkin }
192
+ } = example;
193
+ const title = scope2.title(gherkin);
194
+ if (testName === title) {
195
+ return example;
196
+ }
197
+ if (from) {
198
+ const fullTitle = `${from} ${title}`;
199
+ if (fullTitle === testName) {
200
+ return example;
201
+ }
202
+ }
203
+ for (const scenario of example.scenarios) {
204
+ const newFrom = appendPath(from, title);
205
+ const found = findScenario(scenario, testName, newFrom);
206
+ if (found) {
207
+ return found;
208
+ }
209
+ }
210
+ }
211
+ function findScenario(scenario, testName, from) {
212
+ const {
213
+ data: { scope: scope2, gherkin }
214
+ } = scenario;
215
+ const title = scope2.title(gherkin);
216
+ if (testName === title) {
217
+ return scenario;
218
+ }
219
+ if (from) {
220
+ const fullTitle = `${from} ${title}`;
221
+ if (fullTitle === testName) {
222
+ return scenario;
223
+ }
224
+ }
225
+ }
226
+
227
+ // src/bridges/bridge-query.ts
228
+ import {
229
+ Background
230
+ } from "@autometa/gherkin";
231
+ function failed(bridge) {
232
+ const accumulator = [];
233
+ if (bridge instanceof ScenarioOutlineBridge) {
234
+ return failedOutline(bridge);
235
+ }
236
+ for (const scenario of bridge.scenarios) {
237
+ if (scenario instanceof ScenarioOutlineBridge) {
238
+ accumulator.push(...failedOutline(scenario));
239
+ } else if (!scenario.report.passed) {
240
+ accumulator.push(scenario);
241
+ }
242
+ }
243
+ if (bridge instanceof FeatureBridge) {
244
+ accumulator.push(...failedRule(bridge));
245
+ }
246
+ return accumulator;
247
+ }
248
+ function failedOutline(bridge) {
249
+ const accumulator = [];
250
+ for (const example of bridge.examples) {
251
+ for (const scenario of example.scenarios) {
252
+ if (!scenario.report.passed) {
253
+ accumulator.push(scenario);
254
+ }
255
+ }
256
+ }
257
+ return accumulator;
258
+ }
259
+ function failedRule(bridge) {
260
+ const accumulator = [];
261
+ for (const rule of bridge.rules) {
262
+ for (const scenario of rule.scenarios) {
263
+ if (scenario instanceof ScenarioOutlineBridge) {
264
+ accumulator.push(...failedOutline(scenario));
265
+ } else if (!scenario.report.passed) {
266
+ accumulator.push(scenario);
267
+ }
268
+ }
269
+ }
270
+ return accumulator;
271
+ }
272
+ function gherkinToTestNames(node, path = "", accumulator = []) {
273
+ if (!("name" in node) || node instanceof Background) {
274
+ return;
275
+ }
276
+ const title = `${node.keyword}: ${node.name}`;
277
+ const fullPath = path ? `${path} ${title}` : title;
278
+ accumulator.push(fullPath);
279
+ if (!node.children) {
280
+ return;
281
+ }
282
+ for (const child of node.children) {
283
+ if (!("name" in child) || child instanceof Background) {
284
+ continue;
285
+ }
286
+ gherkinToTestNames(child, fullPath, accumulator);
287
+ }
288
+ return accumulator;
289
+ }
290
+ var Query = {
291
+ find: {
292
+ failed
293
+ },
294
+ testNames: gherkinToTestNames
295
+ };
296
+
297
+ // src/gherkin-walker.ts
298
+ import {
299
+ Background as Background2,
300
+ Examples,
301
+ Feature,
302
+ Rule,
303
+ Scenario,
304
+ ScenarioOutline,
305
+ Step
306
+ } from "@autometa/gherkin";
307
+ import { AutomationError as AutomationError2 } from "@autometa/errors";
308
+ import { Example } from "@autometa/gherkin";
309
+ var _walkNode, walkNode_fn, _walkChildren, walkChildren_fn;
310
+ var GherkinWalker = class {
311
+ static walk(walkFunction, childNode, accumulator, parentNode) {
312
+ if (accumulator === void 0) {
313
+ throw new AutomationError2(
314
+ `An accumulator must be defined to continue the walker from ${childNode.constructor.name}${JSON.stringify(childNode)}`
315
+ );
316
+ }
317
+ __privateMethod(this, _walkNode, walkNode_fn).call(this, childNode, accumulator, walkFunction, parentNode);
318
+ return accumulator;
319
+ }
320
+ };
321
+ _walkNode = new WeakSet();
322
+ walkNode_fn = function(child, accumulator, walkFunction, lastNode) {
323
+ if (child instanceof Feature && walkFunction.onFeature) {
324
+ const acc = walkFunction.onFeature(child, accumulator, lastNode);
325
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
326
+ }
327
+ if (child instanceof Rule && walkFunction.onRule) {
328
+ const acc = walkFunction.onRule(child, accumulator, lastNode);
329
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
330
+ }
331
+ if (child instanceof Examples) {
332
+ const acc = walkFunction.onExamples?.(child, accumulator, lastNode);
333
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
334
+ }
335
+ if (child instanceof Example) {
336
+ const acc = walkFunction.onExample?.(child, accumulator, lastNode);
337
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
338
+ }
339
+ if (child instanceof Scenario) {
340
+ const acc = walkFunction.onScenario?.(child, accumulator, lastNode);
341
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
342
+ }
343
+ if (child instanceof ScenarioOutline) {
344
+ const acc = walkFunction.onScenarioOutline?.(
345
+ child,
346
+ accumulator,
347
+ lastNode
348
+ );
349
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
350
+ }
351
+ if (child instanceof Background2) {
352
+ const acc = walkFunction?.onBackground?.(child, accumulator, lastNode);
353
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
354
+ }
355
+ if (child instanceof Step) {
356
+ const acc = walkFunction.onStep?.(child, accumulator, lastNode);
357
+ return __privateMethod(this, _walkChildren, walkChildren_fn).call(this, child, acc, walkFunction);
358
+ }
359
+ };
360
+ _walkChildren = new WeakSet();
361
+ walkChildren_fn = function(child, accumulator, walkFunction) {
362
+ for (const node of child.children) {
363
+ this.walk(walkFunction, node, accumulator, child);
364
+ }
365
+ };
366
+ __privateAdd(GherkinWalker, _walkNode);
367
+ __privateAdd(GherkinWalker, _walkChildren);
368
+
369
+ // src/scope-search.ts
370
+ import { AutomationError as AutomationError3 } from "@autometa/errors";
371
+ import {
372
+ RuleScope,
373
+ ScenarioScope,
374
+ ScenarioOutlineScope,
375
+ BackgroundScope
376
+ } from "@autometa/scopes";
377
+ import { Empty_Function } from "@autometa/scopes";
378
+ function scope(value) {
379
+ return {
380
+ findRule: (name) => {
381
+ const found = value.closedScopes.find((child) => {
382
+ return child instanceof RuleScope && child.name === name;
383
+ });
384
+ if (!found) {
385
+ const rule = new RuleScope(
386
+ name,
387
+ Empty_Function,
388
+ void 0,
389
+ value.hooks,
390
+ value.steps
391
+ );
392
+ value.attach(rule);
393
+ return rule;
394
+ }
395
+ return found;
396
+ },
397
+ findScenario: (name) => {
398
+ const found = value.closedScopes.find((child) => {
399
+ return child instanceof ScenarioScope && child.name === name && !(child instanceof ScenarioOutlineScope);
400
+ });
401
+ if (!found) {
402
+ const scenario = new ScenarioScope(
403
+ name,
404
+ Empty_Function,
405
+ void 0,
406
+ value.hooks,
407
+ value.steps
408
+ );
409
+ value.attach(scenario);
410
+ return scenario;
411
+ }
412
+ return found;
413
+ },
414
+ findBackground: ({ name }) => {
415
+ const found = value.closedScopes.find((child) => {
416
+ return child instanceof BackgroundScope;
417
+ });
418
+ if (found && found.name !== name) {
419
+ throw new AutomationError3(
420
+ `Could not find background matching ${name} but found ${found?.name}`
421
+ );
422
+ }
423
+ if (found) {
424
+ return found;
425
+ }
426
+ const bgScope = new BackgroundScope(
427
+ name,
428
+ Empty_Function,
429
+ value.hooks,
430
+ value.steps
431
+ );
432
+ value.attach(bgScope);
433
+ return bgScope;
434
+ },
435
+ findScenarioOutline: (name) => {
436
+ const found = value.closedScopes.find((child) => {
437
+ return child instanceof ScenarioOutlineScope && child.name === name;
438
+ });
439
+ if (!found) {
440
+ const scenarioOutline = new ScenarioOutlineScope(
441
+ name,
442
+ Empty_Function,
443
+ void 0,
444
+ value.hooks,
445
+ value.steps
446
+ );
447
+ value.attach(scenarioOutline);
448
+ return scenarioOutline;
449
+ }
450
+ return found;
451
+ },
452
+ findExample(name) {
453
+ const found = value.closedScopes.find((child) => {
454
+ if (!(child instanceof ScenarioScope)) {
455
+ return false;
456
+ }
457
+ return child.name === name;
458
+ });
459
+ if (!found) {
460
+ const scenario = new ScenarioScope(
461
+ name,
462
+ Empty_Function,
463
+ void 0,
464
+ value.hooks,
465
+ value.steps
466
+ );
467
+ value.attach(scenario);
468
+ return scenario;
469
+ }
470
+ return found;
471
+ },
472
+ findStep: (keywordType, keyword, name) => {
473
+ return value.steps.find(keywordType, keyword, name);
474
+ }
475
+ };
476
+ }
477
+
478
+ // src/test-builder.ts
479
+ import { Bind } from "@autometa/bind-decorator";
480
+ import {
481
+ scenarioExampleTitle
482
+ } from "@autometa/gherkin";
483
+ import { raise } from "@autometa/errors";
484
+ var TestBuilder = class {
485
+ constructor(feature) {
486
+ this.feature = feature;
487
+ }
488
+ onFeatureExecuted(featureScope) {
489
+ const bridge = new FeatureBridge();
490
+ GherkinWalker.walk(
491
+ {
492
+ onFeature: (feature, accumulator) => {
493
+ accumulator.data = { gherkin: feature, scope: featureScope };
494
+ return accumulator;
495
+ },
496
+ onRule: (rule, accumulator) => {
497
+ const ruleScope = scope(featureScope).findRule(
498
+ rule.name
499
+ );
500
+ const bridge2 = new RuleBridge();
501
+ bridge2.data = { gherkin: rule, scope: ruleScope };
502
+ accumulator.rules.push(bridge2);
503
+ return bridge2;
504
+ },
505
+ onScenario: (gherkin, accumulator) => {
506
+ const scenarioScope = scope(accumulator.data.scope).findScenario(
507
+ gherkin.name
508
+ );
509
+ const bridge2 = new ScenarioBridge();
510
+ bridge2.data = { gherkin, scope: scenarioScope };
511
+ accumulator.scenarios.push(bridge2);
512
+ return bridge2;
513
+ },
514
+ onScenarioOutline: (gherkin, accumulator) => {
515
+ const outlineScope = scope(
516
+ accumulator.data.scope
517
+ ).findScenarioOutline(gherkin.name);
518
+ const bridge2 = new ScenarioOutlineBridge();
519
+ bridge2.data = { gherkin, scope: outlineScope };
520
+ accumulator.scenarios.push(bridge2);
521
+ return bridge2;
522
+ },
523
+ onExamples: (gherkin, accumulator) => {
524
+ const outlineScope = accumulator.data.scope;
525
+ const bridge2 = new ExamplesBridge();
526
+ bridge2.data = { gherkin, scope: outlineScope };
527
+ accumulator.examples.push(bridge2);
528
+ return bridge2;
529
+ },
530
+ onExample(gherkin, accumulator) {
531
+ if (gherkin.table === void 0) {
532
+ raise(
533
+ `Example ${gherkin.name} has no Example Table data. A Row of data is required.`
534
+ );
535
+ }
536
+ const titleSegments = Object.keys(gherkin.table);
537
+ const values = Object.values(gherkin.table);
538
+ const title = scenarioExampleTitle(
539
+ titleSegments,
540
+ gherkin.name,
541
+ values
542
+ );
543
+ const exampleScope = scope(accumulator.data.scope).findExample(title);
544
+ const bridge2 = new ExampleBridge();
545
+ bridge2.data = { gherkin, scope: exampleScope };
546
+ const acc = accumulator;
547
+ acc.scenarios.push(bridge2);
548
+ return bridge2;
549
+ },
550
+ onBackground(gherkin, accumulator) {
551
+ const backgroundScope = scope(accumulator.data.scope).findBackground({
552
+ name: gherkin.name
553
+ });
554
+ const bridge2 = new BackgroundBridge();
555
+ bridge2.data = { gherkin, scope: backgroundScope };
556
+ const acc = accumulator;
557
+ acc.background = bridge2;
558
+ return bridge2;
559
+ },
560
+ onStep: (step, accumulator) => {
561
+ const {
562
+ data: { scope: parentScope, gherkin }
563
+ } = accumulator;
564
+ const { keyword, keywordType, text } = step;
565
+ const cache = parentScope.steps;
566
+ const existing = getStep(
567
+ accumulator,
568
+ gherkin,
569
+ cache,
570
+ keywordType,
571
+ keyword,
572
+ text
573
+ );
574
+ const bridge2 = new StepBridge();
575
+ const acc = accumulator;
576
+ if (existing) {
577
+ bridge2.data = {
578
+ gherkin: step,
579
+ scope: existing.step,
580
+ args: existing.args
581
+ };
582
+ } else {
583
+ raise(`No step definition matching ${step.keyword} ${step.text}`);
584
+ }
585
+ acc.steps.push(bridge2);
586
+ return accumulator;
587
+ }
588
+ },
589
+ this.feature,
590
+ bridge
591
+ );
592
+ return bridge;
593
+ }
594
+ };
595
+ __decorateClass([
596
+ Bind
597
+ ], TestBuilder.prototype, "onFeatureExecuted", 1);
598
+ function getStep(accumulator, gherkin, cache, keywordType, keyword, text) {
599
+ try {
600
+ if (accumulator instanceof ExampleBridge) {
601
+ const scenario = gherkin;
602
+ if (scenario.table) {
603
+ return cache.findByExample(keywordType, keyword, text, scenario.table);
604
+ }
605
+ }
606
+ return cache.find(keywordType, keyword, text);
607
+ } catch (e) {
608
+ const cause = e;
609
+ const { title } = gherkin;
610
+ raise(
611
+ `'${title}' could not find a step definition`,
612
+ { cause }
613
+ );
614
+ }
615
+ }
3
616
  export {
4
- src_default as default
617
+ BackgroundBridge,
618
+ ExampleBridge,
619
+ ExamplesBridge,
620
+ FeatureBridge,
621
+ GherkinCodeBridge,
622
+ GherkinWalker,
623
+ Query,
624
+ RuleBridge,
625
+ ScenarioBridge,
626
+ ScenarioOutlineBridge,
627
+ StepBridge,
628
+ TestBuilder,
629
+ find,
630
+ findExamplesOrChild,
631
+ findRuleOrChild,
632
+ findRuleTypes,
633
+ findScenario,
634
+ findScenarioOutlineOrChild,
635
+ findTestTypes,
636
+ scope
5
637
  };
638
+ //# sourceMappingURL=index.js.map