mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-30 09:22:24 +00:00
Add tests for modal similar content filtering
This commit is contained in:
1 parent
2016c01183
commit
d09002e0dd
3 files changed
+223
No files matched your search
@@ -1879,6 +1879,9 @@ class Application {
|
||||
if (candidate.isPrivate === true) {
|
||||
continue;
|
||||
}
|
||||
if (candidate.isNsfw === true && ALLOW_NSFW_CONTENT !== true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const candidatePubkey = typeof candidate.pubkey === "string" ? candidate.pubkey : "";
|
||||
if (candidatePubkey && this.isAuthorBlocked(candidatePubkey)) {
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import Application from "../../js/app.js";
|
||||
|
||||
const computeSimilarContent = Application.prototype.computeSimilarContentCandidates;
|
||||
|
||||
function createAppStub({ videos = [] } = {}) {
|
||||
const videosMap = new Map();
|
||||
for (const video of videos) {
|
||||
if (video && typeof video.id === "string") {
|
||||
videosMap.set(video.id, video);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
videoListView: { currentVideos: videos },
|
||||
videosMap,
|
||||
getKnownVideoPostedAt(video) {
|
||||
if (Number.isFinite(video?.rootCreatedAt)) {
|
||||
return Math.floor(video.rootCreatedAt);
|
||||
}
|
||||
if (Number.isFinite(video?.created_at)) {
|
||||
return Math.floor(video.created_at);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
buildShareUrlFromEventId(id) {
|
||||
return id ? `https://bitvid.invalid/${id}` : "";
|
||||
},
|
||||
formatTimeAgo(timestamp) {
|
||||
return Number.isFinite(timestamp) ? `${timestamp}s` : "";
|
||||
},
|
||||
deriveVideoPointerInfo(video) {
|
||||
if (video?.pointerInfo) {
|
||||
return video.pointerInfo;
|
||||
}
|
||||
if (typeof video?.pointerKey === "string" && video.pointerKey.trim()) {
|
||||
return { key: video.pointerKey.trim() };
|
||||
}
|
||||
return null;
|
||||
},
|
||||
isAuthorBlocked() {
|
||||
return false;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createVideo({
|
||||
id,
|
||||
pubkey = "author",
|
||||
displayTags,
|
||||
tags,
|
||||
rootCreatedAt,
|
||||
created_at,
|
||||
pointerKey,
|
||||
pointerInfo,
|
||||
shareUrl,
|
||||
isPrivate = false,
|
||||
isNsfw = false,
|
||||
} = {}) {
|
||||
const video = {
|
||||
id,
|
||||
pubkey,
|
||||
isPrivate,
|
||||
isNsfw,
|
||||
};
|
||||
|
||||
if (Array.isArray(displayTags)) {
|
||||
video.displayTags = displayTags.slice();
|
||||
}
|
||||
if (Array.isArray(tags)) {
|
||||
video.tags = tags.slice();
|
||||
}
|
||||
if (Number.isFinite(rootCreatedAt)) {
|
||||
video.rootCreatedAt = Math.floor(rootCreatedAt);
|
||||
}
|
||||
if (Number.isFinite(created_at)) {
|
||||
video.created_at = Math.floor(created_at);
|
||||
}
|
||||
if (typeof pointerKey === "string") {
|
||||
video.pointerKey = pointerKey;
|
||||
}
|
||||
if (pointerInfo) {
|
||||
video.pointerInfo = pointerInfo;
|
||||
}
|
||||
if (typeof shareUrl === "string") {
|
||||
video.shareUrl = shareUrl;
|
||||
}
|
||||
|
||||
return video;
|
||||
}
|
||||
|
||||
test("orders similar videos by shared tags then timestamp", () => {
|
||||
const activeVideo = createVideo({
|
||||
id: "root-video",
|
||||
displayTags: ["Art", "Music", "News"],
|
||||
});
|
||||
|
||||
const candidateA = createVideo({
|
||||
id: "video-a",
|
||||
displayTags: ["art", "music"],
|
||||
rootCreatedAt: 100,
|
||||
});
|
||||
const candidateB = createVideo({
|
||||
id: "video-b",
|
||||
displayTags: ["art"],
|
||||
rootCreatedAt: 200,
|
||||
});
|
||||
const candidateC = createVideo({
|
||||
id: "video-c",
|
||||
displayTags: ["art", "music"],
|
||||
rootCreatedAt: 50,
|
||||
});
|
||||
|
||||
const app = createAppStub({
|
||||
videos: [candidateA, candidateB, candidateC],
|
||||
});
|
||||
|
||||
const matches = computeSimilarContent.call(app, { activeVideo, maxItems: 5 });
|
||||
assert.equal(matches.length, 3);
|
||||
assert.deepEqual(
|
||||
matches.map((entry) => entry.video.id),
|
||||
["video-a", "video-c", "video-b"],
|
||||
);
|
||||
assert.deepEqual(
|
||||
matches.map((entry) => entry.sharedTagCount),
|
||||
[2, 2, 1],
|
||||
);
|
||||
});
|
||||
|
||||
test("returns no matches when the active video lacks tags", () => {
|
||||
const activeVideo = createVideo({
|
||||
id: "root-video",
|
||||
});
|
||||
|
||||
const candidate = createVideo({
|
||||
id: "video-a",
|
||||
displayTags: ["art"],
|
||||
});
|
||||
|
||||
const app = createAppStub({ videos: [candidate] });
|
||||
const matches = computeSimilarContent.call(app, { activeVideo, maxItems: 5 });
|
||||
assert.deepEqual(matches, []);
|
||||
});
|
||||
|
||||
test("skips candidates without tag metadata", () => {
|
||||
const activeVideo = createVideo({
|
||||
id: "root-video",
|
||||
displayTags: ["art"],
|
||||
});
|
||||
|
||||
const candidateWithTags = createVideo({
|
||||
id: "video-a",
|
||||
displayTags: ["art"],
|
||||
});
|
||||
const candidateWithoutTags = createVideo({
|
||||
id: "video-b",
|
||||
});
|
||||
|
||||
const app = createAppStub({
|
||||
videos: [candidateWithTags, candidateWithoutTags],
|
||||
});
|
||||
|
||||
const matches = computeSimilarContent.call(app, { activeVideo, maxItems: 5 });
|
||||
assert.equal(matches.length, 1);
|
||||
assert.equal(matches[0].video.id, "video-a");
|
||||
});
|
||||
|
||||
test("filters NSFW and private videos when NSFW content is disabled", () => {
|
||||
const activeVideo = createVideo({
|
||||
id: "root-video",
|
||||
displayTags: ["art"],
|
||||
});
|
||||
|
||||
const publicVideo = createVideo({
|
||||
id: "video-public",
|
||||
displayTags: ["art"],
|
||||
});
|
||||
const nsfwVideo = createVideo({
|
||||
id: "video-nsfw",
|
||||
displayTags: ["art"],
|
||||
isNsfw: true,
|
||||
});
|
||||
const privateVideo = createVideo({
|
||||
id: "video-private",
|
||||
displayTags: ["art"],
|
||||
isPrivate: true,
|
||||
});
|
||||
|
||||
const app = createAppStub({
|
||||
videos: [publicVideo, nsfwVideo, privateVideo],
|
||||
});
|
||||
|
||||
const matches = computeSimilarContent.call(app, { activeVideo, maxItems: 5 });
|
||||
assert.deepEqual(
|
||||
matches.map((entry) => entry.video.id),
|
||||
["video-public"],
|
||||
);
|
||||
});
|
||||
@@ -2,6 +2,26 @@ if (typeof globalThis.window === "undefined") {
|
||||
globalThis.window = {};
|
||||
}
|
||||
|
||||
if (typeof globalThis.self === "undefined") {
|
||||
globalThis.self = globalThis;
|
||||
}
|
||||
|
||||
if (typeof globalThis.WebSocket === "undefined") {
|
||||
globalThis.WebSocket = class WebSocket {};
|
||||
}
|
||||
|
||||
if (typeof globalThis.navigator === "undefined") {
|
||||
globalThis.navigator = { userAgent: "node" };
|
||||
}
|
||||
|
||||
if (typeof globalThis.window.WebSocket === "undefined") {
|
||||
globalThis.window.WebSocket = globalThis.WebSocket;
|
||||
}
|
||||
|
||||
if (typeof globalThis.window.navigator === "undefined") {
|
||||
globalThis.window.navigator = globalThis.navigator;
|
||||
}
|
||||
|
||||
if (typeof globalThis.localStorage === "undefined") {
|
||||
const store = new Map();
|
||||
globalThis.localStorage = {
|
||||
|
||||
Reference in new issue
Block a user