Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions nightwatch/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@
if (testRunner !== 'cucumber'){
const uuid = TestMap.storeTestDetails(test);
process.env.TEST_RUN_UUID = uuid;
// LTS-only: reset the per-test step buffer that bstackStep() (injected
// by the LCNC compiler into the compiled spec) writes into. Read back
// in testObservability.sendTestRunEvent at TestRunFinished.
if (helper.isLoadTestingSession()) {globalThis.__bstack_steps = [];}

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

Extra semicolon

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

'globalThis' is not defined

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

Extra semicolon

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

Extra semicolon

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

'globalThis' is not defined

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

Extra semicolon

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

'globalThis' is not defined

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

Extra semicolon

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

Extra semicolon

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

Extra semicolon

Check failure on line 308 in nightwatch/globals.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined
// Capture the live session id at TestRunStarted (when browser.end()
// hasn't run yet). TestRunFinished's async handler can race with
// afterEach: by the time it executes, browser.sessionId may already
Expand Down
13 changes: 13 additions & 0 deletions src/testObservability.js
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,19 @@
if (eventType === 'TestRunFinished') {
const eventData = test.envelope[testName].testcase;
testData.finished_at = eventData.endTimestamp ? new Date(eventData.endTimestamp).toISOString() : new Date(startTimestamp).toISOString();
// LTS-only: main-path Nightwatch TestRunFinished doesn't carry duration_in_ms
// (cucumber/hook/skipped paths do). Compute from timestamps so BTCER duration
// populates for LTS builds. Non-LTS emits unchanged.
if (helper.isLoadTestingSession()) {
testData.duration_in_ms = new Date(testData.finished_at).getTime() - new Date(testData.started_at).getTime();
// LTS-only: attach per-step data collected by bstackStep() (injected by
// the LCNC compiler into the compiled spec). Empty/absent → skip so
// non-instrumented specs stay backward-compatible.
const steps = globalThis.__bstack_steps;

Check failure on line 546 in src/testObservability.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

'globalThis' is not defined

Check failure on line 546 in src/testObservability.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 546 in src/testObservability.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

'globalThis' is not defined

Check failure on line 546 in src/testObservability.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

'globalThis' is not defined

Check failure on line 546 in src/testObservability.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined

Check failure on line 546 in src/testObservability.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 546 in src/testObservability.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined
if (Array.isArray(steps) && steps.length) {
testData.meta = {...(testData.meta || {}), steps};
}
}
testData.result = 'passed';
if (eventData && eventData.commands && Array.isArray(eventData.commands)) {
const failedCommand = eventData.commands.find(cmd => cmd.status === 'fail' && !helper.isSuppressedFailure(cmd));
Expand Down
74 changes: 74 additions & 0 deletions test/src/test-observability/sendTestRunEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,78 @@
`expected failure_reason to reference the real failure, got: ${this.uploaded.test_run.failure_reason}`
);
});

// LTS regression: main-path Nightwatch TestRunFinished never carried
// duration_in_ms, leaving BTCER.duration NULL on load-testing builds and
// zeroing every duration-derived Tests-tab metric (min/avg/p50/p95/max).
// The fix computes duration from the envelope timestamps only when
// helper.isLoadTestingSession() is true. Non-LTS runs remain unchanged.
it('populates duration_in_ms from timestamps on LTS runs', async () => {
this.sandbox.stub(helper, 'isLoadTestingSession').returns(true);
const commands = [{name: 'url', args: ['https://example.com'], status: 'pass'}];

await this.testObservability.sendTestRunEvent('TestRunFinished', buildTest(commands), 'uuid-lts-1');

// Fixture: startTimestamp=1700000000000, endTimestamp=1700000001000 → 1000 ms.
assert.strictEqual(this.uploaded.test_run.duration_in_ms, 1000);
});

it('leaves duration_in_ms unset on non-LTS runs', async () => {
this.sandbox.stub(helper, 'isLoadTestingSession').returns(false);
const commands = [{name: 'url', args: ['https://example.com'], status: 'pass'}];

await this.testObservability.sendTestRunEvent('TestRunFinished', buildTest(commands), 'uuid-lts-2');

assert.ok(
!('duration_in_ms' in this.uploaded.test_run),
'expected no duration_in_ms on non-LTS runs (contract preserved)'
);
});

