@@ -20,11 +20,12 @@ import type {
2020 BrowsingContextInfo ,
2121 NetworkSameSite ,
2222} from 'webdriver/build/bidi/localTypes'
23- import type { CyCookie } from './webkit- automation'
23+ import type { CyCookie as CyBaseCookie } from '../ automation/util '
2424import { bidiGetUrl } from '../automation/commands/get_url'
2525import { bidiReloadFrame } from '../automation/commands/reload_frame'
2626import { bidiNavigateHistory } from '../automation/commands/navigate_history'
2727import { bidiGetFrameTitle } from '../automation/commands/get_frame_title'
28+ import type { StorageCookieFilter , StoragePartialCookie as BidiStoragePartialCookie } from 'webdriver/build/bidi/remoteTypes'
2829
2930const BIDI_DEBUG_NAMESPACE = 'cypress:server:browsers:bidi_automation'
3031const BIDI_COOKIE_DEBUG_NAMESPACE = `${ BIDI_DEBUG_NAMESPACE } :cookies`
@@ -34,6 +35,10 @@ const debug = debugModule(BIDI_DEBUG_NAMESPACE)
3435const debugCookies = debugModule ( BIDI_COOKIE_DEBUG_NAMESPACE )
3536const debugScreenshot = debugModule ( BIDI_SCREENSHOT_DEBUG_NAMESPACE )
3637
38+ type CyCookie = Omit < CyBaseCookie , 'sameSite' > & {
39+ sameSite : 'no_restriction' | 'lax' | 'strict' | 'unspecified'
40+ }
41+
3742// if the filter is not an exact match OR, if looselyMatchCookiePath is enabled, doesn't include the path.
3843// ex: /foo/bar/baz path should include cookies for /foo/bar/baz, /foo/bar, /foo, and /
3944// this is shipped in remoteTypes within webdriver but it isn't exported, so we need to redefine the type
@@ -48,7 +53,7 @@ interface StoragePartialCookie extends Record<string, unknown> {
4853 httpOnly : boolean
4954 hostOnly ?: boolean
5055 secure : boolean
51- sameSite : NetworkSameSite
56+ sameSite : NetworkSameSite | 'default'
5257 expiry ?: number
5358}
5459
@@ -98,22 +103,36 @@ const normalizeResourceType = (type: RequestInitiatorType): ResourceType => {
98103 }
99104}
100105
101- function convertSameSiteBiDiToExtension ( str : NetworkSameSite ) {
106+ function convertSameSiteBiDiToExtension ( str : NetworkSameSite | 'default' ) {
102107 if ( str === 'none' ) {
103108 return 'no_restriction'
104109 }
105110
111+ if ( str === 'default' ) {
112+ // put firefox version check here, under 140 we need to return 'no_restriction'
113+ return 'unspecified'
114+ }
115+
106116 return str
107117}
108118
109- function convertSameSiteExtensionToBiDi ( str : CyCookie [ 'sameSite' ] ) {
119+ function convertSameSiteExtensionToBiDi ( str : CyCookie [ 'sameSite' ] , majorFirefoxVersion ?: number ) {
110120 if ( str === 'no_restriction' ) {
111121 return 'none'
112122 }
113123
124+ if ( str === 'unspecified' ) {
125+ // put firefox version check here, under 140 we need to return 'no_restriction'
126+ return 'default'
127+ }
128+
129+ // @see https://www.w3.org/TR/webdriver-bidi/#type-network-Cookie
130+ // in Firefox 140, BiDi added the 'default' value to be able to assign 'unspecified', which was also added in Firefox 140.
131+ const defaultValue = majorFirefoxVersion && majorFirefoxVersion < 140 ? 'none' : 'default'
132+
114133 // if no value, default to 'none' as this is the browser default in firefox specifically.
115134 // Every other browser defaults to 'lax'
116- return str === undefined ? 'none' : str
135+ return str === undefined ? defaultValue : str
117136}
118137
119138// used to normalize cookies to CyCookie before returning them through the automation client
@@ -135,7 +154,7 @@ const convertBiDiCookieToCyCookie = (cookie: NetworkCookie): CyCookie => {
135154 return cyCookie
136155}
137156
138- const convertCyCookieToBiDiCookie = ( cookie : CyCookie ) : StoragePartialCookie => {
157+ const convertCyCookieToBiDiCookie = ( cookie : CyCookie , majorFirefoxVersion ?: number ) : StoragePartialCookie => {
139158 const cookieToSet : StoragePartialCookie = {
140159 name : cookie . name ,
141160 value : {
@@ -146,7 +165,7 @@ const convertCyCookieToBiDiCookie = (cookie: CyCookie): StoragePartialCookie =>
146165 path : cookie . path ,
147166 httpOnly : cookie . httpOnly ,
148167 secure : cookie . secure ,
149- sameSite : convertSameSiteExtensionToBiDi ( cookie . sameSite ) ,
168+ sameSite : convertSameSiteExtensionToBiDi ( cookie . sameSite , majorFirefoxVersion ) ,
150169 // BiDi cookie expiry is in seconds from EPOCH, but sometimes the automation client feeds in a float and BiDi does not know how to handle it.
151170 // If trying to set a float on the expiry time in BiDi, the setting silently fails.
152171 expiry : ( cookie . expirationDate === - Infinity ? 0 : ( isNumber ( cookie . expirationDate ) ? toInteger ( cookie . expirationDate ) : null ) ) ?? undefined ,
@@ -165,7 +184,7 @@ const convertCyCookieToBiDiCookie = (cookie: CyCookie): StoragePartialCookie =>
165184 return cookieToSet
166185}
167186
168- const buildBiDiClearCookieFilterFromCyCookie = ( cookie : CyCookie ) : StoragePartialCookie => {
187+ const buildBiDiClearCookieFilterFromCyCookie = ( cookie : CyCookie , majorFirefoxVersion ?: number ) : StoragePartialCookie => {
169188 const cookieToClearFilter : StoragePartialCookie = {
170189 name : cookie . name ,
171190 value : {
@@ -176,7 +195,7 @@ const buildBiDiClearCookieFilterFromCyCookie = (cookie: CyCookie): StoragePartia
176195 path : cookie . path ,
177196 httpOnly : cookie . httpOnly ,
178197 secure : cookie . secure ,
179- sameSite : convertSameSiteExtensionToBiDi ( cookie . sameSite ) ,
198+ sameSite : convertSameSiteExtensionToBiDi ( cookie . sameSite , majorFirefoxVersion ) ,
180199 }
181200
182201 if ( ! cookie . hostOnly && isHostOnlyCookie ( cookie ) ) {
@@ -208,11 +227,13 @@ export class BidiAutomation {
208227 // set in firefox-utils when creating the webdriver session initially and in the 'reset:browser:tabs:for:next:spec' automation hook for subsequent tests when the top level context is recreated
209228 private topLevelContextId : string | undefined = undefined
210229 private interceptId : string | undefined = undefined
230+ private majorFirefoxVersion : number | undefined
211231
212232 private constructor ( webDriverClient : WebDriverClient , automation : Automation ) {
213233 debug ( 'initializing bidi automation' )
214234 this . automation = automation
215235 this . webDriverClient = webDriverClient
236+ this . majorFirefoxVersion = parseInt ( webDriverClient ?. capabilities ?. browserVersion || '' ) || undefined
216237 // bind Bidi Events to update the standard automation client
217238 // Error here is expected until webdriver adds initiatorType and destination to the request object
218239 // @ts -expect-error
@@ -464,7 +485,7 @@ export class BidiAutomation {
464485 // because of the above comment on the BiDi API, we get ALL cookies not filtering by domain
465486 // (name filter is safe to reduce the payload coming back)
466487 // and filter out all cookies that apply to the given domain, path, and name (which should already be done)
467- const filteredCookies = normalizedCookies . filter ( ( cookie ) => cookieMatches ( cookie , filter ) )
488+ const filteredCookies = normalizedCookies . filter ( ( cookie ) => cookieMatches ( cookie as CyBaseCookie , filter ) )
468489
469490 debugCookies ( `filtered additional cookies based on domain, path, or name: %o` , filteredCookies )
470491
@@ -495,7 +516,7 @@ export class BidiAutomation {
495516
496517 // if it does, convert it to a BiDi cookie filter and delete the cookie
497518 await this . webDriverClient . storageDeleteCookies ( {
498- filter : buildBiDiClearCookieFilterFromCyCookie ( cookieToBeCleared ) ,
519+ filter : buildBiDiClearCookieFilterFromCyCookie ( cookieToBeCleared , this . majorFirefoxVersion ) as StorageCookieFilter ,
499520 } )
500521
501522 return cookieToBeCleared
@@ -537,7 +558,7 @@ export class BidiAutomation {
537558 {
538559 debugCookies ( `set:cookie %o` , data )
539560 await this . webDriverClient . storageSetCookie ( {
540- cookie : convertCyCookieToBiDiCookie ( data ) ,
561+ cookie : convertCyCookieToBiDiCookie ( data , this . majorFirefoxVersion ) as BidiStoragePartialCookie ,
541562 } )
542563
543564 const cookies = await this . getAllCookiesMatchingFilter ( data )
@@ -549,7 +570,7 @@ export class BidiAutomation {
549570 debugCookies ( `add:cookies %o` , data )
550571 await Promise . all ( data . map ( ( cookie ) => {
551572 return this . webDriverClient . storageSetCookie ( {
552- cookie : convertCyCookieToBiDiCookie ( cookie ) ,
573+ cookie : convertCyCookieToBiDiCookie ( cookie , this . majorFirefoxVersion ) as BidiStoragePartialCookie ,
553574 } )
554575 } ) )
555576
@@ -562,7 +583,7 @@ export class BidiAutomation {
562583
563584 await Promise . all ( data . map ( ( cookie ) => {
564585 return this . webDriverClient . storageSetCookie ( {
565- cookie : convertCyCookieToBiDiCookie ( cookie ) ,
586+ cookie : convertCyCookieToBiDiCookie ( cookie , this . majorFirefoxVersion ) as BidiStoragePartialCookie ,
566587 } )
567588 } ) )
568589
0 commit comments