netx/web/tests/mappingText.test.mjs
oliver 315539e0fd 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>
2026-10-12 11:51:55 +08:00

30 lines
1.4 KiB
JavaScript

import assert from "node:assert/strict";
import { test } from "node:test";
import { parseMapText, mapTextDirty } from "../src/features/cutover/lib/mappingText.ts";
test("comma, pipe, tab and exactly-two-token space lines are all accepted", () => {
const r = parseMapText("a1,b1\na2|b2\na3\tb3\na4 b4\n# note\n\nbefore_if,after_if");
assert.deepEqual(r.rows.map((x) => [x.before_if, x.after_if]), [["a1", "b1"], ["a2", "b2"], ["a3", "b3"], ["a4", "b4"]]);
assert.deepEqual(r.invalidLines, []);
});
test("unreadable lines are reported with their line numbers instead of dropped", () => {
const r = parseMapText("a1,b1\nonlyone\na,b,c\na5 b5 c5\nok1,ok2");
assert.deepEqual(r.invalidLines, [2, 3, 4]);
assert.equal(r.rows.length, 2);
});
test("repeated before port is flagged and the first pair is kept", () => {
const r = parseMapText("a,b\na,c");
assert.deepEqual(r.duplicateBefore, ["a"]);
assert.deepEqual(r.rows, [{ before_if: "a", after_if: "b" }]);
});
test("dirty check ignores order and spacing but sees edits and invalid text", () => {
const saved = [{ before_if: "a", after_if: "b" }, { before_if: "c", after_if: "d" }];
assert.equal(mapTextDirty("c , d\na,b", saved), false);
assert.equal(mapTextDirty("a,b", saved), true);
assert.equal(mapTextDirty("a,b\nc,d\nbroken", saved), true);
assert.equal(mapTextDirty("", undefined), false);
assert.equal(mapTextDirty("x,y", undefined), true);
});