mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
461 lines
10 KiB
TypeScript
461 lines
10 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
import type { MainWeaponId, StageId } from "~/modules/in-game-lists/types";
|
|
import { dbInsertUsers, dbReset } from "~/utils/Test";
|
|
import * as VodRepository from "./VodRepository.server";
|
|
|
|
let vodCounter = 0;
|
|
|
|
const createVod = async ({
|
|
submitterUserId,
|
|
type = "TOURNAMENT",
|
|
povUserId,
|
|
povName,
|
|
weaponSplIds = [0, 10],
|
|
mode = "TW",
|
|
stageId = 0,
|
|
isValidated = true,
|
|
}: {
|
|
submitterUserId: number;
|
|
type?: "TOURNAMENT" | "CAST" | "SCRIM";
|
|
povUserId?: number;
|
|
povName?: string;
|
|
weaponSplIds?: MainWeaponId[];
|
|
mode?: "TW" | "SZ" | "TC" | "RM" | "CB";
|
|
stageId?: StageId;
|
|
isValidated?: boolean;
|
|
}) => {
|
|
vodCounter++;
|
|
|
|
const result = await VodRepository.insert({
|
|
title: `Test VOD ${vodCounter}`,
|
|
youtubeUrl: `https://www.youtube.com/watch?v=test${vodCounter}`,
|
|
date: {
|
|
day: 1,
|
|
month: 0,
|
|
year: 2024,
|
|
},
|
|
matches: [
|
|
{
|
|
mode,
|
|
stageId: stageId,
|
|
startsAt: "0:00",
|
|
weapons: weaponSplIds,
|
|
},
|
|
],
|
|
type,
|
|
pov: povUserId
|
|
? { type: "USER", userId: povUserId }
|
|
: povName
|
|
? { type: "NAME", name: povName }
|
|
: undefined,
|
|
submitterUserId,
|
|
isValidated,
|
|
});
|
|
|
|
return result.id;
|
|
};
|
|
|
|
describe("findByUserId", () => {
|
|
beforeEach(async () => {
|
|
vodCounter = 0;
|
|
await dbInsertUsers(5);
|
|
});
|
|
|
|
afterEach(() => {
|
|
dbReset();
|
|
});
|
|
|
|
test("returns vods for a specific user", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
await createVod({ submitterUserId: 1, povUserId: 2 });
|
|
await createVod({ submitterUserId: 1, povUserId: 3 });
|
|
|
|
const result = await VodRepository.findByUserId(2);
|
|
|
|
expect(result).toHaveLength(1);
|
|
});
|
|
|
|
test("returns empty array when user has no vods", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
|
|
const result = await VodRepository.findByUserId(2);
|
|
|
|
expect(result).toHaveLength(0);
|
|
});
|
|
|
|
test("respects the limit parameter", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
|
|
const result = await VodRepository.findByUserId(1, 2);
|
|
|
|
expect(result).toHaveLength(2);
|
|
});
|
|
});
|
|
|
|
describe("findVods", () => {
|
|
beforeEach(async () => {
|
|
vodCounter = 0;
|
|
await dbInsertUsers(5);
|
|
});
|
|
|
|
afterEach(() => {
|
|
dbReset();
|
|
});
|
|
|
|
test("filters by weapon", async () => {
|
|
const vodId = await createVod({
|
|
submitterUserId: 1,
|
|
povUserId: 1,
|
|
weaponSplIds: [1000],
|
|
});
|
|
await createVod({
|
|
submitterUserId: 1,
|
|
povUserId: 1,
|
|
weaponSplIds: [2000],
|
|
});
|
|
|
|
const result = await VodRepository.findVods({ weapon: 1000 });
|
|
|
|
expect(result.length).toBeGreaterThan(0);
|
|
expect(result.some((vod) => vod.id === vodId)).toBe(true);
|
|
});
|
|
|
|
test("filters by mode", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1, mode: "TW" });
|
|
await createVod({ submitterUserId: 1, povUserId: 1, mode: "SZ" });
|
|
await createVod({ submitterUserId: 1, povUserId: 1, mode: "TC" });
|
|
|
|
const result = await VodRepository.findVods({ mode: "SZ" });
|
|
|
|
expect(result).toHaveLength(1);
|
|
});
|
|
|
|
test("filters by stageId", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1, stageId: 0 });
|
|
await createVod({ submitterUserId: 1, povUserId: 1, stageId: 1 });
|
|
await createVod({ submitterUserId: 1, povUserId: 1, stageId: 2 });
|
|
|
|
const result = await VodRepository.findVods({ stageId: 1 });
|
|
|
|
expect(result).toHaveLength(1);
|
|
});
|
|
|
|
test("filters by type", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1, type: "TOURNAMENT" });
|
|
await createVod({ submitterUserId: 1, povUserId: 1, type: "CAST" });
|
|
await createVod({ submitterUserId: 1, povUserId: 1, type: "SCRIM" });
|
|
|
|
const result = await VodRepository.findVods({ type: "CAST" });
|
|
|
|
expect(result).toHaveLength(1);
|
|
});
|
|
|
|
test("returns all vods when no filters provided", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
await createVod({ submitterUserId: 1, povUserId: 2 });
|
|
await createVod({ submitterUserId: 1, povUserId: 3 });
|
|
|
|
const result = await VodRepository.findVods({});
|
|
|
|
expect(result).toHaveLength(3);
|
|
});
|
|
|
|
test("respects limit parameter", async () => {
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
|
|
const result = await VodRepository.findVods({ limit: 2 });
|
|
|
|
expect(result).toHaveLength(2);
|
|
});
|
|
});
|
|
|
|
describe("findVodById", () => {
|
|
beforeEach(async () => {
|
|
vodCounter = 0;
|
|
await dbInsertUsers(5);
|
|
});
|
|
|
|
afterEach(() => {
|
|
dbReset();
|
|
});
|
|
|
|
test("returns null when vod doesn't exist", async () => {
|
|
const result = await VodRepository.findVodById(999);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
test("correctly resolves pov from user", async () => {
|
|
const vodId = await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
|
|
const result = await VodRepository.findVodById(vodId);
|
|
|
|
expect(result).not.toBeNull();
|
|
expect(result?.pov).toBeDefined();
|
|
expect(typeof result?.pov).not.toBe("string");
|
|
});
|
|
|
|
test("correctly resolves pov from player name", async () => {
|
|
const vodId = await createVod({
|
|
submitterUserId: 1,
|
|
povName: "PlayerName",
|
|
});
|
|
|
|
const result = await VodRepository.findVodById(vodId);
|
|
|
|
expect(result).not.toBeNull();
|
|
expect(result?.pov).toBe("PlayerName");
|
|
});
|
|
});
|
|
|
|
describe("insert", () => {
|
|
beforeEach(async () => {
|
|
vodCounter = 0;
|
|
await dbInsertUsers(5);
|
|
});
|
|
|
|
afterEach(() => {
|
|
dbReset();
|
|
});
|
|
|
|
test("inserts vod with all metadata", async () => {
|
|
const result = await VodRepository.insert({
|
|
title: "Complete VOD",
|
|
youtubeUrl: "https://www.youtube.com/watch?v=abc123",
|
|
date: {
|
|
day: 15,
|
|
month: 5,
|
|
year: 2024,
|
|
},
|
|
matches: [
|
|
{
|
|
mode: "TW",
|
|
stageId: 0 as any,
|
|
startsAt: "0:00",
|
|
weapons: [0, 10, 20] as any,
|
|
},
|
|
],
|
|
type: "TOURNAMENT",
|
|
pov: { type: "USER", userId: 1 },
|
|
submitterUserId: 1,
|
|
isValidated: true,
|
|
});
|
|
|
|
const vod = await VodRepository.findVodById(result.id);
|
|
|
|
expect(vod).not.toBeNull();
|
|
expect(vod?.title).toBe("Complete VOD");
|
|
expect(vod?.youtubeId).toBe("abc123");
|
|
expect(vod?.type).toBe("TOURNAMENT");
|
|
expect(vod?.matches).toHaveLength(1);
|
|
expect(vod?.matches[0].weapons).toHaveLength(3);
|
|
});
|
|
|
|
test("extracts YouTube ID from URL correctly", async () => {
|
|
const vodId = await createVod({
|
|
submitterUserId: 1,
|
|
povUserId: 1,
|
|
});
|
|
|
|
const result = await VodRepository.findVodById(vodId);
|
|
|
|
expect(result?.youtubeId).toBe("test1");
|
|
});
|
|
|
|
test("handles NAME type pov", async () => {
|
|
const result = await VodRepository.insert({
|
|
title: "Test VOD",
|
|
youtubeUrl: "https://www.youtube.com/watch?v=test123",
|
|
date: {
|
|
day: 1,
|
|
month: 0,
|
|
year: 2024,
|
|
},
|
|
matches: [
|
|
{
|
|
mode: "TW",
|
|
stageId: 0 as any,
|
|
startsAt: "0:00",
|
|
weapons: [0] as any,
|
|
},
|
|
],
|
|
type: "TOURNAMENT",
|
|
pov: { type: "NAME", name: "TestPlayer" },
|
|
submitterUserId: 1,
|
|
isValidated: true,
|
|
});
|
|
|
|
const vod = await VodRepository.findVodById(result.id);
|
|
|
|
expect(vod?.pov).toBe("TestPlayer");
|
|
});
|
|
|
|
test("handles USER type pov", async () => {
|
|
const result = await VodRepository.insert({
|
|
title: "Test VOD",
|
|
youtubeUrl: "https://www.youtube.com/watch?v=test123",
|
|
date: {
|
|
day: 1,
|
|
month: 0,
|
|
year: 2024,
|
|
},
|
|
matches: [
|
|
{
|
|
mode: "TW",
|
|
stageId: 0 as any,
|
|
startsAt: "0:00",
|
|
weapons: [0] as any,
|
|
},
|
|
],
|
|
type: "TOURNAMENT",
|
|
pov: { type: "USER", userId: 1 },
|
|
submitterUserId: 1,
|
|
isValidated: true,
|
|
});
|
|
|
|
const vod = await VodRepository.findVodById(result.id);
|
|
|
|
expect(vod?.pov).toBeDefined();
|
|
expect(typeof vod?.pov).not.toBe("string");
|
|
});
|
|
});
|
|
|
|
describe("update", () => {
|
|
beforeEach(async () => {
|
|
vodCounter = 0;
|
|
await dbInsertUsers(5);
|
|
});
|
|
|
|
afterEach(() => {
|
|
dbReset();
|
|
});
|
|
|
|
test("updates vod metadata", async () => {
|
|
const vodId = await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
|
|
await VodRepository.update({
|
|
id: vodId,
|
|
title: "Updated Title",
|
|
youtubeUrl: "https://www.youtube.com/watch?v=updated123",
|
|
date: {
|
|
day: 1,
|
|
month: 0,
|
|
year: 2024,
|
|
},
|
|
matches: [
|
|
{
|
|
mode: "SZ",
|
|
stageId: 5 as any,
|
|
startsAt: "0:00",
|
|
weapons: [50] as any,
|
|
},
|
|
],
|
|
type: "CAST",
|
|
pov: { type: "USER", userId: 2 },
|
|
submitterUserId: 1,
|
|
isValidated: true,
|
|
});
|
|
|
|
const result = await VodRepository.findVodById(vodId);
|
|
|
|
expect(result?.title).toBe("Updated Title");
|
|
expect(result?.youtubeId).toBe("updated123");
|
|
expect(result?.type).toBe("CAST");
|
|
});
|
|
|
|
test("deletes and recreates matches", async () => {
|
|
const result = await VodRepository.insert({
|
|
title: "Test VOD",
|
|
youtubeUrl: "https://www.youtube.com/watch?v=test123",
|
|
date: {
|
|
day: 1,
|
|
month: 0,
|
|
year: 2024,
|
|
},
|
|
matches: [
|
|
{
|
|
mode: "TW",
|
|
stageId: 0 as any,
|
|
startsAt: "0:00",
|
|
weapons: [0] as any,
|
|
},
|
|
{
|
|
mode: "SZ",
|
|
stageId: 1 as any,
|
|
startsAt: "5:00",
|
|
weapons: [10] as any,
|
|
},
|
|
],
|
|
type: "TOURNAMENT",
|
|
pov: { type: "USER", userId: 1 },
|
|
submitterUserId: 1,
|
|
isValidated: true,
|
|
});
|
|
|
|
await VodRepository.update({
|
|
id: result.id,
|
|
title: "Test VOD",
|
|
youtubeUrl: "https://www.youtube.com/watch?v=test123",
|
|
date: {
|
|
day: 1,
|
|
month: 0,
|
|
year: 2024,
|
|
},
|
|
matches: [
|
|
{
|
|
mode: "TC",
|
|
stageId: 2 as any,
|
|
startsAt: "0:00",
|
|
weapons: [20] as any,
|
|
},
|
|
],
|
|
type: "TOURNAMENT",
|
|
pov: { type: "USER", userId: 1 },
|
|
submitterUserId: 1,
|
|
isValidated: true,
|
|
});
|
|
|
|
const vod = await VodRepository.findVodById(result.id);
|
|
|
|
expect(vod?.matches).toHaveLength(1);
|
|
expect(vod?.matches[0].mode).toBe("TC");
|
|
});
|
|
});
|
|
|
|
describe("deleteById", () => {
|
|
beforeEach(async () => {
|
|
vodCounter = 0;
|
|
await dbInsertUsers(5);
|
|
});
|
|
|
|
afterEach(() => {
|
|
dbReset();
|
|
});
|
|
|
|
test("deletes vod by id", async () => {
|
|
const vodId = await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
|
|
await VodRepository.deleteById(vodId);
|
|
|
|
const result = await VodRepository.findVodById(vodId);
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
test("only deletes the specified vod", async () => {
|
|
const firstVodId = await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
const secondVodId = await createVod({ submitterUserId: 1, povUserId: 1 });
|
|
|
|
await VodRepository.deleteById(firstVodId);
|
|
|
|
const firstResult = await VodRepository.findVodById(firstVodId);
|
|
const secondResult = await VodRepository.findVodById(secondVodId);
|
|
|
|
expect(firstResult).toBeNull();
|
|
expect(secondResult).not.toBeNull();
|
|
});
|
|
});
|