@@ -78,71 +78,77 @@ export default async function globalSetup() {
7878 if ( debug ) process . stdout . write ( data )
7979 } )
8080
81- await waitForText ( ( ) => output , 'Open this link to start the auth process' , CLI_TIMEOUT . short )
82-
83- const stripped = stripAnsi ( output )
84- const urlMatch = stripped . match ( / h t t p s : \/ \/ a c c o u n t s \. s h o p i f y \. c o m \S + / )
85- if ( ! urlMatch ) {
86- throw new Error ( `[e2e] global-auth: could not find login URL in output:\n${ stripped } ` )
87- }
88-
89- // Complete login in a headless browser
90- const browser = await chromium . launch ( { headless : ! process . env . E2E_HEADED } )
91- const context = await browser . newContext ( {
92- extraHTTPHeaders : {
93- 'X-Shopify-Loadtest-Bf8d22e7-120e-4b5b-906c-39ca9d5499a9' : 'true' ,
94- } ,
95- } )
96- const page = await context . newPage ( )
97-
98- await completeLogin ( page , urlMatch [ 0 ] , email , password )
81+ const storageStatePath = path . join ( tmpBase , 'browser-storage-state.json' )
9982
100- await waitForText ( ( ) => output , 'Logged in' , BROWSER_TIMEOUT . max )
10183 try {
102- ptyProcess . kill ( )
103- // eslint-disable-next-line no-catch-all/no-catch-all
104- } catch ( _error ) {
105- // Process may already be dead
106- }
84+ await waitForText ( ( ) => output , 'Open this link to start the auth process' , CLI_TIMEOUT . short )
10785
108- // Visit admin.shopify.com and dev.shopify.com to establish session cookies
109- // (completeLogin only authenticates on accounts.shopify.com)
110- const orgId = ( process . env . E2E_ORG_ID ?? '' ) . trim ( )
111- if ( orgId ) {
112- // Establish admin.shopify.com cookies
113- await page . goto ( 'https://admin.shopify.com/' , { waitUntil : 'domcontentloaded' } )
114- await page . waitForTimeout ( BROWSER_TIMEOUT . medium )
115-
116- // Handle account picker if shown
117- if ( isAccountsShopifyUrl ( page . url ( ) ) ) {
118- const accountButton = page . locator ( `text=${ email } ` ) . first ( )
119- if ( await accountButton . isVisible ( { timeout : BROWSER_TIMEOUT . long } ) . catch ( ( ) => false ) ) {
120- await accountButton . click ( )
121- await page . waitForTimeout ( BROWSER_TIMEOUT . medium )
122- }
86+ const stripped = stripAnsi ( output )
87+ const urlMatch = stripped . match ( / h t t p s : \/ \/ a c c o u n t s \. s h o p i f y \. c o m \S + / )
88+ if ( ! urlMatch ) {
89+ throw new Error ( `[e2e] global-auth: could not find login URL in output:\n${ stripped } ` )
12390 }
12491
125- // Establish dev.shopify.com cookies
126- await page . goto ( `https://dev.shopify.com/dashboard/${ orgId } /apps` , { waitUntil : 'domcontentloaded' } )
127- await page . waitForTimeout ( BROWSER_TIMEOUT . medium )
92+ // Complete login in a headless browser
93+ const browser = await chromium . launch ( { headless : ! process . env . E2E_HEADED } )
94+ try {
95+ const context = await browser . newContext ( {
96+ extraHTTPHeaders : {
97+ 'X-Shopify-Loadtest-Bf8d22e7-120e-4b5b-906c-39ca9d5499a9' : 'true' ,
98+ } ,
99+ } )
100+ const page = await context . newPage ( )
101+
102+ await completeLogin ( page , urlMatch [ 0 ] , email , password )
103+
104+ await waitForText ( ( ) => output , 'Logged in' , BROWSER_TIMEOUT . max )
105+
106+ // Visit admin.shopify.com and dev.shopify.com to establish session cookies
107+ // (completeLogin only authenticates on accounts.shopify.com)
108+ const orgId = ( process . env . E2E_ORG_ID ?? '' ) . trim ( )
109+ if ( orgId ) {
110+ // Establish admin.shopify.com cookies
111+ await page . goto ( 'https://admin.shopify.com/' , { waitUntil : 'domcontentloaded' } )
112+ await page . waitForTimeout ( BROWSER_TIMEOUT . medium )
128113
129- if ( isAccountsShopifyUrl ( page . url ( ) ) ) {
130- const accountButton = page . locator ( `text=${ email } ` ) . first ( )
131- if ( await accountButton . isVisible ( { timeout : BROWSER_TIMEOUT . long } ) . catch ( ( ) => false ) ) {
132- await accountButton . click ( )
114+ // Handle account picker if shown
115+ if ( isAccountsShopifyUrl ( page . url ( ) ) ) {
116+ const accountButton = page . locator ( `text=${ email } ` ) . first ( )
117+ if ( await accountButton . isVisible ( { timeout : BROWSER_TIMEOUT . long } ) . catch ( ( ) => false ) ) {
118+ await accountButton . click ( )
119+ await page . waitForTimeout ( BROWSER_TIMEOUT . medium )
120+ }
121+ }
122+
123+ // Establish dev.shopify.com cookies
124+ await page . goto ( `https://dev.shopify.com/dashboard/${ orgId } /apps` , { waitUntil : 'domcontentloaded' } )
133125 await page . waitForTimeout ( BROWSER_TIMEOUT . medium )
126+
127+ if ( isAccountsShopifyUrl ( page . url ( ) ) ) {
128+ const accountButton = page . locator ( `text=${ email } ` ) . first ( )
129+ if ( await accountButton . isVisible ( { timeout : BROWSER_TIMEOUT . long } ) . catch ( ( ) => false ) ) {
130+ await accountButton . click ( )
131+ await page . waitForTimeout ( BROWSER_TIMEOUT . medium )
132+ }
133+ }
134+
135+ globalLog ( 'auth' , 'browser sessions established for admin + dev dashboard' )
134136 }
135- }
136137
137- globalLog ( 'auth' , 'browser sessions established for admin + dev dashboard' )
138+ // Save browser cookies/storage so workers can reuse the session
139+ await context . storageState ( { path : storageStatePath } )
140+ } finally {
141+ await browser . close ( )
142+ }
143+ } finally {
144+ try {
145+ ptyProcess . kill ( )
146+ // eslint-disable-next-line no-catch-all/no-catch-all
147+ } catch ( _error ) {
148+ // Process may already be dead
149+ }
138150 }
139151
140- // Save browser cookies/storage so workers can reuse the session
141- // Now includes cookies for both accounts.shopify.com AND admin.shopify.com
142- const storageStatePath = path . join ( tmpBase , 'browser-storage-state.json' )
143- await context . storageState ( { path : storageStatePath } )
144- await browser . close ( )
145-
146152 // Store paths so workers can copy CLI auth + load browser state
147153 /* eslint-disable require-atomic-updates */
148154 process . env . E2E_AUTH_CONFIG_DIR = xdgEnv . XDG_CONFIG_HOME
0 commit comments