mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-25 04:37:13 -05:00
117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
import { addWeeks, subWeeks } from "date-fns";
|
|
import { beforeEach, describe, expect, test } from "vitest";
|
|
import * as AvailabilityWeekFactory from "~/db/seed/factories/AvailabilityWeekFactory";
|
|
import * as UserFactory from "~/db/seed/factories/UserFactory";
|
|
import { databaseTimestampToDate } from "~/utils/dates";
|
|
import { AVAILABILITY } from "../availability-constants";
|
|
import * as Availability from "./Availability";
|
|
import * as RegistrationAvailability from "./RegistrationAvailability.server";
|
|
|
|
const users = UserFactory.pool();
|
|
const playerId = () => users.id(1);
|
|
const viewerId = () => users.id(2);
|
|
|
|
const TIMEZONE = "UTC";
|
|
const HOUR = 60 * 60;
|
|
const DAY = 24 * HOUR;
|
|
|
|
const weekStartsAtIn = (weeksFromNow: number) =>
|
|
Availability.weekStartsAt(addWeeks(new Date(), weeksFromNow), TIMEZONE);
|
|
|
|
const tournamentStartingAt = (startsAt: number) => ({
|
|
id: 1,
|
|
name: "In The Zone",
|
|
organizationId: null,
|
|
startsAt,
|
|
minMembersPerTeam: 4,
|
|
bracketTypes: ["single_elimination" as const],
|
|
teamCount: 8,
|
|
});
|
|
|
|
const availabilityFor = (startsAt: number) =>
|
|
RegistrationAvailability.registrationAvailability({
|
|
tournament: tournamentStartingAt(startsAt),
|
|
userIds: [playerId()],
|
|
timezone: TIMEZONE,
|
|
viewerId: viewerId(),
|
|
});
|
|
|
|
describe("RegistrationAvailability.registrationAvailability", () => {
|
|
beforeEach(async () => {
|
|
await users.create(2);
|
|
});
|
|
|
|
test("computes nothing for a tournament past the reportable horizon", async () => {
|
|
const startsAt = weekStartsAtIn(AVAILABILITY.WEEK_HORIZON) + 18 * HOUR;
|
|
|
|
const result = await availabilityFor(startsAt);
|
|
|
|
expect(result.window).toBeNull();
|
|
expect(result.entries).toBeNull();
|
|
expect(result.beyondHorizon?.opensAt).toBe(
|
|
Availability.weekStartsAt(
|
|
subWeeks(databaseTimestampToDate(startsAt), 1),
|
|
TIMEZONE,
|
|
),
|
|
);
|
|
});
|
|
|
|
test("computes availability for a tournament on the last day still within the horizon", async () => {
|
|
const startsAt = weekStartsAtIn(AVAILABILITY.WEEK_HORIZON) - HOUR;
|
|
|
|
const result = await availabilityFor(startsAt);
|
|
|
|
expect(result.beyondHorizon).toBeNull();
|
|
expect(result.window?.startsAt).toBe(startsAt);
|
|
expect(result.entries).toHaveLength(1);
|
|
});
|
|
|
|
test("reads as unknown for a player not sharing their schedule", async () => {
|
|
const weekStartsAt = weekStartsAtIn(1);
|
|
const startsAt = weekStartsAt + 2 * DAY + 18 * HOUR;
|
|
await AvailabilityWeekFactory.create({
|
|
userId: playerId(),
|
|
weekStartsAt,
|
|
timezone: TIMEZONE,
|
|
slots: [{ startsAt, endsAt: startsAt + 6 * HOUR }],
|
|
dayNotes: [
|
|
{
|
|
date: Availability.dateInTimezone(startsAt, TIMEZONE),
|
|
text: "Have to leave by 21",
|
|
},
|
|
],
|
|
});
|
|
await UserFactory.grant(playerId(), {
|
|
preferences: { scheduleVisibility: { friends: false, teamIds: [] } },
|
|
});
|
|
|
|
const result = await availabilityFor(startsAt);
|
|
|
|
expect(result.entries?.[0].availability.status).toBe("unknown");
|
|
expect(result.entries?.[0].notes).toEqual([]);
|
|
});
|
|
|
|
test("returns only the day notes falling inside the tournament's window", async () => {
|
|
const weekStartsAt = weekStartsAtIn(1);
|
|
const startsAt = weekStartsAt + 2 * DAY + 18 * HOUR;
|
|
const dateOfDay = (dayIndex: number) =>
|
|
Availability.dateInTimezone(
|
|
weekStartsAt + dayIndex * DAY + DAY / 2,
|
|
TIMEZONE,
|
|
);
|
|
await AvailabilityWeekFactory.create({
|
|
userId: playerId(),
|
|
weekStartsAt,
|
|
timezone: TIMEZONE,
|
|
dayNotes: [
|
|
{ date: dateOfDay(2), text: "Have to leave by 21" },
|
|
{ date: dateOfDay(5), text: "Away for the weekend" },
|
|
],
|
|
});
|
|
|
|
const result = await availabilityFor(startsAt);
|
|
|
|
expect(result.entries?.[0].notes).toEqual(["Have to leave by 21"]);
|
|
});
|
|
});
|