Files
OpenFrontIO/tests/Privilege.test.ts
T
Evan 39ad547c04 support for unlockable flags (#3479)
## Description:

Add support for purchasable/gated flags.

* Create a new "Store" modal that renders both skins & flags
* move all store related logic out of TerritoryPatternsModal
* use nation:code for existing nation flags & flag:key for gated flags
* check if user has the appropriate flags before purchasing

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2026-03-23 17:09:18 -07:00

226 lines
7.4 KiB
TypeScript

import {
createMatcher,
PrivilegeCheckerImpl,
shadowNames,
} from "../src/server/Privilege";
const bannedWords = [
"hitler",
"adolf",
"nazi",
"jew",
"auschwitz",
"whitepower",
"heil",
"chair", // Test word to verify custom banned words work
];
const matcher = createMatcher(bannedWords);
// Create a minimal PrivilegeCheckerImpl for testing censorUsername
const mockCosmetics = { patterns: {}, colorPalettes: {}, flags: {} };
const mockDecoder = () => new Uint8Array();
const checker = new PrivilegeCheckerImpl(
mockCosmetics,
mockDecoder,
bannedWords,
);
const emptyChecker = new PrivilegeCheckerImpl(mockCosmetics, mockDecoder, []);
const flagCosmetics = {
patterns: {},
colorPalettes: {},
flags: {
cool_flag: {
name: "cool_flag",
url: "https://example.com/cool.png",
affiliateCode: null,
product: { productId: "prod_1", priceId: "price_1", price: "$4.99" },
},
},
};
const flagChecker = new PrivilegeCheckerImpl(
flagCosmetics,
mockDecoder,
bannedWords,
);
describe("UsernameCensor", () => {
describe("isProfane (via matcher.hasMatch)", () => {
test("detects exact banned words", () => {
expect(matcher.hasMatch("hitler")).toBe(true);
expect(matcher.hasMatch("nazi")).toBe(true);
expect(matcher.hasMatch("auschwitz")).toBe(true);
});
test("detects custom banned words like 'chair'", () => {
expect(matcher.hasMatch("chair")).toBe(true);
expect(matcher.hasMatch("Chair")).toBe(true);
expect(matcher.hasMatch("CHAIR")).toBe(true);
expect(matcher.hasMatch("MyChairName")).toBe(true);
});
test("detects banned words case-insensitively", () => {
expect(matcher.hasMatch("Hitler")).toBe(true);
expect(matcher.hasMatch("NAZI")).toBe(true);
expect(matcher.hasMatch("Adolf")).toBe(true);
});
test("detects banned words with leet speak", () => {
expect(matcher.hasMatch("h1tl3r")).toBe(true);
expect(matcher.hasMatch("4d0lf")).toBe(true);
expect(matcher.hasMatch("n4z1")).toBe(true);
});
test("detects banned words with duplicated characters", () => {
expect(matcher.hasMatch("hiiitler")).toBe(true);
expect(matcher.hasMatch("naazzii")).toBe(true);
});
test("detects banned words with accented characters", () => {
expect(matcher.hasMatch("Adölf")).toBe(true);
});
test("detects banned words as substrings", () => {
expect(matcher.hasMatch("xhitlerx")).toBe(true);
expect(matcher.hasMatch("IloveNazi")).toBe(true);
});
test("allows clean usernames", () => {
expect(matcher.hasMatch("CoolPlayer")).toBe(false);
expect(matcher.hasMatch("GameMaster")).toBe(false);
expect(matcher.hasMatch("xXx_Sniper_xXx")).toBe(false);
});
});
describe("censorUsername", () => {
test("returns clean usernames unchanged", () => {
expect(checker.censorUsername("CoolPlayer")).toBe("CoolPlayer");
expect(checker.censorUsername("GameMaster")).toBe("GameMaster");
});
test("replaces profane usernames with a shadow name", () => {
const result = checker.censorUsername("hitler");
expect(shadowNames).toContain(result);
});
test("replaces leet speak profane usernames with a shadow name", () => {
const result = checker.censorUsername("h1tl3r");
expect(shadowNames).toContain(result);
});
test("preserves clean clan tag when username is profane", () => {
const result = checker.censorUsername("[COOL]hitler");
expect(result).toMatch(/^\[COOL\] /);
const nameAfterTag = result.replace("[COOL] ", "");
expect(shadowNames).toContain(nameAfterTag);
});
test("removes profane clan tag but keeps clean username", () => {
expect(checker.censorUsername("[NAZI]CoolPlayer")).toBe("CoolPlayer");
});
test("removes clan tag with leet speak profanity", () => {
expect(checker.censorUsername("[N4Z1]CoolPlayer")).toBe("CoolPlayer");
});
test("removes clan tag with uppercased banned word", () => {
expect(checker.censorUsername("[ADOLF]CoolPlayer")).toBe("CoolPlayer");
});
test("removes clan tag containing banned word substring", () => {
expect(checker.censorUsername("[JEWS]CoolPlayer")).toBe("CoolPlayer");
});
test("removes profane clan tag and censors profane username", () => {
const result = checker.censorUsername("[NAZI]hitler");
// No clan tag prefix, just a shadow name
expect(shadowNames).toContain(result);
});
test("removes leet speak profane clan tag and censors leet speak username", () => {
const result = checker.censorUsername("[N4Z1]h1tl3r");
// No clan tag prefix, just a shadow name
expect(shadowNames).toContain(result);
});
test("returns deterministic shadow name for same input", () => {
const a = checker.censorUsername("hitler");
const b = checker.censorUsername("hitler");
expect(a).toBe(b);
});
test("handles username with no clan tag", () => {
expect(checker.censorUsername("NormalPlayer")).toBe("NormalPlayer");
});
test("empty banned words list still catches englishDataset profanity", () => {
// The emptyChecker still uses englishDataset, so common profanity is caught
expect(emptyChecker.censorUsername("CoolPlayer")).toBe("CoolPlayer");
// Verify a known english profanity gets censored even without custom banned words
const result = emptyChecker.censorUsername("fuck");
expect(shadowNames).toContain(result);
});
});
});
describe("Flag validation in isAllowed", () => {
test("allows valid country flag and resolves to SVG path", () => {
const result = flagChecker.isAllowed([], { flag: "country:us" });
expect(result.type).toBe("allowed");
if (result.type === "allowed") {
expect(result.cosmetics.flag).toBe("/flags/us.svg");
}
});
test("rejects invalid country code", () => {
const result = flagChecker.isAllowed([], { flag: "country:zzzz" });
expect(result.type).toBe("forbidden");
});
test("rejects flag with no prefix", () => {
const result = flagChecker.isAllowed([], { flag: "us" });
expect(result.type).toBe("forbidden");
});
test("allows cosmetic flag when user has wildcard flare", () => {
const result = flagChecker.isAllowed(["flag:*"], {
flag: "flag:cool_flag",
});
expect(result.type).toBe("allowed");
if (result.type === "allowed") {
expect(result.cosmetics.flag).toBe("https://example.com/cool.png");
}
});
test("allows cosmetic flag when user has specific flare", () => {
const result = flagChecker.isAllowed(["flag:cool_flag"], {
flag: "flag:cool_flag",
});
expect(result.type).toBe("allowed");
if (result.type === "allowed") {
expect(result.cosmetics.flag).toBe("https://example.com/cool.png");
}
});
test("rejects cosmetic flag when user lacks flare", () => {
const result = flagChecker.isAllowed([], { flag: "flag:cool_flag" });
expect(result.type).toBe("forbidden");
});
test("rejects cosmetic flag that does not exist", () => {
const result = flagChecker.isAllowed(["flag:*"], {
flag: "flag:nonexistent",
});
expect(result.type).toBe("forbidden");
});
test("allows no flag", () => {
const result = flagChecker.isAllowed([], {});
expect(result.type).toBe("allowed");
if (result.type === "allowed") {
expect(result.cosmetics.flag).toBeUndefined();
}
});
});