Skip to content

Commit 83e3f84

Browse files
authored
Merge branch 'main' into jkt/preventDebugSerializeExceptions
2 parents a71de59 + e334bea commit 83e3f84

File tree

8 files changed

+92
-21
lines changed

8 files changed

+92
-21
lines changed

.github/workflows/tests.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,15 @@ jobs:
6969
if: always()
7070
with:
7171
name: playwright-report
72-
path: playwright-report/
72+
path: test-results
7373
retention-days: 5
7474
- run: npm run test-int-x
75+
- uses: actions/upload-artifact@v2
76+
if: always()
77+
with:
78+
name: playwright-report-pages
79+
path: packages/special-pages/test-results
80+
retention-days: 5
7581
- name: Build docs
7682
run: npm run docs
7783

packages/special-pages/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
test-results
2+
playwright-report

packages/special-pages/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
"main": "index.js",
77
"scripts": {
88
"build": "node index.mjs",
9-
"build.dev": "node index.mjs --debug",
9+
"build.dev": "node index.mjs --env development",
1010
"test": "playwright test",
1111
"test.windows": "npm run test -- --project duckplayer-windows",
1212
"test.apple": "npm run test -- --project duckplayer-apple",
1313
"test.headed": "npm run test -- --headed",
1414
"test.ui": "npm run test -- --ui",
1515
"pretest": "npm run build.dev",
1616
"pretest.headed": "npm run build.dev",
17-
"test-int-x": "playwright test",
18-
"test-int": "playwright test",
17+
"test-int-x": "npm run test",
18+
"test-int": "npm run test",
1919
"serve": "http-server -c-1 --port 3210 ../../"
2020
},
2121
"license": "ISC",

packages/special-pages/pages/duckplayer/src/js/index.js

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@
3131
*
3232
* Please see {@link DuckPlayerPageMessages} for the up-to-date list
3333
*/
34-
import { createDuckPlayerPageMessaging, DuckPlayerPageMessages, UserValues } from './messages'
34+
import {
35+
callWithRetry,
36+
createDuckPlayerPageMessaging,
37+
DuckPlayerPageMessages,
38+
UserValues
39+
} from './messages'
3540
import { html } from '../../../../../../src/dom-utils'
3641
import { initStorage } from './storage'
3742

