ykq-playwright-ci 0.1.2 → 0.1.3

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/README.md CHANGED
@@ -271,6 +271,7 @@ npm run typecheck
271
271
  | `PW-TEST-002` | 未登录访问 `/home` 是否跳回登录页 |
272
272
  | `PW-TEST-003` | `/serviceAgreement` 是否允许未登录访问 |
273
273
  | `PW-TEST-004` | 登录表单基础校验 |
274
+ | `PW-TEST-005` | 使用测试账号登录成功 |
274
275
 
275
276
  ## 安全注意
276
277
 
@@ -1,11 +1,25 @@
1
+ /* global process */
2
+
1
3
  import { test, expect } from '../../../src/fixtures/base.fixture';
2
4
  import { annotateCase } from '../../../src/utils/evidence';
3
5
  import { appEnv, doctorURL, hasDoctorBaseURL } from '../../../src/utils/env';
4
6
 
7
+ const doctorUsername = process.env.DOCTOR_USERNAME?.trim() || '';
8
+ const doctorLoginCode = (
9
+ process.env.DOCTOR_LOGIN_CODE ||
10
+ process.env.DOCTOR_OTP ||
11
+ process.env.DOCTOR_PASSWORD ||
12
+ ''
13
+ ).trim();
14
+
5
15
  async function gotoDoctor(path: string, page: import('@playwright/test').Page): Promise<void> {
6
16
  await page.goto(doctorURL(path), { waitUntil: 'domcontentloaded' });
7
17
  }
8
18
 
