@emesoft_company/playwright-core 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +62 -0
  2. package/dist/api/index.cjs +248 -0
  3. package/dist/api/index.cjs.map +1 -0
  4. package/dist/api/index.d.cts +12 -0
  5. package/dist/api/index.d.ts +12 -0
  6. package/dist/api/index.js +245 -0
  7. package/dist/api/index.js.map +1 -0
  8. package/dist/api-client-C_StjpPX.d.ts +58 -0
  9. package/dist/api-client-CpXo_NOU.d.cts +58 -0
  10. package/dist/auth/index.cjs +310 -0
  11. package/dist/auth/index.cjs.map +1 -0
  12. package/dist/auth/index.d.cts +98 -0
  13. package/dist/auth/index.d.ts +98 -0
  14. package/dist/auth/index.js +304 -0
  15. package/dist/auth/index.js.map +1 -0
  16. package/dist/config/index.cjs +268 -0
  17. package/dist/config/index.cjs.map +1 -0
  18. package/dist/config/index.d.cts +105 -0
  19. package/dist/config/index.d.ts +105 -0
  20. package/dist/config/index.js +254 -0
  21. package/dist/config/index.js.map +1 -0
  22. package/dist/data/index.cjs +59 -0
  23. package/dist/data/index.cjs.map +1 -0
  24. package/dist/data/index.d.cts +25 -0
  25. package/dist/data/index.d.ts +25 -0
  26. package/dist/data/index.js +50 -0
  27. package/dist/data/index.js.map +1 -0
  28. package/dist/di/index.cjs +47 -0
  29. package/dist/di/index.cjs.map +1 -0
  30. package/dist/di/index.d.cts +19 -0
  31. package/dist/di/index.d.ts +19 -0
  32. package/dist/di/index.js +45 -0
  33. package/dist/di/index.js.map +1 -0
  34. package/dist/errors/index.cjs +90 -0
  35. package/dist/errors/index.cjs.map +1 -0
  36. package/dist/errors/index.d.cts +38 -0
  37. package/dist/errors/index.d.ts +38 -0
  38. package/dist/errors/index.js +83 -0
  39. package/dist/errors/index.js.map +1 -0
  40. package/dist/expect/index.cjs +36 -0
  41. package/dist/expect/index.cjs.map +1 -0
  42. package/dist/expect/index.d.cts +30 -0
  43. package/dist/expect/index.d.ts +30 -0
  44. package/dist/expect/index.js +34 -0
  45. package/dist/expect/index.js.map +1 -0
  46. package/dist/fixtures/index.cjs +660 -0
  47. package/dist/fixtures/index.cjs.map +1 -0
  48. package/dist/fixtures/index.d.cts +68 -0
  49. package/dist/fixtures/index.d.ts +68 -0
  50. package/dist/fixtures/index.js +651 -0
  51. package/dist/fixtures/index.js.map +1 -0
  52. package/dist/index.cjs +1322 -0
  53. package/dist/index.cjs.map +1 -0
  54. package/dist/index.d.cts +21 -0
  55. package/dist/index.d.ts +21 -0
  56. package/dist/index.js +1248 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/logging/index.cjs +32 -0
  59. package/dist/logging/index.cjs.map +1 -0
  60. package/dist/logging/index.d.cts +18 -0
  61. package/dist/logging/index.d.ts +18 -0
  62. package/dist/logging/index.js +25 -0
  63. package/dist/logging/index.js.map +1 -0
  64. package/dist/reporting/index.cjs +59 -0
  65. package/dist/reporting/index.cjs.map +1 -0
  66. package/dist/reporting/index.d.cts +63 -0
  67. package/dist/reporting/index.d.ts +63 -0
  68. package/dist/reporting/index.js +52 -0
  69. package/dist/reporting/index.js.map +1 -0
  70. package/dist/retry-XqnSC8YL.d.cts +27 -0
  71. package/dist/retry-XqnSC8YL.d.ts +27 -0
  72. package/dist/schema-y5w2hbT-.d.cts +292 -0
  73. package/dist/schema-y5w2hbT-.d.ts +292 -0
  74. package/dist/types-CbWnSYEK.d.cts +5 -0
  75. package/dist/types-CbWnSYEK.d.ts +5 -0
  76. package/dist/types-CopwwpSW.d.cts +8 -0
  77. package/dist/types-CopwwpSW.d.ts +8 -0
  78. package/dist/types-hInbkPXf.d.cts +59 -0
  79. package/dist/types-hInbkPXf.d.ts +59 -0
  80. package/dist/ui/index.cjs +366 -0
  81. package/dist/ui/index.cjs.map +1 -0
  82. package/dist/ui/index.d.cts +190 -0
  83. package/dist/ui/index.d.ts +190 -0
  84. package/dist/ui/index.js +348 -0
  85. package/dist/ui/index.js.map +1 -0
  86. package/dist/utils/index.cjs +72 -0
  87. package/dist/utils/index.cjs.map +1 -0
  88. package/dist/utils/index.d.cts +27 -0
  89. package/dist/utils/index.d.ts +27 -0
  90. package/dist/utils/index.js +66 -0
  91. package/dist/utils/index.js.map +1 -0
  92. package/package.json +133 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/errors/app-error.ts","../../src/auth/token-provider.ts","../../src/utils/sleep.ts","../../src/errors/retry.ts","../../src/api/interceptors.ts","../../src/api/api-client.ts","../../src/utils/deep-merge.ts","../../src/config/schema.ts","../../src/config/loader.ts","../../src/logging/logger.ts","../../src/reporting/meta.ts","../../src/fixtures/auth.fixture.ts","../../src/reporting/attachments.ts","../../src/fixtures/diagnostics.fixture.ts","../../src/expect/matchers.ts","../../src/fixtures/base-test.ts"],"names":["logger","base","baseExpect"],"mappings":"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","file":"index.js","sourcesContent":["export interface AppErrorOptions {\n code: string;\n cause?: unknown;\n context?: Record<string, unknown>;\n}\n\n/**\n * Base error class for the framework. Every error thrown by core carries a\n * machine-readable `code` and optional `context`, so callers can branch on\n * `error.code` instead of parsing messages.\n */\nexport class AppError extends Error {\n readonly code: string;\n readonly context?: Record<string, unknown>;\n\n constructor(message: string, options: AppErrorOptions) {\n super(message, { cause: options.cause });\n this.name = new.target.name;\n this.code = options.code;\n this.context = options.context;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConfigValidationError extends AppError {\n constructor(message: string, issues: unknown, context?: Record<string, unknown>) {\n super(message, { code: \"CONFIG_VALIDATION_ERROR\", context: { issues, ...context } });\n }\n}\n\nexport class ApiError extends AppError {\n readonly status?: number;\n readonly method?: string;\n readonly url?: string;\n\n constructor(\n message: string,\n options: AppErrorOptions & { status?: number; method?: string; url?: string },\n ) {\n super(message, options);\n this.status = options.status;\n this.method = options.method;\n this.url = options.url;\n }\n}\n\nexport class AuthError extends AppError {\n constructor(message: string, options: Omit<AppErrorOptions, \"code\"> = {}) {\n super(message, { code: \"AUTH_ERROR\", ...options });\n }\n}\n\nexport class ConfigMissingError extends AppError {\n constructor(name: string) {\n super(`Required environment variable \"${name}\" is not set`, {\n code: \"ENV_VAR_MISSING\",\n context: { name },\n });\n }\n}\n","import { AuthError } from \"../errors/app-error.js\";\nimport type { Logger } from \"../logging/logger.js\";\nimport type { TokenProvider } from \"./types.js\";\n\n/** Token provider that always returns a fixed token. Useful for tests/local dev with a pre-issued token. */\nexport class StaticTokenProvider implements TokenProvider {\n constructor(private readonly token: string) {}\n\n async getToken(): Promise<string> {\n return this.token;\n }\n\n invalidate(): void {\n // no-op: nothing to invalidate for a static token\n }\n}\n\n/** No-op provider for endpoints that don't require authentication. */\nexport class NullTokenProvider implements TokenProvider {\n async getToken(): Promise<string> {\n return \"\";\n }\n\n invalidate(): void {\n // no-op\n }\n}\n\nexport interface JwtTokenProviderOptions {\n tokenUrl: string;\n clientId?: string;\n clientSecret?: string;\n username?: string;\n password?: string;\n /** Seconds subtracted from the token's `expires_in` to refresh proactively. Default: 30. */\n refreshSkewSeconds?: number;\n logger?: Logger;\n fetchImpl?: typeof fetch;\n}\n\ninterface CachedToken {\n token: string;\n expiresAt: number;\n}\n\n/**\n * JWT/OAuth2 token provider supporting client-credentials or password grants.\n * Caches the token in-memory and transparently refreshes it before expiry.\n */\nexport class JwtTokenProvider implements TokenProvider {\n private cached?: CachedToken;\n private inFlight?: Promise<string>;\n\n constructor(private readonly options: JwtTokenProviderOptions) {}\n\n async getToken(): Promise<string> {\n if (this.cached && this.cached.expiresAt > Date.now()) {\n return this.cached.token;\n }\n if (!this.inFlight) {\n this.inFlight = this.fetchToken().finally(() => {\n this.inFlight = undefined;\n });\n }\n return this.inFlight;\n }\n\n invalidate(): void {\n this.cached = undefined;\n }\n\n private async fetchToken(): Promise<string> {\n const { tokenUrl, clientId, clientSecret, username, password, refreshSkewSeconds = 30, logger, fetchImpl = fetch } = this.options;\n\n const body = new URLSearchParams();\n if (username && password) {\n body.set(\"grant_type\", \"password\");\n body.set(\"username\", username);\n body.set(\"password\", password);\n } else {\n body.set(\"grant_type\", \"client_credentials\");\n }\n if (clientId) body.set(\"client_id\", clientId);\n if (clientSecret) body.set(\"client_secret\", clientSecret);\n\n logger?.debug({ tokenUrl }, \"fetching auth token\");\n\n let response: Response;\n try {\n response = await fetchImpl(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body,\n });\n } catch (cause) {\n throw new AuthError(`Failed to reach token endpoint ${tokenUrl}`, { cause });\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new AuthError(`Token endpoint returned ${response.status}: ${text}`, {\n context: { status: response.status, tokenUrl },\n });\n }\n\n const data = (await response.json()) as { access_token?: string; expires_in?: number };\n if (!data.access_token) {\n throw new AuthError(\"Token endpoint response missing access_token\", { context: { tokenUrl } });\n }\n\n const expiresInSeconds = data.expires_in ?? 300;\n this.cached = {\n token: data.access_token,\n expiresAt: Date.now() + Math.max(expiresInSeconds - refreshSkewSeconds, 0) * 1000,\n };\n return this.cached.token;\n }\n}\n","export function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { sleep } from \"../utils/sleep.js\";\n\nexport interface RetryOptions {\n /** Number of retry attempts after the initial try. Default: 2. */\n retries?: number;\n minDelayMs?: number;\n maxDelayMs?: number;\n /** Exponential backoff factor. Default: 2. */\n factor?: number;\n /** Return true to retry this error, false to fail fast. Default: retry everything. */\n retryOn?: (error: unknown) => boolean;\n /** Called before each retry (not before the first attempt). */\n onRetry?: (error: unknown, attempt: number) => void;\n /** Called once when giving up, with the total number of attempts made. */\n onGiveUp?: (error: unknown, attempts: number) => void;\n}\n\nfunction backoffDelay(attempt: number, minDelayMs: number, maxDelayMs: number, factor: number): number {\n const exponential = minDelayMs * factor ** (attempt - 1);\n const jitter = Math.random() * minDelayMs;\n return Math.min(exponential + jitter, maxDelayMs);\n}\n\n/**\n * Runs `fn` with exponential-backoff retry. Used for both flaky API calls and\n * flaky UI actions so the retry policy stays consistent across the framework.\n *\n * Always rethrows the ORIGINAL error — whether it failed fast (`retryOn` returned\n * false) or exhausted its retries. That's what makes `catch (e) { e instanceof ApiError }`\n * and `expect(...).rejects.toThrow(ApiError)` work in tests; wrapping the error in a\n * retry-specific type would hide the only thing the caller actually wants to assert on.\n * Use `onGiveUp` if you need the attempt count.\n */\nexport async function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {\n const {\n retries = 2,\n minDelayMs = 200,\n maxDelayMs = 5_000,\n factor = 2,\n retryOn = () => true,\n onRetry,\n onGiveUp,\n } = options;\n\n const maxAttempts = retries + 1;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n const isLastAttempt = attempt >= maxAttempts;\n if (isLastAttempt || !retryOn(error)) {\n onGiveUp?.(error, attempt);\n throw error;\n }\n onRetry?.(error, attempt);\n await sleep(backoffDelay(attempt, minDelayMs, maxDelayMs, factor));\n }\n }\n\n // Unreachable: the loop either returns or throws.\n throw new Error(\"withRetry: unreachable state\");\n}\n","/** 429 (rate-limited) and any 5xx are considered transient and safe to retry. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 429 || (status >= 500 && status <= 599);\n}\n","import type { APIRequestContext, APIResponse } from \"@playwright/test\";\nimport { NullTokenProvider } from \"../auth/token-provider.js\";\nimport type { TokenProvider } from \"../auth/types.js\";\nimport { ApiError, AppError } from \"../errors/app-error.js\";\nimport { withRetry, type RetryOptions } from \"../errors/retry.js\";\nimport type { Logger } from \"../logging/logger.js\";\nimport { isRetryableStatus } from \"./interceptors.js\";\nimport type { ApiClientInterceptors, ApiRequestOptions, ApiResponse } from \"./types.js\";\n\nexport interface ApiClientOptions {\n /** Playwright's `APIRequestContext` (from `request` fixture or `context.request`). */\n request: APIRequestContext;\n baseUrl?: string;\n tokenProvider?: TokenProvider;\n logger?: Logger;\n retry?: Partial<RetryOptions>;\n defaultHeaders?: Record<string, string>;\n interceptors?: ApiClientInterceptors;\n}\n\n/** Internal signal used to drive retry backoff; never escapes `send()`. */\nclass TransientHttpError extends Error {\n constructor(readonly status: number) {\n super(`Transient HTTP status ${status}`);\n }\n}\n\n/**\n * Thin, project-agnostic abstraction over Playwright's `APIRequestContext`:\n * base URL resolution, bearer-token injection, structured error mapping, and\n * retry-on-5xx/429. Projects extend this for domain-specific API clients\n * instead of calling `request.fetch` directly in tests.\n *\n * Two levels of API, on purpose:\n * - `get`/`post`/... return the body and THROW `ApiError` on an unexpected status — the right\n * default for arranging test data, where a failed call should stop the test loudly.\n * - `send()` returns the full `ApiResponse` (status, headers, body) and never throws for an\n * HTTP status — for tests that assert on error responses themselves.\n */\nexport class ApiClient {\n private readonly request: APIRequestContext;\n private readonly baseUrl?: string;\n private readonly tokenProvider: TokenProvider;\n private readonly logger?: Logger;\n private readonly retryOptions: RetryOptions;\n private readonly defaultHeaders: Record<string, string>;\n private readonly interceptors: ApiClientInterceptors;\n\n constructor(options: ApiClientOptions) {\n this.request = options.request;\n this.baseUrl = options.baseUrl;\n this.tokenProvider = options.tokenProvider ?? new NullTokenProvider();\n this.logger = options.logger;\n this.defaultHeaders = options.defaultHeaders ?? {};\n this.interceptors = options.interceptors ?? {};\n this.retryOptions = { ...options.retry };\n }\n\n get<T = unknown>(path: string, options?: ApiRequestOptions<T>): Promise<T> {\n return this.requestBody<T>(\"GET\", path, options);\n }\n\n post<T = unknown>(path: string, options?: ApiRequestOptions<T>): Promise<T> {\n return this.requestBody<T>(\"POST\", path, options);\n }\n\n put<T = unknown>(path: string, options?: ApiRequestOptions<T>): Promise<T> {\n return this.requestBody<T>(\"PUT\", path, options);\n }\n\n patch<T = unknown>(path: string, options?: ApiRequestOptions<T>): Promise<T> {\n return this.requestBody<T>(\"PATCH\", path, options);\n }\n\n delete<T = unknown>(path: string, options?: ApiRequestOptions<T>): Promise<T> {\n return this.requestBody<T>(\"DELETE\", path, options);\n }\n\n /**\n * Full response including status and headers. Retries transient statuses, then returns\n * whatever came back — a 404 or 500 is a normal return value here, not an exception.\n * Network/timeout failures still throw.\n */\n async send<T = unknown>(\n method: string,\n path: string,\n options: ApiRequestOptions<T> = {},\n ): Promise<ApiResponse<T>> {\n const url = this.resolveUrl(path, options.params);\n let lastResponse: ApiResponse<T> | undefined;\n\n try {\n await withRetry(\n async () => {\n lastResponse = await this.fetchOnce<T>(method, url, options);\n if (isRetryableStatus(lastResponse.status) && !this.isExpectedStatus(lastResponse.status, options)) {\n throw new TransientHttpError(lastResponse.status);\n }\n },\n {\n ...this.retryOptions,\n retryOn: (error) => error instanceof TransientHttpError,\n onRetry: (error, attempt) =>\n this.logger?.warn({ method, url, attempt, err: error }, \"retrying API request\"),\n },\n );\n } catch (error) {\n // A transient status that never recovered is still a response the caller may want to\n // inspect; anything else (DNS, TLS, timeout) is a real failure and must propagate.\n if (!(error instanceof TransientHttpError)) throw error;\n }\n\n if (!lastResponse) {\n throw new AppError(`API request produced no response: ${method} ${url}`, {\n code: \"API_NO_RESPONSE\",\n context: { method, url },\n });\n }\n return lastResponse;\n }\n\n private async requestBody<T>(\n method: string,\n path: string,\n options: ApiRequestOptions<T> = {},\n ): Promise<T> {\n const response = await this.send<T>(method, path, options);\n\n if (!this.isExpectedStatus(response.status, options)) {\n if (response.status === 401) this.tokenProvider.invalidate();\n this.logger?.error(\n { status: response.status, method, url: response.url, body: response.data },\n \"API request failed\",\n );\n throw new ApiError(\n `API request failed: ${method} ${response.url} -> ${response.status}` +\n (options.expectStatus === undefined ? \"\" : ` (expected ${String(options.expectStatus)})`),\n {\n code: \"API_REQUEST_FAILED\",\n status: response.status,\n method,\n url: response.url,\n context: { body: response.data },\n },\n );\n }\n return response.data;\n }\n\n private isExpectedStatus(status: number, options: ApiRequestOptions<unknown>): boolean {\n if (options.expectStatus === undefined) return status >= 200 && status < 300;\n const expected = Array.isArray(options.expectStatus) ? options.expectStatus : [options.expectStatus];\n return expected.includes(status);\n }\n\n private async fetchOnce<T>(\n method: string,\n url: string,\n options: ApiRequestOptions<T>,\n ): Promise<ApiResponse<T>> {\n const headers = await this.buildHeaders(method, url, options);\n const response = await this.request.fetch(url, {\n method,\n headers,\n data: options.data,\n form: options.form,\n multipart: options.multipart,\n timeout: options.timeoutMs,\n });\n await this.interceptors.onResponse?.({ method, url, status: response.status() });\n\n return {\n status: response.status(),\n ok: response.ok(),\n headers: response.headers(),\n data: await this.parseBody<T>(response, options),\n url,\n method,\n };\n }\n\n private resolveUrl(path: string, params?: ApiRequestOptions<unknown>[\"params\"]): string {\n const base = this.baseUrl ? new URL(path, this.baseUrl).toString() : path;\n if (!params) return base;\n const url = new URL(base);\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) url.searchParams.set(key, String(value));\n }\n return url.toString();\n }\n\n private async buildHeaders(\n method: string,\n url: string,\n options: ApiRequestOptions<unknown>,\n ): Promise<Record<string, string>> {\n let headers: Record<string, string> = { ...this.defaultHeaders, ...options.headers };\n if (!options.skipAuth) {\n const token = await this.tokenProvider.getToken();\n if (token) headers = { ...headers, Authorization: `Bearer ${token}` };\n }\n const overridden = await this.interceptors.onRequest?.({ method, url, headers });\n return overridden ?? headers;\n }\n\n private async parseBody<T>(response: APIResponse, options: ApiRequestOptions<T>): Promise<T> {\n const raw = await this.readBody(response);\n\n if (!options.schema) return raw as T;\n\n const result = options.schema.safeParse(raw);\n if (!result.success) {\n throw new ApiError(`API response did not match the expected schema: ${response.url()}`, {\n code: \"API_SCHEMA_MISMATCH\",\n status: response.status(),\n url: response.url(),\n context: { issues: result.error.issues, body: raw },\n });\n }\n return result.data;\n }\n\n private async readBody(response: APIResponse): Promise<unknown> {\n const contentType = response.headers()[\"content-type\"] ?? \"\";\n if (contentType.includes(\"application/json\")) {\n // A JSON content-type with an empty body (some 204s) would otherwise throw on parse.\n const text = await response.text();\n if (text.trim() === \"\") return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return response.text();\n }\n}\n","export function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Recursively merges `override` onto `base`. Arrays and primitives replace wholesale;\n * only plain objects are merged key by key. `undefined` values in `override` are ignored,\n * so a partial object never accidentally erases a configured value.\n */\nexport function deepMerge<T>(base: T, override: unknown): T {\n if (override === undefined) return base;\n if (!isPlainObject(base) || !isPlainObject(override)) {\n return override as T;\n }\n const result: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n const baseValue = (base as Record<string, unknown>)[key];\n result[key] = isPlainObject(baseValue) && isPlainObject(value) ? deepMerge(baseValue, value) : value;\n }\n return result as T;\n}\n\n/** Strips `undefined` values and empty nested objects, so zod defaults apply instead. */\nexport function pruneUndefined(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(pruneUndefined);\n if (isPlainObject(value)) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val === undefined) continue;\n const pruned = pruneUndefined(val);\n if (isPlainObject(pruned) && Object.keys(pruned).length === 0) continue;\n result[key] = pruned;\n }\n return result;\n }\n return value;\n}\n","import { z } from \"zod\";\n\n/** Environments seen most often across projects — autocompleted, but any string is accepted. */\nexport const KNOWN_ENVIRONMENTS = [\"local\", \"dev\", \"qa\", \"uat\", \"staging\", \"prod\"] as const;\n\n/**\n * Free-form on purpose: teams run `uat`, `qa`, `sit`, per-tenant envs and so on. The union\n * below keeps editor autocomplete for the common ones without rejecting anything else\n * (`(string & {})` is the TS idiom that preserves suggestions on an open string type).\n */\nexport type Environment = (typeof KNOWN_ENVIRONMENTS)[number] | (string & {});\n\nexport const EnvironmentSchema = z.string().min(1);\n\nexport const TimeoutsSchema = z.object({\n actionMs: z.number().int().positive().default(15_000),\n navigationMs: z.number().int().positive().default(30_000),\n testMs: z.number().int().positive().default(60_000),\n /** Default budget for `waitForCondition` and other non-locator polling. */\n waitMs: z.number().int().positive().default(30_000),\n});\n\nexport const AuthConfigSchema = z\n .object({\n tokenUrl: z.string().url().optional(),\n clientId: z.string().optional(),\n clientSecret: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n /** Single-session storage state file (see `buildGlobalSetup`). */\n storageStatePath: z.string().optional(),\n /** Directory used for per-role storage state files in multi-role setups. */\n storageStateDir: z.string().default(\".auth\"),\n })\n .default({});\n\nexport const ReportingConfigSchema = z\n .object({\n allureEnabled: z.boolean().default(false),\n resultsDir: z.string().default(\"allure-results\"),\n /** `{id}` is replaced with a test-case id — see `meta()` in `@emesoft_company/playwright-core/reporting`. */\n testCaseUrlTemplate: z.string().optional(),\n })\n .default({});\n\nexport const RetryConfigSchema = z\n .object({\n retries: z.number().int().min(0).default(2),\n minDelayMs: z.number().int().positive().default(200),\n maxDelayMs: z.number().int().positive().default(5_000),\n })\n .default({});\n\nexport const DiagnosticsConfigSchema = z\n .object({\n /** Collect browser console errors + failed requests and attach them to the report. */\n enabled: z.boolean().default(true),\n /** Fail the test if the page logged a console error. Off by default — many apps are noisy. */\n failOnConsoleError: z.boolean().default(false),\n /** Fail the test on an uncaught page exception. */\n failOnPageError: z.boolean().default(false),\n /** Console messages matching any of these substrings are ignored entirely. */\n ignoreConsolePatterns: z.array(z.string()).default([]),\n })\n .default({});\n\n/**\n * Base config schema shared by every project. Projects extend this via\n * `AppConfigSchema.extend({ ... })` or by nesting project-specific fields\n * under `custom` — core never hardcodes project business fields here.\n */\nexport const AppConfigSchema = z.object({\n environment: EnvironmentSchema,\n baseUrl: z.string().url(),\n apiBaseUrl: z.string().url().optional(),\n tenant: z.string().optional(),\n timeouts: TimeoutsSchema.default({}),\n auth: AuthConfigSchema,\n reporting: ReportingConfigSchema,\n retry: RetryConfigSchema,\n diagnostics: DiagnosticsConfigSchema,\n logLevel: z.enum([\"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\", \"silent\"]).default(\"info\"),\n custom: z.record(z.string(), z.unknown()).default({}),\n});\n\nexport type AppConfig = Omit<z.infer<typeof AppConfigSchema>, \"environment\"> & {\n environment: Environment;\n};\nexport type TimeoutsConfig = z.infer<typeof TimeoutsSchema>;\nexport type AuthConfig = z.infer<typeof AuthConfigSchema>;\nexport type ReportingConfig = z.infer<typeof ReportingConfigSchema>;\nexport type RetryConfig = z.infer<typeof RetryConfigSchema>;\nexport type DiagnosticsConfig = z.infer<typeof DiagnosticsConfigSchema>;\n","import { ConfigMissingError, ConfigValidationError } from \"../errors/app-error.js\";\nimport { deepMerge, pruneUndefined } from \"../utils/deep-merge.js\";\nimport { AppConfigSchema, type AppConfig } from \"./schema.js\";\nimport type { DeepPartial } from \"./types.js\";\n\nfunction readEnvConfig(env: NodeJS.ProcessEnv): Record<string, unknown> {\n return {\n environment: env.TEST_ENV ?? \"dev\",\n baseUrl: env.BASE_URL,\n apiBaseUrl: env.API_BASE_URL,\n tenant: env.TENANT,\n logLevel: env.LOG_LEVEL,\n timeouts: {\n actionMs: env.ACTION_TIMEOUT_MS ? Number(env.ACTION_TIMEOUT_MS) : undefined,\n navigationMs: env.NAVIGATION_TIMEOUT_MS ? Number(env.NAVIGATION_TIMEOUT_MS) : undefined,\n testMs: env.TEST_TIMEOUT_MS ? Number(env.TEST_TIMEOUT_MS) : undefined,\n waitMs: env.WAIT_TIMEOUT_MS ? Number(env.WAIT_TIMEOUT_MS) : undefined,\n },\n auth: {\n tokenUrl: env.AUTH_TOKEN_URL,\n clientId: env.AUTH_CLIENT_ID,\n clientSecret: env.AUTH_CLIENT_SECRET,\n username: env.AUTH_USERNAME,\n password: env.AUTH_PASSWORD,\n storageStatePath: env.AUTH_STORAGE_STATE_PATH,\n storageStateDir: env.AUTH_STORAGE_STATE_DIR,\n },\n reporting: {\n allureEnabled: env.REPORT_ALLURE === \"true\",\n resultsDir: env.ALLURE_RESULTS_DIR,\n testCaseUrlTemplate: env.TEST_CASE_URL_TEMPLATE,\n },\n retry: {\n retries: env.RETRY_COUNT ? Number(env.RETRY_COUNT) : undefined,\n minDelayMs: env.RETRY_MIN_DELAY_MS ? Number(env.RETRY_MIN_DELAY_MS) : undefined,\n maxDelayMs: env.RETRY_MAX_DELAY_MS ? Number(env.RETRY_MAX_DELAY_MS) : undefined,\n },\n diagnostics: {\n enabled: env.DIAGNOSTICS === undefined ? undefined : env.DIAGNOSTICS !== \"false\",\n failOnConsoleError: env.FAIL_ON_CONSOLE_ERROR === undefined ? undefined : env.FAIL_ON_CONSOLE_ERROR === \"true\",\n failOnPageError: env.FAIL_ON_PAGE_ERROR === undefined ? undefined : env.FAIL_ON_PAGE_ERROR === \"true\",\n },\n };\n}\n\n/**\n * Reads a required environment variable, failing immediately with a clear message instead of\n * letting an `undefined` surface as a confusing failure deep inside a test.\n */\nexport function requireEnv(name: string, env: NodeJS.ProcessEnv = process.env): string {\n const value = env[name];\n if (value === undefined || value === \"\") {\n throw new ConfigMissingError(name);\n }\n return value;\n}\n\nexport interface LoadConfigOptions {\n /** Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n /** Project-specific overrides (e.g. from a project's `config.override.ts`), merged on top of env-derived values. */\n overrides?: DeepPartial<AppConfig>;\n}\n\n/**\n * Loads and validates the application config for the current environment.\n * Resolution order: env-derived defaults -> project `overrides` -> zod validation.\n * Fails fast with `ConfigValidationError` when required fields (e.g. `baseUrl`) are missing/invalid,\n * instead of letting tests fail later with a confusing `undefined` somewhere downstream.\n */\nexport function loadConfig(options: LoadConfigOptions = {}): AppConfig {\n const { env = process.env, overrides } = options;\n\n const fromEnv = pruneUndefined(readEnvConfig(env)) as DeepPartial<AppConfig>;\n const merged = deepMerge(fromEnv as AppConfig, overrides);\n\n const result = AppConfigSchema.safeParse(merged);\n if (!result.success) {\n throw new ConfigValidationError(\n `Invalid application config: ${result.error.issues\n .map((issue) => `${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`)\n .join(\"; \")}`,\n result.error.issues,\n );\n }\n return result.data;\n}\n","import pino, { type Logger } from \"pino\";\n\nexport interface LoggerOptions {\n level?: string;\n name?: string;\n /**\n * Pretty-print logs for local/interactive runs. Requires the optional\n * `pino-pretty` dev dependency to be installed in the consuming project;\n * leave off (default) for CI where structured JSON logs are preferred.\n */\n pretty?: boolean;\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n level = process.env.LOG_LEVEL ?? \"info\",\n name = \"playwright-core\",\n pretty = process.env.LOG_PRETTY === \"true\",\n } = options;\n\n return pino({\n name,\n level,\n ...(pretty\n ? {\n transport: {\n target: \"pino-pretty\",\n options: { colorize: true, translateTime: \"SYS:standard\" },\n },\n }\n : {}),\n });\n}\n\n/** Default shared logger instance. Prefer `createLogger()` when a project needs a distinct name/level. */\nexport const logger = createLogger();\n\nexport type { Logger };\n","import type { TestInfo } from \"@playwright/test\";\n\nexport interface TestMetaOptions {\n /** Test-case id(s) in your test management tool, e.g. `\"TC-1234\"` or `[\"TC-1\", \"TC-2\"]`. */\n testCase?: string | string[];\n /** Tag(s) for filtering with `--grep`, e.g. `\"@smoke\"`. The leading `@` is added if missing. */\n tag?: string | string[];\n /** Free-form annotations, e.g. `{ type: \"issue\", description: \"JIRA-42\" }`. */\n annotation?: { type: string; description?: string }[];\n}\n\nexport interface TestMeta {\n tag?: string[];\n annotation?: { type: string; description?: string }[];\n}\n\nfunction toArray(value: string | string[] | undefined): string[] {\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/**\n * Builds the `details` argument of `test(title, details, body)` from test-case ids and tags,\n * so the mapping between an automated test and its test-case id lives in the test itself and\n * shows up in the report.\n *\n * ```ts\n * test(\"login success\", meta({ testCase: \"TC-1234\", tag: \"@smoke\" }), async ({ page }) => { ... });\n * ```\n *\n * Set `reporting.testCaseUrlTemplate` (env `TEST_CASE_URL_TEMPLATE`, with `{id}` as the\n * placeholder) to turn the ids into links — see `linkTestCases`.\n */\nexport function meta(options: TestMetaOptions): TestMeta {\n const tags = toArray(options.tag).map((tag) => (tag.startsWith(\"@\") ? tag : `@${tag}`));\n const testCaseAnnotations = toArray(options.testCase).map((id) => ({\n type: \"testCase\",\n description: id,\n }));\n\n const annotation = [...testCaseAnnotations, ...(options.annotation ?? [])];\n\n return {\n ...(tags.length > 0 ? { tag: tags } : {}),\n ...(annotation.length > 0 ? { annotation } : {}),\n };\n}\n\n/**\n * Rewrites `testCase` annotations into full URLs using a template containing `{id}`.\n * Call from a project's `beforeEach`/fixture when `reporting.testCaseUrlTemplate` is set.\n */\nexport function linkTestCases(testInfo: TestInfo, urlTemplate: string | undefined): void {\n if (!urlTemplate) return;\n for (const annotation of testInfo.annotations) {\n if (annotation.type === \"testCase\" && annotation.description) {\n annotation.description = urlTemplate.replace(\"{id}\", annotation.description);\n }\n }\n}\n","import { JwtTokenProvider, NullTokenProvider } from \"../auth/token-provider.js\";\nimport type { TokenProvider } from \"../auth/types.js\";\nimport type { AppConfig } from \"../config/schema.js\";\nimport type { Logger } from \"../logging/logger.js\";\n\n/**\n * Default token-provider resolution: uses JWT client-credentials/password grant when\n * `auth.tokenUrl` is configured, otherwise falls back to no-auth. Projects that need a\n * different strategy (SSO, pre-provisioned storageState, static token, ...) override the\n * `tokenProvider` fixture in their own `fixtures/index.ts` — see `docs/EXTENDING.md`.\n */\nexport function resolveTokenProvider(config: AppConfig, logger?: Logger): TokenProvider {\n const { auth } = config;\n if (auth.tokenUrl) {\n return new JwtTokenProvider({\n tokenUrl: auth.tokenUrl,\n clientId: auth.clientId,\n clientSecret: auth.clientSecret,\n username: auth.username,\n password: auth.password,\n logger,\n });\n }\n return new NullTokenProvider();\n}\n","import type { TestInfo } from \"@playwright/test\";\n\n/**\n * Report attachment helpers. These show up in the HTML report (and Allure, when enabled)\n * next to the test, which is usually the difference between a failure you can diagnose from\n * CI and one you have to reproduce locally.\n */\n\nexport async function attachText(testInfo: TestInfo, name: string, body: string): Promise<void> {\n await testInfo.attach(name, { body, contentType: \"text/plain\" });\n}\n\nexport async function attachJson(testInfo: TestInfo, name: string, value: unknown): Promise<void> {\n await testInfo.attach(name, {\n body: JSON.stringify(value, null, 2),\n contentType: \"application/json\",\n });\n}\n\nexport async function attachScreenshot(testInfo: TestInfo, name: string, buffer: Buffer): Promise<void> {\n await testInfo.attach(name, { body: buffer, contentType: \"image/png\" });\n}\n","import type { Page, TestInfo } from \"@playwright/test\";\nimport type { DiagnosticsConfig } from \"../config/schema.js\";\nimport { attachText } from \"../reporting/attachments.js\";\n\nexport interface CollectedDiagnostics {\n consoleErrors: string[];\n pageErrors: string[];\n failedRequests: string[];\n}\n\n/**\n * Subscribes to a page's error signals. Returns the collected buffers plus a `report()` to\n * call after the test body, which attaches anything collected to the report and — if\n * configured — fails the test.\n *\n * Wired into the `page` fixture override in `base-test.ts` rather than an `auto` fixture on\n * purpose: an auto fixture that depends on `page` would force a browser launch for every\n * API-only test, whereas an override only runs for tests that actually use a page.\n */\nexport function collectDiagnostics(\n page: Page,\n config: DiagnosticsConfig,\n): { collected: CollectedDiagnostics; report: (testInfo: TestInfo) => Promise<void> } {\n const collected: CollectedDiagnostics = { consoleErrors: [], pageErrors: [], failedRequests: [] };\n\n const isIgnored = (text: string): boolean =>\n config.ignoreConsolePatterns.some((pattern) => text.includes(pattern));\n\n page.on(\"console\", (message) => {\n if (message.type() !== \"error\") return;\n const text = message.text();\n if (!isIgnored(text)) collected.consoleErrors.push(text);\n });\n\n page.on(\"pageerror\", (error) => {\n collected.pageErrors.push(error.message);\n });\n\n page.on(\"requestfailed\", (request) => {\n // Navigations and in-flight requests cancelled by the browser land here too, so this is\n // recorded for context but never fails a test on its own.\n collected.failedRequests.push(\n `${request.method()} ${request.url()} — ${request.failure()?.errorText ?? \"failed\"}`,\n );\n });\n\n const report = async (testInfo: TestInfo): Promise<void> => {\n if (collected.consoleErrors.length > 0) {\n await attachText(testInfo, \"console-errors\", collected.consoleErrors.join(\"\\n\"));\n }\n if (collected.pageErrors.length > 0) {\n await attachText(testInfo, \"page-errors\", collected.pageErrors.join(\"\\n\"));\n }\n if (collected.failedRequests.length > 0) {\n await attachText(testInfo, \"failed-requests\", collected.failedRequests.join(\"\\n\"));\n }\n\n // Only escalate when the test would otherwise pass — turning an unrelated console error\n // into the reported failure of an already-failing test hides the real cause.\n if (testInfo.status !== \"passed\") return;\n\n if (config.failOnPageError && collected.pageErrors.length > 0) {\n throw new Error(`Uncaught page error(s):\\n${collected.pageErrors.join(\"\\n\")}`);\n }\n if (config.failOnConsoleError && collected.consoleErrors.length > 0) {\n throw new Error(`Console error(s):\\n${collected.consoleErrors.join(\"\\n\")}`);\n }\n };\n\n return { collected, report };\n}\n","import { expect as baseExpect } from \"@playwright/test\";\nimport type { ZodType } from \"zod\";\nimport type { ApiResponse } from \"../api/types.js\";\n\n/**\n * `expect` with a few framework-specific matchers added. Projects get these automatically by\n * importing `expect` from `@emesoft_company/playwright-core/fixtures` (or their own `fixtures/index.ts`),\n * so there's nothing to register per project.\n */\nexport const expect = baseExpect.extend({\n /**\n * Asserts the status of an `ApiResponse` from `apiClient.send()`, printing the body on\n * failure — otherwise a wrong status tells you nothing about why.\n */\n toHaveStatus(received: ApiResponse<unknown>, expected: number) {\n const pass = received.status === expected;\n return {\n pass,\n name: \"toHaveStatus\",\n expected,\n actual: received.status,\n message: () =>\n pass\n ? `Expected status not to be ${expected}`\n : `Expected ${received.method} ${received.url} to return ${expected}, got ${received.status}\\n` +\n `Body: ${JSON.stringify(received.data, null, 2)}`,\n };\n },\n\n /** Asserts a value matches a zod schema, listing the exact field-level issues on failure. */\n toMatchSchema(received: unknown, schema: ZodType<unknown>) {\n const result = schema.safeParse(received);\n return {\n pass: result.success,\n name: \"toMatchSchema\",\n message: () =>\n result.success\n ? \"Expected value not to match the schema\"\n : `Value did not match the schema:\\n${result.error.issues\n .map((issue) => ` - ${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`)\n .join(\"\\n\")}`,\n };\n },\n});\n","import { test as base } from \"@playwright/test\";\nimport { ApiClient } from \"../api/api-client.js\";\nimport type { TokenProvider } from \"../auth/types.js\";\nimport { loadConfig } from \"../config/loader.js\";\nimport type { AppConfig } from \"../config/schema.js\";\nimport { withRetry, type RetryOptions } from \"../errors/retry.js\";\nimport { createLogger, type Logger } from \"../logging/logger.js\";\nimport { linkTestCases } from \"../reporting/meta.js\";\nimport { resolveTokenProvider } from \"./auth.fixture.js\";\nimport { collectDiagnostics } from \"./diagnostics.fixture.js\";\n\n/** Registers a teardown callback; callbacks run in reverse order after the test. */\nexport type CleanupRegistrar = (task: () => unknown | Promise<unknown>) => void;\n\nexport interface CoreFixtures {\n appConfig: AppConfig;\n logger: Logger;\n tokenProvider: TokenProvider;\n apiClient: ApiClient;\n retry: <T>(fn: () => Promise<T>, options?: RetryOptions) => Promise<T>;\n /**\n * Registers teardown work (delete a record the test created, restore a toggled setting).\n * Runs in reverse registration order, and every task runs even if an earlier one throws —\n * a failed cleanup must not leave the rest of the data behind.\n */\n cleanup: CleanupRegistrar;\n /** Internal auto fixture: rewrites test-case annotations into links. Not meant to be used directly. */\n _testCaseLinks: void;\n}\n\nexport interface CoreWorkerFixtures {\n /** Config is loaded once per worker (env vars don't change mid-run) and shared by all tests in it. */\n workerConfig: AppConfig;\n}\n\n/**\n * Base test extended with the framework's core fixtures. Projects import this (not\n * `@playwright/test`'s `test` directly) and further `.extend()` it with their own\n * Page Objects/fixtures, or override any of these fixtures to change behavior\n * (see `docs/EXTENDING.md`).\n */\nexport const test = base.extend<CoreFixtures, CoreWorkerFixtures>({\n workerConfig: [\n async ({}, use) => {\n await use(loadConfig());\n },\n { scope: \"worker\" },\n ],\n\n appConfig: async ({ workerConfig }, use) => {\n await use(workerConfig);\n },\n\n logger: async ({ appConfig }, use, testInfo) => {\n await use(createLogger({ level: appConfig.logLevel, name: testInfo.title }));\n },\n\n tokenProvider: async ({ appConfig, logger }, use) => {\n await use(resolveTokenProvider(appConfig, logger));\n },\n\n apiClient: async ({ appConfig, tokenProvider, logger, request }, use) => {\n await use(\n new ApiClient({\n request,\n baseUrl: appConfig.apiBaseUrl ?? appConfig.baseUrl,\n tokenProvider,\n logger,\n retry: {\n retries: appConfig.retry.retries,\n minDelayMs: appConfig.retry.minDelayMs,\n maxDelayMs: appConfig.retry.maxDelayMs,\n },\n }),\n );\n },\n\n retry: async ({ logger }, use) => {\n const boundRetry = <T>(fn: () => Promise<T>, options?: RetryOptions) =>\n withRetry(fn, {\n onRetry: (error, attempt) => logger.warn({ err: error, attempt }, \"retrying operation\"),\n ...options,\n });\n await use(boundRetry);\n },\n\n cleanup: async ({ logger }, use) => {\n const tasks: Array<() => unknown | Promise<unknown>> = [];\n await use((task) => {\n tasks.push(task);\n });\n\n for (const task of tasks.reverse()) {\n try {\n await task();\n } catch (error) {\n // Swallowed deliberately: a failing cleanup should be visible but must not mask the\n // test result, nor stop the remaining cleanups from running.\n logger.error({ err: error }, \"cleanup task failed\");\n }\n }\n },\n\n // Overriding `page` (instead of an auto fixture) keeps API-only tests from launching a\n // browser: the override only runs for tests that actually request a page.\n page: async ({ page, appConfig }, use, testInfo) => {\n if (!appConfig.diagnostics.enabled) {\n await use(page);\n return;\n }\n const diagnostics = collectDiagnostics(page, appConfig.diagnostics);\n await use(page);\n await diagnostics.report(testInfo);\n },\n\n // testInfo-only, so this is safe to run automatically for every test.\n _testCaseLinks: [\n async ({ appConfig }, use, testInfo) => {\n linkTestCases(testInfo, appConfig.reporting.testCaseUrlTemplate);\n await use();\n },\n { auto: true },\n ],\n});\n\n// Re-exported from here (rather than straight from @playwright/test) so every project picks up\n// the framework's extra matchers without registering anything itself.\nexport { expect } from \"../expect/matchers.js\";\n"]}