mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-15 17:16:16 -08:00
fix(core): [PKG-DPIP-05] keep web fullscreen in the active document
This commit is contained in:
1 parent
401c5e9684
commit
7e37fd4d0e
19 files changed
+1408
-15
No files matched your search
@@ -6,6 +6,33 @@ async function setup(page, core) {
|
||||
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
|
||||
}
|
||||
|
||||
test('candidate: adopted player enters its current document body and restores placement and focus', async ({ page }) => {
|
||||
await setup(page, 'candidate')
|
||||
const result = await page.evaluate(() => {
|
||||
const frame = document.createElement('iframe')
|
||||
document.body.append(frame)
|
||||
const target = frame.contentDocument
|
||||
const wrapper = target.createElement('div')
|
||||
const sibling = target.createElement('span')
|
||||
const probe = target.createElement('button')
|
||||
const player = window.art.template.$player
|
||||
target.body.append(wrapper)
|
||||
wrapper.append(player, sibling)
|
||||
player.append(probe)
|
||||
probe.focus()
|
||||
window.Artplayer.FULLSCREEN_WEB_IN_BODY = true
|
||||
window.art.fullscreenWeb = true
|
||||
const entered = player.parentNode === target.body && player.ownerDocument === target
|
||||
const focused = target.activeElement === probe
|
||||
window.art.fullscreenWeb = false
|
||||
const restored = player.parentNode === wrapper && player.nextSibling === sibling && target.activeElement === probe
|
||||
window.art.destroy()
|
||||
frame.remove()
|
||||
return { entered, focused, restored }
|
||||
})
|
||||
expect(result).toEqual({ entered: true, focused: true, restored: true })
|
||||
})
|
||||
|
||||
for (const removeHtml of [false, true]) {
|
||||
for (const movedBeforeThrow of [false, true]) {
|
||||
test(`candidate: failed destroy restoration cannot orphan the player removeHtml=${removeHtml} movedBeforeThrow=${movedBeforeThrow}`, async ({ page }) => {
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import fs from 'node:fs'
|
||||
import { hash } from '../../refactor/scripts/releases.mjs'
|
||||
import { dpipCandidate } from '../helpers/dpip.js'
|
||||
import { mbCandidate } from '../helpers/mediabunny.js'
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
const dpip = await dpipCandidate()
|
||||
const mb = await mbCandidate()
|
||||
const canvas = fs.readFileSync(new URL('../../packages/artplayer-proxy-canvas/dist/artplayer-proxy-canvas.js', import.meta.url), 'utf8')
|
||||
|
||||
for (const core of ['published', 'candidate']) {
|
||||
for (const renderer of ['video', 'canvas', 'mediabunny']) {
|
||||
test(`Document PiP native ${core}/${renderer}: repeated windows and real keyboard`, async ({ page, context }, testInfo) => {
|
||||
await page.goto(`/test/player.html?core=${core}`)
|
||||
const supported = await page.evaluate(() => typeof window.documentPictureInPicture?.requestWindow === 'function')
|
||||
const evidence = { core, renderer, supported, dpipSha256: hash(dpip.code), proxySha256: renderer === 'video' ? null : hash(renderer === 'canvas' ? canvas : mb.code), outcome: 'incomplete', rounds: [] }
|
||||
if (!supported) {
|
||||
evidence.outcome = 'native-document-pip-unavailable'
|
||||
await testInfo.attach('dpip-native', { contentType: 'application/json', body: JSON.stringify(evidence) })
|
||||
return
|
||||
}
|
||||
for (const [code, name] of [[dpip.code, 'dpipFactory'], [canvas, 'canvasFactory'], [mb.code, 'mbFactory']])
|
||||
await page.addScriptTag({ content: `(() => { const module = { exports: {} }; const exports = module.exports; ${code}; window.${name} = module.exports.default || module.exports; })();` })
|
||||
await page.evaluate((renderer) => {
|
||||
const proxy = renderer === 'video' ? {} : { proxy: renderer === 'canvas' ? window.canvasFactory() : window.mbFactory() }
|
||||
window.art = new window.Artplayer({ container: '.player', url: '/test/pattern.mp4', muted: true, ...proxy, plugins: [window.dpipFactory({ fallbackToVideoPiP: false })] })
|
||||
window.dpip = window.art.plugins.artplayerPluginDocumentPip
|
||||
window.dpipMedia = window.art.video
|
||||
window.dpipParent = window.art.template.$player.parentNode
|
||||
window.dpipEvents = []
|
||||
window.dpipKeys = 0
|
||||
window.art.on('document-pip', value => window.dpipEvents.push(value))
|
||||
window.art.hotkey.add('KeyQ', () => window.dpipKeys++)
|
||||
const probe = document.createElement('button')
|
||||
probe.id = 'keyboard-probe'
|
||||
probe.textContent = 'Keyboard probe'
|
||||
probe.style.cssText = 'position:absolute;top:20px;left:20px;z-index:9999'
|
||||
window.art.template.$player.append(probe)
|
||||
document.querySelector('#play').onclick = () => window.art.play()
|
||||
const open = document.createElement('button')
|
||||
open.id = 'open-native-pip'
|
||||
open.textContent = 'Open PiP'
|
||||
open.onclick = () => {
|
||||
window.dpipOpening = window.dpip.open()
|
||||
}
|
||||
document.body.append(open)
|
||||
}, renderer)
|
||||
try {
|
||||
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
|
||||
await page.click('#play')
|
||||
let keys = 0
|
||||
for (let round = 0; round < 2; round++) {
|
||||
const popupPromise = context.waitForEvent('page', { timeout: 8000 })
|
||||
await page.click('#open-native-pip')
|
||||
const popup = await popupPromise
|
||||
await page.evaluate(() => window.dpipOpening)
|
||||
await expect(popup.locator('#keyboard-probe')).toBeVisible()
|
||||
expect(await page.evaluate(() => window.art.video === window.dpipMedia && window.art.template.$player.ownerDocument === window.documentPictureInPicture.window.document)).toBe(true)
|
||||
const before = await page.evaluate(() => window.art.currentTime)
|
||||
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(before + 0.2)
|
||||
await popup.locator('#keyboard-probe').click()
|
||||
await popup.keyboard.press('q')
|
||||
await expect.poll(() => page.evaluate(() => window.dpipKeys)).toBe(++keys)
|
||||
const input = await popup.evaluate(() => {
|
||||
const input = document.createElement('input')
|
||||
input.id = 'editable-probe'
|
||||
document.querySelector('.art-video-player').append(input)
|
||||
return input.id
|
||||
})
|
||||
await popup.locator(`#${input}`).press('q')
|
||||
await expect(popup.locator(`#${input}`)).toHaveValue(core === 'published' ? '' : 'q')
|
||||
if (core === 'published')
|
||||
keys++
|
||||
expect(await page.evaluate(() => window.dpipKeys)).toBe(keys)
|
||||
await popup.locator(`#${input}`).evaluate(element => element.remove())
|
||||
if (core === 'candidate') {
|
||||
await page.evaluate(() => {
|
||||
window.Artplayer.FULLSCREEN_WEB_IN_BODY = true
|
||||
window.art.fullscreenWeb = true
|
||||
})
|
||||
expect(await page.evaluate(() => window.art.template.$player.parentNode === window.documentPictureInPicture.window.document.body)).toBe(true)
|
||||
await page.evaluate(() => {
|
||||
window.art.fullscreenWeb = false
|
||||
})
|
||||
expect(await popup.locator('.art-video-player').count()).toBe(1)
|
||||
}
|
||||
await page.evaluate(() => window.documentPictureInPicture.window.close())
|
||||
await expect.poll(() => page.evaluate(() => window.dpip.isActive)).toBe(false)
|
||||
expect(await page.evaluate(() => window.art.template.$player.parentNode === window.dpipParent && window.art.video === window.dpipMedia && document.querySelectorAll('.artplayer-document-pip-placeholder').length === 0)).toBe(true)
|
||||
await page.locator('#keyboard-probe').click()
|
||||
await page.keyboard.press('q')
|
||||
await expect.poll(() => page.evaluate(() => window.dpipKeys)).toBe(++keys)
|
||||
evidence.rounds.push({ round, nativeWindowClosed: popup.isClosed(), keys: await page.evaluate(() => window.dpipKeys) })
|
||||
}
|
||||
expect(await page.evaluate(() => window.dpipEvents)).toEqual([true, false, true, false])
|
||||
evidence.outcome = core === 'published' ? 'native-window-with-historical-editable-hotkey-defect' : 'native-window-media-keyboard-restoration'
|
||||
}
|
||||
finally {
|
||||
await page.evaluate(() => {
|
||||
window.art.destroy(false)
|
||||
window.documentPictureInPicture.window?.close()
|
||||
})
|
||||
await testInfo.attach('dpip-native', { contentType: 'application/json', body: JSON.stringify(evidence) })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user