@@ -325,23 +330,31 @@ const Comms = {
325330
* @param {ImportMeta['env']} opts.env
326331
* @param {ImportMeta['injectName']} opts.injectName
327332
*/
328-
init: (opts) => {
329-
Comms.messaging = createDuckPlayerPageMessaging(opts)
330-
// eslint-disable-next-line promise/prefer-await-to-then
331-
Comms.messaging.getUserValues().then((value) => {
332-
if ('enabled' in value.privatePlayerMode) {
333-
Setting.setState(true)
334-
} else {
335-
Setting.setState(false)
336-
}
333+
init: async (opts) => {
334+
const messaging = createDuckPlayerPageMessaging(opts)
335+
// try to make communication with the native side.
336+
const result = await callWithRetry(() => {
337+
return messaging.getUserValues()
337338
})
338-
Comms.messaging?.onUserValuesChanged(value => {
339-
if ('enabled' in value.privatePlayerMode) {
339+
// if we received a connection, use the initial values
340+
if ('value' in result) {
341+
Comms.messaging = messaging
342+
if ('enabled' in result.value.privatePlayerMode) {
340343
Setting.setState(true)
341344
} else {
342345
Setting.setState(false)
343346
}
344-
})
347+
// eslint-disable-next-line promise/prefer-await-to-then
348+
Comms.messaging?.onUserValuesChanged(value => {
349+
if ('enabled' in value.privatePlayerMode) {
350+
Setting.setState(true)
351+
} else {
352+
Setting.setState(false)
353+
}
354+
})
355+
} else {
356+
console.error(result.error)
357+
}
345358
},
346359
/**
347360
* From the player page, all we can do is 'setUserValues' to {enabled: {}}
@@ -700,14 +713,18 @@ const MouseMove = {
700713
/**
701714
* Initializes all parts of the page on load.
702715
*/
703-
document.addEventListener('DOMContentLoaded', () => {
716+
document.addEventListener('DOMContentLoaded', async () => {
704717
Setting.init({
705718
settingsUrl: settingsUrl(import.meta.injectName)
706719
})
707-
Comms.init({
720+
await Comms.init({
708721
injectName: import.meta.injectName,
709722
env: import.meta.env
710723
})
724+
if (!Comms.messaging) {
725+
console.warn('cannot continue as messaging was not resolved')
726+
return
727+
}
711728
VideoPlayer.init()
712729
Tooltip.init()
713730
PlayOnYouTube.init({

packages/special-pages/pages/duckplayer/src/js/messages.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,40 @@ export function createDuckPlayerPageMessaging (opts) {
159159
}
160160
throw new Error('unreachable - platform not supported')
161161
}
162+
163+
/**
164+
* This will return either { value: awaited value },
165+
* { error: error message }
166+
*
167+
* It will execute the given function in uniform intervals
168+
* until either:
169+
* 1: the given function stops throwing errors
170+
* 2: the maxAttempts limit is reached
171+
*
172+
* This is useful for situations where you don't want to continue
173+
* until a result is found - normally to work around race-conditions
174+
*
175+
* @template {(...args: any[]) => any} FN
176+
* @param {FN} fn
177+
* @param {{maxAttempts?: number, intervalMs?: number}} params
178+
* @returns {Promise<{ value: Awaited<ReturnType<FN>>, attempt: number } | { error: string }>}
179+
*/
180+
export async function callWithRetry (fn, params = {}) {
181+
const { maxAttempts = 10, intervalMs = 300 } = params
182+
let attempt = 1
183+
184+
while (attempt <= maxAttempts) {
185+
try {
186+
return { value: await fn(), attempt }
187+
} catch (error) {
188+
if (attempt === maxAttempts) {
189+
return { error: `Max attempts reached: ${error}` }
190+
}
191+
192+
await new Promise((resolve) => setTimeout(resolve, intervalMs))
193+
attempt++
194+
}
195+
}
196+
197+
return { error: 'Unreachable: value not retrieved' }
198+
}

packages/special-pages/playwright.config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,20 @@ export default defineConfig({
1414
}
1515
],
1616
fullyParallel: !process.env.CI,
17+
/* Retry on CI only */
18+
retries: process.env.CI ? 2 : 0,
19+
/* Opt out of parallel tests on CI. */
20+
workers: process.env.CI ? 1 : undefined,
21+
reporter: process.env.CI ? 'github' : [['html', { open: 'never' }]],
1722
// @ts-expect-error - Type 'undefined' is not assignable to type 'string'. process.env
1823
webServer: {
1924
command: 'npm run serve',
2025
port: 3210,
2126
reuseExistingServer: true,
2227
env: process.env
28+
},
29+
use: {
30+
actionTimeout: 1000,
31+
trace: 'on-first-retry'
2332
}
2433
})

packages/special-pages/tests/duckplayer.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ test.describe('duckplayer toolbar', () => {
8282
})
8383

8484
test.describe('duckplayer settings', () => {
85-
test.skip('always open setting', async ({ page }, workerInfo) => {
85+
test('always open setting', async ({ page }, workerInfo) => {
8686
const duckplayer = DuckPlayerPage.create(page, workerInfo)
8787
// load as normal
8888
await duckplayer.openWithVideoID()
@@ -98,7 +98,7 @@ test.describe('duckplayer settings', () => {
9898
await duckplayer.toggleAlwaysOpenSetting()
9999
await duckplayer.sentUpdatedSettings()
100100
})
101-
test.skip('when a new value arrives via subscription', async ({ page }, workerInfo) => {
101+
test('when a new value arrives via subscription', async ({ page }, workerInfo) => {
102102
const duckplayer = DuckPlayerPage.create(page, workerInfo)
103103
// load as normal
104104
await duckplayer.openWithVideoID()

playwright.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export default defineConfig({
4141
retries: process.env.CI ? 2 : 0,
4242
/* Opt out of parallel tests on CI. */
4343
workers: process.env.CI ? 1 : undefined,
44+
reporter: process.env.CI ? 'github' : [['html', { open: 'never' }]],
4445
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
4546
webServer: {
4647
reuseExistingServer: true,

0 commit comments

Comments
 (0)