diff --git a/.changeset/scope-integration-test-inputs.md b/.changeset/scope-integration-test-inputs.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/scope-integration-test-inputs.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.claude/skills/clerk-monorepo/SKILL.md b/.claude/skills/clerk-monorepo/SKILL.md index 05b27921ba1..9f7f82d1862 100644 --- a/.claude/skills/clerk-monorepo/SKILL.md +++ b/.claude/skills/clerk-monorepo/SKILL.md @@ -138,6 +138,60 @@ If the editor or a build reports stale types from `@clerk/shared`, rebuild the f Integration-test variants (`pnpm test:integration:*`) and canary/snapshot releases are the long tail: see [`references/setup-and-footguns.md`](references/setup-and-footguns.md) and `docs/CONTRIBUTING.md`. +## Integration CI caching + +Each Playwright suite is a root turbo task, `//#test:integration:`, run by the `integration-tests` +matrix in `.github/workflows/ci.yml`. Turbo caches a suite's result, so a PR that cannot change the +outcome skips the suite entirely: no build, no local registry publish, no browser install. + +How the cache key is built: + +- `dependsOn` lists `#build:inputs` for each package the suite uses: always `@clerk/clerk-js` and + `@clerk/ui`, the packages the harness imports (the `devDependencies` of `integration/package.json`), + plus the framework packages that suite's apps install from the local registry. `build:inputs` is a transit node: no package defines the script, so it never + runs or restores anything, but it hashes the same inputs as `build` and depends on `^build:inputs`, + so transitive packages such as `@clerk/shared` are covered without being listed. A cache hit + therefore downloads no build outputs; on a miss the runner script builds. +- `inputs` covers the harness, the test directories the suite's tagged tests live in (and import + from), the templates its apps copy, and any package source file a test imports directly, such as a + `packages/*/src/test` fixture the package build excludes. Other suites' directories are not inputs. Tests live under + `integration/tests//`; a test tagged for several suites lives in `generic/`, and tests no + suite runs live in `unscheduled/`. +- `scripts/integration-deps.test.mjs` derives both lists from `integration/presets` and the tagged + tests and fails when `turbo.json` drifts. Its failure message prints the block to paste. + +Rules that keep this correct: + +- The integration test step must never pass `--only`. It drops dependency hashes from the task hash, + so package changes would stop invalidating suites. +- Keep `build:inputs` identical to `build`'s inputs, in the root `turbo.json` and in every package + `turbo.json` that overrides `build.inputs`; `integration-deps.test.mjs` enforces both. +- The harness's workspace dependencies live in `integration/package.json`, never the root + `package.json`. Turbo folds every file of a root workspace dependency, tests and READMEs included, + into the global hash, so any edit to it would rerun every task in the repo. +- The merge queue sets `TURBO_FORCE=true` on the test step and nightly passes `--force`, so every suite + runs for real before a commit lands on `main`. Forcing reaches only the suite and its transit nodes; + the runner script's own `turbo build` resets `TURBO_FORCE` so package builds still restore from cache. A `dependsOn` gap is a wasted-cache bug on PRs, not a + correctness hole on `main`. +- Per-job setup lives in `integration/scripts/run-integration.mjs`, which the `test:integration:base` + script wraps. When `E2E_CI_SETUP` names the suite it builds, publishes to pkglab, installs clerk-js + and ui into temp dirs, installs Chromium and, for electron, Xvfb, then runs Playwright. Locally + `E2E_CI_SETUP` is unset and it only runs Playwright. It drops `CLERK_*` from the build's + environment: `CLERK_*` is in `globalEnv`, so the test step's secrets would otherwise change every + build hash and miss the Build Packages job's cache. A cache hit runs none of it, including the + user cleanup step, which is gated on the `tests-started` output the script writes. + +Adding a suite: + +1. Add `test:integration:` to the root `package.json`, tagging tests with `@` and + pointing `E2E_APP_ID` at the long-running apps it needs. +2. Add `//#test:integration:` to `turbo.json`. Run `pnpm vitest run --root scripts +integration-deps` and paste the `dependsOn` and `inputs` the failure prints. +3. Add the suite to the `integration-tests` matrix in `ci.yml`. + +To see what a change invalidates, run `node scripts/integration-hash-matrix.mjs` on a clean tree. It +touches a few representative files, dry-runs turbo, and prints which suites would rerun for each. + ## The hard rules Each rule below restates `AGENTS.md`; the parenthetical is how it is enforced. diff --git a/.github/actions/init-blacksmith/action.yml b/.github/actions/init-blacksmith/action.yml index b3718ff9410..77de44ff5dc 100644 --- a/.github/actions/init-blacksmith/action.yml +++ b/.github/actions/init-blacksmith/action.yml @@ -9,6 +9,10 @@ inputs: description: 'Enable Playwright?' required: false default: 'false' + playwright-install-enabled: + description: 'Install Playwright browsers after restoring the cache?' + required: false + default: 'true' turbo-summarize: description: 'The token to use for Turbo task summaries' required: false @@ -146,7 +150,7 @@ runs: key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-playwright-${{ steps.playwright-version.outputs.VERSION }}-v2 - name: Install Playwright Browsers - if: inputs.playwright-enabled == 'true' && steps.playwright-cache.outputs.cache-hit != 'true' + if: inputs.playwright-enabled == 'true' && inputs.playwright-install-enabled == 'true' && steps.playwright-cache.outputs.cache-hit != 'true' shell: bash run: | pnpm playwright install chromium diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8f50d993e5..64d26583645 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -379,9 +379,9 @@ jobs: env: NODE_VERSION: ${{ matrix.node-version }} - - name: Run verify script tests + - name: Run CI script tests if: matrix.node-version == '24.15.0' - run: pnpm vitest run --root scripts verify-attach verify-flaky + run: pnpm vitest run --root scripts verify-attach verify-flaky run-integration integration-deps - name: Upload Turbo Summary uses: actions/upload-artifact@v4.6.2 @@ -582,81 +582,12 @@ jobs: turbo-team: ${{ vars.TURBO_TEAM }} turbo-token: ${{ secrets.TURBO_TOKEN }} playwright-enabled: true - - - name: Verify jq is installed - shell: bash - run: | - if ! command -v jq &> /dev/null; then - echo "jq not found, installing..." - sudo apt-get update && sudo apt-get install -y jq - fi - jq --version + playwright-install-enabled: false - name: Validate turbo task - env: - E2E_APP_CLERK_JS_DIR: ${{runner.temp}} - E2E_APP_CLERK_UI_DIR: ${{runner.temp}} - E2E_CLERK_JS_VERSION: 'latest' - E2E_CLERK_UI_VERSION: 'latest' - E2E_NEXTJS_VERSION: ${{ matrix.next-version }} - E2E_PROJECT: ${{ matrix.test-project }} - INTEGRATION_INSTANCE_KEYS: ${{ secrets.INTEGRATION_INSTANCE_KEYS }} run: | - # Validate the turbo task exists. Turbo's --affected flag is a no-op for - # root-level tasks (//#) — they are always returned as affected. The previous - # --affected check only served to silently skip tests when the task was missing - # from turbo.json, hiding real configuration errors. TASK_NAME="test:integration:${{ matrix.test-name }}" - TURBO_STDERR=$(mktemp) - if ! TURBO_RAW=$(pnpm turbo run "$TASK_NAME" --dry=json 2>"$TURBO_STDERR"); then - echo "::error::Turbo task '$TASK_NAME' failed validation" - cat "$TURBO_STDERR" - exit 1 - fi - - # pnpm can prepend non-JSON lines (e.g. `WARN Unsupported engine: ...`) - # to stdout, which would break jq. Drop everything before the first `{`. - TURBO_JSON=$(printf '%s\n' "$TURBO_RAW" | awk '/^\{/{found=1} found') - - if ! TASK_COUNT=$(jq -er '.tasks | length' <<< "$TURBO_JSON"); then - echo "::error::Turbo task '$TASK_NAME' returned invalid JSON or missing .tasks" - printf '%s\n' "$TURBO_JSON" - exit 1 - fi - - if [ "$TASK_COUNT" -eq 0 ]; then - echo "::error::Turbo task '$TASK_NAME' returned 0 tasks" - exit 1 - fi - - echo "Task '$TASK_NAME' validated ($TASK_COUNT tasks in graph)" - - - name: Build packages - run: pnpm turbo build $TURBO_ARGS --only - - - name: Publish to local registry - run: pkglab pub --force - - - name: Edit .npmrc [link-workspace-packages=false] - run: sed -i -E 's/link-workspace-packages=(deep|true)/link-workspace-packages=false/' .npmrc - - - name: Install @clerk/clerk-js in os temp - working-directory: ${{runner.temp}} - run: | - mkdir clerk-js && cd clerk-js - pnpm init - pkglab add @clerk/clerk-js - - - name: Install @clerk/ui in os temp - working-directory: ${{runner.temp}} - run: | - mkdir clerk-ui && cd clerk-ui - pnpm init - pkglab add @clerk/ui - - - name: Copy components @clerk/astro - if: ${{ matrix.test-name == 'astro' }} - run: cd packages/astro && pnpm copy:components + node -e 'const pkg = require("./package.json"); const turbo = require("./turbo.json"); const name = process.argv[1]; if (!pkg.scripts[name] || !turbo.tasks["//#" + name]) process.exit(1)' "$TASK_NAME" - name: Write all ENV certificates to files in integration/certs uses: actions/github-script@v7.1.0 @@ -675,18 +606,6 @@ jobs: fs.writeFileSync(path.join(process.env.GITHUB_WORKSPACE, 'integration/certs', name), cert); } - - name: LS certs - working-directory: ./integration/certs - run: ls -la && pwd - - - name: Ensure Xvfb is installed - if: ${{ matrix.test-name == 'electron' }} - run: | - if ! command -v xvfb-run &> /dev/null; then - sudo apt-get update - sudo apt-get install -y xvfb - fi - - name: Configure test user cleanup run: echo "INTEGRATION_TEST_RUN_KEY=${RUN_ID}-${RUN_ATTEMPT}-${TEST_NAME}-${TEST_PROJECT}-${NEXT_VERSION:-default}" >> "$GITHUB_ENV" env: @@ -699,13 +618,10 @@ jobs: - name: Run Integration Tests id: integration-tests timeout-minutes: 25 - run: | - if [ "${{ matrix.test-name }}" = "electron" ]; then - xvfb-run -a pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS - else - pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS - fi + run: pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS env: + TURBO_FORCE: ${{ github.event_name == 'merge_group' }} + E2E_CI_SETUP: ${{ matrix.test-name }} CLERK_E2E_OAUTH_PROVIDER_CLIENT_SECRET: ${{ secrets.CLERK_E2E_OAUTH_PROVIDER_CLIENT_SECRET }} CLERK_PLATFORM_API_KEY: ${{ secrets.CLERK_PLATFORM_API_KEY }} E2E_DEBUG: '1' @@ -737,7 +653,7 @@ jobs: retention-days: 1 - name: Delete integration-test users - if: ${{ always() && steps.integration-tests.outcome != 'skipped' }} + if: ${{ always() && steps.integration-tests.outputs.tests-started == 'true' }} timeout-minutes: 10 run: pnpm test:integration:cleanup env: diff --git a/.github/workflows/e2e-staging.yml b/.github/workflows/e2e-staging.yml index 3d99a351fab..29d4eef7771 100644 --- a/.github/workflows/e2e-staging.yml +++ b/.github/workflows/e2e-staging.yml @@ -290,7 +290,7 @@ jobs: run: pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS env: # Staging e2e validates the LIVE staging deploy, which is not a turbo input - # (the cache key is integration/** + env). Force re-execution so a cached green + # (the cache key is the suite's inputs, package sources and env). Force re-execution so a cached green # pass can't stand in for an untested deploy, and so the Playwright JSON report # is regenerated every run instead of being skipped on a `>>> FULL TURBO` hit. TURBO_FORCE: 'true' diff --git a/.github/workflows/nightly-checks.yml b/.github/workflows/nightly-checks.yml index e2e36b6d20f..0ce88453081 100644 --- a/.github/workflows/nightly-checks.yml +++ b/.github/workflows/nightly-checks.yml @@ -74,7 +74,7 @@ jobs: if [ "${{ matrix.test-name }}" == "nextjs" ]; then E2E_DEBUG=1 E2E_APP_ID=quickstart.next.appRouter pnpm test:integration:base --grep @quickstart 2>&1 | tee "$OUTPUT_FILE" else - E2E_DEBUG=1 pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS --only 2>&1 | tee "$OUTPUT_FILE" + E2E_DEBUG=1 pnpm turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS --only --force 2>&1 | tee "$OUTPUT_FILE" fi echo "exit_code=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT env: diff --git a/integration/models/applicationConfig.ts b/integration/models/applicationConfig.ts index 9e9474505d1..28457d03220 100644 --- a/integration/models/applicationConfig.ts +++ b/integration/models/applicationConfig.ts @@ -153,6 +153,9 @@ export const applicationConfig = () => { get scripts() { return scripts; }, + get template() { + return template; + }, get pkglabDependencies() { return [...dependencies.entries()].filter(([, version]) => version === PKGLAB).map(([name]) => name); }, diff --git a/integration/package.json b/integration/package.json index e986b24bbae..6de7fbe8c68 100644 --- a/integration/package.json +++ b/integration/package.json @@ -1,4 +1,11 @@ { + "name": "@clerk/integration", + "version": "0.0.0", "private": true, - "type": "module" + "type": "module", + "devDependencies": { + "@clerk/backend": "workspace:*", + "@clerk/shared": "workspace:*", + "@clerk/testing": "workspace:*" + } } diff --git a/integration/scripts/run-integration.mjs b/integration/scripts/run-integration.mjs new file mode 100644 index 00000000000..b9fa8807672 --- /dev/null +++ b/integration/scripts/run-integration.mjs @@ -0,0 +1,72 @@ +import { spawnSync } from 'node:child_process'; +import { appendFileSync, mkdirSync } from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '../..'); +const [command, ...args] = process.argv.slice(2); +const suite = process.env.E2E_CI_SETUP; + +if (!command) { + fail('usage: node integration/scripts/run-integration.mjs [args...]'); +} + +if (suite) { + prepareCiRunner(suite); +} + +if (suite === 'electron') { + run('xvfb-run', ['-a', command, ...args]); +} else { + run(command, args); +} + +function prepareCiRunner(suite) { + const turboArgs = required('TURBO_ARGS').split(/\s+/).filter(Boolean); + const installs = [ + ['@clerk/clerk-js', join(required('E2E_APP_CLERK_JS_DIR'), 'clerk-js')], + ['@clerk/ui', join(required('E2E_APP_CLERK_UI_DIR'), 'clerk-ui')], + ]; + const githubOutput = required('GITHUB_OUTPUT'); + + const buildEnv = Object.fromEntries(Object.entries(process.env).filter(([name]) => !name.startsWith('CLERK_'))); + run('pnpm', ['turbo', 'build', ...turboArgs, '--only'], { env: { ...buildEnv, TURBO_FORCE: 'false' } }); + run('pkglab', ['pub', '--force']); + for (const [packageName, dir] of installs) { + mkdirSync(dir, { recursive: true }); + run('pnpm', ['init'], { cwd: dir }); + run('pkglab', ['add', packageName], { cwd: dir }); + } + if (suite === 'astro') { + run('pnpm', ['copy:components'], { cwd: join(root, 'packages/astro') }); + } + run('pnpm', ['playwright', 'install', 'chromium']); + if (suite === 'electron' && spawnSync('sh', ['-c', 'command -v xvfb-run'], { stdio: 'ignore' }).status !== 0) { + run('sudo', ['apt-get', 'update']); + run('sudo', ['apt-get', 'install', '-y', 'xvfb']); + } + appendFileSync(githubOutput, 'tests-started=true\n'); +} + +function required(name) { + const value = process.env[name]; + if (!value) { + fail(`${name} must be set when E2E_CI_SETUP is set`); + } + return value; +} + +function run(command, args, options = {}) { + const result = spawnSync(command, args, { cwd: root, stdio: 'inherit', ...options }); + if (result.error) { + fail(result.error.message); + } + if (result.status !== 0) { + process.exit(result.status ?? 1); + } +} + +function fail(message) { + console.error(`run-integration: ${message}`); + process.exit(1); +} diff --git a/integration/tests/billing-hooks.test.ts b/integration/tests/billing/billing-hooks.test.ts similarity index 96% rename from integration/tests/billing-hooks.test.ts rename to integration/tests/billing/billing-hooks.test.ts index f99a40a2f48..c0d6935c3cb 100644 --- a/integration/tests/billing-hooks.test.ts +++ b/integration/tests/billing/billing-hooks.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({})('billing hooks @billing', ({ app }) => { test.describe.configure({ mode: 'parallel' }); diff --git a/integration/tests/per-seat-pricing.test.ts b/integration/tests/billing/per-seat-pricing.test.ts similarity index 95% rename from integration/tests/per-seat-pricing.test.ts rename to integration/tests/billing/per-seat-pricing.test.ts index e8177c6b8af..3970e2321f9 100644 --- a/integration/tests/per-seat-pricing.test.ts +++ b/integration/tests/billing/per-seat-pricing.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; const INVITEE_EMAIL = 'one+clerk_test@clerk.dev'; diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/billing/pricing-table.test.ts similarity index 99% rename from integration/tests/pricing-table.test.ts rename to integration/tests/billing/pricing-table.test.ts index 4983f3d14c8..9a6665669e3 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/billing/pricing-table.test.ts @@ -1,8 +1,8 @@ import type { Locator } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({})('pricing table @billing', ({ app }) => { test.describe.configure({ mode: 'parallel' }); diff --git a/integration/tests/cache-components.test.ts b/integration/tests/cache-components/cache-components.test.ts similarity index 98% rename from integration/tests/cache-components.test.ts rename to integration/tests/cache-components/cache-components.test.ts index 6915724b22c..275d0c088f8 100644 --- a/integration/tests/cache-components.test.ts +++ b/integration/tests/cache-components/cache-components.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes], withPattern: ['next.cacheComponents'] })( 'Next.js Cache Components @cache-components', diff --git a/integration/tests/client-trust.test.ts b/integration/tests/generic/client-trust.test.ts similarity index 95% rename from integration/tests/client-trust.test.ts rename to integration/tests/generic/client-trust.test.ts index 0cb11bcf1c5..42e0d537afe 100644 --- a/integration/tests/client-trust.test.ts +++ b/integration/tests/generic/client-trust.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withNeedsClientTrust] })( 'client trust flow @generic @nextjs', diff --git a/integration/tests/components.test.ts b/integration/tests/generic/components.test.ts similarity index 94% rename from integration/tests/components.test.ts rename to integration/tests/generic/components.test.ts index c8b0c71bf50..35e1b9bdc3b 100644 --- a/integration/tests/components.test.ts +++ b/integration/tests/generic/components.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('component smoke tests @generic', ({ app }) => { let fakeUser: FakeUser; diff --git a/integration/tests/composed-components.test.ts b/integration/tests/generic/composed-components.test.ts similarity index 98% rename from integration/tests/composed-components.test.ts rename to integration/tests/generic/composed-components.test.ts index 43a5139b4b5..dd6a29206d2 100644 --- a/integration/tests/composed-components.test.ts +++ b/integration/tests/generic/composed-components.test.ts @@ -1,11 +1,11 @@ import { type BrowserContext, expect, type Page, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { PKGLAB } from '../presets/utils'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; -import { stringPhoneNumber } from '../testUtils/phoneUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { PKGLAB } from '../../presets/utils'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; +import { stringPhoneNumber } from '../../testUtils/phoneUtils'; /** * E2E parity coverage for the experimental composed exports from `@clerk/ui/experimental`. diff --git a/integration/tests/custom-pages.test.ts b/integration/tests/generic/custom-pages.test.ts similarity index 99% rename from integration/tests/custom-pages.test.ts rename to integration/tests/generic/custom-pages.test.ts index 8dc4e84cdbd..e7aad5fdfe8 100644 --- a/integration/tests/custom-pages.test.ts +++ b/integration/tests/generic/custom-pages.test.ts @@ -1,9 +1,9 @@ /* eslint-disable turbo/no-undeclared-env-vars */ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import type { CreateAppPageObjectArgs, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import type { Application } from '../../models/application'; +import type { CreateAppPageObjectArgs, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; const CUSTOM_PROFILE_PAGE = '/custom-user-profile'; const CUSTOM_BUTTON_PAGE = '/custom-user-button'; diff --git a/integration/tests/dev-browser-partitioned-cookies.test.ts b/integration/tests/generic/dev-browser-partitioned-cookies.test.ts similarity index 94% rename from integration/tests/dev-browser-partitioned-cookies.test.ts rename to integration/tests/generic/dev-browser-partitioned-cookies.test.ts index 4525b382cda..0f53af8e700 100644 --- a/integration/tests/dev-browser-partitioned-cookies.test.ts +++ b/integration/tests/generic/dev-browser-partitioned-cookies.test.ts @@ -1,9 +1,9 @@ import { expect, test } from '@playwright/test'; import { parsePublishableKey } from '@clerk/shared/keys'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })( 'dev browser partitioned cookies @generic', diff --git a/integration/tests/email-code.test.ts b/integration/tests/generic/email-code.test.ts similarity index 93% rename from integration/tests/email-code.test.ts rename to integration/tests/generic/email-code.test.ts index 980894d6487..9c757df531c 100644 --- a/integration/tests/email-code.test.ts +++ b/integration/tests/generic/email-code.test.ts @@ -1,9 +1,9 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; test.describe('sign up and sign in with email code @generic', () => { const configs = [appConfigs.next.appRouter, appConfigs.react.vite]; diff --git a/integration/tests/handshake.test.ts b/integration/tests/generic/handshake.test.ts similarity index 99% rename from integration/tests/handshake.test.ts rename to integration/tests/generic/handshake.test.ts index 7c29dee8c56..d3af2c82ddc 100644 --- a/integration/tests/handshake.test.ts +++ b/integration/tests/generic/handshake.test.ts @@ -2,10 +2,10 @@ import * as http from 'node:http'; import { expect, test } from '@playwright/test'; -import type { OrganizationSyncOptions } from '../../packages/backend/src/tokens/types'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { generateConfig, getJwksFromSecretKey } from '../testUtils/handshake'; +import type { OrganizationSyncOptions } from '../../../packages/backend/src/tokens/types'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { generateConfig, getJwksFromSecretKey } from '../../testUtils/handshake'; const PORT = 4199; diff --git a/integration/tests/impersonation-flow.test.ts b/integration/tests/generic/impersonation-flow.test.ts similarity index 93% rename from integration/tests/impersonation-flow.test.ts rename to integration/tests/generic/impersonation-flow.test.ts index aed9e581693..59b36977e82 100644 --- a/integration/tests/impersonation-flow.test.ts +++ b/integration/tests/generic/impersonation-flow.test.ts @@ -1,9 +1,9 @@ import type { User } from '@clerk/backend'; import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('Impersonation Flow @generic', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/last-authentication-strategy.test.ts b/integration/tests/generic/last-authentication-strategy.test.ts similarity index 98% rename from integration/tests/last-authentication-strategy.test.ts rename to integration/tests/generic/last-authentication-strategy.test.ts index ed81e9c1e7a..6464d2c0fbd 100644 --- a/integration/tests/last-authentication-strategy.test.ts +++ b/integration/tests/generic/last-authentication-strategy.test.ts @@ -2,8 +2,8 @@ import type { LastAuthenticationStrategy } from '@clerk/shared/types'; import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; const mockLastAuthenticationStrategyResponse = async ( page: Page, diff --git a/integration/tests/legal-consent.test.ts b/integration/tests/generic/legal-consent.test.ts similarity index 94% rename from integration/tests/legal-consent.test.ts rename to integration/tests/generic/legal-consent.test.ts index 6f232376b0f..1eefda6c082 100644 --- a/integration/tests/legal-consent.test.ts +++ b/integration/tests/generic/legal-consent.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withLegalConsent] })( 'sign up flow with legal consent @generic @nextjs', diff --git a/integration/tests/navigation.test.ts b/integration/tests/generic/navigation.test.ts similarity index 94% rename from integration/tests/navigation.test.ts rename to integration/tests/generic/navigation.test.ts index d065af9bc58..0ec0a098784 100644 --- a/integration/tests/navigation.test.ts +++ b/integration/tests/generic/navigation.test.ts @@ -1,7 +1,7 @@ import { test } from '@playwright/test'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withPattern: ['next.appRouter.withEmailCodes'] })('navigation modes @generic', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/non-secure-context.test.ts b/integration/tests/generic/non-secure-context.test.ts similarity index 91% rename from integration/tests/non-secure-context.test.ts rename to integration/tests/generic/non-secure-context.test.ts index 268868ee868..49a9f5d908b 100644 --- a/integration/tests/non-secure-context.test.ts +++ b/integration/tests/generic/non-secure-context.test.ts @@ -16,9 +16,9 @@ import type { Server } from 'node:http'; import { test } from '@playwright/test'; -import { createProxyServer } from '../scripts/proxyServer'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { createProxyServer } from '../../scripts/proxyServer'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; // This NEEDS to be a domain that points to localhost // and is not listed in the HSTS preload list diff --git a/integration/tests/offline-session-persistence.test.ts b/integration/tests/generic/offline-session-persistence.test.ts similarity index 96% rename from integration/tests/offline-session-persistence.test.ts rename to integration/tests/generic/offline-session-persistence.test.ts index 1f49d8e227f..34058fa8080 100644 --- a/integration/tests/offline-session-persistence.test.ts +++ b/integration/tests/generic/offline-session-persistence.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })( 'offline session persistence @generic', diff --git a/integration/tests/passkeys.test.ts b/integration/tests/generic/passkeys.test.ts similarity index 97% rename from integration/tests/passkeys.test.ts rename to integration/tests/generic/passkeys.test.ts index 77968ed22a5..c568b13e6b5 100644 --- a/integration/tests/passkeys.test.ts +++ b/integration/tests/generic/passkeys.test.ts @@ -1,10 +1,10 @@ import type { BrowserContext, Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; type SavedCredential = { id: string; diff --git a/integration/tests/protect-check.test.ts b/integration/tests/generic/protect-check.test.ts similarity index 97% rename from integration/tests/protect-check.test.ts rename to integration/tests/generic/protect-check.test.ts index 75f74cf6828..0a155f8c7ac 100644 --- a/integration/tests/protect-check.test.ts +++ b/integration/tests/generic/protect-check.test.ts @@ -1,10 +1,10 @@ import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; const waitForProtectCheckSubmit = (page: Page) => page.waitForResponse( diff --git a/integration/tests/protect-service.test.ts b/integration/tests/generic/protect-service.test.ts similarity index 95% rename from integration/tests/protect-service.test.ts rename to integration/tests/generic/protect-service.test.ts index dc1f82ef304..b9c58bc9cd6 100644 --- a/integration/tests/protect-service.test.ts +++ b/integration/tests/generic/protect-service.test.ts @@ -2,8 +2,8 @@ import type { ProtectConfigJSON } from '@clerk/shared/types'; import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; const mockProtectSettings = async (page: Page, config?: ProtectConfigJSON) => { await page.route('*/**/v1/environment*', async route => { diff --git a/integration/tests/resiliency.test.ts b/integration/tests/generic/resiliency.test.ts similarity index 99% rename from integration/tests/resiliency.test.ts rename to integration/tests/generic/resiliency.test.ts index 695e61ad53c..eef56098c7f 100644 --- a/integration/tests/resiliency.test.ts +++ b/integration/tests/generic/resiliency.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; const make429ClerkResponse = () => ({ status: 429, diff --git a/integration/tests/safari-itp.test.ts b/integration/tests/generic/safari-itp.test.ts similarity index 97% rename from integration/tests/safari-itp.test.ts rename to integration/tests/generic/safari-itp.test.ts index d764437a4d3..16b3109630f 100644 --- a/integration/tests/safari-itp.test.ts +++ b/integration/tests/generic/safari-itp.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; /** * Tests Safari ITP (Intelligent Tracking Prevention) workaround diff --git a/integration/tests/sign-in-flow.test.ts b/integration/tests/generic/sign-in-flow.test.ts similarity index 97% rename from integration/tests/sign-in-flow.test.ts rename to integration/tests/generic/sign-in-flow.test.ts index 4aa124b9176..bfafb1ad3db 100644 --- a/integration/tests/sign-in-flow.test.ts +++ b/integration/tests/generic/sign-in-flow.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign in flow @generic @nextjs', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/sign-out-smoke.test.ts b/integration/tests/generic/sign-out-smoke.test.ts similarity index 96% rename from integration/tests/sign-out-smoke.test.ts rename to integration/tests/generic/sign-out-smoke.test.ts index 3aa855d394b..b668ee901b9 100644 --- a/integration/tests/sign-out-smoke.test.ts +++ b/integration/tests/generic/sign-out-smoke.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign out smoke test @generic', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/sign-up-flow.test.ts b/integration/tests/generic/sign-up-flow.test.ts similarity index 98% rename from integration/tests/sign-up-flow.test.ts rename to integration/tests/generic/sign-up-flow.test.ts index 58ef0d393e0..fa4740340d6 100644 --- a/integration/tests/sign-up-flow.test.ts +++ b/integration/tests/generic/sign-up-flow.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign up flow @generic @nextjs', ({ app }) => { test.describe.configure({ mode: 'parallel' }); diff --git a/integration/tests/update-props.test.ts b/integration/tests/generic/update-props.test.ts similarity index 92% rename from integration/tests/update-props.test.ts rename to integration/tests/generic/update-props.test.ts index 7084bb7edf3..b7a7965bf1b 100644 --- a/integration/tests/update-props.test.ts +++ b/integration/tests/generic/update-props.test.ts @@ -1,7 +1,7 @@ import { test } from '@playwright/test'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withPattern: ['react.vite.withEmailCodes'] })('sign in flow @generic', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/user-avatar.test.ts b/integration/tests/generic/user-avatar.test.ts similarity index 88% rename from integration/tests/user-avatar.test.ts rename to integration/tests/generic/user-avatar.test.ts index 66e7684fda9..99b048c7291 100644 --- a/integration/tests/user-avatar.test.ts +++ b/integration/tests/generic/user-avatar.test.ts @@ -1,8 +1,8 @@ import { test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes], diff --git a/integration/tests/user-profile.test.ts b/integration/tests/generic/user-profile.test.ts similarity index 97% rename from integration/tests/user-profile.test.ts rename to integration/tests/generic/user-profile.test.ts index 540e6e095c1..b916d1fb762 100644 --- a/integration/tests/user-profile.test.ts +++ b/integration/tests/generic/user-profile.test.ts @@ -1,10 +1,10 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; -import { stringPhoneNumber } from '../testUtils/phoneUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; +import { stringPhoneNumber } from '../../testUtils/phoneUtils'; test.describe('user profile @generic', () => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/whatsapp-phone-code.test.ts b/integration/tests/generic/whatsapp-phone-code.test.ts similarity index 97% rename from integration/tests/whatsapp-phone-code.test.ts rename to integration/tests/generic/whatsapp-phone-code.test.ts index 7716eab4511..5b3c20f4bdd 100644 --- a/integration/tests/whatsapp-phone-code.test.ts +++ b/integration/tests/generic/whatsapp-phone-code.test.ts @@ -2,10 +2,10 @@ import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; const clickSendCodeViaSmsInstead = async (page: Page, verificationHeading: RegExp) => { await page.getByRole('heading', { name: verificationHeading }).waitFor(); diff --git a/integration/tests/api-keys-component.test.ts b/integration/tests/machine/api-keys-component.test.ts similarity index 99% rename from integration/tests/api-keys-component.test.ts rename to integration/tests/machine/api-keys-component.test.ts index 4dda3e8b234..75ac837377f 100644 --- a/integration/tests/api-keys-component.test.ts +++ b/integration/tests/machine/api-keys-component.test.ts @@ -1,10 +1,10 @@ import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; const mockAPIKeysEnvironmentSettings = async ( page: Page, diff --git a/integration/tests/next-machine.test.ts b/integration/tests/machine/next-machine.test.ts similarity index 96% rename from integration/tests/next-machine.test.ts rename to integration/tests/machine/next-machine.test.ts index faaffe5944c..472464499ee 100644 --- a/integration/tests/next-machine.test.ts +++ b/integration/tests/machine/next-machine.test.ts @@ -2,10 +2,10 @@ import type { User } from '@clerk/backend'; import { TokenType } from '@clerk/backend/internal'; import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { createTestUtils } from '../testUtils'; -import type { FakeMachineNetwork, MachineAuthTestAdapter } from '../testUtils/machineAuthHelpers'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { createTestUtils } from '../../testUtils'; +import type { FakeMachineNetwork, MachineAuthTestAdapter } from '../../testUtils/machineAuthHelpers'; import { createFakeMachineNetwork, createJwtM2MToken, @@ -13,8 +13,8 @@ import { registerApiKeyAuthTests, registerM2MAuthTests, registerOAuthAuthTests, -} from '../testUtils/machineAuthHelpers'; -import type { FakeAPIKey, FakeUser } from '../testUtils/usersService'; +} from '../../testUtils/machineAuthHelpers'; +import type { FakeAPIKey, FakeUser } from '../../testUtils/usersService'; const adapter: MachineAuthTestAdapter = { baseConfig: appConfigs.next.appRouter, diff --git a/integration/tests/content-security-policy.test.ts b/integration/tests/nextjs/content-security-policy.test.ts similarity index 86% rename from integration/tests/content-security-policy.test.ts rename to integration/tests/nextjs/content-security-policy.test.ts index 638d260ee77..c589eb1caf6 100644 --- a/integration/tests/content-security-policy.test.ts +++ b/integration/tests/nextjs/content-security-policy.test.ts @@ -1,6 +1,6 @@ import { test } from '@playwright/test'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withPattern: ['next.appRouter.withEmailCodes'] })( 'Content Security Policy @nextjs', diff --git a/integration/tests/dynamic-keys.test.ts b/integration/tests/nextjs/dynamic-keys.test.ts similarity index 95% rename from integration/tests/dynamic-keys.test.ts rename to integration/tests/nextjs/dynamic-keys.test.ts index 21b27dcc50c..236a6496a71 100644 --- a/integration/tests/dynamic-keys.test.ts +++ b/integration/tests/nextjs/dynamic-keys.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { createTestUtils } from '../../testUtils'; test.describe('dynamic keys @nextjs', () => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/next-build.test.ts b/integration/tests/nextjs/next-build.test.ts similarity index 98% rename from integration/tests/next-build.test.ts rename to integration/tests/nextjs/next-build.test.ts index 697384b9922..f9dea3c670e 100644 --- a/integration/tests/next-build.test.ts +++ b/integration/tests/nextjs/next-build.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { PKGLAB } from '../presets/utils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { PKGLAB } from '../../presets/utils'; type RenderingModeTestCase = { name: string; diff --git a/integration/tests/next-middleware-keyless.test.ts b/integration/tests/nextjs/next-middleware-keyless.test.ts similarity index 91% rename from integration/tests/next-middleware-keyless.test.ts rename to integration/tests/nextjs/next-middleware-keyless.test.ts index d699b7790f8..36a2111008a 100644 --- a/integration/tests/next-middleware-keyless.test.ts +++ b/integration/tests/nextjs/next-middleware-keyless.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; const commonSetup = appConfigs.next.appRouter.clone(); diff --git a/integration/tests/oauth-flows.test.ts b/integration/tests/nextjs/oauth-flows.test.ts similarity index 98% rename from integration/tests/oauth-flows.test.ts rename to integration/tests/nextjs/oauth-flows.test.ts index 51024988e17..ffafa3d512b 100644 --- a/integration/tests/oauth-flows.test.ts +++ b/integration/tests/nextjs/oauth-flows.test.ts @@ -2,13 +2,13 @@ import { createClerkClient } from '@clerk/backend'; import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; -import { environmentConfig } from '../models/environment'; -import { appConfigs } from '../presets'; -import { resolveInstanceKeys } from '../presets/envs'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; -import { withRetry } from '../testUtils/retryableClerkClient'; -import { createUserService } from '../testUtils/usersService'; +import { environmentConfig } from '../../models/environment'; +import { appConfigs } from '../../presets'; +import { resolveInstanceKeys } from '../../presets/envs'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; +import { withRetry } from '../../testUtils/retryableClerkClient'; +import { createUserService } from '../../testUtils/usersService'; const grantOAuthConsent = async (page: Page) => { const allowAccessButton = page.getByRole('button', { name: 'Allow' }); diff --git a/integration/tests/prefetch-ui.test.ts b/integration/tests/nextjs/prefetch-ui.test.ts similarity index 90% rename from integration/tests/prefetch-ui.test.ts rename to integration/tests/nextjs/prefetch-ui.test.ts index 33b0b6a6991..6973752d1f5 100644 --- a/integration/tests/prefetch-ui.test.ts +++ b/integration/tests/nextjs/prefetch-ui.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; test.describe('prefetchUI disabled @nextjs', () => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/protect-jwt-v2.test.ts b/integration/tests/nextjs/protect-jwt-v2.test.ts similarity index 98% rename from integration/tests/protect-jwt-v2.test.ts rename to integration/tests/nextjs/protect-jwt-v2.test.ts index 3d2f1d36bae..1a9d4034c1a 100644 --- a/integration/tests/protect-jwt-v2.test.ts +++ b/integration/tests/nextjs/protect-jwt-v2.test.ts @@ -1,9 +1,9 @@ import type { OrganizationMembershipRole } from '@clerk/backend'; import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withBillingJwtV2], diff --git a/integration/tests/protect.test.ts b/integration/tests/nextjs/protect.test.ts similarity index 97% rename from integration/tests/protect.test.ts rename to integration/tests/nextjs/protect.test.ts index a103546beb7..afa4718fb62 100644 --- a/integration/tests/protect.test.ts +++ b/integration/tests/nextjs/protect.test.ts @@ -1,9 +1,9 @@ import type { OrganizationMembershipRole } from '@clerk/backend'; import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withCustomRoles, appConfigs.envs.withBillingJwtV2], diff --git a/integration/tests/redirects.test.ts b/integration/tests/nextjs/redirects.test.ts similarity index 95% rename from integration/tests/redirects.test.ts rename to integration/tests/nextjs/redirects.test.ts index 90cd9ada1e2..8304340eec4 100644 --- a/integration/tests/redirects.test.ts +++ b/integration/tests/nextjs/redirects.test.ts @@ -1,8 +1,8 @@ import { test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('redirect props @nextjs', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/reverification.test.ts b/integration/tests/nextjs/reverification.test.ts similarity index 97% rename from integration/tests/reverification.test.ts rename to integration/tests/nextjs/reverification.test.ts index e84631bcc11..10a642f982e 100644 --- a/integration/tests/reverification.test.ts +++ b/integration/tests/nextjs/reverification.test.ts @@ -1,11 +1,11 @@ import type { OrganizationMembershipRole } from '@clerk/backend'; import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; -import { stringPhoneNumber } from '../testUtils/phoneUtils'; -import { fakerPhoneNumber } from '../testUtils/usersService'; +import { appConfigs } from '../../presets'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; +import { stringPhoneNumber } from '../../testUtils/phoneUtils'; +import { fakerPhoneNumber } from '../../testUtils/usersService'; const utils = [ 'action', diff --git a/integration/tests/session-tasks-eject-flow.test.ts b/integration/tests/nextjs/session-tasks-eject-flow.test.ts similarity index 93% rename from integration/tests/session-tasks-eject-flow.test.ts rename to integration/tests/nextjs/session-tasks-eject-flow.test.ts index bc7ef2baa1c..631a1d9677b 100644 --- a/integration/tests/session-tasks-eject-flow.test.ts +++ b/integration/tests/nextjs/session-tasks-eject-flow.test.ts @@ -1,9 +1,9 @@ import { test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; test.describe('session tasks eject flow @nextjs', () => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/session-tasks-multi-session.test.ts b/integration/tests/nextjs/session-tasks-multi-session.test.ts similarity index 95% rename from integration/tests/session-tasks-multi-session.test.ts rename to integration/tests/nextjs/session-tasks-multi-session.test.ts index 6a77bb5d99c..ad419f33d04 100644 --- a/integration/tests/session-tasks-multi-session.test.ts +++ b/integration/tests/nextjs/session-tasks-multi-session.test.ts @@ -1,8 +1,8 @@ import { test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withSessionTasks] })( 'session tasks multi-session flow @nextjs', diff --git a/integration/tests/session-tasks-setup-mfa.test.ts b/integration/tests/nextjs/session-tasks-setup-mfa.test.ts similarity index 97% rename from integration/tests/session-tasks-setup-mfa.test.ts rename to integration/tests/nextjs/session-tasks-setup-mfa.test.ts index af35b70d6de..96bfabe1bd1 100644 --- a/integration/tests/session-tasks-setup-mfa.test.ts +++ b/integration/tests/nextjs/session-tasks-setup-mfa.test.ts @@ -1,9 +1,9 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; -import { stringPhoneNumber } from '../testUtils/phoneUtils'; -import { fakerPhoneNumber } from '../testUtils/usersService'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; +import { stringPhoneNumber } from '../../testUtils/phoneUtils'; +import { fakerPhoneNumber } from '../../testUtils/usersService'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withSessionTasksSetupMfa] })( 'session tasks setup-mfa flow @nextjs', diff --git a/integration/tests/session-tasks-sign-in-reset-password.test.ts b/integration/tests/nextjs/session-tasks-sign-in-reset-password.test.ts similarity index 96% rename from integration/tests/session-tasks-sign-in-reset-password.test.ts rename to integration/tests/nextjs/session-tasks-sign-in-reset-password.test.ts index 4322773bc43..72de5af5e26 100644 --- a/integration/tests/session-tasks-sign-in-reset-password.test.ts +++ b/integration/tests/nextjs/session-tasks-sign-in-reset-password.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { hash } from '../models/helpers'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { hash } from '../../models/helpers'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withSessionTasksResetPassword] })( 'session tasks after sign-in reset password flow @nextjs', diff --git a/integration/tests/session-tasks-sign-in.test.ts b/integration/tests/nextjs/session-tasks-sign-in.test.ts similarity index 91% rename from integration/tests/session-tasks-sign-in.test.ts rename to integration/tests/nextjs/session-tasks-sign-in.test.ts index abb7d623b54..80065de42f8 100644 --- a/integration/tests/session-tasks-sign-in.test.ts +++ b/integration/tests/nextjs/session-tasks-sign-in.test.ts @@ -1,12 +1,12 @@ import { createClerkClient } from '@clerk/backend'; import { test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { resolveInstanceKeys } from '../presets/envs'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; -import { withRetry } from '../testUtils/retryableClerkClient'; -import { createUserService } from '../testUtils/usersService'; +import { appConfigs } from '../../presets'; +import { resolveInstanceKeys } from '../../presets/envs'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; +import { withRetry } from '../../testUtils/retryableClerkClient'; +import { createUserService } from '../../testUtils/usersService'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withSessionTasks] })( 'session tasks after sign-in flow @nextjs', diff --git a/integration/tests/session-tasks-sign-up.test.ts b/integration/tests/nextjs/session-tasks-sign-up.test.ts similarity index 90% rename from integration/tests/session-tasks-sign-up.test.ts rename to integration/tests/nextjs/session-tasks-sign-up.test.ts index 94146b53f5c..726acf88b22 100644 --- a/integration/tests/session-tasks-sign-up.test.ts +++ b/integration/tests/nextjs/session-tasks-sign-up.test.ts @@ -1,13 +1,13 @@ import { createClerkClient } from '@clerk/backend'; import { expect, test } from '@playwright/test'; -import { environmentConfig } from '../models/environment'; -import { appConfigs } from '../presets'; -import { resolveInstanceKeys } from '../presets/envs'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; -import { withRetry } from '../testUtils/retryableClerkClient'; -import { createUserService } from '../testUtils/usersService'; +import { environmentConfig } from '../../models/environment'; +import { appConfigs } from '../../presets'; +import { resolveInstanceKeys } from '../../presets/envs'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; +import { withRetry } from '../../testUtils/retryableClerkClient'; +import { createUserService } from '../../testUtils/usersService'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withSessionTasks] })( 'session tasks after sign-up flow @nextjs', diff --git a/integration/tests/shared-ui-variant.test.ts b/integration/tests/nextjs/shared-ui-variant.test.ts similarity index 92% rename from integration/tests/shared-ui-variant.test.ts rename to integration/tests/nextjs/shared-ui-variant.test.ts index 3ca6641f855..c1c01a4170a 100644 --- a/integration/tests/shared-ui-variant.test.ts +++ b/integration/tests/nextjs/shared-ui-variant.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withSharedUIVariant] })( 'shared React variant @nextjs', diff --git a/integration/tests/sign-in-or-up-component.test.ts b/integration/tests/nextjs/sign-in-or-up-component.test.ts similarity index 83% rename from integration/tests/sign-in-or-up-component.test.ts rename to integration/tests/nextjs/sign-in-or-up-component.test.ts index aaeb4a7a01d..889c6df81e5 100644 --- a/integration/tests/sign-in-or-up-component.test.ts +++ b/integration/tests/nextjs/sign-in-or-up-component.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { createTestUtils } from '../../testUtils'; test.describe('sign-in-or-up component initialization flow @nextjs', () => { test.describe.configure({ mode: 'parallel' }); diff --git a/integration/tests/sign-in-or-up-flow.test.ts b/integration/tests/nextjs/sign-in-or-up-flow.test.ts similarity index 99% rename from integration/tests/sign-in-or-up-flow.test.ts rename to integration/tests/nextjs/sign-in-or-up-flow.test.ts index 5d1e7dde6b0..31c6f7b1e76 100644 --- a/integration/tests/sign-in-or-up-flow.test.ts +++ b/integration/tests/nextjs/sign-in-or-up-flow.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, type FakeUser, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import { createTestUtils, type FakeUser, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withSignInOrUpFlow] })('sign-in-or-up flow @nextjs', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/sign-in-or-up-restricted-mode.test.ts b/integration/tests/nextjs/sign-in-or-up-restricted-mode.test.ts similarity index 85% rename from integration/tests/sign-in-or-up-restricted-mode.test.ts rename to integration/tests/nextjs/sign-in-or-up-restricted-mode.test.ts index 42fefc92f31..641d924cf7a 100644 --- a/integration/tests/sign-in-or-up-restricted-mode.test.ts +++ b/integration/tests/nextjs/sign-in-or-up-restricted-mode.test.ts @@ -1,9 +1,9 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; test.describe('sign-in-or-up restricted mode @nextjs', () => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/testing-token.test.ts b/integration/tests/nextjs/testing-token.test.ts similarity index 99% rename from integration/tests/testing-token.test.ts rename to integration/tests/nextjs/testing-token.test.ts index ca18fe85a82..be92ff33446 100644 --- a/integration/tests/testing-token.test.ts +++ b/integration/tests/nextjs/testing-token.test.ts @@ -4,7 +4,7 @@ import type { AddressInfo } from 'node:net'; import { expect, type Page, test } from '@playwright/test'; -import { setupTestingTokens } from '../testUtils/setupTestingTokens'; +import { setupTestingTokens } from '../../testUtils/setupTestingTokens'; test.describe('OAuth testing tokens @nextjs', () => { let provider: Server; diff --git a/integration/tests/transitions.test.ts b/integration/tests/nextjs/transitions.test.ts similarity index 98% rename from integration/tests/transitions.test.ts rename to integration/tests/nextjs/transitions.test.ts index a80b3d8706c..27b0856b2bd 100644 --- a/integration/tests/transitions.test.ts +++ b/integration/tests/nextjs/transitions.test.ts @@ -2,9 +2,9 @@ import { parsePublishableKey } from '@clerk/shared/keys'; import { clerkSetup } from '@clerk/testing/playwright'; import { test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; /* These tests try to verify some existing transition behaviors. They are not comprehensive, and do not necessarily diff --git a/integration/tests/transitive-state.test.ts b/integration/tests/nextjs/transitive-state.test.ts similarity index 98% rename from integration/tests/transitive-state.test.ts rename to integration/tests/nextjs/transitive-state.test.ts index 1026d593476..5f4e0d92fb5 100644 --- a/integration/tests/transitive-state.test.ts +++ b/integration/tests/nextjs/transitive-state.test.ts @@ -2,9 +2,9 @@ import { parsePublishableKey } from '@clerk/shared/keys'; import { clerkSetup } from '@clerk/testing/playwright'; import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeOrganization, FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeOrganization, FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; /* These tests verify that useAuth emits the correct transitive state sequence when switching diff --git a/integration/tests/unsafeMetadata.test.ts b/integration/tests/nextjs/unsafeMetadata.test.ts similarity index 98% rename from integration/tests/unsafeMetadata.test.ts rename to integration/tests/nextjs/unsafeMetadata.test.ts index 72e2770b5ab..6c573842f8d 100644 --- a/integration/tests/unsafeMetadata.test.ts +++ b/integration/tests/nextjs/unsafeMetadata.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('unsafeMetadata @nextjs', ({ app }) => { test.describe.configure({ mode: 'parallel' }); diff --git a/integration/tests/middleware-placement.test.ts b/integration/tests/quickstart/middleware-placement.test.ts similarity index 96% rename from integration/tests/middleware-placement.test.ts rename to integration/tests/quickstart/middleware-placement.test.ts index 31db473590b..f4357e54309 100644 --- a/integration/tests/middleware-placement.test.ts +++ b/integration/tests/quickstart/middleware-placement.test.ts @@ -1,11 +1,11 @@ import { expect, test } from '@playwright/test'; import path from 'path'; -import type { Application } from '../models/application'; -import { stateFile } from '../models/stateFile'; -import { appConfigs } from '../presets'; -import { fs } from '../scripts'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { stateFile } from '../../models/stateFile'; +import { appConfigs } from '../../presets'; +import { fs } from '../../scripts'; +import { createTestUtils } from '../../testUtils'; function parseSemverMajor(range?: string): number | undefined { if (!range) { diff --git a/integration/tests/next-quickstart-keyless.test.ts b/integration/tests/quickstart/next-quickstart-keyless.test.ts similarity index 89% rename from integration/tests/next-quickstart-keyless.test.ts rename to integration/tests/quickstart/next-quickstart-keyless.test.ts index ef9df6cf772..7dbd994c73c 100644 --- a/integration/tests/next-quickstart-keyless.test.ts +++ b/integration/tests/quickstart/next-quickstart-keyless.test.ts @@ -2,11 +2,11 @@ import * as path from 'node:path'; import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { fs } from '../scripts'; -import { createTestUtils } from '../testUtils'; -import { mockClaimedInstanceEnvironmentCall } from '../testUtils/keylessHelpers'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { fs } from '../../scripts'; +import { createTestUtils } from '../../testUtils'; +import { mockClaimedInstanceEnvironmentCall } from '../../testUtils/keylessHelpers'; const commonSetup = appConfigs.next.appRouterQuickstart.clone(); diff --git a/integration/tests/next-quickstart.test.ts b/integration/tests/quickstart/next-quickstart.test.ts similarity index 95% rename from integration/tests/next-quickstart.test.ts rename to integration/tests/quickstart/next-quickstart.test.ts index 4101f47cfff..3173343f571 100644 --- a/integration/tests/next-quickstart.test.ts +++ b/integration/tests/quickstart/next-quickstart.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodesQuickstart] })('nextjs @quickstart', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/snapshots/appearance.test.ts-snapshots/appearance-prop-all-clerk-themes-render-1-chrome-darwin.png b/integration/tests/snapshots/unscheduled/appearance.test.ts-snapshots/appearance-prop-all-clerk-themes-render-1-chrome-darwin.png similarity index 100% rename from integration/tests/snapshots/appearance.test.ts-snapshots/appearance-prop-all-clerk-themes-render-1-chrome-darwin.png rename to integration/tests/snapshots/unscheduled/appearance.test.ts-snapshots/appearance-prop-all-clerk-themes-render-1-chrome-darwin.png diff --git a/integration/tests/appearance.test.ts b/integration/tests/unscheduled/appearance.test.ts similarity index 91% rename from integration/tests/appearance.test.ts rename to integration/tests/unscheduled/appearance.test.ts index 1773312833d..047c077ce90 100644 --- a/integration/tests/appearance.test.ts +++ b/integration/tests/unscheduled/appearance.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { createTestUtils } from '../../testUtils'; test.describe('appearance prop', () => { test.describe.configure({ mode: 'parallel' }); diff --git a/integration/tests/bundled-ui.test.ts b/integration/tests/unscheduled/bundled-ui.test.ts similarity index 96% rename from integration/tests/bundled-ui.test.ts rename to integration/tests/unscheduled/bundled-ui.test.ts index 7b11fa6d8f7..3157e10e880 100644 --- a/integration/tests/bundled-ui.test.ts +++ b/integration/tests/unscheduled/bundled-ui.test.ts @@ -1,8 +1,8 @@ import { expect, test } from '@playwright/test'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withPattern: ['next.appRouterBundledUI.*'] })( 'bundled UI smoke tests @bundled-ui', diff --git a/integration/tests/db-jwt.test.ts b/integration/tests/unscheduled/db-jwt.test.ts similarity index 94% rename from integration/tests/db-jwt.test.ts rename to integration/tests/unscheduled/db-jwt.test.ts index d6ced6b2e11..ec4bdbcdf46 100644 --- a/integration/tests/db-jwt.test.ts +++ b/integration/tests/unscheduled/db-jwt.test.ts @@ -1,9 +1,9 @@ import { test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; test.describe('Dev browser test', () => { const configs = []; diff --git a/integration/tests/email-link.test.ts b/integration/tests/unscheduled/email-link.test.ts similarity index 96% rename from integration/tests/email-link.test.ts rename to integration/tests/unscheduled/email-link.test.ts index 76001647a6d..c6014f86589 100644 --- a/integration/tests/email-link.test.ts +++ b/integration/tests/unscheduled/email-link.test.ts @@ -1,9 +1,9 @@ import type { Browser, BrowserContext, Page } from '@playwright/test'; import { test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import { createTestUtils } from '../../testUtils'; test.describe('sign up and sign in using email link', () => { const configs = []; diff --git a/integration/tests/restricted-mode.test.ts b/integration/tests/unscheduled/restricted-mode.test.ts similarity index 94% rename from integration/tests/restricted-mode.test.ts rename to integration/tests/unscheduled/restricted-mode.test.ts index 92dae0dbbfe..108120ed501 100644 --- a/integration/tests/restricted-mode.test.ts +++ b/integration/tests/unscheduled/restricted-mode.test.ts @@ -1,9 +1,9 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; test.describe('Sign-up restricted mode', () => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/sign-in-or-up-email-links-flow.test.ts b/integration/tests/unscheduled/sign-in-or-up-email-links-flow.test.ts similarity index 94% rename from integration/tests/sign-in-or-up-email-links-flow.test.ts rename to integration/tests/unscheduled/sign-in-or-up-email-links-flow.test.ts index 77a856f20c9..1515f21c848 100644 --- a/integration/tests/sign-in-or-up-email-links-flow.test.ts +++ b/integration/tests/unscheduled/sign-in-or-up-email-links-flow.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils, testAgainstRunningApps } from '../testUtils'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils, testAgainstRunningApps } from '../../testUtils'; testAgainstRunningApps({ withEnv: [] })('sign-in-or-up email links flow', ({ app }) => { test.describe.configure({ mode: 'serial' }); diff --git a/integration/tests/waitlist-mode.test.ts b/integration/tests/unscheduled/waitlist-mode.test.ts similarity index 96% rename from integration/tests/waitlist-mode.test.ts rename to integration/tests/unscheduled/waitlist-mode.test.ts index 1961e0ea449..15024960a19 100644 --- a/integration/tests/waitlist-mode.test.ts +++ b/integration/tests/unscheduled/waitlist-mode.test.ts @@ -1,9 +1,9 @@ import { expect, test } from '@playwright/test'; -import type { Application } from '../models/application'; -import { appConfigs } from '../presets'; -import type { FakeUser } from '../testUtils'; -import { createTestUtils } from '../testUtils'; +import type { Application } from '../../models/application'; +import { appConfigs } from '../../presets'; +import type { FakeUser } from '../../testUtils'; +import { createTestUtils } from '../../testUtils'; test.describe('Waitlist mode', () => { test.describe.configure({ mode: 'parallel' }); diff --git a/package.json b/package.json index 5d6f89232fc..2b421cce5ab 100644 --- a/package.json +++ b/package.json @@ -38,10 +38,10 @@ "test:cache:clear": "FORCE_COLOR=1 turbo test:cache:clear --continue --concurrency=${TURBO_CONCURRENCY:-80%}", "test:integration:ap-flows": "E2E_DEBUG=1 pnpm test:integration:base --grep @ap-flows", "test:integration:astro": "E2E_APP_ID=astro.* pnpm test:integration:base --grep @astro", - "test:integration:base": "pnpm playwright test --config integration/playwright.config.ts", + "test:integration:base": "node integration/scripts/run-integration.mjs pnpm playwright test --config integration/playwright.config.ts", "test:integration:billing": "E2E_APP_ID=withBillingJwtV2.* pnpm test:integration:base --grep @billing", "test:integration:cache-components": "E2E_APP_ID=next.cacheComponents pnpm test:integration:base --grep @cache-components", - "test:integration:chrome-extension": "pnpm playwright test --config integration/playwright.chrome-extension.config.ts", + "test:integration:chrome-extension": "node integration/scripts/run-integration.mjs pnpm playwright test --config integration/playwright.chrome-extension.config.ts", "test:integration:cleanup": "pnpm playwright test --config integration/playwright.cleanup.config.ts", "test:integration:custom": "pnpm test:integration:base --grep @custom", "test:integration:deployment:nextjs": "pnpm playwright test --config integration/playwright.deployments.config.ts", @@ -78,9 +78,6 @@ "@arethetypeswrong/cli": "0.18.3", "@changesets/cli": "^2.31.1", "@changesets/get-github-info": "^0.8.0", - "@clerk/backend": "workspace:*", - "@clerk/shared": "workspace:*", - "@clerk/testing": "workspace:*", "@commitlint/cli": "^20.5.2", "@commitlint/config-conventional": "^20.5.0", "@eslint-community/eslint-plugin-eslint-comments": "4.8.1", diff --git a/packages/clerk-js/turbo.json b/packages/clerk-js/turbo.json index 5d5f376289a..8f07a93e244 100644 --- a/packages/clerk-js/turbo.json +++ b/packages/clerk-js/turbo.json @@ -20,6 +20,25 @@ "!node_modules/**" ] }, + "build:inputs": { + "inputs": [ + "*.d.ts", + "src/**", + "tsconfig.json", + "tsconfig.declarations.json", + "rspack.config.mjs", + + "!**/*.test.*", + "!**/test/**", + "!**/tests/**", + "!**/__tests__/**", + "!**/__mocks__/**", + "!**/__snapshots__/**", + "!coverage/**", + "!examples/**", + "!node_modules/**" + ] + }, "build:sandbox": { "dependsOn": ["^build", "@clerk/localizations#build"], "inputs": ["sandbox/**"], @@ -39,9 +58,9 @@ "tsconfig.json", "tsconfig.*.json", "tsup.config.ts", + "vitest.*.mts", "webpack.config.js", - "!**/__snapshots__/**", "!coverage/**", "!examples/**", "!node_modules/**" diff --git a/packages/expo/turbo.json b/packages/expo/turbo.json index de856a782d7..da404316192 100644 --- a/packages/expo/turbo.json +++ b/packages/expo/turbo.json @@ -21,7 +21,6 @@ "$TURBO_ROOT$/packages/expo-native-components/android/**", "$TURBO_ROOT$/packages/expo-native-components/ios/**", "!$TURBO_ROOT$/packages/expo-*/android/build/**", - "!**/__snapshots__/**", "!CHANGELOG.md", "!coverage/**", "!dist/**", diff --git a/packages/express/turbo.json b/packages/express/turbo.json index 4379d6c1c35..8c8f810a745 100644 --- a/packages/express/turbo.json +++ b/packages/express/turbo.json @@ -14,6 +14,20 @@ "!coverage/**", "!node_modules/**" ] + }, + "build:inputs": { + "inputs": [ + "*.d.ts", + "**/package.json", + "src/**", + "tsconfig.json", + "tsup.config.ts", + + "!**/__tests__/**", + "!**/__snapshots__/**", + "!coverage/**", + "!node_modules/**" + ] } } } diff --git a/packages/mosaic/turbo.json b/packages/mosaic/turbo.json index 65219661ea9..2109cb9f2cf 100644 --- a/packages/mosaic/turbo.json +++ b/packages/mosaic/turbo.json @@ -23,6 +23,28 @@ "!node_modules/**" ], "outputs": ["dist/**"] + }, + "build:inputs": { + "inputs": [ + "package.json", + "*.d.ts", + "src/**", + "tsconfig.json", + "tsconfig.base.json", + "tsdown.config.mts", + "tsdown.css.config.mts", + "stylex-lightningcss.config.mjs", + "scripts/**", + "!**/*.test.*", + "!**/test/**", + "!**/tests/**", + "!**/__tests__/**", + "!**/__mocks__/**", + "!**/__snapshots__/**", + "!coverage/**", + "!examples/**", + "!node_modules/**" + ] } } } diff --git a/packages/react/turbo.json b/packages/react/turbo.json index 71a56e92f14..cf090c6aa32 100644 --- a/packages/react/turbo.json +++ b/packages/react/turbo.json @@ -12,7 +12,6 @@ "tsconfig.json", "tsconfig.*.json", "tsup.config.ts", - "!**/__snapshots__/**", "!CHANGELOG.md", "!coverage/**", "!dist/**", diff --git a/packages/ui/turbo.json b/packages/ui/turbo.json index dc2b9940748..c44707a73b3 100644 --- a/packages/ui/turbo.json +++ b/packages/ui/turbo.json @@ -28,6 +28,27 @@ ], "outputs": ["*/package.json", "dist/**"] }, + "build:inputs": { + "inputs": [ + "*.d.ts", + "src/**", + "tsconfig.json", + "tsconfig.base.json", + "tsconfig.src.json", + "rspack.config.js", + "tsdown.config.mts", + + "!**/*.test.*", + "!**/test/**", + "!**/tests/**", + "!**/__tests__/**", + "!**/__mocks__/**", + "!**/__snapshots__/**", + "!coverage/**", + "!examples/**", + "!node_modules/**" + ] + }, "test": { "inputs": [ "*.d.ts", @@ -38,7 +59,6 @@ "rspack.config.js", "vitest.*.mts", - "!**/__snapshots__/**", "!coverage/**", "!examples/**", "!node_modules/**" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5b4c50c29a..18e999141f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -125,15 +125,6 @@ importers: '@changesets/get-github-info': specifier: ^0.8.0 version: 0.8.0 - '@clerk/backend': - specifier: workspace:* - version: link:packages/backend - '@clerk/shared': - specifier: workspace:* - version: link:packages/shared - '@clerk/testing': - specifier: workspace:* - version: link:packages/testing '@commitlint/cli': specifier: ^20.5.2 version: 20.5.3(@types/node@22.20.1)(conventional-commits-parser@6.4.0)(typescript@6.0.3) @@ -363,6 +354,18 @@ importers: specifier: catalog:repo version: 8.8.5 + integration: + devDependencies: + '@clerk/backend': + specifier: workspace:* + version: link:../packages/backend + '@clerk/shared': + specifier: workspace:* + version: link:../packages/shared + '@clerk/testing': + specifier: workspace:* + version: link:../packages/testing + packages/astro: dependencies: '@clerk/backend': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 48837676c4b..fb268bf10d9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,7 @@ packages: - packages/* - packages/electron-passkeys/npm/* + - integration catalogs: peer-expo: diff --git a/scripts/integration-deps.mjs b/scripts/integration-deps.mjs new file mode 100644 index 00000000000..cc42b9528e6 --- /dev/null +++ b/scripts/integration-deps.mjs @@ -0,0 +1,228 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +export const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); + +const TASK_PREFIX = '//#test:integration:'; +const TESTS = path.join(root, 'integration/tests'); +const SHARED_INPUTS = [ + 'integration/*', + 'integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**', + 'integration/tests/*', + 'integration/tests/snapshots/**', +]; +const PRESET_GROUPS = { + astro: 'astro', + chromeExtension: 'chrome-extension', + customFlows: 'custom-flows', + electron: 'electron', + expo: 'expo', + express: 'express', + fastify: 'fastify', + hono: 'hono', + next: 'next', + nuxt: 'nuxt', + react: 'react', + reactRouter: 'react-router', + tanstack: 'tanstack', + vue: 'vue', +}; + +const read = file => fs.readFileSync(file, 'utf8'); +const readJson = file => JSON.parse(read(file)); + +const HARNESS_PACKAGES = [ + '@clerk/clerk-js', + '@clerk/ui', + ...Object.keys(readJson(path.join(root, 'integration/package.json')).devDependencies ?? {}), +].sort(); + +export const integrationSuites = () => + Object.keys(readJson(path.join(root, 'turbo.json')).tasks) + .filter(task => task.startsWith(TASK_PREFIX)) + .map(task => task.slice(TASK_PREFIX.length)); + +export const scriptFor = suite => { + const scripts = readJson(path.join(root, 'package.json')).scripts; + const base = suite.replace(/:(canary|staging)$/, ''); + return scripts[`test:integration:${base}`] ?? scripts[`test:integration:${base}:disabled`]; +}; + +function* walk(dir) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const full = path.join(dir, entry.name); + if (entry.isDirectory()) { + yield* walk(full); + } else { + yield full; + } + } +} + +const workspaceGraph = () => { + const graph = new Map(); + for (const dir of fs.readdirSync(path.join(root, 'packages'))) { + const manifestPath = path.join(root, 'packages', dir, 'package.json'); + if (!fs.existsSync(manifestPath)) { + continue; + } + const manifest = readJson(manifestPath); + const deps = { ...manifest.dependencies, ...manifest.devDependencies, ...manifest.optionalDependencies }; + graph.set( + manifest.name, + Object.keys(deps).filter(name => name.startsWith('@clerk/')), + ); + } + return graph; +}; + +const transitiveDeps = (graph, name) => { + const seen = new Set(); + const queue = [...(graph.get(name) ?? [])]; + while (queue.length) { + const next = queue.pop(); + if (!seen.has(next) && graph.has(next)) { + seen.add(next); + queue.push(...graph.get(next)); + } + } + return seen; +}; + +const withoutImplied = (graph, names) => + names.filter( + name => + HARNESS_PACKAGES.includes(name) || !names.some(other => other !== name && transitiveDeps(graph, other).has(name)), + ); + +const INTEGRATION = path.join(root, 'integration'); + +const resolveImport = (from, specifier) => { + const target = path.resolve(path.dirname(from), specifier); + return [target, `${target}.ts`, `${target}.tsx`, path.join(target, 'index.ts')].find( + candidate => fs.existsSync(candidate) && fs.statSync(candidate).isFile(), + ); +}; + +const followImports = seeds => { + const sources = new Map(seeds.map(file => [file, read(file)])); + const external = new Set(); + const queue = [...sources.keys()]; + while (queue.length) { + const file = queue.pop(); + for (const match of sources.get(file).matchAll(/from '(\.{1,2}\/[^']+)'/g)) { + const resolved = resolveImport(file, match[1]); + if (!resolved || sources.has(resolved) || external.has(resolved)) { + continue; + } + if (resolved.startsWith(TESTS + path.sep)) { + sources.set(resolved, read(resolved)); + queue.push(resolved); + } else if (!resolved.startsWith(INTEGRATION + path.sep) && resolved.startsWith(root + path.sep)) { + external.add(resolved); + } + } + } + return { sources, external: [...external].map(file => path.relative(root, file)).sort() }; +}; + +const globToRegExp = glob => + new RegExp( + `^${glob + .split('*') + .map(part => part.replace(/[\\^$.+?()[\]{}|]/g, '\\$&')) + .join('.*')}$`, + ); + +const braceGlob = (prefix, names) => + names.length === 1 ? `${prefix}/${names[0]}/**` : `${prefix}/{${names.join(',')}}/**`; + +const loadAppConfigs = async () => { + const configs = new Map(); + for (const [group, file] of Object.entries(PRESET_GROUPS)) { + const module = await import(path.join(root, 'integration/presets', `${file}.ts`)); + for (const [name, config] of Object.entries(Object.values(module)[0])) { + configs.set(`${group}.${name}`, { + packages: config.pkglabDependencies, + template: config.template ? path.relative(root, config.template) : undefined, + }); + } + } + return configs; +}; + +const longRunningAppConfigs = () => { + const source = read(path.join(root, 'integration/presets/longRunningApps.ts')); + return [...source.matchAll(/id: '([^']+)',\s*config: ([a-zA-Z]+)\.([a-zA-Z0-9]+)/g)].map(match => ({ + id: match[1], + config: `${match[2]}.${match[3]}`, + })); +}; + +export const deriveIntegrationTasks = async () => { + const appConfigs = await loadAppConfigs(); + const longRunning = longRunningAppConfigs(); + const graph = workspaceGraph(); + const testFiles = [...walk(TESTS)].filter(file => file.endsWith('.test.ts')); + + const tasks = new Map(); + for (const suite of integrationSuites()) { + const script = scriptFor(suite) ?? ''; + const tag = script.match(/--grep @([a-z-]+)/)?.[1]; + const base = suite.replace(/:(canary|staging)$/, ''); + const tagged = tag + ? testFiles.filter(file => new RegExp(`@${tag}(?![a-z-])`).test(read(file))) + : testFiles.filter(file => file.startsWith(path.join(TESTS, base) + path.sep)); + const { sources, external } = followImports(tagged); + + const patterns = script.match(/E2E_APP_ID=([^ ]+)/)?.[1].split(',') ?? []; + const configNames = new Set(); + for (const source of sources.values()) { + for (const match of source.matchAll(/appConfigs\.([a-zA-Z]+)\.([a-zA-Z0-9]+)/g)) { + if (PRESET_GROUPS[match[1]]) { + configNames.add(`${match[1]}.${match[2]}`); + } + } + for (const match of source.matchAll(/(?:withPattern:|getByPattern\()\s*\[([^\]]*)\]/g)) { + patterns.push(...[...match[1].matchAll(/'([^']+)'/g)].map(id => id[1])); + } + } + for (const pattern of patterns) { + const matches = globToRegExp(pattern); + longRunning.filter(app => matches.test(app.id)).forEach(app => configNames.add(app.config)); + } + + const packages = new Set(HARNESS_PACKAGES); + const templates = new Set(); + for (const name of configNames) { + const config = appConfigs.get(name); + if (!config) { + throw new Error(`${suite}: tests reference unknown app config ${name}`); + } + config.packages.filter(pkg => graph.has(pkg)).forEach(pkg => packages.add(pkg)); + if (config.template) { + templates.add(path.basename(config.template)); + } + } + const testDirs = new Set( + [...sources.keys()] + .map(file => path.relative(TESTS, file).split(path.sep)[0]) + .filter(segment => !segment.includes('.') && segment !== 'snapshots'), + ); + + tasks.set(suite, { + dependsOn: withoutImplied(graph, [...packages].sort()).map(pkg => `${pkg}#build:inputs`), + inputs: [ + ...SHARED_INPUTS, + ...(testDirs.size ? [braceGlob('integration/tests', [...testDirs].sort())] : []), + 'integration/templates/*', + ...(templates.size ? [braceGlob('integration/templates', [...templates].sort())] : []), + ...external, + ], + external, + configs: [...configNames].sort(), + }); + } + return tasks; +}; diff --git a/scripts/integration-deps.test.mjs b/scripts/integration-deps.test.mjs new file mode 100644 index 00000000000..e18717374a1 --- /dev/null +++ b/scripts/integration-deps.test.mjs @@ -0,0 +1,98 @@ +import { spawnSync } from 'node:child_process'; +import { existsSync, readdirSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; + +import { describe, expect, test } from 'vitest'; + +import { deriveIntegrationTasks, integrationSuites, root, scriptFor } from './integration-deps.mjs'; + +const turbo = JSON.parse(readFileSync(join(root, 'turbo.json'), 'utf8')); +const derived = await deriveIntegrationTasks(); + +const ciMatrixSuites = () => { + const workflow = readFileSync(join(root, '.github/workflows/ci.yml'), 'utf8'); + const job = workflow.slice(workflow.indexOf('\n integration-tests:\n')); + const matrix = job.slice(job.indexOf('matrix:'), job.indexOf('\n steps:')); + const listed = [...matrix.matchAll(/test-name:\s*\[([^\]]*)\]/gs)].flatMap(m => + [...m[1].matchAll(/'([^']+)'/g)].map(q => q[1]), + ); + const included = [...matrix.matchAll(/- test-name: '([^']+)'/g)].map(m => m[1]); + return [...new Set([...listed, ...included])]; +}; + +describe('integration suite tasks in turbo.json', () => { + test.each(integrationSuites())('%s has a package.json script', suite => { + expect(scriptFor(suite), `test:integration:${suite} has no matching script in package.json`).toBeDefined(); + }); + + test.each(ciMatrixSuites())('%s in the ci.yml matrix has a turbo task', suite => { + expect( + turbo.tasks[`//#test:integration:${suite}`], + `ci.yml runs ${suite} but turbo.json has no task for it`, + ).toBeDefined(); + }); + + test('the root package.json depends on no workspace packages', () => { + const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')); + const deps = { ...manifest.dependencies, ...manifest.devDependencies, ...manifest.optionalDependencies }; + const workspace = Object.entries(deps) + .filter(([, version]) => version.startsWith('workspace:')) + .map(([name]) => name); + expect( + workspace, + 'turbo folds every file of a root workspace dependency into the global hash, so any edit to it reruns every task. Declare it in integration/package.json instead.', + ).toEqual([]); + }); + + test('build:inputs hashes the same files as build without running anything', () => { + expect(turbo.tasks['build:inputs']).toEqual({ dependsOn: ['^build:inputs'], inputs: turbo.tasks.build.inputs }); + const packages = readdirSync(join(root, 'packages')).filter(dir => + existsSync(join(root, 'packages', dir, 'package.json')), + ); + for (const dir of packages) { + const { scripts = {} } = JSON.parse(readFileSync(join(root, 'packages', dir, 'package.json'), 'utf8')); + expect(scripts['build:inputs'], `packages/${dir} defines a build:inputs script`).toBeUndefined(); + const packageTurbo = join(root, 'packages', dir, 'turbo.json'); + if (!existsSync(packageTurbo)) { + continue; + } + const { tasks = {} } = JSON.parse(readFileSync(packageTurbo, 'utf8')); + expect( + tasks['build:inputs']?.inputs, + `packages/${dir}/turbo.json overrides build inputs, so its build:inputs must list the same inputs`, + ).toEqual(tasks.build?.inputs); + } + }); + + test('turbo hashes the package source each suite imports directly', () => { + const imported = [...derived.entries()].filter(([, task]) => task.external.length); + expect(imported.map(([suite]) => suite)).toContain('chrome-extension'); + const result = spawnSync( + 'pnpm', + ['turbo', 'run', ...imported.map(([suite]) => `test:integration:${suite}`), '--dry=json'], + { + cwd: root, + encoding: 'utf8', + }, + ); + expect(result.status, result.stderr).toBe(0); + const dry = JSON.parse(result.stdout.slice(result.stdout.search(/^\{/m))); + for (const [suite, task] of imported) { + const hashed = Object.keys(dry.tasks.find(t => t.taskId === `//#test:integration:${suite}`).inputs); + for (const file of task.external) { + expect(hashed, `${file} is imported by the ${suite} suite but turbo does not hash it`).toContain(file); + } + } + }, 120_000); + + test.each([...derived.entries()])('%s depends on the packages its apps install', (suite, expected) => { + const task = turbo.tasks[`//#test:integration:${suite}`]; + const actual = { dependsOn: task.dependsOn, inputs: task.inputs }; + const hint = [ + `turbo.json task //#test:integration:${suite} is out of sync with the apps its tests boot (${expected.configs.join(', ')}).`, + 'Replace its dependsOn and inputs with:', + JSON.stringify({ dependsOn: expected.dependsOn, inputs: expected.inputs }, null, 2), + ].join('\n'); + expect(actual, hint).toEqual({ dependsOn: expected.dependsOn, inputs: expected.inputs }); + }); +}); diff --git a/scripts/integration-hash-matrix.mjs b/scripts/integration-hash-matrix.mjs new file mode 100644 index 00000000000..d95dffc5049 --- /dev/null +++ b/scripts/integration-hash-matrix.mjs @@ -0,0 +1,77 @@ +import { spawnSync } from 'node:child_process'; +import { appendFileSync, existsSync, readFileSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); + +const scenarios = [ + ['upgrade', 'packages/upgrade/src/cli.js'], + ['shared', 'packages/shared/src/index.ts'], + ['shared test', 'packages/shared/src/types/signUpTimezone.type.test.ts'], + ['expo', 'packages/expo/src/index.ts'], + ['mosaic', 'packages/mosaic/src/global.d.ts'], + ['test file', 'integration/tests/generic/sign-in-flow.test.ts'], + ['vue test', 'integration/tests/vue/components.test.ts'], + ['expo-native', 'integration/expo-native/README.md'], + ['js fixture', 'packages/clerk-js/src/test/fixtures.ts'], +]; + +const turbo = JSON.parse(readFileSync(resolve(root, 'turbo.json'), 'utf8')); +const suites = Object.keys(turbo.tasks) + .filter(task => task.startsWith('//#test:integration:')) + .map(task => task.slice('//#'.length)); + +function hashes() { + const result = spawnSync('pnpm', ['turbo', 'run', ...suites, '--dry=json'], { cwd: root, encoding: 'utf8' }); + if (result.status !== 0) { + throw new Error(result.stderr); + } + const json = JSON.parse(result.stdout.slice(result.stdout.search(/^\{/m))); + return new Map( + json.tasks + .filter(task => task.taskId.startsWith('//#test:integration:')) + .map(task => [ + task.taskId.slice('//#test:integration:'.length), + { hash: task.hash, inputs: Object.keys(task.inputs).length }, + ]), + ); +} + +function git(...args) { + const result = spawnSync('git', args, { cwd: root, encoding: 'utf8' }); + if (result.status !== 0) { + throw new Error(result.stderr); + } +} + +for (const [, file] of scenarios) { + if (!existsSync(resolve(root, file))) { + throw new Error(`${file} does not exist; update the scenarios list`); + } + const status = spawnSync('git', ['status', '--porcelain', '--', file], { cwd: root, encoding: 'utf8' }).stdout; + if (status.trim()) { + throw new Error(`${file} has local changes; commit or revert them before running the matrix`); + } +} + +const baseline = hashes(); +const columns = []; +for (const [label, file] of scenarios) { + appendFileSync(resolve(root, file), '\n'); + try { + columns.push([label, hashes()]); + } finally { + git('checkout', '--', file); + } +} + +const pad = (value, width) => String(value).padEnd(width); +console.log(`${pad('suite', 22)} ${pad('inputs', 6)} ${columns.map(([label]) => pad(label, 12)).join('')}`); +for (const suite of [...baseline.keys()].sort()) { + const cells = columns.map(([, result]) => + pad(result.get(suite).hash === baseline.get(suite).hash ? '.' : 'RERUN', 12), + ); + console.log(`${pad(suite, 22)} ${pad(baseline.get(suite).inputs, 6)} ${cells.join('')}`); +} +console.log('\n. = cache hash unchanged by that edit, RERUN = suite would run again'); diff --git a/scripts/run-integration.test.mjs b/scripts/run-integration.test.mjs new file mode 100644 index 00000000000..cf37d1c28ef --- /dev/null +++ b/scripts/run-integration.test.mjs @@ -0,0 +1,106 @@ +import { spawnSync } from 'node:child_process'; +import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join, resolve } from 'node:path'; + +import { describe, expect, test } from 'vitest'; + +const runner = resolve('integration/scripts/run-integration.mjs'); + +function run(setup, fail = '', env = {}) { + const dir = mkdtempSync(join(tmpdir(), 'run-integration-')); + const bin = join(dir, 'bin'); + mkdirSync(bin); + const command = `#!/usr/bin/env node\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst name = path.basename(process.argv[1]);\nconst args = process.argv.slice(2);\nfs.appendFileSync(process.env.COMMAND_LOG, JSON.stringify({ name, args, cwd: process.cwd(), turboForce: process.env.TURBO_FORCE, clerkSecret: process.env.CLERK_PLATFORM_API_KEY }) + '\\n');\nprocess.exit(process.env.FAIL_COMMAND === name || process.env.FAIL_COMMAND === name + ' ' + args.join(' ') ? 7 : 0);\n`; + for (const name of ['pnpm', 'pkglab', 'xvfb-run']) { + const file = join(bin, name); + writeFileSync(file, command, { mode: 0o755 }); + } + const output = join(dir, 'output'); + const log = join(dir, 'log'); + const result = spawnSync(process.execPath, [runner, 'pnpm', 'playwright', 'test', '--grep', '@case'], { + cwd: resolve('.'), + env: { + ...process.env, + PATH: `${bin}:${process.env.PATH}`, + COMMAND_LOG: log, + FAIL_COMMAND: fail, + GITHUB_OUTPUT: output, + E2E_CI_SETUP: setup, + E2E_APP_CLERK_JS_DIR: dir, + E2E_APP_CLERK_UI_DIR: dir, + TURBO_ARGS: '--concurrency=2 --output-logs=new-only', + TURBO_FORCE: 'true', + CLERK_PLATFORM_API_KEY: 'secret', + ...env, + }, + encoding: 'utf8', + }); + const calls = existsSync(log) ? readFileSync(log, 'utf8').trim().split('\n').filter(Boolean).map(JSON.parse) : []; + const marker = existsSync(output) ? readFileSync(output, 'utf8') : ''; + rmSync(dir, { recursive: true, force: true }); + return { result, calls, marker }; +} + +describe('CI integration runner', () => { + test('passes local test arguments through unchanged', () => { + const { result, calls, marker } = run(''); + expect(result.status).toBe(0); + expect(calls).toMatchObject([{ name: 'pnpm', args: ['playwright', 'test', '--grep', '@case'] }]); + expect(marker).toBe(''); + }); + + test('runs CI setup before Playwright and records that tests started', () => { + const { result, calls, marker } = run('generic'); + expect(result.status).toBe(0); + expect(calls.map(({ name, args }) => `${name} ${args.join(' ')}`)).toEqual([ + 'pnpm turbo build --concurrency=2 --output-logs=new-only --only', + 'pkglab pub --force', + 'pnpm init', + 'pkglab add @clerk/clerk-js', + 'pnpm init', + 'pkglab add @clerk/ui', + 'pnpm playwright install chromium', + 'pnpm playwright test --grep @case', + ]); + expect(calls[0].turboForce).toBe('false'); + expect( + calls[0].clerkSecret, + 'CLERK_* is in globalEnv, so passing test secrets to the build misses the build job cache', + ).toBeUndefined(); + expect(calls.at(-1).clerkSecret).toBe('secret'); + expect(marker).toBe('tests-started=true\n'); + }); + + test('refuses CI setup without the environment it needs', () => { + const { result, calls, marker } = run('generic', '', { TURBO_ARGS: '' }); + expect(result.status).toBe(1); + expect(result.stderr).toContain('TURBO_ARGS must be set when E2E_CI_SETUP is set'); + expect(calls).toEqual([]); + expect(marker).toBe(''); + }); + + test('does not run tests or set cleanup marker after setup failure', () => { + const { result, calls, marker } = run('generic', 'pkglab'); + expect(result.status).toBe(7); + expect(calls.map(call => call.name)).toEqual(['pnpm', 'pkglab']); + expect(marker).toBe(''); + }); + + test('records cleanup marker when Playwright fails', () => { + const { result, calls, marker } = run('generic', 'pnpm playwright test --grep @case'); + expect(result.status).toBe(7); + expect(calls.at(-1)).toMatchObject({ name: 'pnpm', args: ['playwright', 'test', '--grep', '@case'] }); + expect(marker).toBe('tests-started=true\n'); + }); + + test('runs Astro copy and Electron tests under Xvfb', () => { + const astro = run('astro'); + expect(astro.calls.some(call => call.args.join(' ') === 'copy:components')).toBe(true); + const electron = run('electron'); + expect(electron.calls.at(-1)).toMatchObject({ + name: 'xvfb-run', + args: ['-a', 'pnpm', 'playwright', 'test', '--grep', '@case'], + }); + }); +}); diff --git a/turbo.json b/turbo.json index 775c85d7f26..1c13fd074a5 100644 --- a/turbo.json +++ b/turbo.json @@ -4,15 +4,7 @@ "signature": true }, "ui": "tui", - "globalDependencies": [ - ".github/.cache-version", - ".npmrc", - "package.json", - "pnpm-lock.yaml", - "pnpm-workspace.yaml", - "tsconfig.json", - "tsconfig.*.json" - ], + "globalDependencies": [".github/.cache-version", ".npmrc", "pnpm-workspace.yaml", "tsconfig.json", "tsconfig.*.json"], "globalEnv": [ "CLERK_*", "EXPO_PUBLIC_CLERK_*", @@ -39,7 +31,13 @@ "ACTIONS_STEP_DEBUG", "VERCEL_AUTOMATION_BYPASS_SECRET", "PORT", - "UI_PORT" + "UI_PORT", + "TURBO_ARGS", + "TURBO_CACHE", + "TURBO_TEAM", + "TURBO_TOKEN", + "TURBO_REMOTE_CACHE_SIGNATURE_KEY", + "GITHUB_OUTPUT" ], "tasks": { "build": { @@ -72,6 +70,34 @@ "outputLogs": "new-only", "outputs": ["*/package.json", "dist/**", "scripts/**"] }, + "build:inputs": { + "dependsOn": ["^build:inputs"], + "inputs": [ + "package.json", + "*.d.ts", + "bundlewatch.config.json", + "src/**", + "tsconfig.json", + "tsconfig.build.json", + "tsconfig.declarations.json", + "tsdown.config.mts", + "tsdown.config.ts", + "tsup.config.ts", + "vite.config.*", + "subpaths.mjs", + "!**/*.test.*", + "!**/test/**", + "!**/tests/**", + "!**/__tests__/**", + "!**/__mocks__/**", + "!**/__snapshots__/**", + "!CHANGELOG.md", + "!coverage/**", + "!dist/**", + "!examples/**", + "!node_modules/**" + ] + }, "build:declarations": { "dependsOn": ["build"], "inputs": ["tsconfig.declarations.json"], @@ -118,7 +144,6 @@ "tsdown.config.mts", "tsdown.config.ts", "tsup.config.ts", - "!**/__snapshots__/**", "!CHANGELOG.md", "!coverage/**", "!dist/**", @@ -227,174 +252,195 @@ "outputs": [] }, "//#test:integration:ap-flows": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/next-account-portal/**", + "integration/templates/*", + "integration/templates/{next-app-router-quickstart,next-app-router-quickstart-v6}/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:generic": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs", + "@clerk/vue#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{generic,session-token-cache}/**", + "integration/templates/*", + "integration/templates/{custom-flows-react-vite,next-app-router,react-vite,vue-vite}/**", + "packages/backend/src/tokens/types.ts" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:express": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/express#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/express/**", + "integration/templates/*", + "integration/templates/express-vite/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:fastify": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/fastify#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/fastify/**", + "integration/templates/*", + "integration/templates/fastify-vite/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:hono": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/hono#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/hono/**", + "integration/templates/*", + "integration/templates/hono-vite/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:mosaic": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/mosaic#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/mosaic/**", + "integration/templates/*", + "integration/templates/next-app-router-mosaic/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:nextjs": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{generic,nextjs,session-token-cache}/**", + "integration/templates/*", + "integration/templates/{next-app-router,react-vite}/**", + "packages/backend/src/tokens/types.ts" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:nextjs:canary": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{generic,nextjs,session-token-cache}/**", + "integration/templates/*", + "integration/templates/{next-app-router,react-vite}/**", + "packages/backend/src/tokens/types.ts" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:quickstart": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": [ "CLEANUP", "DEBUG", @@ -404,46 +450,48 @@ "VERCEL_AUTOMATION_BYPASS_SECRET" ], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/quickstart/**", + "integration/templates/*", + "integration/templates/next-app-router-quickstart/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:astro": { + "dependsOn": [ + "@clerk/astro#build:inputs", + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/astro/**", + "integration/templates/*", + "integration/templates/{astro-hybrid,astro-node}/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:localhost": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": [ "CLEANUP", "DEBUG", @@ -453,338 +501,353 @@ "NODE_EXTRA_CA_CERTS" ], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{localhost,sessions}/**", + "integration/templates/*", + "integration/templates/next-app-router/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:sessions": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "DISABLE_WEB_SECURITY", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "NODE_EXTRA_CA_CERTS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/sessions/**", + "integration/templates/*", + "integration/templates/next-app-router/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:sessions:staging": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "DISABLE_WEB_SECURITY", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "NODE_EXTRA_CA_CERTS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/sessions/**", + "integration/templates/*", + "integration/templates/next-app-router/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:handshake": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "DISABLE_WEB_SECURITY", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "NODE_EXTRA_CA_CERTS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{handshake,sessions}/**", + "integration/templates/*", + "integration/templates/next-app-router/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:handshake:staging": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "DISABLE_WEB_SECURITY", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "NODE_EXTRA_CA_CERTS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{handshake,sessions}/**", + "integration/templates/*", + "integration/templates/next-app-router/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:expo-web": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/expo#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/expo-web/**", + "integration/templates/*", + "integration/templates/expo-web/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:tanstack-react-start": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/tanstack-react-start#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/tanstack-start/**", + "integration/templates/*", + "integration/templates/tanstack-react-start/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:vue": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs", + "@clerk/vue#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/vue/**", + "integration/templates/*", + "integration/templates/vue-vite/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:nuxt": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nuxt#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/nuxt/**", + "integration/templates/*", + "integration/templates/nuxt-node/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:react-router": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/react-router#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/react-router/**", + "integration/templates/*", + "integration/templates/{react-router-library,react-router-node}/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:billing": { + "dependsOn": [ + "@clerk/astro#build:inputs", + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs", + "@clerk/vue#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{astro,billing}/**", + "integration/templates/*", + "integration/templates/{astro-node,next-app-router,vue-vite}/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:machine": { + "dependsOn": [ + "@clerk/astro#build:inputs", + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/express#build:inputs", + "@clerk/fastify#build:inputs", + "@clerk/hono#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/nuxt#build:inputs", + "@clerk/react-router#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/tanstack-react-start#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{astro,express,fastify,hono,machine,nuxt,react-router,tanstack-start}/**", + "integration/templates/*", + "integration/templates/{astro-node,express-vite,fastify-vite,hono-vite,next-app-router,nuxt-node,react-router-node,tanstack-react-start}/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:custom": { + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/react#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/{custom-flows,generic}/**", + "integration/templates/*", + "integration/templates/{custom-flows-react-vite,react-vite}/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:cache-components": { - "dependsOn": ["@clerk/nextjs#build"], + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/nextjs#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/cache-components/**", + "integration/templates/*", + "integration/templates/next-cache-components/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:chrome-extension": { - "dependsOn": ["@clerk/nextjs#build"], + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/chrome-extension#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/chrome-extension/**", + "integration/templates/*", + "integration/templates/{chrome-extension-vite,react-vite}/**", + "packages/clerk-js/src/test/fixtures.ts" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only" }, "//#test:integration:electron": { - "dependsOn": ["@clerk/electron#build"], + "dependsOn": [ + "@clerk/backend#build:inputs", + "@clerk/clerk-js#build:inputs", + "@clerk/electron#build:inputs", + "@clerk/shared#build:inputs", + "@clerk/testing#build:inputs", + "@clerk/ui#build:inputs" + ], "env": ["CLEANUP", "DEBUG", "E2E_*", "INTEGRATION_INSTANCE_KEYS", "INTEGRATION_STAGING_INSTANCE_KEYS"], "inputs": [ - "integration/**", - "packages/*/package.json", - "packages/*/src/**", - "packages/*/tsconfig.json", - "packages/*/tsconfig.build.json", - "packages/*/tsconfig.declarations.json", - "packages/*/tsdown.config.*", - "packages/*/tsup.config.*", - "packages/*/rspack.config.*", - "packages/*/vite.config.*", - "!packages/*/src/**/*.test.*", - "!packages/*/src/**/__tests__/**", - "!packages/*/src/**/__mocks__/**", - "!packages/*/src/**/__snapshots__/**" + "integration/*", + "integration/{certs,cleanup,configs,deployments,models,presets,scripts,testUtils}/**", + "integration/tests/*", + "integration/tests/snapshots/**", + "integration/tests/electron/**", + "integration/templates/*", + "integration/templates/electron-vite/**" ], "outputs": ["integration/playwright-report/**"], "outputLogs": "new-only"