Skip to content

QA to E2E: app basic flow (no extensions)#7047

Open
phyllis-sy-wu wants to merge 3 commits intomainfrom
psyw-0318-QAtoE2E-basic-flow
Open

QA to E2E: app basic flow (no extensions)#7047
phyllis-sy-wu wants to merge 3 commits intomainfrom
psyw-0318-QAtoE2E-basic-flow

Conversation

@phyllis-sy-wu
Copy link
Contributor

@phyllis-sy-wu phyllis-sy-wu commented Mar 19, 2026

WHY are these changes introduced?

To replace manual CLI QA with automated end-to-end tests that validate the complete app development workflow in a real environment.

This is part of Vault project #gsd:49408 to automate CLI QA coverage.

WHAT is this pull request doing?

Adds tests/app-basic.spec.ts: a full lifecycle e2e test covering 9 steps:

Step Command Description
1 app init React Router, JS, npm
2 app dev Waits for "Ready" with keyboard shortcuts enabled (CI='')
3 app execute Runs a GraphQL query against the live dev server
4 q key Sends q keystroke to terminate the dev server
5 app dev clean Tears down the dev preview
6 app deploy Deploys with a unique version tag
7 app versions list --json Asserts the version tag appears
8 app config link --client-id <secondary> Pre-creates a minimal shopify.app.secondary.toml stub (client_id = "...") before spawning, so getTomls() finds the secondary client ID and loadConfigurationFileName returns the filename immediately without triggering the interactive "Configuration file name:" prompt
9 app deploy --config secondary Deploys to the secondary app using the linked config file, with SHOPIFY_FLAG_CLIENT_ID unset to avoid the --config/--client-id mutual exclusion enforced by oclif

Supporting changes:

  • setup/cli.ts: adds extendEnv: false to exec and execCreateApp so the test's explicit processEnv is the complete environment — no leakage from the parent shell
  • setup/auth.ts: logs "Authenticating automatically" for both the browser OAuth path and the partners-token path (was missing from the token path)
  • package.json: adds @shopify/cli-kit: 3.92.0 as a devDependency (required for the joinPath import, pinned to match all other packages per the repo-health version sync check)

Divergence from the manual flow

In the manual flow:

  1. app init creates a new app (you pick org, name a new app)
  2. app dev links to that new app
  3. app deploy deploys to that new app
  4. At the end you clean up the app from the Partners dashboard

In the e2e test:

  1. app init scaffolds the local directory but links to a pre-existing app via SHOPIFY_FLAG_CLIENT_ID
  2. Everything else runs against that pre-existing app

Why the test does it this way:

  • Creating a new Partners app in CI requires interactive prompts (pick org, name the app) that are hard to automate reliably
  • Using a pre-existing app with a known client_id skips all that interactivity
  • No cleanup needed — no risk of leaving orphaned apps on the platform

The tradeoff:

  • The test doesn't cover the "create new app" path of app init
  • It does cover everything else faithfully (dev, execute, deploy, versions, config link, secondary deploy)

How to test your changes?

Running the test

Requires .env with SHOPIFY_FLAG_CLIENT_ID, E2E_STORE_FQDN, E2E_SECONDARY_CLIENT_ID

DEBUG=1 pnpm --filter e2e exec playwright test app-basic

Verifying each step catches failures

  1. Break — edit source, then pnpm nx build app --skip-nx-cache && nx build cli --skip-nx-cache
  2. Run test — confirm it fails with ‼️ Step N - <command> failed
  3. Fix — revert source, then pnpm nx build app --skip-nx-cache && nx build cli --skip-nx-cache
  4. Run test — confirm it passes again
Step Command Source
1 app init init.ts
2 app dev dev.ts
3 app execute execute.ts
4 q key DevSessionUI
5 app dev clean dev-clean.ts
6 shopify app deploy --version v1 deploy.ts, version-name.ts
7 app versions list --json versions-list.ts
8 app config link --client-id <secondary> link.ts
9 app deploy --config secondary deploy.ts

Measuring impact

  • n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes

@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2026

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 82.22% 14928/18157
🟡 Branches 74.65% 7393/9904
🟢 Functions 81.36% 3767/4630
🟢 Lines 82.61% 14115/17086

Test suite run success

3910 tests passing in 1502 suites.

Report generated by 🧪jest coverage report action from f3e68db

