Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

force print log options and fix finding out the failed cy.commands or… #4

Merged
merged 12 commits into from
Feb 18, 2020
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ node_modules
test/node_modules
test/cypress/screenshots
test/cypress/videos
test/cypress/fixtures
.idea
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ The plugin install can receive some options: `.installPlugin(on, options)`:
- `options.commandTrimLength` - default: 600; max length of cy commands.
- `options.routeTrimLength` - default: 5000; max length of cy.route request data.


To print logs for all tests add `{printLogs: always}` to `installSupport`:

require('cypress-terminal-report').installSupport({printLogs: always});

## Release notes

#### Next (unreleased)
Expand Down
20 changes: 13 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
function pipeLogsToTerminal() {
function pipeLogsToTerminal(config) {
let oldConsoleWarn;
let oldConsoleError;
let logs = [];

Cypress.on('fail', error => {
archfz marked this conversation as resolved.
Show resolved Hide resolved
const [type, message] = logs[logs.length - 1];
logs[logs.length - 1] = [type, message, 'failed'];
archfz marked this conversation as resolved.
Show resolved Hide resolved
throw error;
});

Cypress.on('window:before:load', () => {
const docIframe = window.parent.document.querySelector("[id*='Your App']");
const appWindow = docIframe.contentWindow;
Expand Down Expand Up @@ -43,11 +49,11 @@ function pipeLogsToTerminal() {
}
const log =
options.name + '\t' + options.message + (detailMessage !== '' ? ' ' + detailMessage : '');
logs.push(['cy:command', log]);
logs.push(['cy:command', log, options.state]);
}
});

Cypress.Commands.overwrite("server", (originalFn, options = {}) => {
Cypress.Commands.overwrite('server', (originalFn, options = {}) => {
const prevCallback = options && options.onAnyResponse;
options.onAnyResponse = async (route, xhr) => {
if (prevCallback) {
Expand All @@ -73,7 +79,7 @@ function pipeLogsToTerminal() {
});

afterEach(function() {
if (this.currentTest.state !== 'passed') {
if (this.currentTest.state !== 'passed' || (config && config.printLogs === 'always')) {
cy.task('terminalLogs', logs);
}
});
Expand All @@ -98,7 +104,7 @@ function nodeAddLogsPrinter(on, options = {}) {

on('task', {
terminalLogs: messages => {
messages.forEach(([type, message], i) => {
messages.forEach(([type, message, status], i) => {
let color = 'white',
typeString = ' [unknown] ',
processedMessage = message,
Expand Down Expand Up @@ -134,7 +140,7 @@ function nodeAddLogsPrinter(on, options = {}) {
trim = options.routeTrimLength || 5000;
}

if (i === messages.length - 1) {
if (status && status === 'failed') {
color = 'red';
icon = '✘';
}
Expand Down Expand Up @@ -172,5 +178,5 @@ module.exports = {
*
* Needs to be added to support file.
*/
installSupport: () => pipeLogsToTerminal(),
installSupport: config => pipeLogsToTerminal(config),
};
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions test/cypress/integration/alwaysPrintLogs.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
describe('Always print Logs', () => {
/**
* Covers:
* - printing of cy.commands
* - printing xhr with STUBBED
* - printing of console warn and console error
* - printing of cy.route in case of XMLHTTPREQUEST API
*/
it('Always print Logs', () => {
cy.visit('/');
cy.contains('cypress');
});
});
17 changes: 9 additions & 8 deletions test/cypress/integration/happyFlow.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
describe("Happy flow", () => {
describe('Happy flow', () => {
/**
* Covers:
* - printing of cy.commands
Expand All @@ -18,28 +18,30 @@ describe("Happy flow", () => {
// the button is clicked in scripts.js
cy.get('.network-btn').click();

cy.wait('@getComment').its('status').should('eq', 200);
cy.wait('@getComment')
.its('status')
.should('eq', 200);

cy.route('POST', '/comments').as('postComment');

// we have code that posts a comment when
// the button is clicked in scripts.js
cy.get('.network-post').click();
cy.wait('@postComment').should((xhr) => {
cy.wait('@postComment').should(xhr => {
expect(xhr.requestBody).to.include('email');
expect(xhr.requestHeaders).to.have.property('Content-Type');
expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()');
});

cy.window().then((w) => w.console.warn('This is a warning message'));
cy.window().then((w) => w.console.error(new Error('This is an error message')));
cy.window().then(w => w.console.warn('This is a warning message'));
cy.window().then(w => w.console.error(new Error('This is an error message')));

// Stub a response to PUT comments/ ****
cy.route({
method: 'PUT',
url: 'comments/*',
status: 404,
response: { error: message },
response: {error: message},
}).as('putComment');

// we have code that puts a comment when
Expand All @@ -50,7 +52,6 @@ describe("Happy flow", () => {

// our 404 statusCode logic in scripts.js executed
cy.get('.network-put-comment').should('contain', message);

cy.get('breaking-get');
})
});
});
9 changes: 5 additions & 4 deletions test/cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import './commands'
require('../../../index').installSupport();
import './commands';

require('../../../index').installSupport(Cypress.env());

enableFetchWorkaround();
function enableFetchWorkaround() {
let polyfill;

before(() => {
console.info('Load fetch XHR polyfill.');
cy.request('https://cdn.jsdelivr.net/npm/fetch-polyfill@0.8.2/fetch.min.js').then((response) => {
cy.request('https://cdn.jsdelivr.net/npm/fetch-polyfill@0.8.2/fetch.min.js').then(response => {
polyfill = response.body;
});
});

Cypress.on('window:before:load', (win) => {
Cypress.on('window:before:load', win => {
delete win.fetch;
win.eval(polyfill);
});
Expand Down
47 changes: 35 additions & 12 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@
const { exec } = require('child_process');
const { expect } = require('chai');
const {exec} = require('child_process');
const {expect} = require('chai');

const commandBase = 'node ./node_modules/.bin/cypress run --headless -s cypress/integration/';
const commandBase = (env = '') =>
`node ./node_modules/.bin/cypress run --env ${env} --headless -s cypress/integration/`;

describe("cypress-terminal-report", () => {
it("Logs happy flows.", async () => {
await new Promise((resolve) => {
exec(commandBase + "happyFlow.spec.js", (error, stdout, stderr) => {
describe('cypress-terminal-report', () => {
it('Always print logs happy flows with no errors.', async () => {
await new Promise(resolve => {
exec(commandBase('printLogs=always') + 'alwaysPrintLogs.spec.js', (error, stdout, stderr) => {
// cy.command logs.
expect(stdout).to.contain('cy:command ✔ visit\t/\n');
expect(stdout).to.contain('cy:command ✔ contains\tcypress\n');
expect(stdout).to.contain('✔ All specs passed!');
resolve();
});
});
}).timeout(60000);

it('Logs happy flows with errors.', async () => {
await new Promise(resolve => {
exec(commandBase() + 'happyFlow.spec.js', (error, stdout, stderr) => {
// cy.command logs.
expect(stdout).to.contain('cy:command ✔ visit\t/commands/network-requests\n');
expect(stdout).to.contain('cy:command ✔ get\t.network-post\n');
expect(stdout).to.contain('cy:command ✔ xhr\t STUBBED PUT https://jsonplaceholder.cypress.io/comments/1\n');
expect(stdout).to.contain(
'cy:command ✔ xhr\t STUBBED PUT https://jsonplaceholder.cypress.io/comments/1\n'
);

// cy.route logs.
expect(stdout).to.contain('cy:route ⛗ Status: 200 (getComment)\n');
expect(stdout).to.contain('Method: GET\n');
expect(stdout).to.contain('Url: https://jsonplaceholder.cypress.io/comments/1\n');
expect(stdout).to.contain('Response: {"postId":1,"id":1,"name":"id labore ex et quam laborum","email":"Eliseo@gardner.biz"');
expect(stdout).to.contain(
'Response: {"postId":1,"id":1,"name":"id labore ex et quam laborum","email":"Eliseo@gardner.biz"'
);

// console.error and console.warn.
expect(stdout).to.contain('cons.warn ⚠ This is a warning message\n');
expect(stdout).to.contain('cons.error ⚠ Error: This is an error message\n');

// log failed command
expect(stdout).to.contain('cy:command ✘ get\tbreaking-get\n');

resolve();
});
});
}).timeout(60000);

it("Logs FETCH API routes.", async () => {
await new Promise((resolve) => {
exec(commandBase + "apiRoutes.spec.js", (error, stdout, stderr) => {
it('Logs FETCH API routes.', async () => {
await new Promise(resolve => {
exec(commandBase() + 'apiRoutes.spec.js', (error, stdout, stderr) => {
expect(stdout).to.contain('Method: PUT\n');
expect(stdout).to.contain('Url: https://example.cypress.io/comments/10\n');

Expand All @@ -49,6 +69,9 @@ describe("cypress-terminal-report", () => {
expect(stdout).to.contain('cy:route ⛗ Status: 404 (putComment)\n');
expect(stdout).to.contain('Response: {"error":"Test message."}\n');

// log failed command
expect(stdout).to.contain('cy:command ✘ get\tbreaking-get\n');

resolve();
});
});
Expand Down