mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Make each admin action self-explanatory and give content appeals a real effect instead of a dead-end "Dismiss". - submissionsSection.js: per-type action sets, each button paired with a one-line description. Applications show Approve (adds to whitelist) / Deny; appeals that name a real event show "Approve & unblock" (removes the video from the event block list) / "Keep blocked"; other types show "Mark handled". - submissionService.js: parse an appeal's `e` tag into targetEventId (trusted only when it's a well-formed 64-char hex id). - iframe-content-appeals-form.html: add a required "Blocked video link or event ID" field; regex-validate + normalize a share link / nevent / note / hex to the hex event id, tag it as `e`, and include it in the body. Block submission when no valid reference is provided. - CSS: stacked action + hint styling; iframe-form .form-hint. - tests: cover targetEventId parsing (valid, malformed, absent). Co-Authored-By: Claude Opus 4.8 <[email protected]>
161 lines
4.9 KiB
JavaScript
161 lines
4.9 KiB
JavaScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
SUBMISSION_KIND,
|
|
SUBMISSION_TYPES,
|
|
parseSubmissionEvent,
|
|
buildSubmission,
|
|
generateSubmissionId,
|
|
} from "../js/submissions/submissionService.js";
|
|
import { buildSubmissionEvent } from "../js/nostrEventSchemas.js";
|
|
|
|
const EPHEMERAL = "e".repeat(64);
|
|
const ADMIN = "a".repeat(64);
|
|
const APPLICANT = "npub1exampleapplicant";
|
|
|
|
test("buildSubmissionEvent emits kind, d, type, applicant, recipient, topic", () => {
|
|
const event = buildSubmissionEvent({
|
|
pubkey: EPHEMERAL,
|
|
created_at: 1000,
|
|
dTagValue: "sub-1",
|
|
submissionType: "application",
|
|
applicantNpub: APPLICANT,
|
|
recipientPubkey: ADMIN,
|
|
content: "Please whitelist me, I make Blender tutorials.",
|
|
});
|
|
|
|
assert.equal(event.kind, SUBMISSION_KIND);
|
|
assert.equal(event.tags.find((t) => t[0] === "d")?.[1], "sub-1");
|
|
assert.equal(event.tags.find((t) => t[0] === "t")?.[1], "bitvid-submission");
|
|
assert.equal(event.tags.find((t) => t[0] === "k")?.[1], "application");
|
|
assert.equal(event.tags.find((t) => t[0] === "applicant")?.[1], APPLICANT);
|
|
assert.equal(event.tags.find((t) => t[0] === "p")?.[1], ADMIN);
|
|
assert.equal(event.content, "Please whitelist me, I make Blender tutorials.");
|
|
});
|
|
|
|
test("buildSubmissionEvent requires a d-tag", () => {
|
|
assert.throws(
|
|
() => buildSubmissionEvent({ pubkey: EPHEMERAL, created_at: 1, dTagValue: " " }),
|
|
/requires a d-tag/i,
|
|
);
|
|
});
|
|
|
|
test("buildSubmissionEvent defaults type to application", () => {
|
|
const event = buildSubmissionEvent({
|
|
pubkey: EPHEMERAL,
|
|
created_at: 1,
|
|
dTagValue: "d",
|
|
});
|
|
assert.equal(event.tags.find((t) => t[0] === "k")?.[1], "application");
|
|
});
|
|
|
|
test("parseSubmissionEvent structures a submission", () => {
|
|
const event = buildSubmissionEvent({
|
|
pubkey: EPHEMERAL,
|
|
created_at: 4242,
|
|
dTagValue: "sub-7",
|
|
submissionType: "bug",
|
|
applicantNpub: APPLICANT,
|
|
recipientPubkey: ADMIN,
|
|
content: "the zap button is off-center",
|
|
});
|
|
event.id = "event-id-9";
|
|
|
|
const parsed = parseSubmissionEvent(event);
|
|
assert.equal(parsed.id, "sub-7");
|
|
assert.equal(parsed.eventId, "event-id-9");
|
|
assert.equal(parsed.type, "bug");
|
|
assert.equal(parsed.applicant, APPLICANT);
|
|
assert.equal(parsed.recipient, ADMIN);
|
|
assert.equal(parsed.content, "the zap button is off-center");
|
|
assert.equal(parsed.createdAt, 4242);
|
|
assert.equal(parsed.pubkey, EPHEMERAL);
|
|
});
|
|
|
|
test("parseSubmissionEvent surfaces an appeal's blocked-event target from the e tag", () => {
|
|
const target = "b".repeat(64);
|
|
const parsed = parseSubmissionEvent({
|
|
kind: SUBMISSION_KIND,
|
|
pubkey: EPHEMERAL,
|
|
created_at: 10,
|
|
tags: [
|
|
["d", "appeal-1"],
|
|
["k", "appeal"],
|
|
["p", ADMIN],
|
|
["e", target.toUpperCase()],
|
|
],
|
|
});
|
|
assert.equal(parsed.type, "appeal");
|
|
// lowercased, ready to feed straight into the event block list
|
|
assert.equal(parsed.targetEventId, target);
|
|
});
|
|
|
|
test("parseSubmissionEvent ignores a malformed e tag and defaults target to ''", () => {
|
|
const parsed = parseSubmissionEvent({
|
|
kind: SUBMISSION_KIND,
|
|
pubkey: EPHEMERAL,
|
|
created_at: 10,
|
|
tags: [
|
|
["d", "appeal-2"],
|
|
["k", "appeal"],
|
|
["e", "not-a-real-event-id"],
|
|
],
|
|
});
|
|
assert.equal(parsed.targetEventId, "");
|
|
});
|
|
|
|
test("parseSubmissionEvent leaves targetEventId empty when no e tag is present", () => {
|
|
const parsed = parseSubmissionEvent({
|
|
kind: SUBMISSION_KIND,
|
|
pubkey: EPHEMERAL,
|
|
created_at: 10,
|
|
tags: [["d", "x"], ["k", "application"]],
|
|
});
|
|
assert.equal(parsed.targetEventId, "");
|
|
});
|
|
|
|
test("parseSubmissionEvent normalizes an unknown type to 'other'", () => {
|
|
const parsed = parseSubmissionEvent({
|
|
kind: SUBMISSION_KIND,
|
|
pubkey: EPHEMERAL,
|
|
created_at: 1,
|
|
tags: [["d", "x"], ["k", "totally-made-up"]],
|
|
});
|
|
assert.equal(parsed.type, "other");
|
|
});
|
|
|
|
test("parseSubmissionEvent rejects the wrong kind and a missing d", () => {
|
|
assert.equal(parseSubmissionEvent({ kind: 1, tags: [["d", "x"]] }), null);
|
|
assert.equal(
|
|
parseSubmissionEvent({ kind: SUBMISSION_KIND, tags: [["k", "application"]] }),
|
|
null,
|
|
);
|
|
assert.equal(parseSubmissionEvent(null), null);
|
|
});
|
|
|
|
test("build → parse round-trips every known type", () => {
|
|
for (const type of Object.values(SUBMISSION_TYPES)) {
|
|
const event = buildSubmission({
|
|
pubkey: EPHEMERAL,
|
|
id: `rt-${type}`,
|
|
type,
|
|
applicantNpub: APPLICANT,
|
|
recipientPubkey: ADMIN,
|
|
content: `body for ${type}`,
|
|
created_at: 5,
|
|
});
|
|
const parsed = parseSubmissionEvent({ ...event, id: `signed-${type}` });
|
|
assert.equal(parsed.type, type);
|
|
assert.equal(parsed.content, `body for ${type}`);
|
|
assert.equal(parsed.applicant, APPLICANT);
|
|
}
|
|
});
|
|
|
|
test("generateSubmissionId produces distinct, tag-safe ids", () => {
|
|
const a = generateSubmissionId();
|
|
const b = generateSubmissionId();
|
|
assert.notEqual(a, b);
|
|
assert.match(a, /^sub-[0-9a-z]+-[0-9a-z]+$/);
|
|
});
|