Skip to content

Instantly share code, notes, and snippets.

@MarekZeman91
Last active February 22, 2025 03:47
Show Gist options
  • Save MarekZeman91/3d66fb76b215a27fc813ccc4959f46d7 to your computer and use it in GitHub Desktop.
Save MarekZeman91/3d66fb76b215a27fc813ccc4959f46d7 to your computer and use it in GitHub Desktop.
PlaywrightStalker ... for those who like to watch. It is a button/script that always keeps the current test active and visible.
// 1. run Playwright with ui
// 2. paste this code in console
// 3. there is a new PIN button next to Playwright logo
window.PlaywrightStalker?.stop();
window.PlaywrightStalker = ((d = document) => {
const $ = (sel) => d.querySelector(sel);
const $$ = (sel) => Array.from(d.querySelectorAll(sel));
const delay = (ms = 1) => new Promise((r) => setTimeout(r, ms));
const h = (node, props) => Object.assign(d.createElement(node), props);
const refBtn = '.ui-mode-sidebar > .toolbar .toolbar-button';
const playBtn = '.ui-mode-sidebar > .toolbar .toolbar-button.play';
const tests = '.tests-list-view';
const actions = '.actions-list-view';
const entry = '.list-view-entry';
const content = '.list-view-content';
let isActive = false;
let stalkerId = 0;
let $btn = $(refBtn);
const goTo = async (el) => {
el && el.scrollIntoViewIfNeeded() && (await delay());
el && el.focus() && (await delay());
el && el.click() && (await delay());
};
const stalker = async () => {
// testing is not running
if (!$(playBtn).disabled) return;
const $openable = $$(`:is(${tests},${actions}) .codicon-chevron-right`);
$openable.forEach((x) => x.click());
await delay();
const $loading = $$(`${tests} ${entry}:has(.codicon-loading)`).at(-1);
await goTo($loading);
const $current = $(`${actions} ${entry}:last-child:not(.selected)`);
await goTo($current);
const $content = $(`${actions} ${content}`);
$content && ($content.scrollTop = $content.scrollHeight);
};
const start = () => {
clearInterval(stalkerId);
stalkerId = setInterval(stalker, 10);
isActive = true;
$btn.classList.toggle('toggled', isActive);
};
const stop = () => {
clearInterval(stalkerId);
isActive = false;
$btn.classList.toggle('toggled', isActive);
};
const toggle = () => {
isActive = !isActive;
isActive ? start() : stop();
$btn.classList.toggle('toggled', isActive);
};
if ($btn.classList.contains('stalk')) {
$btn.classList.contains('toggled') && $btn.click();
$btn.onclick = toggle;
} else {
const ref = $btn;
$btn = h('button', {
className: 'toolbar-button stalk',
title: 'Stalk',
onclick: toggle,
});
$btn.append(h('span', { className: 'codicon codicon-pinned' }));
ref.before($btn);
}
return { isActive: () => isActive, start, stop };
})();
// to check if it is active use
// PlaywrightStalker.isActive();
// to stop click the button or use
// PlaywrightStalker.stop();
// to start click the button or use
// PlaywrightStalker.start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment