Skip to content

Commit

Permalink
#150: Implement continousl logging option.
Browse files Browse the repository at this point in the history
  • Loading branch information
archfz committed Jul 8, 2022
1 parent 72e3437 commit 726a886
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 3 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ boolean; default false; Whether to print request data for XHR requests besides r
boolean; default false; Enables an extended collector which will also collect command logs from
before all and after all hooks.

#### `options.enableContinuousLogging`
boolean; default false; Enables logging logs to terminal continuously / immediately as they are registered.
This feature is unstable and has an impact on pipeline performance. Use only for debugging purposes in case
the pipelines / tests are timing out.

> NOTE: In case of this option enabled, logs will come before the actual title of the test. Also the
> `printLogsToConsole` option will be ignored. Logging to files might also get impacted.

#### _Example for options for the support install_

```js
Expand Down Expand Up @@ -323,6 +331,10 @@ directory. You should add `it.only` to the test case you are working on to speed
## Release Notes
#### 4.1.0
- Add experimental [`enableContinuousLogging`](#optionsenablecontinuouslogging) option for timeout debugging purposes. [issue](https://github.com/archfz/cypress-terminal-report/issues/150)
#### 4.0.3
- Fix issue with errors throw outside of tests overlapping real error. [issue](https://github.com/archfz/cypress-terminal-report/issues/152)
Expand Down
10 changes: 10 additions & 0 deletions src/collector/LogCollectSimpleControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ module.exports = class LogCollectSimpleControl extends LogCollectBaseControl {
level: testLevel,
consoleTitle: options.consoleTitle,
isHook: options.isHook,
continuous: this.config.enableContinuousLogging,
}
})
// For some reason cypress throws empty error although the task indeed works.
Expand All @@ -74,6 +75,7 @@ module.exports = class LogCollectSimpleControl extends LogCollectBaseControl {
level: testLevel,
consoleTitle: options.consoleTitle,
isHook: options.isHook,
continuous: this.config.enableContinuousLogging,
},
{log: false}
);
Expand Down Expand Up @@ -101,6 +103,14 @@ module.exports = class LogCollectSimpleControl extends LogCollectBaseControl {
registerTests() {
const self = this;

if (this.config.enableContinuousLogging) {
this.collectorState.on('log', () => {
self.sendLogsToPrinter(self.collectorState.getCurrentLogStackIndex(), self.collectorState.getCurrentTest(), {noQueue: true});
this.collectorState.addNewLogStack();
});
return;
}

afterEach(function () {
self.sendLogsToPrinter(self.collectorState.getCurrentLogStackIndex(), self.collectorState.getCurrentTest());
});
Expand Down
12 changes: 12 additions & 0 deletions src/collector/LogCollectorState.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = class LogCollectorState {
constructor(config) {
this.config = config;

this.listeners = {};
this.currentTest = null;
this.logStacks = [];
this.xhrIdsOfLoggedResponses = [];
Expand Down Expand Up @@ -65,6 +66,7 @@ module.exports = class LogCollectorState {
}

currentStack.push(entry);
this.emit('log');
}

updateLog(log, severity, id) {
Expand All @@ -74,6 +76,7 @@ module.exports = class LogCollectorState {
entry[2] = severity;
}
});
this.emit('log');
}

updateLogStatusForChainId(chainId, state = CONSTANTS.SEVERITY.ERROR) {
Expand Down Expand Up @@ -162,4 +165,13 @@ module.exports = class LogCollectorState {
--previousIndex;
}
}

emit(event) {
(this.listeners[event] || []).forEach(callback => callback());
}

on(event, callback) {
this.listeners[event] = this.listeners[event] || [];
this.listeners[event].push(callback);
}
}
7 changes: 7 additions & 0 deletions src/installLogsCollector.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ export interface SupportOptions {
*/
enableExtendedCollector: boolean;

/**
* Enables continuous logging of logs to terminal one by one, as they get registerd or modified.
* @unstable
* @default false
*/
enableContinuousLogging: boolean;

/**
* Enabled debug logging.
* @default false
Expand Down
3 changes: 3 additions & 0 deletions src/installLogsCollector.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
"enableExtendedCollector": {
"type": "boolean"
},
"enableContinuousLogging": {
"type": "boolean"
},
"debug": {
"type": "boolean"
}
Expand Down
2 changes: 1 addition & 1 deletion src/installLogsPrinter.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ function logToTerminal(messages, options, data) {
);
});

if (messages.length !== 0) {
if (messages.length !== 0 && data.continuous === false) {
console.log('\n');
}
}
Expand Down
15 changes: 15 additions & 0 deletions test/cypress/integration/continuousLogging.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
describe('continuous logging', () => {
it('logs many', () => {
cy.log('log 1');
cy.wait(500);
cy.log('log 2');
cy.wait(2000);
cy.log('log 3');
});

it('logs many again', () => {
cy.log('log again 1');
cy.wait(2000);
cy.log('log again 2');
});
});
3 changes: 3 additions & 0 deletions test/cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ if (env.supportGoodConfig == '1') {
if (env.enableExtendedCollector == '1') {
config.enableExtendedCollector = true;
}
if (env.enableContinuousLogging == '1') {
config.enableContinuousLogging = true;
}

require('../../../src/installLogsCollector')(config);

Expand Down
21 changes: 20 additions & 1 deletion test/specs/misc.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
ICONS,
runTest,
commandBase, logLastRun, clean,
commandBase, logLastRun, clean, runTestContinuous,
} from "../utils";

const {expect} = require('chai');
Expand Down Expand Up @@ -96,4 +96,23 @@ describe('Misc.', () => {
});
}).timeout(60000);

it('Should continuously log.', async function () {
let checksMade = 0;
await runTestContinuous(commandBase(['enableContinuousLogging=1'], ['continuousLogging.spec.js']), (data, elapsedTime) => {
if (elapsedTime > 5 && elapsedTime <= 6) {
++checksMade;
expect(clean(data)).to.contain(`cy:log ${ICONS.info} log 1`);
expect(clean(data)).to.contain(`cy:log ${ICONS.info} log 2`);
expect(clean(data)).to.not.contain(`cy:log ${ICONS.info} log 3`);
}
if (elapsedTime > 6 && elapsedTime <= 7) {
++checksMade;
expect(clean(data)).to.contain(`cy:log ${ICONS.info} log again 1`);
expect(clean(data)).to.not.contain(`cy:log ${ICONS.info} log again 2`);
}
});

expect(checksMade, "No checks where made. The process might have ended too early.").to.be.greaterThan(0)
}).timeout(60000);

});
26 changes: 25 additions & 1 deletion test/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const {exec} = require('child_process');
const {exec, spawn} = require('child_process');
const {expect} = require('chai');
const fs = require('fs');
const path = require('path');
Expand Down Expand Up @@ -59,6 +59,30 @@ export const runTest = async (command, callback) => {
});
};

export const runTestContinuous = async (command, callback) => {
await new Promise(resolve => {
let allData = '';
const startTime = (new Date()).getTime();
const mainCommand = command.split(' ')[0];
const args = command.split(' ').map(arg => arg.replace(/^"/, '').replace(/"$/, ''));
args.shift();

const child = spawn(mainCommand, args, {encoding: "UTF-8", env: {...process.env, NO_COLOR: 1}});

child.on('close', resolve);

const dataCallback = (data) => {
allData += data.toString();
callback(allData, ((new Date()).getTime() - startTime) / 1000);
};

child.stdout.setEncoding('utf8');
child.stdout.on('data', dataCallback);
child.stderr.setEncoding('utf8');
child.stderr.on('data', dataCallback);
});
};

export const outputCleanUpAndInitialization = (testOutputs, outRoot) => {
outRoot.value = path.join(__dirname, 'output');
testOutputs.value = ['out.txt', 'out.json', 'out.cst'];
Expand Down

0 comments on commit 726a886

Please sign in to comment.