Giter Site home page Giter Site logo

mochawesome-report-generator's Introduction

mochawesome-report-generator (marge)

npm Node CI

marge (mochawesome-report-generator) is the counterpart to mochawesome, a custom reporter for use with the Javascript testing framework, mocha. Marge takes the JSON output from mochawesome and generates a full fledged HTML/CSS report that helps visualize your test suites.

Features

Mochawesome Report

  • Simple, clean, and modern design
  • Support for test and suite nesting
  • Displays before and after hooks
  • Review test code inline
  • Stack trace for failed tests
  • Support for adding context information to tests
  • Filters to display only the tests you want
  • Responsive and mobile-friendly
  • Offline viewing
  • CLI for generating reports independent of mochawesome

Usage with mochawesome

  1. Add Mochawesome to your project:

npm install --save-dev mochawesome

  1. Tell mocha to use the Mochawesome reporter:

mocha testfile.js --reporter mochawesome

  1. If using mocha programatically:
var mocha = new Mocha({
  reporter: 'mochawesome'
});

CLI Usage

Install mochawesome-report-generator package

npm install -g mochawesome-report-generator

Run the command

marge [options] data_file [data_file2 ...]

Output

marge generates the following inside your project directory:

mochawesome-report/
├── assets
│   ├── app.css
│   ├── app.js
│   ├── MaterialIcons-Regular.woff
│   ├── MaterialIcons-Regular.woff2
│   ├── roboto-light-webfont.woff
│   ├── roboto-light-webfont.woff2
│   ├── roboto-medium-webfont.woff
│   ├── roboto-medium-webfont.woff2
│   ├── roboto-regular-webfont.woff
│   └── roboto-regular-webfont.woff2
└── mochawesome.html

Options

CLI Flags

marge can be configured via the following command line flags:

Flag Type Default Description
-f, --reportFilename string mochawesome Filename of saved report. See notes for available token replacements.
-o, --reportDir string [cwd]/mochawesome-report Path to save report
-t, --reportTitle string mochawesome Report title
-p, --reportPageTitle string mochawesome-report Browser title
-i, --inline boolean false Inline report assets (scripts, styles)
--cdn boolean false Load report assets via CDN (unpkg.com)
--assetsDir string [cwd]/mochawesome-report/assets Path to save report assets (js/css)
--charts boolean false Display Suite charts
--code boolean true Display test code
--autoOpen boolean false Automatically open the report
--overwrite boolean true Overwrite existing report files. See notes.
--timestamp, --ts string Append timestamp in specified format to report filename. See notes.
--showPassed boolean true Set initial state of "Show Passed" filter
--showFailed boolean true Set initial state of "Show Failed" filter
--showPending boolean true Set initial state of "Show Pending" filter
--showSkipped boolean false Set initial state of "Show Skipped" filter
--showHooks string failed Set the default display mode for hooks
failed: show only failed hooks
always: show all hooks
never: hide all hooks
context: show only hooks that have context
--saveJson boolean false Should report data be saved to JSON file
--saveHtml boolean true Should report be saved to HTML file
--dev boolean false Enable dev mode (requires local webpack dev server)
-h, --help Show CLI help

Boolean options can be negated by adding --no before the option. For example: --no-code would set code to false.

reportFilename replacement tokens

Using the following tokens it is possible to dynamically alter the filename of the generated report.

  • [name] will be replaced with the spec filename when possible.
  • [status] will be replaced with the status (pass/fail) of the test run.
  • [datetime] will be replaced with a timestamp. The format can be - specified using the timestamp option.

For example, given the spec cypress/integration/sample.spec.js and the following config:

{
  reporter: "mochawesome",
  reporterOptions: {
    reportFilename: "[status]_[datetime]-[name]-report",
    timestamp: "longDate"
  }
}

The resulting report file will be named pass_February_23_2022-sample-report.html

Note: The [name] replacement only occurs when mocha is running one spec file per process and outputting a separate report for each spec. The most common use-case is with Cypress.

overwrite

By default, report files are overwritten by subsequent report generation. Passing --overwrite=false will not replace existing files. Instead, if a duplicate filename is found, the report will be saved with a counter digit added to the filename. (ie. mochawesome_001.html).

Note: overwrite will always be false when passing multiple files or using the timestamp option.

timestamp

The timestamp option can be used to append a timestamp to the report filename. It uses dateformat to parse format strings so you can pass any valid string that dateformat accepts with a few exceptions. In order to produce valid filenames, the following replacements are made:

Characters Replacement Example Output
spaces, commas underscore Wed March 29, 2017 Wed_March_29_2017
slashes hyphen 3/29/2017 3-29-2017
colons null 17:46:21 174621

If you pass true as the format string, it will default to isoDateTime.

mochawesome reporter-options

The above CLI flags can be used as reporter-options when using the mochawesome reporter.

Use them in a .mocharc.js file:

module.exports = {
    reporter: 'node_modules/mochawesome',
    'reporter-option': [
        'overwrite=true',
        'reportTitle=My\ Custom\ Title',
        'showPassed=false'
    ],
};

or as an object when using mocha programmatically:

const mocha = new Mocha({
  reporter: 'mochawesome',
  reporterOptions: {
    overwrite: true,
    reportTitle: 'My Custom Title',
    showPassed: false
  }
});

Development

To develop locally, clone the repo and install dependencies. In order to test end-to-end you must also clone mochawesome into a directory at the same level as this repo.

You can start the dev server with npm run devserver. If you are working on the CLI, use npm run dev:cli to watch for changes and rebuild.

Running Tests

Unit Tests

To run unit tests, simply use npm run test. You can also run a single unit test with npm run test:single path/to/test.js.

Functional Tests

Functional tests allow you to run real-world test cases in order to debug the output report. First, start up the dev server in one terminal window with npm run devserver. Then, in another window, run the tests with npm run test:functional. This will generate a report that you can open in the browser and debug.

If you want to run a specific folder of functional tests: npm run test:functional path/to/tests

Or if you want to run a single test: npm run test:functional path/to/test.js

Or mix and match: npm run test:functional path/to/some/tests path/to/another/test.js

mochawesome-report-generator's People

Contributors

adamgruber avatar gidztech avatar irvinlim avatar nicholasboll avatar wking avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mochawesome-report-generator's Issues

Feature Request: Filter by Capability

Hey Adam!

I'm using Mochawesome Report Generator alongside WebDriverIO and wdio-mochawesome-reporter to generate reports for our end-to-end tests across multiple browsers. So far, this is perfect when running only in Chrome. But the reports generated become quite redundant and disorganized once each test file is run across multiple browsers.

