simple-playwright-framework 0.0.8 → 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.8",
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",
@@ -26,7 +26,7 @@ writeFileSafe(path.join(demoDir, "package.json"),
26
26
  private: true,
27
27
  scripts: {
28
28
  init: "node ../framework/scripts/init-demo-project.js",
29
- clean: "rimraf dist tsconfig.tsbuildinfo",
29
+ clean: "npx rimraf dist tsconfig.tsbuildinfo",
30
30
  build: "tsc --build --force",
31
31
  test: "playwright test"
32
32
  },
@@ -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,29 +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/*": ["./*"] },
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
- // config
68
+ // -------------------- environments.json --------------------
68
69
  writeFileSafe(path.join(demoDir, "config/environments.json"),
69
70
  JSON.stringify({
70
71
  defaults: { timeout: 30000, retries: 1, autoLaunch: false },
71
72
  dev: { baseUrl: "https://dev.orangehrm.example.com", authStorage: { enabled: true, provider: "OrangeHRMLogin" } },
72
73
  qa: { baseUrl: "https://qa.orangehrm.example.com", authStorage: { enabled: true, provider: "OrangeHRMLogin" } },
73
- 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" } }
74
75
  }, null, 2)
75
76
  );
76
77
 
77
- // 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 --------------------
78
133
  writeFileSafe(path.join(demoDir, "data/login/login.json"),
79
134
  JSON.stringify({
80
135
  prod: {
@@ -87,58 +142,34 @@ writeFileSafe(path.join(demoDir, "data/login/login.json"),
87
142
  }
88
143
  }, null, 2)
89
144
  );
145
+
90
146
  writeFileSafe(path.join(demoDir, "data/login/login.scenarios.json"),
91
147
  JSON.stringify({
92
148
  prod: [
93
149
  { name: "Valid login", url: "https://opensource-demo.orangehrmlive.com/", username: "Admin", password: "admin123", expected: "success", tags: ["smoke"] },
94
150
  { name: "Invalid login", url: "https://opensource-demo.orangehrmlive.com/", username: "WrongUser", password: "WrongPass", expected: "failure", tags: ["negative"] },
95
- { 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"] }
96
152
  ]
97
153
  }, null, 2)
98
154
  );
155
+
99
156
  writeFileSafe(path.join(demoDir, "data/login/loginwithauthstorage.json"),
100
157
  JSON.stringify({ prod: { users: { admin: { username: "Admin", password: "admin123" } } } }, null, 2)
101
158
  );
102
159
 
103
- // data/api
104
160
  writeFileSafe(path.join(demoDir, "data/api/payload.json"),
105
161
  JSON.stringify({ createUser: { username: "demoUser", password: "demoPass" } }, null, 2)
106
162
  );
107
163
 
108
- // data/ui
109
164
  writeFileSafe(path.join(demoDir, "data/ui/sample.txt"), "This is a sample file used for upload tests.\n");
110
165
 
111
- // storage
112
166
  writeFileSafe(path.join(demoDir, "storage/authStorage.json"),
113
167
  JSON.stringify({ session: { validityMinutes: 30, provider: "OrangeHRMLogin" } }, null, 2)
114
168
  );
115
169
 
116
- // auth
117
- writeFileSafe(path.join(demoDir, "auth/orangehrm.login.ts"), `import { Page } from '@playwright/test';
118
- import { AuthProvider } from 'simple-playwright-framework/fixtures/src/types/auth';
119
- export class OrangeHRMLogin implements AuthProvider {
120
- constructor(private creds: { username: string; password: string }) {}
121
- async login(page: Page): Promise<void> {
122
- await page.fill("input[name='username']", this.creds.username);
123
- await page.fill("input[name='password']", this.creds.password);
124
- await page.click("button[type='submit']");
125
- await page.waitForURL("**/dashboard/**");
126
- }
127
- }
128
- `);
129
-
130
- // tests/login
131
- writeFileSafe(path.join(demoDir, "tests/login/login.test.ts"), `import { test, expect } from 'simple-playwright-framework';
132
- test('login with Admin user @smoke', async ({ page, envConfig, td }) => {
133
- await page.goto(envConfig.baseUrl);
134
- await page.fill('input[name="username"]', td.users.admin.username);
135
- await page.fill('input[name="password"]', td.users.admin.password);
136
- await page.click('button[type="submit"]');
137
- await expect(page).toHaveURL(/dashboard/);
138
- });
139
- `);
140
-
141
- 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';
142
173
  import { providerRegistry } from '@demo-project/auth';
143
174
  const scenarios = scenarioLoader(__filename);
144
175
  test.describe.parallel("Login scenarios", () => {
@@ -156,74 +187,51 @@ test.describe.parallel("Login scenarios", () => {
156
187
  });
157
188
  `);
158
189
 
159
- writeFileSafe(path.join(demoDir, "tests/login/loginwithauthstorage.spec.ts"), `import { test, expect, initAuthSession } from 'simple-playwright-framework';
160
- import { providerRegistry } from '@demo-project/auth';
161
- test('login with Admin user using Auth Storage', async ({ page, envConfig, td }) => {
162
- await page.goto(envConfig.baseUrl);
163
- await initAuthSession(page, envConfig.authStorage!, { username: td.users.admin.username, password: td.users.admin.password }, providerRegistry);
164
- await expect(page).toHaveURL(/dashboard/);
165
- });
166
- `);
190
+ writeFileSafe(path.join(demoDir, "tests/filehandling/filehandling.spec.ts"),
191
+ `import { test, expect } from 'simple-playwright-framework';
167
192
 
168
- writeFileSafe(path.join(demoDir, "tests/login/login.testrail.spec.ts"), `import { test, expect } from 'simple-playwright-framework';
169
- test('Login linked to TestRail case C1234', async ({ page, envConfig, testrail }) => {
170
- await page.goto(envConfig.baseUrl);
171
- await page.fill('input[name="username"]', 'Admin');
172
- await page.fill('input[name="password"]', 'admin123');
173
- await page.click('button[type="submit"]');
174
- try {
175
- await expect(page).toHaveURL(/dashboard/);
176
- await testrail.addResult(1234, 1, "Login passed ✅");
177
- } catch (err) {
178
- await testrail.addResult(1234, 5, "Login failed ❌");
179
- throw err;
180
- }
181
- });
182
- `);
183
-
184
- // tests/filehandling
185
- writeFileSafe(path.join(demoDir, "tests/filehandling/filehandling.spec.ts"), `import { test } from 'simple-playwright-framework/fixtures';
186
193
  test("upload and download demo", async ({ page, fileUtils }) => {
187
194
  await page.goto("https://the-internet.herokuapp.com/upload");
188
195
  await fileUtils.uploadFile("#file-upload", "data/ui/sample.txt");
189
196
  await page.click("#file-submit");
197
+
190
198
  await page.goto("https://the-internet.herokuapp.com/download");
191
- 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']");
192
203
  console.log("Downloaded file path:", downloadedPath);
193
204
  });
194
205
  `);
195
206
 
196
- // tests/api
197
- 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';
198
209
  test('sample API call', async ({ request, envConfig }) => {
199
- 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\`);
200
212
  expect(response.status()).toBe(200);
201
213
  });
202
214
  `);
203
215
 
204
- // tests/utils
205
- writeFileSafe(path.join(demoDir, "tests/utils/fileutils.test.ts"), `import { test } from 'simple-playwright-framework/fixtures';
206
- test('use fileUtils directly', async ({ fileUtils }) => {
207
- const path = await fileUtils.downloadFile("https://example.com/file.txt");
208
- console.log("Downloaded:", path);
209
- });
210
- `);
216
+ // -------------------- README --------------------
217
+ writeFileSafe(path.join(demoDir, "README.md"),
218
+ `# Demo Project
211
219
 
212
- // tests/reporting
213
- writeFileSafe(path.join(demoDir, "tests/reporting/testrail.test.ts"), `import { test } from 'simple-playwright-framework';
214
- test('reporting example', async ({ testrail }) => {
215
- await testrail.addResult(5678, 1, "Reporting fixture works ✅");
216
- });
217
- `);
220
+ This is a scaffolded Playwright demo project using **simple-playwright-framework**.
218
221
 
219
- // README
220
- 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
221
227
 
222
- This is a scaffolded Playwright demo project using **simple-playwright-framework**.
223
- 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
224
232
  `);
225
233
 
226
- // Final step: install deps + build
234
+ // -------------------- Final step: install deps + build --------------------
227
235
  try {
228
236
  console.log("🚀 Installing dependencies and building demo-project...");
229
237
  run("npm install", demoDir);
@@ -233,3 +241,4 @@ try {
233
241
  console.error("❌ Init failed:", err.message);
234
242
  process.exit(1);
235
243
  }
244
+