@lynxwall/cucumber-tsflow 7.0.0 → 7.1.1
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/README.md +114 -28
- package/lib/behave.js +1 -1
- package/lib/behave.js.map +1 -1
- package/lib/bindings/binding-context.d.ts +1 -1
- package/lib/bindings/binding-context.js.map +1 -1
- package/lib/bindings/binding-decorator.d.ts +1 -1
- package/lib/bindings/binding-decorator.js +1 -1
- package/lib/bindings/binding-decorator.js.map +1 -1
- package/lib/bindings/binding-registry.d.ts +2 -2
- package/lib/bindings/binding-registry.js +1 -1
- package/lib/bindings/binding-registry.js.map +1 -1
- package/lib/bindings/hook-decorators.js +1 -1
- package/lib/bindings/hook-decorators.js.map +1 -1
- package/lib/bindings/step-binding.d.ts +60 -0
- package/lib/bindings/step-binding.js +6 -0
- package/lib/bindings/step-binding.js.map +1 -0
- package/lib/bindings/step-decorators.js +1 -1
- package/lib/bindings/step-decorators.js.map +1 -1
- package/lib/bindings/types.d.ts +72 -0
- package/lib/bindings/types.js +58 -0
- package/lib/bindings/types.js.map +1 -0
- package/lib/formatter/behave-json-formatter.d.ts +49 -0
- package/lib/formatter/behave-json-formatter.js +85 -0
- package/lib/formatter/behave-json-formatter.js.map +1 -0
- package/lib/formatter/junit-bamboo-formatter.d.ts +17 -0
- package/lib/formatter/junit-bamboo-formatter.js +175 -0
- package/lib/formatter/junit-bamboo-formatter.js.map +1 -0
- package/lib/formatter/step-definition-snippit-syntax/tsflow-snippet-syntax.d.ts +9 -0
- package/lib/formatter/step-definition-snippit-syntax/tsflow-snippet-syntax.js +85 -0
- package/lib/formatter/step-definition-snippit-syntax/tsflow-snippet-syntax.js.map +1 -0
- package/lib/index.d.ts +36 -1
- package/lib/index.js +96 -2
- package/lib/index.js.map +1 -1
- package/lib/junitbamboo.js +1 -1
- package/lib/junitbamboo.js.map +1 -1
- package/lib/runtime/managed-scenario-context.d.ts +3 -3
- package/lib/runtime/managed-scenario-context.js +2 -2
- package/lib/runtime/managed-scenario-context.js.map +1 -1
- package/lib/runtime/message-collector.d.ts +1 -1
- package/lib/runtime/message-collector.js.map +1 -1
- package/lib/runtime/scenario-context.d.ts +16 -0
- package/lib/runtime/scenario-context.js +18 -0
- package/lib/runtime/scenario-context.js.map +1 -0
- package/lib/runtime/scenario-info.d.ts +16 -0
- package/lib/runtime/scenario-info.js +23 -0
- package/lib/runtime/scenario-info.js.map +1 -0
- package/lib/runtime/test-case-runner.d.ts +2 -2
- package/lib/runtime/test-case-runner.js +5 -19
- package/lib/runtime/test-case-runner.js.map +1 -1
- package/lib/snippet.js +1 -1
- package/lib/snippet.js.map +1 -1
- package/lib/tsconfig.node.tsbuildinfo +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/lib/wrapper.mjs +35 -0
- package/package.json +5 -8
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Callsite } from '../utils/our-callsite';
|
|
2
|
+
import { StepBindingFlags } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Encapsulates data about a step binding.
|
|
5
|
+
*/
|
|
6
|
+
export interface StepBinding {
|
|
7
|
+
/**
|
|
8
|
+
* The callsite of the step binding.
|
|
9
|
+
*/
|
|
10
|
+
callsite: Callsite;
|
|
11
|
+
/**
|
|
12
|
+
* The typescript 'binding' class that is associated with the current step.
|
|
13
|
+
*/
|
|
14
|
+
classPrototype: any;
|
|
15
|
+
/**
|
|
16
|
+
* The function name that is associated with the current step.
|
|
17
|
+
*/
|
|
18
|
+
classPropertyKey: string | symbol;
|
|
19
|
+
/**
|
|
20
|
+
* Key passed in with options in cucumber step bindings.
|
|
21
|
+
* This property is used to match tsflow step definitions
|
|
22
|
+
* with cucumber step definitions.
|
|
23
|
+
*/
|
|
24
|
+
cucumberKey: string;
|
|
25
|
+
/**
|
|
26
|
+
* The step binding type.
|
|
27
|
+
*/
|
|
28
|
+
bindingType: StepBindingFlags;
|
|
29
|
+
/**
|
|
30
|
+
* The step pattern.
|
|
31
|
+
*/
|
|
32
|
+
stepPattern: RegExp | string;
|
|
33
|
+
/**
|
|
34
|
+
* Function for this step that's passed in from the decorator.
|
|
35
|
+
*/
|
|
36
|
+
stepFunction: Function | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Flag to indicate if the target is static or not.
|
|
39
|
+
* If true than we don't 'apply' to the class instance.
|
|
40
|
+
*/
|
|
41
|
+
stepIsStatic: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The number of arguments for the step, which is captured in
|
|
44
|
+
* the decorator using arguments.length.
|
|
45
|
+
*/
|
|
46
|
+
stepArgsLength: number;
|
|
47
|
+
/**
|
|
48
|
+
* The optional tag(s) that are associated with the current step.
|
|
49
|
+
*/
|
|
50
|
+
tags?: string;
|
|
51
|
+
/**
|
|
52
|
+
* The optiomal timeout that is associated with the current step.
|
|
53
|
+
*/
|
|
54
|
+
timeout?: number;
|
|
55
|
+
/**
|
|
56
|
+
* The wrapper Option passing to cucumber
|
|
57
|
+
*/
|
|
58
|
+
wrapperOption?: any;
|
|
59
|
+
}
|
|
60
|
+
export { StepBindingFlags } from './types';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StepBindingFlags = void 0;
|
|
4
|
+
var types_1 = require("./types");
|
|
5
|
+
Object.defineProperty(exports, "StepBindingFlags", { enumerable: true, get: function () { return types_1.StepBindingFlags; } });
|
|
6
|
+
//# sourceMappingURL=step-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-binding.js","sourceRoot":"","sources":["../../src/bindings/step-binding.ts"],"names":[],"mappings":";;;AAwEA,iCAA2C;AAAlC,yGAAA,gBAAgB,OAAA","sourcesContent":["import { Callsite } from '../utils/our-callsite';\r\nimport { StepBindingFlags } from './types';\r\n\r\n/**\r\n * Encapsulates data about a step binding.\r\n */\r\nexport interface StepBinding {\r\n\t/**\r\n\t * The callsite of the step binding.\r\n\t */\r\n\tcallsite: Callsite;\r\n\r\n\t/**\r\n\t * The typescript 'binding' class that is associated with the current step.\r\n\t */\r\n\tclassPrototype: any;\r\n\r\n\t/**\r\n\t * The function name that is associated with the current step.\r\n\t */\r\n\tclassPropertyKey: string | symbol;\r\n\r\n\t/**\r\n\t * Key passed in with options in cucumber step bindings.\r\n\t * This property is used to match tsflow step definitions\r\n\t * with cucumber step definitions.\r\n\t */\r\n\tcucumberKey: string;\r\n\r\n\t/**\r\n\t * The step binding type.\r\n\t */\r\n\tbindingType: StepBindingFlags;\r\n\r\n\t/**\r\n\t * The step pattern.\r\n\t */\r\n\tstepPattern: RegExp | string;\r\n\r\n\t/**\r\n\t * Function for this step that's passed in from the decorator.\r\n\t */\r\n\tstepFunction: Function | undefined;\r\n\r\n\t/**\r\n\t * Flag to indicate if the target is static or not.\r\n\t * If true than we don't 'apply' to the class instance.\r\n\t */\r\n\tstepIsStatic: boolean;\r\n\r\n\t/**\r\n\t * The number of arguments for the step, which is captured in\r\n\t * the decorator using arguments.length.\r\n\t */\r\n\tstepArgsLength: number;\r\n\r\n\t/**\r\n\t * The optional tag(s) that are associated with the current step.\r\n\t */\r\n\ttags?: string;\r\n\r\n\t/**\r\n\t * The optiomal timeout that is associated with the current step.\r\n\t */\r\n\ttimeout?: number;\r\n\r\n\t/**\r\n\t * The wrapper Option passing to cucumber\r\n\t */\r\n\twrapperOption?: any;\r\n}\r\n\r\nexport { StepBindingFlags } from './types';\r\n"]}
|
|
@@ -7,7 +7,7 @@ exports.given = given;
|
|
|
7
7
|
exports.when = when;
|
|
8
8
|
exports.then = then;
|
|
9
9
|
const our_callsite_1 = require("../utils/our-callsite");
|
|
10
|
-
const step_binding_1 = require("
|
|
10
|
+
const step_binding_1 = require("./step-binding");
|
|
11
11
|
const short_uuid_1 = __importDefault(require("short-uuid"));
|
|
12
12
|
const binding_context_1 = require("./binding-context");
|
|
13
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step-decorators.js","sourceRoot":"","sources":["../../src/bindings/step-decorators.ts"],"names":[],"mappings":";;;;;AAYA,sBAsBC;AASD,oBAsBC;AASD,oBAsBC;AAhGD,wDAAiD;AACjD,
|
|
1
|
+
{"version":3,"file":"step-decorators.js","sourceRoot":"","sources":["../../src/bindings/step-decorators.ts"],"names":[],"mappings":";;;;;AAYA,sBAsBC;AASD,oBAsBC;AASD,oBAsBC;AAhGD,wDAAiD;AACjD,iDAA+D;AAC/D,4DAAmC;AACnC,uDAAmD;AAEnD;;;;;;GAMG;AACH,SAAgB,KAAK,CAAC,WAA4B,EAAE,GAAY,EAAE,OAAgB,EAAE,aAAmB;IACtG,MAAM,QAAQ,GAAG,uBAAQ,CAAC,OAAO,EAAE,CAAC;IAEpC,OAAO,SAAS,cAAc,CAAC,MAAgB,EAAE,OAAoC;QACpF,MAAM,WAAW,GAAgB;YAChC,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,+BAAgB,CAAC,KAAK;YACnC,cAAc,EAAE,SAAS;YACzB,gBAAgB,EAAE,OAAO,CAAC,IAAI;YAC9B,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,OAAO,CAAC,MAAM;YAC5B,cAAc,EAAE,MAAM,CAAC,MAAM;YAC7B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,OAAO;YAChB,aAAa,EAAE,aAAa;YAC5B,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,IAAA,oBAAS,GAAE,CAAC,GAAG,EAAE;SAC9B,CAAC;QACF,IAAA,gCAAc,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAErC,OAAO;IACR,CAAC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,IAAI,CAAC,WAA4B,EAAE,GAAY,EAAE,OAAgB,EAAE,aAAmB;IACrG,MAAM,QAAQ,GAAG,uBAAQ,CAAC,OAAO,EAAE,CAAC;IAEpC,OAAO,SAAS,aAAa,CAAC,MAAgB,EAAE,OAAoC;QACnF,MAAM,WAAW,GAAgB;YAChC,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,+BAAgB,CAAC,IAAI;YAClC,cAAc,EAAE,SAAS;YACzB,gBAAgB,EAAE,OAAO,CAAC,IAAI;YAC9B,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,OAAO,CAAC,MAAM;YAC5B,cAAc,EAAE,MAAM,CAAC,MAAM;YAC7B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,OAAO;YAChB,aAAa,EAAE,aAAa;YAC5B,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,IAAA,oBAAS,GAAE,CAAC,GAAG,EAAE;SAC9B,CAAC;QACF,IAAA,gCAAc,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAErC,OAAO;IACR,CAAC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,IAAI,CAAC,WAA4B,EAAE,GAAY,EAAE,OAAgB,EAAE,aAAmB;IACrG,MAAM,QAAQ,GAAG,uBAAQ,CAAC,OAAO,EAAE,CAAC;IAEpC,OAAO,SAAS,aAAa,CAAC,MAAgB,EAAE,OAAoC;QACnF,MAAM,WAAW,GAAgB;YAChC,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,+BAAgB,CAAC,IAAI;YAClC,cAAc,EAAE,SAAS;YACzB,gBAAgB,EAAE,OAAO,CAAC,IAAI;YAC9B,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,OAAO,CAAC,MAAM;YAC5B,cAAc,EAAE,MAAM,CAAC,MAAM;YAC7B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,OAAO;YAChB,aAAa,EAAE,aAAa;YAC5B,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,IAAA,oBAAS,GAAE,CAAC,GAAG,EAAE;SAC9B,CAAC;QACF,IAAA,gCAAc,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAErC,OAAO;IACR,CAAC,CAAC;AACH,CAAC","sourcesContent":["import { Callsite } from '../utils/our-callsite';\r\nimport { StepBinding, StepBindingFlags } from './step-binding';\r\nimport shortUuid from 'short-uuid';\r\nimport { addStepBinding } from './binding-context';\r\n\r\n/**\r\n * A method decorator that marks the associated function as a 'Given' step.\r\n *\r\n * @param stepPattern The regular expression that will be used to match steps.\r\n * @param tag An optional tag.\r\n * @param timeout An optional timeout.\r\n */\r\nexport function given(stepPattern: RegExp | string, tag?: string, timeout?: number, wrapperOption?: any): any {\r\n\tconst callsite = Callsite.capture();\r\n\r\n\treturn function givenDecorator(target: Function, context: ClassMethodDecoratorContext) {\r\n\t\tconst stepBinding: StepBinding = {\r\n\t\t\tstepPattern: stepPattern,\r\n\t\t\tbindingType: StepBindingFlags.given,\r\n\t\t\tclassPrototype: undefined,\r\n\t\t\tclassPropertyKey: context.name,\r\n\t\t\tstepFunction: target,\r\n\t\t\tstepIsStatic: context.static,\r\n\t\t\tstepArgsLength: target.length,\r\n\t\t\ttags: tag,\r\n\t\t\ttimeout: timeout,\r\n\t\t\twrapperOption: wrapperOption,\r\n\t\t\tcallsite: callsite,\r\n\t\t\tcucumberKey: shortUuid().new()\r\n\t\t};\r\n\t\taddStepBinding(context, stepBinding);\r\n\r\n\t\treturn;\r\n\t};\r\n}\r\n\r\n/**\r\n * A method decorator that marks the associated function as a 'When' step.\r\n *\r\n * @param stepPattern The regular expression that will be used to match steps.\r\n * @param tag An optional tag.\r\n * @param timeout An optional timeout.\r\n */\r\nexport function when(stepPattern: RegExp | string, tag?: string, timeout?: number, wrapperOption?: any): any {\r\n\tconst callsite = Callsite.capture();\r\n\r\n\treturn function whenDecorator(target: Function, context: ClassMethodDecoratorContext) {\r\n\t\tconst stepBinding: StepBinding = {\r\n\t\t\tstepPattern: stepPattern,\r\n\t\t\tbindingType: StepBindingFlags.when,\r\n\t\t\tclassPrototype: undefined,\r\n\t\t\tclassPropertyKey: context.name,\r\n\t\t\tstepFunction: target,\r\n\t\t\tstepIsStatic: context.static,\r\n\t\t\tstepArgsLength: target.length,\r\n\t\t\ttags: tag,\r\n\t\t\ttimeout: timeout,\r\n\t\t\twrapperOption: wrapperOption,\r\n\t\t\tcallsite: callsite,\r\n\t\t\tcucumberKey: shortUuid().new()\r\n\t\t};\r\n\t\taddStepBinding(context, stepBinding);\r\n\r\n\t\treturn;\r\n\t};\r\n}\r\n\r\n/**\r\n * A method decorator that marks the associated function as a 'Then' step.\r\n *\r\n * @param stepPattern The regular expression that will be used to match steps.\r\n * @param tag An optional tag.\r\n * @param timeout An optional timeout.\r\n */\r\nexport function then(stepPattern: RegExp | string, tag?: string, timeout?: number, wrapperOption?: any): any {\r\n\tconst callsite = Callsite.capture();\r\n\r\n\treturn function thenDecorator(target: Function, context: ClassMethodDecoratorContext) {\r\n\t\tconst stepBinding: StepBinding = {\r\n\t\t\tstepPattern: stepPattern,\r\n\t\t\tbindingType: StepBindingFlags.then,\r\n\t\t\tclassPrototype: undefined,\r\n\t\t\tclassPropertyKey: context.name,\r\n\t\t\tstepFunction: target,\r\n\t\t\tstepIsStatic: context.static,\r\n\t\t\tstepArgsLength: target.length,\r\n\t\t\ttags: tag,\r\n\t\t\ttimeout: timeout,\r\n\t\t\twrapperOption: wrapperOption,\r\n\t\t\tcallsite: callsite,\r\n\t\t\tcucumberKey: shortUuid().new()\r\n\t\t};\r\n\t\taddStepBinding(context, stepBinding);\r\n\r\n\t\treturn;\r\n\t};\r\n}\r\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { World } from '@cucumber/cucumber';
|
|
2
|
+
/**
|
|
3
|
+
* A string representation of a [[RegExp]] that defines a Cucumber step pattern.
|
|
4
|
+
*/
|
|
5
|
+
export type StepPattern = string;
|
|
6
|
+
/**
|
|
7
|
+
* A Cucumber tag name.
|
|
8
|
+
*/
|
|
9
|
+
export type TagName = string;
|
|
10
|
+
/**
|
|
11
|
+
* The CucumberJS step binding types.
|
|
12
|
+
*/
|
|
13
|
+
export declare enum StepBindingFlags {
|
|
14
|
+
/**
|
|
15
|
+
* No bindings.
|
|
16
|
+
*/
|
|
17
|
+
none = 0,
|
|
18
|
+
/**
|
|
19
|
+
* A 'Given' step definition binding.
|
|
20
|
+
*/
|
|
21
|
+
given = 1,
|
|
22
|
+
/**
|
|
23
|
+
* A 'When' step definition binding.
|
|
24
|
+
*/
|
|
25
|
+
when = 2,
|
|
26
|
+
/**
|
|
27
|
+
* A 'Then' step definition binding.
|
|
28
|
+
*/
|
|
29
|
+
then = 4,
|
|
30
|
+
/**
|
|
31
|
+
* A 'Before' hook binding.
|
|
32
|
+
*/
|
|
33
|
+
before = 8,
|
|
34
|
+
/**
|
|
35
|
+
* An 'After' hook binding.
|
|
36
|
+
*/
|
|
37
|
+
after = 16,
|
|
38
|
+
/**
|
|
39
|
+
* An 'BeforeAll' hook binding
|
|
40
|
+
*/
|
|
41
|
+
beforeAll = 32,
|
|
42
|
+
/**
|
|
43
|
+
* An 'AfterAll' hook binding
|
|
44
|
+
*/
|
|
45
|
+
afterAll = 64,
|
|
46
|
+
/**
|
|
47
|
+
* An 'BeforeStep' hook binding
|
|
48
|
+
*/
|
|
49
|
+
beforeStep = 128,
|
|
50
|
+
/**
|
|
51
|
+
* An 'AfterStep' hook binding
|
|
52
|
+
*/
|
|
53
|
+
afterStep = 256,
|
|
54
|
+
/**
|
|
55
|
+
* All step definition bindings.
|
|
56
|
+
*/
|
|
57
|
+
StepDefinitions = 7,
|
|
58
|
+
/**
|
|
59
|
+
* All hook bindings.
|
|
60
|
+
*/
|
|
61
|
+
Hooks = 504
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Represents a class that will be injected into a binding class to provide context
|
|
65
|
+
* during the execution of a Cucumber scenario.
|
|
66
|
+
*/
|
|
67
|
+
export interface ContextType {
|
|
68
|
+
/**
|
|
69
|
+
* A default constructor.
|
|
70
|
+
*/
|
|
71
|
+
new (worldObj: World): any;
|
|
72
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StepBindingFlags = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The CucumberJS step binding types.
|
|
6
|
+
*/
|
|
7
|
+
var StepBindingFlags;
|
|
8
|
+
(function (StepBindingFlags) {
|
|
9
|
+
/**
|
|
10
|
+
* No bindings.
|
|
11
|
+
*/
|
|
12
|
+
StepBindingFlags[StepBindingFlags["none"] = 0] = "none";
|
|
13
|
+
/**
|
|
14
|
+
* A 'Given' step definition binding.
|
|
15
|
+
*/
|
|
16
|
+
StepBindingFlags[StepBindingFlags["given"] = 1] = "given";
|
|
17
|
+
/**
|
|
18
|
+
* A 'When' step definition binding.
|
|
19
|
+
*/
|
|
20
|
+
StepBindingFlags[StepBindingFlags["when"] = 2] = "when";
|
|
21
|
+
/**
|
|
22
|
+
* A 'Then' step definition binding.
|
|
23
|
+
*/
|
|
24
|
+
StepBindingFlags[StepBindingFlags["then"] = 4] = "then";
|
|
25
|
+
/**
|
|
26
|
+
* A 'Before' hook binding.
|
|
27
|
+
*/
|
|
28
|
+
StepBindingFlags[StepBindingFlags["before"] = 8] = "before";
|
|
29
|
+
/**
|
|
30
|
+
* An 'After' hook binding.
|
|
31
|
+
*/
|
|
32
|
+
StepBindingFlags[StepBindingFlags["after"] = 16] = "after";
|
|
33
|
+
/**
|
|
34
|
+
* An 'BeforeAll' hook binding
|
|
35
|
+
*/
|
|
36
|
+
StepBindingFlags[StepBindingFlags["beforeAll"] = 32] = "beforeAll";
|
|
37
|
+
/**
|
|
38
|
+
* An 'AfterAll' hook binding
|
|
39
|
+
*/
|
|
40
|
+
StepBindingFlags[StepBindingFlags["afterAll"] = 64] = "afterAll";
|
|
41
|
+
/**
|
|
42
|
+
* An 'BeforeStep' hook binding
|
|
43
|
+
*/
|
|
44
|
+
StepBindingFlags[StepBindingFlags["beforeStep"] = 128] = "beforeStep";
|
|
45
|
+
/**
|
|
46
|
+
* An 'AfterStep' hook binding
|
|
47
|
+
*/
|
|
48
|
+
StepBindingFlags[StepBindingFlags["afterStep"] = 256] = "afterStep";
|
|
49
|
+
/**
|
|
50
|
+
* All step definition bindings.
|
|
51
|
+
*/
|
|
52
|
+
StepBindingFlags[StepBindingFlags["StepDefinitions"] = 7] = "StepDefinitions";
|
|
53
|
+
/**
|
|
54
|
+
* All hook bindings.
|
|
55
|
+
*/
|
|
56
|
+
StepBindingFlags[StepBindingFlags["Hooks"] = 504] = "Hooks";
|
|
57
|
+
})(StepBindingFlags || (exports.StepBindingFlags = StepBindingFlags = {}));
|
|
58
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/bindings/types.ts"],"names":[],"mappings":";;;AAcA;;GAEG;AACH,IAAY,gBAiEX;AAjED,WAAY,gBAAgB;IAC3B;;OAEG;IACH,uDAAQ,CAAA;IAER;;OAEG;IACH,yDAAc,CAAA;IAEd;;OAEG;IACH,uDAAa,CAAA;IAEb;;OAEG;IACH,uDAAa,CAAA;IAEb;;OAEG;IACH,2DAAe,CAAA;IAEf;;OAEG;IACH,0DAAc,CAAA;IAEd;;OAEG;IACH,kEAAkB,CAAA;IAElB;;OAEG;IACH,gEAAiB,CAAA;IAEjB;;OAEG;IACH,qEAAmB,CAAA;IAEnB;;OAEG;IACH,mEAAkB,CAAA;IAElB;;OAEG;IACH,6EAAwF,CAAA;IAExF;;OAEG;IACH,2DAK2B,CAAA;AAC5B,CAAC,EAjEW,gBAAgB,gCAAhB,gBAAgB,QAiE3B","sourcesContent":["// tslint:disable:no-bitwise\r\nimport { World } from '@cucumber/cucumber';\r\nimport { Callsite } from '../utils/our-callsite';\r\n\r\n/**\r\n * A string representation of a [[RegExp]] that defines a Cucumber step pattern.\r\n */\r\nexport type StepPattern = string;\r\n\r\n/**\r\n * A Cucumber tag name.\r\n */\r\nexport type TagName = string;\r\n\r\n/**\r\n * The CucumberJS step binding types.\r\n */\r\nexport enum StepBindingFlags {\r\n\t/**\r\n\t * No bindings.\r\n\t */\r\n\tnone = 0,\r\n\r\n\t/**\r\n\t * A 'Given' step definition binding.\r\n\t */\r\n\tgiven = 1 << 0,\r\n\r\n\t/**\r\n\t * A 'When' step definition binding.\r\n\t */\r\n\twhen = 1 << 1,\r\n\r\n\t/**\r\n\t * A 'Then' step definition binding.\r\n\t */\r\n\tthen = 1 << 2,\r\n\r\n\t/**\r\n\t * A 'Before' hook binding.\r\n\t */\r\n\tbefore = 1 << 3,\r\n\r\n\t/**\r\n\t * An 'After' hook binding.\r\n\t */\r\n\tafter = 1 << 4,\r\n\r\n\t/**\r\n\t * An 'BeforeAll' hook binding\r\n\t */\r\n\tbeforeAll = 1 << 5,\r\n\r\n\t/**\r\n\t * An 'AfterAll' hook binding\r\n\t */\r\n\tafterAll = 1 << 6,\r\n\r\n\t/**\r\n\t * An 'BeforeStep' hook binding\r\n\t */\r\n\tbeforeStep = 1 << 7,\r\n\r\n\t/**\r\n\t * An 'AfterStep' hook binding\r\n\t */\r\n\tafterStep = 1 << 8,\r\n\r\n\t/**\r\n\t * All step definition bindings.\r\n\t */\r\n\tStepDefinitions = StepBindingFlags.given | StepBindingFlags.when | StepBindingFlags.then,\r\n\r\n\t/**\r\n\t * All hook bindings.\r\n\t */\r\n\tHooks = StepBindingFlags.before |\r\n\t\tStepBindingFlags.after |\r\n\t\tStepBindingFlags.beforeAll |\r\n\t\tStepBindingFlags.afterAll |\r\n\t\tStepBindingFlags.beforeStep |\r\n\t\tStepBindingFlags.afterStep\r\n}\r\n\r\n/**\r\n * Represents a class that will be injected into a binding class to provide context\r\n * during the execution of a Cucumber scenario.\r\n */\r\nexport interface ContextType {\r\n\t/**\r\n\t * A default constructor.\r\n\t */\r\n\tnew (worldObj: World): any;\r\n}\r\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as messages from '@cucumber/messages';
|
|
2
|
+
import JsonFormatter from '@cucumber/cucumber/lib/formatter/json_formatter';
|
|
3
|
+
export interface IJsonFeature {
|
|
4
|
+
description: string;
|
|
5
|
+
elements: IJsonScenario[];
|
|
6
|
+
id: string;
|
|
7
|
+
keyword: string;
|
|
8
|
+
line: number;
|
|
9
|
+
name: string;
|
|
10
|
+
tags: IJsonTag[];
|
|
11
|
+
uri: string;
|
|
12
|
+
}
|
|
13
|
+
export interface IJsonScenario {
|
|
14
|
+
description: string;
|
|
15
|
+
id: string;
|
|
16
|
+
keyword: string;
|
|
17
|
+
line: number;
|
|
18
|
+
name: string;
|
|
19
|
+
steps: IJsonStep[];
|
|
20
|
+
tags: IJsonTag[];
|
|
21
|
+
type: string;
|
|
22
|
+
}
|
|
23
|
+
export interface IJsonStep {
|
|
24
|
+
arguments?: any;
|
|
25
|
+
embeddings?: any;
|
|
26
|
+
hidden?: boolean;
|
|
27
|
+
keyword?: string;
|
|
28
|
+
line?: number;
|
|
29
|
+
match?: any;
|
|
30
|
+
name?: string;
|
|
31
|
+
result?: any;
|
|
32
|
+
}
|
|
33
|
+
export interface IJsonTag {
|
|
34
|
+
name: string;
|
|
35
|
+
line: number;
|
|
36
|
+
}
|
|
37
|
+
interface IBuildJsonStepOptions {
|
|
38
|
+
isBeforeHook: boolean;
|
|
39
|
+
gherkinStepMap: Record<string, messages.Step>;
|
|
40
|
+
pickleStepMap: Record<string, messages.PickleStep>;
|
|
41
|
+
testStep: messages.TestStep;
|
|
42
|
+
testStepAttachments: messages.Attachment[];
|
|
43
|
+
testStepResult: messages.TestStepResult;
|
|
44
|
+
}
|
|
45
|
+
export default class BehaveJsonFormatter extends JsonFormatter {
|
|
46
|
+
static readonly documentation: string;
|
|
47
|
+
getStepData({ isBeforeHook, gherkinStepMap, pickleStepMap, testStep, testStepAttachments, testStepResult }: IBuildJsonStepOptions): IJsonStep;
|
|
48
|
+
}
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const index_1 = require("@cucumber/cucumber/lib/formatter/helpers/index");
|
|
40
|
+
const messages = __importStar(require("@cucumber/messages"));
|
|
41
|
+
const value_checker_1 = require("@cucumber/cucumber/lib/value_checker");
|
|
42
|
+
const json_formatter_1 = __importDefault(require("@cucumber/cucumber/lib/formatter/json_formatter"));
|
|
43
|
+
const { getStepKeyword } = index_1.PickleParser;
|
|
44
|
+
class BehaveJsonFormatter extends json_formatter_1.default {
|
|
45
|
+
static documentation = 'Prints the feature as JSON that can be used with Behave Pro';
|
|
46
|
+
getStepData({ isBeforeHook, gherkinStepMap, pickleStepMap, testStep, testStepAttachments, testStepResult }) {
|
|
47
|
+
const data = {};
|
|
48
|
+
if ((0, value_checker_1.doesHaveValue)(testStep.pickleStepId)) {
|
|
49
|
+
const pickleStep = pickleStepMap[testStep.pickleStepId];
|
|
50
|
+
data.arguments = this.formatStepArgument(pickleStep.argument, gherkinStepMap[pickleStep.astNodeIds[0]]);
|
|
51
|
+
data.keyword = getStepKeyword({ pickleStep, gherkinStepMap });
|
|
52
|
+
data.line = gherkinStepMap[pickleStep.astNodeIds[0]].location.line;
|
|
53
|
+
data.name = pickleStep.text;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
data.keyword = isBeforeHook ? 'Before' : 'After';
|
|
57
|
+
data.hidden = true;
|
|
58
|
+
data.name = '';
|
|
59
|
+
}
|
|
60
|
+
if ((0, value_checker_1.doesHaveValue)(testStep.stepDefinitionIds) && testStep.stepDefinitionIds?.length === 1) {
|
|
61
|
+
const stepDefinitionId = testStep.stepDefinitionIds[0];
|
|
62
|
+
const stepDefinition = this.supportCodeLibrary.stepDefinitions.find(s => s.id === stepDefinitionId);
|
|
63
|
+
data.match = { location: (0, index_1.formatLocation)(stepDefinition) };
|
|
64
|
+
}
|
|
65
|
+
const { message, status } = testStepResult;
|
|
66
|
+
data.result = {
|
|
67
|
+
status: messages.TestStepResultStatus[status].toLowerCase()
|
|
68
|
+
};
|
|
69
|
+
if ((0, value_checker_1.doesHaveValue)(testStepResult.duration)) {
|
|
70
|
+
data.result.duration = messages.TimeConversion.durationToMilliseconds(testStepResult.duration) * 1000000;
|
|
71
|
+
}
|
|
72
|
+
if (status === messages.TestStepResultStatus.FAILED && (0, value_checker_1.doesHaveValue)(message)) {
|
|
73
|
+
data.result.error_message = message;
|
|
74
|
+
}
|
|
75
|
+
if (testStepAttachments?.length > 0) {
|
|
76
|
+
data.embeddings = testStepAttachments.map(attachment => ({
|
|
77
|
+
data: attachment.body,
|
|
78
|
+
mime_type: attachment.mediaType
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
return data;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = BehaveJsonFormatter;
|
|
85
|
+
//# sourceMappingURL=behave-json-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behave-json-formatter.js","sourceRoot":"","sources":["../../src/formatter/behave-json-formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatLocation, PickleParser } from '@cucumber/cucumber/lib/formatter/helpers/index';\r\nimport * as messages from '@cucumber/messages';\r\nimport { doesHaveValue } from '@cucumber/cucumber/lib/value_checker';\r\nimport JsonFormatter from '@cucumber/cucumber/lib/formatter/json_formatter';\r\nimport { ILineAndUri } from '@cucumber/cucumber/lib/types/index';\r\nconst { getStepKeyword } = PickleParser;\r\n\r\nexport interface IJsonFeature {\r\n\tdescription: string;\r\n\telements: IJsonScenario[];\r\n\tid: string;\r\n\tkeyword: string;\r\n\tline: number;\r\n\tname: string;\r\n\ttags: IJsonTag[];\r\n\turi: string;\r\n}\r\n\r\nexport interface IJsonScenario {\r\n\tdescription: string;\r\n\tid: string;\r\n\tkeyword: string;\r\n\tline: number;\r\n\tname: string;\r\n\tsteps: IJsonStep[];\r\n\ttags: IJsonTag[];\r\n\ttype: string;\r\n}\r\n\r\nexport interface IJsonStep {\r\n\targuments?: any; // TODO\r\n\tembeddings?: any; // TODO\r\n\thidden?: boolean;\r\n\tkeyword?: string; // TODO, not optional\r\n\tline?: number;\r\n\tmatch?: any; // TODO\r\n\tname?: string;\r\n\tresult?: any; // TODO\r\n}\r\n\r\nexport interface IJsonTag {\r\n\tname: string;\r\n\tline: number;\r\n}\r\ninterface IBuildJsonStepOptions {\r\n\tisBeforeHook: boolean;\r\n\tgherkinStepMap: Record<string, messages.Step>;\r\n\tpickleStepMap: Record<string, messages.PickleStep>;\r\n\ttestStep: messages.TestStep;\r\n\ttestStepAttachments: messages.Attachment[];\r\n\ttestStepResult: messages.TestStepResult;\r\n}\r\nexport default class BehaveJsonFormatter extends JsonFormatter {\r\n\tpublic static readonly documentation: string = 'Prints the feature as JSON that can be used with Behave Pro';\r\n\r\n\tgetStepData({\r\n\t\tisBeforeHook,\r\n\t\tgherkinStepMap,\r\n\t\tpickleStepMap,\r\n\t\ttestStep,\r\n\t\ttestStepAttachments,\r\n\t\ttestStepResult\r\n\t}: IBuildJsonStepOptions): IJsonStep {\r\n\t\tconst data: IJsonStep = {};\r\n\t\tif (doesHaveValue(testStep.pickleStepId)) {\r\n\t\t\tconst pickleStep = pickleStepMap[testStep.pickleStepId as string];\r\n\t\t\tdata.arguments = this.formatStepArgument(\r\n\t\t\t\tpickleStep.argument as messages.PickleStepArgument,\r\n\t\t\t\tgherkinStepMap[pickleStep.astNodeIds[0]]\r\n\t\t\t);\r\n\t\t\tdata.keyword = getStepKeyword({ pickleStep, gherkinStepMap });\r\n\t\t\tdata.line = gherkinStepMap[pickleStep.astNodeIds[0]].location.line;\r\n\t\t\tdata.name = pickleStep.text;\r\n\t\t} else {\r\n\t\t\tdata.keyword = isBeforeHook ? 'Before' : 'After';\r\n\t\t\tdata.hidden = true;\r\n\t\t\tdata.name = '';\r\n\t\t}\r\n\t\tif (doesHaveValue(testStep.stepDefinitionIds) && testStep.stepDefinitionIds?.length === 1) {\r\n\t\t\tconst stepDefinitionId = testStep.stepDefinitionIds[0];\r\n\t\t\tconst stepDefinition = this.supportCodeLibrary.stepDefinitions.find(s => s.id === stepDefinitionId);\r\n\t\t\tdata.match = { location: formatLocation(stepDefinition as ILineAndUri) };\r\n\t\t}\r\n\t\tconst { message, status } = testStepResult;\r\n\t\tdata.result = {\r\n\t\t\tstatus: messages.TestStepResultStatus[status].toLowerCase()\r\n\t\t};\r\n\t\tif (doesHaveValue(testStepResult.duration)) {\r\n\t\t\tdata.result.duration = messages.TimeConversion.durationToMilliseconds(testStepResult.duration) * 1000000;\r\n\t\t}\r\n\t\tif (status === messages.TestStepResultStatus.FAILED && doesHaveValue(message)) {\r\n\t\t\tdata.result.error_message = message;\r\n\t\t}\r\n\t\tif (testStepAttachments?.length > 0) {\r\n\t\t\tdata.embeddings = testStepAttachments.map(attachment => ({\r\n\t\t\t\tdata: attachment.body,\r\n\t\t\t\tmime_type: attachment.mediaType\r\n\t\t\t}));\r\n\t\t}\r\n\t\treturn data;\r\n\t}\r\n}\r\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Formatter, IFormatterOptions } from '@cucumber/cucumber';
|
|
2
|
+
export default class JunitBambooFormatter extends Formatter {
|
|
3
|
+
private readonly names;
|
|
4
|
+
private readonly suiteName;
|
|
5
|
+
static readonly documentation: string;
|
|
6
|
+
constructor(options: IFormatterOptions);
|
|
7
|
+
private getTestCases;
|
|
8
|
+
private getTestSteps;
|
|
9
|
+
private getTestStep;
|
|
10
|
+
private getTestCaseResult;
|
|
11
|
+
private durationToSeconds;
|
|
12
|
+
private nameOrDefault;
|
|
13
|
+
private getTestCaseName;
|
|
14
|
+
private formatTestSteps;
|
|
15
|
+
private onTestRunFinished;
|
|
16
|
+
private buildXmlReport;
|
|
17
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const xmlbuilder_1 = __importDefault(require("xmlbuilder"));
|
|
7
|
+
const messages_1 = require("@cucumber/messages");
|
|
8
|
+
const value_checker_1 = require("@cucumber/cucumber/lib/value_checker");
|
|
9
|
+
const pickle_parser_1 = require("@cucumber/cucumber/lib/formatter/helpers/pickle_parser");
|
|
10
|
+
const gherkin_document_parser_1 = require("@cucumber/cucumber/lib/formatter/helpers/gherkin_document_parser");
|
|
11
|
+
const cucumber_1 = require("@cucumber/cucumber");
|
|
12
|
+
class JunitBambooFormatter extends cucumber_1.Formatter {
|
|
13
|
+
names = {};
|
|
14
|
+
suiteName;
|
|
15
|
+
static documentation = 'Outputs JUnit report';
|
|
16
|
+
constructor(options) {
|
|
17
|
+
super(options);
|
|
18
|
+
this.suiteName = (0, value_checker_1.valueOrDefault)(options.parsedArgvOptions.junit?.suiteName, 'cucumber-js');
|
|
19
|
+
options.eventBroadcaster.on('envelope', (envelope) => {
|
|
20
|
+
if ((0, value_checker_1.doesHaveValue)(envelope.testRunFinished)) {
|
|
21
|
+
this.onTestRunFinished();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
getTestCases() {
|
|
26
|
+
return this.eventDataCollector.getTestCaseAttempts().filter(attempt => !attempt.willBeRetried);
|
|
27
|
+
}
|
|
28
|
+
getTestSteps(testCaseAttempt, gherkinStepMap, pickleStepMap) {
|
|
29
|
+
return testCaseAttempt.testCase.testSteps.map(testStep => {
|
|
30
|
+
const isBeforeHook = !(0, value_checker_1.doesHaveValue)(testStep.pickleStepId);
|
|
31
|
+
return this.getTestStep({
|
|
32
|
+
isBeforeHook,
|
|
33
|
+
gherkinStepMap,
|
|
34
|
+
pickleStepMap,
|
|
35
|
+
testStep,
|
|
36
|
+
testStepAttachments: testCaseAttempt.stepAttachments[testStep.id],
|
|
37
|
+
testStepResult: testCaseAttempt.stepResults[testStep.id]
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
getTestStep({ isBeforeHook, gherkinStepMap, pickleStepMap, testStep, testStepAttachments, testStepResult }) {
|
|
42
|
+
const data = {};
|
|
43
|
+
if (testStep.pickleStepId) {
|
|
44
|
+
const pickleStep = pickleStepMap[testStep.pickleStepId];
|
|
45
|
+
data.keyword = (0, pickle_parser_1.getStepKeyword)({ pickleStep, gherkinStepMap });
|
|
46
|
+
data.line = gherkinStepMap[pickleStep.astNodeIds[0]].location.line;
|
|
47
|
+
data.name = pickleStep.text;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
data.keyword = isBeforeHook ? 'Before' : 'After';
|
|
51
|
+
data.hidden = true;
|
|
52
|
+
}
|
|
53
|
+
data.result = testStepResult;
|
|
54
|
+
data.time = testStepResult.duration ? this.durationToSeconds(testStepResult.duration) : 0;
|
|
55
|
+
data.attachments = testStepAttachments;
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
getTestCaseResult(steps) {
|
|
59
|
+
const { status, message, exception } = (0, messages_1.getWorstTestStepResult)(steps.map(step => step.result));
|
|
60
|
+
return {
|
|
61
|
+
status,
|
|
62
|
+
failure: message || exception
|
|
63
|
+
? {
|
|
64
|
+
type: exception?.type,
|
|
65
|
+
message: exception?.message,
|
|
66
|
+
detail: message
|
|
67
|
+
}
|
|
68
|
+
: undefined
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
durationToSeconds(duration) {
|
|
72
|
+
const NANOS_IN_SECOND = 1_000_000_000;
|
|
73
|
+
return (duration.seconds * NANOS_IN_SECOND + duration.nanos) / NANOS_IN_SECOND;
|
|
74
|
+
}
|
|
75
|
+
nameOrDefault(name, fallbackSuffix) {
|
|
76
|
+
if (!name) {
|
|
77
|
+
return `(unnamed ${fallbackSuffix})`;
|
|
78
|
+
}
|
|
79
|
+
return name;
|
|
80
|
+
}
|
|
81
|
+
getTestCaseName(feature, rule, pickle) {
|
|
82
|
+
const featureName = this.nameOrDefault(feature.name, 'feature');
|
|
83
|
+
const pickleName = this.nameOrDefault(pickle.name, 'scenario');
|
|
84
|
+
const testCaseName = rule ? this.nameOrDefault(rule.name, 'rule') + ': ' + pickleName : pickleName;
|
|
85
|
+
if (!this.names[featureName]) {
|
|
86
|
+
this.names[featureName] = [];
|
|
87
|
+
}
|
|
88
|
+
let index = 0;
|
|
89
|
+
while (this.names[featureName].includes(index > 0 ? `${testCaseName} [${index}]` : testCaseName)) {
|
|
90
|
+
index++;
|
|
91
|
+
}
|
|
92
|
+
const name = index > 0 ? `${testCaseName} [${index}]` : testCaseName;
|
|
93
|
+
this.names[featureName].push(name);
|
|
94
|
+
return name;
|
|
95
|
+
}
|
|
96
|
+
formatTestSteps(steps) {
|
|
97
|
+
return steps
|
|
98
|
+
.filter(step => !step.hidden)
|
|
99
|
+
.map(step => {
|
|
100
|
+
const statusText = step.result.status.toLowerCase();
|
|
101
|
+
const maxLength = 80 - statusText.length - 3;
|
|
102
|
+
const stepText = `${step.keyword}${step.name}`.padEnd(maxLength, '.').substring(0, maxLength);
|
|
103
|
+
return `${stepText}...${statusText}`;
|
|
104
|
+
})
|
|
105
|
+
.join('\n');
|
|
106
|
+
}
|
|
107
|
+
onTestRunFinished() {
|
|
108
|
+
const testCases = this.getTestCases();
|
|
109
|
+
const tests = testCases.map((testCaseAttempt) => {
|
|
110
|
+
const { gherkinDocument, pickle } = testCaseAttempt;
|
|
111
|
+
const { feature } = gherkinDocument;
|
|
112
|
+
const gherkinExampleRuleMap = (0, gherkin_document_parser_1.getGherkinExampleRuleMap)(gherkinDocument);
|
|
113
|
+
const rule = gherkinExampleRuleMap[pickle.astNodeIds[0]];
|
|
114
|
+
const gherkinStepMap = (0, gherkin_document_parser_1.getGherkinStepMap)(gherkinDocument);
|
|
115
|
+
const pickleStepMap = (0, pickle_parser_1.getPickleStepMap)(pickle);
|
|
116
|
+
const steps = this.getTestSteps(testCaseAttempt, gherkinStepMap, pickleStepMap);
|
|
117
|
+
const stepDuration = steps.reduce((total, step) => total + (step.time || 0), 0);
|
|
118
|
+
return {
|
|
119
|
+
classname: this.nameOrDefault(feature?.name ?? '', 'feature'),
|
|
120
|
+
name: this.getTestCaseName(feature ?? {}, rule, pickle),
|
|
121
|
+
time: stepDuration,
|
|
122
|
+
result: this.getTestCaseResult(steps),
|
|
123
|
+
systemOutput: this.formatTestSteps(steps),
|
|
124
|
+
steps
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
const passed = tests.filter(item => item.result.status === messages_1.TestStepResultStatus.PASSED).length;
|
|
128
|
+
const skipped = tests.filter(item => item.result.status === messages_1.TestStepResultStatus.SKIPPED ||
|
|
129
|
+
item.result.status === messages_1.TestStepResultStatus.UNDEFINED ||
|
|
130
|
+
item.result.status === messages_1.TestStepResultStatus.PENDING).length;
|
|
131
|
+
const failures = tests.length - passed - skipped;
|
|
132
|
+
const testSuite = {
|
|
133
|
+
name: this.suiteName,
|
|
134
|
+
tests,
|
|
135
|
+
failures,
|
|
136
|
+
skipped,
|
|
137
|
+
time: tests.reduce((total, test) => total + test.time, 0)
|
|
138
|
+
};
|
|
139
|
+
this.log(this.buildXmlReport(testSuite));
|
|
140
|
+
}
|
|
141
|
+
buildXmlReport(testSuite) {
|
|
142
|
+
const xmlReport = xmlbuilder_1.default
|
|
143
|
+
.create('testsuite', { invalidCharReplacement: '' })
|
|
144
|
+
.att('failures', testSuite.failures)
|
|
145
|
+
.att('skipped', testSuite.skipped)
|
|
146
|
+
.att('name', testSuite.name)
|
|
147
|
+
.att('time', testSuite.time)
|
|
148
|
+
.att('tests', testSuite.tests.length);
|
|
149
|
+
testSuite.tests.forEach(test => {
|
|
150
|
+
const xmlTestCase = xmlReport.ele('testcase', {
|
|
151
|
+
classname: test.classname,
|
|
152
|
+
name: test.name,
|
|
153
|
+
time: test.time
|
|
154
|
+
});
|
|
155
|
+
if (test.result.status === messages_1.TestStepResultStatus.SKIPPED ||
|
|
156
|
+
test.result.status === messages_1.TestStepResultStatus.PENDING ||
|
|
157
|
+
test.result.status === messages_1.TestStepResultStatus.UNDEFINED) {
|
|
158
|
+
xmlTestCase.ele('skipped');
|
|
159
|
+
}
|
|
160
|
+
else if (test.result.status !== messages_1.TestStepResultStatus.PASSED) {
|
|
161
|
+
const xmlFailure = xmlTestCase.ele('failure', {
|
|
162
|
+
type: test.result.failure?.type,
|
|
163
|
+
message: test.result.failure?.message
|
|
164
|
+
});
|
|
165
|
+
if (test.result?.failure) {
|
|
166
|
+
xmlFailure.cdata(test.result.failure.detail);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
xmlTestCase.ele('system-out', {}).cdata(test.systemOutput);
|
|
170
|
+
});
|
|
171
|
+
return xmlReport.end({ pretty: true });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.default = JunitBambooFormatter;
|
|
175
|
+
//# sourceMappingURL=junit-bamboo-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit-bamboo-formatter.js","sourceRoot":"","sources":["../../src/formatter/junit-bamboo-formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import xmlbuilder from 'xmlbuilder';\r\nimport * as messages from '@cucumber/messages';\r\nimport {\r\n\tAttachment,\r\n\tDuration,\r\n\tFeature,\r\n\tgetWorstTestStepResult,\r\n\tPickle,\r\n\tRule,\r\n\tTestStepResult,\r\n\tTestStepResultStatus\r\n} from '@cucumber/messages';\r\nimport { ITestCaseAttempt } from '@cucumber/cucumber/lib/formatter/helpers/event_data_collector';\r\nimport { doesHaveValue, valueOrDefault } from '@cucumber/cucumber/lib/value_checker';\r\nimport { getPickleStepMap, getStepKeyword } from '@cucumber/cucumber/lib/formatter/helpers/pickle_parser';\r\nimport {\r\n\tgetGherkinExampleRuleMap,\r\n\tgetGherkinStepMap\r\n} from '@cucumber/cucumber/lib/formatter/helpers/gherkin_document_parser';\r\nimport { Formatter, IFormatterOptions } from '@cucumber/cucumber';\r\n\r\ninterface IJUnitTestSuite {\r\n\tname: string;\r\n\tfailures: number;\r\n\tskipped: number;\r\n\ttime: number;\r\n\ttests: IJUnitTestCase[];\r\n}\r\n\r\ninterface IJUnitTestCase {\r\n\tclassname: string;\r\n\tname: string;\r\n\ttime: number;\r\n\tresult: IJUnitTestCaseResult;\r\n\tsystemOutput: string;\r\n\tsteps: IJUnitTestStep[];\r\n}\r\n\r\ninterface IJUnitTestCaseFailure {\r\n\ttype: string;\r\n\tmessage?: string;\r\n\tdetail: string;\r\n}\r\n\r\ninterface IJUnitTestCaseResult {\r\n\tstatus: TestStepResultStatus;\r\n\tfailure?: IJUnitTestCaseFailure;\r\n}\r\n\r\ninterface IJUnitTestStep {\r\n\tattachments: Attachment[];\r\n\thidden: boolean;\r\n\tkeyword: string;\r\n\tline: number;\r\n\tname?: string;\r\n\tresult: TestStepResult;\r\n\ttime: number;\r\n}\r\n\r\ninterface IBuildJUnitTestStepOptions {\r\n\tisBeforeHook: boolean;\r\n\tgherkinStepMap: Record<string, messages.Step>;\r\n\tpickleStepMap: Record<string, messages.PickleStep>;\r\n\ttestStep: messages.TestStep;\r\n\ttestStepAttachments: messages.Attachment[];\r\n\ttestStepResult: messages.TestStepResult;\r\n}\r\n\r\nexport default class JunitBambooFormatter extends Formatter {\r\n\tprivate readonly names: Record<string, string[]> = {};\r\n\tprivate readonly suiteName: string;\r\n\tpublic static readonly documentation: string = 'Outputs JUnit report';\r\n\r\n\tconstructor(options: IFormatterOptions) {\r\n\t\tsuper(options);\r\n\t\tthis.suiteName = valueOrDefault(options.parsedArgvOptions.junit?.suiteName, 'cucumber-js');\r\n\t\toptions.eventBroadcaster.on('envelope', (envelope: messages.Envelope) => {\r\n\t\t\tif (doesHaveValue(envelope.testRunFinished)) {\r\n\t\t\t\tthis.onTestRunFinished();\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tprivate getTestCases() {\r\n\t\treturn this.eventDataCollector.getTestCaseAttempts().filter(attempt => !attempt.willBeRetried);\r\n\t}\r\n\r\n\tprivate getTestSteps(\r\n\t\ttestCaseAttempt: ITestCaseAttempt,\r\n\t\tgherkinStepMap: Record<string, messages.Step>,\r\n\t\tpickleStepMap: Record<string, messages.PickleStep>\r\n\t) {\r\n\t\treturn testCaseAttempt.testCase.testSteps.map(testStep => {\r\n\t\t\tconst isBeforeHook = !doesHaveValue(testStep.pickleStepId);\r\n\t\t\treturn this.getTestStep({\r\n\t\t\t\tisBeforeHook,\r\n\t\t\t\tgherkinStepMap,\r\n\t\t\t\tpickleStepMap,\r\n\t\t\t\ttestStep,\r\n\t\t\t\ttestStepAttachments: testCaseAttempt.stepAttachments[testStep.id],\r\n\t\t\t\ttestStepResult: testCaseAttempt.stepResults[testStep.id]\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n\tprivate getTestStep({\r\n\t\tisBeforeHook,\r\n\t\tgherkinStepMap,\r\n\t\tpickleStepMap,\r\n\t\ttestStep,\r\n\t\ttestStepAttachments,\r\n\t\ttestStepResult\r\n\t}: IBuildJUnitTestStepOptions): IJUnitTestStep {\r\n\t\tconst data: Partial<IJUnitTestStep> = {};\r\n\t\tif (testStep.pickleStepId) {\r\n\t\t\tconst pickleStep = pickleStepMap[testStep.pickleStepId];\r\n\t\t\tdata.keyword = getStepKeyword({ pickleStep, gherkinStepMap });\r\n\t\t\tdata.line = gherkinStepMap[pickleStep.astNodeIds[0]].location.line;\r\n\t\t\tdata.name = pickleStep.text;\r\n\t\t} else {\r\n\t\t\tdata.keyword = isBeforeHook ? 'Before' : 'After';\r\n\t\t\tdata.hidden = true;\r\n\t\t}\r\n\t\tdata.result = testStepResult;\r\n\t\tdata.time = testStepResult.duration ? this.durationToSeconds(testStepResult.duration) : 0;\r\n\t\tdata.attachments = testStepAttachments;\r\n\t\treturn data as IJUnitTestStep;\r\n\t}\r\n\r\n\tprivate getTestCaseResult(steps: IJUnitTestStep[]): IJUnitTestCaseResult {\r\n\t\tconst { status, message, exception } = getWorstTestStepResult(steps.map(step => step.result));\r\n\t\treturn {\r\n\t\t\tstatus,\r\n\t\t\tfailure:\r\n\t\t\t\tmessage || exception\r\n\t\t\t\t\t? ({\r\n\t\t\t\t\t\t\ttype: exception?.type,\r\n\t\t\t\t\t\t\tmessage: exception?.message,\r\n\t\t\t\t\t\t\tdetail: message\r\n\t\t\t\t\t\t} as IJUnitTestCaseFailure)\r\n\t\t\t\t\t: undefined\r\n\t\t};\r\n\t}\r\n\r\n\tprivate durationToSeconds(duration: Duration): number {\r\n\t\tconst NANOS_IN_SECOND = 1_000_000_000;\r\n\t\treturn (duration.seconds * NANOS_IN_SECOND + duration.nanos) / NANOS_IN_SECOND;\r\n\t}\r\n\r\n\tprivate nameOrDefault(name: string, fallbackSuffix: string): string {\r\n\t\tif (!name) {\r\n\t\t\treturn `(unnamed ${fallbackSuffix})`;\r\n\t\t}\r\n\t\treturn name;\r\n\t}\r\n\r\n\tprivate getTestCaseName(feature: Feature, rule: Rule | undefined, pickle: Pickle) {\r\n\t\tconst featureName = this.nameOrDefault(feature.name, 'feature');\r\n\t\tconst pickleName = this.nameOrDefault(pickle.name, 'scenario');\r\n\t\tconst testCaseName = rule ? this.nameOrDefault(rule.name, 'rule') + ': ' + pickleName : pickleName;\r\n\t\tif (!this.names[featureName]) {\r\n\t\t\tthis.names[featureName] = [];\r\n\t\t}\r\n\t\tlet index = 0;\r\n\t\twhile (this.names[featureName].includes(index > 0 ? `${testCaseName} [${index}]` : testCaseName)) {\r\n\t\t\tindex++;\r\n\t\t}\r\n\t\tconst name = index > 0 ? `${testCaseName} [${index}]` : testCaseName;\r\n\t\tthis.names[featureName].push(name);\r\n\t\treturn name;\r\n\t}\r\n\r\n\tprivate formatTestSteps(steps: IJUnitTestStep[]): string {\r\n\t\treturn steps\r\n\t\t\t.filter(step => !step.hidden)\r\n\t\t\t.map(step => {\r\n\t\t\t\tconst statusText = step.result.status.toLowerCase();\r\n\t\t\t\tconst maxLength = 80 - statusText.length - 3;\r\n\t\t\t\tconst stepText = `${step.keyword}${step.name}`.padEnd(maxLength, '.').substring(0, maxLength);\r\n\t\t\t\treturn `${stepText}...${statusText}`;\r\n\t\t\t})\r\n\t\t\t.join('\\n');\r\n\t}\r\n\r\n\tprivate onTestRunFinished(): void {\r\n\t\tconst testCases = this.getTestCases();\r\n\r\n\t\tconst tests = testCases.map<IJUnitTestCase>((testCaseAttempt: ITestCaseAttempt) => {\r\n\t\t\tconst { gherkinDocument, pickle } = testCaseAttempt;\r\n\t\t\tconst { feature } = gherkinDocument;\r\n\t\t\tconst gherkinExampleRuleMap = getGherkinExampleRuleMap(gherkinDocument);\r\n\t\t\tconst rule = gherkinExampleRuleMap[pickle.astNodeIds[0]];\r\n\t\t\tconst gherkinStepMap = getGherkinStepMap(gherkinDocument);\r\n\t\t\tconst pickleStepMap = getPickleStepMap(pickle);\r\n\r\n\t\t\tconst steps = this.getTestSteps(testCaseAttempt, gherkinStepMap, pickleStepMap);\r\n\t\t\tconst stepDuration = steps.reduce((total, step) => total + (step.time || 0), 0);\r\n\r\n\t\t\treturn {\r\n\t\t\t\tclassname: this.nameOrDefault(feature?.name ?? '', 'feature'),\r\n\t\t\t\tname: this.getTestCaseName(feature ?? ({} as Feature), rule, pickle),\r\n\t\t\t\ttime: stepDuration,\r\n\t\t\t\tresult: this.getTestCaseResult(steps),\r\n\t\t\t\tsystemOutput: this.formatTestSteps(steps),\r\n\t\t\t\tsteps\r\n\t\t\t};\r\n\t\t});\r\n\r\n\t\tconst passed = tests.filter(item => item.result.status === TestStepResultStatus.PASSED).length;\r\n\t\tconst skipped = tests.filter(\r\n\t\t\titem =>\r\n\t\t\t\titem.result.status === TestStepResultStatus.SKIPPED ||\r\n\t\t\t\titem.result.status === TestStepResultStatus.UNDEFINED ||\r\n\t\t\t\titem.result.status === TestStepResultStatus.PENDING\r\n\t\t).length;\r\n\t\tconst failures = tests.length - passed - skipped;\r\n\r\n\t\tconst testSuite: IJUnitTestSuite = {\r\n\t\t\tname: this.suiteName,\r\n\t\t\ttests,\r\n\t\t\tfailures,\r\n\t\t\tskipped,\r\n\t\t\ttime: tests.reduce((total, test) => total + test.time, 0)\r\n\t\t};\r\n\r\n\t\tthis.log(this.buildXmlReport(testSuite));\r\n\t}\r\n\r\n\tprivate buildXmlReport(testSuite: IJUnitTestSuite): string {\r\n\t\tconst xmlReport = xmlbuilder\r\n\t\t\t.create('testsuite', { invalidCharReplacement: '' })\r\n\t\t\t.att('failures', testSuite.failures)\r\n\t\t\t.att('skipped', testSuite.skipped)\r\n\t\t\t.att('name', testSuite.name)\r\n\t\t\t.att('time', testSuite.time)\r\n\t\t\t.att('tests', testSuite.tests.length);\r\n\t\ttestSuite.tests.forEach(test => {\r\n\t\t\tconst xmlTestCase = xmlReport.ele('testcase', {\r\n\t\t\t\tclassname: test.classname,\r\n\t\t\t\tname: test.name,\r\n\t\t\t\ttime: test.time\r\n\t\t\t});\r\n\t\t\tif (\r\n\t\t\t\ttest.result.status === TestStepResultStatus.SKIPPED ||\r\n\t\t\t\ttest.result.status === TestStepResultStatus.PENDING ||\r\n\t\t\t\ttest.result.status === TestStepResultStatus.UNDEFINED\r\n\t\t\t) {\r\n\t\t\t\txmlTestCase.ele('skipped');\r\n\t\t\t} else if (test.result.status !== TestStepResultStatus.PASSED) {\r\n\t\t\t\tconst xmlFailure = xmlTestCase.ele('failure', {\r\n\t\t\t\t\ttype: test.result.failure?.type,\r\n\t\t\t\t\tmessage: test.result.failure?.message\r\n\t\t\t\t});\r\n\t\t\t\tif (test.result?.failure) {\r\n\t\t\t\t\txmlFailure.cdata(test.result.failure.detail);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\txmlTestCase.ele('system-out', {}).cdata(test.systemOutput);\r\n\t\t});\r\n\r\n\t\treturn xmlReport.end({ pretty: true });\r\n\t}\r\n}\r\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ISnippetSnytax, ISnippetSyntaxBuildOptions, SnippetInterface } from '@cucumber/cucumber/lib/formatter/step_definition_snippet_builder/snippet_syntax';
|
|
2
|
+
/**
|
|
3
|
+
* Generate snippets for tsflow.
|
|
4
|
+
*/
|
|
5
|
+
export default class TsflowSnippetSyntax implements ISnippetSnytax {
|
|
6
|
+
private readonly snippetInterface;
|
|
7
|
+
constructor(snippetInterface: SnippetInterface);
|
|
8
|
+
build({ comment, generatedExpressions, functionName, stepParameterNames }: ISnippetSyntaxBuildOptions): string;
|
|
9
|
+
}
|