import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { REGULAR_USER_TEST_ID } from "~/db/seed/constants"; import { db } from "~/db/sql"; import { assertResponseErrored, dbInsertUsers, dbReset, wrappedAction, } from "~/utils/Test"; import { action as _teamPageAction } from "../actions/t.$customUrl.index.server"; import { action as teamIndexPageAction } from "../actions/t.server"; import { action as _editTeamAction } from "../routes/t.$customUrl.edit"; import * as TeamRepository from "../TeamRepository.server"; import type { createTeamSchema } from "../team-schemas"; import type { editTeamSchema, teamProfilePageActionSchema, } from "../team-schemas.server"; const createTeamAction = wrappedAction({ action: teamIndexPageAction, isJsonSubmission: true, }); const teamPageAction = wrappedAction({ action: _teamPageAction, isJsonSubmission: true, }); const editTeamAction = wrappedAction({ action: _editTeamAction, isJsonSubmission: true, }); async function loadTeams() { const teams = await TeamRepository.teamsByMemberUserId(REGULAR_USER_TEST_ID); const mainTeam = teams.find((t) => t.isMainTeam); const secondaryTeams = teams.filter((t) => !t.isMainTeam); return { team: mainTeam, secondaryTeams }; } describe("Secondary teams", () => { beforeEach(async () => { await dbInsertUsers(); }); afterEach(() => { dbReset(); }); it("first team created becomes main team", async () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); const { team, secondaryTeams } = await loadTeams(); expect(team!.name).toBe("Team 1"); expect(secondaryTeams).toHaveLength(0); }); it("second team created becomes secondary", async () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); await createTeamAction({ name: "Team 2" }, { user: "regular" }); const { team, secondaryTeams } = await loadTeams(); expect(team!.name).toBe("Team 1"); expect(secondaryTeams[0].name).toBe("Team 2"); }); it("makes secondary team main team", async () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); await createTeamAction({ name: "Team 2" }, { user: "regular" }); const { team, secondaryTeams } = await loadTeams(); expect(team!.name).toBe("Team 1"); expect(secondaryTeams[0].name).toBe("Team 2"); }); it("sets main team (2 team)", async () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); await createTeamAction({ name: "Team 2" }, { user: "regular" }); await teamPageAction( { _action: "MAKE_MAIN_TEAM" }, { user: "regular", params: { customUrl: "team-2" } }, ); const { team } = await loadTeams(); expect(team!.name).toBe("Team 2"); }); it("when deleting the main team, the secondary team becomes main", async () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); await createTeamAction({ name: "Team 2" }, { user: "regular" }); await editTeamAction( { _action: "DELETE_TEAM", }, { user: "regular", params: { customUrl: "team-1" }, }, ); const { team, secondaryTeams } = await loadTeams(); expect(team!.name).toBe("Team 2"); expect(secondaryTeams).toHaveLength(0); }); it("when leaving the main team, the secondary team becomes main", async () => { // has to be made by "admin" because can't leave team you own await createTeamAction({ name: "Team 1" }, { user: "admin" }); await createTeamAction({ name: "Team 2" }, { user: "admin" }); await TeamRepository.addNewTeamMember({ userId: REGULAR_USER_TEST_ID, teamId: 1, maxTeamsAllowed: 2, }); await TeamRepository.addNewTeamMember({ userId: REGULAR_USER_TEST_ID, teamId: 2, maxTeamsAllowed: 2, }); const { team, secondaryTeams } = await loadTeams(); expect(team!.name).toBe("Team 1"); expect(secondaryTeams[0].name).toBe("Team 2"); await teamPageAction( { _action: "LEAVE_TEAM", }, { user: "regular", params: { customUrl: "team-1" }, }, ); const { team: newTeam, secondaryTeams: newSecondaryTeams } = await loadTeams(); expect(newTeam!.name).toBe("Team 2"); expect(newSecondaryTeams).toHaveLength(0); }); it("creates max 2 teams as non-patron", async () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); await createTeamAction({ name: "Team 2" }, { user: "regular" }); const response = await createTeamAction( { name: "Team 3" }, { user: "regular" }, ); assertResponseErrored(response); }); const makeUserPatron = () => db .updateTable("User") .set({ patronTier: 2 }) .where("id", "=", REGULAR_USER_TEST_ID) .execute(); it("creates more than 2 teams as patron", async () => { await makeUserPatron(); await createTeamAction({ name: "Team 1" }, { user: "regular" }); await createTeamAction({ name: "Team 2" }, { user: "regular" }); await createTeamAction({ name: "Team 3" }, { user: "regular" }); const { secondaryTeams } = await loadTeams(); expect(secondaryTeams).toHaveLength(2); }); const createTeamWithImage = async (imageType: "avatar" | "banner") => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); const imageId = await db .insertInto("UnvalidatedUserSubmittedImage") .values({ url: `https://example.com/test-${imageType}.jpg`, submitterUserId: REGULAR_USER_TEST_ID, }) .returning("id") .executeTakeFirstOrThrow(); const imageField = imageType === "avatar" ? "avatarImgId" : "bannerImgId"; await db .updateTable("AllTeam") .set({ [imageField]: imageId.id }) .where("customUrl", "=", "team-1") .execute(); return imageId.id; }; it("deletes team avatar", async () => { const imageId = await createTeamWithImage("avatar"); await editTeamAction( { _action: "DELETE_AVATAR" }, { user: "regular", params: { customUrl: "team-1" } }, ); const team = await db .selectFrom("Team") .select("avatarImgId") .where("customUrl", "=", "team-1") .executeTakeFirst(); expect(team?.avatarImgId).toBeNull(); const image = await db .selectFrom("UnvalidatedUserSubmittedImage") .select("id") .where("id", "=", imageId) .executeTakeFirst(); expect(image).toBeUndefined(); }); it("deletes team banner", async () => { const imageId = await createTeamWithImage("banner"); await editTeamAction( { _action: "DELETE_BANNER" }, { user: "regular", params: { customUrl: "team-1" } }, ); const team = await db .selectFrom("Team") .select("bannerImgId") .where("customUrl", "=", "team-1") .executeTakeFirst(); expect(team?.bannerImgId).toBeNull(); const image = await db .selectFrom("UnvalidatedUserSubmittedImage") .select("id") .where("id", "=", imageId) .executeTakeFirst(); expect(image).toBeUndefined(); }); it("only team owner can delete images", async () => { await createTeamWithImage("avatar"); await db .insertInto("User") .values({ discordName: "otheruser", discordId: "999", }) .execute(); const response = await editTeamAction( { _action: "DELETE_AVATAR" }, { user: "regular", params: { customUrl: "team-1" } }, ); expect(response.status).toBe(302); }); });