Skip to content

Commit 51eaf05

Browse files
authored
Merge branch 'master' into APS_8909_Enforce_Run_Settings
2 parents ae509f8 + 8b87783 commit 51eaf05

File tree

5 files changed

+148
-11
lines changed

5 files changed

+148
-11
lines changed

bin/commands/runs.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,10 @@ module.exports = function run(args, rawArgs) {
111111
/*
112112
Send build start to Observability
113113
*/
114-
if(isTestObservabilitySession) await launchTestSession(bsConfig, bsConfigPath);
114+
if(isTestObservabilitySession) {
115+
await launchTestSession(bsConfig, bsConfigPath);
116+
utils.setO11yProcessHooks(null, bsConfig, args, null, buildReportData);
117+
}
115118

116119
// accept the system env list from bsconf and set it
117120
utils.setSystemEnvs(bsConfig);
@@ -272,6 +275,9 @@ module.exports = function run(args, rawArgs) {
272275
markBlockEnd('createBuild');
273276
markBlockEnd('total');
274277
utils.setProcessHooks(data.build_id, bsConfig, bs_local, args, buildReportData);
278+
if(isTestObservabilitySession) {
279+
utils.setO11yProcessHooks(data.build_id, bsConfig, bs_local, args, buildReportData);
280+
}
275281
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
276282
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
277283
buildReportData = { 'build_id': data.build_id, 'parallels': userSpecifiedParallels, ...buildReportData }

bin/helpers/utils.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const usageReporting = require("./usageReporting"),
2222
config = require("../helpers/config"),
2323
pkg = require('../../package.json'),
2424
transports = require('./logger').transports,
25-
{ findGitConfig, printBuildLink, isTestObservabilitySession, isBrowserstackInfra, shouldReRunObservabilityTests } = require('../testObservability/helper/helper'),
25+
o11yHelpers = require('../testObservability/helper/helper'),
2626
{ OBSERVABILITY_ENV_VARS, TEST_OBSERVABILITY_REPORTER } = require('../testObservability/helper/constants');
2727

2828
const request = require('request');
@@ -481,7 +481,7 @@ exports.setNodeVersion = (bsConfig, args) => {
481481
// specs can be passed via command line args as a string
482482
// command line args takes precedence over config
483483
exports.setUserSpecs = (bsConfig, args) => {
484-
if(isBrowserstackInfra() && isTestObservabilitySession() && shouldReRunObservabilityTests()) {
484+
if(o11yHelpers.isBrowserstackInfra() && o11yHelpers.isTestObservabilitySession() && o11yHelpers.shouldReRunObservabilityTests()) {
485485
bsConfig.run_settings.specs = process.env.BROWSERSTACK_RERUN_TESTS;
486486
return;
487487
}
@@ -581,8 +581,8 @@ exports.setSystemEnvs = (bsConfig) => {
581581
envKeys[key] = process.env[key];
582582
});
583583

584-
let gitConfigPath = findGitConfig(process.cwd());
585-
if(!isBrowserstackInfra()) process.env.OBSERVABILITY_GIT_CONFIG_PATH_LOCAL = gitConfigPath;
584+
let gitConfigPath = o11yHelpers.findGitConfig(process.cwd());
585+
if(!o11yHelpers.isBrowserstackInfra()) process.env.OBSERVABILITY_GIT_CONFIG_PATH_LOCAL = gitConfigPath;
586586
if(gitConfigPath) {
587587
const relativePathFromGitConfig = path.relative(gitConfigPath, process.cwd());
588588
envKeys["OBSERVABILITY_GIT_CONFIG_PATH"] = relativePathFromGitConfig ? relativePathFromGitConfig : 'DEFAULT';
@@ -1188,8 +1188,8 @@ exports.handleSyncExit = (exitCode, dashboard_url) => {
11881188
syncCliLogger.info(Constants.userMessages.BUILD_REPORT_MESSAGE);
11891189
syncCliLogger.info(dashboard_url);
11901190
}
1191-
if(isTestObservabilitySession()) {
1192-
printBuildLink(true, exitCode);
1191+
if(o11yHelpers.isTestObservabilitySession()) {
1192+
o11yHelpers.printBuildLink(true, exitCode);
11931193
} else {
11941194
process.exit(exitCode);
11951195
}
@@ -1336,7 +1336,7 @@ exports.setEnforceSettingsConfig = (bsConfig) => {
13361336

13371337
// blindly send other passed configs with run_settings and handle at backend
13381338
exports.setOtherConfigs = (bsConfig, args) => {
1339-
if(isTestObservabilitySession() && process.env.BS_TESTOPS_JWT) {
1339+
if(o11yHelpers.isTestObservabilitySession() && process.env.BS_TESTOPS_JWT) {
13401340
bsConfig["run_settings"]["reporter"] = TEST_OBSERVABILITY_REPORTER;
13411341
return;
13421342
}
@@ -1501,14 +1501,37 @@ exports.setProcessHooks = (buildId, bsConfig, bsLocal, args, buildReportData) =>
15011501
process.on('uncaughtException', processExitHandler.bind(this, bindData));
15021502
}
15031503

1504+
exports.setO11yProcessHooks = (() => {
1505+
let bindData = {};
1506+
let handlerAdded = false;
1507+
return (buildId, bsConfig, bsLocal, args, buildReportData) => {
1508+
bindData.buildId = buildId;
1509+
bindData.bsConfig = bsConfig;
1510+
bindData.bsLocal = bsLocal;
1511+
bindData.args = args;
1512+
bindData.buildReportData = buildReportData;
1513+
if (handlerAdded) return;
1514+
handlerAdded = true;
1515+
process.on('beforeExit', processO11yExitHandler.bind(this, bindData));
1516+
}
1517+
})()
1518+
15041519
async function processExitHandler(exitData){
15051520
logger.warn(Constants.userMessages.PROCESS_KILL_MESSAGE);
15061521
await this.stopBrowserStackBuild(exitData.bsConfig, exitData.args, exitData.buildId, null, exitData.buildReportData);
15071522
await this.stopLocalBinary(exitData.bsConfig, exitData.bsLocalInstance, exitData.args, null, exitData.buildReportData);
1508-
await printBuildLink(true);
1523+
await o11yHelpers.printBuildLink(true);
15091524
process.exit(0);
15101525
}
15111526

1527+
async function processO11yExitHandler(exitData){
1528+
if (exitData.buildId) {
1529+
await o11yHelpers.printBuildLink(false);
1530+
} else {
1531+
await o11yHelpers.printBuildLink(true);
1532+
}
1533+
}
1534+
15121535
exports.fetchZipSize = (fileName) => {
15131536
try {
15141537
let stats = fs.statSync(fileName)

bin/testObservability/helper/helper.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ const supportFileCleanup = () => {
6464
});
6565
}
6666

67+
exports.buildStopped = false;
68+
6769
exports.printBuildLink = async (shouldStopSession, exitCode = null) => {
68-
if(!this.isTestObservabilitySession()) return;
70+
if(!this.isTestObservabilitySession() || exports.buildStopped) return;
71+
exports.buildStopped = true;
6972
try {
7073
if(shouldStopSession) {
7174
supportFileCleanup();

bin/testObservability/reporter/index.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class MyReporter {
7171
this._paths = new PathHelper({ cwd: process.cwd() }, this._testEnv.location_prefix);
7272
this.currentTestSteps = [];
7373
this.currentTestCucumberSteps = [];
74+
this.hooksStarted = {};
7475
this.beforeHooks = [];
7576
this.platformDetailsMap = {};
7677
this.runStatusMarkedHash = {};
@@ -110,6 +111,9 @@ class MyReporter {
110111
} else {
111112
this.runStatusMarkedHash[hook.hookAnalyticsId] = true;
112113
}
114+
115+
// Remove hooks added at hook start
116+
delete this.hooksStarted[hook.hookAnalyticsId];
113117
await this.sendTestRunEvent(hook,undefined,false,"HookRunFinished");
114118
}
115119
}
@@ -152,12 +156,14 @@ class MyReporter {
152156
})
153157

154158
.on(EVENT_TEST_BEGIN, async (test) => {
159+
if (test.isSkipped) return;
155160
if(this.testObservability == true) {
156161
await this.testStarted(test);
157162
}
158163
})
159164

160165
.on(EVENT_TEST_END, async (test) => {
166+
if (test.isSkipped) return;
161167
if(this.testObservability == true) {
162168
if(!this.runStatusMarkedHash[test.testAnalyticsId]) {
163169
if(test.testAnalyticsId) this.runStatusMarkedHash[test.testAnalyticsId] = true;
@@ -435,6 +441,38 @@ class MyReporter {
435441
};
436442
await uploadEventData(buildUpdateData);
437443
}
444+
445+
// Add started hooks to the hash
446+
if(eventType === 'HookRunStarted' && ['BEFORE_EACH', 'AFTER_EACH', 'BEFORE_ALL'].includes(testData['hook_type'])) {
447+
this.hooksStarted[testData.uuid] = uploadData;
448+
}
449+
450+
// Send pending hook finsihed events for hook starts
451+
if (eventType === 'TestRunFinished') {
452+
Object.values(this.hooksStarted).forEach(async hookData => {
453+
hookData['event_type'] = 'HookRunFinished';
454+
hookData['hook_run'] = {
455+
...hookData['hook_run'],
456+
result: uploadData['test_run'].result,
457+
failure: uploadData['test_run'].failure,
458+
failure_type: uploadData['test_run'].failure_type,
459+
failure_reason: uploadData['test_run'].failure_reason,
460+
failure_reason_expanded: uploadData['test_run'].failure_reason_expanded,
461+
failure_backtrace: uploadData['test_run'].failure_backtrace
462+
463+
}
464+
465+
if (hookData['hook_run']['hook_type'] === 'BEFORE_ALL') {
466+
hookData['hook_run'].finished_at = uploadData['test_run'].finished_at;
467+
hookData['hook_run'].duration_in_ms = new Date(hookData['hook_run'].finished_at).getTime() - new Date(hookData['hook_run'].started_at).getTime();
468+
} else {
469+
hookData['hook_run'].finished_at = hookData['hook_run'].started_at;
470+
hookData['hook_run'].duration_in_ms = 0;
471+
}
472+
await uploadEventData(hookData);
473+
})
474+
this.hooksStarted = {};
475+
}
438476
} catch(error) {
439477
debug(`Exception in populating test data for event ${eventType} with error : ${error}`, true, error);
440478
}

test/unit/bin/helpers/utils.js

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const utils = require('../../../../bin/helpers/utils'),
2121
fileHelpers = require('../../../../bin/helpers/fileHelpers'),
2222
testObjects = require('../../support/fixtures/testObjects'),
2323
syncLogger = require('../../../../bin/helpers/logger').syncCliLogger,
24-
Contants = require('../../../../bin/helpers/constants');
24+
Contants = require('../../../../bin/helpers/constants'),
25+
o11yHelpers = require('../../../../bin/testObservability/helper/helper');
2526
const browserstack = require('browserstack-local');
2627
const { CYPRESS_V10_AND_ABOVE_TYPE, CYPRESS_V9_AND_OLDER_TYPE } = require('../../../../bin/helpers/constants');
2728
const { winstonLogger, syncCliLogger } = require('../../../../bin/helpers/logger');
@@ -3484,6 +3485,72 @@ describe('utils', () => {
34843485
});
34853486
});
34863487

3488+
describe('setO11yProcessHooks', () => {
3489+
it('should handle multiple calls', (done) => {
3490+
let buildId = null;
3491+
let bsConfig = testObjects.sampleBsConfig;
3492+
let bsLocalStub = sinon.stub();
3493+
let args= {};
3494+
3495+
let printBuildLinkStub = sinon.stub(o11yHelpers, 'printBuildLink').returns(Promise.resolve(true));
3496+
let processOnSpy = sinon.spy(process, 'on');
3497+
3498+
utils.setO11yProcessHooks(buildId, bsConfig, bsLocalStub, args);
3499+
sinon.assert.calledOnce(processOnSpy);
3500+
processOnSpy.restore();
3501+
processOnSpy = sinon.spy(process, 'on');
3502+
utils.setO11yProcessHooks('build_id', bsConfig, bsLocalStub, args);
3503+
sinon.assert.notCalled(processOnSpy);
3504+
processOnSpy.restore();
3505+
process.on('beforeExit', () => {
3506+
sinon.assert.calledOnce(printBuildLinkStub);
3507+
sinon.assert.calledWith(printBuildLinkStub, false);
3508+
done();
3509+
});
3510+
process.emit('beforeExit');
3511+
printBuildLinkStub.restore();
3512+
sinon.stub.restore();
3513+
});
3514+
3515+
it('should handle "beforeExit" event, with build id', (done) => {
3516+
let buildId = 'build_id';
3517+
let bsConfig = testObjects.sampleBsConfig;
3518+
let bsLocalStub = sinon.stub();
3519+
let args= {};
3520+
3521+
let printBuildLinkStub = sinon.stub(o11yHelpers, 'printBuildLink').returns(Promise.resolve(true));
3522+
3523+
utils.setO11yProcessHooks(buildId, bsConfig, bsLocalStub, args);
3524+
process.on('beforeExit', () => {
3525+
sinon.assert.calledOnce(printBuildLinkStub);
3526+
sinon.assert.calledWith(printBuildLinkStub, false);
3527+
done();
3528+
});
3529+
process.emit('beforeExit');
3530+
printBuildLinkStub.restore();
3531+
sinon.stub.restore();
3532+
});
3533+
3534+
it('should handle "beforeExit" event, without build id', (done) => {
3535+
let buildId = null;
3536+
let bsConfig = testObjects.sampleBsConfig;
3537+
let bsLocalStub = sinon.stub();
3538+
let args= {};
3539+
3540+
let printBuildLinkStub = sinon.stub(o11yHelpers, 'printBuildLink').returns(Promise.resolve(true));
3541+
3542+
utils.setO11yProcessHooks(buildId, bsConfig, bsLocalStub, args);
3543+
process.on('beforeExit', () => {
3544+
sinon.assert.calledOnce(printBuildLinkStub);
3545+
sinon.assert.calledWith(printBuildLinkStub, true);
3546+
done();
3547+
});
3548+
process.emit('beforeExit');
3549+
printBuildLinkStub.restore();
3550+
sinon.stub.restore();
3551+
});
3552+
});
3553+
34873554
describe('fetchZipSize', () => {
34883555
it('should return size in bytes if file is present', () => {
34893556
sinon.stub(fs, 'statSync').returns({size: 123});

0 commit comments

Comments
 (0)