Skip to content

Commit dae692c

Browse files
test: fix e2e importer tests
1 parent d4e6f3c commit dae692c

11 files changed

Lines changed: 554 additions & 132 deletions

File tree

packages/apps/explorer/playwright.config.ts

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { defineConfig, devices } from '@playwright/test'
2-
import { dirname, resolve } from 'node:path'
2+
import { spawnSync } from 'node:child_process'
3+
import { mkdtempSync } from 'node:fs'
4+
import { tmpdir } from 'node:os'
5+
import { dirname, join, resolve } from 'node:path'
36
import { fileURLToPath } from 'node:url'
47
import { loadProfileEnvironment } from '@powersync-community/powergit-core/profile-env'
58

@@ -10,21 +13,18 @@ const BASE_HTTP = `http://${HOST}:${PORT}`
1013
const __filename = fileURLToPath(import.meta.url)
1114
const __dirname = dirname(__filename)
1215
const repoRoot = resolve(__dirname, '..', '..', '..')
13-
const profileEnv = loadProfileEnvironment({
14-
startDir: repoRoot,
15-
updateState: false,
16-
})
17-
const combinedEnv = profileEnv.combinedEnv
1816

1917
const isPlaceholder = (value?: string | null) => {
2018
if (typeof value !== 'string') return true
2119
return value.trim().length === 0
2220
}
2321

24-
for (const [key, value] of Object.entries(combinedEnv)) {
25-
if (isPlaceholder(process.env[key])) {
26-
process.env[key] = value
27-
}
22+
const ensureE2eHome = () => {
23+
const existing = process.env.POWERGIT_HOME
24+
if (existing && existing.trim().length > 0) return existing.trim()
25+
const dir = mkdtempSync(join(tmpdir(), 'powergit-explorer-e2e-'))
26+
process.env.POWERGIT_HOME = dir
27+
return dir
2828
}
2929

3030
const stripQuotes = (value?: string) => {
@@ -35,6 +35,100 @@ const stripQuotes = (value?: string) => {
3535
return value
3636
}
3737

38+
function parseExportedEnv(output: string): Record<string, string> {
39+
const env: Record<string, string> = {}
40+
const regex = /^export\s+([A-Z0-9_]+)=(.*)$/gm
41+
let match: RegExpExecArray | null = null
42+
while ((match = regex.exec(output)) !== null) {
43+
const key = match[1]
44+
const rawValue = match[2]
45+
if (!key || rawValue == null) continue
46+
try {
47+
env[key] = JSON.parse(rawValue) as string
48+
} catch {
49+
env[key] = rawValue.replace(/^"+|"+$/g, '')
50+
}
51+
}
52+
return env
53+
}
54+
55+
const ensureLocalStackEnv = () => {
56+
const explicitProfile = (process.env.STACK_PROFILE ?? '').trim()
57+
const desiredProfile = explicitProfile || 'local-dev'
58+
if (!explicitProfile) {
59+
process.env.STACK_PROFILE = desiredProfile
60+
}
61+
62+
if (desiredProfile === 'local-dev') {
63+
ensureE2eHome()
64+
}
65+
66+
let profileEnv = loadProfileEnvironment({
67+
profile: desiredProfile,
68+
startDir: repoRoot,
69+
updateState: false,
70+
strict: Boolean(explicitProfile),
71+
})
72+
const applyCombinedEnv = (combinedEnv: Record<string, string>) => {
73+
for (const [key, value] of Object.entries(combinedEnv)) {
74+
if (isPlaceholder(process.env[key])) {
75+
process.env[key] = value
76+
}
77+
}
78+
}
79+
applyCombinedEnv(profileEnv.combinedEnv)
80+
81+
const requiredLiveEnv = [
82+
'SUPABASE_URL',
83+
'SUPABASE_ANON_KEY',
84+
'SUPABASE_SERVICE_ROLE_KEY',
85+
'SUPABASE_EMAIL',
86+
'SUPABASE_PASSWORD',
87+
'POWERSYNC_URL',
88+
'POWERSYNC_DAEMON_URL',
89+
'POWERGIT_TEST_REMOTE_URL',
90+
]
91+
const missingLive = requiredLiveEnv.filter((name) => isPlaceholder(process.env[name]))
92+
93+
if (missingLive.length === 0 || desiredProfile !== 'local-dev') {
94+
return
95+
}
96+
97+
const scriptPath = resolve(repoRoot, 'scripts', 'dev-local-stack.mjs')
98+
const result = spawnSync(process.execPath, [scriptPath, 'start', '--print-exports'], {
99+
cwd: repoRoot,
100+
env: { ...process.env, STACK_PROFILE: desiredProfile },
101+
encoding: 'utf8',
102+
})
103+
if (result.status !== 0) {
104+
const stderr = typeof result.stderr === 'string' ? result.stderr : ''
105+
throw new Error(
106+
`[playwright] Failed to start local PowerSync stack for live e2e (missing: ${missingLive.join(', ')}).${stderr ? `\n${stderr}` : ''}`,
107+
)
108+
}
109+
110+
const exportedEnv = parseExportedEnv(typeof result.stdout === 'string' ? result.stdout : '')
111+
for (const [key, value] of Object.entries(exportedEnv)) {
112+
process.env[key] = value
113+
}
114+
115+
profileEnv = loadProfileEnvironment({
116+
profile: desiredProfile,
117+
startDir: repoRoot,
118+
updateState: false,
119+
strict: Boolean(explicitProfile),
120+
})
121+
applyCombinedEnv(profileEnv.combinedEnv)
122+
}
123+
124+
ensureLocalStackEnv()
125+
126+
const profileEnv = loadProfileEnvironment({
127+
startDir: repoRoot,
128+
updateState: false,
129+
})
130+
const combinedEnv = profileEnv.combinedEnv
131+
38132
const getEnvOrEmpty = (...keys: string[]) => {
39133
for (const key of keys) {
40134
const value = stripQuotes(process.env[key])
@@ -53,6 +147,7 @@ const SUPABASE_URL = getEnvOrEmpty('VITE_SUPABASE_URL', 'SUPABASE_URL') || 'http
53147
const SUPABASE_ANON_KEY = getEnvOrEmpty('VITE_SUPABASE_ANON_KEY', 'SUPABASE_ANON_KEY') || 'test-anon-key'
54148

55149
const TEST_TIMEOUT_MS = 30_000
150+
const LIVE_TEST_TIMEOUT_MS = Number(process.env.POWERSYNC_E2E_LIVE_TIMEOUT_MS ?? (process.env.CI ? 600_000 : 120_000))
56151
export const BASE_URL = BASE_HTTP
57152

58153
export default defineConfig({
@@ -82,6 +177,7 @@ export default defineConfig({
82177
},
83178
{
84179
name: 'chromium-live',
180+
timeout: LIVE_TEST_TIMEOUT_MS,
85181
use: { ...devices['Desktop Chrome'], },
86182
testMatch: /tests\/e2e\/live-.*\.spec\.ts/,
87183
dependencies: ['setup-live'],

0 commit comments

Comments
 (0)