@@ -4,13 +4,19 @@ import { perPlatform } from '../type-helpers.mjs';
44import { ResultsCollector } from './results-collector.js' ;
55
66/**
7- * @import { PageType} from '../../src/features/duck-player- native.js'
7+ * @import { PageType } from '../../src/features/duckplayer- native/messages .js'
88 * @typedef {"default" | "incremental-dom" | "age-restricted-error" | "sign-in-error" } PlayerPageVariants
99 */
1010
1111// eslint-disable-next-line @typescript-eslint/no-unused-vars
1212const configFiles = /** @type {const } */ ( [ 'native.json' ] ) ;
1313
14+ const defaultInitialSetup = {
15+ locale : 'en' ,
16+ } ;
17+
18+ const featureName = 'duckPlayerNative' ;
19+
1420export class DuckPlayerNative {
1521 /** @type {Partial<Record<PageType, string>> } */
1622 pages = {
@@ -29,9 +35,7 @@ export class DuckPlayerNative {
2935 this . platform = platform ;
3036 this . collector = new ResultsCollector ( page , build , platform ) ;
3137 this . collector . withMockResponse ( {
32- initialSetup : {
33- locale : 'en' ,
34- } ,
38+ initialSetup : defaultInitialSetup ,
3539 onCurrentTimestamp : { } ,
3640 } ) ;
3741 this . collector . withUserPreferences ( {
@@ -79,7 +83,7 @@ export class DuckPlayerNative {
7983 * @param {string } [params.videoID]
8084 */
8185 async gotoPage ( pageType , params = { } ) {
82- await this . pageTypeIs ( pageType ) ;
86+ await this . withPageType ( pageType ) ;
8387
8488 const { variant = 'default' , videoID = '123' } = params ;
8589 const urlParams = new URLSearchParams ( [
@@ -107,14 +111,23 @@ export class DuckPlayerNative {
107111 * @param {PageType } pageType
108112 * @return {Promise<void> }
109113 */
110- async pageTypeIs ( pageType ) {
111- const initialSetupResponse = {
112- locale : 'en' ,
113- pageType,
114- } ;
114+ async withPageType ( pageType ) {
115+ const initialSetup = this . collector . mockResponses ?. initialSetup || defaultInitialSetup ;
115116
116117 await this . collector . updateMockResponse ( {
117- initialSetup : initialSetupResponse ,
118+ initialSetup : { pageType, ...initialSetup } ,
119+ } ) ;
120+ }
121+
122+ /**
123+ * @param {boolean } playbackPaused
124+ * @return {Promise<void> }
125+ */
126+ async withPlaybackPaused ( playbackPaused = true ) {
127+ const initialSetup = this . collector . mockResponses . initialSetup || defaultInitialSetup ;
128+
129+ await this . collector . updateMockResponse ( {
130+ initialSetup : { playbackPaused, ...initialSetup } ,
118131 } ) ;
119132 }
120133
@@ -123,7 +136,7 @@ export class DuckPlayerNative {
123136 * @param {Record<string, any> } payload
124137 */
125138 async simulateSubscriptionMessage ( name , payload ) {
126- await this . collector . simulateSubscriptionMessage ( 'duckPlayerNative' , name , payload ) ;
139+ await this . collector . simulateSubscriptionMessage ( featureName , name , payload ) ;
127140 }
128141
129142 /**
@@ -176,6 +189,13 @@ export class DuckPlayerNative {
176189 await this . simulateSubscriptionMessage ( 'onMuteAudio' , options ) ;
177190 }
178191
192+ /**
193+ * @param {PageType } pageType
194+ */
195+ async sendURLChanged ( pageType ) {
196+ await this . simulateSubscriptionMessage ( 'onUrlChanged' , { pageType } ) ;
197+ }
198+
179199 /* Messaging assertions */
180200
181201 async didSendInitialHandshake ( ) {
@@ -184,7 +204,7 @@ export class DuckPlayerNative {
184204 {
185205 payload : {
186206 context : this . collector . messagingContextName ,
187- featureName : 'duckPlayerNative' ,
207+ featureName,
188208 method : 'initialSetup' ,
189209 params : { } ,
190210 } ,
@@ -198,24 +218,46 @@ export class DuckPlayerNative {
198218 {
199219 payload : {
200220 context : this . collector . messagingContextName ,
201- featureName : 'duckPlayerNative' ,
221+ featureName,
202222 method : 'onCurrentTimestamp' ,
203- params : { timestamp : 0 } ,
223+ params : { timestamp : "0" } ,
204224 } ,
205225 } ,
206226 ] ) ;
207227 }
208228
209229 /* Thumbnail Overlay assertions */
210230
211- async didShowThumbnailOverlay ( ) {
231+ async didShowOverlay ( ) {
212232 await this . page . locator ( 'ddg-video-thumbnail-overlay-mobile' ) . waitFor ( { state : 'visible' , timeout : 1000 } ) ;
213233 }
214234
215235 async didShowLogoInOverlay ( ) {
216236 await this . page . locator ( 'ddg-video-thumbnail-overlay-mobile .logo' ) . waitFor ( { state : 'visible' , timeout : 1000 } ) ;
217237 }
218238
239+ async clickOnOverlay ( ) {
240+ await this . page . locator ( 'ddg-video-thumbnail-overlay-mobile' ) . click ( ) ;
241+ }
242+
243+ async didDismissOverlay ( ) {
244+ await this . page . locator ( 'ddg-video-thumbnail-overlay-mobile' ) . waitFor ( { state : 'hidden' , timeout : 1000 } ) ;
245+ }
246+
247+ async didSendOverlayDismissalMessage ( ) {
248+ const messages = await this . collector . waitForMessage ( 'didDismissOverlay' ) ;
249+ expect ( messages ) . toMatchObject ( [
250+ {
251+ payload : {
252+ context : this . collector . messagingContextName ,
253+ featureName,
254+ method : 'didDismissOverlay' ,
255+ params : { } ,
256+ } ,
257+ } ,
258+ ] ) ;
259+ }
260+
219261 /* Custom Error assertions */
220262
221263 async didShowGenericError ( ) {
@@ -233,6 +275,24 @@ export class DuckPlayerNative {
233275 - paragraph: If this doesn’t work, you can still watch this video on YouTube, but without the added privacy of Duck Player.
234276 ` ) ;
235277 }
278+
279+ /**
280+ * @param {number } numberOfCalls - Number of times the message should be received
281+ */
282+ async didSendDuckPlayerScriptsReady ( numberOfCalls = 1 ) {
283+ const expectedMessage = {
284+ payload : {
285+ context : this . collector . messagingContextName ,
286+ featureName,
287+ method : 'onDuckPlayerScriptsReady' ,
288+ params : { } ,
289+ } ,
290+ } ;
291+ const expectedMessages = Array ( numberOfCalls ) . fill ( expectedMessage ) ;
292+ const actualMessages = await this . collector . waitForMessage ( 'onDuckPlayerScriptsReady' ) ;
293+
294+ expect ( actualMessages ) . toMatchObject ( expectedMessages ) ;
295+ }
236296}
237297
238298/**
0 commit comments