@phyllis-sy-wu phyllis-sy-wu added the #gsd:49408 Agentic app validation label Mar 19, 2026
Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@phyllis-sy-wu phyllis-sy-wu force-pushed the psyw-0318-QAtoE2E-basic-flow branch from 09c1991 to 04d93f8 Compare March 19, 2026 17:56
@phyllis-sy-wu phyllis-sy-wu force-pushed the psyw-0318-QAtoE2E-basic-flow branch from 04d93f8 to 11a9ece Compare March 19, 2026 18:28
@phyllis-sy-wu phyllis-sy-wu force-pushed the psyw-0318-QAtoE2E-basic-flow branch from b215880 to f3e68db Compare March 20, 2026 01:27
@phyllis-sy-wu phyllis-sy-wu marked this pull request as ready for review March 20, 2026 13:19
@phyllis-sy-wu phyllis-sy-wu requested a review from a team as a code owner March 20, 2026 13:19
Copilot AI review requested due to automatic review settings March 20, 2026 13:19
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Playwright end-to-end test in packages/e2e to automate the “basic app lifecycle” QA flow (init → dev → execute → quit → dev clean → deploy → versions → config link → deploy via secondary config), plus supporting fixture and dependency updates to make the flow reliable in CI.

Changes:

  • Introduces app-basic.spec.ts to cover the full app workflow including secondary config link + deploy.
  • Updates the e2e CLI fixture to avoid inheriting the parent shell environment (extendEnv: false).
  • Adds a @shopify/cli-kit devDependency to packages/e2e to support joinPath usage.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pnpm-lock.yaml Lockfile updates for the new @shopify/cli-kit devDependency and resulting dependency graph changes.
packages/e2e/tests/app-basic.spec.ts New end-to-end “basic flow” test including config link + secondary deploy.
packages/e2e/setup/cli.ts Adjusts execa options to prevent env leakage by disabling env extension.
packages/e2e/setup/auth.ts Adds a console log indicating automatic authentication.
packages/e2e/setup/app.ts Avoids parsing scaffold output when create-app exits non-zero (returns early).
packages/e2e/package.json Adds @shopify/cli-kit devDependency needed by the new test.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 52 to 58
const execaOpts: ExecaOptions = {
cwd: opts.cwd,
env: {...env.processEnv, ...opts.env},
extendEnv: false,
timeout,
reject: false,
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLIProcess.exec/execCreateApp pass {...env.processEnv, ...opts.env} directly to execa. If a test sets an env key to undefined (used in this PR to “unset” SHOPIFY_FLAG_CLIENT_ID), Node will coerce it to the string 'undefined', so the variable remains effectively set and can break flag/env resolution. Filter out undefined values (similar to spawn()), or explicitly delete keys with undefined before calling execa.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
import {appScaffoldFixture as test} from '../setup/app.js'
import {requireEnv} from '../setup/env.js'
import {expect} from '@playwright/test'
import {joinPath} from '@shopify/cli-kit/node/path'
import * as fs from 'fs'

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test imports Node built-ins (fs) but doesn’t include the /* eslint-disable no-restricted-imports */ header that other e2e tests/fixtures use when importing fs/path. Since packages/e2e’s lint target includes tests/**/*.ts, this is likely to fail lint; add the disable (or switch to the preferred abstractions per the restricted-import rule).

Copilot uses AI. Check for mistakes.
'--message',
'E2E secondary app deployment',
],
{timeout: 5 * 60 * 1000, env: {SHOPIFY_FLAG_CLIENT_ID: undefined}},
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing env: {SHOPIFY_FLAG_CLIENT_ID: undefined} to cli.exec(...) won’t actually unset the variable with the current CLIProcess.exec implementation; it will be forwarded to the child process and can become the string 'undefined'. Prefer omitting the key entirely, or update CLIProcess.exec to drop undefined env entries (as spawn() already does).

Suggested change
{timeout: 5 * 60 * 1000, env: {SHOPIFY_FLAG_CLIENT_ID: undefined}},
{timeout: 5 * 60 * 1000},

Copilot uses AI. Check for mistakes.
Comment on lines 19 to +25
if (!email || !password) {
await use()
return
}

process.stdout.write('[e2e] Authenticating automatically — no action required.\n')

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the "Authenticating automatically" log should appear for both OAuth and partners-token auth paths, but this message is only printed when E2E_ACCOUNT_EMAIL/E2E_ACCOUNT_PASSWORD are set. If the partners-token path is intended to log too, move/add the log before the early return or condition it on env.partnersToken.

Copilot uses AI. Check for mistakes.
},
"devDependencies": {
"@playwright/test": "^1.50.0",
"@shopify/cli-kit": "3.92.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to include cli-kit in e2e. e2e should test the public exposed behavior via the cli binary itself, it shouldn't need to be aware of any cli internals.

import {appScaffoldFixture as test} from '../setup/app.js'
import {requireEnv} from '../setup/env.js'
import {expect} from '@playwright/test'
import {joinPath} from '@shopify/cli-kit/node/path'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just use node directly in e2e

{timeout: 60 * 1000},
)
const executeOutput = executeResult.stdout + executeResult.stderr
expect(executeResult.exitCode, '‼️ Step 3 - app execute failed').toBe(0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a little unclear -- we expect exit code to be 0, but the text is asserting the operation failed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

#gsd:49408 Agentic app validation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants