simple-playwright-framework 0.0.9 → 0.0.11

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,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-playwright-framework",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "A modular Playwright framework with fixtures, loaders, and demo scaffolding.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,6 +40,7 @@
40
40
  "rimraf": "^6.1.2",
41
41
  "ts-node": "^10.9.2",
42
42
  "tsconfig-paths": "^4.2.0",
43
- "typescript": "^5.9.3"
43
+ "typescript": "^5.9.3",
44
+ "node-fetch": "^2.6.7"
44
45
  }
45
46
  }
@@ -18,7 +18,7 @@ function run(cmd, cwd) {
18
18
  execSync(cmd, { stdio: "inherit", cwd });
19
19
  }
20
20
 
21
- // package.json
21
+ // -------------------- package.json --------------------
22
22
  writeFileSafe(path.join(demoDir, "package.json"),
23
23
  JSON.stringify({
24
24
  name: "demo-project",
@@ -39,7 +39,7 @@ writeFileSafe(path.join(demoDir, "package.json"),
39
39
  }, null, 2)
40
40
  );
41
41
 
42
- // tsconfig.json
42
+ // -------------------- tsconfig.json --------------------
43
43
  writeFileSafe(path.join(demoDir, "tsconfig.json"),
44
44
  JSON.stringify({
45
45
  compilerOptions: {
@@ -52,30 +52,84 @@ writeFileSafe(path.join(demoDir, "tsconfig.json"),
52
52
  resolveJsonModule: true,
53
53
  types: ["@playwright/test", "simple-playwright-framework", "node"],
54
54
  baseUrl: ".",
55
- paths: { "@demo-project/*": ["./*"] , "@demo-project/auth": ["auth/index.ts"]},
55
+ paths: { "@demo-project/*": ["./*"], "@demo-project/auth": ["auth/index.ts"] },
56
56
  outDir: "dist"
57
57
  },
58
58
  include: ["tests/**/*.ts", "global.d.ts"]
59
59
  }, null, 2)
60
60
  );
61
61
 
62
- // playwright.config.ts
63
- writeFileSafe(path.join(demoDir, "playwright.config.ts"), `import { defineConfig } from '@playwright/test';
62
+ // -------------------- playwright.config.ts --------------------
63
+ writeFileSafe(path.join(demoDir, "playwright.config.ts"),
64
+ `import { defineConfig } from '@playwright/test';
64
65
  export default defineConfig({ testDir: './tests', reporter: [['html']] });
65
66
  `);
66
67
 
67
-
68
- // config
68
+ // -------------------- environments.json --------------------
69
69
  writeFileSafe(path.join(demoDir, "config/environments.json"),
70
70
  JSON.stringify({
71
71
  defaults: { timeout: 30000, retries: 1, autoLaunch: false },
72
72
  dev: { baseUrl: "https://dev.orangehrm.example.com", authStorage: { enabled: true, provider: "OrangeHRMLogin" } },
73
73
  qa: { baseUrl: "https://qa.orangehrm.example.com", authStorage: { enabled: true, provider: "OrangeHRMLogin" } },
74
- prod: { baseUrl: "https://opensource-demo.orangehrmlive.com/", authStorage: { enabled: true, provider: "OrangeHRMLogin" } }
74
+ prod: { baseUrl: "https://opensource-demo.orangehrmlive.com/", apiUrl: "https://jsonplaceholder.typicode.com", authStorage: { enabled: true, provider: "OrangeHRMLogin" } }
75
75
  }, null, 2)
76
76
  );
77
77
 
78
- // data/login
78
+ // -------------------- Auth Provider --------------------
79
+ writeFileSafe(path.join(demoDir, "auth/index.ts"),
80
+ `import { OrangeHRMLogin } from "./orangehrm.login";
81
+
82
+ export const providerRegistry = {
83
+ OrangeHRMLogin,
84
+ };
85
+ `);
86
+
87
+ writeFileSafe(path.join(demoDir, "auth/orangehrm.login.ts"),
88
+ `import { Page } from '@playwright/test';
89
+ import { AuthProvider } from 'simple-playwright-framework';
90
+ export class OrangeHRMLogin implements AuthProvider {
91
+ constructor(private creds: { username: string; password: string }) {}
92
+ async login(page: Page): Promise<void> {
93
+ await page.fill("input[name='username']", this.creds.username);
94
+ await page.fill("input[name='password']", this.creds.password);
95
+ await page.click("button[type='submit']");
96
+ // No unconditional waitForURL here — handled in tests
97
+ }
98
+ }
99
+ `);
100
+
101
+ // -------------------- FileUtils --------------------
102
+ writeFileSafe(path.join(demoDir, "utils/file-utils.ts"),
103
+ `import { Page } from "@playwright/test";
104
+ import fs from "fs";
105
+ import path from "path";
106
+
107
+ export class FileUtils {
108
+ constructor(private page: Page) {}
109
+
110
+ async uploadFile(selector: string, filePath: string) {
111
+ const absolutePath = path.resolve(filePath);
112
+ if (!fs.existsSync(absolutePath)) {
113
+ throw new Error(\`❌ File not found: \${absolutePath}\`);
114
+ }
115
+ await this.page.setInputFiles(selector, absolutePath);
116
+ console.log(\`✅ Uploaded file: \${absolutePath}\`);
117
+ }
118
+
119
+ async downloadFile(selector: string, downloadDir: string = "downloads") {
120
+ const downloadPromise = this.page.waitForEvent("download");
121
+ await this.page.click(selector);
122
+ const download = await downloadPromise;
123
+
124
+ const filePath = path.join(downloadDir, await download.suggestedFilename());
125
+ await download.saveAs(filePath);
126
+ console.log(\`✅ File downloaded to: \${filePath}\`);
127
+ return filePath;
128
+ }
129
+ }
130
+ `);
131
+
132
+ // -------------------- Data --------------------
79
133
  writeFileSafe(path.join(demoDir, "data/login/login.json"),
80
134
  JSON.stringify({
81
135
  prod: {
@@ -88,58 +142,35 @@ writeFileSafe(path.join(demoDir, "data/login/login.json"),
88
142
  }
89
143
  }, null, 2)
90
144
  );
145
+
91
146
  writeFileSafe(path.join(demoDir, "data/login/login.scenarios.json"),
92
147
  JSON.stringify({
93
148
  prod: [
94
149
  { name: "Valid login", url: "https://opensource-demo.orangehrmlive.com/", username: "Admin", password: "admin123", expected: "success", tags: ["smoke"] },
95
150
  { name: "Invalid login", url: "https://opensource-demo.orangehrmlive.com/", username: "WrongUser", password: "WrongPass", expected: "failure", tags: ["negative"] },
96
- { name: "Valid login Two", url: "https://opensource-demo.orangehrmlive.com/", username: "akshay.emp.61499", password: "October@2020", expected: "success", tags: ["regression","positive"] }
151
+ { name: "Valid login Two", url: "https://opensource-demo.orangehrmlive.com/", username: "Admin", password: "admin123", expected: "success", tags: ["regression","positive"] }
97
152
  ]
98
153
  }, null, 2)
99
154
  );
155
+
100
156
  writeFileSafe(path.join(demoDir, "data/login/loginwithauthstorage.json"),
101
157
  JSON.stringify({ prod: { users: { admin: { username: "Admin", password: "admin123" } } } }, null, 2)
102
158
  );
103
159
 
104
-
105
- // -------------------- auth/index.ts --------------------
106
- writeFileSafe(path.join(demoDir, "auth/index.ts"),
107
- `import { OrangeHRMLogin } from "./orangehrm.login";
108
-
109
- export const providerRegistry = {
110
- OrangeHRMLogin,
111
- };
112
- `);
113
-
114
- // data/api
115
160
  writeFileSafe(path.join(demoDir, "data/api/payload.json"),
116
161
  JSON.stringify({ createUser: { username: "demoUser", password: "demoPass" } }, null, 2)
117
162
  );
118
163
 
119
- // data/ui
120
164
  writeFileSafe(path.join(demoDir, "data/ui/sample.txt"), "This is a sample file used for upload tests.\n");
121
165
 
122
- // storage
123
166
  writeFileSafe(path.join(demoDir, "storage/authStorage.json"),
124
167
  JSON.stringify({ session: { validityMinutes: 30, provider: "OrangeHRMLogin" } }, null, 2)
125
168
  );
126
169
 
127
- // auth
128
- writeFileSafe(path.join(demoDir, "auth/orangehrm.login.ts"), `import { Page } from '@playwright/test';
129
- import { AuthProvider } from 'simple-playwright-framework';
130
- export class OrangeHRMLogin implements AuthProvider {
131
- constructor(private creds: { username: string; password: string }) {}
132
- async login(page: Page): Promise<void> {
133
- await page.fill("input[name='username']", this.creds.username);
134
- await page.fill("input[name='password']", this.creds.password);
135
- await page.click("button[type='submit']");
136
- await page.waitForURL("**/dashboard/**");
137
- }
138
- }
139
- `);
140
-
141
- // tests/login
142
- writeFileSafe(path.join(demoDir, "tests/login/login.test.ts"), `import { test, expect } from 'simple-playwright-framework';
170
+ // -------------------- Tests --------------------
171
+ // Login basic test
172
+ writeFileSafe(path.join(demoDir, "tests/login/login.test.ts"),
173
+ `import { test, expect } from 'simple-playwright-framework';
143
174
  test('login with Admin user @smoke', async ({ page, envConfig, td }) => {
144
175
  await page.goto(envConfig.baseUrl);
145
176
  await page.fill('input[name="username"]', td.users.admin.username);
@@ -149,7 +180,9 @@ test('login with Admin user @smoke', async ({ page, envConfig, td }) => {
149
180
  });
150
181
  `);
151
182
 
152
- writeFileSafe(path.join(demoDir, "tests/login/login.scenarios.spec.ts"), `import { test, expect, scenarioLoader, initAuthSession } from 'simple-playwright-framework';
183
+ // Login scenarios
184
+ writeFileSafe(path.join(demoDir, "tests/login/login.scenarios.spec.ts"),
185
+ `import { test, expect, scenarioLoader, initAuthSession } from 'simple-playwright-framework';
153
186
  import { providerRegistry } from '@demo-project/auth';
154
187
  const scenarios = scenarioLoader(__filename);
155
188
  test.describe.parallel("Login scenarios", () => {
@@ -167,7 +200,9 @@ test.describe.parallel("Login scenarios", () => {
167
200
  });
168
201
  `);
169
202
 
170
- writeFileSafe(path.join(demoDir, "tests/login/loginwithauthstorage.spec.ts"), `import { test, expect, initAuthSession } from 'simple-playwright-framework';
203
+ // Login with auth storage
204
+ writeFileSafe(path.join(demoDir, "tests/login/loginwithauthstorage.spec.ts"),
205
+ `import { test, expect, initAuthSession } from 'simple-playwright-framework';
171
206
  import { providerRegistry } from '@demo-project/auth';
172
207
  test('login with Admin user using Auth Storage', async ({ page, envConfig, td }) => {
173
208
  await page.goto(envConfig.baseUrl);
@@ -176,7 +211,9 @@ test('login with Admin user using Auth Storage', async ({ page, envConfig, td })
176
211
  });
177
212
  `);
178
213
 
179
- writeFileSafe(path.join(demoDir, "tests/login/login.testrail.spec.ts"), `import { test, expect } from 'simple-playwright-framework';
214
+ // Login with TestRail reporting
215
+ writeFileSafe(path.join(demoDir, "tests/login/login.testrail.spec.ts"),
216
+ `import { test, expect } from 'simple-playwright-framework';
180
217
  test('Login linked to TestRail case C1234', async ({ page, envConfig, testrail }) => {
181
218
  await page.goto(envConfig.baseUrl);
182
219
  await page.fill('input[name="username"]', 'Admin');
@@ -192,46 +229,59 @@ test('Login linked to TestRail case C1234', async ({ page, envConfig, testrail }
192
229
  });
193
230
  `);
194
231
 
195
- // tests/filehandling
196
- writeFileSafe(path.join(demoDir, "tests/filehandling/filehandling.spec.ts"), `import { test } from 'simple-playwright-framework';
232
+ // File handling test
233
+ writeFileSafe(path.join(demoDir, "tests/filehandling/filehandling.spec.ts"),
234
+ `import { test, expect } from 'simple-playwright-framework';
235
+
197
236
  test("upload and download demo", async ({ page, fileUtils }) => {
198
237
  await page.goto("https://the-internet.herokuapp.com/upload");
199
238
  await fileUtils.uploadFile("#file-upload", "data/ui/sample.txt");
200
239
  await page.click("#file-submit");
240
+
201
241
  await page.goto("https://the-internet.herokuapp.com/download");
202
- const downloadedPath = await fileUtils.downloadFile("a[href*='some-file.txt']");
242
+ const link = page.locator("a[href*='sample.txt']");
243
+ await expect(link).toBeVisible();
244
+
245
+ const downloadedPath = await fileUtils.downloadFile("a[href*='sample.txt']");
203
246
  console.log("Downloaded file path:", downloadedPath);
204
247
  });
205
248
  `);
206
249
 
207
- // tests/api
208
- writeFileSafe(path.join(demoDir, "tests/api/api.test.ts"), `import { test, expect } from 'simple-playwright-framework';
250
+ // API test
251
+ writeFileSafe(path.join(demoDir, "tests/api/api.test.ts"),
252
+ `import { test, expect } from 'simple-playwright-framework';
209
253
  test('sample API call', async ({ request, envConfig }) => {
210
- const response = await request.get(\`\${envConfig.baseUrl}/api/health\`);
254
+ console.log("API URL: " + envConfig.apiUrl);
255
+ const response = await request.get(\`\${envConfig.apiUrl}/users\`);
211
256
  expect(response.status()).toBe(200);
212
257
  });
213
258
  `);
214
259
 
215
- // tests/utils
216
- writeFileSafe(path.join(demoDir, "tests/utils/fileutils.test.ts"), `import { test } from 'simple-playwright-framework';
217
- test('use fileUtils directly', async ({ fileUtils }) => {
218
- const path = await fileUtils.downloadFile("https://example.com/file.txt");
219
- console.log("Downloaded:", path);
220
- });
221
- `);
222
-
223
- // tests/reporting
224
- writeFileSafe(path.join(demoDir, "tests/reporting/testrail.test.ts"), `import { test } from 'simple-playwright-framework';
260
+ // Reporting example
261
+ writeFileSafe(path.join(demoDir, "tests/reporting/testrail.test.ts"),
262
+ `import { test } from 'simple-playwright-framework';
225
263
  test('reporting example', async ({ testrail }) => {
226
264
  await testrail.addResult(5678, 1, "Reporting fixture works ✅");
227
265
  });
228
266
  `);
229
267
 
230
268
  // README
231
- writeFileSafe(path.join(demoDir, "README.md"), `# Demo Project
269
+ writeFileSafe(path.join(demoDir, "README.md"),
270
+ `# Demo Project
232
271
 
233
272
  This is a scaffolded Playwright demo project using **simple-playwright-framework**.
234
- Run \`npm run test\` to execute the sample tests.
273
+
274
+ ## Features
275
+ - ✅ UI login scenarios (success & failure)
276
+ - ✅ API test using jsonplaceholder
277
+ - ✅ File upload & download test with FileUtils
278
+ - ✅ Auth storage example
279
+ - ✅ TestRail reporting example
280
+
281
+ ## Usage
282
+ - Run \`npm run init\` to scaffold the project
283
+ - Run \`npm run test\` to execute all sample tests
284
+ - Run \`npm run build\` to compile TypeScript
235
285
  `);
236
286
 
237
287
  // Final step: install deps + build