@reasonabletech/config-playwright 0.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.
package/src/index.ts ADDED
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Base Playwright configuration for all applications
3
+ * @module @reasonabletech/config-playwright
4
+ */
5
+
6
+ import { type PlaywrightTestConfig, devices } from "@playwright/test";
7
+
8
+ /**
9
+ * Recursively makes all properties of `T` readonly.
10
+ *
11
+ * Useful for configuration objects defined with `as const`, ensuring callers
12
+ * don't accidentally mutate shared config.
13
+ */
14
+ export type DeepReadonly<T> = {
15
+ readonly [P in keyof T]: T[P] extends ReadonlyArray<infer U>
16
+ ? ReadonlyArray<DeepReadonly<U>>
17
+ : T[P] extends Array<infer U>
18
+ ? ReadonlyArray<DeepReadonly<U>>
19
+ : T[P] extends object
20
+ ? DeepReadonly<T[P]>
21
+ : T[P];
22
+ };
23
+
24
+ /**
25
+ * Immutable Playwright config type accepted by config helpers.
26
+ */
27
+ export type PlaywrightConfig = DeepReadonly<PlaywrightTestConfig>;
28
+
29
+ // Empty readonly config for default parameters
30
+ const EMPTY_CONFIG = {} as const satisfies PlaywrightConfig;
31
+
32
+ /**
33
+ * Service configuration for a test environment.
34
+ */
35
+ export interface TestEnvironmentServices {
36
+ /** Whether to use real backend services instead of mocks. */
37
+ useRealServices: boolean;
38
+ /** Whether to mock external (third-party) API calls. */
39
+ mockExternalAPIs: boolean;
40
+ }
41
+
42
+ /**
43
+ * Configuration for a single test environment (e.g. development, staging, production).
44
+ *
45
+ * Consumers define their own environment map and pass it to helpers like
46
+ * {@link createCrossAppConfig} in `cross-app.ts`.
47
+ */
48
+ export interface TestEnvironmentConfig {
49
+ /** Map of application names to their base URLs. */
50
+ baseUrls: Record<string, string>;
51
+ /** Service-layer settings for this environment. */
52
+ services: TestEnvironmentServices;
53
+ /** When true, only smoke tests should run (e.g. in production). */
54
+ smokeTestsOnly?: boolean;
55
+ }
56
+
57
+ /**
58
+ * Base configuration options that apply to all acceptance test environments
59
+ */
60
+ export const baseConfig: PlaywrightTestConfig = {
61
+ // Test discovery and execution
62
+ testDir: "./tests/acceptance",
63
+ testMatch: "**/*.{test,spec}.{ts,js}",
64
+
65
+ // Global test settings
66
+ fullyParallel: true,
67
+ forbidOnly: Boolean(process.env.CI),
68
+ retries: process.env.CI !== undefined ? 2 : 0,
69
+ workers: process.env.CI !== undefined ? 4 : undefined,
70
+
71
+ // Test execution timeouts
72
+ timeout: 30 * 1000, // 30 seconds for individual tests
73
+ expect: {
74
+ timeout: 5 * 1000, // 5 seconds for assertions
75
+ },
76
+
77
+ // Reporter configuration for different environments
78
+ reporter: [
79
+ ["html", { outputFolder: "./generated/playwright/reports" }],
80
+ ["json", { outputFile: "./generated/playwright/results.json" }],
81
+ process.env.CI !== undefined ? ["github"] : ["list"],
82
+ ],
83
+
84
+ // Output folder for test results
85
+ outputDir: "./generated/playwright/test-results",
86
+
87
+ // Global test options
88
+ use: {
89
+ // Browser context settings
90
+ viewport: { width: 1280, height: 720 },
91
+ ignoreHTTPSErrors: true,
92
+ headless: true, // Always headless by default (use --headed flag to override)
93
+
94
+ // Action timeouts
95
+ actionTimeout: 10 * 1000, // 10 seconds for actions
96
+ navigationTimeout: 30 * 1000, // 30 seconds for navigation
97
+
98
+ // Debugging and artifact collection - sensible defaults
99
+ trace: "on-first-retry",
100
+ video: "retain-on-failure",
101
+ screenshot: "only-on-failure",
102
+
103
+ // No authentication state by default (apps can override)
104
+ storageState: undefined,
105
+ },
106
+
107
+ // Browser and device matrix
108
+ // Local dev: Chromium only for speed
109
+ // CI: Full browser matrix for compatibility testing
110
+ projects:
111
+ process.env.CI !== undefined
112
+ ? [
113
+ // Desktop browsers
114
+ {
115
+ name: "chromium",
116
+ use: { ...devices["Desktop Chrome"] },
117
+ },
118
+ {
119
+ name: "firefox",
120
+ use: { ...devices["Desktop Firefox"] },
121
+ },
122
+ {
123
+ name: "webkit",
124
+ use: { ...devices["Desktop Safari"] },
125
+ },
126
+
127
+ // Mobile devices
128
+ {
129
+ name: "Mobile Chrome",
130
+ use: { ...devices["Pixel 5"] },
131
+ },
132
+ {
133
+ name: "Mobile Safari",
134
+ use: { ...devices["iPhone 12"] },
135
+ },
136
+
137
+ // Tablet devices
138
+ {
139
+ name: "iPad",
140
+ use: { ...devices["iPad Pro"] },
141
+ },
142
+ ]
143
+ : [
144
+ // Local development: Chromium only for fast iteration
145
+ {
146
+ name: "chromium",
147
+ use: { ...devices["Desktop Chrome"] },
148
+ },
149
+ ],
150
+
151
+ // Development server integration - common defaults for web apps
152
+ webServer:
153
+ process.env.CI !== undefined
154
+ ? undefined
155
+ : {
156
+ command: "pnpm dev",
157
+ reuseExistingServer: true,
158
+ timeout: 120 * 1000, // 2 minutes to start
159
+ },
160
+ };
161
+
162
+ /**
163
+ * Creates a merged configuration from the base and any custom options
164
+ * @param customConfig - Additional configuration options
165
+ * @returns A merged Playwright configuration
166
+ */
167
+ export function createPlaywrightConfig(
168
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
169
+ ): PlaywrightTestConfig {
170
+ return {
171
+ ...baseConfig,
172
+ ...customConfig,
173
+ use: {
174
+ ...baseConfig.use,
175
+ ...customConfig.use,
176
+ },
177
+ projects: customConfig.projects ?? baseConfig.projects,
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Creates a configuration optimized for CI/CD environments
183
+ * @param customConfig - Additional configuration options
184
+ * @returns A Playwright configuration optimized for CI/CD
185
+ */
186
+ export function createCIConfig(
187
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
188
+ ): PlaywrightTestConfig {
189
+ return createPlaywrightConfig({
190
+ ...customConfig,
191
+ fullyParallel: true,
192
+ retries: 3,
193
+ workers: 4,
194
+ use: {
195
+ ...customConfig.use,
196
+ trace: "retain-on-failure",
197
+ video: "retain-on-failure",
198
+ screenshot: "only-on-failure",
199
+ },
200
+ });
201
+ }
202
+
203
+ // Re-export for convenience
204
+ export { createCrossAppConfig } from "./cross-app.js";
205
+ export { createBaseConfig } from "./base.js";
206
+
207
+ export default createPlaywrightConfig;