in src/common/runtime/standalone.ts [404:520]
function makeTreeNodeHeaderHTML(
n: TestTreeNode,
runSubtree: RunSubtree,
parentLevel: TestQueryLevel,
onChange: (checked: boolean) => void
): [HTMLElement, SetCheckedRecursively] {
const isLeaf = 'run' in n;
const div = $('<details>').addClass('nodeheader');
const header = $('<summary>').appendTo(div);
// prevent toggling if user is selecting text from an input element
{
let lastNodeName = '';
div.on('pointerdown', event => {
lastNodeName = event.target.nodeName;
});
div.on('click', event => {
if (lastNodeName === 'INPUT') {
event.preventDefault();
}
});
}
const setChecked = () => {
div.prop('open', true); // (does not fire onChange)
onChange(true);
};
const href = createSearchQuery([n.query.toString()]);
if (onChange) {
div.on('toggle', function (this) {
onChange((this as HTMLDetailsElement).open);
});
// Expand the shallower parts of the tree at load.
// Also expand completely within subtrees that are at the same query level
// (e.g. s:f:t,* and s:f:t,t,*).
if (n.query.level <= lastQueryLevelToExpand || n.query.level === parentLevel) {
setChecked();
}
}
const runtext = isLeaf ? 'Run case' : 'Run subtree';
$('<button>')
.addClass(isLeaf ? 'leafrun' : 'subtreerun')
.attr('alt', runtext)
.attr('title', runtext)
.on('click', async () => {
if (runDepth > 0) {
showInfo('tests are already running');
return;
}
showInfo('');
console.log(`Starting run for ${n.query}`);
// turn off all run buttons
$('#resultsVis').addClass('disable-run');
const startTime = performance.now();
await runSubtree();
const dt = performance.now() - startTime;
const dtMinutes = dt / 1000 / 60;
// turn on all run buttons
$('#resultsVis').removeClass('disable-run');
console.log(`Finished run: ${dt.toFixed(1)} ms = ${dtMinutes.toFixed(1)} min`);
})
.appendTo(header);
$('<a>')
.addClass('nodelink')
.attr('href', href)
.attr('alt', kOpenTestLinkAltText)
.attr('title', kOpenTestLinkAltText)
.appendTo(header);
$('<button>')
.addClass('copybtn')
.attr('alt', 'copy query')
.attr('title', 'copy query')
.on('click', () => {
void navigator.clipboard.writeText(n.query.toString());
})
.appendTo(header);
if ('testCreationStack' in n && n.testCreationStack) {
$('<button>')
.addClass('testcaselogbtn')
.attr('alt', 'Log test creation stack to console')
.attr('title', 'Log test creation stack to console')
.appendTo(header)
.on('click', () => {
consoleLogError(n.testCreationStack);
});
}
const nodetitle = $('<div>').addClass('nodetitle').appendTo(header);
const nodecolumns = $('<span>').addClass('nodecolumns').appendTo(nodetitle);
{
$('<input>')
.attr('type', 'text')
.attr('title', n.query.toString())
.prop('readonly', true)
.addClass('nodequery')
.on('click', event => {
(event.target as HTMLInputElement).select();
})
.val(n.query.toString())
.appendTo(nodecolumns);
if (n.subtreeCounts) {
$('<span>')
.attr('title', '(Nodes with TODOs) / (Total test count)')
.text(TestTree.countsToString(n))
.appendTo(nodecolumns);
}
}
if ('description' in n && n.description) {
nodetitle.append(' ');
$('<pre>') //
.addClass('nodedescription')
.text(n.description)
.appendTo(header);
}
return [div[0], setChecked];
}