// LTS step-level insights: the LCNC compiler wraps each recorded step in a
// bstackStep() helper that pushes {id, text, duration, ...} to
// globalThis.__bstack_steps. sendTestRunEvent must attach that array to
// testData.meta.steps at TestRunFinished (only when isLoadTestingSession()
// is true) so the Testhub MV mv_btcer_step_metrics_v5 fans it out into the
// btcer_step_metrics_v5 table that Step Insights aggregates on.
it('attaches globalThis.__bstack_steps to meta.steps on LTS runs', async () => {
this.sandbox.stub(helper, 'isLoadTestingSession').returns(true);
const steps = [
{id: 'a', text: 'Open page', keyword: '', duration: 800, started_at: '2026-07-27T16:00:00.000', finished_at: '2026-07-27T16:00:00.800', result: 'passed', failure: null},
{id: 'b', text: 'Click X', keyword: '', duration: 120, started_at: '2026-07-27T16:00:00.800', finished_at: '2026-07-27T16:00:00.920', result: 'passed', failure: null}
];
globalThis.__bstack_steps = steps;

Check failure on line 204 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

'globalThis' is not defined

Check failure on line 204 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 204 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

'globalThis' is not defined

Check failure on line 204 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

'globalThis' is not defined

Check failure on line 204 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined

Check failure on line 204 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 204 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined
const commands = [{name: 'url', args: ['https://example.com'], status: 'pass'}];

try {
await this.testObservability.sendTestRunEvent('TestRunFinished', buildTest(commands), 'uuid-lts-steps-1');
assert.deepStrictEqual(this.uploaded.test_run.meta && this.uploaded.test_run.meta.steps, steps);
} finally {
delete globalThis.__bstack_steps;

Check failure on line 211 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

'globalThis' is not defined

Check failure on line 211 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 211 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

'globalThis' is not defined

Check failure on line 211 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

'globalThis' is not defined

Check failure on line 211 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined

Check failure on line 211 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 211 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined
}
});

it('omits meta.steps on non-LTS runs even when the buffer is populated', async () => {
this.sandbox.stub(helper, 'isLoadTestingSession').returns(false);
globalThis.__bstack_steps = [{id: 'a', text: 'Open page', duration: 800, result: 'passed'}];

Check failure on line 217 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

'globalThis' is not defined

Check failure on line 217 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 217 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

'globalThis' is not defined

Check failure on line 217 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

'globalThis' is not defined

Check failure on line 217 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined

Check failure on line 217 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 217 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined
const commands = [{name: 'url', args: ['https://example.com'], status: 'pass'}];

try {
await this.testObservability.sendTestRunEvent('TestRunFinished', buildTest(commands), 'uuid-lts-steps-2');
const meta = this.uploaded.test_run.meta;
assert.ok(!meta || !('steps' in meta), 'expected no meta.steps on non-LTS runs (contract preserved)');
} finally {
delete globalThis.__bstack_steps;

Check failure on line 225 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

'globalThis' is not defined

Check failure on line 225 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 225 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

'globalThis' is not defined

Check failure on line 225 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

'globalThis' is not defined

Check failure on line 225 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined

Check failure on line 225 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 225 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined
}
});

it('leaves meta.steps unset on LTS runs when the buffer is empty or missing', async () => {
this.sandbox.stub(helper, 'isLoadTestingSession').returns(true);
delete globalThis.__bstack_steps;

Check failure on line 231 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (20.x)

'globalThis' is not defined

Check failure on line 231 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 231 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (21.x)

'globalThis' is not defined

Check failure on line 231 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (21.x)

'globalThis' is not defined

Check failure on line 231 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined

Check failure on line 231 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / linux (18.x)

'globalThis' is not defined

Check failure on line 231 in test/src/test-observability/sendTestRunEvent.js

View workflow job for this annotation

GitHub Actions / windows (20.x)

'globalThis' is not defined
const commands = [{name: 'url', args: ['https://example.com'], status: 'pass'}];

await this.testObservability.sendTestRunEvent('TestRunFinished', buildTest(commands), 'uuid-lts-steps-3');
const meta = this.uploaded.test_run.meta;
assert.ok(!meta || !('steps' in meta), 'expected no meta.steps when nothing was recorded');
});
});
Loading