simple-playwright-framework 0.0.4 → 0.0.6

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/package.json CHANGED
@@ -1,23 +1,45 @@
1
1
  {
2
2
  "name": "simple-playwright-framework",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
+ "description": "A modular Playwright framework with fixtures, loaders, and demo scaffolding.",
4
5
  "main": "dist/index.js",
5
6
  "types": "dist/index.d.ts",
6
7
  "scripts": {
7
- "clean": "rimraf dist .cache",
8
- "build": "tsc -p tsconfig.json"
9
- },
10
- "dependencies": {
11
- "node-fetch": "^2.6.7"
12
- },
13
- "peerDependencies": {
14
- "@playwright/test": "^1.58.2"
8
+ "clean": "rimraf node_modules package-lock.json dist .cache",
9
+ "reinstall": "npm install",
10
+ "compile": "tsc -p tsconfig.json",
11
+ "build": "npm run clean && npm run reinstall && npm run compile",
12
+ "test": "rimraf playwright-report && playwright test",
13
+ "report": "playwright show-report"
15
14
  },
16
15
  "bin": {
17
- "init-sample-project": "./scripts/setup-framework.js"
16
+ "init-framework-project": "scripts/init-framework-project.js",
17
+ "init-demo-project": "scripts/init-demo-project.js"
18
18
  },
19
19
  "files": [
20
- "dist",
21
- "scripts"
22
- ]
20
+ "dist/**/*",
21
+ "scripts/init-framework-project.js",
22
+ "scripts/init-demo-project.js"
23
+ ],
24
+ "keywords": [
25
+ "playwright",
26
+ "framework",
27
+ "testing",
28
+ "automation",
29
+ "fixtures",
30
+ "typescript"
31
+ ],
32
+ "author": "Udayakumar",
33
+ "license": "MIT",
34
+ "dependencies": {
35
+ "@framework/fixtures": "file:../framework"
36
+ },
37
+ "devDependencies": {
38
+ "@playwright/test": "^1.58.2",
39
+ "@types/node": "^25.2.3",
40
+ "rimraf": "^6.1.2",
41
+ "ts-node": "^10.9.2",
42
+ "tsconfig-paths": "^4.2.0",
43
+ "typescript": "^5.9.3"
44
+ }
23
45
  }
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+
5
+ const cwd = process.cwd();
6
+ const demoDir = path.join(cwd, "demo-project");
7
+ fs.mkdirSync(demoDir, { recursive: true });
8
+
9
+ function writeFileSafe(filePath, content) {
10
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
11
+ fs.writeFileSync(filePath, content);
12
+ console.log(`šŸ“„ Created: ${filePath}`);
13
+ }
14
+
15
+ // package.json
16
+ writeFileSafe(path.join(demoDir, "package.json"),
17
+ JSON.stringify({
18
+ name: "demo-project",
19
+ version: "1.0.0",
20
+ private: true,
21
+ scripts: { test: "playwright test" },
22
+ devDependencies: {
23
+ "@playwright/test": "^1.58.2",
24
+ "simple-playwright-framework": "latest"
25
+ }
26
+ }, null, 2)
27
+ );
28
+
29
+ // playwright.config.ts
30
+ writeFileSafe(path.join(demoDir, "playwright.config.ts"), `import { defineConfig } from '@playwright/test';
31
+ export default defineConfig({ testDir: './tests', reporter: [['html']] });
32
+ `);
33
+
34
+ // config
35
+ writeFileSafe(path.join(demoDir, "config/environments.json"),
36
+ JSON.stringify({
37
+ defaults: { timeout: 30000, retries: 1, autoLaunch: false },
38
+ dev: { baseUrl: "https://dev.orangehrm.example.com", authStorage: { enabled: true, provider: "OrangeHRMLogin" } },
39
+ qa: { baseUrl: "https://qa.orangehrm.example.com", authStorage: { enabled: true, provider: "OrangeHRMLogin" } },
40
+ prod: { baseUrl: "https://opensource-demo.orangehrmlive.com/", authStorage: { enabled: true, provider: "OrangeHRMLogin" } }
41
+ }, null, 2)
42
+ );
43
+
44
+ // data/login
45
+ writeFileSafe(path.join(demoDir, "data/login/login.json"),
46
+ JSON.stringify({
47
+ prod: {
48
+ users: {
49
+ admin: { username: "Admin", password: "admin123" },
50
+ employee: { username: "Emp", password: "emp123" },
51
+ locked: { username: "LockedUser", password: "locked123" },
52
+ problem: { username: "ProblemUser", password: "problem123" }
53
+ }
54
+ }
55
+ }, null, 2)
56
+ );
57
+ writeFileSafe(path.join(demoDir, "data/login/login.scenarios.json"),
58
+ JSON.stringify({
59
+ prod: [
60
+ { name: "Valid login", url: "https://opensource-demo.orangehrmlive.com/", username: "Admin", password: "admin123", expected: "success", tags: ["smoke"] },
61
+ { name: "Invalid login", url: "https://opensource-demo.orangehrmlive.com/", username: "WrongUser", password: "WrongPass", expected: "failure", tags: ["negative"] },
62
+ { name: "Valid login Two", url: "https://opensource-demo.orangehrmlive.com/", username: "akshay.emp.61499", password: "October@2020", expected: "success", tags: ["regression","positive"] }
63
+ ]
64
+ }, null, 2)
65
+ );
66
+ writeFileSafe(path.join(demoDir, "data/login/loginwithauthstorage.json"),
67
+ JSON.stringify({ prod: { users: { admin: { username: "Admin", password: "admin123" } } } }, null, 2)
68
+ );
69
+
70
+ // data/api
71
+ writeFileSafe(path.join(demoDir, "data/api/payload.json"),
72
+ JSON.stringify({ createUser: { username: "demoUser", password: "demoPass" } }, null, 2)
73
+ );
74
+
75
+ // data/ui
76
+ writeFileSafe(path.join(demoDir, "data/ui/sample.txt"), "This is a sample file used for upload tests.\n");
77
+
78
+ // storage
79
+ writeFileSafe(path.join(demoDir, "storage/authStorage.json"),
80
+ JSON.stringify({ session: { validityMinutes: 30, provider: "OrangeHRMLogin" } }, null, 2)
81
+ );
82
+
83
+ // auth
84
+ writeFileSafe(path.join(demoDir, "auth/orangehrm.login.ts"), `import { Page } from '@playwright/test';
85
+ import { AuthProvider } from 'simple-playwright-framework/fixtures/src/types/auth';
86
+ export class OrangeHRMLogin implements AuthProvider {
87
+ constructor(private creds: { username: string; password: string }) {}
88
+ async login(page: Page): Promise<void> {
89
+ await page.fill("input[name='username']", this.creds.username);
90
+ await page.fill("input[name='password']", this.creds.password);
91
+ await page.click("button[type='submit']");
92
+ await page.waitForURL("**/dashboard/**");
93
+ }
94
+ }
95
+ `);
96
+
97
+ // tests/login
98
+ writeFileSafe(path.join(demoDir, "tests/login/login.test.ts"), `import { test, expect } from 'simple-playwright-framework';
99
+ test('login with Admin user @smoke', async ({ page, envConfig, td }) => {
100
+ await page.goto(envConfig.baseUrl);
101
+ await page.fill('input[name="username"]', td.users.admin.username);
102
+ await page.fill('input[name="password"]', td.users.admin.password);
103
+ await page.click('button[type="submit"]');
104
+ await expect(page).toHaveURL(/dashboard/);
105
+ });
106
+ `);
107
+
108
+ writeFileSafe(path.join(demoDir, "tests/login/login.scenarios.spec.ts"), `import { test, expect, scenarioLoader, initAuthSession } from 'simple-playwright-framework';
109
+ import { providerRegistry } from '@project/auth';
110
+ const scenarios = scenarioLoader(__filename);
111
+ test.describe.parallel("Login scenarios", () => {
112
+ for (const sc of scenarios) {
113
+ test(\`Scenario: \${sc.name}\`, async ({ page, envConfig }) => {
114
+ await page.goto(envConfig.baseUrl);
115
+ await initAuthSession(page, envConfig.authStorage!, { username: sc.username, password: sc.password }, providerRegistry);
116
+ if (sc.expected === "success") {
117
+ await expect(page).toHaveURL(/.*dashboard.*/);
118
+ } else {
119
+ await expect(page.locator(".oxd-alert-content")).toBeVisible();
120
+ }
121
+ });
122
+ }
123
+ });
124
+ `);
125
+
126
+ writeFileSafe(path.join(demoDir, "tests/login/loginwithauthstorage.spec.ts"), `import { test, expect, initAuthSession } from 'simple-playwright-framework';
127
+ import { providerRegistry } from '@project/auth';
128
+ test('login with Admin user using Auth Storage', async ({ page, envConfig, td }) => {
129
+ await page.goto(envConfig.baseUrl);
130
+ await initAuthSession(page, envConfig.authStorage!, { username: td.users.admin.username, password: td.users.admin.password }, providerRegistry);
131
+ await expect(page).toHaveURL(/dashboard/);
132
+ });
133
+ `);
134
+
135
+ writeFileSafe(path.join(demoDir, "tests/login/login.testrail.spec.ts"), `import { test, expect } from 'simple-playwright-framework';
136
+ test('Login linked to TestRail case C1234', async ({ page, envConfig, testrail }) => {
137
+ await page.goto(envConfig.baseUrl);
138
+ await page.fill('input[name="username"]', 'Admin');
139
+ await page.fill('input[name="password"]', 'admin123');
140
+ await page.click('button[type="submit"]');
141
+ try {
142
+ await expect(page).toHaveURL(/dashboard/);
143
+ await testrail.addResult(1234, 1, "Login passed āœ…");
144
+ } catch (err) {
145
+ await testrail.addResult(1234, 5, "Login failed āŒ");
146
+ throw err;
147
+ }
148
+ });
149
+ `);
150
+
151
+ // tests/filehandling
152
+ writeFileSafe(path.join(demoDir, "tests/filehandling/filehandling.spec.ts"), `import { test } from 'simple-playwright-framework/fixtures';
153
+ test("upload and download demo", async ({ page, fileUtils }) => {
154
+ await page.goto("https://the-internet.herokuapp.com/upload");
155
+ await fileUtils.uploadFile("#file-upload", "data/ui/sample.txt");
156
+ await page.click("#file-submit");
157
+ await page.goto("https://the-internet.herokuapp.com/download");
158
+ const downloadedPath = await fileUtils.downloadFile("a[href*='some-file.txt']");
159
+ console.log("Downloaded file path:", downloadedPath);
160
+ });
161
+ `);
162
+
163
+ // tests/api
164
+ writeFileSafe(path.join(demoDir, "tests/api/api.test.ts"), `import { test, expect } from 'simple-playwright-framework';
165
+ test('sample API call', async ({ request, envConfig }) => {
166
+ const response = await request.get(\`\${envConfig.baseUrl}/api/health\`);
167
+ expect(response.status()).toBe(200);
168
+ });
169
+ `);
170
+
171
+ // tests/utils
172
+ writeFileSafe(path.join(demoDir, "tests/utils/fileutils.test.ts"), `import { test } from 'simple-playwright-framework/fixtures';
173
+ test('use fileUtils directly', async ({ fileUtils }) => {
174
+ const path = await fileUtils.downloadFile("https://example.com/file.txt");
175
+ console.log("Downloaded:", path);
176
+ });
177
+ `);
178
+
179
+ // tests/reporting
180
+ writeFileSafe(path.join(demoDir, "tests/reporting/testrail.test.ts"), `import { test } from 'simple-playwright-framework';
181
+ test('reporting example', async ({ testrail }) => {
182
+ await testrail.addResult(5678, 1, "Reporting fixture works āœ…");
183
+ });
184
+ `);
185
+
186
+ // README
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env node
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+ const readline = require("readline");
5
+
6
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
7
+ const ask = (q) => new Promise(res => rl.question(q, ans => res(ans.trim())));
8
+
9
+ async function scaffoldFile(filePath, content) {
10
+ if (fs.existsSync(filePath)) {
11
+ console.log(`āš ļø ALERT: ${filePath} already exists.`);
12
+ const ans = await ask(`Do you want to overwrite ${filePath}? (y/N): `);
13
+ if (ans.toLowerCase() !== "y") {
14
+ console.log(`āŒ Skipped ${filePath}`);
15
+ return;
16
+ }
17
+ console.log(`āœ… Approved overwrite for ${filePath}`);
18
+ } else {
19
+ const ans = await ask(`Create new file ${filePath}? (y/N): `);
20
+ if (ans.toLowerCase() !== "y") {
21
+ console.log(`āŒ Skipped ${filePath}`);
22
+ return;
23
+ }
24
+ console.log(`āœ… Approved creation of ${filePath}`);
25
+ }
26
+
27
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
28
+ fs.writeFileSync(filePath, content);
29
+ console.log(`šŸ“„ File created/updated: ${filePath}`);
30
+ }
31
+
32
+ (async () => {
33
+ const cwd = process.cwd();
34
+ console.log("šŸš€ Starting framework integration with confirmations...");
35
+
36
+ // config
37
+ await scaffoldFile(path.join(cwd, "config/environments.json"),
38
+ JSON.stringify({
39
+ defaults: { timeout: 30000, retries: 1, autoLaunch: false },
40
+ qa: { baseUrl: "http://localhost:3000", authStorage: { enabled: true, provider: "OrangeHRMLogin" } }
41
+ }, null, 2)
42
+ );
43
+
44
+ // data/login
45
+ await scaffoldFile(path.join(cwd, "data/login/login.json"),
46
+ JSON.stringify({ qa: { users: { admin: { username: "Admin", password: "admin123" } } } }, null, 2)
47
+ );
48
+ await scaffoldFile(path.join(cwd, "data/login/login.scenarios.json"),
49
+ JSON.stringify({ qa: [
50
+ { name: "Valid login", username: "Admin", password: "admin123", expected: "success" },
51
+ { name: "Invalid login", username: "WrongUser", password: "WrongPass", expected: "failure" }
52
+ ] }, null, 2)
53
+ );
54
+ await scaffoldFile(path.join(cwd, "data/login/loginwithauthstorage.json"),
55
+ JSON.stringify({ qa: { users: { admin: { username: "Admin", password: "admin123" } } } }, null, 2)
56
+ );
57
+
58
+ // data/api
59
+ await scaffoldFile(path.join(cwd, "data/api/payload.json"),
60
+ JSON.stringify({ createUser: { username: "demoUser", password: "demoPass" } }, null, 2)
61
+ );
62
+
63
+ // data/ui
64
+ await scaffoldFile(path.join(cwd, "data/ui/sample.txt"), "This is a sample file used for upload tests.\n");
65
+
66
+ // storage
67
+ await scaffoldFile(path.join(cwd, "storage/authStorage.json"),
68
+ JSON.stringify({ session: { validityMinutes: 30, provider: "OrangeHRMLogin" } }, null, 2)
69
+ );
70
+
71
+ // auth
72
+ await scaffoldFile(path.join(cwd, "auth/orangehrm.login.ts"), `import { Page } from '@playwright/test';
73
+ import { AuthProvider } from 'simple-playwright-framework/fixtures/src/types/auth';
74
+ export class OrangeHRMLogin implements AuthProvider {
75
+ constructor(private creds: { username: string; password: string }) {}
76
+ async login(page: Page): Promise<void> {
77
+ await page.fill("input[name='username']", this.creds.username);
78
+ await page.fill("input[name='password']", this.creds.password);
79
+ await page.click("button[type='submit']");
80
+ await page.waitForURL("**/dashboard/**");
81
+ }
82
+ }
83
+ `);
84
+
85
+ // tests/login
86
+ await scaffoldFile(path.join(cwd, "tests/login/login.test.ts"), `import { test, expect } from 'simple-playwright-framework';
87
+ test('login with Admin user @smoke', async ({ page, envConfig, td }) => {
88
+ await page.goto(envConfig.baseUrl);
89
+ await page.fill('input[name="username"]', td.users.admin.username);
90
+ await page.fill('input[name="password"]', td.users.admin.password);
91
+ await page.click('button[type="submit"]');
92
+ await expect(page).toHaveURL(/dashboard/);
93
+ });
94
+ `);
95
+
96
+ await scaffoldFile(path.join(cwd, "tests/login/login.scenarios.spec.ts"), `import { test, expect, scenarioLoader, initAuthSession } from 'simple-playwright-framework';
97
+ import { providerRegistry } from '@project/auth';
98
+ const scenarios = scenarioLoader(__filename);
99
+ test.describe.parallel("Login scenarios", () => {
100
+ for (const sc of scenarios) {
101
+ test(\`Scenario: \${sc.name}\`, async ({ page, envConfig }) => {
102
+ await page.goto(envConfig.baseUrl);
103
+ await initAuthSession(page, envConfig.authStorage!, { username: sc.username, password: sc.password }, providerRegistry);
104
+ if (sc.expected === "success") {
105
+ await expect(page).toHaveURL(/.*dashboard.*/);
106
+ } else {
107
+ await expect(page.locator(".oxd-alert-content")).toBeVisible();
108
+ }
109
+ });
110
+ }
111
+ });
112
+ `);
113
+
114
+ await scaffoldFile(path.join(cwd, "tests/login/loginwithauthstorage.spec.ts"), `import { test, expect, initAuthSession } from 'simple-playwright-framework';
115
+ import { providerRegistry } from '@project/auth';
116
+ test('login with Admin user using Auth Storage', async ({ page, envConfig, td }) => {
117
+ await page.goto(envConfig.baseUrl);
118
+ await initAuthSession(page, envConfig.authStorage!, { username: td.users.admin.username, password: td.users.admin.password }, providerRegistry);
119
+ await expect(page).toHaveURL(/dashboard/);
120
+ });
121
+ `);
122
+
123
+ await scaffoldFile(path.join(cwd, "tests/login/login.testrail.spec.ts"), `import { test, expect } from 'simple-playwright-framework';
124
+ test('Login linked to TestRail case C1234', async ({ page, envConfig, testrail }) => {
125
+ await page.goto(envConfig.baseUrl);
126
+ await page.fill('input[name="username"]', 'Admin');
127
+ await page.fill('input[name="password"]', 'admin123');
128
+ await page.click('button[type="submit"]');
129
+ try {
130
+ await expect(page).toHaveURL(/dashboard/);
131
+ await testrail.addResult(1234, 1, "Login passed āœ…");
132
+ } catch (err) {
133
+ await testrail.addResult(1234, 5, "Login failed āŒ");
134
+ throw err;
135
+ }
136
+ });
137
+ `);
138
+
139
+ // tests/filehandling
140
+ await scaffoldFile(path.join(cwd, "tests/filehandling/filehandling.spec.ts"), `import { test } from 'simple-playwright-framework/fixtures';
141
+ test("upload and download demo", async ({ page, fileUtils }) => {
142
+ await page.goto("https://the-internet.herokuapp.com/upload");
143
+ await fileUtils.uploadFile("#file-upload", "data/ui/sample.txt");
144
+ await page.click("#file-submit");
145
+ await page.goto("https://the-internet.herokuapp.com/download");
146
+ const downloadedPath = await fileUtils.downloadFile("a[href*='some-file.txt']");
147
+ console.log("Downloaded file path:", downloadedPath);
148
+ });
149
+ `);
150
+
151
+ // tests/api
152
+ await scaffoldFile(path.join(cwd, "tests/api/api.test.ts"), `import { test, expect } from 'simple-playwright-framework';
153
+ test('sample API call', async ({ request, envConfig }) => {
154
+ const response = await request.get(\`\${envConfig.baseUrl}/api/health\`);
155
+ expect(response.status()).toBe(200);
156
+ });
157
+ `);
158
+
159
+ // tests/utils
160
+ await scaffoldFile(path.join(cwd, "tests/utils/fileutils.test.ts"), `import { test } from 'simple-playwright-framework/fixtures';
161
+ test('use fileUtils directly', async ({ fileUtils }) => {
162
+ const path = await fileUtils.downloadFile("https://example.com/file.txt");
163
+ console.log("Downloaded:", path);
164
+ });
165
+ `);
166
+
167
+ // tests/reporting
168
+ await scaffoldFile(path.join(cwd, "tests/reporting/testrail.test.ts"), `import { test } from 'simple-playwright-framework';
169
+ test('reporting example', async ({ testrail }) => {
170
+ await testrail.addResult(5678, 1, "Reporting fixture works āœ…");
171
+ });
172
+ `);
173
+
174
+ rl.close();
175
+ console.log("\nšŸŽ‰ Framework integration complete with confirmations.");
176
+ console.log("šŸ‘‰ Next step: commit and push these changes to GitHub:");
177
+ console.log(" git add . && git commit -m \"Integrate Playwright framework\" && git push");
178
+ })();
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from "fs";
3
- import path from "path";
4
- import readline from "readline";
5
-
6
- const rl = readline.createInterface({
7
- input: process.stdin,
8
- output: process.stdout,
9
- });
10
-
11
- function ask(question, defaultValue) {
12
- return new Promise(resolve => {
13
- rl.question(`${question} (${defaultValue}): `, answer => {
14
- resolve(answer.trim() || defaultValue);
15
- });
16
- });
17
- }
18
-
19
- async function main() {
20
- console.log("šŸš€ Init Sample Playwright Project");
21
-
22
- const projectName = await ask("Project name", "sample-project");
23
- const includeAuth = await ask("Include auth example? yes/no", "yes");
24
- const includeData = await ask("Include data example? yes/no", "yes");
25
-
26
- rl.close();
27
-
28
- const projectDir = path.join(process.cwd(), projectName);
29
- fs.mkdirSync(projectDir, { recursive: true });
30
-
31
- // Config
32
- fs.mkdirSync(path.join(projectDir, "config"), { recursive: true });
33
- fs.writeFileSync(
34
- path.join(projectDir, "config", "environments.json"),
35
- JSON.stringify({ qa: { baseUrl: "http://localhost:3000" } }, null, 2)
36
- );
37
-
38
- // Tests
39
- fs.mkdirSync(path.join(projectDir, "tests", "ui"), { recursive: true });
40
- fs.writeFileSync(
41
- path.join(projectDir, "tests", "ui", "login.spec.ts"),
42
- `import { test, expect } from '@playwright/test';
43
-
44
- test('login example', async ({ page }) => {
45
- await page.goto('http://localhost:3000/login');
46
- await expect(page).toHaveTitle(/Login/);
47
- });`
48
- );
49
-
50
- if (includeAuth.toLowerCase() === "yes") {
51
- fs.mkdirSync(path.join(projectDir, "auth"), { recursive: true });
52
- fs.writeFileSync(
53
- path.join(projectDir, "auth", "index.ts"),
54
- `export const creds = { username: "testuser", password: "testpass" };`
55
- );
56
- }
57
-
58
- if (includeData.toLowerCase() === "yes") {
59
- fs.mkdirSync(path.join(projectDir, "data", "ui"), { recursive: true });
60
- fs.writeFileSync(
61
- path.join(projectDir, "data", "ui", "sample.txt"),
62
- "Sample test data"
63
- );
64
- }
65
-
66
- console.log(`āœ… Sample project created in ${projectDir}`);
67
- console.log(`šŸ‘‰ Next steps:\n cd ${projectName}\n npx playwright test`);
68
- }
69
-
70
- main();