@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.
@@ -0,0 +1,111 @@
1
+ # @reasonabletech/config-playwright Usage Guide
2
+
3
+ This guide covers the canonical setup patterns for `@reasonabletech/config-playwright` in greenfield projects.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add -D @reasonabletech/config-playwright @playwright/test
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```ts
14
+ // playwright.config.ts
15
+ import { createPlaywrightConfig } from "@reasonabletech/config-playwright";
16
+
17
+ export default createPlaywrightConfig({
18
+ use: {
19
+ baseURL: "http://localhost:3000",
20
+ },
21
+ });
22
+ ```
23
+
24
+ ## Core Config Factories
25
+
26
+ ### Standard Configuration
27
+
28
+ ```ts
29
+ import { createPlaywrightConfig } from "@reasonabletech/config-playwright";
30
+
31
+ export default createPlaywrightConfig();
32
+ ```
33
+
34
+ ### CI Configuration
35
+
36
+ ```ts
37
+ import { createCIConfig } from "@reasonabletech/config-playwright";
38
+
39
+ export default createCIConfig({
40
+ use: {
41
+ baseURL: "https://staging.example.com",
42
+ },
43
+ });
44
+ ```
45
+
46
+ ### Single-App Presets
47
+
48
+ ```ts
49
+ import {
50
+ createChromiumConfig,
51
+ createDesktopConfig,
52
+ createMobileConfig,
53
+ } from "@reasonabletech/config-playwright/base";
54
+
55
+ export default createDesktopConfig();
56
+ ```
57
+
58
+ ## Cross-App Workflows
59
+
60
+ `createCrossAppConfig` selects environment settings from `process.env.TEST_ENV` (default: `development`).
61
+
62
+ ```ts
63
+ import { createCrossAppConfig } from "@reasonabletech/config-playwright/cross-app";
64
+
65
+ const environments = {
66
+ development: {
67
+ baseUrls: {
68
+ app: "http://localhost:3000",
69
+ admin: "http://localhost:3001",
70
+ },
71
+ services: {
72
+ useRealServices: false,
73
+ mockExternalAPIs: true,
74
+ },
75
+ },
76
+ staging: {
77
+ baseUrls: {
78
+ app: "https://staging.example.com",
79
+ admin: "https://admin-staging.example.com",
80
+ },
81
+ services: {
82
+ useRealServices: true,
83
+ mockExternalAPIs: false,
84
+ },
85
+ },
86
+ } as const;
87
+
88
+ export default createCrossAppConfig({ environments });
89
+ ```
90
+
91
+ ## Generated Outputs
92
+
93
+ Default artifact locations:
94
+
95
+ - `generated/playwright/reports`
96
+ - `generated/playwright/results.json`
97
+ - `generated/playwright/test-results`
98
+
99
+ ## Troubleshooting
100
+
101
+ ### Unknown test environment
102
+
103
+ If `TEST_ENV` points to an environment key that is missing from your map, `createCrossAppConfig` throws. Ensure your environment map contains all expected deployment keys.
104
+
105
+ ### Local server startup
106
+
107
+ The base config starts `pnpm dev` outside CI. Override `webServer` if your app uses a different startup command.
108
+
109
+ ## Related Documentation
110
+
111
+ - [Package README](../../README.md)
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@reasonabletech/config-playwright",
3
+ "version": "0.1.0",
4
+ "description": "Shared Playwright configuration for E2E testing",
5
+ "keywords": [
6
+ "reasonabletech",
7
+ "config",
8
+ "typescript",
9
+ "playwright",
10
+ "e2e",
11
+ "browser-testing",
12
+ "test-automation"
13
+ ],
14
+ "type": "module",
15
+ "main": "dist/index.js",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/src/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ },
21
+ "./base": {
22
+ "types": "./dist/src/base.d.ts",
23
+ "import": "./dist/base.js"
24
+ },
25
+ "./cross-app": {
26
+ "types": "./dist/src/cross-app.d.ts",
27
+ "import": "./dist/cross-app.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "docs/**/*",
33
+ "src"
34
+ ],
35
+ "dependencies": {
36
+ "@axe-core/playwright": "^4.11.1",
37
+ "playwright-lighthouse": "^4.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@playwright/test": "1.58.2",
41
+ "@types/node": "25.3.1",
42
+ "@vitest/coverage-v8": "4.0.18",
43
+ "eslint": "10.0.2",
44
+ "lighthouse": "13.0.3",
45
+ "tsup": "8.5.1",
46
+ "typescript": "5.9.3",
47
+ "vitest": "4.0.18",
48
+ "@reasonabletech/config-eslint": "0.1.0",
49
+ "@reasonabletech/config-tsup": "0.1.0",
50
+ "@reasonabletech/config-typescript": "0.1.0",
51
+ "@reasonabletech/config-vitest": "0.1.0"
52
+ },
53
+ "peerDependencies": {
54
+ "@playwright/test": ">=1.58.2 <2",
55
+ "lighthouse": ">= 10.0.0"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public",
59
+ "registry": "https://registry.npmjs.org/"
60
+ },
61
+ "license": "MIT",
62
+ "author": "Reasonable Tech Company",
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "https://github.com/ReasonableTech/core-utils.git",
66
+ "directory": "packages/config-playwright"
67
+ },
68
+ "bugs": {
69
+ "url": "https://github.com/ReasonableTech/core-utils/issues"
70
+ },
71
+ "homepage": "https://github.com/ReasonableTech/core-utils/tree/main/packages/config-playwright",
72
+ "sideEffects": false,
73
+ "engines": {
74
+ "node": ">=22"
75
+ },
76
+ "scripts": {
77
+ "build": "tsup && tsc --emitDeclarationOnly -p tsconfig.build.json",
78
+ "clean": "rm -rf dist .turbo node_modules tsconfig.tsbuildinfo",
79
+ "dev": "tsc --watch",
80
+ "docs:coverage": "tsx ../../../scripts/analysis/check-doc-coverage.ts --html",
81
+ "lint": "eslint . --fix",
82
+ "lint:check": "eslint .",
83
+ "test": "vitest run",
84
+ "test:coverage": "vitest run --coverage",
85
+ "test:e2e": "vitest run tests/e2e",
86
+ "test:integration": "vitest run tests/integration",
87
+ "test:ui": "vitest --ui",
88
+ "test:unit": "vitest run tests/unit",
89
+ "test:watch": "vitest --watch",
90
+ "typecheck": "tsc --noEmit",
91
+ "verify:release": "pnpm typecheck && pnpm lint:check && pnpm test && pnpm build"
92
+ }
93
+ }
package/src/base.ts ADDED
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Base browser configuration for Playwright testing
3
+ * @module @reasonabletech/config-playwright/base
4
+ */
5
+
6
+ import { type PlaywrightTestConfig, devices } from "@playwright/test";
7
+ import { baseConfig, type PlaywrightConfig } from "./index.js";
8
+
9
+ // Empty readonly config for default parameters
10
+ const EMPTY_CONFIG = {} as const satisfies PlaywrightConfig;
11
+
12
+ /**
13
+ * Desktop-only browser configuration
14
+ */
15
+ export const desktopConfig: PlaywrightTestConfig = {
16
+ projects: [
17
+ {
18
+ name: "chromium",
19
+ use: { ...devices["Desktop Chrome"] },
20
+ },
21
+ {
22
+ name: "firefox",
23
+ use: { ...devices["Desktop Firefox"] },
24
+ },
25
+ {
26
+ name: "webkit",
27
+ use: { ...devices["Desktop Safari"] },
28
+ },
29
+ ],
30
+ };
31
+
32
+ /**
33
+ * Mobile-only browser configuration
34
+ */
35
+ export const mobileConfig: PlaywrightTestConfig = {
36
+ projects: [
37
+ {
38
+ name: "Mobile Chrome",
39
+ use: { ...devices["Pixel 5"] },
40
+ },
41
+ {
42
+ name: "Mobile Safari",
43
+ use: { ...devices["iPhone 12"] },
44
+ },
45
+ ],
46
+ };
47
+
48
+ /**
49
+ * Chromium-only configuration for faster development testing
50
+ */
51
+ export const chromiumOnlyConfig: PlaywrightTestConfig = {
52
+ projects: [
53
+ {
54
+ name: "chromium",
55
+ use: { ...devices["Desktop Chrome"] },
56
+ },
57
+ ],
58
+ };
59
+
60
+ /**
61
+ * Creates a base Playwright configuration for single-app testing
62
+ * @param customConfig - Additional configuration options
63
+ * @returns A Playwright configuration for standard single-app testing
64
+ */
65
+ export function createBaseConfig(
66
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
67
+ ): PlaywrightTestConfig {
68
+ return {
69
+ ...baseConfig,
70
+ ...customConfig,
71
+ use: {
72
+ ...baseConfig.use,
73
+ ...customConfig.use,
74
+ // Single-app specific settings
75
+ storageState: undefined, // No cross-app auth state by default
76
+ },
77
+ projects: customConfig.projects ?? baseConfig.projects,
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Creates a desktop-only configuration for faster testing cycles
83
+ * @param customConfig - Additional configuration options
84
+ * @returns A Playwright configuration for desktop browsers only
85
+ */
86
+ export function createDesktopConfig(
87
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
88
+ ): PlaywrightTestConfig {
89
+ return createBaseConfig({
90
+ ...customConfig,
91
+ projects: desktopConfig.projects,
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Creates a mobile-only configuration for mobile-specific testing
97
+ * @param customConfig - Additional configuration options
98
+ * @returns A Playwright configuration for mobile browsers only
99
+ */
100
+ export function createMobileConfig(
101
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
102
+ ): PlaywrightTestConfig {
103
+ return createBaseConfig({
104
+ ...customConfig,
105
+ projects: mobileConfig.projects,
106
+ });
107
+ }
108
+
109
+ /**
110
+ * Creates a Chromium-only configuration for development
111
+ * @param customConfig - Additional configuration options
112
+ * @returns A Playwright configuration for Chromium browser only
113
+ */
114
+ export function createChromiumConfig(
115
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
116
+ ): PlaywrightTestConfig {
117
+ return createBaseConfig({
118
+ ...customConfig,
119
+ projects: chromiumOnlyConfig.projects,
120
+ workers: 1, // Single worker for development
121
+ });
122
+ }
123
+
124
+ export default createBaseConfig;
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Cross-app Playwright configuration for multi-frontend testing
3
+ * @module @reasonabletech/config-playwright/cross-app
4
+ */
5
+
6
+ import { type PlaywrightTestConfig } from "@playwright/test";
7
+ import {
8
+ baseConfig,
9
+ type PlaywrightConfig,
10
+ type TestEnvironmentConfig,
11
+ } from "./index.js";
12
+
13
+ // Empty readonly config for default parameters
14
+ const EMPTY_CONFIG = {} as const satisfies PlaywrightConfig;
15
+
16
+ /**
17
+ * Cross-app specific configuration options
18
+ */
19
+ export const crossAppConfig: PlaywrightTestConfig = {
20
+ testDir: "./tests/acceptance/cross-app",
21
+ testMatch: "**/*.{test,spec}.{ts,js}",
22
+
23
+ use: {
24
+ // Extended timeout for cross-app navigation
25
+ actionTimeout: 10000,
26
+ navigationTimeout: 15000,
27
+
28
+ // Cross-domain configuration
29
+ extraHTTPHeaders: {
30
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
31
+ },
32
+
33
+ // Authentication state for cross-app flows
34
+ storageState: "tests/fixtures/auth/cross-app-authenticated.json",
35
+
36
+ // Enable video for complex cross-app debugging
37
+ video: "retain-on-failure",
38
+ trace: "retain-on-failure",
39
+ },
40
+ };
41
+
42
+ /**
43
+ * Accessibility testing configuration with axe-core
44
+ */
45
+ export const accessibilityConfig: PlaywrightTestConfig = {
46
+ testDir: "./tests/acceptance/accessibility",
47
+ testMatch: "**/*.{test,spec}.{ts,js}",
48
+
49
+ use: {
50
+ // Slower execution for accessibility checks
51
+ actionTimeout: 15000,
52
+ navigationTimeout: 20000,
53
+ },
54
+ };
55
+
56
+ /**
57
+ * Performance testing configuration for Lighthouse integration
58
+ */
59
+ export const performanceConfig: PlaywrightTestConfig = {
60
+ testDir: "./tests/acceptance/performance",
61
+ testMatch: "**/*.{test,spec}.{ts,js}",
62
+
63
+ // Sequential execution for accurate performance measurements
64
+ fullyParallel: false,
65
+ workers: 1,
66
+
67
+ use: {
68
+ // Extended timeouts for performance measurements
69
+ actionTimeout: 30000,
70
+ navigationTimeout: 45000,
71
+
72
+ // Minimal interference for accurate measurements
73
+ video: "off",
74
+ screenshot: "off",
75
+ trace: "off",
76
+ },
77
+ };
78
+
79
+ /**
80
+ * Options for creating a cross-domain authentication workflow configuration.
81
+ */
82
+ export interface AuthWorkflowOptions {
83
+ /** The cookie domain (e.g. ".example.com"). */
84
+ domain: string;
85
+ /**
86
+ * List of subdomains where authentication cookies should persist
87
+ * (e.g. ["accounts.example.com", "app.example.com"]).
88
+ */
89
+ expectedPersistence: readonly string[];
90
+ }
91
+
92
+ /**
93
+ * Configuration shape returned by {@link createAuthWorkflowConfig}.
94
+ */
95
+ export interface AuthWorkflowConfig {
96
+ /**
97
+ * Cookie settings used for cross-domain authentication.
98
+ */
99
+ readonly cookieConfig: {
100
+ readonly domain: string;
101
+ readonly secure: true;
102
+ readonly httpOnly: true;
103
+ readonly sameSite: "lax";
104
+ };
105
+ /**
106
+ * Subdomains where authentication should remain valid.
107
+ */
108
+ readonly expectedPersistence: readonly string[];
109
+ }
110
+
111
+ /**
112
+ * Creates a cross-domain authentication configuration for the given domain.
113
+ * @param options - Domain and persistence settings
114
+ * @returns An authentication workflow config object
115
+ */
116
+ export function createAuthWorkflowConfig(
117
+ options: AuthWorkflowOptions,
118
+ ): AuthWorkflowConfig {
119
+ return {
120
+ cookieConfig: {
121
+ domain: options.domain,
122
+ secure: true,
123
+ httpOnly: true,
124
+ sameSite: "lax" as const,
125
+ },
126
+ expectedPersistence: options.expectedPersistence,
127
+ } as const;
128
+ }
129
+
130
+ /**
131
+ * Options for creating a cross-app Playwright configuration.
132
+ */
133
+ export interface CrossAppConfigOptions {
134
+ /**
135
+ * Map of environment names to their configuration.
136
+ * The key used is determined by the `TEST_ENV` environment variable,
137
+ * falling back to `"development"`.
138
+ */
139
+ environments: Readonly<Record<string, TestEnvironmentConfig | undefined>>;
140
+ /** Additional Playwright configuration overrides. */
141
+ customConfig?: PlaywrightConfig;
142
+ }
143
+
144
+ /**
145
+ * Creates a Playwright configuration for cross-app workflows.
146
+ *
147
+ * Consumers must supply their own environment map so that base URLs are not
148
+ * hardcoded in this shared package.
149
+ * @param options - Environments map and optional custom config overrides
150
+ * @returns A Playwright configuration optimized for cross-app testing
151
+ */
152
+ export function createCrossAppConfig(
153
+ options: CrossAppConfigOptions,
154
+ ): PlaywrightTestConfig {
155
+ const { environments, customConfig = EMPTY_CONFIG } = options;
156
+
157
+ const environment = process.env.TEST_ENV ?? "development";
158
+ const envConfig = environments[environment];
159
+
160
+ if (envConfig === undefined) {
161
+ throw new Error(
162
+ `Unknown test environment "${environment}". Available environments: ${Object.keys(environments).join(", ")}`,
163
+ );
164
+ }
165
+
166
+ const defaultBaseUrl = Object.values(envConfig.baseUrls).at(0);
167
+
168
+ if (defaultBaseUrl === undefined) {
169
+ throw new Error(
170
+ `Environment "${environment}" must define at least one base URL`,
171
+ );
172
+ }
173
+
174
+ return {
175
+ ...baseConfig,
176
+ ...crossAppConfig,
177
+ ...customConfig,
178
+ use: {
179
+ ...baseConfig.use,
180
+ ...crossAppConfig.use,
181
+ ...(customConfig as PlaywrightTestConfig).use,
182
+ // Set base URL to the first entry in baseUrls (typically the landing page)
183
+ baseURL: defaultBaseUrl,
184
+ },
185
+ projects: [
186
+ // Desktop browsers for cross-app flows
187
+ {
188
+ name: "cross-app-chromium",
189
+ testDir: "./tests/acceptance/cross-app",
190
+ use: {
191
+ ...baseConfig.projects?.[0]?.use,
192
+ // Cross-app specific browser settings
193
+ viewport: { width: 1920, height: 1080 },
194
+ },
195
+ },
196
+ {
197
+ name: "cross-app-firefox",
198
+ testDir: "./tests/acceptance/cross-app",
199
+ use: {
200
+ ...baseConfig.projects?.[1]?.use,
201
+ viewport: { width: 1920, height: 1080 },
202
+ },
203
+ },
204
+ {
205
+ name: "cross-app-webkit",
206
+ testDir: "./tests/acceptance/cross-app",
207
+ use: {
208
+ ...baseConfig.projects?.[2]?.use,
209
+ viewport: { width: 1920, height: 1080 },
210
+ },
211
+ },
212
+ ],
213
+ };
214
+ }
215
+
216
+ /**
217
+ * Creates a configuration for accessibility testing with axe-core
218
+ * @param customConfig - Additional configuration options
219
+ * @returns A Playwright configuration with accessibility testing setup
220
+ */
221
+ export function createAccessibilityConfig(
222
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
223
+ ): PlaywrightTestConfig {
224
+ return {
225
+ ...baseConfig,
226
+ ...accessibilityConfig,
227
+ ...customConfig,
228
+ use: {
229
+ ...baseConfig.use,
230
+ ...accessibilityConfig.use,
231
+ ...(customConfig as PlaywrightTestConfig).use,
232
+ },
233
+ projects: [
234
+ {
235
+ name: "accessibility-chromium",
236
+ testDir: "./tests/acceptance/accessibility",
237
+ use: {
238
+ ...baseConfig.projects?.[0]?.use,
239
+ viewport: { width: 1280, height: 720 },
240
+ },
241
+ },
242
+ ],
243
+ };
244
+ }
245
+
246
+ /**
247
+ * Creates a configuration for performance testing with Lighthouse
248
+ * @param customConfig - Additional configuration options
249
+ * @returns A Playwright configuration with performance testing setup
250
+ */
251
+ export function createPerformanceConfig(
252
+ customConfig: PlaywrightConfig = EMPTY_CONFIG,
253
+ ): PlaywrightTestConfig {
254
+ return {
255
+ ...baseConfig,
256
+ ...performanceConfig,
257
+ ...customConfig,
258
+ use: {
259
+ ...baseConfig.use,
260
+ ...performanceConfig.use,
261
+ ...(customConfig as PlaywrightTestConfig).use,
262
+ },
263
+ projects: [
264
+ {
265
+ name: "performance-chromium",
266
+ testDir: "./tests/acceptance/performance",
267
+ use: {
268
+ ...baseConfig.projects?.[0]?.use,
269
+ viewport: { width: 1920, height: 1080 },
270
+ },
271
+ },
272
+ ],
273
+ };
274
+ }
275
+
276
+ /**
277
+ * Creates a configuration optimized for authentication workflow testing
278
+ * @param options - Cross-app config options (environments map and optional custom config)
279
+ * @returns A Playwright configuration for auth workflow testing
280
+ */
281
+ export function createAuthTestConfig(
282
+ options: CrossAppConfigOptions,
283
+ ): PlaywrightTestConfig {
284
+ const { environments, customConfig = EMPTY_CONFIG } = options;
285
+ return createCrossAppConfig({
286
+ environments,
287
+ customConfig: {
288
+ ...customConfig,
289
+ testDir: "./tests/acceptance/auth",
290
+ use: {
291
+ ...(customConfig as PlaywrightTestConfig).use,
292
+ // No pre-authenticated state for auth tests
293
+ storageState: undefined,
294
+ },
295
+ },
296
+ });
297
+ }
298
+
299
+ export default createCrossAppConfig;