@@ -6,12 +6,6 @@ import * as fs from 'fs'
66import type { CLIContext , CLIProcess , ExecResult } from './cli.js'
77import type { BrowserContext } from './browser.js'
88
9- // Env override applied to all CLI helpers — strips CLIENT_ID so commands use the app's own toml.
10- // NOTE: Do NOT add SHOPIFY_CLI_PARTNERS_TOKEN here. The partners token overrides OAuth in the
11- // CLI's auth priority, and the App Management API token it exchanges to lacks permissions to
12- // create apps (403). OAuth provides the full set of required permissions.
13- const FRESH_APP_ENV = { SHOPIFY_FLAG_CLIENT_ID : undefined }
14-
159// ---------------------------------------------------------------------------
1610// CLI helpers — thin wrappers around cli.exec()
1711// ---------------------------------------------------------------------------
@@ -45,8 +39,8 @@ export async function createApp(ctx: {
4539 if ( ctx . flavor ) args . push ( '--flavor' , ctx . flavor )
4640
4741 const result = await cli . execCreateApp ( args , {
48- // Strip CLIENT_ID so the CLI creates a new app instead of linking to a pre-existing one
49- env : { FORCE_COLOR : '0' , ... FRESH_APP_ENV } ,
42+ // Disable color output and strip CLIENT_ID to prevent leaking from parent process.env
43+ env : { FORCE_COLOR : '0' , SHOPIFY_FLAG_CLIENT_ID : undefined } ,
5044 timeout : 5 * 60 * 1000 ,
5145 } )
5246
@@ -81,6 +75,33 @@ export async function createApp(ctx: {
8175 return { ...result , appDir}
8276}
8377
78+ // ---------------------------------------------------------------------------
79+ // Fixture helpers — TOML manipulation for test setup
80+ // ---------------------------------------------------------------------------
81+
82+ /**
83+ * Read the client_id from a shopify.app.toml file.
84+ */
85+ export function extractClientId ( appDir : string ) : string {
86+ const toml = fs . readFileSync ( path . join ( appDir , 'shopify.app.toml' ) , 'utf8' )
87+ const match = toml . match ( / c l i e n t _ i d \s * = \s * " ( [ ^ " ] + ) " / )
88+ if ( ! match ?. [ 1 ] ) {
89+ throw new Error ( `Could not find client_id in ${ path . join ( appDir , 'shopify.app.toml' ) } ` )
90+ }
91+ return match [ 1 ]
92+ }
93+
94+ /**
95+ * Overwrite a created app's shopify.app.toml with a fixture TOML template.
96+ * The template should contain `__CLIENT_ID__` and `__NAME__` placeholders which get
97+ * replaced with the app's real client_id and the provided name.
98+ */
99+ export function injectFixtureToml ( appDir : string , fixtureTomlContent : string , name : string ) : void {
100+ const clientId = extractClientId ( appDir )
101+ const toml = fixtureTomlContent . replace ( / _ _ C L I E N T _ I D _ _ / g, clientId ) . replace ( / _ _ N A M E _ _ / g, name )
102+ fs . writeFileSync ( path . join ( appDir , 'shopify.app.toml' ) , toml )
103+ }
104+
84105export async function generateExtension (
85106 ctx : CLIContext & {
86107 name : string
@@ -90,11 +111,11 @@ export async function generateExtension(
90111) : Promise < ExecResult > {
91112 const args = [ 'app' , 'generate' , 'extension' , '--name' , ctx . name , '--path' , ctx . appDir , '--template' , ctx . template ]
92113 if ( ctx . flavor ) args . push ( '--flavor' , ctx . flavor )
93- return ctx . cli . exec ( args , { env : FRESH_APP_ENV , timeout : 5 * 60 * 1000 } )
114+ return ctx . cli . exec ( args , { timeout : 5 * 60 * 1000 } )
94115}
95116
96117export async function buildApp ( ctx : CLIContext ) : Promise < ExecResult > {
97- return ctx . cli . exec ( [ 'app' , 'build' , '--path' , ctx . appDir ] , { env : FRESH_APP_ENV , timeout : 5 * 60 * 1000 } )
118+ return ctx . cli . exec ( [ 'app' , 'build' , '--path' , ctx . appDir ] , { timeout : 5 * 60 * 1000 } )
98119}
99120
100121export async function deployApp (
@@ -112,7 +133,7 @@ export async function deployApp(
112133 if ( ctx . version ) args . push ( '--version' , ctx . version )
113134 if ( ctx . message ) args . push ( '--message' , ctx . message )
114135 if ( ctx . config ) args . push ( '--config' , ctx . config )
115- return ctx . cli . exec ( args , { env : FRESH_APP_ENV , timeout : 5 * 60 * 1000 } )
136+ return ctx . cli . exec ( args , { timeout : 5 * 60 * 1000 } )
116137}
117138
118139export async function appInfo ( ctx : CLIContext ) : Promise < {
@@ -124,15 +145,15 @@ export async function appInfo(ctx: CLIContext): Promise<{
124145 entrySourceFilePath : string
125146 } [ ]
126147} > {
127- const result = await ctx . cli . exec ( [ 'app' , 'info' , '--path' , ctx . appDir , '--json' ] , { env : FRESH_APP_ENV } )
148+ const result = await ctx . cli . exec ( [ 'app' , 'info' , '--path' , ctx . appDir , '--json' ] )
128149 if ( result . exitCode !== 0 ) {
129150 throw new Error ( `app info failed (exit ${ result . exitCode } ):\nstdout: ${ result . stdout } \nstderr: ${ result . stderr } ` )
130151 }
131152 return JSON . parse ( result . stdout )
132153}
133154
134155export async function functionBuild ( ctx : CLIContext ) : Promise < ExecResult > {
135- return ctx . cli . exec ( [ 'app' , 'function' , 'build' , '--path' , ctx . appDir ] , { env : FRESH_APP_ENV , timeout : 3 * 60 * 1000 } )
156+ return ctx . cli . exec ( [ 'app' , 'function' , 'build' , '--path' , ctx . appDir ] , { timeout : 3 * 60 * 1000 } )
136157}
137158
138159export async function functionRun (
@@ -141,14 +162,12 @@ export async function functionRun(
141162 } ,
142163) : Promise < ExecResult > {
143164 return ctx . cli . exec ( [ 'app' , 'function' , 'run' , '--path' , ctx . appDir , '--input' , ctx . inputPath ] , {
144- env : FRESH_APP_ENV ,
145165 timeout : 60 * 1000 ,
146166 } )
147167}
148168
149169export async function versionsList ( ctx : CLIContext ) : Promise < ExecResult > {
150170 return ctx . cli . exec ( [ 'app' , 'versions' , 'list' , '--path' , ctx . appDir , '--json' ] , {
151- env : FRESH_APP_ENV ,
152171 timeout : 60 * 1000 ,
153172 } )
154173}
@@ -159,7 +178,6 @@ export async function configLink(
159178 } ,
160179) : Promise < ExecResult > {
161180 return ctx . cli . exec ( [ 'app' , 'config' , 'link' , '--path' , ctx . appDir , '--client-id' , ctx . clientId ] , {
162- env : FRESH_APP_ENV ,
163181 timeout : 2 * 60 * 1000 ,
164182 } )
165183}
@@ -374,13 +392,9 @@ export async function cleanupApp(
374392// ---------------------------------------------------------------------------
375393
376394export const appTestFixture = authFixture . extend < { authReady : void } > ( {
377- // Auto-trigger authLogin and strip CLIENT_ID so tests create their own apps
395+ // Auto-trigger authLogin so the OAuth session is available for all app tests
378396 authReady : [
379- async (
380- { authLogin : _authLogin , env} : { authLogin : void ; env : import ( './env.js' ) . E2EEnv } ,
381- use : ( ) => Promise < void > ,
382- ) => {
383- delete env . processEnv . SHOPIFY_FLAG_CLIENT_ID
397+ async ( { authLogin : _authLogin } : { authLogin : void } , use : ( ) => Promise < void > ) => {
384398 await use ( )
385399 } ,
386400 { auto : true } ,
0 commit comments