@dev-blinq/cucumber-js 1.0.3 → 1.0.5

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 CHANGED
@@ -1,124 +1,68 @@
1
1
  <h1 align="center">
2
- <img src="./docs/images/logo.svg" alt="">
2
+ <img src="./docs/images/icon.png" style="width:150px;height:150px;" alt="">
3
3
  <br>
4
- Cucumber
4
+ Cucumber - Blinq.io
5
5
  </h1>
6
6
  <p align="center">
7
- <b>Automated tests in plain language, for Node.js</b>
7
+ <b>Cucumber.js with Blinq.io adaptation</b>
8
8
  </p>
9
9
 
10
- [![#StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://vshymanskyy.github.io/StandWithUkraine)
11
- [![npm](https://img.shields.io/npm/v/@cucumber/cucumber.svg)](https://www.npmjs.com/package/@cucumber/cucumber)
12
- [![build](https://github.com/cucumber/cucumber-js/workflows/Build/badge.svg)](https://github.com/cucumber/cucumber-js/actions)
13
- [![coverage](https://coveralls.io/repos/github/cucumber/cucumber-js/badge.svg?branch=master)](https://coveralls.io/github/cucumber/cucumber-js?branch=master)
14
- [![backers](https://opencollective.com/cucumber/backers/badge.svg)](https://opencollective.com/cucumber)
15
- [![sponsors](https://opencollective.com/cucumber/sponsors/badge.svg)](https://opencollective.com/cucumber)
16
-
17
- [Cucumber](https://github.com/cucumber) is a tool for running automated tests written in plain language. Because they're
18
- written in plain language, they can be read by anyone on your team. Because they can be
19
- read by anyone, you can use them to help improve communication, collaboration and trust on
20
- your team.
21
-
22
- This is the JavaScript implementation of Cucumber. It runs on [maintained versions](https://github.com/nodejs/Release) of Node.js. You can [quickly try it via CodeSandbox](https://codesandbox.io/s/cucumber-js-demo-2p3vrl?file=/features/greeting.feature), or read on to get started locally in a couple of minutes.
23
-
24
- Looking to contribute? Read our [code of conduct](https://github.com/cucumber/.github/blob/main/CODE_OF_CONDUCT.md) first, then check the [contributing guide](./CONTRIBUTING.md) to get up and running.
10
+ We took the regular old [Cucumber](https://github.com/cucumber) (A tool for running automated tests) and made improvements
11
+ that could be helpful when working with data that should be saved or when we want to generate fake data for testing
12
+ purposes in our Gherkin feature file.
25
13
 
26
14
  ## Install
27
15
 
28
- Cucumber is [available on npm](https://www.npmjs.com/package/@cucumber/cucumber):
16
+ @dev-blinq/cucumber-js is [available on npm](https://www.npmjs.com/package/@dev-blinq/cucumber-js):
29
17
 
30
18
  ```shell
31
- $ npm install @cucumber/cucumber
19
+ $ npm install @dev-blinq/cucumber-js
32
20
  ```
33
21
 
34
22
  ## Get Started
35
23
 
36
- Let's take this example of something to test:
37
-
38
-
39
- First, write your main code in `src/index.js`:
40
-
41
- ```js
42
- class Greeter {
43
- sayHello() {
44
- return 'hello'
45
- }
46
- }
47
-
48
- module.exports = {
49
- Greeter
50
- }
51
- ```
52
-
53
- Then, write your feature in `features/greeting.feature`:
24
+ Before, we used to write Gherkin feature files like this -
54
25
 
55
26
  ```gherkin
56
- Feature: Greeting
57
-
58
- Scenario: Say hello
59
- When the greeter says hello
60
- Then I should have heard "hello"
27
+ Feature: Github
28
+ Scenario Outline: Create a new repository
29
+ Given Create a new repository name "<repo>"
30
+ Examples:
31
+ | repo
32
+ | random_repo_name
61
33
  ```
62
34
 
63
- Next, implement your steps in `features/support/steps.js`:
35
+ Now, instead of picking a random name by ourselfs, we could fake data using the [faker](https://www.npmjs.com/package/@faker-js/faker) library and get a random value -
64
36
 
65
- ```js
66
- const assert = require('assert')
67
- const { When, Then } = require('@cucumber/cucumber')
68
- const { Greeter } = require('../../src')
69
-
70
- When('the greeter says hello', function () {
71
- this.whatIHeard = new Greeter().sayHello()
72
- });
73
-
74
- Then('I should have heard {string}', function (expectedResponse) {
75
- assert.equal(this.whatIHeard, expectedResponse)
76
- });
37
+ ```gherkin
38
+ Feature: Github
39
+ Scenario Outline: Create a new repository
40
+ Given Create a new repository name "<repo>"
41
+ Examples:
42
+ | repo
43
+ | {{string.alpha(10)}}
77
44
  ```
78
45
 
79
- Finally, run Cucumber:
46
+ We could also save our fake data (or any data really) as a variable for future use using the equals (=) sign -
80
47
 
81
- ```shell
82
- $ npx cucumber-js
48
+ ```gherkin
49
+ Feature: Github
50
+ Scenario Outline: Create a new repository
51
+ Given Create a new repository name "<repo>"
52
+ Examples:
53
+ | repo
54
+ | {{repo=string.alpha(10)}}
55
+
56
+ Scenario Outline: Create a second repository
57
+ Given Create a new repository with the same name as before "<repo>"
58
+ Examples:
59
+ | repo
60
+ | {{repo}}
83
61
  ```
84
62
 
85
- And see the output:
86
-
87
- ![Terminal output showing a successful test run with 1 scenario and 2 steps, all passing](./docs/images/readme-output.png)
88
-
89
- If you learn best by example, we have [a repo with several example projects](https://github.com/cucumber/cucumber-js-examples), that might help you get going.
63
+ In that example, we saved repo as a variable with a value of some fake data and used it again as the second repo
64
+ value, both repos will have the same fake value.
90
65
 
91
66
  ## Documentation
92
67
 
93
- The following documentation is for `main`, which might contain some unreleased features. See [documentation for older versions](./docs/older_versions.md) if you need it.
94
-
95
- * [Installation](./docs/installation.md)
96
- * [CLI](./docs/cli.md)
97
- * [Configuration](./docs/configuration.md)
98
- * Support Code
99
- * [API Reference](./docs/support_files/api_reference.md)
100
- * [Attachments](./docs/support_files/attachments.md)
101
- * [Data Tables](./docs/support_files/data_table_interface.md)
102
- * [Hooks](./docs/support_files/hooks.md)
103
- * [Step Definitions](./docs/support_files/step_definitions.md)
104
- * [Timeouts](./docs/support_files/timeouts.md)
105
- * [World](./docs/support_files/world.md)
106
- * Guides
107
- * [Debugging](./docs/debugging.md)
108
- * [Dry run](./docs/dry_run.md)
109
- * [ES Modules](./docs/esm.md)
110
- * [Failing fast](./docs/fail_fast.md)
111
- * [Filtering which scenarios run](./docs/filtering.md)
112
- * [Formatters for feedback and reporting](./docs/formatters.md)
113
- * [Parallel running for speed](./docs/parallel.md)
114
- * [Profiles for composable configuration](./docs/profiles.md)
115
- * [Rerunning just failures](./docs/rerun.md)
116
- * [Retrying flaky scenarios](./docs/retry.md)
117
- * [JavaScript API for running programmatically](./docs/javascript_api.md)
118
- * [Snippets for undefined steps](./docs/snippets.md)
119
- * [Transpiling (from TypeScript etc)](./docs/transpiling.md)
120
- * [FAQ](./docs/faq.md)
121
-
122
- ## Support
123
-
124
- Support is [available from the community](https://cucumber.io/tools/cucumber-open/support/) if you need it.
68
+ See documentation for the [Blinq.io](https://docs.blinq.io) app.
@@ -0,0 +1,9 @@
1
+ import Formatter, { IFormatterOptions } from '.';
2
+ import { JsonReport } from './helpers/report_generator';
3
+ export default class BVTFormatter extends Formatter {
4
+ private reportGenerator;
5
+ private uploadService;
6
+ constructor(options: IFormatterOptions);
7
+ uploadRun(report: JsonReport): Promise<void>;
8
+ createZip(reportFolder: string | null, report: JsonReport): Promise<string>;
9
+ }
@@ -0,0 +1,62 @@
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 _1 = __importDefault(require("."));
7
+ const report_generator_1 = __importDefault(require("./helpers/report_generator"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const jszip_1 = __importDefault(require("jszip"));
11
+ const form_data_1 = __importDefault(require("form-data"));
12
+ const upload_serivce_1 = require("./helpers/upload_serivce");
13
+ const REPORT_SERVICE_URL = process.env.REPORT_SERVICE_URL;
14
+ const REPORT_SERVICE_TOKEN = process.env.REPORT_SERVICE_TOKEN;
15
+ class BVTFormatter extends _1.default {
16
+ constructor(options) {
17
+ super(options);
18
+ this.reportGenerator = new report_generator_1.default();
19
+ this.uploadService = new upload_serivce_1.RunUploadService(REPORT_SERVICE_URL, REPORT_SERVICE_TOKEN);
20
+ if (!REPORT_SERVICE_URL || !REPORT_SERVICE_TOKEN) {
21
+ throw new Error('REPORT_SERVICE_URL and REPORT_SERVICE_TOKEN must be set');
22
+ }
23
+ options.eventBroadcaster.on('envelope', async (envelope) => {
24
+ this.reportGenerator.handleMessage(envelope);
25
+ if (envelope.testRunFinished) {
26
+ const report = this.reportGenerator.getReport();
27
+ // this.log(JSON.stringify(report, null, 2))
28
+ await this.uploadRun(report);
29
+ }
30
+ });
31
+ }
32
+ async uploadRun(report) {
33
+ const runDoc = await this.uploadService.createRunDocument('test');
34
+ const runDocId = runDoc._id;
35
+ const formData = new form_data_1.default();
36
+ const reportFolder = this.reportGenerator.reportFolder;
37
+ if (!fs_1.default.existsSync(reportFolder)) {
38
+ fs_1.default.mkdirSync(reportFolder);
39
+ }
40
+ const zipPath = await this.createZip(reportFolder, report);
41
+ formData.append(runDocId, fs_1.default.readFileSync(zipPath), 'report.zip');
42
+ await this.uploadService.upload(formData);
43
+ process.exit(0);
44
+ }
45
+ async createZip(reportFolder, report) {
46
+ const zip = new jszip_1.default();
47
+ zip.file('report.json', JSON.stringify(report, null, 2));
48
+ const folder = zip.folder('screenshots');
49
+ const files = fs_1.default.readdirSync(path_1.default.join(reportFolder, 'screenshots'));
50
+ files.forEach((file) => {
51
+ folder.file(file, fs_1.default.readFileSync(path_1.default.join(reportFolder, file)));
52
+ });
53
+ const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' });
54
+ // save zip file
55
+ const zipPath = path_1.default.join(reportFolder, 'report.zip');
56
+ fs_1.default.writeFileSync(zipPath, zipBuffer);
57
+ fs_1.default.writeFileSync(path_1.default.join(reportFolder, 'report.json'), JSON.stringify(report, null, 2));
58
+ return zipPath;
59
+ }
60
+ }
61
+ exports.default = BVTFormatter;
62
+ //# sourceMappingURL=bvt_formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bvt_formatter.js","sourceRoot":"","sources":["../../src/formatter/bvt_formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import * as messages from '@cucumber/messages'\nimport Formatter, { IFormatterOptions } from '.'\nimport ReportGenerator, { JsonReport } from './helpers/report_generator'\nimport path from 'path'\nimport fs from 'fs'\nimport JSZip from 'jszip'\nimport FormData from 'form-data'\nimport { RunUploadService } from './helpers/upload_serivce'\n\nconst REPORT_SERVICE_URL = process.env.REPORT_SERVICE_URL\nconst REPORT_SERVICE_TOKEN = process.env.REPORT_SERVICE_TOKEN\n\nexport default class BVTFormatter extends Formatter {\n private reportGenerator = new ReportGenerator()\n private uploadService = new RunUploadService(\n REPORT_SERVICE_URL,\n REPORT_SERVICE_TOKEN\n )\n constructor(options: IFormatterOptions) {\n super(options)\n if (!REPORT_SERVICE_URL || !REPORT_SERVICE_TOKEN) {\n throw new Error('REPORT_SERVICE_URL and REPORT_SERVICE_TOKEN must be set')\n }\n options.eventBroadcaster.on(\n 'envelope',\n async (envelope: messages.Envelope) => {\n this.reportGenerator.handleMessage(envelope)\n if (envelope.testRunFinished) {\n const report = this.reportGenerator.getReport()\n // this.log(JSON.stringify(report, null, 2))\n await this.uploadRun(report)\n }\n }\n )\n }\n async uploadRun(report: JsonReport) {\n const runDoc = await this.uploadService.createRunDocument('test')\n const runDocId = runDoc._id\n const formData = new FormData()\n const reportFolder = this.reportGenerator.reportFolder\n if (!fs.existsSync(reportFolder)) {\n fs.mkdirSync(reportFolder)\n }\n const zipPath = await this.createZip(reportFolder, report)\n formData.append(runDocId, fs.readFileSync(zipPath), 'report.zip')\n await this.uploadService.upload(formData)\n process.exit(0)\n }\n async createZip(reportFolder: string | null, report: JsonReport) {\n const zip = new JSZip()\n zip.file('report.json', JSON.stringify(report, null, 2))\n const folder = zip.folder('screenshots')\n const files = fs.readdirSync(path.join(reportFolder, 'screenshots'))\n files.forEach((file) => {\n folder.file(file, fs.readFileSync(path.join(reportFolder, file)))\n })\n const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' })\n // save zip file\n const zipPath = path.join(reportFolder, 'report.zip')\n fs.writeFileSync(zipPath, zipBuffer)\n fs.writeFileSync(\n path.join(reportFolder, 'report.json'),\n JSON.stringify(report, null, 2)\n )\n return zipPath\n }\n}\n"]}
@@ -7,16 +7,16 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
7
7
  const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g;
8
8
  let newContent = featureFileContent;
9
9
  let match;
10
- const metches = [];
10
+ const matches = [];
11
11
  // collect all matches
12
12
  while ((match = regexp.exec(featureFileContent)) !== null) {
13
- metches.push(match);
13
+ matches.push(match);
14
14
  }
15
15
  // find all variables in the matches
16
16
  const variables = { ...vars };
17
17
  if (Object.keys(variables).length > 0) {
18
- for (let i = 0; i < metches.length; i++) {
19
- const _match = metches[i];
18
+ for (let i = 0; i < matches.length; i++) {
19
+ const _match = matches[i];
20
20
  const value = _match[1];
21
21
  const variableMatch = variableRegex.exec(value);
22
22
  if (variableMatch !== null) {
@@ -29,8 +29,8 @@ const generateTestData = (featureFileContent, vars, fakeData) => {
29
29
  }
30
30
  }
31
31
  else {
32
- for (let i = 0; i < metches.length; i++) {
33
- const _match = metches[i];
32
+ for (let i = 0; i < matches.length; i++) {
33
+ const _match = matches[i];
34
34
  const value = _match[1];
35
35
  const variableMatch = variableRegex.exec(value);
36
36
  if (variableMatch !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"feature_data_format.js","sourceRoot":"","sources":["../../src/formatter/feature_data_format.ts"],"names":[],"mappings":"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","sourcesContent":["import { faker } from '@faker-js/faker'\n\nconst generateTestData = (\n featureFileContent: string,\n vars?: any,\n fakeData?: {\n var: string\n fake: string\n }[]\n) => {\n const regexp = /\\{\\{([^}]+)\\}\\}/g\n const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g\n let newContent = featureFileContent\n let match: RegExpExecArray\n const metches = []\n // collect all matches\n while ((match = regexp.exec(featureFileContent)) !== null) {\n metches.push(match)\n }\n // find all variables in the matches\n const variables: any = { ...vars }\n\n if (Object.keys(variables).length > 0) {\n for (let i = 0; i < metches.length; i++) {\n const _match = metches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n newContent = newContent.replaceAll(`{{${variable.var}}}`, variable.fake)\n }\n } else {\n for (let i = 0; i < metches.length; i++) {\n const _match = metches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n variables[variableMatch[1]] = {\n var: variableMatch[1],\n toFake: variableMatch[2],\n }\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n const fake = faker.helpers.fake(`{{${variable.toFake}}}`)\n newContent = newContent.replaceAll(`{{${variable.var}}}`, fake)\n variables[key].fake = fake\n }\n }\n\n regexp.lastIndex = 0\n const otherFakeData = []\n const duplicateFakeData = fakeData ? [...fakeData] : []\n let fakeIndex = 0\n\n while ((match = regexp.exec(featureFileContent)) !== null) {\n try {\n const fake =\n duplicateFakeData && duplicateFakeData.length > 0\n ? duplicateFakeData.shift().fake\n : faker.helpers.fake(match[0])\n otherFakeData.push({\n var: match[0],\n fake,\n })\n newContent = newContent.replace(match[0], fake)\n fakeIndex++\n } catch (err) {\n // eslint-disable-next-line no-console\n console.log('unknown faker variable:' + match[0])\n }\n }\n\n return {\n newContent,\n variables,\n otherFakeData,\n changed: newContent !== featureFileContent,\n fakeIndex,\n }\n}\n\n//let result = generateTestData(\"/Users/guyarieli/Documents/GitHub/ai-qa/cucumber_demo/features/create_issues.feature\");\n//console.log(result.newContent);\nexport { generateTestData }\n"]}
1
+ {"version":3,"file":"feature_data_format.js","sourceRoot":"","sources":["../../src/formatter/feature_data_format.ts"],"names":[],"mappings":"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","sourcesContent":["import { faker } from '@faker-js/faker'\n\nconst generateTestData = (\n featureFileContent: string,\n vars?: any,\n fakeData?: {\n var: string\n fake: string\n }[]\n) => {\n const regexp = /\\{\\{([^}]+)\\}\\}/g\n const variableRegex = /^([a-zA-Z0-9_]*)=(.*)/g\n let newContent = featureFileContent\n let match: RegExpExecArray\n const matches = []\n // collect all matches\n while ((match = regexp.exec(featureFileContent)) !== null) {\n matches.push(match)\n }\n // find all variables in the matches\n const variables: any = { ...vars }\n\n if (Object.keys(variables).length > 0) {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n newContent = newContent.replaceAll(`{{${variable.var}}}`, variable.fake)\n }\n } else {\n for (let i = 0; i < matches.length; i++) {\n const _match = matches[i]\n const value = _match[1]\n const variableMatch = variableRegex.exec(value)\n if (variableMatch !== null) {\n variables[variableMatch[1]] = {\n var: variableMatch[1],\n toFake: variableMatch[2],\n }\n newContent = newContent.replaceAll(_match[0], `{{${variableMatch[1]}}}`)\n }\n }\n\n for (const key in variables) {\n const variable = variables[key]\n const fake = faker.helpers.fake(`{{${variable.toFake}}}`)\n newContent = newContent.replaceAll(`{{${variable.var}}}`, fake)\n variables[key].fake = fake\n }\n }\n\n regexp.lastIndex = 0\n const otherFakeData = []\n const duplicateFakeData = fakeData ? [...fakeData] : []\n let fakeIndex = 0\n\n while ((match = regexp.exec(featureFileContent)) !== null) {\n try {\n const fake =\n duplicateFakeData && duplicateFakeData.length > 0\n ? duplicateFakeData.shift().fake\n : faker.helpers.fake(match[0])\n otherFakeData.push({\n var: match[0],\n fake,\n })\n newContent = newContent.replace(match[0], fake)\n fakeIndex++\n } catch (err) {\n // eslint-disable-next-line no-console\n console.log('unknown faker variable:' + match[0])\n }\n }\n\n return {\n newContent,\n variables,\n otherFakeData,\n changed: newContent !== featureFileContent,\n fakeIndex,\n }\n}\n\n//let result = generateTestData(\"/Users/guyarieli/Documents/GitHub/ai-qa/cucumber_demo/features/create_issues.feature\");\n//console.log(result.newContent);\nexport { generateTestData }\n"]}
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const json_formatter_1 = __importDefault(require("../json_formatter"));
7
+ const bvt_formatter_1 = __importDefault(require("../bvt_formatter"));
7
8
  const message_formatter_1 = __importDefault(require("../message_formatter"));
8
9
  const progress_bar_formatter_1 = __importDefault(require("../progress_bar_formatter"));
9
10
  const progress_formatter_1 = __importDefault(require("../progress_formatter"));
@@ -18,6 +19,7 @@ const Formatters = {
18
19
  getFormatters() {
19
20
  return {
20
21
  json: json_formatter_1.default,
22
+ bvt: bvt_formatter_1.default,
21
23
  message: message_formatter_1.default,
22
24
  html: html_formatter_1.default,
23
25
  progress: progress_formatter_1.default,
@@ -1 +1 @@
1
- {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../../src/formatter/helpers/formatters.ts"],"names":[],"mappings":";;;;;AACA,uEAA6C;AAC7C,6EAAmD;AACnD,uFAA4D;AAC5D,+EAAqD;AACrD,yEAA+C;AAC/C,+EAAqD;AACrD,6EAAmD;AACnD,yEAA+C;AAC/C,mFAAwD;AACxD,uEAA6C;AAC7C,yEAA+C;AAE/C,MAAM,UAAU,GAAG;IACjB,aAAa;QACX,OAAO;YACL,IAAI,EAAE,wBAAa;YACnB,OAAO,EAAE,2BAAgB;YACzB,IAAI,EAAE,wBAAa;YACnB,QAAQ,EAAE,4BAAiB;YAC3B,cAAc,EAAE,gCAAoB;YACpC,KAAK,EAAE,yBAAc;YACrB,QAAQ,EAAE,4BAAiB;YAC3B,OAAO,EAAE,2BAAgB;YACzB,KAAK,EAAE,yBAAc;YACrB,YAAY,EAAE,8BAAkB;YAChC,KAAK,EAAE,yBAAc;SACtB,CAAA;IACH,CAAC;IACD,kCAAkC;QAChC,IAAI,mCAAmC,GAAW,EAAE,CAAA;QACpD,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QACvC,KAAK,MAAM,aAAa,IAAI,UAAU,EAAE;YACtC,mCAAmC,IAAI,OAAO,aAAa,KAAK,UAAU,CAAC,aAAa,CAAC,CAAC,aAAa,IAAI,CAAA;SAC5G;QAED,OAAO,mCAAmC,CAAA;IAC5C,CAAC;CACF,CAAA;AAED,kBAAe,UAAU,CAAA","sourcesContent":["import Formatter from '../.'\nimport JsonFormatter from '../json_formatter'\nimport MessageFormatter from '../message_formatter'\nimport ProgressBarFormatter from '../progress_bar_formatter'\nimport ProgressFormatter from '../progress_formatter'\nimport RerunFormatter from '../rerun_formatter'\nimport SnippetsFormatter from '../snippets_formatter'\nimport SummaryFormatter from '../summary_formatter'\nimport UsageFormatter from '../usage_formatter'\nimport UsageJsonFormatter from '../usage_json_formatter'\nimport HtmlFormatter from '../html_formatter'\nimport JunitFormatter from '../junit_formatter'\n\nconst Formatters = {\n getFormatters(): Record<string, typeof Formatter> {\n return {\n json: JsonFormatter,\n message: MessageFormatter,\n html: HtmlFormatter,\n progress: ProgressFormatter,\n 'progress-bar': ProgressBarFormatter,\n rerun: RerunFormatter,\n snippets: SnippetsFormatter,\n summary: SummaryFormatter,\n usage: UsageFormatter,\n 'usage-json': UsageJsonFormatter,\n junit: JunitFormatter,\n }\n },\n buildFormattersDocumentationString(): string {\n let concatanatedFormattersDocumentation: string = ''\n const formatters = this.getFormatters()\n for (const formatterName in formatters) {\n concatanatedFormattersDocumentation += ` ${formatterName}: ${formatters[formatterName].documentation}\\n`\n }\n\n return concatanatedFormattersDocumentation\n },\n}\n\nexport default Formatters\n"]}
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../../src/formatter/helpers/formatters.ts"],"names":[],"mappings":";;;;;AACA,uEAA6C;AAC7C,qEAA2C;AAC3C,6EAAmD;AACnD,uFAA4D;AAC5D,+EAAqD;AACrD,yEAA+C;AAC/C,+EAAqD;AACrD,6EAAmD;AACnD,yEAA+C;AAC/C,mFAAwD;AACxD,uEAA6C;AAC7C,yEAA+C;AAE/C,MAAM,UAAU,GAAG;IACjB,aAAa;QACX,OAAO;YACL,IAAI,EAAE,wBAAa;YACnB,GAAG,EAAE,uBAAY;YACjB,OAAO,EAAE,2BAAgB;YACzB,IAAI,EAAE,wBAAa;YACnB,QAAQ,EAAE,4BAAiB;YAC3B,cAAc,EAAE,gCAAoB;YACpC,KAAK,EAAE,yBAAc;YACrB,QAAQ,EAAE,4BAAiB;YAC3B,OAAO,EAAE,2BAAgB;YACzB,KAAK,EAAE,yBAAc;YACrB,YAAY,EAAE,8BAAkB;YAChC,KAAK,EAAE,yBAAc;SACtB,CAAA;IACH,CAAC;IACD,kCAAkC;QAChC,IAAI,mCAAmC,GAAW,EAAE,CAAA;QACpD,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QACvC,KAAK,MAAM,aAAa,IAAI,UAAU,EAAE;YACtC,mCAAmC,IAAI,OAAO,aAAa,KAAK,UAAU,CAAC,aAAa,CAAC,CAAC,aAAa,IAAI,CAAA;SAC5G;QAED,OAAO,mCAAmC,CAAA;IAC5C,CAAC;CACF,CAAA;AAED,kBAAe,UAAU,CAAA","sourcesContent":["import Formatter from '../.'\nimport JsonFormatter from '../json_formatter'\nimport BVTFormatter from '../bvt_formatter'\nimport MessageFormatter from '../message_formatter'\nimport ProgressBarFormatter from '../progress_bar_formatter'\nimport ProgressFormatter from '../progress_formatter'\nimport RerunFormatter from '../rerun_formatter'\nimport SnippetsFormatter from '../snippets_formatter'\nimport SummaryFormatter from '../summary_formatter'\nimport UsageFormatter from '../usage_formatter'\nimport UsageJsonFormatter from '../usage_json_formatter'\nimport HtmlFormatter from '../html_formatter'\nimport JunitFormatter from '../junit_formatter'\n\nconst Formatters = {\n getFormatters(): Record<string, typeof Formatter> {\n return {\n json: JsonFormatter,\n bvt: BVTFormatter,\n message: MessageFormatter,\n html: HtmlFormatter,\n progress: ProgressFormatter,\n 'progress-bar': ProgressBarFormatter,\n rerun: RerunFormatter,\n snippets: SnippetsFormatter,\n summary: SummaryFormatter,\n usage: UsageFormatter,\n 'usage-json': UsageJsonFormatter,\n junit: JunitFormatter,\n }\n },\n buildFormattersDocumentationString(): string {\n let concatanatedFormattersDocumentation: string = ''\n const formatters = this.getFormatters()\n for (const formatterName in formatters) {\n concatanatedFormattersDocumentation += ` ${formatterName}: ${formatters[formatterName].documentation}\\n`\n }\n\n return concatanatedFormattersDocumentation\n },\n}\n\nexport default Formatters\n"]}
@@ -0,0 +1,91 @@
1
+ import * as messages from '@cucumber/messages';
2
+ type JsonTimestamp = number;
3
+ type JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome';
4
+ type JsonResultUnknown = {
5
+ status: 'UNKNOWN';
6
+ };
7
+ type JsonResultSkipped = {
8
+ status: 'SKIPPED';
9
+ };
10
+ type JsonResultUndefined = {
11
+ status: 'UNDEFINED';
12
+ };
13
+ type JsonResultAmbiguous = {
14
+ status: 'AMBIGUOUS';
15
+ };
16
+ type JsonResultStarted = {
17
+ status: 'STARTED';
18
+ startTime: JsonTimestamp;
19
+ };
20
+ type JsonResultPending = {
21
+ status: 'PENDING';
22
+ startTime: JsonTimestamp;
23
+ endTime: JsonTimestamp;
24
+ };
25
+ type JsonResultPassed = {
26
+ status: 'PASSED';
27
+ startTime: JsonTimestamp;
28
+ endTime: JsonTimestamp;
29
+ };
30
+ type JsonResultFailed = {
31
+ status: 'FAILED';
32
+ startTime: JsonTimestamp;
33
+ endTime: JsonTimestamp;
34
+ message?: string;
35
+ };
36
+ type JsonCommandResult = JsonResultPassed | JsonResultFailed;
37
+ type JsonStepResult = JsonResultUnknown | JsonResultSkipped | JsonResultUndefined | JsonResultAmbiguous | JsonResultStarted | JsonResultPending | JsonResultPassed | JsonResultFailed;
38
+ type JsonTestResult = JsonResultUnknown | JsonResultStarted | JsonResultPassed | JsonResultFailed;
39
+ type JsonReportResult = JsonTestResult;
40
+ type JsonCommand = {
41
+ type: string;
42
+ value?: string;
43
+ text: string;
44
+ screenshotId?: string;
45
+ result: JsonCommandResult;
46
+ };
47
+ type JsonStep = {
48
+ type: JsonStepType;
49
+ text: string;
50
+ commands: JsonCommand[];
51
+ result: JsonStepResult;
52
+ };
53
+ type JsonTestProgress = {
54
+ id: string;
55
+ featureName: string;
56
+ uri: string;
57
+ scenarioName: string;
58
+ parameters: Record<string, string>;
59
+ steps: JsonStep[];
60
+ result: JsonTestResult;
61
+ };
62
+ export type JsonReport = {
63
+ testCases: JsonTestProgress[];
64
+ result: JsonReportResult;
65
+ };
66
+ export default class ReportGenerator {
67
+ private report;
68
+ private gherkinDocumentMap;
69
+ private pickleMap;
70
+ private testCaseMap;
71
+ private testStepMap;
72
+ private stepProgressMap;
73
+ private testProgressMap;
74
+ reportFolder: null | string;
75
+ handleMessage(envelope: messages.Envelope): void;
76
+ getReport(): JsonReport;
77
+ private handleParseError;
78
+ private onGherkinDocument;
79
+ private onPickle;
80
+ private getTimeStamp;
81
+ private onTestRunStarted;
82
+ private onTestCase;
83
+ private onTestCaseStarted;
84
+ private onTestStepStarted;
85
+ private onAttachment;
86
+ private onTestStepFinished;
87
+ private getTestCaseResult;
88
+ private onTestCaseFinished;
89
+ private onTestRunFinished;
90
+ }
91
+ export {};
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class ReportGenerator {
4
+ constructor() {
5
+ this.report = {
6
+ result: {
7
+ status: 'UNKNOWN',
8
+ },
9
+ testCases: [],
10
+ };
11
+ this.gherkinDocumentMap = new Map();
12
+ this.pickleMap = new Map();
13
+ this.testCaseMap = new Map();
14
+ this.testStepMap = new Map();
15
+ this.stepProgressMap = new Map();
16
+ this.testProgressMap = new Map();
17
+ this.reportFolder = null;
18
+ }
19
+ handleMessage(envelope) {
20
+ const type = Object.keys(envelope)[0];
21
+ switch (type) {
22
+ // case "meta": { break}
23
+ // case "source": { break}
24
+ case 'parseError': {
25
+ const parseError = envelope[type];
26
+ this.handleParseError(parseError);
27
+ break;
28
+ }
29
+ case 'gherkinDocument': {
30
+ const doc = envelope[type];
31
+ this.onGherkinDocument(doc);
32
+ break;
33
+ }
34
+ case 'pickle': {
35
+ const pickle = envelope[type];
36
+ this.onPickle(pickle);
37
+ break;
38
+ }
39
+ // case "stepDefinition": { break}
40
+ // case "hook": { break} // Before Hook
41
+ case 'testRunStarted': {
42
+ const testRunStarted = envelope[type];
43
+ this.onTestRunStarted(testRunStarted);
44
+ break;
45
+ }
46
+ case 'testCase': {
47
+ const testCase = envelope[type];
48
+ this.onTestCase(testCase);
49
+ break;
50
+ }
51
+ case 'testCaseStarted': {
52
+ const testCaseStarted = envelope[type];
53
+ this.onTestCaseStarted(testCaseStarted);
54
+ break;
55
+ }
56
+ case 'testStepStarted': {
57
+ const testStepStarted = envelope[type];
58
+ this.onTestStepStarted(testStepStarted);
59
+ break;
60
+ }
61
+ case 'attachment': {
62
+ const attachment = envelope[type];
63
+ this.onAttachment(attachment);
64
+ break;
65
+ }
66
+ case 'testStepFinished': {
67
+ const testStepFinished = envelope[type];
68
+ this.onTestStepFinished(testStepFinished);
69
+ break;
70
+ }
71
+ case 'testCaseFinished': {
72
+ const testCaseFinished = envelope[type];
73
+ this.onTestCaseFinished(testCaseFinished);
74
+ break;
75
+ }
76
+ // case "hook": { break} // After Hook
77
+ case 'testRunFinished': {
78
+ const testRunFinished = envelope[type];
79
+ this.onTestRunFinished(testRunFinished);
80
+ break;
81
+ }
82
+ // case "parameterType" : { break}
83
+ // case "undefinedParameterType": { break}
84
+ }
85
+ }
86
+ getReport() {
87
+ return this.report;
88
+ }
89
+ handleParseError(parseError) {
90
+ const { message, source } = parseError;
91
+ const timestamp = new Date().getTime();
92
+ this.report.result = {
93
+ status: 'FAILED',
94
+ startTime: timestamp,
95
+ endTime: timestamp,
96
+ message: message,
97
+ };
98
+ }
99
+ onGherkinDocument(doc) {
100
+ this.gherkinDocumentMap.set(doc.uri, doc);
101
+ }
102
+ onPickle(pickle) {
103
+ this.pickleMap.set(pickle.id, pickle);
104
+ }
105
+ getTimeStamp(timestamp) {
106
+ return timestamp.seconds * 1000 + timestamp.nanos / 1000000;
107
+ }
108
+ onTestRunStarted(testRunStarted) {
109
+ this.report.result = {
110
+ status: 'STARTED',
111
+ startTime: this.getTimeStamp(testRunStarted.timestamp),
112
+ };
113
+ }
114
+ onTestCase(testCase) {
115
+ this.testCaseMap.set(testCase.id, testCase);
116
+ testCase.testSteps.forEach((testStep) => {
117
+ this.testStepMap.set(testStep.id, testStep);
118
+ });
119
+ }
120
+ onTestCaseStarted(testCaseStarted) {
121
+ const { testCaseId, id, timestamp } = testCaseStarted;
122
+ const testCase = this.testCaseMap.get(testCaseId);
123
+ if (testCase === undefined)
124
+ throw new Error(`testCase with id ${testCaseId} not found`);
125
+ const pickle = this.pickleMap.get(testCase.pickleId);
126
+ if (pickle === undefined)
127
+ throw new Error(`pickle with id ${testCase.pickleId} not found`);
128
+ const doc = this.gherkinDocumentMap.get(pickle.uri);
129
+ if (doc === undefined)
130
+ throw new Error(`gherkinDocument with uri ${pickle.uri} not found`);
131
+ const featureName = doc.feature.name;
132
+ const scenarioName = pickle.name;
133
+ const steps = pickle.steps.map((step) => {
134
+ this.stepProgressMap.set(step.id, {
135
+ type: step.type,
136
+ text: step.text,
137
+ commands: [],
138
+ result: {
139
+ status: 'UNKNOWN',
140
+ },
141
+ });
142
+ return this.stepProgressMap.get(step.id);
143
+ });
144
+ this.testProgressMap.set(id, {
145
+ id,
146
+ uri: pickle.uri,
147
+ featureName,
148
+ scenarioName,
149
+ // TODO: compute parameters
150
+ parameters: {},
151
+ steps,
152
+ result: {
153
+ status: 'STARTED',
154
+ startTime: this.getTimeStamp(timestamp),
155
+ },
156
+ });
157
+ this.report.testCases.push(this.testProgressMap.get(id));
158
+ }
159
+ onTestStepStarted(testStepStarted) {
160
+ const { testStepId, timestamp, testCaseStartedId } = testStepStarted;
161
+ const testStep = this.testStepMap.get(testStepId);
162
+ if (testStep === undefined)
163
+ throw new Error(`testStep with id ${testStepId} not found`);
164
+ if (testStep.pickleStepId === undefined)
165
+ return;
166
+ const stepProgess = this.stepProgressMap.get(testStep.pickleStepId);
167
+ stepProgess.result = {
168
+ status: 'STARTED',
169
+ startTime: this.getTimeStamp(timestamp),
170
+ };
171
+ }
172
+ onAttachment(attachment) {
173
+ const { testCaseStartedId, testStepId, body, mediaType, contentEncoding, fileName, source, url, } = attachment;
174
+ if (mediaType === 'text/plain') {
175
+ this.reportFolder = body.replaceAll('\\', '/');
176
+ }
177
+ const testStep = this.testStepMap.get(testStepId);
178
+ if (testStep.pickleStepId === undefined)
179
+ return;
180
+ const stepProgess = this.stepProgressMap.get(testStep.pickleStepId);
181
+ if (mediaType === 'application/json') {
182
+ const command = JSON.parse(body);
183
+ stepProgess.commands.push(command);
184
+ }
185
+ }
186
+ onTestStepFinished(testStepFinished) {
187
+ const { testStepId, testCaseStartedId, testStepResult, timestamp } = testStepFinished;
188
+ const testStep = this.testStepMap.get(testStepId);
189
+ if (testStep.pickleStepId === undefined)
190
+ return;
191
+ const stepProgess = this.stepProgressMap.get(testStep.pickleStepId);
192
+ const prevStepResult = stepProgess.result;
193
+ stepProgess.result = {
194
+ status: testStepResult.status,
195
+ startTime: prevStepResult.startTime,
196
+ endTime: this.getTimeStamp(timestamp),
197
+ message: testStepResult.message,
198
+ // exception: testStepResult.exception,
199
+ };
200
+ }
201
+ getTestCaseResult(steps) {
202
+ for (const step of steps) {
203
+ switch (step.result.status) {
204
+ case 'FAILED':
205
+ return {
206
+ status: step.result.status,
207
+ message: step.result.message,
208
+ // exception: step.result.exception,
209
+ };
210
+ case 'AMBIGUOUS':
211
+ case 'UNDEFINED':
212
+ case 'PENDING':
213
+ return {
214
+ status: 'FAILED',
215
+ message: `step "${step.text}" is ${step.result.status}`,
216
+ };
217
+ }
218
+ }
219
+ return {
220
+ status: 'PASSED',
221
+ };
222
+ }
223
+ onTestCaseFinished(testCaseFinished) {
224
+ const { testCaseStartedId, timestamp } = testCaseFinished;
225
+ const testProgress = this.testProgressMap.get(testCaseStartedId);
226
+ const prevResult = testProgress.result;
227
+ const steps = Object.values(testProgress.steps);
228
+ const result = this.getTestCaseResult(steps);
229
+ testProgress.result = {
230
+ ...result,
231
+ startTime: prevResult.startTime,
232
+ endTime: this.getTimeStamp(timestamp),
233
+ };
234
+ }
235
+ onTestRunFinished(testRunFinished) {
236
+ const { timestamp, success, exception, message } = testRunFinished;
237
+ const prevResult = this.report.result;
238
+ this.report.result = {
239
+ status: success ? 'PASSED' : 'FAILED',
240
+ startTime: prevResult.startTime,
241
+ endTime: this.getTimeStamp(timestamp),
242
+ message,
243
+ // exception,
244
+ };
245
+ }
246
+ }
247
+ exports.default = ReportGenerator;
248
+ //# sourceMappingURL=report_generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report_generator.js","sourceRoot":"","sources":["../../../src/formatter/helpers/report_generator.ts"],"names":[],"mappings":"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","sourcesContent":["import * as messages from '@cucumber/messages'\n\n// type JsonException = messages.Exception\ntype JsonTimestamp = number //messages.Timestamp\ntype JsonStepType = 'Unknown' | 'Context' | 'Action' | 'Outcome'\n\ntype JsonResultUnknown = {\n status: 'UNKNOWN'\n}\ntype JsonResultSkipped = {\n status: 'SKIPPED'\n}\ntype JsonResultUndefined = {\n status: 'UNDEFINED'\n}\ntype JsonResultAmbiguous = {\n status: 'AMBIGUOUS'\n}\ntype JsonResultStarted = {\n status: 'STARTED'\n startTime: JsonTimestamp\n}\ntype JsonResultPending = {\n status: 'PENDING'\n startTime: JsonTimestamp\n endTime: JsonTimestamp\n}\ntype JsonResultPassed = {\n status: 'PASSED'\n startTime: JsonTimestamp\n endTime: JsonTimestamp\n}\ntype JsonResultFailed = {\n status: 'FAILED'\n startTime: JsonTimestamp\n endTime: JsonTimestamp\n message?: string\n // exception?: JsonException\n}\n\ntype JsonCommandResult = JsonResultPassed | JsonResultFailed\ntype JsonStepResult =\n | JsonResultUnknown\n | JsonResultSkipped\n | JsonResultUndefined\n | JsonResultAmbiguous\n | JsonResultStarted\n | JsonResultPending\n | JsonResultPassed\n | JsonResultFailed\ntype JsonTestResult =\n | JsonResultUnknown\n | JsonResultStarted\n | JsonResultPassed\n | JsonResultFailed\ntype JsonReportResult = JsonTestResult\n\ntype JsonCommand = {\n type: string\n value?: string\n text: string\n screenshotId?: string\n result: JsonCommandResult\n}\ntype JsonStep = {\n type: JsonStepType\n text: string\n commands: JsonCommand[]\n result: JsonStepResult\n}\n\ntype JsonTestProgress = {\n id: string\n featureName: string\n uri: string\n scenarioName: string\n parameters: Record<string, string>\n steps: JsonStep[]\n result: JsonTestResult\n}\n\nexport type JsonReport = {\n testCases: JsonTestProgress[]\n result: JsonReportResult\n}\n\nexport default class ReportGenerator {\n private report: JsonReport = {\n result: {\n status: 'UNKNOWN',\n },\n testCases: [] as JsonTestProgress[],\n }\n private gherkinDocumentMap = new Map<string, messages.GherkinDocument>()\n private pickleMap = new Map<string, messages.Pickle>()\n private testCaseMap = new Map<string, messages.TestCase>()\n private testStepMap = new Map<string, messages.TestStep>()\n private stepProgressMap = new Map<string, JsonStep>()\n private testProgressMap = new Map<string, JsonTestProgress>()\n\n reportFolder:null|string = null\n\n handleMessage(envelope: messages.Envelope) {\n const type = Object.keys(envelope)[0] as keyof messages.Envelope\n switch (type) {\n // case \"meta\": { break}\n // case \"source\": { break}\n case 'parseError': {\n const parseError = envelope[type]\n this.handleParseError(parseError)\n break\n }\n case 'gherkinDocument': {\n const doc = envelope[type]\n this.onGherkinDocument(doc)\n break\n }\n case 'pickle': {\n const pickle = envelope[type]\n this.onPickle(pickle)\n break\n }\n // case \"stepDefinition\": { break}\n // case \"hook\": { break} // Before Hook\n case 'testRunStarted': {\n const testRunStarted = envelope[type]\n this.onTestRunStarted(testRunStarted)\n break\n }\n case 'testCase': {\n const testCase = envelope[type]\n this.onTestCase(testCase)\n break\n }\n case 'testCaseStarted': {\n const testCaseStarted = envelope[type]\n this.onTestCaseStarted(testCaseStarted)\n break\n }\n case 'testStepStarted': {\n const testStepStarted = envelope[type]\n this.onTestStepStarted(testStepStarted)\n break\n }\n case 'attachment': {\n const attachment = envelope[type]\n this.onAttachment(attachment)\n break\n }\n case 'testStepFinished': {\n const testStepFinished = envelope[type]\n this.onTestStepFinished(testStepFinished)\n break\n }\n case 'testCaseFinished': {\n const testCaseFinished = envelope[type]\n this.onTestCaseFinished(testCaseFinished)\n break\n }\n // case \"hook\": { break} // After Hook\n case 'testRunFinished': {\n const testRunFinished = envelope[type]\n this.onTestRunFinished(testRunFinished)\n break\n }\n // case \"parameterType\" : { break}\n // case \"undefinedParameterType\": { break}\n }\n }\n getReport() {\n return this.report\n }\n private handleParseError(parseError: messages.ParseError) {\n const { message, source } = parseError\n const timestamp = new Date().getTime()\n this.report.result = {\n status: 'FAILED',\n startTime: timestamp,\n endTime: timestamp,\n message: message,\n }\n }\n private onGherkinDocument(doc: messages.GherkinDocument) {\n this.gherkinDocumentMap.set(doc.uri, doc)\n }\n private onPickle(pickle: messages.Pickle) {\n this.pickleMap.set(pickle.id, pickle)\n }\n private getTimeStamp(timestamp: messages.Timestamp) {\n return timestamp.seconds * 1000 + timestamp.nanos / 1000000\n }\n private onTestRunStarted(testRunStarted: messages.TestRunStarted) {\n this.report.result = {\n status: 'STARTED',\n startTime: this.getTimeStamp(testRunStarted.timestamp),\n }\n }\n private onTestCase(testCase: messages.TestCase) {\n this.testCaseMap.set(testCase.id, testCase)\n testCase.testSteps.forEach((testStep) => {\n this.testStepMap.set(testStep.id, testStep)\n })\n }\n private onTestCaseStarted(testCaseStarted: messages.TestCaseStarted) {\n const { testCaseId, id, timestamp } = testCaseStarted\n const testCase = this.testCaseMap.get(testCaseId)\n if (testCase === undefined)\n throw new Error(`testCase with id ${testCaseId} not found`)\n const pickle = this.pickleMap.get(testCase.pickleId)\n if (pickle === undefined)\n throw new Error(`pickle with id ${testCase.pickleId} not found`)\n\n const doc = this.gherkinDocumentMap.get(pickle.uri)\n if (doc === undefined)\n throw new Error(`gherkinDocument with uri ${pickle.uri} not found`)\n const featureName = doc.feature.name\n\n const scenarioName = pickle.name\n\n const steps: JsonStep[] = pickle.steps.map((step) => {\n this.stepProgressMap.set(step.id, {\n type: step.type,\n text: step.text,\n commands: [],\n result: {\n status: 'UNKNOWN',\n },\n })\n return this.stepProgressMap.get(step.id)\n })\n this.testProgressMap.set(id, {\n id,\n uri: pickle.uri,\n featureName,\n scenarioName,\n // TODO: compute parameters\n parameters: {},\n steps,\n result: {\n status: 'STARTED',\n startTime: this.getTimeStamp(timestamp),\n },\n })\n this.report.testCases.push(this.testProgressMap.get(id))\n }\n private onTestStepStarted(testStepStarted: messages.TestStepStarted) {\n const { testStepId, timestamp, testCaseStartedId } = testStepStarted\n const testStep = this.testStepMap.get(testStepId)\n if (testStep === undefined)\n throw new Error(`testStep with id ${testStepId} not found`)\n if (testStep.pickleStepId === undefined) return\n const stepProgess = this.stepProgressMap.get(testStep.pickleStepId)\n stepProgess.result = {\n status: 'STARTED',\n startTime: this.getTimeStamp(timestamp),\n }\n }\n private onAttachment(attachment: messages.Attachment) {\n const {\n testCaseStartedId,\n testStepId,\n body,\n mediaType,\n contentEncoding,\n fileName,\n source,\n url,\n } = attachment\n if (mediaType === 'text/plain') {\n this.reportFolder = body.replaceAll('\\\\', '/')\n }\n const testStep = this.testStepMap.get(testStepId)\n if (testStep.pickleStepId === undefined) return\n\n const stepProgess = this.stepProgressMap.get(testStep.pickleStepId)\n if (mediaType === 'application/json') {\n const command:JsonCommand = JSON.parse(body)\n stepProgess.commands.push(command)\n }\n }\n private onTestStepFinished(testStepFinished: messages.TestStepFinished) {\n const { testStepId, testCaseStartedId, testStepResult, timestamp } =\n testStepFinished\n const testStep = this.testStepMap.get(testStepId)\n if (testStep.pickleStepId === undefined) return\n const stepProgess = this.stepProgressMap.get(testStep.pickleStepId)\n const prevStepResult = stepProgess.result as {\n status: 'STARTED'\n startTime: JsonTimestamp\n }\n stepProgess.result = {\n status: testStepResult.status,\n startTime: prevStepResult.startTime,\n endTime: this.getTimeStamp(timestamp),\n message: testStepResult.message,\n // exception: testStepResult.exception,\n }\n }\n private getTestCaseResult(steps: JsonStep[]) {\n for (const step of steps) {\n switch (step.result.status) {\n case 'FAILED':\n return {\n status: step.result.status,\n message: step.result.message,\n // exception: step.result.exception,\n } as const\n case 'AMBIGUOUS':\n case 'UNDEFINED':\n case 'PENDING':\n return {\n status: 'FAILED',\n message: `step \"${step.text}\" is ${step.result.status}`,\n } as const\n }\n }\n return {\n status: 'PASSED',\n } as const\n }\n private onTestCaseFinished(testCaseFinished: messages.TestCaseFinished) {\n const { testCaseStartedId, timestamp } = testCaseFinished\n const testProgress = this.testProgressMap.get(testCaseStartedId)\n const prevResult = testProgress.result as {\n status: 'STARTED'\n startTime: JsonTimestamp\n }\n const steps = Object.values(testProgress.steps)\n const result = this.getTestCaseResult(steps)\n testProgress.result = {\n ...result,\n startTime: prevResult.startTime,\n endTime: this.getTimeStamp(timestamp),\n }\n }\n private onTestRunFinished(testRunFinished: messages.TestRunFinished) {\n const { timestamp, success, exception, message } = testRunFinished\n const prevResult = this.report.result as {\n status: 'STARTED'\n startTime: JsonTimestamp\n }\n this.report.result = {\n status: success ? 'PASSED' : 'FAILED',\n startTime: prevResult.startTime,\n endTime: this.getTimeStamp(timestamp),\n message,\n // exception,\n }\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import FormData from "form-data";
2
+ declare class RunUploadService {
3
+ private runsApiBaseURL;
4
+ private accessToken;
5
+ constructor(runsApiBaseURL: string, accessToken: string);
6
+ createRunDocument(name: string): Promise<any>;
7
+ upload(formData: FormData): Promise<void>;
8
+ }
9
+ export { RunUploadService };
@@ -0,0 +1,47 @@
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
+ exports.RunUploadService = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ class RunUploadService {
9
+ constructor(runsApiBaseURL, accessToken) {
10
+ this.runsApiBaseURL = runsApiBaseURL;
11
+ this.accessToken = accessToken;
12
+ }
13
+ async createRunDocument(name) {
14
+ const runDocResult = await axios_1.default.post(this.runsApiBaseURL + "/cucumber-runs/create", {
15
+ name,
16
+ }, {
17
+ headers: {
18
+ Authorization: "Bearer " + this.accessToken,
19
+ "x-source": "cucumber_js"
20
+ },
21
+ });
22
+ if (runDocResult.status !== 200) {
23
+ throw new Error("Failed to create run document in the server");
24
+ }
25
+ if (runDocResult.data.status !== true) {
26
+ throw new Error("Failed to create run document in the server");
27
+ }
28
+ return runDocResult.data.run;
29
+ }
30
+ async upload(formData) {
31
+ const response = await axios_1.default.post(this.runsApiBaseURL + "/cucumber-runs/upload", formData, {
32
+ headers: {
33
+ ...formData.getHeaders(),
34
+ Authorization: "Bearer " + this.accessToken,
35
+ "x-source": "cucumber_js"
36
+ },
37
+ });
38
+ if (response.status !== 200) {
39
+ throw new Error("Failed to upload run to the server");
40
+ }
41
+ if (response.data.status !== true) {
42
+ throw new Error("Failed to upload run to the server");
43
+ }
44
+ }
45
+ }
46
+ exports.RunUploadService = RunUploadService;
47
+ //# sourceMappingURL=upload_serivce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload_serivce.js","sourceRoot":"","sources":["../../../src/formatter/helpers/upload_serivce.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAE1B,MAAM,gBAAgB;IAClB,YAAoB,cAAqB,EAAU,WAAkB;QAAjD,mBAAc,GAAd,cAAc,CAAO;QAAU,gBAAW,GAAX,WAAW,CAAO;IACrE,CAAC;IACD,KAAK,CAAC,iBAAiB,CAAC,IAAW;QACjC,MAAM,YAAY,GAAG,MAAM,eAAK,CAAC,IAAI,CACnC,IAAI,CAAC,cAAc,GAAG,uBAAuB,EAC7C;YACE,IAAI;SACL,EACD;YACE,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC,WAAW;gBAC3C,UAAU,EAAC,aAAa;aACzB;SACF,CACF,CAAC;QACF,IAAG,YAAY,CAAC,MAAM,KAAK,GAAG,EAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;SAChE;QACD,IAAG,YAAY,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,EAAC;YACnC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;SAChE;QACD,OAAO,YAAY,CAAC,IAAI,CAAC,GAAG,CAAA;IAC9B,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,QAAiB;QAC1B,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,uBAAuB,EAAE,QAAQ,EAAE;YACvF,OAAO,EAAE;gBACP,GAAG,QAAQ,CAAC,UAAU,EAAE;gBACxB,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC,WAAW;gBAC3C,UAAU,EAAC,aAAa;aACzB;SACF,CAAC,CAAA;QACF,IAAG,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAC;YACzB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACvD;QACD,IAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,EAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACvD;IACP,CAAC;CACJ;AACO,4CAAgB","sourcesContent":["import axios from \"axios\";\nimport FormData from \"form-data\";\nclass RunUploadService {\n constructor(private runsApiBaseURL:string, private accessToken:string){\n }\n async createRunDocument(name:string){\n const runDocResult = await axios.post(\n this.runsApiBaseURL + \"/cucumber-runs/create\",\n {\n name,\n },\n {\n headers: {\n Authorization: \"Bearer \" + this.accessToken,\n \"x-source\":\"cucumber_js\"\n },\n }\n );\n if(runDocResult.status !== 200){\n throw new Error(\"Failed to create run document in the server\");\n }\n if(runDocResult.data.status !== true){\n throw new Error(\"Failed to create run document in the server\");\n }\n return runDocResult.data.run\n }\n async upload(formData:FormData){\n const response = await axios.post(this.runsApiBaseURL + \"/cucumber-runs/upload\", formData, {\n headers: {\n ...formData.getHeaders(),\n Authorization: \"Bearer \" + this.accessToken,\n \"x-source\":\"cucumber_js\"\n },\n })\n if(response.status !== 200){\n throw new Error(\"Failed to upload run to the server\");\n }\n if(response.data.status !== true){\n throw new Error(\"Failed to upload run to the server\");\n }\n }\n}\nexport {RunUploadService}"]}
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "1.0.3";
1
+ export declare const version = "1.0.5";
package/lib/version.js CHANGED
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
4
  // Generated by genversion.
5
- exports.version = '1.0.3';
5
+ exports.version = '1.0.5';
6
6
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AACd,QAAA,OAAO,GAAG,OAAO,CAAA","sourcesContent":["// Generated by genversion.\nexport const version = '1.0.3'\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AACd,QAAA,OAAO,GAAG,OAAO,CAAA","sourcesContent":["// Generated by genversion.\nexport const version = '1.0.5'\n"]}
package/package.json CHANGED
@@ -8,7 +8,9 @@
8
8
  "gherkin",
9
9
  "tests"
10
10
  ],
11
- "version": "1.0.3",
11
+
12
+ "version": "1.0.5",
13
+
12
14
  "homepage": "https://github.com/blinq-io/cucumber-js",
13
15
  "author": "blinq.io",
14
16
  "contributors": [
@@ -61,6 +63,7 @@
61
63
  "@cucumber/tag-expressions": "5.0.1",
62
64
  "@faker-js/faker": "^8.0.2",
63
65
  "assertion-error-formatter": "^3.0.0",
66
+ "axios": "^1.6.2",
64
67
  "capital-case": "^1.0.4",
65
68
  "chalk": "^4.1.2",
66
69
  "cli-table3": "0.6.3",
@@ -73,6 +76,7 @@
73
76
  "indent-string": "^4.0.0",
74
77
  "is-installed-globally": "^0.4.0",
75
78
  "is-stream": "^2.0.0",
79
+ "jszip": "^3.10.1",
76
80
  "knuth-shuffle-seeded": "^1.0.6",
77
81
  "lodash.merge": "^4.6.2",
78
82
  "lodash.mergewith": "^4.6.2",
@@ -169,7 +173,7 @@
169
173
  "prelint-code": "npm run build-local",
170
174
  "precck-test": "npm run build-local",
171
175
  "prefeature-test": "npm run build-local",
172
- "prepublishOnly": "rm -rf lib && npm run build-local",
176
+ "prepublishOnly": "shx rm -rf lib && npm run build-local",
173
177
  "pretest-coverage": "npm run build-local",
174
178
  "pretypes-test": "npm run build-local",
175
179
  "test-coverage": "nyc --silent mocha 'src/**/*_spec.ts' 'compatibility/**/*_spec.ts' && nyc --silent --no-clean node bin/cucumber.js --tags \"not @source-mapping\" && nyc report --reporter=lcov",