What I would like to see added (and I am certainly willing to contribute code) is better support for handling multiple capabilities. The first and least complex step seems to be to allow for filtering by capability.

The more complex solution is to group multiple capabilities for the same test into a single block, but I suspect that would be the responsibility of the reporter and not the report generator (see: http://webdriver.io/v3.4/guide/testrunner/reporters.html#Spec-Reporter).

Here's a UI mock for what I'm imagining; does that seem doable, or should this just move upstream to the reporter?

Filter by Capability

And thanks so much for building mochawesome report generator! It's fantastic.

Auto expand option for context

I looked through the doc but didn't see this option available. I'd like see if there is a possibility for a contextAutoExpand option. In the tests I'm working on, the screenshot images are important references, and visually it will make more sense it they are auto expanded.

Ability to provide html snippets for test title

I would like to be able to make my test titles more descriptive for the business folks and would like the ability to add html snippets like <ul>, <ol> etc. Let me know if that is something you would consider adding to the library and I can provide a pull request. Also, any pointers as to how you would go about doing it would be appreciated as well, hoping it is a simple change to the Test component. Thanks.

Search

Filter tests via text search.

Implement keyboard navigation

The report does not currently support keyboard navigation. I think it should.

  • Tab through tests
  • Space to toggle tests open/closed
  • Shortcut to open nav menu
  • Close nav menu on ESC
  • Shortcuts for toggling filters

can we use this reporter in jest

I'm looking for the reporter that can append the result not to override and this reporter can do that. So, I want to use this reporter in jest if I able to do so. kindly let me know.

run generator from code

Hey there,
I have simple question:
Currently docs are only telling running a command in cli. For my case I i have multiple Test json files that can be simply merged by my code but then after running all tests and merge them I want to generate the html output with the generator. So now the question is if I can run this also from code base instead of cli.

greetings
Geramy92

Optmize for thousands of test cases

I have 2600+ test cases, and the generated mochawesome.html file needs 14 seconds to be opened by Chrome.

Is there any idea to optmize it?

PS: The generated mochawesome.html file is 10MB and mochawesome.json is 8.2MB

Wildcard support

Is it easy to add a wildcard functionality, something like marge reports/*.json --options?
I have no idea how to do that :(...

Thanks!

PDF Reports

It would be nice to be able to export the report into PDF. I am thinking of integrating this with a Slack bot which will run tests, and export the document via PDF and upload it to a channel. I am finding it a bit of a pain to convert the HTML into PDF (have to use like headless chrome to load the page, then print it in PDF).

Threoretical question: Programmatic usage and receiving results as objects

Hi!

I doing some research about some reporter for mocha to be used inside AWS lambda function.

Since lambda has readonly file system, i need to receive JSON results as object, not as file. Then i will pass that json as response to caller, where i will grab all those objects, and generate HTML on caller side(host that ivoked lambda).

Sure i understand that this is pretty crazy usage, most of all i will fork this repo and rewrite some parts to make that happen. But can you guys point me to right direction to make that fast?

So what i need

  • get results as object instead of JSON file. Probably i can monkey-patch some NodeJS fs functions to intercept saving to file call.

  • Grab array of JSON results, and generate HTML from them

  • Attachments and so on not planned yet.

Show context images smaller with ability to zoom

Context images are set to max-width: 100% by default. As screenshots can be large this can disrupt the flow of the report. Suggest making images smaller by default with an option to enlarge or zoom on click. Current click behavior opens the image in a new window so this functionality would need to be retained as well.

Context on Suite

Hi,

Is there the ability to add "context" (or even just HTML) at the suite level, not the individual test level?

Thanks! :)

Pulling the generated link from unpkg.com returns 404

I don't know why but for some strange reasons I was trying to load assets from a CDN using the cdn:true option but my generated report was trying to load the following javascript file that didn't exist on unpkg.com and it was returning 404 for a while. After I regenerated my report and hit multiple times the refresh button It got fixed.

File

https://unpkg.com/[email protected]/dist/app.js

Result

Cannot find module "/dist/app.js" in package [email protected]

mocha-report-bug

Bug: report considers skipped tests as failed

I'm using your report with Cypress. I have one skipped Cypress test:

Screenshot 2019-07-25 at 14 39 35

Expected: either 100% tests passed (green); or 93% passed and 7% tests skipped (grey)
Actual: bar shows red and 7% of tests failed, which is not true

It looks to me your report considers skipped tests as failed

Option to pull assets from a CDN

Currently mochawesome supports inline and external assets. External assets are copied into an assets/ folder in the directory where the report is generated. Copying these assets adds overhead. In the case where generating multiple reports into different locations, this overhead may be considered undesirable. Inlining the assets would solve the issue but also bloat the report filesize.

If the assets were requested via CDN like unpkg.com then the overhead would be eliminated. I propose adding this as an option.

Obvious note: Serving the assets via CDN requires an internet connection when viewing the report.

Long test names are truncated

As this example shows, long test titles are truncated. However, there is currently no way to see the full test title.

32666231-604a38b2-c5fc-11e7-8110-98c7ca5cbf24

Possible solutions

  • Show full test title when test is expanded
  • Add title attribute to the <h4> so hovering will show the full test title

Some files could not be processed

Followed all the instructions but I'm getting an error message:

am I missing something?

✘ Some files could not be processed:
mochawesome-report.json

below is the output:

✘ Some files could not be processed:
mochawesome-report.json
  Invalid value {
  "title": "should have the Dashboard selected on the left hand menu",
  "fullTitle": "should have the Dashboard selected on the left hand menu",
  "timedOut": false,
  "duration": 86,
  "speed": "fast",
  "pass": true,
  "fail": false,
  "pending": false,
  "code": "",
  "isRoot": false,
  "uuid": "7ec36917-e8bd-4f32-8a9b-63a7fca4e839",
  "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
  "skipped": false,
  "isHook": false,
  "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
  "state": "passed",
  "err": {}
} supplied to /suites/suites/0/passes/0: String
  Invalid value {
  "title": "should have an Aggregate panel",
  "fullTitle": "should have an Aggregate panel",
  "timedOut": false,
  "duration": 1588,
  "speed": "fast",
  "pass": true,
  "fail": false,
  "pending": false,
  "code": "",
  "isRoot": false,
  "uuid": "bced4b42-4438-4903-ae0e-b82d85be0d07",
  "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
  "skipped": false,
  "isHook": false,
  "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
  "state": "passed",
  "err": {}
} supplied to /suites/suites/0/passes/1: String
  Invalid value {
  "title": "should have a Curate panel",
  "fullTitle": "should have a Curate panel",
  "timedOut": false,
  "duration": 80,
  "speed": "fast",
  "pass": true,
  "fail": false,
  "pending": false,
  "code": "",
  "isRoot": false,
  "uuid": "f84af609-0237-483c-aa9a-f34f1de23ebe",
  "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
  "skipped": false,
  "isHook": false,
  "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
  "state": "passed",
  "err": {}
} supplied to /suites/suites/0/passes/2: String
  Invalid value {
  "title": "should have a Display panel",
  "fullTitle": "should have a Display panel",
  "timedOut": false,
  "duration": 86,
  "speed": "fast",
  "pass": true,
  "fail": false,
  "pending": false,
  "code": "",
  "isRoot": false,
  "uuid": "7c5a05f3-d161-4725-9e82-3421ee810320",
  "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
  "skipped": false,
  "isHook": false,
  "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
  "state": "passed",
  "err": {}
} supplied to /suites/suites/0/passes/3: String
  Invalid value true supplied to /suites/suites/0/hasTests: Nil
  Invalid value false supplied to /suites/suites/0/hasSuites: Nil
  Invalid value 4 supplied to /suites/suites/0/totalTests: Nil
  Invalid value 4 supplied to /suites/suites/0/totalPasses: Nil
  Invalid value 0 supplied to /suites/suites/0/totalFailures: Nil
  Invalid value 0 supplied to /suites/suites/0/totalPending: Nil
  Invalid value 0 supplied to /suites/suites/0/totalSkipped: Nil
  Invalid value true supplied to /suites/suites/0/hasPasses: Nil
  Invalid value false supplied to /suites/suites/0/hasFailures: Nil
  Invalid value false supplied to /suites/suites/0/hasPending: Nil
  Invalid value false supplied to /suites/suites/0/hasSkipped: Nil
  Invalid value false supplied to /suites/suites/0/hasBeforeHooks: Nil
  Invalid value false supplied to /suites/suites/0/hasAfterHooks: Nil
  Invalid value {
  "title": "should be visible",
  "fullTitle": "should be visible",
  "timedOut": false,
  "duration": 62,
  "speed": "fast",
  "pass": true,
  "fail": false,
  "pending": false,
  "code": "",
  "isRoot": false,
  "uuid": "1df6a038-d3b7-40dc-adc7-6efdac3cd1b8",
  "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
  "skipped": false,
  "isHook": false,
  "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
  "state": "passed",
  "err": {}
} supplied to /suites/suites/1/passes/0: String
  Invalid value {
  "title": "should have cycling plugin banners every 5 seconds",
  "fullTitle": "should have cycling plugin banners every 5 seconds",
  "timedOut": false,
  "duration": 12949,
  "speed": "fast",
  "pass": true,
  "fail": false,
  "pending": false,
  "code": "",
  "isRoot": false,
  "uuid": "bf9f568f-924b-4058-9363-3c3a6b054db1",
  "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
  "skipped": false,
  "isHook": false,
  "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
  "state": "passed",
  "err": {}
} supplied to /suites/suites/1/passes/1: String
  Invalid value {
  "title": "should display the correct banner when plugin is selected",
  "fullTitle": "should display the correct banner when plugin is selected",
  "timedOut": false,
  "duration": 654,
  "speed": "fast",
  "pass": true,
  "fail": false,
  "pending": false,
  "code": "",
  "isRoot": false,
  "uuid": "c49704cf-4dba-4548-9843-7973e73a16d8",
  "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
  "skipped": false,
  "isHook": false,
  "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
  "state": "passed",
  "err": {}
} supplied to /suites/suites/1/passes/2: String
  Invalid value true supplied to /suites/suites/1/hasTests: Nil
  Invalid value false supplied to /suites/suites/1/hasSuites: Nil
  Invalid value 3 supplied to /suites/suites/1/totalTests: Nil
  Invalid value 3 supplied to /suites/suites/1/totalPasses: Nil
  Invalid value 0 supplied to /suites/suites/1/totalFailures: Nil
  Invalid value 0 supplied to /suites/suites/1/totalPending: Nil
  Invalid value 0 supplied to /suites/suites/1/totalSkipped: Nil
  Invalid value true supplied to /suites/suites/1/hasPasses: Nil
  Invalid value false supplied to /suites/suites/1/hasFailures: Nil
  Invalid value false supplied to /suites/suites/1/hasPending: Nil
  Invalid value false supplied to /suites/suites/1/hasSkipped: Nil
  Invalid value false supplied to /suites/suites/1/hasBeforeHooks: Nil
  Invalid value false supplied to /suites/suites/1/hasAfterHooks: Nil
  Invalid value false supplied to /suites/hasTests: Nil
  Invalid value true supplied to /suites/hasSuites: Nil
  Invalid value 0 supplied to /suites/totalTests: Nil
  Invalid value 0 supplied to /suites/totalPasses: Nil
  Invalid value 0 supplied to /suites/totalFailures: Nil
  Invalid value 0 supplied to /suites/totalPending: Nil
  Invalid value 0 supplied to /suites/totalSkipped: Nil
  Invalid value false supplied to /suites/hasPasses: Nil
  Invalid value false supplied to /suites/hasFailures: Nil
  Invalid value false supplied to /suites/hasPending: Nil
  Invalid value false supplied to /suites/hasSkipped: Nil
  Invalid value false supplied to /suites/hasBeforeHooks: Nil
  Invalid value false supplied to /suites/hasAfterHooks: Nil
  Invalid value [
  {
    "title": "should have the Dashboard selected on the left hand menu",
    "fullTitle": "should have the Dashboard selected on the left hand menu",
    "timedOut": false,
    "duration": 86,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "7ec36917-e8bd-4f32-8a9b-63a7fca4e839",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have an Aggregate panel",
    "fullTitle": "should have an Aggregate panel",
    "timedOut": false,
    "duration": 1588,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "bced4b42-4438-4903-ae0e-b82d85be0d07",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have a Curate panel",
    "fullTitle": "should have a Curate panel",
    "timedOut": false,
    "duration": 80,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "f84af609-0237-483c-aa9a-f34f1de23ebe",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have a Display panel",
    "fullTitle": "should have a Display panel",
    "timedOut": false,
    "duration": 86,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "7c5a05f3-d161-4725-9e82-3421ee810320",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should be visible",
    "fullTitle": "should be visible",
    "timedOut": false,
    "duration": 62,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "1df6a038-d3b7-40dc-adc7-6efdac3cd1b8",
    "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have cycling plugin banners every 5 seconds",
    "fullTitle": "should have cycling plugin banners every 5 seconds",
    "timedOut": false,
    "duration": 12949,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "bf9f568f-924b-4058-9363-3c3a6b054db1",
    "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should display the correct banner when plugin is selected",
    "fullTitle": "should display the correct banner when plugin is selected",
    "timedOut": false,
    "duration": 654,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "c49704cf-4dba-4548-9843-7973e73a16d8",
    "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  }
] supplied to /allTests: Nil
  Invalid value [] supplied to /allPending: Nil
  Invalid value [
  {
    "title": "should have the Dashboard selected on the left hand menu",
    "fullTitle": "should have the Dashboard selected on the left hand menu",
    "timedOut": false,
    "duration": 86,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "7ec36917-e8bd-4f32-8a9b-63a7fca4e839",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have an Aggregate panel",
    "fullTitle": "should have an Aggregate panel",
    "timedOut": false,
    "duration": 1588,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "bced4b42-4438-4903-ae0e-b82d85be0d07",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have a Curate panel",
    "fullTitle": "should have a Curate panel",
    "timedOut": false,
    "duration": 80,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "f84af609-0237-483c-aa9a-f34f1de23ebe",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have a Display panel",
    "fullTitle": "should have a Display panel",
    "timedOut": false,
    "duration": 86,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "7c5a05f3-d161-4725-9e82-3421ee810320",
    "parentUUID": "810def88-49c7-4105-b153-66185d5a77b0",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should be visible",
    "fullTitle": "should be visible",
    "timedOut": false,
    "duration": 62,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "1df6a038-d3b7-40dc-adc7-6efdac3cd1b8",
    "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should have cycling plugin banners every 5 seconds",
    "fullTitle": "should have cycling plugin banners every 5 seconds",
    "timedOut": false,
    "duration": 12949,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "bf9f568f-924b-4058-9363-3c3a6b054db1",
    "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  },
  {
    "title": "should display the correct banner when plugin is selected",
    "fullTitle": "should display the correct banner when plugin is selected",
    "timedOut": false,
    "duration": 654,
    "speed": "fast",
    "pass": true,
    "fail": false,
    "pending": false,
    "code": "",
    "isRoot": false,
    "uuid": "c49704cf-4dba-4548-9843-7973e73a16d8",
    "parentUUID": "60d7c9af-a563-4e40-8d39-8232600c982a",
    "skipped": false,
    "isHook": false,
    "context": "[{\"title\":\"Session Id\",\"value\":\"e81deda74470006587047650cf901926\"}]",
    "state": "passed",
    "err": {}
  }
] supplied to /allPasses: Nil
  Invalid value [] supplied to /allFailures: Nil

Investigate filtering via CSS

When the number of tests is large, re-rendering can be very slow. It may be quicker to filter tests via CSS.

Current Filtering Behavior

  • When a filter is toggled the store recomputes the suites object
  • The ReportBody component observes this object and re-renders as needed

Proposed Solution

  • Add a new observable array to the store filteredTests.
  • When a filter is toggled, populate this array with a list of test/suite IDs that should be hidden. Note that filtering is depth-first and works its way up the tree
    • Suites that would be empty after filtering should also be hidden
    • Suites with nested suites that would be hidden after filtering should be hidden
  • Create a component that observes this property and renders CSS to the page to hide the tests/suites:
#filtered-test-id1,
#filtered-test-id2,
#filtered-test-id3,
#filtered-suite-id1,
... { display: none; }

Questions

  • Is hiding via CSS quicker than re-rendering?
  • Is there a limit to the number of inline style declarations?
  • Is there a performance hit from adding a large number of style declarations to the DOM?

Call programmatically

I want to integrate this with Jest, but I don't see how to programmatically call marge. Is there a simple way to pass a JSON payload to marge without creating a new JSON file and calling via CLI?

UX - Pagination

Would be nice to have a form of pagination for large reports. In my case I have a report of 7000+ tests that takes 5-10 seconds to load. One idea is to set a limit of visible items and have a "Show more" button that progressively makes more items visible, or a classic pagination scheme with numbers of items per page.

Reduce bundle size

The bundle size as of 3.0.1 is ~985.95kB. Ideally this would be smaller. According to the webpack analyzer, the bundles is largely inflated due to moment.js and chart.js. It is worth investigating alternatives to these packages.

Don't apply syntax highlighting on addContext strings

This is a follow-up from my previous issue, #35, where I briefly covered the issue with syntax highlighting on contexts added using addContext.

For example, this is what I am passing in:

addContext(this, {
    title: "HTTP Response",
    value: "HTTP/1.1 403 Forbidden\n...."
});

The following is an example of how syntax highlighting is wrongly applied:

screen shot 2017-06-28 at 1 31 32 am

This is what I would expect:

screen shot 2017-06-28 at 1 31 24 am


To summarize, there are currently 4 types of contexts that can be added:

  1. Simple string, i.e. addContext(this, 'this is a string'), which will not apply syntax highlighting
  2. Image URL, i.e. addContext(this, 'https://images.com/cheezburger.gif')
  3. URL, i.e. addContext(this, https://google.com)
  4. Object with the following schema:
addContext(this, {
    title: "My Title",
    value: "" // anything here
})

which will render a context with a h4 header, as shown above.


The problem arises when I use the 4th option (using an object) with a string, which causes the string to have JS highlighting when it is not supposed to.

A simple fix would be to turn off syntax highlighting for all string-typed value values by default, until we offer a third "options" argument for addContext (which we also discussed previously).

In other words, the following is my suggested implementation for renderContextContent in components/test/context.jsx:

renderContextContent = (content, title) => {
  // Images
  if (imgRegEx.test(content)) {
    return this.renderImage(content, title);
  }

  // URLs
  if (urlRegEx.test(content)) {
    return this.renderLink(content, title);
  }

  // Simple strings
  if (isString(content)) {
    return <CodeSnippet className={ cx('code-snippet') } code={ content } highlight={ false } />;
  }

  // All other types, including primitives, objects and arrays should have syntax highlighting
  const code = JSON.stringify(content, null, 2);
  return (
    <CodeSnippet className={ cx('code-snippet') } code={ code } highlight />
  );
}

This might make sense because most people might be using this method to be passing in either strings, primitives, objects or arrays. For all types except for strings, applying syntax highlighting is fine and even encouraged, but as for strings, I'm not sure whether users will use it to pass in JavaScript code.

Do correct me if I'm wrong about that. Otherwise, I could create a PR if you are agreeable with this.

do we have any way to combine multiple test runs report into one report (when running test in parallel)

What are you trying to achieve?
Suppose I am running three test case in parallel mode(i.e. codeceptjs run-multiple parallel) so three report gets generated each have details on one test case each,

But I want one report which has information of all three test run just like test run in normal mode(i.e without parallel mode).

What do you get instead?
three separate reports generated with details of one test case in each report

A retried test doesn't appear in the report when still failed (mocha)

Hello,

I add a retry option on a test which is run with mocha.
When this test is failed, after a retry, it appears in the json file with following status:
"pass": false,
"fail": false,
"pending": false,
...
"skipped": true

So I can see duration, and number of failed test = 1 on top of the report, but I can't see the detail of test. It doesn't appear in the report's body.

Example:

describe(
'Test retries on describe', function () {
this.retries(1);

  it('always failed test', function () {
    expect(1).to.equal(2);
  });

}

You can find the full json report here:
https://gist.github.com/Stephane99/57f23fd5938f71e2e7e49fe9eb543e58

Generate a single report from multiple JSON files

I see two options here.

  1. Merge the JSON files into one long report
  2. Add some kind of tabbed display to show the different reports on one screen

Option 1 is the simpler choice as it only requires merging of data and minimal (if any) updates to the report itself.

Option 2 requires bigger changes to the report components to support tabs and raises questions.

  • Would there be a max number of tabs allowed?
  • How do they behave if there are a lot?
  • How about on smaller screens?
  • Are the tabs ordered?
  • What does the design look like?

3.0 Roadmap

Tasks to complete for 3.0 release

Display test context code without rendering HTML

Is it possible for the test context content to display without rendering as HTML? I noticed that in code-snippet.jsx, the CodeSnippet component uses dangerouslySetInnerHTML.

Is there a reason for this? I am displaying HTML code in the test context and I believe it shouldn't be rendering (since it's a CodeSnippet after all). Plus, this might open up XSS risks (I'm personally using this to generate dynamic test reports).

I would be happy to create a PR to fix this if neeeded.

[request] Expose internal MochawesomeReport React components for rendering test results

Hi! Love the reports, this is great! I'm working on a project to render test run histories on an internal dashboard, but I'm running into issues embedding the generated HTML/JS in a React component. I noticed this library uses React under the hood, so I'm wondering if you could expose the MochawesomeReport component (or a standalone) as an importable React component. It would accept the mochawesome JSON as input.

Thanks!

Invalid value undefined supplied to /suites/suites/0/tests/0/timedOut: Boolean

I am getting the above error with the following json

{
  "stats": {
    "suites": 1,
    "tests": 1,
    "passes": 0,
    "pending": 0,
    "failures": 1,
    "start": "2018-01-22T15:06:36.116Z",
    "end": "2018-01-22T15:06:36.602Z",
    "duration": 486,
    "testsRegistered": 1,
    "passPercent": 0,
    "pendingPercent": 0,
    "other": 0,
    "hasOther": false,
    "skipped": 0,
    "hasSkipped": false,
    "passPercentClass": "danger",
    "pendingPercentClass": "danger"
  },
  "suites": {
    "uuid": "49ace02e-54fe-4939-b896-ca93300bc4f5",
    "title": "",
    "fullFile": "",
    "file": "",
    "beforeHooks": [],
    "afterHooks": [],
    "tests": [],
    "suites": [
      {
        "uuid": "cea92469-5c61-4fdb-8b02-64b2aa4c9657",
        "title": "Add Bank MOP",
        "fullFile": "",
        "file": "",
        "beforeHooks": [],
        "afterHooks": [],
        "tests": [
          {
            "title": "should fail",
            "fullTitle": "Add Bank MOP should fail",
            "duration": 64,
            "state": "failed",
            "pass": false,
            "fail": true,
            "pending": false,
            "code": "cy.visit('localhost:8080');",
            "err": {
              "message": "CypressError: cy.visit() failed trying to load:\n\nhttp://localhost:8080/\n\nWe attempted to make an http request to this URL but the request failed without a response.\n\nWe received this error at the network level:\n\n  > Error: connect ECONNREFUSED 127.0.0.1:8080\n\nCommon situations why this would fail:\n  - you don't have internet access\n  - you forgot to run / boot your web server\n  - your web server isn't accessible\n  - you have weird network configuration settings on your computer\n\nThe stack trace for this error is:\n\nError: connect ECONNREFUSED 127.0.0.1:8080\n    at Object.exports._errnoException (util.js:1026:11)\n    at exports._exceptionWithHostPort (util.js:1049:20)\n    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1081:14)\nFrom previous event:\n    at Server._onResolveUrl (/Users/john.hamlett/Documents/Work/cypress/packages/server/lib/server.coffee:321:11)\n    at backendRequest (/Users/john.hamlett/Documents/Work/cypress/packages/server/lib/socket.coffee:296:23)\nFrom previous event:\n    at Socket.<anonymous> (/Users/john.hamlett/Documents/Work/cypress/packages/server/lib/socket.coffee:312:9)\n    at emitMany (events.js:127:13)\n    at Socket.emit (events.js:201:7)\n    at /Users/john.hamlett/Documents/Work/cypress/packages/socket/node_modules/socket.io/lib/socket.js:503:12\n    at _combinedTickCallback (internal/process/next_tick.js:67:7)\n    at process._tickCallback (internal/process/next_tick.js:98:9)",
              "estack": "CypressError: cy.visit() failed trying to load:\n\nhttp://localhost:8080/\n\nWe attempted to make an http request to this URL but the request failed without a response.\n\nWe received this error at the network level:\n\n  > Error: connect ECONNREFUSED 127.0.0.1:8080\n\nCommon situations why this would fail:\n  - you don't have internet access\n  - you forgot to run / boot your web server\n  - your web server isn't accessible\n  - you have weird network configuration settings on your computer\n\nThe stack trace for this error is:\n\nError: connect ECONNREFUSED 127.0.0.1:8080\n    at Object.exports._errnoException (util.js:1026:11)\n    at exports._exceptionWithHostPort (util.js:1049:20)\n    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1081:14)\nFrom previous event:\n    at Server._onResolveUrl (/Users/john.hamlett/Documents/Work/cypress/packages/server/lib/server.coffee:321:11)\n    at backendRequest (/Users/john.hamlett/Documents/Work/cypress/packages/server/lib/socket.coffee:296:23)\nFrom previous event:\n    at Socket.<anonymous> (/Users/john.hamlett/Documents/Work/cypress/packages/server/lib/socket.coffee:312:9)\n    at emitMany (events.js:127:13)\n    at Socket.emit (events.js:201:7)\n    at /Users/john.hamlett/Documents/Work/cypress/packages/socket/node_modules/socket.io/lib/socket.js:503:12\n    at _combinedTickCallback (internal/process/next_tick.js:67:7)\n    at process._tickCallback (internal/process/next_tick.js:98:9)\n    at Object.cypressErr (http://localhost:51874/__cypress/runner/cypress_runner.js:65969:11)\n    at Object.throwErr (http://localhost:51874/__cypress/runner/cypress_runner.js:65934:18)\n    at Object.throwErrByPath (http://localhost:51874/__cypress/runner/cypress_runner.js:65961:17)\n    at http://localhost:51874/__cypress/runner/cypress_runner.js:57623:31\n    at visitFailedByErr (http://localhost:51874/__cypress/runner/cypress_runner.js:57242:12)\n    at http://localhost:51874/__cypress/runner/cypress_runner.js:57622:22\n    at tryCatcher (http://localhost:51874/__cypress/runner/cypress_runner.js:6268:23)\n    at Promise._settlePromiseFromHandler (http://localhost:51874/__cypress/runner/cypress_runner.js:4290:31)\n    at Promise._settlePromise (http://localhost:51874/__cypress/runner/cypress_runner.js:4347:18)\n    at Promise._settlePromise0 (http://localhost:51874/__cypress/runner/cypress_runner.js:4392:10)\n    at Promise._settlePromises (http://localhost:51874/__cypress/runner/cypress_runner.js:4467:18)\n    at Async._drainQueue (http://localhost:51874/__cypress/runner/cypress_runner.js:1200:16)\n    at Async._drainQueues (http://localhost:51874/__cypress/runner/cypress_runner.js:1210:10)\n    at Async.drainQueues (http://localhost:51874/__cypress/runner/cypress_runner.js:1084:14)"
            },
            "isRoot": false,
            "uuid": "0dcc7c19-1b95-4eca-bbb1-67bf7a6f597f",
            "isHook": false,
            "skipped": false
          }
        ],
        "suites": [],
        "passes": [],
        "failures": [
          "0dcc7c19-1b95-4eca-bbb1-67bf7a6f597f"
        ],
        "pending": [],
        "skipped": [],
        "duration": 64,
        "root": false,
        "rootEmpty": false,
        "_timeout": 2000
      }
    ],
    "passes": [],
    "failures": [],
    "pending": [],
    "skipped": [],
    "duration": 0,
    "root": true,
    "rootEmpty": true,
    "_timeout": 2000
  },
  "copyrightYear": 2018
}

This was generated using Cypress.io, and was unmodified. The HTML is generated just fine if I allow mochawesome to generate the html, however I don't wanna do that I have to do some modifications to the JSON before making the HTML

I am only sending the minimum flags

marge ./json/mochawesome.json -f test --assetsDir=./test/assets

How do I have marge generate the html report?

Persist options

First of all, love this reporter!

It would be nice if options (showPassed etc.) persisted using localStorage or sessionStorage. I could submit a PR if you think it's a good idea.

Invalid value [] supplied to /allFailures: Nil

Hi,
reporters: ['mochawesome'],
reporterOptions: {
outputDir: test

The script produces a wdiomochawesome.json report file under xx output dir. The outcome of the format is as below.

Invalid value {
"title": "sometitle"",
"fullTitle": "I am logged in as some one",
"timedOut": false,
"duration": 0,
"speed": "fast",
"pass": true,
"fail": false,
"pending": false,
"code": "",
"isRoot": false,
"uuid": "something",
"parentUUID": "something",
"skipped": false,
"isHook": false,
"context": "[{something}]",
"state": "passed",
"err": {}
} supplied to /suites/suites/0/passes/10: String
Invalid value true supplied to /suites/suites/0/hasTests: Nil
Invalid value false supplied to /suites/suites/0/hasSuites: Nil
Invalid value 11 supplied to /suites/suites/0/totalTests: Nil
Invalid value 11 supplied to /suites/suites/0/totalPasses: Nil
Invalid value 0 supplied to /suites/suites/0/totalFailures: Nil
Invalid value 0 supplied to /suites/suites/0/totalPending: Nil
Invalid value 0 supplied to /suites/suites/0/totalSkipped: Nil
Invalid value true supplied to /suites/suites/0/hasPasses: Nil
Invalid value false supplied to /suites/suites/0/hasFailures: Nil
Invalid value false supplied to /suites/suites/0/hasPending: Nil
Invalid value false supplied to /suites/suites/0/hasSkipped: Nil
Invalid value false supplied to /suites/suites/0/hasBeforeHooks: Nil
Invalid value false supplied to /suites/suites/0/hasAfterHooks: Nil
Invalid value false supplied to /suites/hasTests: Nil
Invalid value true supplied to /suites/hasSuites: Nil
Invalid value 0 supplied to /suites/totalTests: Nil
Invalid value 0 supplied to /suites/totalPasses: Nil
Invalid value 0 supplied to /suites/totalFailures: Nil
Invalid value 0 supplied to /suites/totalPending: Nil
Invalid value 0 supplied to /suites/totalSkipped: Nil
Invalid value false supplied to /suites/hasPasses: Nil
Invalid value false supplied to /suites/hasFailures: Nil
Invalid value false supplied to /suites/hasPending: Nil
Invalid value false supplied to /suites/hasSkipped: Nil
Invalid value false supplied to /suites/hasBeforeHooks: Nil
Invalid value false supplied to /suites/hasAfterHooks: Nil
Invalid value [
{
}
] supplied to /allPasses: Nil
Invalid value [] supplied to /allFailures: Nil

Now when i produce the Mochawesomereport using the command "marge path xx/filename.json" within package.json it ends up without the Mochawesomereport file. Any suggestion?

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test:generateMochawesomereport: marge test/wdiomochaw esome.json
npm ERR! Exit status 1
npm ERR! [email protected] test:generateMochawesomereport: marge test esome.json
npm ERR! Exit status 1

Expected/Actual reversed when using chai-subset

running mocha from CLI returns this result:

1) Checkout Test (JSON version) change shipping address:

      Uncaught AssertionError: expected { Object (company, firstName, ...) } to contain subset { Object (firstName, lastName, ...) }
      + expected - actual

       {
      -  "address1": "100 Peachtree St NW"
      -  "address2": ""
      -  "addressId": "0"
      -  "city": "Atlanta"
      -  "company": ""
      -  "country": "United States"
      -  "countryId": "249"
      -  "email": "[email protected]"
      -  "fax": ""
      -  "firstName": "Floo"
      -  "isResidential": ""
      -  "lastName": "Bit"
      -  "override": "1"
      -  "phone": "+1 800-800-2222"
      -  "phoneNight": [null]
      -  "state": "GA"
      -  "stateId": "24"
      -  "timeZone": "US/Eastern"
      -  "validated": "1"
      -  "zipcode": "30303-1906"
      +  "address1": "201 Columbine St Ste 100"
      +  "firstName": "Michael"
      +  "lastName": "McMaster"
       }

However, Mochawesome (generator or reporter, I'm not sure) shows the reverse:
https://www.dropbox.com/s/z6hsq271bk82ymr/Screenshot%202017-07-24%2015.04.14.png?dl=0

The specific assertion is:

                items[0].splits[0].address.should.containSubset( {
                    first_name:"Michael",
                    last_name:"McMaster",
                    address1:"201 Columbine St Ste 100",
                })

Design tweaks

Possible design changes

  • Update icons / switch to SVG
  • Refine typography (smaller suite titles / headers)
  • Streamline quick summary
  • Make quick summary icons clickable for fast filtering
  • Default to hide charts (Are the charts even useful?)
  • More obvious hover states for tests
  • Adjust text contrast #92

Ability to customize default filtering when opening report

First of all, kudos for your project Adam, it has been really helpful for us.

About my proposal - We use mochawesome as the default reporter on our CI builds, but the report is usually reviewed only when builds fail at the regression stage. In that context, the most likely first action after opening the report is going to the filters to show only the failed ones, so it would be really nice to have that as a config option.

Invalid value "pending" supplied to /suites/suites/0/tests/0/state: TestState

I am getting this issue that occurs for tests that are in a skipped/pending state. I believe it has to do with the skipped/pending value for one of my tests. If I remove that test, using "marge" and generating the report works as expected with the JSON.

"mocha": "^5.2.0",
"mochawesome": "^3.0.3",

I am using this in CLI

marge ${uuid}.json --reportFilename FuncTestReport --reportDir mochaReports --inline true
{
  "stats": {
    "suites": 2,
    "tests": 4,
    "passes": 3,
    "pending": 0,
    "failures": 1,
    "start": "2018-10-02T18:20:55.891Z",
    "end": "2018-10-02T18:24:28.055Z",
    "duration": 212164,
    "testsRegistered": 4,
    "passPercent": 75,
    "pendingPercent": 0,
    "other": 0,
    "hasOther": false,
    "skipped": 0,
    "hasSkipped": false,
    "passPercentClass": "warning",
    "pendingPercentClass": "danger"
  },
  "suites": {
    "uuid": "662d9420-c670-11e8-935c-6f7f14b4331d",
    "title": "",
    "fullFile": "",
    "file": "",
    "beforeHooks": [],
    "afterHooks": [],
    "tests": [],
    "suites": [{
      "uuid": "8dda2435-40d5-4108-b54d-c521301ffb9c",
      "title": "Image Diff 1",
      "fullFile": "",
      "file": "",
      "beforeHooks": [],
      "afterHooks": [],
      "tests": [{
        "title": "Draw Polygon and check for Image diff. Test should fail",
        "fullTitle": "Image Diff 1 Draw Polygon and check for Image diff. Test should fail",
        "duration": 64868,
        "state": "failed",
        "pass": false,
        "fail": true,
        "pending": false,
        "code": "cy.viewport(1280, 720);\ncy.get(\"#drawIcon\").click();\ncy.get(\".insertText\").contains(\"Draw Polygon\").should(\"be.visible\").click();\ncy.get(\"#MapPanel #geoStyler\").should(\"be.visible\");\ncy.wait(7000);\ncy.matchImageSnapshot(\"drawPolygon\", { capture: \"fullPage\", scale: true });\n// Draw the Polygon.\ncy.get(\"#labelCanvasId\").click(1000, 850, {\n  force: true\n});\ncy.get(\"#labelCanvasId\").click(1250, 750, {\n  force: true\n});\ncy.get(\"#labelCanvasId\").click(1150, 550, {\n  force: true\n});\ncy.get(\"#labelCanvasId\").click(1350, 650, {\n  force: true\n});\ncy.get(\"#labelCanvasId\").dblclick();\n// End draw\ncy.get(\"#geoStyler_accept\").click();\ncy.wait(10000);\n// Compare the snapshots\ncy.matchImageSnapshot(\"drawPolygon\", { capture: \"fullPage\", scale: true });",
        "err": {
          "message": "Error: Screenshot was 58.04698350694445% different from saved snapshot with 534961 different pixels.\n  See diff for details: C:\\SStream Client\\lib\\3.0\\cypress\\snapshots\\funcTests\\testcases\\drawIcon_toolbar.js\\__diff_output__\\drawPolygon-diff.png",
          "estack": "Error: Screenshot was 58.04698350694445% different from saved snapshot with 534961 different pixels.\n  See diff for details: C:\\SStream Client\\lib\\3.0\\cypress\\snapshots\\funcTests\\testcases\\drawIcon_toolbar.js\\__diff_output__\\drawPolygon-diff.png\n    at Context.cy.task.then (https://localhost:44344/__cypress/tests?p=cypress\\support\\index.js-159:27206:15)"
        },
        "isRoot": false,
        "uuid": "7a775cc6-863f-4ee5-9da2-661132c70f3a",
        "isHook": false,
        "skipped": false,
        "timedOut": false
      }],
      "suites": [],
      "passes": [],
      "failures": ["7a775cc6-863f-4ee5-9da2-661132c70f3a"],
      "pending": [],
      "skipped": [],
      "duration": 64868,
      "root": false,
      "rootEmpty": false,
      "_timeout": 2000
    }, {
      "uuid": "804a63e9-7ce7-4644-99fa-737c76c86ba6",
      "title": "Parcel Tests",
      "fullFile": "",
      "file": "",
      "beforeHooks": [],
      "afterHooks": [],
      "tests": [{
        "title": "Parcel Copied 1.1: Verify Parcel is copied",
        "fullTitle": "Parcel Tests Parcel Copied 1.1: Verify Parcel is copied",
        "duration": 65983,
        "state": "passed",
        "speed": "slow",
        "pass": true,
        "fail": false,
        "pending": false,
        "code": "\ncy.searchAddress(address);\ncy.get(\".js-popout_card\").click();\n// Poput should appear\ncy.get(\"[aria-labelledby=\\\"ui-dialog-title-SubjectSummary\\\"]\").then(function ($modal) {\n  var display = $modal.css(\"display\");\n  cy.expect(display).to.equal(\"block\");\n});\ncy.wait(5000);\ncy.get(\"body\").screenshot(\"notCopied\");\ncy.get(\"[aria-labelledby=\\\"ui-dialog-title-SubjectSummary\\\"] .ui-icon-closethick\").click();\n// Popout should not appear.\ncy.get(\"[aria-labelledby=\\\"ui-dialog-title-SubjectSummary\\\"]\").then(function ($modal) {\n  var display = $modal.css(\"display\");\n  cy.expect(display).to.equal(\"none\");\n});\ncy.wait(5000);\n// Compare the snapshots test should fail.\ncy.get(\"body\").screenshot(\"Copied\");\n// Close all dialogs\ncy.get(\".js-close_card > .fa\").click();",
        "err": {},
        "isRoot": false,
        "uuid": "f4050710-5d42-4537-8048-8857aeb13f3b",
        "isHook": false,
        "skipped": false,
        "timedOut": false
      }, {
        "title": "Shared Documents 1.2: Manage Documents command. Upload a file and save.",
        "fullTitle": "Parcel Tests Shared Documents 1.2: Manage Documents command. Upload a file and save.",
        "duration": 12100,
        "state": "passed",
        "speed": "slow",
        "pass": true,
        "fail": false,
        "pending": false,
        "code": "\ncy.searchAddress(address);\n// ---Wait for the parcel to load\ncy.get(\".title\").contains(\"Shared Documents\").click();\ncy.get(\".command_name\").contains(\"Manage Documents\").scrollIntoView().click();\ncy.get(\".ui-dialog-title\").contains(\"Attachments\").should(\"be.visible\");\ncy.get(\"[aria-labelledby=\\\"ui-dialog-title-4\\\"] > .ui-dialog-buttonpane > .ui-dialog-buttonset > :nth-child(1) > .ui-button-text\").contains(\"Add\").last().click();\ncy.upload_file2(\"TestAutomation.csv\", \"#attach_doc_browse_file\");\ncy.get(\"#attach_doc_desc\").type(\"Testing upload\");\ncy.get(\".ui-dialog-title\").contains(\"Attach a file\").should(\"be.visible\").then(function ($modal) {\n  var id = $modal.attr(\"id\");\n  // Click the Ok Button\n  cy.get(\"[aria-labelledby=\" + id + \"] .ui-button-text\").contains(\"OK\").click();\n});\ncy.get(\"#attach_doc_list_dialog a\").contains(\"TestAutomation.csv\").should(\"be.visible\");\n// Remove the created attachment.\ncy.get(\"#attach_doc_list_dialog [title=\\\"Remove from list\\\"]\").click();\ncy.get(\".ui-button-text\").contains(\"Yes\").click();\ncy.get(\"[aria-labelledby=\\\"ui-dialog-title-4\\\"] > .ui-dialog-buttonpane > .ui-dialog-buttonset > :nth-child(2) > .ui-button-text\").contains(\"Close\").click();",
        "err": {},
        "isRoot": false,
        "uuid": "76f3a940-343f-4b27-85c3-f583f0765fd6",
        "isHook": false,
        "skipped": false,
        "timedOut": false
      }, {
        "title": "Shared Notes: Manage Notes. Upload a note and save.",
        "fullTitle": "Parcel Tests Shared Notes: Manage Notes. Upload a note and save.",
        "duration": 11819,
        "state": "passed",
        "speed": "slow",
        "pass": true,
        "fail": false,
        "pending": false,
        "code": "\ncy.searchAddress(address);\ncy.get(\".title\").contains(\"Shared Notes\").click();\ncy.get(\".command_name\").contains(\"Manage Notes\").scrollIntoView().click();\ncy.get(\".ui-dialog-title\").contains(\"Notes\").should(\"be.visible\");\ncy.get(\"[aria-labelledby=\\\"ui-dialog-title-3\\\"] > .ui-dialog-buttonpane > .ui-dialog-buttonset > :nth-child(1) > .ui-button-text\").contains(\"Add\").last().click({\n  force: true\n});\ncy.get(\".editAttributeLabel\").contains(\"Title\").next().clear().type(title);\ncy.get(\".editAttributeLabel\").contains(\"type\").next().clear().type(noteType);\ncy.get(\".editAttributeLabel\").contains(\"Note\").next().clear().type(note);\ncy.get(\".editAttributeSubmit\").click();\ncy.get(\"#AddNotesListDiv label u\").first().contains(title).should(\"be.visible\");\n// Remove the created attachment.\ncy.get(\"#AddNotesListDiv [title=\\\"Remove from list\\\"]\").click();\ncy.get(\"[aria-labelledby=\\\"ui-dialog-title-3\\\"] > .ui-dialog-buttonpane > .ui-dialog-buttonset > :nth-child(2) > .ui-button-text\").contains(\"Close\").click();",
        "err": {},
        "isRoot": false,
        "uuid": "7cf4f226-795d-409f-8d91-09d111cb5ad1",
        "isHook": false,
        "skipped": false,
        "timedOut": false
      }],
      "suites": [],
      "passes": ["f4050710-5d42-4537-8048-8857aeb13f3b", "76f3a940-343f-4b27-85c3-f583f0765fd6", "7cf4f226-795d-409f-8d91-09d111cb5ad1"],
      "failures": [],
      "pending": [],
      "skipped": [],
      "duration": 89902,
      "root": false,
      "rootEmpty": false,
      "_timeout": 2000
    }],
    "passes": [],
    "failures": [],
    "pending": [],
    "skipped": [],
    "duration": 0,
    "root": true,
    "rootEmpty": true,
    "_timeout": 2000
  },
  "copyrightYear": 2018
}

Feature Request: Use darker text for addContext html output

In the html output under the section Additional Test Context the text is very hard to read. So when letting others read the text output, it is hard to see the words.

Can you darken the text, please.

Platform running on:

  • ubuntu, 16.04

  • Node, running tests via nightwatch and mocha

  • current version of mocha awesome

  • Using it for end to end testing for business users to read the test

  • example code
    thenTheSummaryWheelIsPresentForCompletedEvents(); addContext(this, 'and summary wheels is present for completed events');

  • to reproduce use addContext as above and look at the html output

Thanks for your time

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.