@toolstackhq/create-qa-patterns 1.0.0 → 1.0.1

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 (34) hide show
  1. package/README.md +17 -10
  2. package/index.js +197 -1
  3. package/package.json +4 -3
  4. package/templates/playwright-template/.env.example +17 -0
  5. package/templates/playwright-template/.github/workflows/playwright-tests.yml +126 -0
  6. package/templates/playwright-template/README.md +234 -0
  7. package/templates/playwright-template/allurerc.mjs +10 -0
  8. package/templates/playwright-template/components/flash-message.ts +16 -0
  9. package/templates/playwright-template/config/environments.ts +41 -0
  10. package/templates/playwright-template/config/runtime-config.ts +53 -0
  11. package/templates/playwright-template/config/secret-manager.ts +28 -0
  12. package/templates/playwright-template/config/test-env.ts +9 -0
  13. package/templates/playwright-template/data/README.md +9 -0
  14. package/templates/playwright-template/data/factories/data-factory.ts +33 -0
  15. package/templates/playwright-template/data/generators/id-generator.ts +17 -0
  16. package/templates/playwright-template/data/generators/seeded-faker.ts +13 -0
  17. package/templates/playwright-template/docker/Dockerfile +21 -0
  18. package/templates/playwright-template/eslint.config.mjs +66 -0
  19. package/templates/playwright-template/fixtures/test-fixtures.ts +43 -0
  20. package/templates/playwright-template/lint/architecture-plugin.cjs +118 -0
  21. package/templates/playwright-template/package-lock.json +4724 -0
  22. package/templates/playwright-template/package.json +34 -0
  23. package/templates/playwright-template/pages/base-page.ts +24 -0
  24. package/templates/playwright-template/pages/login-page.ts +22 -0
  25. package/templates/playwright-template/pages/people-page.ts +39 -0
  26. package/templates/playwright-template/playwright.config.ts +46 -0
  27. package/templates/playwright-template/reporters/structured-reporter.ts +61 -0
  28. package/templates/playwright-template/scripts/generate-allure-report.mjs +57 -0
  29. package/templates/playwright-template/scripts/run-tests.sh +6 -0
  30. package/templates/playwright-template/tests/api-people.spec.ts +28 -0
  31. package/templates/playwright-template/tests/ui-journey.spec.ts +30 -0
  32. package/templates/playwright-template/tsconfig.json +31 -0
  33. package/templates/playwright-template/utils/logger.ts +55 -0
  34. package/templates/playwright-template/utils/test-step.ts +22 -0
package/README.md CHANGED
@@ -1,24 +1,31 @@
1
1
  # @toolstackhq/create-qa-patterns
2
2
 
3
- This package is the future scaffolding entrypoint for the `qa-patterns` repository.
3
+ CLI for generating QA framework templates from `qa-patterns`.
4
4
 
5
- ## Current status
5
+ ## Install
6
6
 
7
- The package is intentionally minimal today. It exists so the repository can reserve the CLI name and publish a stable install target while the scaffold commands evolve.
7
+ ```bash
8
+ npm install -g @toolstackhq/create-qa-patterns
9
+ ```
8
10
 
9
11
  ## Usage
10
12
 
11
13
  ```bash
12
- npm install -g @toolstackhq/create-qa-patterns
13
14
  create-qa-patterns
14
15
  ```
15
16
 
16
- Current output:
17
+ Generate into a new directory:
18
+
19
+ ```bash
20
+ create-qa-patterns my-project
21
+ ```
22
+
23
+ Generate the Playwright template explicitly:
17
24
 
18
- - prints a placeholder message
25
+ ```bash
26
+ create-qa-patterns playwright-template my-project
27
+ ```
19
28
 
20
- Planned direction:
29
+ ## Supported templates
21
30
 
