playwright.config.ts
Rama main · réplica de lectura del repositorio original.
import { defineConfig, devices } from "@playwright/test";
const baseURL = process.env.E2E_BASE_URL ?? "http://127.0.0.1:5173";
// Fixture safety checks in workers must see the same resolved target as the
// runner, including the default isolated server started by `test:e2e`.
process.env.E2E_BASE_URL = baseURL;
const seedCommand = process.env.E2E_SEED_COMMAND ?? "npm run seed:test";
const testDatabaseURL = process.env.TEST_DATABASE_URL
?? "postgres://tasktopia:tasktopia@127.0.0.1:55432/tasktopia_test";
// The server and direct database fixtures must use the same isolated database.
// webServer.env alone does not propagate this alias into Playwright workers.
process.env.E2E_DATABASE_URL ??= testDatabaseURL;
const serverPort = new URL(baseURL).port || (baseURL.startsWith("https:") ? "443" : "80");
const webCommand = process.env.E2E_WEB_COMMAND
?? `${seedCommand} && npm run build && NODE_ENV=production PORT=${serverPort} SESSION_COOKIE_SECURE=false npm start`;
const worldReviewMatch = /(?:task-card-paging|task-navigation-history|navigation-scope-recovery|socket-session-expiry|realtime-replay-recovery|realtime-notice-ui|city-album|task-catalog-navigation|news-feed-explicit|city-render-reliability|city-world-observation|city-neighbourhood|city-terrain-coverage|city-quarter-character|city-transport-furniture|city-road-continuity)\.spec\.ts/;
export default defineConfig({
testDir: "./tests/e2e",
timeout: 60_000,
// Hosted software renderers need longer for first-scene readiness. Explicit
// performance budgets and fault-injection timeouts remain in their tests.
expect: { timeout: process.env.CI ? 15_000 : 5_000 },
// Stateful UI scenarios intentionally share one seeded country. Running
// them concurrently makes tests rename/delete data underneath each other.
workers: 1,
webServer: {
command: webCommand,
url: baseURL,
// `localhost` and `127.0.0.1` are distinct origins. Tie the API's CSRF
// allow-list to the exact origin Playwright opens in every environment.
env: {
APP_ORIGIN: baseURL,
AUTH_RATE_LIMIT_MAX: "100",
// One local IP drives many independent users and reload journeys in CI.
CITY_SCENE_RATE_LIMIT_MAX: "300",
REGISTRATION_ENABLED: "true",
DATABASE_URL: process.env.E2E_DATABASE_URL ?? testDatabaseURL,
TEST_DATABASE_URL: testDatabaseURL,
VAPID_SUBJECT: "mailto:e2e@tasktopia.local",
VAPID_PUBLIC_KEY: "BJr0tc_HuCMQJu3JNPXyXdHtYn6BfvSw7C-gDbRQKwtFDGRg8dTM8kUJQTiG49l7O1AvdtGHst44gv-wfpFegZM",
VAPID_PRIVATE_KEY: "gI87ZWE09zw6Mc76CD9oKQCpRsJGFjdgOWgLjmKDKUA",
},
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
use: {
baseURL,
trace: "retain-on-failure",
screenshot: "only-on-failure",
},
projects: [
{
name: "chromium",
testIgnore: /(?:mobile-pwa|device-compatibility)\.spec\.ts/,
use: {
...devices["Desktop Chrome"],
viewport: { width: 1440, height: 900 },
// Desktop regression tests deliberately intercept lazy chunks. Keep
// the PWA cache isolated to the dedicated mobile PWA project.
serviceWorkers: "block",
},
},
{ name: "world-review-firefox", testMatch: worldReviewMatch, use: { ...devices["Desktop Firefox"], viewport: { width: 1440, height: 900 }, serviceWorkers: "block" } },
{ name: "world-review-webkit", testMatch: worldReviewMatch, use: { ...devices["Desktop Safari"], viewport: { width: 1440, height: 900 }, serviceWorkers: "block" } },
{ name: "world-review-android", testMatch: worldReviewMatch, use: { ...devices["Pixel 7"], serviceWorkers: "block" } },
{ name: "world-review-iphone", testMatch: worldReviewMatch, use: { ...devices["iPhone 13"], serviceWorkers: "block" } },
{ name: "webkit-visual", testMatch: /(?:transport-rework-live|city-200-loading|city-documents|city-development|world-digest|task-entry|atlas-transport|atlas-flight-geometry|atlas-pixel-zoom|planet-feedback|visual-consistency|visual-services|world-preferences|city-asset-overlap|auth-game-entry|forest-ui-design|forest-ui-surfaces|forest-ui-archive|forest-ui-states|living-city-events|everyday-city-events)\.spec\.ts/, use: { ...devices["Desktop Safari"], viewport: { width: 1440, height: 900 }, serviceWorkers: "block" } },
{ name: "ui-review-firefox", testMatch: /(?:auth-game-entry|ui-design-review|ui-public-preview)\.spec\.ts/, use: { ...devices["Desktop Firefox"], viewport: { width: 1440, height: 900 }, serviceWorkers: "block" } },
{ name: "ui-review-webkit", testMatch: /(?:auth-game-entry|ui-design-review|ui-public-preview)\.spec\.ts/, use: { ...devices["Desktop Safari"], viewport: { width: 1440, height: 900 }, serviceWorkers: "block" } },
{ name: "ui-review-mobile-chromium", testMatch: /(?:auth-game-entry|ui-design-review)\.spec\.ts/, grep: /touch:/, use: { ...devices["Pixel 7"], serviceWorkers: "block" } },
{ name: "ui-review-mobile-webkit", testMatch: /(?:auth-game-entry|ui-design-review)\.spec\.ts/, grep: /touch:/, use: { ...devices["iPhone 13"], serviceWorkers: "block" } },
{ name: "transport-firefox",testMatch:/transport-rework-live\.spec\.ts/,grep:/ready real/,use:{...devices["Desktop Firefox"],viewport:{width:1440,height:900},serviceWorkers:"block"}},
{ name:'transport-mobile-chromium',testMatch:/transport-rework-live\.spec\.ts/,grep:/touch transport/,use:{...devices['Pixel 7'],serviceWorkers:'block'}},
{ name:'transport-mobile-webkit',testMatch:/transport-rework-live\.spec\.ts/,grep:/touch transport/,use:{...devices['iPhone 13'],serviceWorkers:'block'}},
{ name: "living-city-mobile-chromium", testMatch: /(?:living-city-events|everyday-city-events)\.spec\.ts/, grep: /touch-sized/, use: { ...devices["Pixel 7"], serviceWorkers: "block" } },
{ name: "living-city-mobile-webkit", testMatch: /(?:living-city-events|everyday-city-events)\.spec\.ts/, grep: /touch-sized/, use: { ...devices["iPhone 13"], serviceWorkers: "block" } },
{ name: "mobile-chromium", testMatch: /mobile-pwa\.spec\.ts/, use: { ...devices["Pixel 7"] } },
{ name: "mobile-webkit", testMatch: /(?:mobile-pwa|pwa-update)\.spec\.ts/, use: { ...devices["iPhone 13"] } },
],
});