diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/media-moments-feed-test.js | 22 | ||||
| -rw-r--r-- | tools/media-timeline-test.js | 10 |
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(); } |
