Files
anonymous_github/test/term-presence.test.js
T

76 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { expect } = require("chai");
require("ts-node/register/transpile-only");
const { TermPresenceIndex } = require("../src/core/term-presence");
const { compileTerms, ContentAnonimizer } = require("../src/core/anonymize-utils");
function reference(terms, text) {
const anonymizer = new ContentAnonimizer({ terms });
anonymizer.termPresence = null;
for (const term of anonymizer.compiledTerms) delete term.literalPrefilter;
return anonymizer.anonymize(text);
}
describe("term candidate index", function () {
it("retains shared prefixes, nested matches and Unicode-folded alternatives", function () {
const patterns = [/Alice/iu, /AliceSmith/iu, /Smith/iu, /[sśŝşšș]/iu, /ſ/iu, /K/iu, /k/iu, /研究/iu];
const index = new TermPresenceIndex(patterns);
for (const text of ["AliceSmith", "ALICESMITH K ſ 研究", "nothing", "ś", "k", "aAliceSmith"]) {
for (let after = -1; after < patterns.length; after++) {
const candidates = index.candidates(text, after);
patterns.forEach((pattern, i) => {
if (i > after && pattern.test(text)) expect(candidates.has(i), `${text}: ${i}`).to.equal(true);
if (i <= after) expect(candidates.has(i)).to.equal(false);
});
}
}
});
it("keeps dot's CR and Unicode line-separator matches", function () {
for (const text of ["first\rlast", "first\u2028last", "first\u2029last", "first\nlast", "first😀last"]) {
expect(new ContentAnonimizer({ terms: ["first.last"] }).anonymize(text)).to.equal(reference(["first.last"], text));
}
});
it("retains ordered cascades, URL removal, and matches created across replacement boundaries", function () {
const cases = [
[["Alice=>Bob", "Bob=>Hidden"], "Alice Bob https://host/Alice"],
[["Alice=>", "@Bob=>Hidden"], "@AliceBob"],
[["a-a", "Alice"], "xa-a-a Alice https://host/Alice/file"],
[["first.last", "firstXlast=>other"], "firstXlast first.last"],
[["Alice=>Bob", "Bob"], "https://host/Alice"],
[["k", "s"], "K ſ ék k_ xK Kx"],
[["Alice=>Bob", "B.b=>Done"], "Alice"],
[["k=>Kk"], "https://host/k"],
[["Alice=>$&", "Bob=>$$"], "Alice Bob"],
[["\u0301"], "abc"],
[["a.*b", "Alice"], "axxb Alice"],
];
for (const [terms, text] of cases) {
expect(new ContentAnonimizer({ terms }).anonymize(text), JSON.stringify([terms, text])).to.equal(reference(terms, text));
}
});
it("matches the RE2 path for fixed-width terms and surrounding characters", function () {
const terms = ["a-a", "a.a", "k", "s", "k.s", "Alice", "@Alice", "Σ", "研究", "😀", "..", "a.", "a..b"];
const edges = ["", "x", "_", "é", "K", "ſ", "😀", "𐐀", "\r", "\n", "\u2028"];
for (const term of terms) {
const input = edges.flatMap(left => edges.map(right => `${left}${term}${right} ${left}${term.replaceAll(".", "\r")}${right}`)).join(" ");
expect(new ContentAnonimizer({ terms: [term] }).anonymize(input), term).to.equal(reference([term], input));
}
});
it("does not reuse stale rules after the caller edits its term list", function () {
const terms = ["Alice=>first"];
expect(new ContentAnonimizer({ terms }).anonymize("Alice")).to.equal("first");
terms[0] = "Alice=>second";
expect(new ContentAnonimizer({ terms }).anonymize("Alice")).to.equal("second");
expect(new ContentAnonimizer({ terms: ["Alice=>first"] }).anonymize("Alice")).to.equal("first");
});
it("does not index quantified, capturing, or escaped user patterns", function () {
for (const term of ["a.*b", "a+b", "(Alice)", "a\\.b", "a(?=b)"]) {
expect(compileTerms([term]).every(c => !c.literalPrefilter), term).to.equal(true);
}
});
});