19
+ function hasDoctorLoginCredentials(): boolean {
20
+ return Boolean(doctorUsername && doctorLoginCode);
21
+ }
22
+
9
23
  test.describe('doctor-master test environment basics', () => {
10
24
  test.beforeEach(async () => {
11
25
  test.skip(!hasDoctorBaseURL(), 'DOCTOR_BASE_URL is required for doctor-master test environment tests.');
@@ -86,4 +100,40 @@ test.describe('doctor-master test environment basics', () => {
86
100
  await page.locator('.submit-btn', { hasText: '登录' }).click();
87
101
  await expect(page.getByText('请阅读并勾选《荷叶健康用户服务协议》')).toBeVisible();
88
102
  });
103
+
104
+ test('PW-TEST-005 @smoke doctor can login with configured test account', async ({
105
+ page
106
+ }, testInfo) => {
107
+ test.skip(
108
+ !hasDoctorLoginCredentials(),
109
+ 'DOCTOR_USERNAME and DOCTOR_LOGIN_CODE/DOCTOR_OTP/DOCTOR_PASSWORD are required.'
110
+ );
111
+ annotateCase(testInfo, {
112
+ caseId: 'PW-TEST-005',
113
+ evidenceId: 'TEST-doctor-login-success',
114
+ priority: 'Smoke'
115
+ });
116
+
117
+ await gotoDoctor(appEnv.doctorLoginPath, page);
118
+
119
+ const loginResponsePromise = page.waitForResponse(
120
+ (response) =>
121
+ response.url().includes('/physician/account/loginPhysician') &&
122
+ response.request().method() === 'POST'
123
+ );
124
+
125
+ await page.getByPlaceholder('手机号').fill(doctorUsername);
126
+ await page.getByPlaceholder('图形验证码').fill('playwright');
127
+ await page.getByPlaceholder('验证码', { exact: true }).fill(doctorLoginCode);
128
+ await page.locator('.el-checkbox', { hasText: '我已阅读并同意' }).click();
129
+ await expect(page.locator('.submit-btn', { hasText: '登录' })).not.toHaveClass(/gruyBtn/);
130
+ await page.locator('.submit-btn', { hasText: '登录' }).click();
131
+
132
+ const loginResponse = await loginResponsePromise;
133
+ const loginBody = await loginResponse.json();
134
+ expect(loginResponse.ok()).toBeTruthy();
135
+ expect(loginBody?.data?.accountId, loginBody?.msg || '登录接口未返回 accountId').toBeTruthy();
136
+
137
+ await expect(page).toHaveURL(/\/physician-admin\/home(?:\?|#|$)/, { timeout: 15_000 });
138
+ });
89
139
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ykq-playwright-ci",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Company-level Playwright E2E test project for doctor PC workflows.",
5
5
  "bin": {
6
6
  "playwright-ci": "bin/playwright-ci.mjs"
@@ -2,24 +2,41 @@
2
2
 
3
3
  import { spawn, spawnSync } from 'node:child_process';
4
4
  import fs from 'node:fs';
5
- import { createRequire } from 'node:module';
6
5
  import os from 'node:os';
7
6
  import path from 'node:path';
8
7
  import { fileURLToPath } from 'node:url';
9
8
 
10
9
  const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
11
- const require = createRequire(import.meta.url);
12
10
  const configPath = process.env.PROJECTS_CONFIG_PATH
13
11
  ? path.resolve(process.env.PROJECTS_CONFIG_PATH)
14
12
  : path.join(rootDir, 'projects.config.json');
15
13
  const workspaceDir = process.env.PROJECTS_CONFIG_PATH ? path.dirname(configPath) : rootDir;
16
14
  const playwrightConfigPath = path.join(rootDir, 'playwright.config.mjs');
17
- const playwrightCliPath = path.join(path.dirname(require.resolve('@playwright/test/package.json')), 'cli.js');
15
+ const packageNodeModulesDir = resolveNodeModulesDir(rootDir);
16
+ const playwrightCliPath = path.join(packageNodeModulesDir, '@playwright', 'test', 'cli.js');
18
17
  const knownModeArgs = new Set(['--headed', '--debug', '--ui']);
19
18
  const resultsDir = process.env.PLAYWRIGHT_CI_RESULTS_DIR || path.join(workspaceDir, 'test-results');
20
19
  const reportDir = process.env.PLAYWRIGHT_CI_REPORT_DIR || path.join(workspaceDir, 'playwright-report');
21
20
  let gitAskpassPath = '';
22
21
 
22
+ function resolveNodeModulesDir(startDir) {
23
+ let currentDir = startDir;
24
+
25
+ while (true) {
26
+ const nodeModulesDir = path.join(currentDir, 'node_modules');
27
+ const playwrightCli = path.join(nodeModulesDir, '@playwright', 'test', 'cli.js');
28
+ if (fs.existsSync(playwrightCli)) {
29
+ return nodeModulesDir;
30
+ }
31
+
32
+ const parentDir = path.dirname(currentDir);
33
+ if (parentDir === currentDir) {
34
+ throw new Error(`Cannot find @playwright/test from ${startDir}`);
35
+ }
36
+ currentDir = parentDir;
37
+ }
38
+ }
39
+
23
40
  function readConfig() {
24
41
  return JSON.parse(fs.readFileSync(configPath, 'utf8'));
25
42
  }
@@ -203,6 +220,19 @@ function buildPlaywrightArgs(caseDir, project, passthroughArgs) {
203
220
  return args;
204
221
  }
205
222
 
223
+ function createPlaywrightEnv(projectEnv) {
224
+ const nodePath = [packageNodeModulesDir, process.env.NODE_PATH].filter(Boolean).join(path.delimiter);
225
+
226
+ return {
227
+ ...projectEnv,
228
+ ...process.env,
229
+ NODE_PATH: nodePath,
230
+ PLAYWRIGHT_CI_RESULTS_DIR: resultsDir,
231
+ PLAYWRIGHT_CI_REPORT_DIR: reportDir,
232
+ PLAYWRIGHT_CI_TEST_DIR: workspaceDir
233
+ };
234
+ }
235
+
206
236
  function formatDuration(durationMs = 0) {
207
237
  if (durationMs < 1000) {
208
238
  return `${Math.round(durationMs)}ms`;
@@ -333,13 +363,7 @@ function main() {
333
363
  [playwrightCliPath, ...buildPlaywrightArgs(caseDir, project, passthroughArgs)],
334
364
  {
335
365
  cwd: workspaceDir,
336
- env: {
337
- ...(project.env || {}),
338
- ...process.env,
339
- PLAYWRIGHT_CI_RESULTS_DIR: resultsDir,
340
- PLAYWRIGHT_CI_REPORT_DIR: reportDir,
341
- PLAYWRIGHT_CI_TEST_DIR: workspaceDir
342
- },
366
+ env: createPlaywrightEnv(project.env || {}),
343
367
  stdio: 'inherit'
344
368
  }
345
369
  );