sendou.ink/e2e/org.spec.ts
2026-07-29 15:08:01 +03:00

209 lines
7.1 KiB
TypeScript

import { addHours } from "date-fns";
import { NZAP_TEST_ID } from "~/db/seed/constants";
import { ADMIN_ID } from "~/features/admin/admin-constants";
import { dateToDatabaseTimestamp } from "~/utils/dates";
import {
expect,
impersonate,
isNotVisible,
navigate,
test,
waitForPOSTResponse,
} from "./helpers/playwright";
import { CalendarNewEventPage } from "./pages/calendar/calendar-new-event-page";
import { AnythingAdder } from "./pages/layout/anything-adder";
import { NewOrganizationPage } from "./pages/org/new-organization-page";
import { OrganizationPage } from "./pages/org/organization-page";
import { TournamentPage } from "./pages/tournament/tournament-page";
const ORGANIZATION_NAME = "Sendou.ink";
const TOURNAMENT_NAME = "PICNIC #2";
const PLAYER_NAME = "Banned Bob";
test.describe("Tournament Organization", () => {
test("can create a new organization", async ({ page, factories }) => {
const organizer = await factories.UserFactory.create(null, {
roles: ["TOURNAMENT_ORGANIZER"],
});
await impersonate(page, organizer.id);
await navigate({ page, url: "/" });
await new AnythingAdder(page).add("organization");
const newOrganization = new NewOrganizationPage(page);
await newOrganization.form.fill("name", "Test Organization");
await newOrganization.save();
const organization = new OrganizationPage(page);
await expect(organization.locators.editButton).toBeVisible();
});
test("user can be promoted to admin gaining org controls and can edit tournaments", async ({
page,
factories,
}) => {
const org = await factories.TournamentOrganizationFactory.create(
{ ownerId: ADMIN_ID, name: ORGANIZATION_NAME },
{ members: [{ userId: NZAP_TEST_ID, role: "MEMBER" }] },
);
const tournament = await factories.TournamentFactory.create({
authorId: ADMIN_ID,
name: TOURNAMENT_NAME,
organizationId: org.id,
startTimes: [dateToDatabaseTimestamp(addHours(new Date(), 2))],
});
const organization = new OrganizationPage(page);
// 1. As a regular user, verify edit controls are not visible
await impersonate(page, NZAP_TEST_ID);
await organization.goto(org.slug);
await isNotVisible(organization.locators.editButton);
// 2. As admin, promote user to admin
await impersonate(page, ADMIN_ID);
await organization.goto(org.slug);
const organizationEdit = await organization.openEdit();
await organizationEdit.setMemberRole("N-ZAP", "ADMIN");
await organizationEdit.save();
// Establish the organization so its admins can edit tournament event info
await organization.goto(org.slug);
await organization.establish();
// 3. As the promoted user, verify edit controls are visible and page can be accessed
await impersonate(page, NZAP_TEST_ID);
await organization.goto(org.slug);
await organization.openEdit();
await expect(organizationEdit.locators.title).toBeVisible();
// 4. As the promoted user, verify they can edit tournaments
const tournamentPage = new TournamentPage(page);
await tournamentPage.goto(tournament.id);
const tournamentAdmin = await tournamentPage.nav.openAdmin();
const calendarEvent = await tournamentAdmin.editEventInfo();
await expect(calendarEvent.locators.nameInput).toHaveValue(TOURNAMENT_NAME);
});
test("banned player cannot join a tournament of that organization", async ({
page,
factories,
}) => {
const player = await factories.UserFactory.create({
discordName: PLAYER_NAME,
});
const org = await factories.TournamentOrganizationFactory.create({
ownerId: ADMIN_ID,
name: ORGANIZATION_NAME,
});
const tournament = await factories.TournamentFactory.create({
authorId: ADMIN_ID,
name: TOURNAMENT_NAME,
organizationId: org.id,
startTimes: [dateToDatabaseTimestamp(addHours(new Date(), 2))],
});
const organization = new OrganizationPage(page);
const tournamentPage = new TournamentPage(page);
// 1. As admin, ban the player from the organization
await impersonate(page, ADMIN_ID);
await organization.goto(org.slug);
await organization.openBannedUsers();
const banModal = await organization.openBanModal();
await expect(banModal.locators.dialog).toBeVisible();
await banModal.selectUser(PLAYER_NAME);
await banModal.form.fill("privateNote", "Test reason");
// a future expiration date to avoid validation issues
await banModal.form.setDateTime("expiresAt", addHours(new Date(), 24));
await banModal.save();
await expect(organization.locators.bannedUsersTable).toContainText(
"Test reason",
);
// 2. As the banned user, try to join a tournament
await impersonate(page, player.id);
await tournamentPage.goto(tournament.id);
const register = await tournamentPage.register();
await register.form.fill("pickUpName", "Banned Team");
await waitForPOSTResponse(page, () => register.form.submit());
// "Fill roster" only appears after a successful registration
await expect(register.locators.fillRosterHeading).not.toBeVisible();
// 3. As admin, remove the ban
await impersonate(page, ADMIN_ID);
await organization.goto(org.slug);
await organization.openBannedUsers();
await organization.unban();
// 4. As the unbanned user, verify they can now join a tournament
await impersonate(page, player.id);
await tournamentPage.goto(tournament.id);
const registerAgain = await tournamentPage.register();
const teamsTab = tournamentPage.nav.locators.teamsTab;
await expect(teamsTab).toContainText("Teams (0)");
await registerAgain.form.fill("pickUpName", "Unbanned Team");
await registerAgain.form.submit();
await expect(teamsTab).toContainText("Teams (1)");
// 5. As admin, ban user again but with permanent ban this time
await impersonate(page, ADMIN_ID);
await organization.goto(org.slug);
await organization.openBannedUsers();
const permanentBanModal = await organization.openBanModal();
await expect(permanentBanModal.locators.dialog).toBeVisible();
await permanentBanModal.selectUser(PLAYER_NAME);
await permanentBanModal.form.fill("privateNote", "Does not expire");
// expiresAt left empty makes the ban permanent
await permanentBanModal.save();
await expect(organization.locators.bannedUsersTable).toContainText(
"Permanent",
);
});
test("allows member of established org to create tournament", async ({
page,
factories,
}) => {
const orgAdmin = await factories.UserFactory.create();
const org = await factories.TournamentOrganizationFactory.create(
{ ownerId: ADMIN_ID, name: ORGANIZATION_NAME },
{ members: [{ userId: orgAdmin.id, role: "ADMIN" }] },
);
const newTournament = new CalendarNewEventPage(page);
await impersonate(page, orgAdmin.id);
await newTournament.gotoNewTournament();
await expect(
newTournament.locators.noTournamentPermissionsAlert,
).toBeVisible();
await expect(newTournament.locators.newTournamentHeading).not.toBeVisible();
await impersonate(page, ADMIN_ID);
const organization = new OrganizationPage(page);
await organization.goto(org.slug);
await organization.establish();
await impersonate(page, orgAdmin.id);
await newTournament.gotoNewTournament();
await expect(
newTournament.locators.noTournamentPermissionsAlert,
).not.toBeVisible();
await expect(newTournament.locators.newTournamentHeading).toBeVisible();
});
});