load tests: show the live timing in the run banner
release / release (push) Has been cancelled

The test-run banner (visible on every Test-script view) now carries the
same live stats as the script head and the suite summary: elapsed so far,
the average per completed iteration and the estimated time left.  The
text is built by a pure helper (testRunBannerText) so it is testable;
testRender only calls it while a run is active, and non-load runs keep
their position text (step or suite-member progress).

The existing banner-source assertion moved to the helper.  Tests: the
banner text for a load suite and a plain run.  1061 Python + 1075
frontend; sw cache simple-v481.  CHANGELOG/help/docs/AGENTS updated.
This commit is contained in:
catarrh committed 2026-10-24 12:03:23 +03:00
1 parent 8ebcfd8af4
commit 80cbd8e935
7 files changed
+62 -24

No files matched your search

+21 -4
View File
@@ -25,7 +25,7 @@ function extractFunc(src, name) {
const FNS = ['esc', 'testStatusBadge', 'testRenderScriptRun', 'testRenderReport',
'testIterationsInit', 'testIterationsChanged', 'testIterationsValue',
'testLoadTiming', 'testDurationText', 'testIterAvgText'];
'testLoadTiming', 'testDurationText', 'testIterAvgText', 'testRunBannerText'];
const code = FNS.map(f => extractFunc(html, f)).join('\n');
function fakeEl(id) {
@@ -51,7 +51,7 @@ function build(els, storage, curRef) {
getState: () => _testRunState,
testRenderScriptRun, testRenderReport,
testIterationsValue, testIterationsChanged, testIterationsInit,
testLoadTiming, testDurationText, testIterAvgText,
testLoadTiming, testDurationText, testIterAvgText, testRunBannerText,
};
`);
return fn(els, storage, curRef);
@@ -132,6 +132,23 @@ test('the live load timing computes elapsed, average and left', () => {
assert.strictEqual(app.testIterAvgText(1500), '1.50 s');
});
test('the run banner carries the live load timing', () => {
const app = build({}, { getItem: () => null, setItem: () => {} }, { value: null });
const now = Date.now();
const text = app.testRunBannerText({ running: true, name: 'Load suite',
load: { enabled: true, suite: true, iterations: 50, iteration: 6, done: 5,
started: now / 1000 - 10 } });
assert.match(text, /Test suite running: Load suite/);
assert.match(text, /Iteration 6\/50/);
assert.match(text, /elapsed 0:10/);
assert.match(text, /avg 2\.00 s/);
assert.match(text, /left ~1:30/);
// a non-load run has no timing part (only its position)
const plain = app.testRunBannerText({ running: true, name: 'S', index: 2, total: 5 });
assert.match(plain, /Test script running: S \(3\/5\)/);
assert.ok(!plain.includes('elapsed'), plain);
});
test('a running load test shows elapsed, average and left', () => {
const els = { 'test-run-status': fakeEl('test-run-status'),
'test-run-steps': fakeEl('test-run-steps') };
@@ -221,6 +238,6 @@ test('a successful load run can be exported and reopened after a reload (v3.37.0
assert.match(init, /st\.load && st\.load\.enabled/);
assert.match(init, /const idx = st\.suite\s*\?/, 'a null suite must not break the reopen');
// the banner knows a load suite even when its state is cleared
const render = extractFunc(html, 'testRender');
assert.match(render, /const isSuite = !!\(snap\.suite \|\| \(load && load\.suite\)\);/);
const banner = extractFunc(html, 'testRunBannerText');
assert.match(banner, /const isSuite = !!\(snap\.suite \|\| \(load && load\.suite\)\);/);
});