22
- - scaffold a Playwright automation framework
23
- - scaffold reference demo applications
24
- - generate standardized config, lint, CI, and reporting assets
31
+ - `playwright-template`
package/index.js CHANGED
@@ -1,3 +1,199 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- console.log("create-qa-patterns is reserved for future repository scaffolding workflows.");
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const DEFAULT_TEMPLATE = "playwright-template";
7
+ const DEFAULT_GITIGNORE = `node_modules/
8
+
9
+ .env
10
+ .env.*
11
+ !.env.example
12
+
13
+ reports/
14
+ allure-results/
15
+ allure-report/
16
+ test-results/
17
+ playwright-report/
18
+ `;
19
+ const TEMPLATE_ALIASES = new Map([
20
+ ["playwright", DEFAULT_TEMPLATE],
21
+ ["pw", DEFAULT_TEMPLATE],
22
+ [DEFAULT_TEMPLATE, DEFAULT_TEMPLATE]
23
+ ]);
24
+
25
+ function printHelp() {
26
+ process.stdout.write(`create-qa-patterns
27
+
28
+ Usage:
29
+ create-qa-patterns
30
+ create-qa-patterns <target-directory>
31
+ create-qa-patterns <template> [target-directory]
32
+
33
+ Supported templates:
34
+ playwright-template
35
+ playwright
36
+ pw
37
+ `);
38
+ }
39
+
40
+ function resolveTemplate(value) {
41
+ return TEMPLATE_ALIASES.get(value);
42
+ }
43
+
44
+ function resolveScaffoldArgs(args) {
45
+ if (args.length === 0) {
46
+ return {
47
+ templateName: DEFAULT_TEMPLATE,
48
+ targetDirectory: process.cwd(),
49
+ generatedInCurrentDirectory: true
50
+ };
51
+ }
52
+
53
+ if (args.length === 1) {
54
+ const templateName = resolveTemplate(args[0]);
55
+ if (templateName) {
56
+ return {
57
+ templateName,
58
+ targetDirectory: process.cwd(),
59
+ generatedInCurrentDirectory: true
60
+ };
61
+ }
62
+
63
+ return {
64
+ templateName: DEFAULT_TEMPLATE,
65
+ targetDirectory: path.resolve(process.cwd(), args[0]),
66
+ generatedInCurrentDirectory: false
67
+ };
68
+ }
69
+
70
+ if (args.length === 2) {
71
+ const templateName = resolveTemplate(args[0]);
72
+ if (!templateName) {
73
+ throw new Error(`Unsupported template "${args[0]}". Use "playwright-template".`);
74
+ }
75
+
76
+ return {
77
+ templateName,
78
+ targetDirectory: path.resolve(process.cwd(), args[1]),
79
+ generatedInCurrentDirectory: false
80
+ };
81
+ }
82
+
83
+ throw new Error("Too many arguments. Run `create-qa-patterns --help` for usage.");
84
+ }
85
+
86
+ function ensureScaffoldTarget(targetDirectory) {
87
+ if (!fs.existsSync(targetDirectory)) {
88
+ fs.mkdirSync(targetDirectory, { recursive: true });
89
+ return;
90
+ }
91
+
92
+ const entries = fs
93
+ .readdirSync(targetDirectory)
94
+ .filter((entry) => ![".git", ".DS_Store"].includes(entry));
95
+
96
+ if (entries.length > 0) {
97
+ throw new Error(`Target directory is not empty: ${targetDirectory}`);
98
+ }
99
+ }
100
+
101
+ function toPackageName(targetDirectory) {
102
+ const baseName = path.basename(targetDirectory).toLowerCase();
103
+ const normalized = baseName
104
+ .replace(/[^a-z0-9-_]+/g, "-")
105
+ .replace(/^-+|-+$/g, "")
106
+ .replace(/-{2,}/g, "-");
107
+
108
+ return normalized || "playwright-template";
109
+ }
110
+
111
+ function updateJsonFile(filePath, update) {
112
+ const current = JSON.parse(fs.readFileSync(filePath, "utf8"));
113
+ const next = update(current);
114
+ fs.writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`, "utf8");
115
+ }
116
+
117
+ function customizeProject(targetDirectory) {
118
+ const packageName = toPackageName(targetDirectory);
119
+ const packageJsonPath = path.join(targetDirectory, "package.json");
120
+ const packageLockPath = path.join(targetDirectory, "package-lock.json");
121
+ const gitignorePath = path.join(targetDirectory, ".gitignore");
122
+
123
+ if (fs.existsSync(packageJsonPath)) {
124
+ updateJsonFile(packageJsonPath, (pkg) => ({
125
+ ...pkg,
126
+ name: packageName
127
+ }));
128
+ }
129
+
130
+ if (fs.existsSync(packageLockPath)) {
131
+ updateJsonFile(packageLockPath, (lock) => ({
132
+ ...lock,
133
+ name: packageName,
134
+ packages: lock.packages
135
+ ? {
136
+ ...lock.packages,
137
+ "": {
138
+ ...lock.packages[""],
139
+ name: packageName
140
+ }
141
+ }
142
+ : lock.packages
143
+ }));
144
+ }
145
+
146
+ if (!fs.existsSync(gitignorePath)) {
147
+ fs.writeFileSync(gitignorePath, DEFAULT_GITIGNORE, "utf8");
148
+ }
149
+ }
150
+
151
+ function scaffoldProject(templateName, targetDirectory) {
152
+ const templateDirectory = path.resolve(__dirname, "templates", templateName);
153
+
154
+ if (!fs.existsSync(templateDirectory)) {
155
+ throw new Error(`Template files are missing for "${templateName}".`);
156
+ }
157
+
158
+ ensureScaffoldTarget(targetDirectory);
159
+ fs.cpSync(templateDirectory, targetDirectory, { recursive: true });
160
+ customizeProject(targetDirectory);
161
+ }
162
+
163
+ function printNextSteps(targetDirectory, generatedInCurrentDirectory) {
164
+ process.stdout.write(`Generated ${DEFAULT_TEMPLATE} in ${targetDirectory}
165
+
166
+ Next steps:
167
+ `);
168
+
169
+ if (!generatedInCurrentDirectory) {
170
+ process.stdout.write(` cd ${path.relative(process.cwd(), targetDirectory) || "."}
171
+ `);
172
+ }
173
+
174
+ process.stdout.write(` npm install
175
+ npx playwright install
176
+ npm test
177
+ `);
178
+ }
179
+
180
+ function main() {
181
+ const args = process.argv.slice(2);
182
+
183
+ if (args.includes("--help") || args.includes("-h")) {
184
+ printHelp();
185
+ return;
186
+ }
187
+
188
+ const { templateName, targetDirectory, generatedInCurrentDirectory } = resolveScaffoldArgs(args);
189
+ scaffoldProject(templateName, targetDirectory);
190
+ printNextSteps(targetDirectory, generatedInCurrentDirectory);
191
+ }
192
+
193
+ try {
194
+ main();
195
+ } catch (error) {
196
+ const message = error instanceof Error ? error.message : String(error);
197
+ process.stderr.write(`${message}\n`);
198
+ process.exit(1);
199
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@toolstackhq/create-qa-patterns",
3
- "version": "1.0.0",
4
- "description": "Placeholder CLI for future test framework scaffolding.",
3
+ "version": "1.0.1",
4
+ "description": "CLI for generating QA framework templates.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "index.js",
19
+ "templates",
19
20
  "README.md",
20
21
  "LICENSE"
21
22
  ],
@@ -24,6 +25,6 @@
24
25
  },
25
26
  "scripts": {
26
27
  "start": "node ./index.js",
27
- "test": "node ./index.js"
28
+ "test": "node ./index.js --help"
28
29
  }
29
30
  }
@@ -0,0 +1,17 @@
1
+ TEST_ENV=dev
2
+ TEST_RUN_ID=local
3
+
4
+ DEV_UI_BASE_URL=http://127.0.0.1:3000
5
+ DEV_API_BASE_URL=http://127.0.0.1:3001
6
+ DEV_APP_USERNAME=tester
7
+ DEV_APP_PASSWORD=Password123!
8
+
9
+ STAGING_UI_BASE_URL=https://staging-ui.example.internal
10
+ STAGING_API_BASE_URL=https://staging-api.example.internal
11
+ STAGING_APP_USERNAME=staging-user
12
+ STAGING_APP_PASSWORD=replace-me
13
+
14
+ PROD_UI_BASE_URL=https://ui.example.internal
15
+ PROD_API_BASE_URL=https://api.example.internal
16
+ PROD_APP_USERNAME=prod-user
17
+ PROD_APP_PASSWORD=replace-me
@@ -0,0 +1,126 @@
1
+ name: Playwright Template Validation
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ paths:
7
+ - "templates/playwright-template/**"
8
+ - "test-apps/**"
9
+ - "package.json"
10
+
11
+ jobs:
12
+ playwright:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: "20"
21
+
22
+ - name: Install workspace dependencies
23
+ run: npm ci
24
+
25
+ - name: Install Playwright browsers
26
+ working-directory: templates/playwright-template
27
+ run: npx playwright install --with-deps chromium
28
+
29
+ - name: Start API demo server
30
+ run: npm run dev --workspace @toolstackhq/api-demo-server &
31
+
32
+ - name: Start UI demo app
33
+ run: npm run dev --workspace @toolstackhq/ui-demo-app &
34
+
35
+ - name: Wait for demo services
36
+ run: |
37
+ for target in http://127.0.0.1:3000/health http://127.0.0.1:3001/health; do
38
+ until curl --silent --fail "$target" >/dev/null; do
39
+ sleep 1
40
+ done
41
+ done
42
+
43
+ - name: Run Playwright validation
44
+ working-directory: templates/playwright-template
45
+ env:
46
+ TEST_ENV: dev
47
+ TEST_RUN_ID: ci
48
+ run: bash ./scripts/run-tests.sh
49
+
50
+ - name: Generate Allure report
51
+ if: always()
52
+ working-directory: templates/playwright-template
53
+ run: npm run report:allure
54
+
55
+ - name: Upload Playwright artifacts
56
+ if: always()
57
+ uses: actions/upload-artifact@v4
58
+ with:
59
+ name: playwright-template-artifacts
60
+ path: |
61
+ templates/playwright-template/reports
62
+ templates/playwright-template/allure-results
63
+ templates/playwright-template/test-results
64
+
65
+ playwright-docker:
66
+ runs-on: ubuntu-latest
67
+
68
+ steps:
69
+ - uses: actions/checkout@v4
70
+
71
+ - uses: actions/setup-node@v4
72
+ with:
73
+ node-version: "20"
74
+
75
+ - name: Install workspace dependencies
76
+ run: npm ci
77
+
78
+ - name: Start API demo server
79
+ run: npm run dev --workspace @toolstackhq/api-demo-server &
80
+
81
+ - name: Start UI demo app
82
+ run: npm run dev --workspace @toolstackhq/ui-demo-app &
83
+
84
+ - name: Wait for demo services
85
+ run: |
86
+ for target in http://127.0.0.1:3000/health http://127.0.0.1:3001/health; do
87
+ until curl --silent --fail "$target" >/dev/null; do
88
+ sleep 1
89
+ done
90
+ done
91
+
92
+ - name: Prepare Docker artifacts directories
93
+ run: |
94
+ rm -rf templates/playwright-template/reports templates/playwright-template/test-results templates/playwright-template/allure-results
95
+ mkdir -p templates/playwright-template/reports templates/playwright-template/test-results templates/playwright-template/allure-results
96
+
97
+ - name: Build Playwright template Docker image
98
+ run: docker build -t qa-patterns-playwright-template:ci -f templates/playwright-template/docker/Dockerfile templates/playwright-template
99
+
100
+ - name: Run Playwright template inside Docker
101
+ run: |
102
+ docker run --rm \
103
+ --add-host=host.docker.internal:host-gateway \
104
+ -e TEST_ENV=dev \
105
+ -e TEST_RUN_ID=ci-docker \
106
+ -e DEV_UI_BASE_URL=http://host.docker.internal:3000 \
107
+ -e DEV_API_BASE_URL=http://host.docker.internal:3001 \
108
+ -v "${GITHUB_WORKSPACE}/templates/playwright-template/reports:/workspace/reports" \
109
+ -v "${GITHUB_WORKSPACE}/templates/playwright-template/allure-results:/workspace/allure-results" \
110
+ -v "${GITHUB_WORKSPACE}/templates/playwright-template/test-results:/workspace/test-results" \
111
+ qa-patterns-playwright-template:ci
112
+
113
+ - name: Generate Allure report
114
+ if: always()
115
+ working-directory: templates/playwright-template
116
+ run: npm run report:allure
117
+
118
+ - name: Upload Docker Playwright artifacts
119
+ if: always()
120
+ uses: actions/upload-artifact@v4
121
+ with:
122
+ name: playwright-template-docker-artifacts
123
+ path: |
124
+ templates/playwright-template/reports
125
+ templates/playwright-template/allure-results
126
+ templates/playwright-template/test-results
@@ -0,0 +1,234 @@
1
+ # Playwright Template
2
+
3
+ This is a Playwright + TypeScript automation framework template for UI and API tests.
4
+
5
+ ## Table of contents
6
+
7
+ - [Feature set](#feature-set)
8
+ - [How it works](#how-it-works)
9
+ - [Project structure](#project-structure)
10
+ - [Quick start](#quick-start)
11
+ - [Environment and secrets](#environment-and-secrets)
12
+ - [Main commands](#main-commands)
13
+ - [Reports and artifacts](#reports-and-artifacts)
14
+ - [Add a new test](#add-a-new-test)
15
+ - [Extend the framework](#extend-the-framework)
16
+ - [CI and Docker](#ci-and-docker)
17
+
18
+ ## Feature set
19
+
20
+ - Playwright + TypeScript setup
21
+ - page object pattern with selectors kept out of tests
22
+ - shared fixtures for config, logging, data, and page objects
23
+ - generic data factory pattern with `DataFactory`
24
+ - multi-environment runtime config with `dev`, `staging`, and `prod`
25
+ - env-based secret resolution with a replaceable `SecretProvider`
26
+ - Playwright HTML report by default
27
+ - optional Allure single-file report
28
+ - traces, screenshots, videos, and structured logs for debugging
29
+ - ESLint rules that protect framework conventions
30
+ - GitHub Actions workflow and Docker support
31
+
32
+ ## How it works
33
+
34
+ - tests import shared fixtures from `fixtures/test-fixtures.ts`
35
+ - page objects in `pages/` own locators and user actions
36
+ - runtime config is loaded from `config/runtime-config.ts`
37
+ - application URLs and credentials are resolved from `TEST_ENV`
38
+ - reports and artifacts are written under `reports/`, `allure-results/`, and `test-results/`
39
+
40
+ ## Project structure
41
+
42
+ ```text
43
+ playwright-template
44
+ ├── tests
45
+ ├── pages
46
+ ├── components
47
+ ├── fixtures
48
+ ├── data
49
+ ├── config
50
+ ├── reporters
51
+ ├── utils
52
+ ├── lint
53
+ ├── scripts
54
+ ├── docker
55
+ ├── playwright.config.ts
56
+ └── package.json
57
+ ```
58
+
59
+ ## Quick start
60
+
61
+ 1. Install dependencies.
62
+
63
+ ```bash
64
+ npm install
65
+ ```
66
+
67
+ 2. Start the target apps you want the tests to hit.
68
+
69
+ For the local demo apps from the root repo:
70
+
71
+ ```bash
72
+ npm run dev:ui
73
+ ```
74
+
75
+ ```bash
76
+ npm run dev:api
77
+ ```
78
+
79
+ 3. Run tests.
80
+
81
+ ```bash
82
+ npm test
83
+ ```
84
+
85
+ Default local values:
86
+
87
+ - UI base URL: `http://127.0.0.1:3000`
88
+ - API base URL: `http://127.0.0.1:3001`
89
+ - username: `tester`
90
+ - password: `Password123!`
91
+
92
+ ## Environment and secrets
93
+
94
+ The template supports:
95
+
96
+ - `TEST_ENV=dev`
97
+ - `TEST_ENV=staging`
98
+ - `TEST_ENV=prod`
99
+
100
+ Runtime values are resolved in this order:
101
+
102
+ 1. environment-specific variables such as `DEV_UI_BASE_URL`
103
+ 2. generic variables such as `UI_BASE_URL`
104
+ 3. built-in defaults from `config/environments.ts`
105
+
106
+ The same pattern is used for credentials:
107
+
108
+ 1. `DEV_APP_USERNAME` or `DEV_APP_PASSWORD`
109
+ 2. `APP_USERNAME` or `APP_PASSWORD`
110
+ 3. built-in defaults for the selected environment
111
+
112
+ For local overrides, copy:
113
+
114
+ ```bash
115
+ .env.example
116
+ ```
117
+
118
+ to:
119
+
120
+ ```bash
121
+ .env
122
+ ```
123
+
124
+ The template loads:
125
+
126
+ - `.env`
127
+ - `.env.<TEST_ENV>`
128
+
129
+ Example:
130
+
131
+ ```bash
132
+ TEST_ENV=staging \
133
+ STAGING_UI_BASE_URL=https://staging-ui.example.internal \
134
+ STAGING_API_BASE_URL=https://staging-api.example.internal \
135
+ STAGING_APP_USERNAME=my-user \
136
+ STAGING_APP_PASSWORD=my-password \
137
+ npx playwright test
138
+ ```
139
+
140
+ If your team uses a real secret system later, replace the implementation behind `config/secret-manager.ts`.
141
+
142
+ ## Main commands
143
+
144
+ ```bash
145
+ npm test
146
+ npm run test:smoke
147
+ npm run test:regression
148
+ npm run test:critical
149
+ npm run lint
150
+ npm run typecheck
151
+ npm run report:playwright
152
+ npm run report:allure
153
+ ```
154
+
155
+ ## Reports and artifacts
156
+
157
+ Default Playwright HTML report:
158
+
159
+ ```bash
160
+ npm run report:playwright
161
+ ```
162
+
163
+ Optional Allure report:
164
+
165
+ ```bash
166
+ npm run report:allure
167
+ ```
168
+
169
+ Outputs:
170
+
171
+ - Playwright HTML: `reports/html`
172
+ - Allure single file: `reports/allure/index.html`
173
+ - structured event log: `reports/logs/playwright-events.jsonl`
174
+ - raw Allure results: `allure-results`
175
+ - traces, screenshots, videos: `test-results`
176
+
177
+ If you only want Playwright reporting, remove the `allure-playwright` reporter entry in `playwright.config.ts`.
178
+
179
+ ## Add a new test
180
+
181
+ Create tests under `tests/` and import the shared fixtures:
182
+
183
+ ```ts
184
+ import { expect, test } from "../fixtures/test-fixtures";
185
+ ```
186
+
187
+ Keep the pattern simple:
188
+
189
+ - create data with `dataFactory`
190
+ - interact through page objects
191
+ - assert in the test
192
+
193
+ Example shape:
194
+
195
+ ```ts
196
+ test("do something @smoke", async ({ dataFactory, loginPage }) => {
197
+ const person = dataFactory.person();
198
+ // use page objects here
199
+ });
200
+ ```
201
+
202
+ ## Extend the framework
203
+
204
+ Common extension points:
205
+
206
+ - add page objects under `pages/`
207
+ - add reusable UI pieces under `components/`
208
+ - extend fixtures in `fixtures/test-fixtures.ts`
209
+ - add more generic builders under `data/factories/`
210
+ - add stronger custom lint rules in `lint/architecture-plugin.cjs`
211
+ - add custom reporters under `reporters/`
212
+
213
+ Recommended rules:
214
+
215
+ - keep selectors in page objects
216
+ - keep assertions in test files
217
+ - prefer semantic selectors such as `getByRole`, `getByLabel`, and `data-testid`
218
+ - keep the data layer generic until the project really needs domain-specific factories
219
+
220
+ ## CI and Docker
221
+
222
+ The CI entrypoint is:
223
+
224
+ ```bash
225
+ scripts/run-tests.sh
226
+ ```
227
+
228
+ Docker support is included in:
229
+
230
+ ```bash
231
+ docker/Dockerfile
232
+ ```
233
+
234
+ The included GitHub Actions workflow installs dependencies, runs tests, and uploads artifacts. The Docker path is also validated in CI so the container setup does not drift from the normal runner path.
@@ -0,0 +1,10 @@
1
+ export default {
2
+ name: "qa-patterns Playwright Template",
3
+ plugins: {
4
+ awesome: {
5
+ options: {
6
+ singleFile: true
7
+ }
8
+ }
9
+ }
10
+ };
@@ -0,0 +1,16 @@
1
+ import type { Locator, Page } from "@playwright/test";
2
+
3
+ export class FlashMessage {
4
+ private readonly message: Locator;
5
+
6
+ constructor(page: Page) {
7
+ this.message = page.getByTestId("flash-message");
8
+ }
9
+
10
+ async getText(): Promise<string | null> {
11
+ if (!(await this.message.count())) {
12
+ return null;
13
+ }
14
+ return this.message.textContent();
15
+ }
16
+ }