Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
strategy:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit, dashboard-chromium]
browser: [chromium, firefox, webkit]

# Shared env required by the SDK E2E helpers. Configure these in the repo → Settings → Secrets / Variables
env:
Expand Down Expand Up @@ -113,7 +113,7 @@ jobs:
- name: 🚀 Start preview server
run: |
cd apps/kitchensink-react
pnpm build --mode e2e && pnpm run preview --mode e2e --port 3333 &
pnpm build && pnpm run preview --port 3333 &
timeout 60 bash -c 'until curl -f -s http://localhost:3333 > /dev/null; do echo "Waiting for server..."; sleep 2; done'
echo "Server is ready!"
Expand Down
10 changes: 8 additions & 2 deletions apps/kitchensink-react/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import {createPlaywrightConfig} from '@repo/e2e'

const isWebkitProject =
process.argv.includes('--project=webkit') || process.argv.some((arg) => arg.includes('webkit'))

export default createPlaywrightConfig({
testDir: './e2e',
/* Run your local dev server before starting the tests */
...(process.env['CI']
? {} // In CI, don't start a webServer since it's started manually
: {
webServer: {
command: 'pnpm dev --mode e2e',
command: isWebkitProject ? 'pnpm exec vite --port 3333' : 'pnpm dev',
reuseExistingServer: true,
stdout: 'pipe',
env: {
// Pass e2e organization ID to sanity dev
SDK_E2E_ORGANIZATION_ID: process.env['SDK_E2E_ORGANIZATION_ID'] || '',
},
},
}),
})
3 changes: 2 additions & 1 deletion apps/kitchensink-react/sanity.cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {

export default defineCliConfig({
app: {
organizationId: 'oblZgbTFj',
// Use e2e organization ID if provided, otherwise use dev organization ID
organizationId: process.env['SDK_E2E_ORGANIZATION_ID'] || 'oblZgbTFj',
entry: './src/App.tsx',
id: 'wkyoigmzawwnnwx458zgoh46',
},
Expand Down
7 changes: 6 additions & 1 deletion apps/kitchensink-react/vite.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ export default defineConfig(({mode}) => {
const rootDir = resolve(process.cwd(), '../..')
const env = loadEnv(mode, rootDir, '')

const isE2E = mode === 'e2e'
// This variable is usually always going to be present in the user's env files,
// but only comes into play when explicitly injected into the env.
// (`sanity dev` will otherwise ignore all env variables that don't start with `SANITY_APP_`)
// 1. Playwright explicitly injects the env variables
// 2. `pnpm dev:e2e` sets it as part of the command in the root package.json
const isE2E = !!process.env['SDK_E2E_ORGANIZATION_ID']

return {
server: {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"cleanup:e2e": "turbo run cleanup --filter=@repo/e2e",
"dev": "pnpm dev:kitchensink",
"dev:kitchensink": "turbo run dev --filter=@sanity/kitchensink-react",
"dev:e2e": "turbo run dev --filter=@sanity/kitchensink-react -- --mode=e2e",
"dev:e2e": "SANITY_INTERNAL_ENV=staging SDK_E2E_ORGANIZATION_ID=oFvj4MZWQ turbo run dev --filter=@sanity/kitchensink-react",
"deploy:kitchensink": "turbo run deploy --filter=@sanity/kitchensink-react",
"format": "prettier --write --cache --ignore-unknown .",
"lint": "turbo run lint -- --fix && eslint . --fix",
Expand All @@ -37,6 +37,8 @@
"test:coverage": "vitest run --coverage",
"test:coverage:open": "open coverage/index.html",
"test:e2e": "turbo run test:e2e",
"test:e2e:dashboard": "turbo run test:e2e --filter=@sanity/kitchensink-react -- --project=chromium --project=firefox",
"test:e2e:webkit": "turbo run test:e2e --filter=@sanity/kitchensink-react -- --project=webkit",
"test:watch": "vitest watch",
"ts:check": "turbo run ts:check --filter='./packages/*' --filter='./apps/*'",
"depcheck": "DEPCHECK=true knip",
Expand Down
15 changes: 9 additions & 6 deletions packages/@repo/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The tests expect to find the below env variables. Either define them in your she
- `SDK_E2E_ORGANIZATION_ID`: We use oFvj4MZWQ internally
- `SDK_E2E_USER_ID`: sdk+e2e@sanity.io
- `SDK_E2E_USER_PASSWORD`: found in 1Password
- `RECAPTCHA_E2E_STAGING_KEY`: found in 1Password
- `RECAPTCHA_E2E_STAGING_KEY`: found in 1Password as "E2E staging reCAPTCHA bypass token" in Dev Secrets
- `SDK_E2E_DATASET_0`=production
- `SDK_E2E_DATASET_1`=testing

Expand Down Expand Up @@ -38,18 +38,19 @@ test('can click a button', async ({page, getPageContext}) => {

## Running tests

To run E2E tests run the following commands from the root of the project
Right now, tests are split into two separate commands to make local testing easier. This is because we run our tests in the Dashboard, and Safari struggles with an iframed app in localhost. To run E2E tests run the following commands from the root of the project

- Run all the tests

```sh
pnpm test:e2e
pnpm test:e2e:dashboard
pnpm test:e2e:webkit
```

- Run files that have my-spec or my-spec-2 in the file name

```sh
pnpm test:e2e -- my-spec my-spec-2
pnpm test:e2e:dashboard -- my-spec my-spec-2
```

- For help, run
Expand All @@ -59,7 +60,9 @@ To run E2E tests run the following commands from the root of the project

Other useful helper commands

- "dev:e2e": Starts the Kitchensink pointing to the E2E project and dataset. This server can be used by both you as a developer and the e2e tests at the same time for debugging purposes.
- `dev:e2e`: Starts the Kitchensink pointing to the E2E project and dataset. This server can be used by both you as a developer and the e2e tests at the same time for debugging purposes.

NOTE: The `dev:e2e` command hardcodes the Sanity staging environment and the SDK e2e test organization as part of its command. If you'd like to run in a different target organization, you will have to temporarily change the command.

For more useful commands, see the [Playwright Command Line](https://playwright.dev/docs/test-cli) documentation.

Expand All @@ -69,6 +72,6 @@ You can run your tests in your editor with the help of some useful editor plugin

### Running in CI mode

These tests run in CI with a built application (rather than dev server). It also runs its tests in the Dashboard. If you'd like to replicate that, you should add the following variables to your .env.local file:
These tests run in CI with a built application (rather than dev server). It also has more workers and retries. If you'd like to replicate that, you should add the following variables to your .env.local file:

- `CI`: true
5 changes: 4 additions & 1 deletion packages/@repo/e2e/src/helpers/pageContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ export type PageContext = Pick<Page, 'getByTestId' | 'getByText' | 'getByRole' |
context: Page | FrameLocator
}

const DASHBOARD_PROJECTS = ['dashboard-chromium']
// Webkit is excluded from dashboard tests because webkit blocks script execution
// in sandboxed iframes without 'allow-scripts', and the dashboard creates
// sandboxed iframes that webkit cannot execute JavaScript in
const DASHBOARD_PROJECTS = ['chromium', 'firefox']

/**
* Determines if we're in a dashboard context by checking the project name
Expand Down
14 changes: 6 additions & 8 deletions packages/@repo/e2e/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
const SETUP_DIR = path.join(path.dirname(__dirname), 'src', 'setup')
const TEARDOWN_DIR = path.join(path.dirname(__dirname), 'src', 'teardown')
const AUTH_FILE = path.join(path.dirname(__dirname), '.auth', 'user.json')
const BASE_URL = 'http://localhost:3333/'

const {CI, SDK_E2E_ORGANIZATION_ID} = getE2EEnv()
const BASE_URL = `https://www.sanity.work/@${SDK_E2E_ORGANIZATION_ID}/application/__dev/`

/**
* @internal
Expand Down Expand Up @@ -65,15 +65,13 @@ export const basePlaywrightConfig: PlaywrightTestConfig = {
},
{
name: 'webkit',
use: {...devices['Desktop Safari'], storageState: AUTH_FILE, baseURL: BASE_URL},
dependencies: ['setup'],
},
{
name: 'dashboard-chromium',
use: {
...devices['Desktop Chrome'],
...devices['Desktop Safari'],
storageState: AUTH_FILE,
baseURL: `https://www.sanity.work/@${SDK_E2E_ORGANIZATION_ID}/application/__dev/`,
// Webkit cannot execute JavaScript in sandboxed iframes without 'allow-scripts'
// The dashboard creates sandboxed iframes for localhost apps that webkit cannot use
// So webkit runs as standalone (localhost) instead of in the dashboard
baseURL: 'http://localhost:3333/',
},
dependencies: ['setup'],
},
Expand Down
7 changes: 3 additions & 4 deletions packages/@repo/e2e/src/setup/auth.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const authenticateUser = async (context: BrowserContext, config: AuthConfig) =>
await page.goto(loginUrl.toString())

// Wait for the redirect to complete AND network to be idle
await Promise.all([page.waitForURL(config.expectedRedirectUrl)])
await page.waitForURL(config.expectedRedirectUrl)

await page.close()
}
Expand All @@ -68,13 +68,12 @@ setup('setup authentication', async ({browser}) => {
const context = await browser.newContext()

try {
// Authenticate for standalone apps
// Authenticate for standalone (webkit)
await authenticateUser(context, {
origin: 'http://localhost:3333',
expectedRedirectUrl: 'http://localhost:3333',
})

// Authenticate for embedded apps (Dashboard)
// Authenticate for Dashboard (other browsers)
await authenticateUser(context, {
origin: 'https://www.sanity.work/api/dashboard/authenticate',
expectedRedirectUrl: `https://www.sanity.work/@${env.SDK_E2E_ORGANIZATION_ID}`,
Expand Down
36 changes: 8 additions & 28 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@
"PKG_VERSION",
"NPM_CONFIG_PROVENANCE",
"CI",
"SDK_E2E_PROJECT_ID",
"SDK_E2E_ORGANIZATION_ID",
"SDK_E2E_DATASET_0",
"SDK_E2E_DATASET_1",
"SDK_E2E_SESSION_TOKEN",
"SDK_E2E_USER_ID",
"SDK_E2E_USER_PASSWORD",
"SDK_E2E_*",
"RECAPTCHA_E2E_STAGING_KEY"
],
"tasks": {
Expand All @@ -28,25 +22,21 @@
"dependsOn": ["^build"],
"outputs": ["docs/**"]
},
"check-types": {
"dependsOn": ["^check-types"]
"ts:check": {
"dependsOn": ["^ts:check"]
},
"clean": {},
"cleanup": {
"cache": false,
"env": [
"SDK_E2E_PROJECT_ID",
"SDK_E2E_DATASET_0",
"SDK_E2E_DATASET_1",
"SDK_E2E_SESSION_TOKEN"
]
"env": ["SDK_E2E_*"]
},
"depcheck": {
"env": ["DEPCHECK"]
},
"dev": {
"persistent": true,
"cache": false
"cache": false,
"env": ["SANITY_INTERNAL_ENV"]
},
"docs": {
"dependsOn": ["^build"],
Expand All @@ -55,7 +45,7 @@
"dev:e2e": {
"persistent": true,
"cache": false,
"env": ["SDK_E2E_PROJECT_ID", "SDK_E2E_DATASET_0", "SDK_E2E_DATASET_1"]
"env": ["SDK_E2E_*", "SANITY_INTERNAL_ENV"]
},
"lint": {
"cache": false
Expand All @@ -72,17 +62,7 @@
},
"test:e2e": {
"cache": false,
"env": [
"SDK_E2E_PROJECT_ID",
"SDK_E2E_ORGANIZATION_ID",
"SDK_E2E_DATASET_0",
"SDK_E2E_DATASET_1",
"SDK_E2E_SESSION_TOKEN",
"NODE_ENV",
"SDK_E2E_USER_ID",
"SDK_E2E_USER_PASSWORD",
"RECAPTCHA_E2E_STAGING_KEY"
],
"env": ["SDK_E2E_*", "NODE_ENV", "RECAPTCHA_E2E_STAGING_KEY"],
"dependsOn": ["@repo/e2e#build"],
"outputs": ["e2e/test-results/**", "e2e/test-report/**"]
},
Expand Down
Loading