aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/media-moments-feed-test.js22
-rw-r--r--tools/media-timeline-test.js10
2 files changed, 21 insertions, 11 deletions
diff --git a/tools/media-moments-feed-test.js b/tools/media-moments-feed-test.js
index f2d2774..a188c5d 100644
--- a/tools/media-moments-feed-test.js
+++ b/tools/media-moments-feed-test.js
@@ -135,15 +135,19 @@ try {
check('published audio waveform renders in the actual feed', true);
await page.evaluate(() => { const a = document.querySelector('.note-audio audio'); a.pause(); a.currentTime = 5; });
await sleep(100);
- await page.evaluate(() => document.querySelectorAll('.note-audio .media-moment-actions button')[1].click());
+ // the post's own Like carries where the clip is: no buttons of its own for that
+ const act = (sel, label) => page.evaluate(([sel, label]) => document.querySelector(sel).closest('[data-zap-post]').querySelector('.note-acts [aria-label="' + label + '"]').click(), [sel, label]);
+ check('no "at this time" buttons', await page.evaluate(() => !document.body.innerText.includes('at this time')));
+ await act('.note-audio', 'Like');
await page.waitForSelector('.msg-sheet');
await page.evaluate(() => document.querySelector('.msg-sheet button').click());
await sleep(400);
const reaction = await page.evaluate(() => window.__relayGuard.events.find(e => e.kind === 7 && e.tags.some(t => t[0] === 'media')));
check('reaction is signed with the selected file and position', reaction?.tags.some(t => t[0] === 'media' && t[2] === '5'));
check('reaction marker appears while paused', await page.evaluate(() => !!document.querySelector('.note-audio .media-mark')));
+ check('...on the bar at its moment', await page.evaluate(() => { const m = document.querySelector('.note-audio .media-mark'); return Math.abs(parseFloat(m.style.left) - 5 / document.querySelector('.note-audio audio').duration * 100) < 0.5; }));
await page.screenshot({ path: '/tmp/media-timeline-playing.png' });
- await page.evaluate(() => document.querySelector('.note-audio .media-moment-actions button').click());
+ await act('.note-audio', 'Reply');
await page.waitForSelector('.thread-reply-input');
check('timestamp is visible in the reply composer', (await page.evaluate(() => document.body.innerText)).includes('Comment at 0:05'));
await page.evaluate(() => { const input = document.querySelector('.thread-reply-input'); input.value = 'Great moment'; input.dispatchEvent(new Event('input', { bubbles: true })); });
@@ -156,15 +160,21 @@ try {
await page.waitForFunction(() => document.querySelector('.note-audio audio')?.currentTime >= 5);
check('the comment link starts playback at its timestamp', true);
await click('back'); await sleep(250);
- await page.evaluate(() => document.querySelector('video.note-video').play());
- await page.waitForSelector('.note-video-box .media-moment-actions');
- await page.evaluate(() => { const v = document.querySelector('video.note-video'); v.pause(); v.currentTime = 1; });
+ // a clip in the pager: its ♥ carries the moment, which then sits on its seek bar
+ await page.evaluate(() => { const v = document.querySelector('video.note-video'); const r = v.getBoundingClientRect();
+ v.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: r.left + r.width / 2, clientY: r.top + r.height / 3 })); });
+ await page.waitForSelector('.media-pager .mp-cur video', { timeout: 8000 });
+ await page.waitForFunction(() => document.querySelector('.media-pager .mp-cur video').duration > 0, { timeout: 8000 });
+ await page.evaluate(() => { const v = document.querySelector('.media-pager .mp-cur video'); v.pause(); v.currentTime = 1; });
await sleep(150);
- await page.evaluate(() => document.querySelectorAll('.note-video-box .media-moment-actions button')[1].click());
+ await page.evaluate(() => document.querySelector('.media-pager .mp-cur .mp-like').click());
await page.waitForSelector('.msg-sheet');
await page.evaluate(() => document.querySelector('.msg-sheet button').click());
await sleep(300);
check('video reaction carries the video URL and selected second', await page.evaluate(() => window.__relayGuard.events.some(e => e.kind === 7 && e.tags.some(t => t[0] === 'media' && t[1].endsWith('.mp4') && t[2] === '1'))));
+ check('...and shows over the pager\'s seek bar', await page.waitForFunction(() => !!document.querySelector('.media-pager .mp-cur .mp-seek .mp-mark'), { timeout: 3000 }).then(() => true, () => false));
+ check('no timeline panel over the pager', await page.evaluate(() => !document.querySelector('.media-pager .media-timeline')));
+ await page.screenshot({ path: '/tmp/media-timeline-pager.png' });
check('no browser exceptions', errs.length === 0, errs.join(' | '));
await page.screenshot({ path: '/tmp/media-timeline-feed.png' });
} finally { await browser.close(); server.stop(); }
diff --git a/tools/media-timeline-test.js b/tools/media-timeline-test.js
index c8f1fd9..3b812ff 100644
--- a/tools/media-timeline-test.js
+++ b/tools/media-timeline-test.js
@@ -54,27 +54,27 @@ try {
const url = 'https://example.com/song.mp3';
const ev = { id: 'post', tags: [['imeta', 'url ' + url, 'waveform 1 10 4 8']] };
const calls = [], items = [{ id: 'a', moment: { seconds: 30 }, icon: '♡', text: 'Nice!' }];
- const box = mediaTimeline(player, url, { h, event: () => ev, moments: () => items, action: (...a) => calls.push(a.slice(0, 3)), label: x => ({ mediaAtTime: 'at this time' }[x] || x) });
+ const box = mediaTimeline(player, url, { h, event: () => ev, moments: () => items, glyph: x => x.icon, label: x => x });
document.body.append(player, box);
player.dispatchEvent(new Event('timeupdate'));
const wave = box.querySelectorAll('.media-wave i').length;
const range = box.querySelector('input'); range.value = 500; range.dispatchEvent(new Event('input'));
const seek = at;
- for (const b of box.querySelectorAll('.media-moment-actions button')) b.click();
box.querySelector('.media-mark').click();
const marker = at;
items.push({ id: 'b', moment: { seconds: 70 }, icon: '⚡', text: '' });
player.dispatchEvent(new Event('mediaactivity'));
window.fixture = box;
- return { wave, seek, marker, calls, markers: box.querySelectorAll('.media-mark').length, aria: range.getAttribute('aria-valuetext') };
+ return { wave, seek, marker, calls, markers: box.querySelectorAll('.media-mark').length, left: [...box.querySelectorAll('.media-mark')].map(m => m.style.left), buttons: box.querySelectorAll('button:not(.media-mark)').length, aria: range.getAttribute('aria-valuetext') };
});
assert.equal(result.wave, 4);
assert.equal(result.seek, 60);
assert.equal(result.marker, 30);
assert.equal(result.markers, 2);
- assert.deepEqual(result.calls.map(c => [c[0], c[1].id, c[2].seconds]), [['comment', 'post', 60], ['reaction', 'post', 60], ['zap', 'post', 60]]);
+ assert.deepEqual(result.left, ['25%', '58.3333%']); // each on the bar at its moment
+ assert.equal(result.buttons, 0); // no "at this time" buttons
await page.setViewport({ width: 360, height: 740 });
assert.equal(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), true);
await page.screenshot({ path: '/tmp/media-timeline-mobile.png' });
- console.log('✓ Timestamp validation, Lightning receipt round-trip, untimed zap isolation, waveform peaks, browser seeking, all three actions, marker updates and mobile layout');
+ console.log('✓ Timestamp validation, Lightning receipt round-trip, untimed zap isolation, waveform peaks, browser seeking, markers placed at their moments and mobile layout');
} finally { await browser.close(); server.stop(); }