Skip to content

Commit 9fc4b79

Browse files
authored
Duck Player Native feature (#1604)
1 parent 7f3ddc3 commit 9fc4b79

38 files changed

+2394
-147
lines changed

injected/entry-points/integration.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function generateConfig() {
4747
'webCompat',
4848
'apiManipulation',
4949
'duckPlayer',
50+
'duckPlayerNative',
5051
],
5152
},
5253
};
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { test } from '@playwright/test';
2+
import { DuckPlayerNative } from './page-objects/duckplayer-native.js';
3+
4+
test.describe('Duck Player Native messaging', () => {
5+
test('Calls initial setup', async ({ page }, workerInfo) => {
6+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
7+
8+
// Given the duckPlayerNative feature is enabled
9+
await duckPlayer.withRemoteConfig();
10+
11+
// When I go to a YouTube page
12+
await duckPlayer.gotoYouTubePage();
13+
14+
// Then Initial Setup should be called
15+
await duckPlayer.didSendInitialHandshake();
16+
17+
// And an onDuckPlayerScriptsReady event should be called
18+
await duckPlayer.didSendDuckPlayerScriptsReady();
19+
});
20+
21+
test('Responds to onUrlChanged', async ({ page }, workerInfo) => {
22+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
23+
24+
// Given the duckPlayerNative feature is enabled
25+
await duckPlayer.withRemoteConfig();
26+
27+
// When I go to a YouTube page
28+
await duckPlayer.gotoYouTubePage();
29+
30+
// And the frontend receives an onUrlChanged event
31+
await duckPlayer.sendURLChanged('NOCOOKIE');
32+
33+
// Then an onDuckPlayerScriptsReady event should be fired twice
34+
await duckPlayer.didSendDuckPlayerScriptsReady(2);
35+
});
36+
37+
test('Polls timestamp on YouTube', async ({ page }, workerInfo) => {
38+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
39+
40+
// Given the duckPlayerNative feature is enabled
41+
await duckPlayer.withRemoteConfig();
42+
43+
// When I go to a YouTube page
44+
await duckPlayer.gotoYouTubePage();
45+
46+
// Then the current timestamp should be polled back to the browser
47+
await duckPlayer.didSendCurrentTimestamp();
48+
});
49+
50+
test('Polls timestamp on NoCookie page', async ({ page }, workerInfo) => {
51+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
52+
53+
// Given the duckPlayerNative feature is enabled
54+
await duckPlayer.withRemoteConfig();
55+
56+
// When I go to a NoCookie page
57+
await duckPlayer.gotoNoCookiePage();
58+
59+
// Then the current timestamp should be polled back to the browser
60+
await duckPlayer.didSendCurrentTimestamp();
61+
});
62+
});
63+
64+
test.describe('Duck Player Native thumbnail overlay', () => {
65+
test('Shows overlay on YouTube player page', async ({ page }, workerInfo) => {
66+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
67+
68+
// Given the duckPlayerNative feature is enabled
69+
await duckPlayer.withRemoteConfig();
70+
71+
// When I go to a YouTube page
72+
await duckPlayer.gotoYouTubePage();
73+
await duckPlayer.sendOnMediaControl();
74+
75+
// Then I should see the thumbnail overlay in the page
76+
await duckPlayer.didShowOverlay();
77+
await duckPlayer.didShowLogoInOverlay();
78+
});
79+
test('Dismisses overlay on click', async ({ page }, workerInfo) => {
80+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
81+
82+
// Given the duckPlayerNative feature is enabled
83+
await duckPlayer.withRemoteConfig();
84+
85+
// When I go to a YouTube page
86+
await duckPlayer.gotoYouTubePage();
87+
await duckPlayer.sendOnMediaControl();
88+
89+
// And I see the thumbnail overlay in the page
90+
await duckPlayer.didShowOverlay();
91+
92+
// And I click on the overlay
93+
await duckPlayer.clickOnOverlay();
94+
95+
// Then the overlay should be dismissed
96+
await duckPlayer.didDismissOverlay();
97+
98+
// And a didDismissOverlay event should be fired
99+
await duckPlayer.didSendOverlayDismissalMessage();
100+
});
101+
});
102+
103+
test.describe('Duck Player Native custom error view', () => {
104+
test('Shows age-restricted error', async ({ page }, workerInfo) => {
105+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
106+
107+
// Given the duckPlayerNative feature is enabled
108+
await duckPlayer.withRemoteConfig();
109+
110+
// When I go to a YouTube page with an age-restricted error
111+
await duckPlayer.gotoAgeRestrictedErrorPage();
112+
113+
// Then I should see the generic error screen
114+
await duckPlayer.didShowGenericError();
115+
});
116+
117+
test('Shows sign-in error', async ({ page }, workerInfo) => {
118+
const duckPlayer = DuckPlayerNative.create(page, workerInfo);
119+
120+
// Given the duckPlayerNative feature is enabled
121+
await duckPlayer.withRemoteConfig();
122+
123+
// When I go to a YouTube page with an age-restricted error
124+
await duckPlayer.gotoSignInErrorPage();
125+
126+
// Then I should see the generic error screen
127+
await duckPlayer.didShowSignInError();
128+
});
129+
});

0 commit comments

Comments
 (0)