├── .eslintrc.json
├── .github
├── ISSUE_TEMPLATE
│ ├── --bug-report.md
│ ├── --documentation.md
│ ├── --feature-request.md
│ └── --question.md
└── stale.yml
├── .gitignore
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── docs
└── images
│ └── protractor-support.jpg
├── index.js
├── package.json
└── test
├── css
├── custom.css
└── override.css
├── cucumber
├── config
│ ├── full-options.conf.js
│ ├── no-log.conf.js
│ ├── no-options.conf.js
│ └── protractor.shared.conf.js
├── features
│ ├── foo.feature
│ └── generate.report.feature
└── step_definitions
│ └── steps.js
├── jasmine.json
├── test.spec.js
└── test_util.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parserOptions": {
3 | "ecmaVersion": 6,
4 | "sourceType": "module"
5 | },
6 | "env": {
7 | "es6": true,
8 | "node": true,
9 | "protractor": true
10 | },
11 | "globals": {
12 | "$": true,
13 | "process": true,
14 | "beforeEach": true,
15 | "describe": true,
16 | "it": true,
17 | "expect": true,
18 | "fit": true,
19 | "fdiscribe": true,
20 | "xit": true,
21 | "xdiscribe": true,
22 | "After": true,
23 | "Before": true,
24 | "Given": true,
25 | "When": true,
26 | "Then": true
27 | },
28 | "root": true,
29 | "rules": {
30 | // Possible Errors
31 | "comma-dangle": [
32 | 2,
33 | "never"
34 | ],
35 | "no-cond-assign": 2,
36 | "no-console": 0,
37 | "no-constant-condition": 2,
38 | "no-control-regex": 2,
39 | "no-debugger": 2,
40 | "no-dupe-args": 2,
41 | "no-dupe-keys": 2,
42 | "no-duplicate-case": 2,
43 | "no-empty-character-class": 2,
44 | "no-empty": [
45 | "error",
46 | {
47 | "allowEmptyCatch": true
48 | }
49 | ],
50 | "no-ex-assign": 2,
51 | "no-extra-boolean-cast": 2,
52 | "no-extra-parens": [
53 | "error",
54 | "all",
55 | {
56 | "nestedBinaryExpressions": false
57 | }
58 | ],
59 | "no-extra-semi": 2,
60 | "no-func-assign": 2,
61 | "no-inner-declarations": 2,
62 | "no-invalid-regexp": 2,
63 | "no-irregular-whitespace": 2,
64 | "no-negated-in-lhs": 2,
65 | "no-obj-calls": 2,
66 | "no-regex-spaces": 2,
67 | "no-sparse-arrays": 2,
68 | "no-unexpected-multiline": 2,
69 | "no-unreachable": 2,
70 | "use-isnan": 2,
71 | "valid-jsdoc": [
72 | 2,
73 | {
74 | "requireReturn": false,
75 | "requireParamDescription": false,
76 | "requireReturnDescription": false,
77 | "prefer": {
78 | "return": "returns"
79 | }
80 | }
81 | ],
82 | "valid-typeof": 2,
83 | // Best Practices
84 | "accessor-pairs": 2,
85 | "block-scoped-var": 2,
86 | "complexity": [
87 | "error",
88 | {
89 | "max": 20
90 | }
91 | ],
92 | "consistent-return": 0,
93 | "curly": 2,
94 | "default-case": 2,
95 | "dot-location": [
96 | 2,
97 | "property"
98 | ],
99 | "dot-notation": 2,
100 | "eqeqeq": 2,
101 | "guard-for-in": 2,
102 | "no-alert": 2,
103 | "no-caller": 2,
104 | "no-case-declarations": 2,
105 | "no-div-regex": 2,
106 | "no-else-return": 1,
107 | "no-empty-pattern": 2,
108 | "no-eq-null": 2,
109 | "no-eval": 2,
110 | "no-extend-native": 2,
111 | "no-extra-bind": 2,
112 | "no-fallthrough": 2,
113 | "no-floating-decimal": 2,
114 | "no-implicit-coercion": 0,
115 | "no-implied-eval": 2,
116 | "no-invalid-this": 0,
117 | "no-iterator": 2,
118 | "no-labels": 2,
119 | "no-lone-blocks": 2,
120 | "no-loop-func": 2,
121 | "no-multi-spaces": 2,
122 | "no-multi-str": 0,
123 | "no-native-reassign": 2,
124 | "no-new-func": 2,
125 | "no-new-wrappers": 2,
126 | "no-new": 0,
127 | "no-octal-escape": 2,
128 | "no-octal": 2,
129 | "no-param-reassign": 2,
130 | "no-process-env": 0,
131 | "no-proto": 2,
132 | "no-redeclare": 2,
133 | "no-return-assign": 2,
134 | "no-script-url": 2,
135 | "no-self-compare": 2,
136 | "no-sequences": 2,
137 | "no-throw-literal": 2,
138 | "no-unused-expressions": [
139 | 2,
140 | {
141 | "allowShortCircuit": true
142 | }
143 | ],
144 | "no-useless-call": 2,
145 | "no-useless-concat": 2,
146 | "no-void": 2,
147 | "no-warning-comments": 0,
148 | "no-with": 2,
149 | "radix": 2,
150 | "vars-on-top": 0,
151 | // FIXME should be enabled at some point
152 | "wrap-iife": [
153 | 2,
154 | "inside"
155 | ],
156 | "yoda": [
157 | 2,
158 | "never",
159 | {
160 | "exceptRange": true
161 | }
162 | ],
163 | // Strict Mode
164 | "strict": [
165 | 0,
166 | "global"
167 | ],
168 | // Variables
169 | "init-declarations": 0,
170 | "no-catch-shadow": 2,
171 | "no-delete-var": 2,
172 | "no-label-var": 2,
173 | "no-shadow-restricted-names": 2,
174 | "no-shadow": 2,
175 | "no-undef-init": 2,
176 | "no-undef": 2,
177 | "no-undefined": 0,
178 | "no-unused-vars": 1,
179 | "no-use-before-define": 2,
180 | // Stylistic Issues
181 | "array-bracket-spacing": [
182 | 2,
183 | "never"
184 | ],
185 | "block-spacing": 2,
186 | "brace-style": [
187 | 2,
188 | "1tbs"
189 | ],
190 | "camelcase": 0,
191 | "comma-spacing": [
192 | 2,
193 | {
194 | "before": false,
195 | "after": true
196 | }
197 | ],
198 | "comma-style": [
199 | 2,
200 | "last"
201 | ],
202 | "computed-property-spacing": [
203 | 2,
204 | "never"
205 | ],
206 | "consistent-this": [
207 | 2,
208 | "that"
209 | ],
210 | "eol-last": 2,
211 | "func-names": 0,
212 | "func-style": 0,
213 | "id-length": 0,
214 | "id-match": 0,
215 | "indent": [
216 | "error",
217 | 4,
218 | {
219 | "SwitchCase": 1
220 | }
221 | ],
222 | "jsx-quotes": 0,
223 | "key-spacing": [
224 | 2,
225 | {
226 | "beforeColon": false,
227 | "afterColon": true
228 | }
229 | ],
230 | "linebreak-style": [
231 | 2,
232 | "unix"
233 | ],
234 | "lines-around-comment": 0,
235 | "max-nested-callbacks": [
236 | 2,
237 | 5
238 | ],
239 | "new-cap": [
240 | "error",
241 | {
242 | "capIsNewExceptions": [
243 | "After",
244 | "Before",
245 | "Given",
246 | "When",
247 | "Then"
248 | ]
249 | }
250 | ],
251 | "new-parens": 2,
252 | "newline-after-var": 2,
253 | "no-array-constructor": 2,
254 | "no-continue": 2,
255 | "no-inline-comments": 0,
256 | "no-lonely-if": 2,
257 | "no-mixed-spaces-and-tabs": 2,
258 | "no-multiple-empty-lines": [
259 | 2,
260 | {
261 | "max": 2
262 | }
263 | ],
264 | "no-negated-condition": 2,
265 | "no-nested-ternary": 2,
266 | "no-new-object": 2,
267 | "no-restricted-syntax": 0,
268 | "no-spaced-func": 0,
269 | "no-ternary": 0,
270 | "no-trailing-spaces": 2,
271 | "no-underscore-dangle": 0,
272 | "no-unneeded-ternary": 2,
273 | "object-curly-spacing": [
274 | 2,
275 | "always",
276 | {
277 | "objectsInObjects": true,
278 | "arraysInObjects": true
279 | }
280 | ],
281 | "one-var": [
282 | 2,
283 | "never"
284 | ],
285 | "operator-assignment": 2,
286 | "operator-linebreak": [
287 | 2,
288 | "before"
289 | ],
290 | "padded-blocks": 0,
291 | "quote-props": [
292 | 2,
293 | "consistent-as-needed"
294 | ],
295 | "quotes": [
296 | 2,
297 | "single",
298 | "avoid-escape"
299 | ],
300 | "require-jsdoc": 2,
301 | "semi-spacing": [
302 | 2,
303 | {
304 | "before": false,
305 | "after": true
306 | }
307 | ],
308 | "semi": [
309 | 0,
310 | "always"
311 | ],
312 | "sort-vars": 0,
313 | "keyword-spacing": 2,
314 | "space-before-blocks": 2,
315 | "space-before-function-paren": [
316 | "error",
317 | {
318 | "anonymous": "always",
319 | "named": "never"
320 | }
321 | ],
322 | "space-in-parens": [
323 | 2,
324 | "never"
325 | ],
326 | "space-infix-ops": 2,
327 | "space-unary-ops": 2,
328 | "spaced-comment": [
329 | 2,
330 | "always",
331 | {
332 | "exceptions": [
333 | "-",
334 | "+",
335 | "!"
336 | ]
337 | }
338 | ],
339 | "wrap-regex": 2,
340 | // ES6
341 | "arrow-parens": [
342 | 2,
343 | "always"
344 | ],
345 | // Legacy
346 | "max-depth": [
347 | 2,
348 | 4
349 | ],
350 | "max-len": [
351 | 2,
352 | 140
353 | ],
354 | "max-params": [
355 | 2,
356 | 5
357 | ],
358 | "max-statements": 0,
359 | "no-bitwise": 2,
360 | "no-plusplus": 0
361 | }
362 | }
363 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41BBug report"
3 | about: Create a report to help us improve.
4 |
5 | ---
6 |
7 | **Environment (please complete the following information):**
8 | - protractor-multiple-cucumber-html-reporter: [e.g. 1.6.1]
9 | - Node.js version: [e.g. 8.9.1]
10 | - NPM version: [e.g. 5.8.0]
11 | - Platform name and version: [e.g. Windows 10]
12 | - protractor version: [e.g. 5.1.0]
13 | - Cucucmber version: [e.g. 4.2.0]
14 | - protractor-cucumber-framework version: [e.g. 6.0.0]
15 |
16 | **Config of protractor + protractor-multiple-cucumber-html-reporter**
17 | An example of how you configured the reporter in your webdriver.io config
18 |
19 | **Describe the bug**
20 | A clear and concise description of what the bug is.
21 |
22 | **To Reproduce**
23 | Steps to reproduce the behavior:
24 |
25 | [Include code or an example repository that can easily be set up]
26 |
27 | **Expected behavior**
28 | A clear and concise description of what you expected to happen.
29 |
30 | **Log**
31 | If applicable, add logs to help explain your problem. If you don't have log, enable 'debug:true' in the config and paste the log here.
32 | Please use proper markdown to style it
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F4D6Documentation"
3 | about: Suggest improvements or report missing/unclear documentation.
4 |
5 | ---
6 |
7 | **Pre-check**
8 | - [ ] I'm aware that I can [edit the docs](https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin) and submit a pull request
9 |
10 | **Describe the improvement**
11 |
12 | I'd like to report
13 | - [ ] Unclear documentation
14 | - [ ] A typo
15 | - [ ] Missing documentation
16 | - [ ] Other
17 |
18 | **Description of the improvement / report**
19 | A clear and concise description.
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F4A1Feature request"
3 | about: Suggest an idea for this module.
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F4ACQuestion"
3 | about: Ask questions.
4 |
5 | ---
6 |
7 | **Describe your question with as much detail as possible**
8 | A clear and concise question that doesn't require too much conversation. Need more help? [Find me on Gitter](https://gitter.im/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin)
9 |
10 |
11 | **If it's about a specific piece of code, try and include some of it to support your question.**
12 | [...]
13 |
14 |
15 | **Environment (please complete the following information):**
16 | - protractor-multiple-cucumber-html-reporter: [e.g. 1.6.1]
17 | - Node.js version: [e.g. 8.9.1]
18 | - NPM version: [e.g. 5.8.0]
19 | - Platform name and version: [e.g. Windows 10]
20 | - protractor version: [e.g. 5.1.0]
21 | - Cucucmber version: [e.g. 4.2.0]
22 | - protractor-cucumber-framework version: [e.g. 6.0.0]
23 |
24 |
25 | **Additional context**
26 | Add any other context about the problem here.
27 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 90
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 14
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - bug
8 | # Label to use when marking an issue as stale
9 | staleLabel: wontfix
10 | # Comment to post when marking an issue as stale. Set to `false` to disable
11 | markComment: >
12 | This issue has been automatically marked as stale because it has not had
13 | recent activity. It will be closed if no further activity occurs. Thank you
14 | for your contributions.
15 | # Comment to post when closing a stale issue. Set to `false` to disable
16 | closeComment: false
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .tmp/
3 | coverage/
4 | node_modules/
5 | reports/
6 | report-path/
7 | json-output-path/
8 | package-lock.json
9 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .tmp/
3 | coverage/
4 | node_modules/
5 | reports/
6 | test/
7 | docs/
8 | package-lock.json
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | dist: trusty
3 |
4 | language: node_js
5 | node_js:
6 | - "8"
7 | - "10"
8 |
9 | before_install:
10 | - export DISPLAY=:99.0
11 | - sh -e /etc/init.d/xvfb start
12 | - sleep 3 # give xvfb some time to start
13 |
14 | addons:
15 | chrome: stable
16 |
17 | install:
18 | - npm install
19 |
20 | script:
21 | - npm test
22 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributer's Guide
2 |
3 | We welcome contributions - thanks for taking the time to contribute! Here are
4 | some guidelines to help you get started. These are just guidelines, not rules,
5 | use your best judgment and feel free to propose changes to this document in a
6 | pull request.
7 |
8 | ## Discussion
9 |
10 | While not absolutely requir ed, it is encouraged that you first open an
11 | [issue](https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/issues)
12 | for any bug or feature request. This allows discussion on the proper course of
13 | action to take before coding begins.
14 |
15 | ## Building
16 |
17 | ```shell
18 | npm install
19 | ```
20 |
21 | ## Changing
22 |
23 | Most of the information you need to contribute code changes can [be found here](https://guides.github.com/activities/contributing-to-open-source/).
24 | In short: fork, make your changes and submit a pull request (PR).
25 |
26 | ### Fork
27 |
28 | Fork the project [on Github](https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin)
29 | and check out your copy locally:
30 |
31 | ```shell
32 | git clone https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin.git
33 | cd protractor-numerator
34 | ```
35 |
36 | ### Create your branch
37 |
38 | Create a feature branch and start hacking:
39 |
40 | ```shell
41 | git checkout -b my-feature-branch
42 | ```
43 |
44 | We practice HEAD-based development, which means all changes are applied
45 | directly on top of master.
46 |
47 | ### Commit
48 |
49 | First make sure git knows your name and email address:
50 |
51 | ```shell
52 | git config --global user.name 'John Doe'
53 | git config --global user.email 'john@example.com'
54 | ```
55 |
56 | **Writing good commit message is important.** A commit message should be around
57 | 50 characters or less and contain a short description of the change and
58 | reference issues fixed (if any). Include `Fixes #N`, where _N_ is the issue
59 | number the commit fixes, if any.
60 |
61 | ### Rebase
62 |
63 | Use `git rebase` (not `git merge`) to sync your work with the core repository
64 | from time to time:
65 |
66 | ```shell
67 | git remote add upstream https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin.git
68 | git fetch upstream
69 | git rebase upstream/master
70 | ```
71 |
72 | ### Test
73 |
74 | Bug fixes and features **should have tests**. Look at other tests to see how
75 | they should be structured.
76 |
77 | This project makes use of code linting and e2e tests to make sure we don't break
78 | anything. Before you submit your pull request make sure you pass all the tests:
79 |
80 | You can run code linting with: `npm run lint`.
81 | You can run all the e2e tests with: `npm test`.
82 |
83 | ### Push
84 |
85 | ```shell
86 | git push origin my-feature-branch
87 | ```
88 |
89 | Go to https://github.com/yourusername/protractor-multiple-cucumber-html-reporter-plugin.git and press the
90 | _New pull request_ button and fill out the form.
91 |
92 | A good PR comment message can look like this:
93 |
94 | ```text
95 | Explain PR normatively in one line
96 |
97 | Details of PR message are a few lines of text, explaining things
98 | in more detail, possibly giving some background about the issue
99 | being fixed, etc.
100 |
101 | Fixes #142
102 | ```
103 |
104 | Pull requests are usually reviewed within a few days. If there are comments to
105 | address, apply your changes in new commits (preferably
106 | [fixups](http://git-scm.com/docs/git-commit)) and push to the same branch.
107 |
108 | ### Integration
109 |
110 | When code review is complete, a committer will take your PR and integrate it on
111 | protractor-multiple-cucumber-html-reporter-plugin's master branch. Because we like to keep a linear history
112 | on the master branch, we will normally squash and rebase your branch history.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 wswebcreation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # protractor-multiple-cucumber-html-reporter-plugin
2 |
3 | [](https://gitter.im/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://travis-ci.org/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin)
4 | [](https://www.npmjs.com/package/protractor-multiple-cucumber-html-reporter-plugin)
5 | [](https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/blob/master/LICENSE)
6 |
7 | [](https://nodei.co/npm/protractor-multiple-cucumber-html-reporter-plugin/)
8 |
9 | # Important News
10 | **Date: 8th of May** I decided to stop maintaining this package per today and add the DEPRECATED status to all versions
11 |
12 | **Date: 16th of January 2020**
13 |
14 | **I will stop maintaining this module per the first of July 2020.** If you look at Protractor you can get the feeling that, in spite of all the effort that the Open Source Community is putting in it, it is not being maintained by Google anymore.
15 | To be honest, I'm pretty sure about it. If you look at the facts, see image below, you will notice that:
16 | - the amount of issues is increasing
17 | - the amount of PR's is increasing
18 | - the activity in the project is decreasing
19 |
20 | This is not giving me a good feeling. As a contributor to the Protractor project in the last years, I also have the feeling that there won't be a big chance that this is going to change.
21 |
22 | I'm not the only one who thinks about Protractor like this, please take a look at [this great article](https://dev.to/davert/5-reasons-you-should-not-use-protractor-in-2019-3l4b) which might also give you some insights.
23 |
24 | I want to thank all contributors for their help in the past 3-4 years and I feel blessed that I was able to help so many people over the last few years.
25 |
26 | 
27 |
28 | This plugin will connect [Protractor](https://www.npmjs.com/package/protractor), [CucumberJS](https://www.npmjs.com/package/cucumber) and [protractor-cucumber-framework](https://www.npmjs.com/package/protractor-cucumber-framework) to generate unique JSON files per feature with only a few lines of code.
29 | It will also replace the extra CucumberJS hook you needed to make in CucumberJS 1 and 2 to generate unique JSON report files.
30 |
31 | > It was born when CucucmberJS 3 [removed](https://github.com/cucumber/cucumber-js/blob/master/CHANGELOG.md#300-2017-08-08) the `registerHandler` and `registerListener`. As of version 3 Protractor and CucumberJS users don't have the possibility to generate and create unique JSON report files. With this module they have.
32 |
33 | You will also get [multiple-cucumber-html-reporter](https://github.com/wswebcreation/multiple-cucumber-html-reporter) as a dependency and use it on the fly to generate beautiful reports. A sample can be found [here](https://wswebcreation.github.io/multiple-cucumber-html-reporter/)
34 |
35 | ## Supported versions
36 | | [Node.js](http://nodejs.org/and) | [Protractor](https://www.npmjs.com/package/protractor) | [CucumberJS](https://www.npmjs.com/package/cucumber) | [protractor-cucumber-framework](https://www.npmjs.com/package/protractor-cucumber-framework) | [multiple-cucumber-html-reporter](https://github.com/wswebcreation/multiple-cucumber-html-reporter) |
37 | | -------------------------------- | ------------------------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
38 | | 6.x | 4.x | 1.x | 3.1.2 or higher | 1.0.0 or higher |
39 | | 7.x | 5.x | 2.x | | |
40 | | | | 3.x | | |
41 |
42 | ## Installation
43 | `npm install protractor-multiple-cucumber-html-reporter-plugin --save-dev`
44 |
45 | ## Usage
46 | You need to do 2 things.
47 |
48 | 1. Add `format: 'json:.tmp/results.json'` to your `cucumberOpts` in the config. This will tell CucumbjerJS to generate a JSON-file. As of `protractor-cucumber-framework` version 3.1.2 you will get unique JSON files, see also [here](https://github.com/protractor-cucumber-framework/protractor-cucumber-framework#formatters-when-tests-are-sharded-or-with-multi-capabilities).
49 | 2. Add the `protractor-multiple-cucumber-html-reporter-plugin` in the `plugins` block inside
50 | `protractor.config.js`.
51 |
52 | > **!!The path that is defined in the `format` is the path where all files and reports are saved. Advice is not to save the CucumberJS JSON report fil in the root of the project but in for example a `.tmp/` folder!!**
53 |
54 | Here is a short config example of both steps.
55 |
56 | ```javascript
57 | const path = require('path');
58 |
59 | exports.config = {
60 |
61 | framework: 'custom',
62 | frameworkPath: require.resolve('protractor-cucumber-framework'),
63 | cucumberOpts: {
64 | require: [
65 | path.resolve(process.cwd(), './**/*.steps.js')
66 | ],
67 | // Tell CucumberJS to save the JSON report
68 | format: 'json:.tmp/results.json',
69 | strict: true
70 | },
71 |
72 | specs: [
73 | '*.feature'
74 | ],
75 |
76 | multiCapabilities: [{
77 | browserName: 'chrome',
78 | shardTestFiles: true,
79 | maxInstances: 2,
80 | chromeOptions: {
81 | args: ['disable-infobars']
82 | }
83 | }],
84 |
85 | // Here the magic happens
86 | plugins: [{
87 | package: 'protractor-multiple-cucumber-html-reporter-plugin',
88 | options:{
89 | // read the options part
90 | }
91 | }]
92 | };
93 |
94 | ```
95 | ## Options
96 | If you don't provide `options` the pluging will use the defaults as mentioned below. Options can be added by creating an object like this:
97 |
98 | ```js
99 | plugins: [{
100 | package: 'protractor-multiple-cucumber-html-reporter-plugin',
101 | options:{
102 | // read the options part for more options
103 | automaticallyGenerateReport: true,
104 | removeExistingJsonReportFile: true
105 | }
106 | }]
107 | ```
108 |
109 | ### `automaticallyGenerateReport`
110 | - **Type:** `boolean`
111 | - **Default:** `false`
112 | - **Mandatory:** No
113 |
114 | Setting this option will autimatically generate a new report with `multiple-cucumber-html-reporter`. It will generate a log at the end of the testexection where you can find the report and looks like this. This means that you don't need to call the report module in a seperate node process. For the options of the report see the options `openReportInBrowser`, `reportPath` and `saveCollectedJSON`
115 |
116 | ```shell
117 | =====================================================================================================
118 | Multiple Cucumber HTML report generated in:
119 |
120 | /Users/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/.tmp/report/index.html
121 | =====================================================================================================
122 | ```
123 |
124 | ### `customData`
125 | - **Type:** `object`
126 | - **Mandatory:** No
127 |
128 | You can add a custom data block to the report like this
129 |
130 | ```js
131 | customData: {
132 | title: 'Run info',
133 | data: [
134 | {label: 'Project', value: 'Custom project'},
135 | {label: 'Release', value: '1.2.3'},
136 | {label: 'Cycle', value: 'B11221.34321'}
137 | ]
138 | }
139 | ```
140 |
141 | > **THIS WILL ONLY WORK WITH `automaticallyGenerateReport:true`. IF YOU GENERATE THE REPORT LATER PLEASE LOOK AT [multiple-cucumber-html-reporter](https://github.com/wswebcreation/multiple-cucumber-html-reporter#usage)**
142 |
143 | ### `customMetadata`
144 | - **Type:** `boolean`
145 | - **Mandatory:** No
146 |
147 | It is possible to provide custom metadata by setting this variable to `true`. Custom metadata will override the regular metadata completely and potentially have strange formatting bugs if too many (10+) variables are used.
148 | The columns will be in the order defined by the order of the list.
149 |
150 | Adding the metadata is done in the same way as with normal metadata. The metadata is formed as a list of key-value pairs to preserve order:
151 |
152 | ```js
153 | metadata: [
154 | {name: 'Environment v.', value: '12.3'},
155 | {name: 'Plugin v.', value: '32.1'},
156 | {name: 'Variable set', value: 'Foo'}
157 | ]
158 | ```
159 |
160 | ### `customStyle`
161 | - **Type:** `path`
162 | - **Mandatory:** No
163 |
164 | If you need add some custom style to your report. Add it like this `customStyle: 'your-path-where/custom.css'`
165 |
166 | ### `disableLog`
167 | - **Type:** `boolean`
168 | - **Mandatory:** No
169 | - **Default:** `false`
170 |
171 | This will disable the log so will **NOT** see this.
172 |
173 | ```shell
174 | =====================================================================================================
175 | Multiple Cucumber HTML report generated in:
176 |
177 | /Users/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/.tmp/report/index.html
178 | =====================================================================================================
179 | ```
180 |
181 | ### `displayDuration`
182 | - **Type:** `boolean`
183 | - **Mandatory:** No
184 |
185 | If set to `true` the duration of steps, scenarios and features is displayed on the Features overview and single feature page in an easily readable format.
186 | This expects the durations in the report to be in **nanoseconds**, which might result in incorrect durations when using a version of Cucumber(JS 2 and 3) that does not report in nanoseconds but in milliseconds. This can be changed to milliseconds by adding the parameter `durationInMS: true`, see below
187 |
188 | > **NOTE: Only the duration of a feature can be shown in the features overview. A total duration over all features CAN NOT be given because the module doesn't know if all features have been run in parallel**
189 |
190 | ### `durationInMS`
191 | - **Type:** `boolean`
192 | - **Default:** `false`
193 | - **Mandatory:** No
194 |
195 | If set to `true` the duration of steps will be expected to be in **milliseconds**, which might result in incorrect durations when using a version of Cucumber(JS 1 or 4) that does report in **nanaseconds**.
196 | This parameter relies on `displayDuration: true`
197 |
198 | ### `jsonOutputPath`
199 | - **Type:** `string`
200 | - **Default:** `json-output-folder`
201 | - **Mandatory:** No
202 |
203 | The directory that will hold all the unique generated JSON files, relative from where the script is started.
204 |
205 | **N.B.:** If you use a npm script from the command line, like for example `npm run generate-report` the `jsonOutputPath` will be relative from the path where the script is executed. Executing it from the root of your project will also search for the `jsonOutputPath ` from the root of you project.
206 |
207 | If you **DON'T** provide this it will generate a `json-output-folder`-folder in the `path` that it defined the `cucumberOpts.format`.
208 |
209 | ### `metadataKey`
210 | - **Type:** `string`
211 | - **Default:** `metadata`
212 | - **Mandatory:** No
213 |
214 | This will be the `key` reference in the `capabilities` or `multiCapabilities` that will refer to where the instance specific data is saved. The metadata is used for the report that will be generated, see also [metadata](#metadata).
215 |
216 | If for example all the metadata is already present in the `capabilities` but with the `key` called `deviceProperties` you can add the option `metadataKey: 'deviceProperties'` and the plugin will automatically copy the `deviceProperties`-object to the `metadata` of the report.
217 |
218 | ### `openReportInBrowser`
219 | - **Type:** `boolean`
220 | - **Default:** `false`
221 | - **Mandatory:** No
222 |
223 | Settign this option will automatically open the generated report in the default browser of the operating system. See also [here](https://github.com/wswebcreation/multiple-cucumber-html-reporter#openreportinbrowser).
224 |
225 | ### `overrideStyle`
226 | - **Type:** `path`
227 | - **Mandatory:** No
228 |
229 | If you need replace default style for your report. Add it like this `overrideStyle: 'your-path-where/custom.css'`
230 |
231 | ### `pageFooter`
232 | - **Type:** `string`
233 | - **Mandatory:** No
234 |
235 | You can customise Page Footer if required. You just need to provide a html string like `
`
236 |
237 | ### `pageTitle`
238 | - **Type:** `string`
239 | - **Mandatory:** No
240 | - **Default:** Multiple Cucumber HTML Reporter
241 |
242 | You can change the report title in the HTML head Tag
243 |
244 | ### `removeExistingJsonReportFile`
245 | - **Type:** `boolean`
246 | - **Default:** `false`
247 | - **Mandatory:** No
248 |
249 | Settign this option will remove the previous unique JSON report file if it exists. It will prevent double reports of 1 feature + browser execution combination when generating te report with `multiple-cucumber-html-reporter`. This may come in handy when you rerun your flakey features with for example [protractor-flake](https://github.com/NickTomlin/protractor-flake)
250 |
251 | ### `removeOriginalJsonReportFile`
252 | - **Type:** `boolean`
253 | - **Default:** `false`
254 | - **Mandatory:** No
255 |
256 | Setting this option will remove the original json report file, defined in the `cucumberOpts.format`. It will clean up the folder where you save all your results and may be needed if you have a lot of JSON-files with screenshots in it.
257 |
258 | ### `reportName`
259 | - **Type:** `string`
260 | - **Mandatory:** No
261 |
262 | You can change the report name to a name you want.
263 |
264 | > **THIS WILL ONLY WORK WITH `automaticallyGenerateReport:true`. IF YOU GENERATE THE REPORT LATER PLEASE LOOK AT [multiple-cucumber-html-reporter](https://github.com/wswebcreation/multiple-cucumber-html-reporter#usage)**
265 |
266 | ### `reportPath`
267 | - **Type:** `string`
268 | - **Default:** `report`
269 | - **Mandatory:** No
270 |
271 | The directory in which the report needs to be saved, relative from where the script is started. See also [here](https://github.com/wswebcreation/multiple-cucumber-html-reporter#jsondir).
272 | If you **DON'T** provide this it will generate a `report`-folder in the `path` that it defined the `cucumberOpts.format`.
273 |
274 | N.B.: If you use a npm script from the command line, like for example `npm run generate-report` the `reportPath` will be relative from the path where the script is executed. Executing it from the root of your project will also save the report in the `reportPath` in the root of you project.
275 |
276 | ### `saveCollectedJSON`
277 | - **Type:** `boolean`
278 | - **Default:** `false`
279 | - **Mandatory:** No
280 |
281 | `multiple-cucumber-html-reporter` will first merge all the JSON-files to 1 file and then enrich it with data that is used for the report. If `saveCollectedJSON :true` the merged JSON **AND** the enriched JSON will be saved in the [`reportPath`](#reportpath). They will be saved as:
282 |
283 | - `merged-output.json`
284 | - `enriched-output.json`
285 |
286 | See also [here](https://github.com/wswebcreation/multiple-cucumber-html-reporter#savecollectedjson)
287 |
288 | ## Metadata
289 | The report can also show on which browser / device a feature has been executed. It is shown on the featurs overview in the table as well as on the feature overview in a container. You can add this by adding the following object to your `capabilities` or `multiCapabilities`
290 |
291 | ```js
292 | capabilities: {
293 | browserName: 'chrome',
294 | chromeOptions: {
295 | args: ['disable-infobars']
296 | },
297 | // Add this
298 | metadata: {
299 | browser: {
300 | name: 'chrome',
301 | version: '58'
302 | },
303 | device: 'MacBook Pro 15',
304 | platform: {
305 | name: 'OSX',
306 | version: '10.12.6'
307 | }
308 | }
309 | }
310 |
311 | // Or
312 | multiCapabilities: [{
313 | browserName: 'chrome',
314 | chromeOptions: {
315 | args: ['disable-infobars']
316 | },
317 | // Add this
318 | metadata: {
319 | browser: {
320 | name: 'chrome',
321 | version: '58'
322 | },
323 | device: 'MacBook Pro 15',
324 | platform: {
325 | name: 'OSX',
326 | version: '10.12.6'
327 | }
328 | }
329 | }
330 |
331 | ```
332 |
333 | See the metadata information [here](https://github.com/wswebcreation/multiple-cucumber-html-reporter#metadatabrowsername) for the correct values.
334 |
335 | > If you don't provide a `browser.name` or a `browser.version` the module will try to determine this automatically. The rest will be shown as questionmarks in the report
336 |
337 | ## FAQ
338 |
339 | * **Multiple HTML files generated in the in `report/features`-folder, but they are not shown in the overview-page:** See the answer in issue [13](https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/issues/13#issuecomment-377797176)
340 |
341 | ## Changelog/Releases
342 | The Changelog/Releases can be found [here](https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/releases)
343 |
344 | ## Contributing
345 | How to contribute can be found [here](./CONTRIBUTING.md)
346 |
347 | ## Credits
348 | When creating this plugin I got a lot of inspiration from:
349 |
350 | - [protractor-cucumber-framework](https://www.npmjs.com/package/protractor-cucumber-framework)
351 | - [cucumber-js](https://github.com/cucumber/cucumber-js)
352 | - Protractor [plugin-page](https://github.com/angular/protractor/blob/master/docs/plugins.md)
353 |
354 | ## Thanks
355 | If this plugin was helpful for you, please give it a **★ Star** on
356 | [Github](https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin) and
357 | [npm](https://www.npmjs.com/package/protractor-multiple-cucumber-html-reporter-plugin)
358 |
--------------------------------------------------------------------------------
/docs/images/protractor-support.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/f4d30dd1622ff2c03fa4457373a77baa4e4b4995/docs/images/protractor-support.jpg
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs-extra');
4 | const path = require('path');
5 | const multiCucumberHTLMReporter = require('multiple-cucumber-html-reporter');
6 |
7 | let IS_JSON_FORMAT = false;
8 | let PID_INSTANCE_DATA;
9 | const REPORT_FOLDER = 'report';
10 | const METADATA_KEY = 'metadata';
11 | const JSON_OUTPUT_FOLDER = 'json-output-folder';
12 | const PLUGIN_CONFIG = {
13 | /**
14 | * multiple-cucumber-html-reporter specific options
15 | */
16 | customMetadata: false,
17 | customStyle: '',
18 | disableLog: false,
19 | displayDuration: false,
20 | durationInMS: false,
21 | openReportInBrowser: false,
22 | overrideStyle: '',
23 | pageFooter: false,
24 | pageTitle: false,
25 | reportPath: REPORT_FOLDER,
26 | saveCollectedJSON: false,
27 |
28 | /**
29 | * protractor-multiple-cucumber-html-reporter-plugin specific options
30 | */
31 | automaticallyGenerateReport: false,
32 | removeExistingJsonReportFile: false,
33 | removeOriginalJsonReportFile: false,
34 | metadataKey: METADATA_KEY,
35 |
36 | /**
37 | * Used for both modules
38 | */
39 | jsonOutputPath: JSON_OUTPUT_FOLDER
40 | };
41 |
42 | /**
43 | * Configures the plugin with the correct data
44 | *
45 | * @see docs/plugins.md
46 | * @returns {Promise} A promise which resolves into a configured setup
47 | * @public
48 | */
49 | function setup() {
50 | return browser.getProcessedConfig()
51 | .then((configuration) => {
52 | let cucumberFormat = configuration.cucumberOpts.format;
53 |
54 | IS_JSON_FORMAT = cucumberFormat && cucumberFormat.includes('json');
55 |
56 | if (Array.isArray(cucumberFormat)) {
57 | IS_JSON_FORMAT = cucumberFormat.find((format) => {
58 | cucumberFormat = format;
59 | return format.includes('json')
60 | });
61 | }
62 |
63 | if (IS_JSON_FORMAT) {
64 | /**
65 | * If options are provided override the values to the PLUGIN_CONFIG object
66 | */
67 | if (this.config.options) {
68 | Object.assign(PLUGIN_CONFIG, this.config.options);
69 | }
70 |
71 | /**
72 | * Get the JSON folder path and file name if they are still empty
73 | */
74 | const formatPathMatch = cucumberFormat.match(/(.+):(.+)/);
75 | const filePathMatch = formatPathMatch[2].match(/(.*)\/(.*)\.json/);
76 |
77 | // Get the cucumber results path
78 | PLUGIN_CONFIG.cucumberResultsPath = filePathMatch[1];
79 |
80 | // Get the cucumber report name
81 | PLUGIN_CONFIG.cucumberReportName = filePathMatch[2];
82 |
83 | /**
84 | * If the json output folder is still default, then create a new one
85 | */
86 | if (PLUGIN_CONFIG.jsonOutputPath === JSON_OUTPUT_FOLDER) {
87 | PLUGIN_CONFIG.jsonOutputPath = path.join(PLUGIN_CONFIG.cucumberResultsPath, JSON_OUTPUT_FOLDER);
88 | }
89 |
90 | /**
91 | * Check whether the file name need to be unique
92 | */
93 | PLUGIN_CONFIG.uniqueReportFileName = (Array.isArray(configuration.multiCapabilities)
94 | && configuration.multiCapabilities.length > 0)
95 | || typeof configuration.getMultiCapabilities === 'function'
96 | || configuration.capabilities.shardTestFiles;
97 |
98 | /**
99 | * Prepare the PID_INSTANCE_DATA
100 | */
101 | const metadata = {
102 | browser: {
103 | name: '',
104 | version: ''
105 | },
106 | device: '',
107 | platform: {
108 | name: '',
109 | version: ''
110 | }
111 | };
112 |
113 | PID_INSTANCE_DATA = {
114 | pid: process.pid,
115 | metadata: Object.assign(metadata, configuration.capabilities[PLUGIN_CONFIG.metadataKey] || {})
116 | };
117 |
118 | /**
119 | * Create the needed folders if they are not present
120 | */
121 | fs.ensureDirSync(PLUGIN_CONFIG.cucumberResultsPath);
122 | fs.ensureDirSync(PLUGIN_CONFIG.jsonOutputPath);
123 | } else {
124 | console.warn('\n### NO `JSON` FORMAT IS SPECIFIED IN THE PROTRACTOR CONF FILE UNDER `cucumberOpts.format ###`\n');
125 | }
126 | });
127 | }
128 |
129 | /**
130 | * Enrich the instance data
131 | *
132 | * @see docs/plugins.md
133 | * @returns {Promise} A promise which resolves in a enriched instance data object
134 | * @public
135 | */
136 | function onPrepare() {
137 | if (IS_JSON_FORMAT) {
138 | return browser.getCapabilities()
139 | .then((capabilities) => {
140 | PID_INSTANCE_DATA.metadata.browser.name = PID_INSTANCE_DATA.metadata.browser.name === ''
141 | ? capabilities.get('browserName').toLowerCase()
142 | : PID_INSTANCE_DATA.metadata.browser.name;
143 | PID_INSTANCE_DATA.metadata.browser.version = (capabilities.get('version') || capabilities.get('browserVersion'))
144 | || PID_INSTANCE_DATA.metadata.browser.version;
145 | });
146 | }
147 | }
148 |
149 | /**
150 | * When a report file has been made by CucumberJS, parse it by
151 | * - cutting it up to a file per feature
152 | * - adding the instance data to it.
153 | *
154 | * @see docs/plugins.md
155 | * @public
156 | */
157 | function postResults() {
158 | if (IS_JSON_FORMAT) {
159 | const reportPath = `${path.join(PLUGIN_CONFIG.cucumberResultsPath, PLUGIN_CONFIG.cucumberReportName)}.json`;
160 | const pidReportPath = `${path.join(
161 | PLUGIN_CONFIG.cucumberResultsPath,
162 | PLUGIN_CONFIG.cucumberReportName
163 | )}.${PID_INSTANCE_DATA.pid}.json`;
164 |
165 | if ((!PLUGIN_CONFIG.uniqueReportFileName && fs.existsSync(reportPath))
166 | || (PLUGIN_CONFIG.uniqueReportFileName && fs.existsSync(pidReportPath))
167 | ) {
168 | const currentReportPath = PLUGIN_CONFIG.uniqueReportFileName ? pidReportPath : reportPath;
169 | const currentReport = fs.readJsonSync(currentReportPath);
170 |
171 | currentReport.map((singleReport) => {
172 | const featureName = singleReport.name.replace(/\s+/g, '_').replace(/\W/g, '').toLowerCase() || 'noName';
173 | const browserVersion = PID_INSTANCE_DATA.metadata.browser.version === ''
174 | ? ''
175 | : `.${PID_INSTANCE_DATA.metadata.browser.version}`;
176 | const plaformName = PID_INSTANCE_DATA.metadata.platform.name === ''
177 | ? ''
178 | : `.${PID_INSTANCE_DATA.metadata.platform.name}`;
179 | const plaformVersion = PID_INSTANCE_DATA.metadata.platform.version === ''
180 | ? ''
181 | : `.${PID_INSTANCE_DATA.metadata.platform.version}`;
182 | let fileName = `${featureName}.${PID_INSTANCE_DATA.metadata.browser.name}`;
183 |
184 | fileName += browserVersion + plaformName + plaformVersion;
185 | const filePath = path.join(PLUGIN_CONFIG.jsonOutputPath, `${fileName}_${Date.now()}.json`);
186 |
187 | /**
188 | * If needed remove the previous file if it exists to prevent double reports of 1 feature + browser execution
189 | */
190 | if (PLUGIN_CONFIG.removeExistingJsonReportFile) {
191 | fs.readdirSync(PLUGIN_CONFIG.jsonOutputPath)
192 | .filter((file) => file.match(new RegExp(fileName, 'ig')))
193 | .forEach((file) => fs.removeSync(path.resolve(PLUGIN_CONFIG.jsonOutputPath, file)));
194 | }
195 |
196 | /**
197 | * Add the metadata from the running instance to the report
198 | */
199 | singleReport.metadata = PID_INSTANCE_DATA.metadata;
200 |
201 | /**
202 | * Save the file
203 | */
204 | fs.writeJsonSync(filePath, JSON.parse(`[${ JSON.stringify(singleReport) }]`), { spaces: 2 });
205 | });
206 |
207 | /**
208 | * Remove the original json report file, defined in the `cucumberOpts.format` if needed
209 | */
210 | if (PLUGIN_CONFIG.removeOriginalJsonReportFile) {
211 | fs.removeSync(currentReportPath);
212 | }
213 |
214 | if ((PLUGIN_CONFIG.customData || PLUGIN_CONFIG.reportName) && !PLUGIN_CONFIG.automaticallyGenerateReport) {
215 | console.warn(`
216 | ===========================================================================
217 | YOU ADDED A CUSTOM reportName AND OR ADDED A cucsomerData-object
218 | WITHOUT SETTING 'automaticallyGenerateReport: true'.
219 |
220 | !!!THIS WILL NOT RESULT IN SETTING THE CUSTOM DATA IN THE REPORT!!!
221 | ===========================================================================`);
222 | }
223 |
224 | /**
225 | * Generate the HTML report if needed
226 | */
227 | if (PLUGIN_CONFIG.automaticallyGenerateReport) {
228 | /**
229 | * If the reportPath is still default, then add the default folder to the same folder
230 | * where the results are stored
231 | */
232 | if (PLUGIN_CONFIG.reportPath === REPORT_FOLDER) {
233 | PLUGIN_CONFIG.reportPath = path.join(PLUGIN_CONFIG.cucumberResultsPath, REPORT_FOLDER);
234 | }
235 |
236 | const multiCucumberHTLMReporterConfig = {
237 | customMetadata: PLUGIN_CONFIG.customMetadata,
238 | displayDuration: PLUGIN_CONFIG.displayDuration,
239 | durationInMS: PLUGIN_CONFIG.durationInMS,
240 | disableLog: PLUGIN_CONFIG.disableLog,
241 | jsonDir: PLUGIN_CONFIG.jsonOutputPath,
242 | openReportInBrowser: PLUGIN_CONFIG.openReportInBrowser,
243 | reportPath: PLUGIN_CONFIG.reportPath,
244 | saveCollectedJSON: PLUGIN_CONFIG.saveCollectedJSON
245 | };
246 |
247 | /**
248 | * Add the custom data if needed
249 | */
250 | if (PLUGIN_CONFIG.customData) {
251 | multiCucumberHTLMReporterConfig.customData = PLUGIN_CONFIG.customData;
252 | }
253 |
254 | /**
255 | * Add the custom css if needed
256 | */
257 | if (PLUGIN_CONFIG.customStyle !== '') {
258 | multiCucumberHTLMReporterConfig.customStyle = PLUGIN_CONFIG.customStyle;
259 | }
260 |
261 | /**
262 | * Add the override css if needed
263 | */
264 | if (PLUGIN_CONFIG.overrideStyle !== '') {
265 | multiCucumberHTLMReporterConfig.overrideStyle = PLUGIN_CONFIG.overrideStyle;
266 | }
267 |
268 | /**
269 | * Add the pageFooter if needed
270 | */
271 | if (PLUGIN_CONFIG.pageFooter) {
272 | multiCucumberHTLMReporterConfig.pageFooter = PLUGIN_CONFIG.pageFooter;
273 | }
274 |
275 | /**
276 | * Add the pageTitle if needed
277 | */
278 | if (PLUGIN_CONFIG.pageTitle) {
279 | multiCucumberHTLMReporterConfig.pageTitle = PLUGIN_CONFIG.pageTitle;
280 | }
281 |
282 | /**
283 | * Add the custom report name if needed
284 | */
285 | if (PLUGIN_CONFIG.reportName) {
286 | multiCucumberHTLMReporterConfig.reportName = PLUGIN_CONFIG.reportName;
287 | }
288 |
289 | multiCucumberHTLMReporter.generate(multiCucumberHTLMReporterConfig);
290 | }
291 | } else {
292 | console.warn(`\n### File: '${reportPath}' or '${pidReportPath}' is not present! ###\n`);
293 | }
294 | }
295 | }
296 |
297 | // Exports
298 | exports.onPrepare = onPrepare;
299 | exports.postResults = postResults;
300 | exports.setup = setup;
301 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "protractor-multiple-cucumber-html-reporter-plugin",
3 | "version": "1.8.1",
4 | "description": "A protractor plugin to use multiple-cucumber-html-reporter with CucumberJs 1, 2 or 3",
5 | "main": "index.js",
6 | "scripts": {
7 | "lint": "node_modules/.bin/eslint *.js test/**/*.js",
8 | "pretest": "webdriver-manager update",
9 | "release": "np",
10 | "test": "npm run lint && node node_modules/.bin/jasmine ./test/test.spec.js",
11 | "test.single": "./node_modules/.bin/protractor ./test/cucumber/config/full-options.conf.js"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin.git"
16 | },
17 | "keywords": [
18 | "protractor",
19 | "cucumber",
20 | "html",
21 | "test report",
22 | "multiple-cucumber-html-reporter",
23 | "html report",
24 | "json to html"
25 | ],
26 | "author": "wswebcreation",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin/issues"
30 | },
31 | "homepage": "https://github.com/wswebcreation/protractor-multiple-cucumber-html-reporter-plugin#readme",
32 | "devDependencies": {
33 | "cucumber": "^5.1.0",
34 | "eslint": "^4.11.0",
35 | "glob": "^7.1.2",
36 | "np": "^5.0.2",
37 | "protractor": "^5.4.1",
38 | "protractor-cucumber-framework": "^6.1.1"
39 | },
40 | "peerDependencies": {
41 | "cucumber": ">= 1.3.0 || >= 2.0.0 || >= 3.0.0",
42 | "protractor-cucumber-framework": ">= 3.1.2",
43 | "protractor": ">= 4.0.0"
44 | },
45 | "dependencies": {
46 | "fs-extra": "^3.0.1",
47 | "multiple-cucumber-html-reporter": "^1.11.7"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/test/css/custom.css:
--------------------------------------------------------------------------------
1 | .custom {
2 | width: 100%;
3 | }
4 |
--------------------------------------------------------------------------------
/test/css/override.css:
--------------------------------------------------------------------------------
1 | .override {
2 | height: 100%;
3 | }
4 |
--------------------------------------------------------------------------------
/test/cucumber/config/full-options.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const config = require('./protractor.shared.conf').config;
3 |
4 | config.multiCapabilities = [{
5 | 'browserName': 'chrome',
6 | 'shardTestFiles': false,
7 | 'maxInstances': 2,
8 | 'goog:chromeOptions': {
9 | args: ['--headless']
10 | },
11 | 'deviceProperties': {
12 | browser: {
13 | name: 'chrome',
14 | version: 'latest'
15 | },
16 | device: 'local development machine',
17 | platform: {
18 | name: 'osx',
19 | version: '10.12.6'
20 | }
21 | }
22 | }];
23 |
24 | config.plugins = [{
25 | path: path.resolve(process.cwd(), './'),
26 | options: {
27 | automaticallyGenerateReport: true,
28 | jsonOutputPath: './json-output-path/',
29 | metadataKey: 'deviceProperties',
30 | reportPath: './report-path/',
31 | removeExistingJsonReportFile: true,
32 | removeOriginalJsonReportFile: true,
33 | saveCollectedJSON: true,
34 | reportName: 'You can adjust this report name',
35 | pageFooter: '',
36 | pageTitle: 'A custom page title',
37 | customData: {
38 | title: 'Run info',
39 | data: [
40 | { label: 'Project', value: 'Custom project' },
41 | { label: 'Release', value: '1.2.3' }
42 | ]
43 | },
44 | displayDuration: true,
45 | customMetadata: true,
46 | customStyle: path.join(__dirname, './../../css/custom.css'),
47 | overrideStyle: path.join(__dirname, './../../css/override.css')
48 | }
49 | }];
50 |
51 | exports.config = config;
52 |
--------------------------------------------------------------------------------
/test/cucumber/config/no-log.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const config = require('./protractor.shared.conf').config;
3 |
4 | config.multiCapabilities = [{
5 | 'browserName': 'chrome',
6 | 'shardTestFiles': false,
7 | 'maxInstances': 2,
8 | 'goog:chromeOptions': {
9 | args: ['--headless']
10 | },
11 | 'deviceProperties': {
12 | browser: {
13 | name: 'chrome',
14 | version: 'latest'
15 | },
16 | device: 'local development machine',
17 | platform: {
18 | name: 'osx',
19 | version: '10.12.6'
20 | }
21 | }
22 | }];
23 |
24 | config.plugins = [{
25 | path: path.resolve(process.cwd(), './'),
26 | options: {
27 | automaticallyGenerateReport: true,
28 | disableLog: true
29 | }
30 | }];
31 |
32 | exports.config = config;
33 |
--------------------------------------------------------------------------------
/test/cucumber/config/no-options.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const config = require('./protractor.shared.conf').config;
3 |
4 | config.capabilities = {
5 | 'browserName': 'chrome',
6 | 'shardTestFiles': false,
7 | 'maxInstances': 2,
8 | 'goog:chromeOptions': {
9 | args: ['--headless']
10 | },
11 | 'deviceProperties': {
12 | browser: {
13 | name: 'chrome',
14 | version: 'latest'
15 | },
16 | device: 'local development machine',
17 | platform: {
18 | name: 'osx',
19 | version: '10.12.6'
20 | }
21 | }
22 | };
23 |
24 | config.plugins = [{
25 | path: path.resolve(process.cwd(), './')
26 | }];
27 |
28 | exports.config = config;
29 |
--------------------------------------------------------------------------------
/test/cucumber/config/protractor.shared.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | exports.config = {
4 |
5 | framework: 'custom',
6 | frameworkPath: require.resolve('protractor-cucumber-framework'),
7 | cucumberOpts: {
8 | require: [
9 | path.resolve(process.cwd(), './test/cucumber/**/*steps.js')
10 | ],
11 | format: 'json:.tmp/results.json',
12 | strict: true
13 | },
14 |
15 | specs: [
16 | path.resolve(process.cwd(), './test/cucumber/**/*.feature')
17 | ]
18 | };
19 |
--------------------------------------------------------------------------------
/test/cucumber/features/foo.feature:
--------------------------------------------------------------------------------
1 | Feature: Foo until you bar
2 |
3 | Scenario: I want to foo
4 | Given I foo
5 | When I foo it
6 | Then I foo the bar
7 |
--------------------------------------------------------------------------------
/test/cucumber/features/generate.report.feature:
--------------------------------------------------------------------------------
1 | Feature: Generate a JSON file
2 |
3 | Scenario: I want to generate a report
4 | Given I do something
5 | When I verified it
6 | Then a report will be created
7 |
--------------------------------------------------------------------------------
/test/cucumber/step_definitions/steps.js:
--------------------------------------------------------------------------------
1 | const { Before, Given, When, Then } = require('cucumber');
2 |
3 | // Before(() => Promise.reject('Error'));
4 |
5 | Given('I do something', () => Promise.resolve('I do something'));
6 |
7 | Given('I foo', () => Promise.resolve('I foo'));
8 |
9 | When('I verified it', () => Promise.resolve('I verified it'));
10 |
11 | When('I foo it', () => Promise.resolve('I foo it'));
12 |
13 | Then('a report will be created', () => Promise.resolve('a report will be created'));
14 |
15 | Then('I foo the bar', () => Promise.resolve('I foo the bar'));
16 |
--------------------------------------------------------------------------------
/test/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "test/",
3 | "spec_files": [
4 | "*.spec.js"
5 | ],
6 | "stopSpecOnExpectationFailure": false,
7 | "random": false
8 | }
9 |
--------------------------------------------------------------------------------
/test/test.spec.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const path = require('path');
3 | const util = require('./test_util');
4 |
5 | const BROWSER_NAME = 'chrome';
6 | const CUCUMBER_RESULTS_FILE_PATH = path.resolve(process.cwd(), './.tmp/');
7 | const CUCUMBER_RESULTS_FILE_NAME = 'results';
8 | const CUCUMBER_RESULTS = `${CUCUMBER_RESULTS_FILE_PATH}/${CUCUMBER_RESULTS_FILE_NAME}`;
9 | const JSON_OUTPUT_PATH = path.resolve(CUCUMBER_RESULTS_FILE_PATH, 'json-output-folder');
10 | const CUCUMBER_FOO_FEATURE_NAME = 'foo_until_you_bar';
11 | const CUCUMBER_GENERATE_FEATURE_NAME = 'generate_a_json_file';
12 |
13 | describe('validate plugin and all the options', () => {
14 | beforeEach(() => {
15 | fs.removeSync(CUCUMBER_RESULTS_FILE_PATH);
16 | });
17 |
18 | it('should create 2 unique json report files with all the defaults', () => {
19 | const cmd = 'test/cucumber/config/no-options.conf.js';
20 |
21 | return util
22 | .runOne(cmd)
23 | .after(() => {
24 | const cucumberFoo = `${JSON_OUTPUT_PATH}/${CUCUMBER_FOO_FEATURE_NAME}`;
25 | const cucumberGenerate = `${JSON_OUTPUT_PATH}/${CUCUMBER_GENERATE_FEATURE_NAME}`;
26 | const cucumberResults = util.findJsonReportFiles(CUCUMBER_RESULTS)[0];
27 | const fooResults = util.findJsonReportFiles(cucumberFoo)[0];
28 | const generateResults = util.findJsonReportFiles(cucumberGenerate)[0];
29 | const fooJson = fs.readJsonSync(fooResults);
30 | const generateJson = fs.readJsonSync(generateResults);
31 |
32 | // Check original JSON still exists => default `removeOriginalJsonReportFile = false`
33 | expect(cucumberResults).toEqual(`${CUCUMBER_RESULTS}.json`);
34 |
35 | // Check if the jsonOutputPath is default => `jsonOutputPath: './.tmp/json-output-path/'`
36 | expect(fooResults).toContain(`${cucumberFoo}.${BROWSER_NAME}`);
37 |
38 | // Check not metadata has been added from the capability
39 | expect(fooJson[0].metadata.browser.name).toEqual(BROWSER_NAME);
40 | expect(/(\d+)./.test(fooJson[0].metadata.browser.version)).toEqual(true);
41 | expect(fooJson[0].metadata.device).toEqual('');
42 | expect(fooJson[0].metadata.platform.name).toEqual('');
43 | expect(fooJson[0].metadata.platform.version).toEqual('');
44 |
45 | // Check if the jsonOutputPath is default => `jsonOutputPath: './.tmp/json-output-path/'`
46 | expect(generateResults).toContain(`${cucumberGenerate}.${BROWSER_NAME}`);
47 |
48 | // Check not metadata has been added from the capability
49 | expect(generateJson[0].metadata.browser.name).toEqual(BROWSER_NAME);
50 | expect(/(\d+)./.test(generateJson[0].metadata.browser.version)).toEqual(true);
51 | expect(generateJson[0].metadata.device).toEqual('');
52 | expect(generateJson[0].metadata.platform.name).toEqual('');
53 | expect(generateJson[0].metadata.platform.version).toEqual('');
54 | })
55 | .run();
56 | }, 11000);
57 |
58 | it('should validate all options and output', () => {
59 | const cmd = 'test/cucumber/config/full-options.conf.js';
60 | const jsonOutputPath = path.resolve(process.cwd(), './json-output-path');
61 | const reportPath = path.resolve(process.cwd(), './report-path');
62 |
63 | // Clear the state
64 | fs.removeSync(jsonOutputPath);
65 | fs.removeSync(reportPath);
66 |
67 | return util
68 | .runOne(cmd)
69 | .expectOutput('Multiple Cucumber HTML report generated in:')
70 | .after(() => {
71 | const cucumberFoo = `${jsonOutputPath}/${CUCUMBER_FOO_FEATURE_NAME}`;
72 | const cucumberGenerate = `${jsonOutputPath}/${CUCUMBER_GENERATE_FEATURE_NAME}`;
73 | const cucumberResults = util.findJsonReportFiles(CUCUMBER_RESULTS)[0];
74 | const fooResults = util.findJsonReportFiles(cucumberFoo)[0];
75 | const generateResults = util.findJsonReportFiles(cucumberGenerate)[0];
76 | const fooJson = fs.readJsonSync(fooResults);
77 | const generateJson = fs.readJsonSync(generateResults);
78 | const report = path.resolve(`${reportPath}/index.html`);
79 | const reportMergedJonOutput = path.resolve(`${reportPath}/merged-output.json`);
80 | const reportEnrichedJsonOutput = path.resolve(`${reportPath}/enriched-output.json`);
81 | const reportEnrichedJson = fs.readJsonSync(reportEnrichedJsonOutput);
82 | const reportContent = fs.readFileSync(report, 'utf8');
83 |
84 | // Check original JSON has been removed => `removeOriginalJsonReportFile = true`
85 | expect(cucumberResults).not.toBeDefined();
86 |
87 | // Check if the jsonOutputPath has been changed => `jsonOutputPath: './json-output-path/'`
88 | expect(fooResults).toContain(`${cucumberFoo}.${BROWSER_NAME}`);
89 |
90 | // Check all metadata has been added from the capability
91 | expect(fooJson[0].metadata.browser.name).toEqual(BROWSER_NAME);
92 | expect(/(\d+)./.test(fooJson[0].metadata.browser.version)).toEqual(true);
93 | expect(fooJson[0].metadata.device).toEqual('local development machine');
94 | expect(fooJson[0].metadata.platform.name).toEqual('osx');
95 | expect(fooJson[0].metadata.platform.version).toEqual('10.12.6');
96 |
97 | // Check if the jsonOutputPath has been changed => `jsonOutputPath: './json-output-path/'`
98 | expect(generateResults).toContain(`${cucumberGenerate}.${BROWSER_NAME}`);
99 |
100 | // Check all metadata has been added from the capability
101 | expect(generateJson[0].metadata.browser.name).toEqual(BROWSER_NAME);
102 | expect(/(\d+)./.test(generateJson[0].metadata.browser.version)).toEqual(true);
103 | expect(generateJson[0].metadata.device).toEqual('local development machine');
104 | expect(generateJson[0].metadata.platform.name).toEqual('osx');
105 | expect(generateJson[0].metadata.platform.version).toEqual('10.12.6');
106 |
107 | // Check if the report path has been created with the report in it `reportPath: './report-path/'`
108 | expect(fs.existsSync(report)).toEqual(true);
109 |
110 | // Merged and enriched file has been saved => `saveCollectedJSON: true`
111 | expect(fs.existsSync(reportMergedJonOutput)).toEqual(true);
112 | expect(fs.existsSync(reportEnrichedJsonOutput)).toEqual(true);
113 |
114 | // Check that the report name has been added to the enriched file
115 | expect(reportEnrichedJson.reportName).toEqual('You can adjust this report name');
116 | expect(reportEnrichedJson.customData.title).toEqual('Run info');
117 | expect(reportEnrichedJson.customData.data).toEqual([
118 | { label: 'Project', value: 'Custom project' },
119 | { label: 'Release', value: '1.2.3' }
120 | ]);
121 |
122 | // Check that the customMetadata has been set
123 | expect(reportEnrichedJson.customMetadata).toEqual(true);
124 |
125 | // Check that the displayDuration has been set
126 | expect(reportEnrichedJson.displayDuration).toEqual(true);
127 |
128 | // Check that customStyle has been set
129 | expect(reportContent).toContain('.custom');
130 |
131 | // Check that overrideStyle has been set
132 | expect(reportContent).toContain('.override');
133 | // Check that default style has been overridden
134 | expect(reportContent).not.toContain('.main_conainer');
135 |
136 | })
137 | .run();
138 | }, 11000);
139 |
140 | it('should not print the log', () => {
141 | const cmd = 'test/cucumber/config/no-log.conf.js';
142 |
143 | return util
144 | .runOne(cmd)
145 | .expectOutput('Running 1 instances of WebDriver')
146 | .run();
147 | }, 11000);
148 | });
149 |
--------------------------------------------------------------------------------
/test/test_util.js:
--------------------------------------------------------------------------------
1 | // Source: https://github.com/protractor-cucumber-framework/protractor-cucumber-framework/blob/master/test/test_util.js
2 | // Adjusted for own tests
3 |
4 | const glob = require('glob');
5 | const child_process = require('child_process');
6 |
7 | const CommandlineTest = function (command) {
8 | const that = this;
9 |
10 | this.command_ = command;
11 | this.expectedExitCode_ = 0;
12 | this.expectedOutput_ = [];
13 | this.expectExitCode = function (exitCode) {
14 | that.expectedExitCode_ = exitCode;
15 | return that;
16 | };
17 |
18 | this.after = function (callback) {
19 | that.after_ = callback;
20 | return that;
21 | };
22 |
23 | this.expectOutput = function (output) {
24 | that.expectedOutput_.push(output);
25 | return that;
26 | };
27 |
28 | this.run = function () {
29 | let output = '';
30 |
31 | const flushAndFail = (errorMsg) => {
32 | process.stdout.write(output);
33 | throw new Error(errorMsg);
34 | };
35 |
36 | return new Promise((resolve, reject) => {
37 | const args = that.command_.split(/\s/);
38 | let test_process;
39 |
40 | test_process = child_process.spawn(args[0], args.slice(1));
41 | test_process.stdout.on('data', (data) => {
42 | output += data
43 | });
44 | test_process.stderr.on('data', (data) => {
45 | output += data
46 | });
47 | test_process.on('error', (err) => reject(err));
48 | test_process.on('exit', (exitCode) => resolve(exitCode));
49 | })
50 | .then((exitCode) => {
51 | if (that.expectedExitCode_ !== exitCode) {
52 | flushAndFail(
53 | `expecting exit code: ${that.expectedExitCode_}, actual: ${exitCode}`
54 | );
55 | }
56 |
57 | that.expectedOutput_.forEach((out) => {
58 | if (output.indexOf(out) < 0) {
59 | flushAndFail(`expecting output '${out}' in '${output}'`);
60 | }
61 | });
62 |
63 | if (that.after_) {
64 | that.after_();
65 | }
66 | });
67 | };
68 | };
69 |
70 | /**
71 | *
72 | * @param {string} options
73 | * @returns {CommandlineTest}
74 | */
75 | function runOne(options) {
76 | const test = new CommandlineTest(
77 | `node node_modules/protractor/bin/protractor ${options}`
78 | );
79 |
80 | return test;
81 | }
82 |
83 | /**
84 | * Find json report files
85 | *
86 | * @param {string} pattern
87 | * @returns {Array} array of found files
88 | */
89 | function findJsonReportFiles(pattern) {
90 | return glob.sync(`${pattern}*.json`);
91 | }
92 |
93 | module.exports = {
94 | runOne,
95 | findJsonReportFiles
96 | };
97 |
--------------------------------------------------------------------------------