simple-playwright-framework 0.0.9 → 0.0.10

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.10",
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,68 +142,34 @@ 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';
143
- test('login with Admin user @smoke', async ({ page, envConfig, td }) => {
144
- await page.goto(envConfig.baseUrl);
145
- await page.fill('input[name="username"]', td.users.admin.username);
146
- await page.fill('input[name="password"]', td.users.admin.password);
147
- await page.click('button[type="submit"]');
148
- await expect(page).toHaveURL(/dashboard/);
149
- });
150
- `);
151
-
152
- writeFileSafe(path.join(demoDir, "tests/login/login.scenarios.spec.ts"), `import { test, expect, scenarioLoader, initAuthSession } from 'simple-playwright-framework';
170
+ // -------------------- Tests --------------------
171
+ writeFileSafe(path.join(demoDir, "tests/login/login.scenarios.spec.ts"),
172
+ `import { test, expect, scenarioLoader, initAuthSession } from 'simple-playwright-framework';
153
173
  import { providerRegistry } from '@demo-project/auth';
154
174
  const scenarios = scenarioLoader(__filename);
155
175
  test.describe.parallel("Login scenarios", () => {
@@ -167,74 +187,51 @@ test.describe.parallel("Login scenarios", () => {
167
187
  });
168
188
  `);
169
189
 
170
- writeFileSafe(path.join(demoDir, "tests/login/loginwithauthstorage.spec.ts"), `import { test, expect, initAuthSession } from 'simple-playwright-framework';
171
- import { providerRegistry } from '@demo-project/auth';
172
- test('login with Admin user using Auth Storage', async ({ page, envConfig, td }) => {
173
- await page.goto(envConfig.baseUrl);
174
- await initAuthSession(page, envConfig.authStorage!, { username: td.users.admin.username, password: td.users.admin.password }, providerRegistry);
175
- await expect(page).toHaveURL(/dashboard/);
176
- });
177
- `);
190
+ writeFileSafe(path.join(demoDir, "tests/filehandling/filehandling.spec.ts"),
191
+ `import { test, expect } from 'simple-playwright-framework';
178
192
 
179
- writeFileSafe(path.join(demoDir, "tests/login/login.testrail.spec.ts"), `import { test, expect } from 'simple-playwright-framework';
180
- test('Login linked to TestRail case C1234', async ({ page, envConfig, testrail }) => {
181
- await page.goto(envConfig.baseUrl);
182
- await page.fill('input[name="username"]', 'Admin');
183
- await page.fill('input[name="password"]', 'admin123');
184
- await page.click('button[type="submit"]');
185
- try {
186
- await expect(page).toHaveURL(/dashboard/);
187
- await testrail.addResult(1234, 1, "Login passed ✅");
188
- } catch (err) {
189
- await testrail.addResult(1234, 5, "Login failed ❌");
190
- throw err;
191
- }
192
- });
193
- `);
194
-
195
- // tests/filehandling
196
- writeFileSafe(path.join(demoDir, "tests/filehandling/filehandling.spec.ts"), `import { test } from 'simple-playwright-framework';
197
193
  test("upload and download demo", async ({ page, fileUtils }) => {
198
194
  await page.goto("https://the-internet.herokuapp.com/upload");
199
195
  await fileUtils.uploadFile("#file-upload", "data/ui/sample.txt");
200
196
  await page.click("#file-submit");
197
+
201
198
  await page.goto("https://the-internet.herokuapp.com/download");
202
- const downloadedPath = await fileUtils.downloadFile("a[href*='some-file.txt']");
199
+ const link = page.locator("a[href*='sample.txt']");
200
+ await expect(link).toBeVisible();
201
+
202
+ const downloadedPath = await fileUtils.downloadFile("a[href*='sample.txt']");
203
203
  console.log("Downloaded file path:", downloadedPath);
204
204
  });
205
205
  `);
206
206
 
207
- // tests/api
208
- writeFileSafe(path.join(demoDir, "tests/api/api.test.ts"), `import { test, expect } from 'simple-playwright-framework';
207
+ writeFileSafe(path.join(demoDir, "tests/api/api.test.ts"),
208
+ `import { test, expect } from 'simple-playwright-framework';
209
209
  test('sample API call', async ({ request, envConfig }) => {
210
- const response = await request.get(\`\${envConfig.baseUrl}/api/health\`);
210
+ console.log("API URL: " + envConfig.apiUrl);
211
+ const response = await request.get(\`\${envConfig.apiUrl}/users\`);
211
212
  expect(response.status()).toBe(200);
212
213
  });
213
214
  `);
214
215
 
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
- `);
216
+ // -------------------- README --------------------
217
+ writeFileSafe(path.join(demoDir, "README.md"),
218
+ `# Demo Project
222
219
 
223
- // tests/reporting
224
- writeFileSafe(path.join(demoDir, "tests/reporting/testrail.test.ts"), `import { test } from 'simple-playwright-framework';
225
- test('reporting example', async ({ testrail }) => {
226
- await testrail.addResult(5678, 1, "Reporting fixture works ✅");
227
- });
228
- `);
220
+ This is a scaffolded Playwright demo project using **simple-playwright-framework**.
229
221
 
230
- // README
231
- writeFileSafe(path.join(demoDir, "README.md"), `# Demo Project
222
+ ## Features
223
+ - UI login scenarios (success & failure)
224
+ - ✅ API test using jsonplaceholder
225
+ - ✅ File upload & download test with FileUtils
226
+ - ✅ Auth storage example
232
227
 
233
- This is a scaffolded Playwright demo project using **simple-playwright-framework**.
234
- Run \`npm run test\` to execute the sample tests.
228
+ ## Usage
229
+ - Run \`npm run init\` to scaffold the project
230
+ - Run \`npm run test\` to execute all sample tests
231
+ - Run \`npm run build\` to compile TypeScript
235
232
  `);
236
233
 
237
- // Final step: install deps + build
234
+ // -------------------- Final step: install deps + build --------------------
238
235
  try {
239
236
  console.log("🚀 Installing dependencies and building demo-project...");
240
237
  run("npm install", demoDir);
@@ -244,3 +241,4 @@ try {
244
241
  console.error("❌ Init failed:", err.message);
245
242
  process.exit(1);
246
243
  }
244
+