@sridharkikkeri/playwright-common 1.0.39 ā 1.0.41
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/create-healthedge-tests.js +267 -100
- package/package.json +1 -1
- package/src/tests/visual.spec.ts +4 -4
|
@@ -7,130 +7,297 @@ const { execSync } = require('child_process');
|
|
|
7
7
|
const projectName = process.argv[2] || 'my-healthedge-tests';
|
|
8
8
|
const projectPath = path.join(process.cwd(), projectName);
|
|
9
9
|
|
|
10
|
-
console.log(`\nš Creating HealthEdge Playwright project
|
|
11
|
-
|
|
12
|
-
// Recursive Copy Helper
|
|
13
|
-
function copyRecursiveSync(src, dest) {
|
|
14
|
-
if (!fs.existsSync(src)) return;
|
|
15
|
-
const stats = fs.statSync(src);
|
|
16
|
-
if (stats.isDirectory()) {
|
|
17
|
-
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
18
|
-
fs.readdirSync(src).forEach((child) => {
|
|
19
|
-
copyRecursiveSync(path.join(src, child), path.join(dest, child));
|
|
20
|
-
});
|
|
21
|
-
} else {
|
|
22
|
-
fs.copyFileSync(src, dest);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
10
|
+
console.log(`\nš Creating HealthEdge Playwright project: ${projectName}\n`);
|
|
25
11
|
|
|
26
|
-
//
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
12
|
+
// Create project structure matching smokeTest
|
|
13
|
+
const dirs = [
|
|
14
|
+
'src/main/pages',
|
|
15
|
+
'src/main/api/auth',
|
|
16
|
+
'src/main/builders',
|
|
17
|
+
'src/main/config',
|
|
18
|
+
'src/main/fixtures',
|
|
19
|
+
'src/main/i18n',
|
|
20
|
+
'src/main/reporting',
|
|
21
|
+
'src/main/selfhealing',
|
|
22
|
+
'src/main/utils',
|
|
23
|
+
'src/main/visual',
|
|
24
|
+
'src/main/workflows',
|
|
25
|
+
'src/main/wrappers',
|
|
26
|
+
'src/tests/specs',
|
|
27
|
+
'src/tests/data',
|
|
28
|
+
'config',
|
|
29
|
+
'allure-results',
|
|
30
|
+
'allure-report'
|
|
34
31
|
];
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (!fs.existsSync(fullPath)) {
|
|
39
|
-
fs.mkdirSync(fullPath, { recursive: true });
|
|
40
|
-
}
|
|
33
|
+
dirs.forEach(dir => {
|
|
34
|
+
fs.mkdirSync(path.join(projectPath, dir), { recursive: true });
|
|
41
35
|
});
|
|
42
36
|
|
|
43
|
-
//
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
// package.json
|
|
38
|
+
const packageJson = {
|
|
39
|
+
name: projectName,
|
|
40
|
+
version: '1.0.0',
|
|
41
|
+
scripts: {
|
|
42
|
+
'test': 'playwright test',
|
|
43
|
+
'test:dev': 'TEST_ENV=dev playwright test',
|
|
44
|
+
'test:qa': 'TEST_ENV=qa playwright test',
|
|
45
|
+
'test:auto': 'TEST_ENV=auto playwright test',
|
|
46
|
+
'test:staging': 'TEST_ENV=staging playwright test',
|
|
47
|
+
'test:prod': 'TEST_ENV=prod playwright test',
|
|
48
|
+
'report': 'allure generate allure-results --clean -o allure-report && allure open allure-report',
|
|
49
|
+
'lint': 'eslint .',
|
|
50
|
+
'lint:fix': 'eslint . --fix'
|
|
51
|
+
},
|
|
52
|
+
dependencies: {
|
|
53
|
+
'@sridharkikkeri/playwright-common': 'latest',
|
|
54
|
+
'@playwright/test': '^1.42.0',
|
|
55
|
+
'allure-playwright': '^3.4.5'
|
|
56
|
+
},
|
|
57
|
+
devDependencies: {
|
|
58
|
+
'@typescript-eslint/eslint-plugin': '^8.55.0',
|
|
59
|
+
'@typescript-eslint/parser': '^8.55.0',
|
|
60
|
+
'eslint': '^8.57.1',
|
|
61
|
+
'typescript': '^5.3.0'
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
fs.writeFileSync(
|
|
66
|
+
path.join(projectPath, 'package.json'),
|
|
67
|
+
JSON.stringify(packageJson, null, 2)
|
|
68
|
+
);
|
|
47
69
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
console.log('š Copying framework source logic...');
|
|
51
|
-
copyRecursiveSync(path.join(frameworkSrc, 'core'), path.join(projectPath, 'src/core'));
|
|
52
|
-
copyRecursiveSync(path.join(frameworkSrc, 'fixtures'), path.join(projectPath, 'src/fixtures'));
|
|
70
|
+
// playwright.config.ts
|
|
71
|
+
const playwrightConfig = `import { defineConfig } from '@playwright/test';
|
|
53
72
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
73
|
+
export default defineConfig({
|
|
74
|
+
testDir: './src/tests/specs',
|
|
75
|
+
timeout: 30000,
|
|
76
|
+
retries: process.env.CI ? 2 : 0,
|
|
77
|
+
workers: process.env.CI ? 1 : undefined,
|
|
78
|
+
reporter: [
|
|
79
|
+
['html'],
|
|
80
|
+
['allure-playwright', { outputFolder: 'allure-results' }]
|
|
81
|
+
],
|
|
82
|
+
use: {
|
|
83
|
+
baseURL: process.env.BASE_URL || 'https://example.com',
|
|
84
|
+
trace: 'on-first-retry',
|
|
85
|
+
screenshot: 'only-on-failure',
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
`;
|
|
89
|
+
|
|
90
|
+
fs.writeFileSync(path.join(projectPath, 'playwright.config.ts'), playwrightConfig);
|
|
91
|
+
|
|
92
|
+
// Create all environment configs
|
|
93
|
+
const envConfigs = {
|
|
94
|
+
dev: {
|
|
95
|
+
healingEnabled: true,
|
|
96
|
+
environment: 'dev',
|
|
97
|
+
baseUrl: 'https://dev.example.com',
|
|
98
|
+
apiUrl: 'https://api-dev.example.com',
|
|
99
|
+
timeout: 30000,
|
|
100
|
+
retries: 2
|
|
101
|
+
},
|
|
102
|
+
qa: {
|
|
103
|
+
healingEnabled: true,
|
|
104
|
+
environment: 'qa',
|
|
105
|
+
baseUrl: 'https://qa.example.com',
|
|
106
|
+
apiUrl: 'https://api-qa.example.com',
|
|
107
|
+
timeout: 30000,
|
|
108
|
+
retries: 2
|
|
109
|
+
},
|
|
110
|
+
auto: {
|
|
111
|
+
healingEnabled: true,
|
|
112
|
+
environment: 'auto',
|
|
113
|
+
baseUrl: 'https://auto.example.com',
|
|
114
|
+
apiUrl: 'https://api-auto.example.com',
|
|
115
|
+
timeout: 30000,
|
|
116
|
+
retries: 2
|
|
117
|
+
},
|
|
118
|
+
staging: {
|
|
119
|
+
healingEnabled: true,
|
|
120
|
+
environment: 'staging',
|
|
121
|
+
baseUrl: 'https://staging.example.com',
|
|
122
|
+
apiUrl: 'https://api-staging.example.com',
|
|
123
|
+
timeout: 30000,
|
|
124
|
+
retries: 1
|
|
125
|
+
},
|
|
126
|
+
prod: {
|
|
127
|
+
healingEnabled: false,
|
|
128
|
+
environment: 'prod',
|
|
129
|
+
baseUrl: 'https://example.com',
|
|
130
|
+
apiUrl: 'https://api.example.com',
|
|
131
|
+
timeout: 60000,
|
|
132
|
+
retries: 0
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
Object.entries(envConfigs).forEach(([env, config]) => {
|
|
137
|
+
fs.writeFileSync(
|
|
138
|
+
path.join(projectPath, 'config', `${env}.json`),
|
|
139
|
+
JSON.stringify(config, null, 2)
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Sample Page Object
|
|
144
|
+
const samplePage = `import { Page } from '@playwright/test';
|
|
145
|
+
import { BasePage } from '@sridharkikkeri/playwright-common';
|
|
146
|
+
|
|
147
|
+
export class HomePage extends BasePage {
|
|
148
|
+
constructor(page: Page) {
|
|
149
|
+
super(page, 'HomePage');
|
|
57
150
|
}
|
|
58
|
-
}
|
|
59
151
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
152
|
+
private readonly searchInput = this.element('[data-testid="search"]');
|
|
153
|
+
private readonly searchBtn = this.element('button[type="submit"]');
|
|
154
|
+
|
|
155
|
+
async search(query: string) {
|
|
156
|
+
await this.searchInput.fill(query, 'Enter search query');
|
|
157
|
+
await this.searchBtn.click('Click search button');
|
|
158
|
+
}
|
|
64
159
|
}
|
|
160
|
+
`;
|
|
65
161
|
|
|
66
|
-
|
|
67
|
-
const strategyFiles = [
|
|
68
|
-
'HEALING_CACHE_STRATEGY.md',
|
|
69
|
-
'VISUAL_TESTING.md',
|
|
70
|
-
'README.md'
|
|
71
|
-
];
|
|
162
|
+
fs.writeFileSync(path.join(projectPath, 'src/main/pages/HomePage.ts'), samplePage);
|
|
72
163
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
164
|
+
// Sample Test
|
|
165
|
+
const sampleTest = `import { test } from '@sridharkikkeri/playwright-common';
|
|
166
|
+
import { HomePage } from '../../main/pages/HomePage';
|
|
167
|
+
|
|
168
|
+
test.describe('Sample Tests', () => {
|
|
169
|
+
test('Search functionality', async ({ page }) => {
|
|
170
|
+
const homePage = new HomePage(page);
|
|
171
|
+
await page.goto('/');
|
|
172
|
+
await homePage.search('playwright');
|
|
173
|
+
});
|
|
79
174
|
});
|
|
175
|
+
`;
|
|
80
176
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
'lint': 'eslint . --ext .ts'
|
|
90
|
-
},
|
|
91
|
-
dependencies: {
|
|
92
|
-
'@playwright/test': '^1.42.0',
|
|
93
|
-
'allure-playwright': '^3.4.5'
|
|
94
|
-
},
|
|
95
|
-
devDependencies: {
|
|
96
|
-
'@typescript-eslint/eslint-plugin': '^8.55.0',
|
|
97
|
-
'@typescript-eslint/parser': '^8.55.0',
|
|
98
|
-
'eslint': '^8.57.1',
|
|
99
|
-
'typescript': '^5.3.0'
|
|
100
|
-
}
|
|
177
|
+
fs.writeFileSync(path.join(projectPath, 'src/tests/specs/sample.spec.ts'), sampleTest);
|
|
178
|
+
|
|
179
|
+
// Test data
|
|
180
|
+
const testData = {
|
|
181
|
+
users: [
|
|
182
|
+
{ username: 'testuser1', password: 'password123' },
|
|
183
|
+
{ username: 'testuser2', password: 'password456' }
|
|
184
|
+
]
|
|
101
185
|
};
|
|
102
|
-
fs.writeFileSync(path.join(projectPath, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
103
186
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const playwrightConfig = `import { defineConfig } from '@playwright/test';
|
|
109
|
-
export default defineConfig({
|
|
110
|
-
testDir: './src/tests',
|
|
111
|
-
timeout: 30000,
|
|
112
|
-
reporter: [['html'], ['allure-playwright', { outputFolder: 'allure-results' }]],
|
|
113
|
-
use: { trace: 'on-first-retry', screenshot: 'only-on-failure' }
|
|
114
|
-
});`;
|
|
115
|
-
fs.writeFileSync(path.join(projectPath, 'playwright.config.ts'), playwrightConfig);
|
|
187
|
+
fs.writeFileSync(
|
|
188
|
+
path.join(projectPath, 'src/tests/data/testdata.json'),
|
|
189
|
+
JSON.stringify(testData, null, 2)
|
|
190
|
+
);
|
|
116
191
|
|
|
192
|
+
// tsconfig.json
|
|
117
193
|
const tsConfig = {
|
|
118
|
-
|
|
119
|
-
|
|
194
|
+
compilerOptions: {
|
|
195
|
+
target: 'ES2020',
|
|
196
|
+
module: 'commonjs',
|
|
197
|
+
lib: ['ES2020'],
|
|
198
|
+
strict: true,
|
|
199
|
+
esModuleInterop: true,
|
|
200
|
+
skipLibCheck: true,
|
|
201
|
+
forceConsistentCasingInFileNames: true,
|
|
202
|
+
resolveJsonModule: true,
|
|
203
|
+
baseUrl: '.',
|
|
204
|
+
paths: {
|
|
205
|
+
'@main/*': ['src/main/*'],
|
|
206
|
+
'@tests/*': ['src/tests/*']
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
include: ['src/**/*']
|
|
120
210
|
};
|
|
121
|
-
fs.writeFileSync(path.join(projectPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2));
|
|
122
211
|
|
|
123
|
-
|
|
212
|
+
fs.writeFileSync(
|
|
213
|
+
path.join(projectPath, 'tsconfig.json'),
|
|
214
|
+
JSON.stringify(tsConfig, null, 2)
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
// .gitignore
|
|
218
|
+
const gitignore = `node_modules/
|
|
219
|
+
allure-results/
|
|
220
|
+
allure-report/
|
|
221
|
+
test-results/
|
|
222
|
+
playwright-report/
|
|
223
|
+
.env
|
|
224
|
+
*.log
|
|
225
|
+
`;
|
|
226
|
+
|
|
124
227
|
fs.writeFileSync(path.join(projectPath, '.gitignore'), gitignore);
|
|
125
228
|
|
|
126
|
-
|
|
127
|
-
|
|
229
|
+
// README
|
|
230
|
+
const readme = `# ${projectName}
|
|
231
|
+
|
|
232
|
+
Generated with \`npx create-healthedge-tests\`
|
|
233
|
+
|
|
234
|
+
## Project Structure
|
|
235
|
+
|
|
236
|
+
\`\`\`
|
|
237
|
+
${projectName}/
|
|
238
|
+
āāā config/ # Environment configs (dev, qa, auto, staging, prod)
|
|
239
|
+
āāā src/
|
|
240
|
+
ā āāā main/ # Framework code
|
|
241
|
+
ā ā āāā pages/ # Page Object Models
|
|
242
|
+
ā ā āāā api/ # API client & auth
|
|
243
|
+
ā ā āāā builders/ # Test data builders
|
|
244
|
+
ā ā āāā workflows/ # Reusable workflows
|
|
245
|
+
ā ā āāā ... # Other framework modules
|
|
246
|
+
ā āāā tests/
|
|
247
|
+
ā āāā specs/ # Test specifications
|
|
248
|
+
ā āāā data/ # Test data
|
|
249
|
+
āāā allure-results/ # Test reports
|
|
250
|
+
āāā playwright.config.ts
|
|
251
|
+
\`\`\`
|
|
252
|
+
|
|
253
|
+
## Quick Start
|
|
254
|
+
|
|
255
|
+
\`\`\`bash
|
|
256
|
+
npm install
|
|
257
|
+
npm run test:dev
|
|
258
|
+
npm run report
|
|
259
|
+
\`\`\`
|
|
260
|
+
|
|
261
|
+
## Environment-Specific Tests
|
|
262
|
+
|
|
263
|
+
\`\`\`bash
|
|
264
|
+
npm run test:dev # Uses config/dev.json
|
|
265
|
+
npm run test:qa # Uses config/qa.json
|
|
266
|
+
npm run test:auto # Uses config/auto.json
|
|
267
|
+
npm run test:staging # Uses config/staging.json
|
|
268
|
+
npm run test:prod # Uses config/prod.json
|
|
269
|
+
\`\`\`
|
|
270
|
+
|
|
271
|
+
## Features
|
|
272
|
+
|
|
273
|
+
ā
AI-Powered Self-Healing
|
|
274
|
+
ā
Visual Regression Testing
|
|
275
|
+
ā
API Testing Support
|
|
276
|
+
ā
Allure Reporting
|
|
277
|
+
ā
Multi-Environment Configs
|
|
278
|
+
ā
Page Object Pattern
|
|
279
|
+
ā
Test Data Builders
|
|
280
|
+
ā
Reusable Workflows
|
|
281
|
+
|
|
282
|
+
## Documentation
|
|
283
|
+
|
|
284
|
+
- [Framework Package](https://www.npmjs.com/package/@sridharkikkeri/playwright-common)
|
|
285
|
+
- [Clean Imports Guide](https://github.com/healthedge/playwright-framework/blob/main/CLEAN_IMPORTS.md)
|
|
286
|
+
- [Visual Testing](https://github.com/healthedge/playwright-framework/blob/main/VISUAL_TESTING.md)
|
|
287
|
+
`;
|
|
288
|
+
|
|
289
|
+
fs.writeFileSync(path.join(projectPath, 'README.md'), readme);
|
|
290
|
+
|
|
291
|
+
console.log('ā
Project structure created');
|
|
292
|
+
console.log('\nš¦ Installing dependencies...\n');
|
|
128
293
|
|
|
129
294
|
try {
|
|
130
|
-
|
|
131
|
-
|
|
295
|
+
execSync('npm install', { cwd: projectPath, stdio: 'inherit' });
|
|
296
|
+
console.log('\nā
Dependencies installed');
|
|
132
297
|
} catch (error) {
|
|
133
|
-
|
|
298
|
+
console.log('\nā ļø Run "npm install" manually in the project directory');
|
|
134
299
|
}
|
|
135
300
|
|
|
136
|
-
console.log(`\nš
|
|
301
|
+
console.log(`\nš Project ready! Next steps:\n`);
|
|
302
|
+
console.log(` cd ${projectName}`);
|
|
303
|
+
console.log(` npm run test:dev\n`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sridharkikkeri/playwright-common",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.41",
|
|
4
4
|
"description": "Production-grade Playwright framework with AI-powered self-healing, visual regression, and enterprise features",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/src/tests/visual.spec.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { test } from '@playwright/test';
|
|
2
2
|
import { VisualTesting } from '../core/visual/VisualTesting';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
test('Full page comparison', async ({ page }) => {
|
|
5
5
|
const visual = new VisualTesting(page);
|
|
6
6
|
|
|
7
7
|
await page.goto('https://playwright.dev');
|
|
@@ -13,7 +13,7 @@ resilientTest('Full page comparison', async ({ page }) => {
|
|
|
13
13
|
});
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
test('Element comparison', async ({ page }) => {
|
|
17
17
|
const visual = new VisualTesting(page);
|
|
18
18
|
|
|
19
19
|
await page.goto('https://playwright.dev');
|
|
@@ -24,7 +24,7 @@ resilientTest('Element comparison', async ({ page }) => {
|
|
|
24
24
|
});
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
test('Viewport comparison with masking', async ({ page }) => {
|
|
28
28
|
const visual = new VisualTesting(page);
|
|
29
29
|
|
|
30
30
|
await page.goto('https://playwright.dev');
|