31
votes

Is it possible to redirect or capture Cypress browser log and command log to output?

I read some Cypress github issues on this topic. But I don't know how to make it work.

Basically, I want to capture all the Cypress GUI command logs in the headless non-GUI mode. If I can include browser console log will be even better. The purpose is to understand what happened when a test fails.

I use teamcity as ci. Here is an example of my build log. I want to see all the command log here too. Actually, any console.log run on the server side using cy.task is displayed in the build log. Running cy.task('log',message) is too manual. Any smarter ways?

[09:49:08][Step 1/1] 2 of 4: new actions (52s)
[09:50:00][Step 1/1] 3 of 4: new actions (52s)
[09:50:53][Step 1/1] 4 of 4: new actions (53s)
[09:51:47][Step 1/1]   (Results)
[09:51:47][Step 1/1] 
[09:51:47][Step 1/1]   ┌─────────────────────────────────────┐
[09:51:47][Step 1/1]   │ Tests:        8                     │
[09:51:47][Step 1/1]   │ Passing:      8                     │
[09:51:47][Step 1/1]   │ Failing:      0                     │
[09:51:47][Step 1/1]   │ Pending:      0                     │
[09:51:47][Step 1/1]   │ Skipped:      0                     │
[09:51:47][Step 1/1]   │ Screenshots:  0                     │
[09:51:47][Step 1/1]   │ Video:        true                  │
[09:51:47][Step 1/1]   │ Duration:     3 minutes, 38 seconds │
[09:51:47][Step 1/1]   │ Estimated:    1 minute, 8 seconds   │
[09:51:47][Step 1/1]   │ Spec Ran:     action/action_spec.js │
[09:51:47][Step 1/1]   └─────────────────────────────────────┘
4
It looks like they are trying to produce an all-encompassing feature rather than a simple hook, which is what most people seem to want. jantoebe's code here looks promising. Might be worth asking him where he adds it in the tests.user8745435
How about sending client's browser log back to the server? Using jantoebe's idea of replacing console and somehow send the log back to node's console log. Do I need to make an endpoint to listen on a port using cy.task?Jake He
Use something like this github.com/krakenjs/beaver-logger. It might be an overkill.Jake He
Yes, definitely a cy.task to run the code into Node env. Then just fs to a file, but with some nice formatting. I am also interested in capturing the command log formatted html (not just the test) for documentation, so document.getElementById('root').innerHTML looks like the way to do that.user8745435
Please also see cypress-failed-log which enumerates the commands - looks quite useful for CI scenario.user8745435

4 Answers

49
votes

As of Cypress 3.0.0, you can use cy.task() to access node directly and output to the node console. From the docs:

// in test
cy.task('log', 'This will be output to the terminal')
// in plugins file
on('task', {
  log (message) {
    console.log(message)
    return null
  }
})

See here for more info.

I don't know of a way to mirror the Cypress logs to the console directly, but this is at least a workable alternative.

4
votes

FYI:

Cypress community is going to provide native support so that we don't have to do any workarounds to print the logs on non-GUI(headless) CLI.

Ongoing issue: https://github.com/cypress-io/cypress/issues/448

3
votes

Expanding on @Joshua-wade's answer, you can overwrite cy.log to redirect all calls to it to the log task. Just as the following:

Cypress.Commands.overwrite('log', (subject, message) => cy.task('log', message));

Note: there's a small drawback to this: when you run the test using the Test Runner, instead of seeing LOG my message in the command log, you'll see TASK log, my message. But IMHO it's negligible.

0
votes

Setting the ELECTRON_ENABLE_LOGGING environment variable to 1 will cause all Chrome internal logging to be printed to the console.

ELECTRON_ENABLE_LOGGING=1 npx cypress run

ELECTRON_ENABLE_LOGGING

Prints Chrome's internal logging to the console.

With this enabled, in addition to capturing any existing logging, this will also allow you to manually log within a test using console.log:

console.log('Response JSON: ' + json)