105 lines
3.3 KiB
TypeScript
105 lines
3.3 KiB
TypeScript
import {
|
|
createUser,
|
|
db,
|
|
insertComment,
|
|
insertDump,
|
|
insertPlaylist,
|
|
test,
|
|
} from "../helpers.ts";
|
|
import { assertEquals } from "@std/assert";
|
|
import {
|
|
communityStatsOf,
|
|
getCommunityStats,
|
|
refreshCommunityStats,
|
|
} from "../../services/community-service.ts";
|
|
|
|
const DAY = 86_400_000;
|
|
const ago = (ms: number) => new Date(Date.now() - ms).toISOString();
|
|
const week = () =>
|
|
[new Date(Date.now() - 7 * DAY), new Date(Date.now() + 60_000)] as const;
|
|
|
|
function vote(dumpId: string, n: number) {
|
|
db.prepare(`UPDATE dumps SET vote_count = ? WHERE id = ?;`).run(n, dumpId);
|
|
}
|
|
|
|
test("communityStatsOf: the period's top public dumps, members, public playlists and totals", async () => {
|
|
const ann = await createUser({ createdAt: ago(20 * DAY) });
|
|
const bob = await createUser({ invitedBy: ann.id, createdAt: ago(2 * DAY) });
|
|
const cy = await createUser({ createdAt: ago(DAY) });
|
|
const hit = insertDump({ userId: bob.id, title: "Hit" });
|
|
vote(hit.id, 5);
|
|
const tie = insertDump({ userId: ann.id, title: "Tie", createdAt: ago(DAY) });
|
|
vote(tie.id, 2);
|
|
const newer = insertDump({ userId: ann.id, title: "Newer" });
|
|
vote(newer.id, 2);
|
|
insertDump({ userId: ann.id, title: "No votes" });
|
|
vote(insertDump({ userId: ann.id, title: "Private", isPrivate: true }).id, 9);
|
|
vote(
|
|
insertDump({ userId: ann.id, title: "Too old", createdAt: ago(10 * DAY) })
|
|
.id,
|
|
9,
|
|
);
|
|
insertComment({ dumpId: hit.id, userId: cy.id, body: "nice" });
|
|
insertPlaylist({ userId: ann.id, title: "Small" });
|
|
const full = insertPlaylist({ userId: bob.id, title: "Full" });
|
|
insertPlaylist({ userId: bob.id, title: "Hidden", isPublic: false });
|
|
// Bob's private dump isn't counted: every reader gets the same figures.
|
|
const secret = insertDump({
|
|
userId: bob.id,
|
|
title: "Secret",
|
|
isPrivate: true,
|
|
});
|
|
db.prepare(
|
|
`INSERT INTO playlist_dumps (playlist_id, dump_id, position, added_at) VALUES (?, ?, 0, ?), (?, ?, 1, ?), (?, ?, 2, ?);`,
|
|
).run(
|
|
full.id,
|
|
hit.id,
|
|
ago(0),
|
|
full.id,
|
|
tie.id,
|
|
ago(0),
|
|
full.id,
|
|
secret.id,
|
|
ago(0),
|
|
);
|
|
|
|
const stats = communityStatsOf(...week());
|
|
assertEquals(stats.top.map((d) => d.title), ["Hit", "Newer", "Tie"]);
|
|
assertEquals(stats.top[0].ownerUsername, bob.username);
|
|
assertEquals(
|
|
stats.members.map((m) => [m.username, m.invitedByUsername]),
|
|
[[bob.username, ann.username], [cy.username, undefined]],
|
|
);
|
|
assertEquals(
|
|
stats.playlists.map((p) => [p.title, p.dumpCount]),
|
|
[["Full", 2], ["Small", 0]],
|
|
);
|
|
assertEquals(stats.totals, { dumps: 4, upvotes: 0, comments: 1 });
|
|
assertEquals(stats.chatMessages, 0);
|
|
});
|
|
|
|
test("getCommunityStats: serves the last refresh, of the week or the month", async () => {
|
|
const ann = await createUser({ createdAt: ago(20 * DAY) });
|
|
vote(
|
|
insertDump({ userId: ann.id, title: "Month", createdAt: ago(20 * DAY) })
|
|
.id,
|
|
1,
|
|
);
|
|
refreshCommunityStats();
|
|
assertEquals(getCommunityStats("weekly").top, []);
|
|
assertEquals(getCommunityStats("monthly").top.map((d) => d.title), [
|
|
"Month",
|
|
]);
|
|
assertEquals(getCommunityStats("monthly").members.length, 1);
|
|
|
|
vote(
|
|
insertDump({ userId: ann.id, title: "Later", createdAt: ago(1000) }).id,
|
|
1,
|
|
);
|
|
assertEquals(getCommunityStats("weekly").top, []);
|
|
refreshCommunityStats();
|
|
assertEquals(getCommunityStats("weekly").top.map((d) => d.title), [
|
|
"Later",
|
|
]);
|
|
});
|