aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/harness/music_queue_probe.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/harness/music_queue_probe.py')
-rwxr-xr-xpackages/meshbay-hub/tests/harness/music_queue_probe.py58
1 files changed, 55 insertions, 3 deletions
diff --git a/packages/meshbay-hub/tests/harness/music_queue_probe.py b/packages/meshbay-hub/tests/harness/music_queue_probe.py
index f74ceb2..a9146ce 100755
--- a/packages/meshbay-hub/tests/harness/music_queue_probe.py
+++ b/packages/meshbay-hub/tests/harness/music_queue_probe.py
@@ -119,12 +119,24 @@ function Harness() {
const onPlayQueue = useCallback((tracks, startIndex, source, op) => {
setQueue({ tracks, startIndex, nonce: Date.now(), op: op || 'replace' });
}, []);
+ // A queue that crosses groups cannot be built from one group's page, and
+ // that is the case the skipping rule exists for — so the probe reaches in
+ // for that one step rather than pretending a gesture builds it.
+ window.__probePlayQueue = onPlayQueue;
+
+ // Rejects at once for a group nothing serves, and hangs for every other —
+ // hanging is what the stub node does anyway, and what matters here is which
+ // track the playhead lands on, not whether anything plays.
+ const getConnection = (groupId) => (String(groupId).startsWith('dead')
+ ? Promise.reject(new Error('no node'))
+ : new Promise(() => {}));
+
return html`
<${GroupPage} groupId="g1" token="t" username="me" userId="u1"
group=${{ id: 'g1', name: 'un groupe', owner_username: 'me', is_admin: false }}
userPrefs=${{ default_tab: 'music', media_page_size: '50' }}
onPlayQueue=${onPlayQueue} />
- ${queue && html`<${MusicPlayerBar} getConnection=${() => new Promise(() => {})}
+ ${queue && html`<${MusicPlayerBar} getConnection=${getConnection}
queue=${queue} userPrefs=${{}} onClose=${() => setQueue(null)} />`}
`;
}
@@ -171,9 +183,29 @@ const clickMenu = async (i) => {
await initLocale();
render(html`<${Harness} />`, document.getElementById('root'));
- if (!await waitFor('.music-card')) return fail('no album grid');
+ // Wait for the grid to be *complete*, not merely present — and scroll,
+ // because it will not complete otherwise: the tiles mount on intersection
+ // (`LazyTile`), so an album below the fold has no card at all until the
+ // page is scrolled to it. A probe that counts what happens to be on screen
+ // is measuring the height of its own iframe; adding one button to the
+ // toolbar was enough to push the fourth album out of view.
+ const waitForCount = async (sel, n, tries = 80) => {
+ for (let i = 0; i < tries; i++) {
+ if (document.querySelectorAll(sel).length >= n) {
+ scrollTo(0, 0);
+ await sleep(100);
+ return true;
+ }
+ scrollTo(0, document.documentElement.scrollHeight);
+ await sleep(50);
+ }
+ return false;
+ };
+ if (!await waitForCount('.music-card', 4)) {
+ return fail('expected 4 albums, got '
+ + document.querySelectorAll('.music-card').length);
+ }
const cards = [...document.querySelectorAll('.music-card')];
- if (cards.length < 4) return fail('expected 4 albums, got ' + cards.length);
// 1. Open album 1 and play its second track — the ordinary path, through a
// row that is no longer one big button.
@@ -219,6 +251,26 @@ const clickMenu = async (i) => {
await sleep(250);
await queueNow('replace with album 4');
+ // 6. A group that does not answer: every one of its queued tracks is
+ // skipped in one step, not one failure at a time against a bound that
+ // was sized for corrupt files.
+ const mixed = (id, group) => ({
+ id, name: id + '.flac', display_title: id, path: 'p', size: 10,
+ type: 'audio', duration: 100, groupId: group,
+ });
+ window.__probePlayQueue([
+ mixed('live-1', 'g1'),
+ mixed('dead-1', 'dead-a'), mixed('dead-2', 'dead-a'),
+ mixed('dead-3', 'dead-a'), mixed('dead-4', 'dead-a'),
+ mixed('dead-5', 'dead-a'), mixed('dead-6', 'dead-a'),
+ mixed('live-2', 'g1'),
+ ], 1, null, 'replace');
+ await sleep(1200);
+ steps.push({
+ step: 'an unreachable group is skipped whole',
+ nowPlaying: (document.querySelector('.music-player-title') || {}).textContent || null,
+ });
+
parent.postMessage({ steps, logs: LOGS.slice(0, 8) }, '*');
} catch (err) {
fail(String((err && err.stack) || err));