mirror of
https://github.com/hansjone/netx.git
synced 2026-10-15 09:43:18 +08:00
Optimize cutover compare/monitor per the 2026-10-12 plan.
Correctness (A): normalize port-map names with the template rules (snapshot v2, v1 replays unchanged); protect mappings/templates that are referenced; stop dropping edited mapping text; accept pulled-but-not-shutdown ports as migrated; validate baseline ownership on project create; one canonical key form; fix built-in template tolerances and upgrade old packaged values in place. Cross-vendor identity (B): single identity pipeline for every path, per-side and per-vendor interface rules, value maps, filters after normalization, mapping pre-flight for compare and cutover projects, SQL eligibility fixes. Data quality (V): no_data / suspect_parse / not_collected sheet states, command slice coverage, directional compare modes, value-sorted duplicate pairing, before-side raw names in results and CSV. Robustness (H): bounded auto-run history, background evaluate/finish with polling, manual route tables out of the acceptance gate, baseline row cache, scoped duplicate-key failures, merged HF tasks with a per-NE session cap, same-device cutover, explicit scope_by_port_map, read-only GETs, resolvable red tickets. Frontend: pre-flight report, mapping table view, template editor support for the new rules, data-state banners. Docs: canonical field contract. Not included: Huawei status parsers (no real samples), SQL-path route compare. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fff7d63b9b
commit
315539e0fd
59 changed files with 6483 additions and 487 deletions
|
|
@ -149,6 +149,45 @@ try {
|
|||
await savedJob;
|
||||
assert.deepEqual(writes.at(-1).enabled_sheet_ids, []);
|
||||
passed.push("missing sheets block save", "incomplete sources disabled", "explicit scope repair");
|
||||
// Cross-vendor identity rules: value maps, directional compare, per-side aliases and sheet options
|
||||
// must reach the API exactly as edited.
|
||||
await page.goto(`${base}/network/cutover/compare-templates`);
|
||||
await templateRow().waitFor();
|
||||
await openEditor();
|
||||
await editor().locator("details.ct-editor__norm summary").click();
|
||||
await editor().getByLabel("接口归一化", { exact: true }).fill("GE,gei\nEth-Trunk,ae,after,huawei");
|
||||
await editor().getByRole("tab", { name: /^字段规则/ }).click();
|
||||
const stateRow = editor().locator(".ct-field-table tbody tr").filter({ has: page.getByText("state", { exact: true }) });
|
||||
await stateRow.locator('input[type="checkbox"]').nth(2).check();
|
||||
await editor().getByLabel("state 方式", { exact: true }).selectOption("not_worse");
|
||||
await editor().getByLabel("state 好→坏顺序", { exact: true }).fill("up,down");
|
||||
await editor().getByLabel("state 值映射", { exact: true }).fill("estab,established\n*down,down");
|
||||
await editor().getByLabel("state 值映射", { exact: true }).blur();
|
||||
await editor().getByLabel("state 值映射范围", { exact: true }).selectOption("before");
|
||||
await editor().getByLabel("state 值映射", { exact: true }).fill("up/up,up");
|
||||
await editor().getByLabel("state 值映射", { exact: true }).blur();
|
||||
await editor().getByLabel("未映射端口", { exact: true }).selectOption("ignore_port");
|
||||
await editor().getByLabel("同键多行配对", { exact: true }).selectOption("ordered");
|
||||
await editor().getByRole("checkbox", { name: /内置厂商接口名称统一/ }).uncheck();
|
||||
await editor().getByRole("button", { name: "保存模板", exact: true }).click();
|
||||
await page.waitForTimeout(500);
|
||||
const saved = writes.at(-1);
|
||||
assert.deepEqual(saved.iface_normalize_rules, [{ from: "GE", to: "gei" }, { from: "Eth-Trunk", to: "ae", side: "after", vendor: "huawei" }]);
|
||||
const sheetS = saved.metrics.find((m) => m.sheet_id === "s");
|
||||
const stateRules = sheetS.field_rules.filter((r) => r.field === "state");
|
||||
assert.deepEqual(stateRules.find((r) => !r.side), { field: "state", compare: "not_worse", rank: ["up", "down"], value_map: { estab: "established", "*down": "down" } });
|
||||
assert.deepEqual(stateRules.find((r) => r.side === "before"), { field: "state", side: "before", value_map: { "up/up": "up" } });
|
||||
assert.equal(sheetS.unmapped_port_policy, "ignore_port");
|
||||
assert.equal(sheetS.duplicate_pairing, "ordered");
|
||||
assert.equal(sheetS.builtin_vendor_canonical, false);
|
||||
assert.deepEqual(sheetS.row_filters, complex, "opaque filters survive the same save");
|
||||
passed.push("value map and rank saved", "per-side value map saved", "per-side alias saved", "sheet identity options saved");
|
||||
// ... and come back unchanged when the template is opened again.
|
||||
await openEditor();
|
||||
await editor().getByRole("tab", { name: /^字段规则/ }).click();
|
||||
assert.equal(await editor().getByLabel("state 值映射", { exact: true }).inputValue(), "estab,established\n*down,down");
|
||||
assert.equal(await editor().getByLabel("未映射端口", { exact: true }).inputValue(), "ignore_port");
|
||||
await page.keyboard.press("Escape");
|
||||
assert.deepEqual(errors, []);
|
||||
passed.push("no runtime errors");
|
||||
console.log(JSON.stringify({ passed, output }));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue