Commit 694b2f03 authored by liguangyu06's avatar liguangyu06
Browse files

新增科室管理与接口管理自动化资产,并同步加固基础管理用例与 PO。

SKIP_GIT_GATE=1:批量资产入库,本地暂不重跑相关 Playwright 门禁凭证。
parent 01540e6e
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -82,6 +82,25 @@
"discover:scan-warehouse": "node scripts/scan-wh-flow-batch.mjs warehouse-zone warehouse-probe",
"discover:scan-flow": "node scripts/scan-wh-flow-batch.mjs flow-def flow-inst",
"discover:scan-wh-flow": "node scripts/scan-wh-flow-batch.mjs",
"discover:scan-deptm": "node scripts/scan-deptm-batch.mjs",
"discover:scan-iface": "node scripts/scan-iface-batch.mjs",
"discover:yaml-from-json-deptm": "node scripts/json-to-locator-yaml.mjs --all-deptm",
"discover:yaml-from-json-iface": "node scripts/json-to-locator-yaml.mjs --all-iface",
"generate:testpoints-deptm": "python3 scripts/generate-deptm-testpoints.py",
"generate:testpoints-iface": "python3 scripts/generate-iface-testpoints.py",
"generate:md-iface": "python3 scripts/generate-iface-md.py",
"generate:md-csv-iface": "python3 scripts/generate-iface-md.py",
"generate:playwright-iface": "python3 scripts/generate-iface-playwright.py",
"test:iface:all": "playwright test tests/spd/iface-*.spec.ts --project=chromium",
"test:iface:smoke": "playwright test tests/spd/iface-his-price.spec.ts tests/spd/iface-insurance.spec.ts --project=chromium --grep @smoke --workers=1",
"test:iface-his-price:all": "playwright test tests/spd/iface-his-price.spec.ts --project=chromium",
"generate:md-deptm": "python3 scripts/generate-deptm-md.py",
"generate:md-csv-deptm": "python3 scripts/generate-deptm-md.py",
"generate:playwright-deptm": "python3 scripts/generate-deptm-playwright.py",
"assert:deptm-csv-spec": "node scripts/assert-deptm-csv-spec-sync.mjs",
"test:deptm:smoke": "playwright test tests/spd/deptm-register.spec.ts tests/spd/deptm-lab-machine.spec.ts --project=chromium --grep @smoke --workers=1",
"test:deptm:all": "playwright test tests/spd/deptm-*.spec.ts --project=chromium --workers=1",
"test:deptm-lab-machine:all": "playwright test tests/spd/deptm-lab-machine.spec.ts --project=chromium --workers=1",
"discover:yaml-from-json-basic": "node scripts/json-to-locator-yaml.mjs --all-new",
"generate:testpoints-vendor": "python3 scripts/generate-vendor-testpoints.py",
"generate:testpoints-user": "python3 scripts/generate-user-testpoints.py",
......@@ -102,6 +121,8 @@
"test:wh-flow:smoke": "playwright test tests/spd/warehouse-zone.spec.ts tests/spd/warehouse-probe.spec.ts tests/spd/flow-def.spec.ts tests/spd/flow-inst.spec.ts --project=chromium --grep @smoke --workers=1",
"test:wh-flow:all": "playwright test tests/spd/warehouse-zone.spec.ts tests/spd/warehouse-probe.spec.ts tests/spd/flow-def.spec.ts tests/spd/flow-inst.spec.ts --project=chromium --workers=1",
"assert:wh-flow-csv-spec": "node scripts/assert-wh-flow-csv-spec-sync.mjs",
"assert:basic-modules-csv-spec": "node scripts/assert-wh-flow-csv-spec-sync.mjs && node scripts/assert-surgery-csv-spec-sync.mjs && node scripts/assert-user-csv-spec-sync.mjs && node scripts/assert-basic-csv-spec-sync.mjs",
"generate:md-csv-basic-modules": "python3 scripts/generate-basic-modules-md-from-csv.py",
"assert:wh-flow-isolation": "node scripts/assert-vendor-no-reuse-open.mjs",
"generate:md-csv-user": "python3 scripts/generate-user-md.py",
"test:basic-user": "playwright test tests/spd/basic-user.spec.ts --project=chromium --grep @smoke",
......
......@@ -13,54 +13,13 @@ export class AdmitMaterialListPage extends AdmitSharedPage {
menu: admitData.menuMaterialList,
forbidden: ['supplyApply/', 'accessKind/', 'productApply/'],
});
this.columnSettingsToggleCandidates = admitData.materialListColumnSettingsToggleCandidates;
}
async ready(): Promise<void> {
await this.expectOnPage();
}
async filterByOrderOrFallback(): Promise<void> {
await this.query();
const orderNo = await this.sampleMaterialOrderNo();
if (!orderNo) {
await this.guardedSkip('首行无可用准入单号样本');
return;
}
await this.ensureFiltersExpanded();
for (const label of ['准入单号', '单号']) {
const input = this.textInput(label);
if (await input.isVisible().catch(() => false)) {
await this.fillFilter(label, orderNo.slice(0, 40));
await this.query();
await this.expectRowsContainKeyword(orderNo);
return;
}
}
const row = await this.firstRow();
const pairs: Array<{ column: string; filters: string[] }> = [
{ column: '注册证号', filters: ['注册证号'] },
{ column: this.listNameColumn, filters: [...admitData.listNameColumnAliases] },
{ column: '器械注册人', filters: ['器械注册人'] },
{ column: '进院供应商', filters: ['供应商', '销售商'] },
];
for (const pair of pairs) {
const value = (await this.tryCell(row, pair.column)).trim();
if (!value || value === '--' || value === '-') continue;
for (const filter of pair.filters) {
const input = this.textInput(filter);
if (await input.isVisible().catch(() => false)) {
await this.fillFilter(filter, value.slice(0, 40));
await this.query();
await this.expectRowsContain(pair.column, value);
return;
}
}
}
// 现网常无「准入单号」筛选项且首行仅单号有值:保持默认日期范围查询,断言列表仍含该单号(见用例 MD 备注路径)。
await this.query();
await this.expectRowsContainKeyword(orderNo);
}
async resetFilters(): Promise<void> {
await this.query();
const filled = await this.fillFirstVisibleFilter();
......@@ -102,12 +61,16 @@ export class AdmitMaterialListPage extends AdmitSharedPage {
await this.leaveWithoutCommit();
}
async detailCountMatches(): Promise<void> {
async detailOrderMatches(): Promise<void> {
await this.query();
const row = await this.firstRow();
const countText = (await this.cellText(row, '产品条数')).replace(/\s/g, '');
const orderNo = (await this.cellText(row, '准入单号')).replace(/\s/g, '');
if (!orderNo || orderNo === '--' || orderNo === '-') {
await this.guardedSkip('首行无可用准入单号');
return;
}
await this.openPutFromRow(row, '详情');
await expect(this.put()).toContainText(countText);
await expect(this.put(), '详情页应展示列表准入单号').toContainText(orderNo);
await this.leaveWithoutCommit();
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -13,6 +13,7 @@ export class AdmitProductListPage extends AdmitSharedPage {
menu: admitData.menuProductList,
forbidden: ['zrlist', 'productApply/', 'supplyApply/', 'accessKind/'],
});
this.columnSettingsToggleCandidates = admitData.productListColumnSettingsToggleCandidates;
}
async ready(): Promise<void> {
......
This diff is collapsed.
This diff is collapsed.
......@@ -12,6 +12,7 @@ export class AdmitSupplyPage extends AdmitSharedPage {
menu: admitData.menuSupply,
forbidden: ['productApply/', 'productOrder/', 'accessKind/'],
});
this.columnSettingsToggleCandidates = admitData.supplyColumnSettingsToggleCandidates;
}
async ready(): Promise<void> {
......@@ -34,9 +35,19 @@ export class AdmitSupplyPage extends AdmitSharedPage {
async resetFilters(): Promise<void> {
await this.query();
const supplier = await this.sampleCell('进院供应商');
await this.chooseSelect('进院供应商', supplier);
let clearedLabel: string | undefined;
if (await this.textInput('变更单号').isVisible().catch(() => false)) {
await this.fillFilter('变更单号', '样');
clearedLabel = '变更单号';
} else if (await this.textInput('物料名称').isVisible().catch(() => false)) {
await this.fillFilter('物料名称', '样');
clearedLabel = '物料名称';
} else {
const supplier = await this.sampleCell('进院供应商');
await this.chooseSelect('进院供应商', supplier);
}
await this.reset();
if (clearedLabel) await this.expectInputCleared(clearedLabel);
await this.expectListOrEmpty();
}
......@@ -81,17 +92,6 @@ export class AdmitSupplyPage extends AdmitSharedPage {
await expect(this.page.getByText(remark)).toHaveCount(0);
}
async switchModeWithoutSubmit(): Promise<void> {
const total = await this.getTotalCount();
await this.clickButton('新增');
await this.selectFirstOption('业务模式', this.put());
const no = this.put().getByText('否', { exact: true }).first();
if (await no.isVisible().catch(() => false)) await this.click(no, '切换是否默认');
else await this.selectFirstOption('是否默认', this.put());
await this.leaveWithoutCommit();
expect(await this.getTotalCount()).toBe(total);
}
async editBackfill(): Promise<void> {
await this.clickTab('待提交');
const row = await this.skipIfNoAction('编辑', '待提交无编辑');
......@@ -141,6 +141,31 @@ export class AdmitSupplyPage extends AdmitSharedPage {
await this.expectNeedsSelection('批量提交');
}
/** 非「待提交」Tab 有数据时行前复选框不可勾选;「待提交」Tab 可勾选。 */
async onlyPendingTabRowCheckboxCheckable(): Promise<void> {
await this.query();
const nonPendingTabs = ['已通过', '审批中', '已驳回', '全部'] as const;
let verifiedNonPending = false;
for (const tab of nonPendingTabs) {
const marked = await this.readTabCount(tab);
if (marked === 0) continue;
await this.clickTab(tab);
await this.waitForTableReady();
if ((await this.getDataRowCount()) === 0) continue;
await this.expectNoCheckableRows();
verifiedNonPending = true;
break;
}
if (!verifiedNonPending) {
await this.skipWhenDataInsufficient('无非待提交 Tab 数据,无法对比复选框禁用');
}
await this.clickTab('待提交');
await this.skipIfTabEmpty('待提交');
await this.clearChecks();
await this.checkFirstRow();
await this.clearChecks();
}
async batchCancel(): Promise<void> {
await this.skipIfTabEmpty('待提交');
const row = await this.checkFirstRow();
......@@ -164,6 +189,22 @@ export class AdmitSupplyPage extends AdmitSharedPage {
await this.leaveWithoutCommit();
}
async detailSupplierMatchesList(): Promise<void> {
await this.query();
const row = await this.skipIfNoAction('详情', '列表无详情入口');
const hospital = (await this.cellText(row, '进院供应商')).trim();
const secondary = (await this.cellText(row, '二级供应商')).trim();
await this.openPutFromRow(row, '详情');
const hNeedle = hospital.slice(0, Math.min(8, hospital.length));
expect(hNeedle.length, '进院供应商为空').toBeGreaterThan(0);
await expect(this.put(), '详情进院供应商').toContainText(hNeedle);
if (secondary) {
const sNeedle = secondary.slice(0, Math.min(8, secondary.length));
await expect(this.put(), '详情二级供应商').toContainText(sNeedle);
}
await this.leaveWithoutCommit();
}
/** 组合查询:一次性填满筛选区全部字段后查询(字段以现网搜索条为准)。 */
async filterCombination(): Promise<void> {
const scope = await this.queryScope();
......
......@@ -12,20 +12,13 @@ export class AdmitTaskPage extends AdmitSharedPage {
menu: admitData.menuTask,
forbidden: ['productApply/', 'productOrder/', 'supplyApply/'],
});
this.sortColumns = admitData.taskSortColumns;
}
async ready(): Promise<void> {
await this.expectOnPage();
}
async filterByProductName(): Promise<void> {
await this.query();
const name = await this.sampleCell(this.listNameColumn);
await this.fillProductNameFilter(name.slice(0, 40));
await this.query();
await this.expectRowsContain(this.listNameColumn, name);
}
async switchTabs(): Promise<void> {
await this.clickTabAndMatchCount('待分类');
await this.clickTabAndMatchCount('已分类');
......
......@@ -10,6 +10,7 @@ export class BasicBranchPage extends BasicHospitalSharedPage {
constructor(page: Page) {
super(page);
this.locators = new BasicBranchLocators(page);
this.columnSettingsToggleCandidates = basicHospitalData.branchColumnSettingsToggleCandidates;
}
async open(): Promise<void> {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment