aboutsummaryrefslogtreecommitdiff
path: root/src/lib/User/BadgeWall/badgeLinks.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/User/BadgeWall/badgeLinks.test.ts')
-rw-r--r--src/lib/User/BadgeWall/badgeLinks.test.ts70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/lib/User/BadgeWall/badgeLinks.test.ts b/src/lib/User/BadgeWall/badgeLinks.test.ts
new file mode 100644
index 00000000..301288ec
--- /dev/null
+++ b/src/lib/User/BadgeWall/badgeLinks.test.ts
@@ -0,0 +1,70 @@
+import { describe, expect, it } from "vitest";
+import { classifyDesigner, classifySource } from "./badgeLinks";
+
+describe("classifySource", () => {
+ it("labels known hosts and keeps the original href", () => {
+ expect(classifySource("https://www.pixiv.net/en/artworks/1")).toEqual({
+ href: "https://www.pixiv.net/en/artworks/1",
+ label: "Pixiv",
+ });
+ expect(classifySource("https://x.com/someone")).toEqual({
+ href: "https://x.com/someone",
+ label: "X (Twitter)",
+ });
+ });
+
+ it("falls back to the raw url as label for unknown hosts", () => {
+ expect(classifySource("https://example.com/art")).toEqual({
+ href: "https://example.com/art",
+ label: "https://example.com/art",
+ });
+ });
+
+ it("rejects non-http(s) and malformed urls (href becomes null)", () => {
+ expect(classifySource("javascript:alert(1)").href).toBeNull();
+ expect(classifySource("data:text/html,<script>1</script>").href).toBeNull();
+ expect(classifySource("not a url").href).toBeNull();
+ });
+
+ it("never produces a usable href for an html-injection payload", () => {
+ const payload = 'http://x"><img src=x onerror=alert(document.cookie)>';
+ const result = classifySource(payload);
+
+ expect(result.href).toBeNull();
+ expect(result.label).toBe(payload);
+ });
+});
+
+describe("classifyDesigner", () => {
+ it("extracts the username from an anilist profile url", () => {
+ expect(classifyDesigner("https://anilist.co/user/fuwn/")).toEqual({
+ href: "https://anilist.co/user/fuwn/",
+ label: "fuwn",
+ });
+ });
+
+ it("builds an anilist link from an @handle", () => {
+ expect(classifyDesigner("@fuwn")).toEqual({
+ href: "https://anilist.co/user/fuwn/",
+ label: "fuwn",
+ });
+ });
+
+ it("builds an anilist link from a bare name", () => {
+ expect(classifyDesigner("fuwn")).toEqual({
+ href: "https://anilist.co/user/fuwn/",
+ label: "fuwn",
+ });
+ });
+
+ it("forces an html-injection payload into the anilist path, never its own scheme/host", () => {
+ const payload = '"><img src=x onerror=alert(document.cookie)>';
+ const result = classifyDesigner(payload);
+
+ expect(
+ result.href === null ||
+ result.href.startsWith("https://anilist.co/user/"),
+ ).toBe(true);
+ expect(result.label).toBe(payload);
+ });
+});