Skip to content

Sidebar · E2E tests

1 module · 7 exports · 0 repositories · 25 e2e tests · 0 routes

  • NN-ZAP
  • Users a test creates itself are coloured per test
  • Arrange data setup
  • Act what the user does
  • Assert what is expected

Renders//to/:id/to/:id/info

Setup
Arrange
  1. Create tournament author Sendou name “Saved Tournament” start times inHours(1) → saved
    const saved = await factories.TournamentFactory.create({
    	authorId: ADMIN_ID,
    	name: "Saved Tournament",
    	startTimes: [inHours(1)],
    });
  2. Create saved calendar event user N-ZAP tournament id saved.id
    await factories.SavedCalendarEventFactory.create({
    	userId: NZAP_TEST_ID,
    	tournamentId: saved.id,
    });
  3. Create tournament author Sendou name “Played Tournament” start times inHours(2) → played
    const played = await factories.TournamentFactory.create({
    	authorId: ADMIN_ID,
    	name: "Played Tournament",
    	startTimes: [inHours(2)],
    });
  4. Create tournament team tournament id played.id member user ids N-ZAP
    await factories.TournamentTeamFactory.create({
    	tournamentId: played.id,
    	memberUserIds: [NZAP_TEST_ID],
    });
  5. Create scrim post starts at inHours(3) users user N-ZAP is owner 1
    await factories.ScrimPostFactory.create({
    	startsAt: inHours(3),
    	users: [{ userId: NZAP_TEST_ID, isOwner: 1 }],
    });
  6. Create tournament author N-ZAP name “Organized Tournament” start times inHours(4)
    await factories.TournamentFactory.create({
    	authorId: NZAP_TEST_ID,
    	name: "Organized Tournament",
    	startTimes: [inHours(4)],
    });
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. list items count is 4
    await expect(sideNav.locators.listItems).toHaveCount(4);
  2. sideNav.eventItem("Saved Tournament"), sideNav.eventItem("Played Tournament"), sideNav.eventItem("Looking for scrim"), sideNav.eventItem("Organized Tournament") top to bottom
    await expectTopToBottom([
    	sideNav.eventItem("Saved Tournament"),
    	sideNav.eventItem("Played Tournament"),
    	sideNav.eventItem("Looking for scrim"),
    	sideNav.eventItem("Organized Tournament"),
    ]);
  3. item subtitle “Played Tournament” reads /\d{1,2}:\d{2}/
    await expect(sideNav.itemSubtitle("Played Tournament")).toHaveText(
    	/\d{1,2}:\d{2}/,
    );
Act
  1. Click event item “Played Tournament”
    await sideNav.eventItem("Played Tournament").click();
Assert
  1. the page URL is new RegExp(`/to/${played.id}`)
    await expect(page).toHaveURL(new RegExp(`/to/${played.id}`));
  2. no error page
    await expectNoErrorPage(page);
Source
test("shows my tournaments, my scrims and saved events, soonest first", async ({
	page,
	factories,
}) => {
	const saved = await factories.TournamentFactory.create({
		authorId: ADMIN_ID,
		name: "Saved Tournament",
		startTimes: [inHours(1)],
	});
	await factories.SavedCalendarEventFactory.create({
		userId: NZAP_TEST_ID,
		tournamentId: saved.id,
	});

	const played = await factories.TournamentFactory.create({
		authorId: ADMIN_ID,
		name: "Played Tournament",
		startTimes: [inHours(2)],
	});
	await factories.TournamentTeamFactory.create({
		tournamentId: played.id,
		memberUserIds: [NZAP_TEST_ID],
	});

	await factories.ScrimPostFactory.create({
		startsAt: inHours(3),
		users: [{ userId: NZAP_TEST_ID, isOwner: 1 }],
	});

	await factories.TournamentFactory.create({
		authorId: NZAP_TEST_ID,
		name: "Organized Tournament",
		startTimes: [inHours(4)],
	});

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.locators.listItems).toHaveCount(4);
	await expectTopToBottom([
		sideNav.eventItem("Saved Tournament"),
		sideNav.eventItem("Played Tournament"),
		sideNav.eventItem("Looking for scrim"),
		sideNav.eventItem("Organized Tournament"),
	]);
	await expect(sideNav.itemSubtitle("Played Tournament")).toHaveText(
		/\d{1,2}:\d{2}/,
	);

	await sideNav.eventItem("Played Tournament").click();

	await expect(page).toHaveURL(new RegExp(`/to/${played.id}`));
	await expectNoErrorPage(page);
})

Renders//scrims/scrims/:id

Setup
Arrange
  1. Create 2 × user → [opponentOwner, otherPostOwner]
    const [opponentOwner, otherPostOwner] =
    	await factories.UserFactory.createMany(2);
  2. Create team name “Squid Squad” member user ids opponentOwner.id → opponentTeam
    const opponentTeam = await factories.TeamFactory.create({
    	name: "Squid Squad",
    	memberUserIds: [opponentOwner.id],
    });
  3. Create scrim post starts at inHours(1) team id opponentTeam.id users user id opponentOwner.id is owner 1 requests users user N-ZAP is owner 1 is accepted true → booked
    const booked = await factories.ScrimPostFactory.create(
    	{
    		startsAt: inHours(1),
    		teamId: opponentTeam.id,
    		users: [{ userId: opponentOwner.id, isOwner: 1 }],
    	},
    	{
    		requests: [
    			{ users: [{ userId: NZAP_TEST_ID, isOwner: 1 }], isAccepted: true },
    		],
    	},
    );
  4. Create scrim post starts at inHours(2) users user N-ZAP is owner 1
    await factories.ScrimPostFactory.create({
    	startsAt: inHours(2),
    	users: [{ userId: NZAP_TEST_ID, isOwner: 1 }],
    });
  5. Create scrim post starts at inHours(3) users user id otherPostOwner.id is owner 1 requests users user N-ZAP is owner 1 → pending
    const pending = await factories.ScrimPostFactory.create(
    	{
    		startsAt: inHours(3),
    		users: [{ userId: otherPostOwner.id, isOwner: 1 }],
    	},
    	{ requests: [{ users: [{ userId: NZAP_TEST_ID, isOwner: 1 }] }] },
    );
NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. event item “vs. Squid Squad” is visible
    await expect(sideNav.eventItem("vs. Squid Squad")).toBeVisible();
  2. event item “Looking for scrim” is visible
    await expect(sideNav.eventItem("Looking for scrim")).toBeVisible();
  3. event item “Request pending” is visible
    await expect(sideNav.eventItem("Request pending")).toBeVisible();
Act
  1. Click event item “vs. Squid Squad”
    await sideNav.eventItem("vs. Squid Squad").click();
Assert
  1. the page URL is `/scrims/${booked.id}`
    await expect(page).toHaveURL(`/scrims/${booked.id}`);
  2. no error page
    await expectNoErrorPage(page);
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Click event item “Looking for scrim”
    await sideNav.eventItem("Looking for scrim").click();
Assert
  1. the page URL is “/scrims”
    await expect(page).toHaveURL("/scrims");
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. event item “Request pending” has “href” = `/scrims?pendingRequestPostId=${pending.id}`
    await expect(sideNav.eventItem("Request pending")).toHaveAttribute(
    	"href",
    	`/scrims?pendingRequestPostId=${pending.id}`,
    );
Act
  1. Click event item “Request pending”
    await sideNav.eventItem("Request pending").click();
Assert
  1. the scrims page clears the param once it has scrolled to the post

    the page URL is “/scrims”
    await expect(page).toHaveURL("/scrims");
  2. no error page
    await expectNoErrorPage(page);
Source
test("scrim rows show their status and link to the right place", async ({
	page,
	factories,
}) => {
	const [opponentOwner, otherPostOwner] =
		await factories.UserFactory.createMany(2);
	const opponentTeam = await factories.TeamFactory.create({
		name: "Squid Squad",
		memberUserIds: [opponentOwner.id],
	});

	const booked = await factories.ScrimPostFactory.create(
		{
			startsAt: inHours(1),
			teamId: opponentTeam.id,
			users: [{ userId: opponentOwner.id, isOwner: 1 }],
		},
		{
			requests: [
				{ users: [{ userId: NZAP_TEST_ID, isOwner: 1 }], isAccepted: true },
			],
		},
	);
	await factories.ScrimPostFactory.create({
		startsAt: inHours(2),
		users: [{ userId: NZAP_TEST_ID, isOwner: 1 }],
	});
	const pending = await factories.ScrimPostFactory.create(
		{
			startsAt: inHours(3),
			users: [{ userId: otherPostOwner.id, isOwner: 1 }],
		},
		{ requests: [{ users: [{ userId: NZAP_TEST_ID, isOwner: 1 }] }] },
	);

	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	await front.goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.eventItem("vs. Squid Squad")).toBeVisible();
	await expect(sideNav.eventItem("Looking for scrim")).toBeVisible();
	await expect(sideNav.eventItem("Request pending")).toBeVisible();

	await sideNav.eventItem("vs. Squid Squad").click();
	await expect(page).toHaveURL(`/scrims/${booked.id}`);
	await expectNoErrorPage(page);

	await front.goto();
	await sideNav.eventItem("Looking for scrim").click();
	await expect(page).toHaveURL("/scrims");

	await front.goto();
	await expect(sideNav.eventItem("Request pending")).toHaveAttribute(
		"href",
		`/scrims?pendingRequestPostId=${pending.id}`,
	);

	await sideNav.eventItem("Request pending").click();
	// the scrims page clears the param once it has scrolled to the post
	await expect(page).toHaveURL("/scrims");
	await expectNoErrorPage(page);
})

Renders//events

Setup
Arrange
  1. For each nth of 1, 2, 3, 4, 5, 6, 7
    for (const nth of [1, 2, 3, 4, 5, 6, 7]) {
    	const tournament = await factories.TournamentFactory.create({
    		authorId: ADMIN_ID,
    		name: `Tournament ${nth}`,
    		startTimes: [inHours(nth)],
    	});
    	await factories.TournamentTeamFactory.create({
    		tournamentId: tournament.id,
    		memberUserIds: [NZAP_TEST_ID],
    	});
    }
    1. Create tournament author Sendou name `Tournament ${nth}` start times inHours(nth) → tournament
      const tournament = await factories.TournamentFactory.create({
      	authorId: ADMIN_ID,
      	name: `Tournament ${nth}`,
      	startTimes: [inHours(nth)],
      });
    2. Create tournament team tournament id tournament.id member user ids N-ZAP
      await factories.TournamentTeamFactory.create({
      	tournamentId: tournament.id,
      	memberUserIds: [NZAP_TEST_ID],
      });
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. list items count is 5
    await expect(sideNav.locators.listItems).toHaveCount(5);
  2. event item “Tournament 5” is visible
    await expect(sideNav.eventItem("Tournament 5")).toBeVisible();
  3. event item “Tournament 6” count is 0
    await expect(sideNav.eventItem("Tournament 6")).toHaveCount(0);
Act
  1. Click view all link “Events”
    await sideNav.viewAllLink("Events").click();
Assert
  1. the page URL is EVENTS_PAGE
    await expect(page).toHaveURL(EVENTS_PAGE);
Events page
Assert
  1. event link “Tournament 6” is visible
    await expect(events.eventLink("Tournament 6")).toBeVisible();
  2. event link “Tournament 7” is visible
    await expect(events.eventLink("Tournament 7")).toBeVisible();
Source
test("caps at five events and View all opens the events page", async ({
	page,
	factories,
}) => {
	for (const nth of [1, 2, 3, 4, 5, 6, 7]) {
		const tournament = await factories.TournamentFactory.create({
			authorId: ADMIN_ID,
			name: `Tournament ${nth}`,
			startTimes: [inHours(nth)],
		});
		await factories.TournamentTeamFactory.create({
			tournamentId: tournament.id,
			memberUserIds: [NZAP_TEST_ID],
		});
	}

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.locators.listItems).toHaveCount(5);
	await expect(sideNav.eventItem("Tournament 5")).toBeVisible();
	await expect(sideNav.eventItem("Tournament 6")).toHaveCount(0);

	await sideNav.viewAllLink("Events").click();
	await expect(page).toHaveURL(EVENTS_PAGE);

	const events = new EventsPage(page);
	await expect(events.eventLink("Tournament 6")).toBeVisible();
	await expect(events.eventLink("Tournament 7")).toBeVisible();
})

Renders/

NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. empty text NO_EVENTS_TEXT is visible
    await expect(sideNav.emptyText(NO_EVENTS_TEXT)).toBeVisible();
  2. view all link “Events” is visible
    await expect(sideNav.viewAllLink("Events")).toBeVisible();
Source
test("shows an empty state without upcoming events", async ({ page }) => {
	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.emptyText(NO_EVENTS_TEXT)).toBeVisible();
	await expect(sideNav.viewAllLink("Events")).toBeVisible();
})

Renders/

Setup
Arrange
  1. Create named users “IdleFriend”, “QueueFriend”, “SubFriend”, “MatchFriend”, “GroupMate” → [idle, queueing, sub, inMatch, groupMate]
    const [idle, queueing, sub, inMatch, groupMate] = await createNamedUsers(
    	factories,
    	["IdleFriend", "QueueFriend", "SubFriend", "MatchFriend", "GroupMate"],
    );
  2. Befriend idle.id, queueing.id, sub.id, inMatch.id
    await befriend(factories, [idle.id, queueing.id, sub.id, inMatch.id]);
  3. Create SQ group member user ids queueing.id, groupMate.id
    await factories.SQGroupFactory.create({
    	memberUserIds: [queueing.id, groupMate.id],
    });
  4. Create sub seeking tournament name “Sub Tournament” sub id sub.id
    await createSubSeekingTournament(factories, {
    	name: "Sub Tournament",
    	subId: sub.id,
    });
  5. Create in progress match name “Match Tournament” friend id inMatch.id
    await createInProgressMatch(factories, {
    	name: "Match Tournament",
    	friendId: inMatch.id,
    });
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Act
  1. Friend “IdleFriend” → idleRow
    const idleRow = sideNav.friend("IdleFriend");
Friend row
Assert
  1. trigger is visible
    await expect(idleRow.trigger).toBeVisible();
  2. subtitle count is 0
    await expect(idleRow.locators.subtitle).toHaveCount(0);
  3. badge count is 0
    await expect(idleRow.locators.badge).toHaveCount(0);
Side nav
Act
  1. Friend “QueueFriend” → queueingRow
    const queueingRow = sideNav.friend("QueueFriend");
Friend row
Assert
  1. subtitle reads “SendouQ”
    await expect(queueingRow.locators.subtitle).toHaveText("SendouQ");
  2. badge reads “2/4”
    await expect(queueingRow.locators.badge).toHaveText("2/4");
Side nav
Act
  1. Friend “SubFriend” → subRow
    const subRow = sideNav.friend("SubFriend");
Friend row
Assert
  1. subtitle reads “Sub Tournament”
    await expect(subRow.locators.subtitle).toHaveText("Sub Tournament");
  2. badge reads “1/4”
    await expect(subRow.locators.badge).toHaveText("1/4");
Side nav
Act
  1. Friend “MatchFriend” → inMatchRow
    const inMatchRow = sideNav.friend("MatchFriend");
Friend row
Assert
  1. subtitle reads “Match Tournament”
    await expect(inMatchRow.locators.subtitle).toHaveText("Match Tournament");
  2. badge reads “Match”
    await expect(inMatchRow.locators.badge).toHaveText("Match");
Source
test("shows what each friend is doing right now", async ({
	page,
	factories,
}) => {
	const [idle, queueing, sub, inMatch, groupMate] = await createNamedUsers(
		factories,
		["IdleFriend", "QueueFriend", "SubFriend", "MatchFriend", "GroupMate"],
	);
	await befriend(factories, [idle.id, queueing.id, sub.id, inMatch.id]);

	await factories.SQGroupFactory.create({
		memberUserIds: [queueing.id, groupMate.id],
	});

	await createSubSeekingTournament(factories, {
		name: "Sub Tournament",
		subId: sub.id,
	});

	await createInProgressMatch(factories, {
		name: "Match Tournament",
		friendId: inMatch.id,
	});

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);

	const idleRow = sideNav.friend("IdleFriend");
	await expect(idleRow.trigger).toBeVisible();
	await expect(idleRow.locators.subtitle).toHaveCount(0);
	await expect(idleRow.locators.badge).toHaveCount(0);

	const queueingRow = sideNav.friend("QueueFriend");
	await expect(queueingRow.locators.subtitle).toHaveText("SendouQ");
	await expect(queueingRow.locators.badge).toHaveText("2/4");

	const subRow = sideNav.friend("SubFriend");
	await expect(subRow.locators.subtitle).toHaveText("Sub Tournament");
	await expect(subRow.locators.badge).toHaveText("1/4");

	const inMatchRow = sideNav.friend("MatchFriend");
	await expect(inMatchRow.locators.subtitle).toHaveText("Match Tournament");
	await expect(inMatchRow.locators.badge).toHaveText("Match");
})

Renders//q/looking/q/match/:id/u/:identifier/u/:identifier

Setup
Arrange
  1. Create named users “SidebarUser”, “IdleFriend”, “QueueFriend”, “MatchFriend” → [me, idle, queueing, inSendouQMatch]
    const [me, idle, queueing, inSendouQMatch] = await createNamedUsers(
    	factories,
    	["SidebarUser", "IdleFriend", "QueueFriend", "MatchFriend"],
    );
  2. Befriend idle.id, queueing.id, inSendouQMatch.id, me.id
    await befriend(factories, [idle.id, queueing.id, inSendouQMatch.id], me.id);
  3. Create SQ group member user ids queueing.id
    await factories.SQGroupFactory.create({ memberUserIds: [queueing.id] });
  4. Create SQ match alpha user ids inSendouQMatch.id, ...(await createUserIds(factories, 3)) bravo user ids createUserIds(factories, 4) → match
    const match = await factories.SQMatchFactory.create({
    	alphaUserIds: [inSendouQMatch.id, ...(await createUserIds(factories, 3))],
    	bravoUserIds: await createUserIds(factories, 4),
    });
Mme
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “IdleFriend” → idleRow
    const idleRow = sideNav.friend("IdleFriend");
Friend row
Act
  1. Open menu
    await idleRow.openMenu();
Assert
  1. menu item “Delete friend” count is 0
    await expect(idleRow.menuItem("Delete friend")).toHaveCount(0);
Act
  1. Click menu item “View user page”
    await idleRow.menuItem("View user page").click();
Assert
  1. the page URL is /\/u\//
    await expect(page).toHaveURL(/\/u\//);
  2. no error page
    await expectNoErrorPage(page);
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “MatchFriend” → matchRow
    const matchRow = sideNav.friend("MatchFriend");
Friend row
Act
  1. Open menu
    await matchRow.openMenu();
  2. Click menu item “View match”
    await matchRow.menuItem("View match").click();
Assert
  1. the page URL is sendouQMatchPage(match.id)
    await expect(page).toHaveURL(sendouQMatchPage(match.id));
  2. no error page
    await expectNoErrorPage(page);
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “QueueFriend” → queueingRow
    const queueingRow = sideNav.friend("QueueFriend");
Friend row
Act
  1. Open menu
    await queueingRow.openMenu();
  2. Click menu item “Join SendouQ”
    await waitForPOSTResponse(page, () =>
    	queueingRow.menuItem("Join SendouQ").click(),
    );
Assert
  1. the page URL is SENDOUQ_LOOKING_PAGE
    await expect(page).toHaveURL(SENDOUQ_LOOKING_PAGE);
  2. no error page
    await expectNoErrorPage(page);
Source
test("friend menu actions of SendouQ friends land on a real page", async ({
	page,
	factories,
}) => {
	const [me, idle, queueing, inSendouQMatch] = await createNamedUsers(
		factories,
		["SidebarUser", "IdleFriend", "QueueFriend", "MatchFriend"],
	);
	await befriend(factories, [idle.id, queueing.id, inSendouQMatch.id], me.id);

	await factories.SQGroupFactory.create({ memberUserIds: [queueing.id] });

	const match = await factories.SQMatchFactory.create({
		alphaUserIds: [inSendouQMatch.id, ...(await createUserIds(factories, 3))],
		bravoUserIds: await createUserIds(factories, 4),
	});

	await impersonate(page, me.id);
	const front = new FrontPage(page);
	await front.goto();

	const sideNav = new SideNav(page);

	const idleRow = sideNav.friend("IdleFriend");
	await idleRow.openMenu();
	await expect(idleRow.menuItem("Delete friend")).toHaveCount(0);
	await idleRow.menuItem("View user page").click();
	await expect(page).toHaveURL(/\/u\//);
	await expectNoErrorPage(page);

	await front.goto();
	const matchRow = sideNav.friend("MatchFriend");
	await matchRow.openMenu();
	await matchRow.menuItem("View match").click();
	await expect(page).toHaveURL(sendouQMatchPage(match.id));
	await expectNoErrorPage(page);

	await front.goto();
	const queueingRow = sideNav.friend("QueueFriend");
	await queueingRow.openMenu();
	await waitForPOSTResponse(page, () =>
		queueingRow.menuItem("Join SendouQ").click(),
	);
	await expect(page).toHaveURL(SENDOUQ_LOOKING_PAGE);
	await expectNoErrorPage(page);
})

Renders//to/:id/to/:id/looking/to/:id/matches/:mid/to/:id/brackets

Setup
Arrange
  1. Create named users “SubFriend”, “MatchFriend”, “WaitingFriend” → [sub, inMatch, waiting]
    const [sub, inMatch, waiting] = await createNamedUsers(factories, [
    	"SubFriend",
    	"MatchFriend",
    	"WaitingFriend",
    ]);
  2. Befriend sub.id, inMatch.id, waiting.id
    await befriend(factories, [sub.id, inMatch.id, waiting.id]);
  3. Create sub seeking tournament name “Sub Tournament” sub id sub.id → { tournament: subTournament }
    const { tournament: subTournament } = await createSubSeekingTournament(
    	factories,
    	{ name: "Sub Tournament", subId: sub.id },
    );
  4. Create in progress match name “Match Tournament” friend id inMatch.id → { tournament, matchId }
    const { tournament, matchId } = await createInProgressMatch(factories, {
    	name: "Match Tournament",
    	friendId: inMatch.id,
    });
  5. Create tournament with bye team name “Waiting Tournament” waiting user id waiting.id → { tournament: waitingTournament }
    const { tournament: waitingTournament } = await createTournamentWithByeTeam(
    	factories,
    	{ name: "Waiting Tournament", waitingUserId: waiting.id },
    );
NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “SubFriend” → subRow
    const subRow = sideNav.friend("SubFriend");
Friend row
Act
  1. Open menu
    await subRow.openMenu();
  2. Click menu item “View tournament”
    await subRow.menuItem("View tournament").click();
Assert
  1. the page URL is tournamentSubsPage(subTournament.id)
    await expect(page).toHaveURL(tournamentSubsPage(subTournament.id));
  2. no error page
    await expectNoErrorPage(page);
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “WaitingFriend” → waitingRow
    const waitingRow = sideNav.friend("WaitingFriend");
Friend row
Assert
  1. badge reads “Next”
    await expect(waitingRow.locators.badge).toHaveText("Next");
Act
  1. Open menu
    await waitingRow.openMenu();
  2. Click menu item “View tournament”
    await waitingRow.menuItem("View tournament").click();
Assert
  1. the page URL is new RegExp(`/to/${waitingTournament.id}(/|$)`)
    await expect(page).toHaveURL(
    	new RegExp(`/to/${waitingTournament.id}(/|$)`),
    );
  2. no error page
    await expectNoErrorPage(page);
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “MatchFriend” → inMatchRow
    const inMatchRow = sideNav.friend("MatchFriend");
Friend row
Act
  1. Open menu
    await inMatchRow.openMenu();
  2. Click menu item “View match”
    await inMatchRow.menuItem("View match").click();
Assert
  1. the page URL is tournamentMatchPage({ tournamentId: tournament.id, matchId })
    await expect(page).toHaveURL(
    	tournamentMatchPage({ tournamentId: tournament.id, matchId }),
    );
  2. no error page
    await expectNoErrorPage(page);
Source
test("friend menu actions of tournament friends land on a real page", async ({
	page,
	factories,
}) => {
	const [sub, inMatch, waiting] = await createNamedUsers(factories, [
		"SubFriend",
		"MatchFriend",
		"WaitingFriend",
	]);
	await befriend(factories, [sub.id, inMatch.id, waiting.id]);

	const { tournament: subTournament } = await createSubSeekingTournament(
		factories,
		{ name: "Sub Tournament", subId: sub.id },
	);

	const { tournament, matchId } = await createInProgressMatch(factories, {
		name: "Match Tournament",
		friendId: inMatch.id,
	});
	const { tournament: waitingTournament } = await createTournamentWithByeTeam(
		factories,
		{ name: "Waiting Tournament", waitingUserId: waiting.id },
	);

	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	await front.goto();

	const sideNav = new SideNav(page);

	const subRow = sideNav.friend("SubFriend");
	await subRow.openMenu();
	await subRow.menuItem("View tournament").click();
	await expect(page).toHaveURL(tournamentSubsPage(subTournament.id));
	await expectNoErrorPage(page);

	await front.goto();
	const waitingRow = sideNav.friend("WaitingFriend");
	await expect(waitingRow.locators.badge).toHaveText("Next");
	await waitingRow.openMenu();
	await waitingRow.menuItem("View tournament").click();
	await expect(page).toHaveURL(
		new RegExp(`/to/${waitingTournament.id}(/|$)`),
	);
	await expectNoErrorPage(page);

	await front.goto();
	const inMatchRow = sideNav.friend("MatchFriend");
	await inMatchRow.openMenu();
	await inMatchRow.menuItem("View match").click();
	await expect(page).toHaveURL(
		tournamentMatchPage({ tournamentId: tournament.id, matchId }),
	);
	await expectNoErrorPage(page);
})

Renders//friends

Setup
Arrange
  1. names = Array.from( { length: 10 }, (_, index) => `Friend${String(index + 1).padStart…
    const names = Array.from(
    	{ length: 10 },
    	(_, index) => `Friend${String(index + 1).padStart(2, "0")}`,
    );
  2. Create named users names → friends
    const friends = await createNamedUsers(factories, names);
  3. Befriend friends.map((friend) => friend.id)
    await befriend(
    	factories,
    	friends.map((friend) => friend.id),
    );
NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. friend items count is 4
    await expect(sideNav.locators.friendItems).toHaveCount(4);
Arrange
  1. Use a MOBILE_VIEWPORT viewport
    await page.setViewportSize(MOBILE_VIEWPORT);
Front page
Act
  1. Open the front page
    await front.goto();
Mobile nav
Act
  1. Open panel “friends”
    await mobileNav.openPanel("friends");
Assert
  1. friend items count is 8
    await expect(mobileNav.locators.friendItems).toHaveCount(8);
Act
  1. Click view all link
    await mobileNav.locators.viewAllLink.click();
Assert
  1. the page URL is FRIENDS_PAGE
    await expect(page).toHaveURL(FRIENDS_PAGE);
  2. For each name of names
    for (const name of names) {
    	await expect(friendsPage.friendButton(name)).toBeVisible();
    }
    1. friend button name is visible
      await expect(friendsPage.friendButton(name)).toBeVisible();
Source
test("shows four friends on desktop, eight in the mobile panel", async ({
	page,
	factories,
}) => {
	const names = Array.from(
		{ length: 10 },
		(_, index) => `Friend${String(index + 1).padStart(2, "0")}`,
	);
	const friends = await createNamedUsers(factories, names);
	await befriend(
		factories,
		friends.map((friend) => friend.id),
	);

	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	await front.goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.locators.friendItems).toHaveCount(4);

	await page.setViewportSize(MOBILE_VIEWPORT);
	await front.goto();

	const mobileNav = new MobileNav(page);
	await mobileNav.openPanel("friends");
	await expect(mobileNav.locators.friendItems).toHaveCount(8);

	await mobileNav.locators.viewAllLink.click();
	await expect(page).toHaveURL(FRIENDS_PAGE);

	const friendsPage = new FriendsPage(page);
	for (const name of names) {
		await expect(friendsPage.friendButton(name)).toBeVisible();
	}
})

Renders//friends

Setup
Arrange
  1. Create 2 × user → requesters
    const requesters = await factories.UserFactory.createMany(2);
  2. For each requester of requesters
    for (const requester of requesters) {
    	await factories.FriendRequestFactory.create({
    		senderId: requester.id,
    		receiverId: NZAP_TEST_ID,
    	});
    }
    1. Create friend request sender id requester.id receiver N-ZAP
      await factories.FriendRequestFactory.create({
      	senderId: requester.id,
      	receiverId: NZAP_TEST_ID,
      });
NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. unseen requests badge reads “2”
    await expect(sideNav.locators.unseenRequestsBadge).toHaveText("2");
Act
  1. Toggle collapse
    await sideNav.toggleCollapse();
Assert
  1. collapsed requests badge reads “2”
    await expect(sideNav.collapsedRequestsBadge).toHaveText("2");
Friends page
Act
  1. Open the friends page
    await friendsPage.goto();
  2. Accept request
    await friendsPage.acceptRequest();
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. unseen requests badge count is 0
    await expect(sideNav.locators.unseenRequestsBadge).toHaveCount(0);
Source
test("unseen friend requests show as a badge", async ({
	page,
	factories,
}) => {
	const requesters = await factories.UserFactory.createMany(2);
	for (const requester of requesters) {
		await factories.FriendRequestFactory.create({
			senderId: requester.id,
			receiverId: NZAP_TEST_ID,
		});
	}

	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	await front.goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.locators.unseenRequestsBadge).toHaveText("2");

	await sideNav.toggleCollapse();
	await expect(sideNav.collapsedRequestsBadge).toHaveText("2");

	const friendsPage = new FriendsPage(page);
	await friendsPage.goto();
	await friendsPage.acceptRequest();

	await front.goto();
	await expect(sideNav.locators.unseenRequestsBadge).toHaveCount(0);
})

Renders/

LOLogged out
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. empty text LOGGED_OUT_FRIENDS_TEXT is visible
    await expect(sideNav.emptyText(LOGGED_OUT_FRIENDS_TEXT)).toBeVisible();
  2. view all link “Friends” count is 0
    await expect(sideNav.viewAllLink("Friends")).toHaveCount(0);
NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. empty text NO_FRIENDS_TEXT is visible
    await expect(sideNav.emptyText(NO_FRIENDS_TEXT)).toBeVisible();
  2. view all link “Friends” is visible
    await expect(sideNav.viewAllLink("Friends")).toBeVisible();
Source
test("shows an empty state for both logged out and friendless users", async ({
	page,
}) => {
	const front = new FrontPage(page);
	await front.goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.emptyText(LOGGED_OUT_FRIENDS_TEXT)).toBeVisible();
	await expect(sideNav.viewAllLink("Friends")).toHaveCount(0);

	await impersonate(page, NZAP_TEST_ID);
	await front.goto();

	await expect(sideNav.emptyText(NO_FRIENDS_TEXT)).toBeVisible();
	await expect(sideNav.viewAllLink("Friends")).toBeVisible();
})

Renders/

Setup
Arrange
  1. Create named users “StreamFriend”, “StreamTeammate”, “StreamOpponent” → [friend, teammate, opponent]
    const [friend, teammate, opponent] = await createNamedUsers(factories, [
    	"StreamFriend",
    	"StreamTeammate",
    	"StreamOpponent",
    ]);
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Create in progress match name “Match Tournament” friend id friend.id teammate id teammate.id opponent id opponent.id → { tournament, matchId }
    const { tournament, matchId } = await createInProgressMatch(factories, {
    	name: "Match Tournament",
    	friendId: friend.id,
    	teammateId: teammate.id,
    	opponentId: opponent.id,
    });
  4. Cast match tournament tournament id tournament.id matchId twitch account “cast_account”
    await factories.TournamentFactory.castMatch({
    	tournamentId: tournament.id,
    	matchId,
    	twitchAccount: CAST_ACCOUNT,
    });
NN-ZAP
Side nav
Act
  1. Friend “StreamFriend” → friendRow
    const friendRow = new SideNav(page).friend("StreamFriend");
Arrange
  1. expectWatchStream = async (account: string) => { await front.goto(); await expect(friendRow.locat…
    const expectWatchStream = async (account: string) => {
    	await front.goto();
    	await expect(friendRow.locators.badge).toHaveText("Live");
    	await friendRow.openMenu();
    	expect(await friendRow.watchStreamHref()).toBe(twitchUrl(account));
    };
  2. Replace all live stream user id friend.id
    await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);
Assert
  1. streamAccountOf(friend.id) watch stream
    await expectWatchStream(streamAccountOf(friend.id));
Arrange
  1. Replace all live stream user id teammate.id
    await factories.LiveStreamFactory.replaceAll([{ userId: teammate.id }]);
Assert
  1. streamAccountOf(teammate.id) watch stream
    await expectWatchStream(streamAccountOf(teammate.id));
Arrange
  1. Replace all live stream user id null account “cast_account”
    await factories.LiveStreamFactory.replaceAll([
    	{ userId: null, account: CAST_ACCOUNT },
    ]);
Assert
  1. “cast_account” watch stream
    await expectWatchStream(CAST_ACCOUNT);
Arrange
  1. Replace all live stream user id opponent.id
    await factories.LiveStreamFactory.replaceAll([{ userId: opponent.id }]);
Assert
  1. streamAccountOf(opponent.id) watch stream
    await expectWatchStream(streamAccountOf(opponent.id));
Arrange
  1. Replace all live stream user id friend.id, user id teammate.id, user id opponent.id, user id null account “cast_account”
    await factories.LiveStreamFactory.replaceAll([
    	{ userId: friend.id },
    	{ userId: teammate.id },
    	{ userId: opponent.id },
    	{ userId: null, account: CAST_ACCOUNT },
    ]);
Assert
  1. streamAccountOf(friend.id) watch stream
    await expectWatchStream(streamAccountOf(friend.id));
Source
test("picks the best available stream for a friend's tournament match", async ({
	page,
	factories,
}) => {
	const [friend, teammate, opponent] = await createNamedUsers(factories, [
		"StreamFriend",
		"StreamTeammate",
		"StreamOpponent",
	]);
	await befriend(factories, [friend.id]);

	const { tournament, matchId } = await createInProgressMatch(factories, {
		name: "Match Tournament",
		friendId: friend.id,
		teammateId: teammate.id,
		opponentId: opponent.id,
	});
	await factories.TournamentFactory.castMatch({
		tournamentId: tournament.id,
		matchId,
		twitchAccount: CAST_ACCOUNT,
	});

	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	const friendRow = new SideNav(page).friend("StreamFriend");

	const expectWatchStream = async (account: string) => {
		await front.goto();
		await expect(friendRow.locators.badge).toHaveText("Live");
		await friendRow.openMenu();
		expect(await friendRow.watchStreamHref()).toBe(twitchUrl(account));
	};

	await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);
	await expectWatchStream(streamAccountOf(friend.id));

	await factories.LiveStreamFactory.replaceAll([{ userId: teammate.id }]);
	await expectWatchStream(streamAccountOf(teammate.id));

	await factories.LiveStreamFactory.replaceAll([
		{ userId: null, account: CAST_ACCOUNT },
	]);
	await expectWatchStream(CAST_ACCOUNT);

	await factories.LiveStreamFactory.replaceAll([{ userId: opponent.id }]);
	await expectWatchStream(streamAccountOf(opponent.id));

	await factories.LiveStreamFactory.replaceAll([
		{ userId: friend.id },
		{ userId: teammate.id },
		{ userId: opponent.id },
		{ userId: null, account: CAST_ACCOUNT },
	]);
	await expectWatchStream(streamAccountOf(friend.id));
})

Renders/

Setup
Arrange
  1. Create named users “StreamFriend” → [friend]
    const [friend] = await createNamedUsers(factories, ["StreamFriend"]);
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Create in progress match name “Match Tournament” friend id friend.id
    await createInProgressMatch(factories, {
    	name: "Match Tournament",
    	friendId: friend.id,
    });
  4. Replace all live stream user id friend.id
    await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);
LOLogged out
Act
  1. stubbed rather than aborted so the popup keeps the URL it was opened with

    Route “https://twitch.tv/**”, (route) => route.fulfill({ status: 200, contentType: "text/html", body: "<htm…
    await page.context().route("https://twitch.tv/**", (route) =>
    	route.fulfill({
    		status: 200,
    		contentType: "text/html",
    		body: "<html lang='en'><head><title>Twitch</title></head><body></body></html>",
    	}),
    );
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Act
  1. Friend “StreamFriend” → friendRow
    const friendRow = new SideNav(page).friend("StreamFriend");
Friend row
Act
  1. Open menu
    await friendRow.openMenu();
  2. Menu item “Watch stream” → watchStream
    const watchStream = friendRow.menuItem("Watch stream");
Assert
  1. watchStream has “href” = twitchUrl(streamAccountOf(friend.id))
    await expect(watchStream).toHaveAttribute(
    	"href",
    	twitchUrl(streamAccountOf(friend.id)),
    );
  2. watchStream has “target” = “_blank”
    await expect(watchStream).toHaveAttribute("target", "_blank");
  3. watchStream has “rel” = “noreferrer”
    await expect(watchStream).toHaveAttribute("rel", "noreferrer");
Act
  1. Catch () => null → popupPromise
    const popupPromise = page
    	.context()
    	.waitForEvent("page", { timeout: 5_000 })
    	.catch(() => null);
  2. Click watchStream
    await watchStream.click();
  3. popup = popupPromise
    const popup = await popupPromise;
  4. If popup
    if (popup) {
    	expect(popup.url()).toContain("twitch.tv");
    	await popup.close();
    }
    1. popup.url() contains “twitch.tv”
      expect(popup.url()).toContain("twitch.tv");
    2. Close
      await popup.close();
Assert
  1. the page URL is “/”
    await expect(page).toHaveURL("/");
  2. no error page
    await expectNoErrorPage(page);
Source
test("watch stream opens Twitch, not an in-app error page", async ({
	page,
	factories,
}) => {
	const [friend] = await createNamedUsers(factories, ["StreamFriend"]);
	await befriend(factories, [friend.id]);

	await createInProgressMatch(factories, {
		name: "Match Tournament",
		friendId: friend.id,
	});
	await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);

	// stubbed rather than aborted so the popup keeps the URL it was opened with
	await page.context().route("https://twitch.tv/**", (route) =>
		route.fulfill({
			status: 200,
			contentType: "text/html",
			body: "<html lang='en'><head><title>Twitch</title></head><body></body></html>",
		}),
	);

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const friendRow = new SideNav(page).friend("StreamFriend");
	await friendRow.openMenu();

	const watchStream = friendRow.menuItem("Watch stream");
	await expect(watchStream).toHaveAttribute(
		"href",
		twitchUrl(streamAccountOf(friend.id)),
	);
	await expect(watchStream).toHaveAttribute("target", "_blank");
	await expect(watchStream).toHaveAttribute("rel", "noreferrer");

	const popupPromise = page
		.context()
		.waitForEvent("page", { timeout: 5_000 })
		.catch(() => null);
	await watchStream.click();
	const popup = await popupPromise;

	if (popup) {
		expect(popup.url()).toContain("twitch.tv");
		await popup.close();
	}

	await expect(page).toHaveURL("/");
	await expectNoErrorPage(page);
})

Renders/

Setup
Arrange
  1. the friend has a Twitch account on their profile throughout: only an actually live stream may turn the row live

    Create named users “StreamFriend”, “Outsider”, twitch “friend_twitch” → [friend, outsider]
    const [friend, outsider] = await createNamedUsers(
    	factories,
    	["StreamFriend", "Outsider"],
    	{ twitch: "friend_twitch" },
    );
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Create in progress match name “Match Tournament” friend id friend.id → { tournament, matchId }
    const { tournament, matchId } = await createInProgressMatch(factories, {
    	name: "Match Tournament",
    	friendId: friend.id,
    });
NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “StreamFriend” → friendRow
    const friendRow = new SideNav(page).friend("StreamFriend");
Friend row
Assert
  1. badge reads “Match”
    await expect(friendRow.locators.badge).toHaveText("Match");
Act
  1. Open menu
    await friendRow.openMenu();
Assert
  1. menu item “View user page” is visible
    await expect(friendRow.menuItem("View user page")).toBeVisible();
  2. menu item “View match” has “href” = tournamentMatchPage({ tournamentId: tournament.id, matchId })
    await expect(friendRow.menuItem("View match")).toHaveAttribute(
    	"href",
    	tournamentMatchPage({ tournamentId: tournament.id, matchId }),
    );
  3. menu item “Watch stream” count is 0
    await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
Arrange
  1. Replace all live stream user id outsider.id
    await factories.LiveStreamFactory.replaceAll([{ userId: outsider.id }]);
Front page
Act
  1. Open the front page
    await front.goto();
Friend row
Assert
  1. badge reads “Match”
    await expect(friendRow.locators.badge).toHaveText("Match");
Act
  1. Open menu
    await friendRow.openMenu();
Assert
  1. menu item “Watch stream” count is 0
    await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
Source
test("shows no stream when nobody streams the friend's match", async ({
	page,
	factories,
}) => {
	// the friend has a Twitch account on their profile throughout: only an
	// actually live stream may turn the row live
	const [friend, outsider] = await createNamedUsers(
		factories,
		["StreamFriend", "Outsider"],
		{ twitch: "friend_twitch" },
	);
	await befriend(factories, [friend.id]);

	const { tournament, matchId } = await createInProgressMatch(factories, {
		name: "Match Tournament",
		friendId: friend.id,
	});

	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	await front.goto();

	const friendRow = new SideNav(page).friend("StreamFriend");
	await expect(friendRow.locators.badge).toHaveText("Match");
	await friendRow.openMenu();
	await expect(friendRow.menuItem("View user page")).toBeVisible();
	await expect(friendRow.menuItem("View match")).toHaveAttribute(
		"href",
		tournamentMatchPage({ tournamentId: tournament.id, matchId }),
	);
	await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);

	await factories.LiveStreamFactory.replaceAll([{ userId: outsider.id }]);
	await front.goto();

	await expect(friendRow.locators.badge).toHaveText("Match");
	await friendRow.openMenu();
	await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
})

Renders/

Setup
Arrange
  1. Create named users “StreamFriend” → [friend]
    const [friend] = await createNamedUsers(factories, ["StreamFriend"]);
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Create in progress match name “Match Tournament” friend id friend.id → { tournament, matchId }
    const { tournament, matchId } = await createInProgressMatch(factories, {
    	name: "Match Tournament",
    	friendId: friend.id,
    });
  4. Cast match tournament tournament id tournament.id matchId twitch account “cast_account”
    await factories.TournamentFactory.castMatch({
    	tournamentId: tournament.id,
    	matchId,
    	twitchAccount: CAST_ACCOUNT,
    });
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Act
  1. Friend “StreamFriend” → friendRow
    const friendRow = new SideNav(page).friend("StreamFriend");
Friend row
Assert
  1. badge reads “Match”
    await expect(friendRow.locators.badge).toHaveText("Match");
Act
  1. Open menu
    await friendRow.openMenu();
Assert
  1. menu item “Watch stream” count is 0
    await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
Source
test("a casted match whose caster is offline is not live", async ({
	page,
	factories,
}) => {
	const [friend] = await createNamedUsers(factories, ["StreamFriend"]);
	await befriend(factories, [friend.id]);

	const { tournament, matchId } = await createInProgressMatch(factories, {
		name: "Match Tournament",
		friendId: friend.id,
	});
	await factories.TournamentFactory.castMatch({
		tournamentId: tournament.id,
		matchId,
		twitchAccount: CAST_ACCOUNT,
	});

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const friendRow = new SideNav(page).friend("StreamFriend");
	await expect(friendRow.locators.badge).toHaveText("Match");
	await friendRow.openMenu();
	await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
})

Renders/

Setup
Arrange
  1. Create named users “WaitingFriend” → [friend]
    const [friend] = await createNamedUsers(factories, ["WaitingFriend"]);
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Create tournament with bye team name “Waiting Tournament” waiting user id friend.id
    await createTournamentWithByeTeam(factories, {
    	name: "Waiting Tournament",
    	waitingUserId: friend.id,
    });
  4. Replace all live stream user id friend.id
    await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Act
  1. Friend “WaitingFriend” → friendRow
    const friendRow = new SideNav(page).friend("WaitingFriend");
Friend row
Assert
  1. badge reads “Next”
    await expect(friendRow.locators.badge).toHaveText("Next");
Act
  1. Open menu
    await friendRow.openMenu();
Assert
  1. menu item “View tournament” is visible
    await expect(friendRow.menuItem("View tournament")).toBeVisible();
  2. menu item “Watch stream” count is 0
    await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
Source
test("a friend waiting for their next match is never live", async ({
	page,
	factories,
}) => {
	const [friend] = await createNamedUsers(factories, ["WaitingFriend"]);
	await befriend(factories, [friend.id]);

	await createTournamentWithByeTeam(factories, {
		name: "Waiting Tournament",
		waitingUserId: friend.id,
	});
	await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const friendRow = new SideNav(page).friend("WaitingFriend");
	await expect(friendRow.locators.badge).toHaveText("Next");
	await friendRow.openMenu();
	await expect(friendRow.menuItem("View tournament")).toBeVisible();
	await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
})

Renders//q/match/:id

Setup
Arrange
  1. Create named users “MatchFriend”, “MatchStreamer” → [friend, streamer]
    const [friend, streamer] = await createNamedUsers(factories, [
    	"MatchFriend",
    	"MatchStreamer",
    ]);
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Create SQ match alpha user ids friend.id, streamer.id, ...(await createUserIds(factories, 2)) bravo user ids createUserIds(factories, 4) → match
    const match = await factories.SQMatchFactory.create({
    	alphaUserIds: [
    		friend.id,
    		streamer.id,
    		...(await createUserIds(factories, 2)),
    	],
    	bravoUserIds: await createUserIds(factories, 4),
    });
  4. Replace all live stream user id streamer.id
    await factories.LiveStreamFactory.replaceAll([{ userId: streamer.id }]);
NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Friend “MatchFriend” → friendRow
    const friendRow = new SideNav(page).friend("MatchFriend");
Friend row
Assert
  1. badge reads “Live”
    await expect(friendRow.locators.badge).toHaveText("Live");
Act
  1. Open menu
    await friendRow.openMenu();
Assert
  1. watch stream href is twitchUrl(streamAccountOf(streamer.id))
    expect(await friendRow.watchStreamHref()).toBe(
    	twitchUrl(streamAccountOf(streamer.id)),
    );
Arrange
  1. Replace all live stream
    await factories.LiveStreamFactory.replaceAll([]);
Front page
Act
  1. Open the front page
    await front.goto();
Friend row
Assert
  1. badge reads “Match”
    await expect(friendRow.locators.badge).toHaveText("Match");
Act
  1. Open menu
    await friendRow.openMenu();
Assert
  1. menu item “Watch stream” count is 0
    await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
Act
  1. Click menu item “View match”
    await friendRow.menuItem("View match").click();
Assert
  1. the page URL is sendouQMatchPage(match.id)
    await expect(page).toHaveURL(sendouQMatchPage(match.id));
  2. no error page
    await expectNoErrorPage(page);
Source
test("shows the stream of a friend's SendouQ match", async ({
	page,
	factories,
}) => {
	const [friend, streamer] = await createNamedUsers(factories, [
		"MatchFriend",
		"MatchStreamer",
	]);
	await befriend(factories, [friend.id]);

	const match = await factories.SQMatchFactory.create({
		alphaUserIds: [
			friend.id,
			streamer.id,
			...(await createUserIds(factories, 2)),
		],
		bravoUserIds: await createUserIds(factories, 4),
	});
	await factories.LiveStreamFactory.replaceAll([{ userId: streamer.id }]);

	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	await front.goto();

	const friendRow = new SideNav(page).friend("MatchFriend");
	await expect(friendRow.locators.badge).toHaveText("Live");
	await friendRow.openMenu();
	expect(await friendRow.watchStreamHref()).toBe(
		twitchUrl(streamAccountOf(streamer.id)),
	);

	await factories.LiveStreamFactory.replaceAll([]);
	await front.goto();

	await expect(friendRow.locators.badge).toHaveText("Match");
	await friendRow.openMenu();
	await expect(friendRow.menuItem("Watch stream")).toHaveCount(0);
	await friendRow.menuItem("View match").click();

	await expect(page).toHaveURL(sendouQMatchPage(match.id));
	await expectNoErrorPage(page);
})

Renders/

NN-ZAP
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Act
  1. Toggle collapse
    await sideNav.toggleCollapse();
Assert
  1. section heading “Events” count is 0
    await expect(sideNav.sectionHeading("Events")).toHaveCount(0);
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. section heading “Events” count is 0
    await expect(sideNav.sectionHeading("Events")).toHaveCount(0);
Act
  1. Toggle collapse
    await sideNav.toggleCollapse();
Assert
  1. section heading “Events” is visible
    await expect(sideNav.sectionHeading("Events")).toBeVisible();
Front page
Act
  1. Open the front page
    await front.goto();
Side nav
Assert
  1. section heading “Events” is visible
    await expect(sideNav.sectionHeading("Events")).toBeVisible();
Source
test("collapsing the sidebar sticks across reloads", async ({ page }) => {
	await impersonate(page, NZAP_TEST_ID);
	const front = new FrontPage(page);
	await front.goto();

	const sideNav = new SideNav(page);
	await sideNav.toggleCollapse();
	await expect(sideNav.sectionHeading("Events")).toHaveCount(0);

	await front.goto();
	await expect(sideNav.sectionHeading("Events")).toHaveCount(0);

	await sideNav.toggleCollapse();
	await expect(sideNav.sectionHeading("Events")).toBeVisible();

	await front.goto();
	await expect(sideNav.sectionHeading("Events")).toBeVisible();
})

Renders//u/:identifier/u/:identifier

Setup
Arrange
  1. Create named users “ModalFriend” → [friend]
    const [friend] = await createNamedUsers(factories, ["ModalFriend"]);
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Use a TABLET_VIEWPORT viewport
    await page.setViewportSize(TABLET_VIEWPORT);
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. section heading “Events” count is 0
    await expect(sideNav.sectionHeading("Events")).toHaveCount(0);
Act
  1. Open modal
    await sideNav.openModal();
Assert
  1. section heading “Events” is visible
    await expect(sideNav.sectionHeading("Events")).toBeVisible();
  2. section heading “Friends” is visible
    await expect(sideNav.sectionHeading("Friends")).toBeVisible();
  3. section heading “Streams” is visible
    await expect(sideNav.sectionHeading("Streams")).toBeVisible();
  4. trigger is visible
    await expect(sideNav.friend("ModalFriend").trigger).toBeVisible();
Act
  1. Close modal
    await sideNav.closeModal();
Assert
  1. section heading “Events” count is 0
    await expect(sideNav.sectionHeading("Events")).toHaveCount(0);
Act
  1. Open modal
    await sideNav.openModal();
  2. Friend “ModalFriend” → friendRow
    const friendRow = sideNav.friend("ModalFriend");
Friend row
Act
  1. Open menu
    await friendRow.openMenu();
  2. Click menu item “View user page”
    await friendRow.menuItem("View user page").click();
Assert
  1. the page URL is /\/u\//
    await expect(page).toHaveURL(/\/u\//);
Side nav
Assert
  1. section heading “Events” count is 0
    await expect(sideNav.sectionHeading("Events")).toHaveCount(0);
  2. no error page
    await expectNoErrorPage(page);
Source
test("tablet shows the same sidebar in a modal", async ({
	page,
	factories,
}) => {
	const [friend] = await createNamedUsers(factories, ["ModalFriend"]);
	await befriend(factories, [friend.id]);

	await page.setViewportSize(TABLET_VIEWPORT);
	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.sectionHeading("Events")).toHaveCount(0);

	await sideNav.openModal();
	await expect(sideNav.sectionHeading("Events")).toBeVisible();
	await expect(sideNav.sectionHeading("Friends")).toBeVisible();
	await expect(sideNav.sectionHeading("Streams")).toBeVisible();
	await expect(sideNav.friend("ModalFriend").trigger).toBeVisible();

	await sideNav.closeModal();
	await expect(sideNav.sectionHeading("Events")).toHaveCount(0);

	await sideNav.openModal();
	const friendRow = sideNav.friend("ModalFriend");
	await friendRow.openMenu();
	await friendRow.menuItem("View user page").click();

	await expect(page).toHaveURL(/\/u\//);
	await expect(sideNav.sectionHeading("Events")).toHaveCount(0);
	await expectNoErrorPage(page);
})

Renders//events

Setup
Arrange
  1. Create named users “StreamFriend” → [friend]
    const [friend] = await createNamedUsers(factories, ["StreamFriend"]);
  2. Befriend friend.id
    await befriend(factories, [friend.id]);
  3. Create in progress match name “Streamed Tournament” friend id friend.id
    await createInProgressMatch(factories, {
    	name: "Streamed Tournament",
    	friendId: friend.id,
    });
  4. Replace all live stream user id friend.id
    await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);
  5. Create tournament author Sendou name “My Tournament” start times inHours(2) → tournament
    const tournament = await factories.TournamentFactory.create({
    	authorId: ADMIN_ID,
    	name: "My Tournament",
    	startTimes: [inHours(2)],
    });
  6. Create tournament team tournament id tournament.id member user ids N-ZAP
    await factories.TournamentTeamFactory.create({
    	tournamentId: tournament.id,
    	memberUserIds: [NZAP_TEST_ID],
    });
  7. Use a MOBILE_VIEWPORT viewport
    await page.setViewportSize(MOBILE_VIEWPORT);
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Mobile nav
Act
  1. Open panel “friends”
    await mobileNav.openPanel("friends");
  2. Friend “StreamFriend” → friendRow
    const friendRow = mobileNav.friend("StreamFriend");
Friend row
Assert
  1. badge reads “Live”
    await expect(friendRow.locators.badge).toHaveText("Live");
Act
  1. Open menu
    await friendRow.openMenu();
Assert
  1. watch stream href is twitchUrl(streamAccountOf(friend.id))
    expect(await friendRow.watchStreamHref()).toBe(
    	twitchUrl(streamAccountOf(friend.id)),
    );
Act
  1. Press Escape
    await page.keyboard.press("Escape");
Mobile nav
Act
  1. Switch panel “tourneys”
    await mobileNav.switchPanel("tourneys");
Assert
  1. event item “My Tournament” is visible
    await expect(mobileNav.eventItem("My Tournament")).toBeVisible();
Act
  1. Switch panel “menu”
    await mobileNav.switchPanel("menu");
Assert
  1. streams heading is visible
    await expect(mobileNav.locators.streamsHeading).toBeVisible();
  2. stream item “Streamed Tournament” is visible
    await expect(mobileNav.streamItem("Streamed Tournament")).toBeVisible();
Act
  1. Switch panel “tourneys”
    await mobileNav.switchPanel("tourneys");
  2. Click view all link
    await mobileNav.locators.viewAllLink.click();
Assert
  1. the page URL is EVENTS_PAGE
    await expect(page).toHaveURL(EVENTS_PAGE);
  2. view all link count is 0
    await expect(mobileNav.locators.viewAllLink).toHaveCount(0);
Source
test("mobile panels show the same data as the desktop sidebar", async ({
	page,
	factories,
}) => {
	const [friend] = await createNamedUsers(factories, ["StreamFriend"]);
	await befriend(factories, [friend.id]);

	await createInProgressMatch(factories, {
		name: "Streamed Tournament",
		friendId: friend.id,
	});
	await factories.LiveStreamFactory.replaceAll([{ userId: friend.id }]);

	const tournament = await factories.TournamentFactory.create({
		authorId: ADMIN_ID,
		name: "My Tournament",
		startTimes: [inHours(2)],
	});
	await factories.TournamentTeamFactory.create({
		tournamentId: tournament.id,
		memberUserIds: [NZAP_TEST_ID],
	});

	await page.setViewportSize(MOBILE_VIEWPORT);
	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const mobileNav = new MobileNav(page);
	await mobileNav.openPanel("friends");

	const friendRow = mobileNav.friend("StreamFriend");
	await expect(friendRow.locators.badge).toHaveText("Live");
	await friendRow.openMenu();
	expect(await friendRow.watchStreamHref()).toBe(
		twitchUrl(streamAccountOf(friend.id)),
	);
	await page.keyboard.press("Escape");

	await mobileNav.switchPanel("tourneys");
	await expect(mobileNav.eventItem("My Tournament")).toBeVisible();

	await mobileNav.switchPanel("menu");
	await expect(mobileNav.locators.streamsHeading).toBeVisible();
	await expect(mobileNav.streamItem("Streamed Tournament")).toBeVisible();

	await mobileNav.switchPanel("tourneys");
	await mobileNav.locators.viewAllLink.click();
	await expect(page).toHaveURL(EVENTS_PAGE);
	await expect(mobileNav.locators.viewAllLink).toHaveCount(0);
})

Renders//to/:id/to/:id/streams

Setup
Arrange
  1. Create named users “TournamentStreamer” → [streamer]
    const [streamer] = await createNamedUsers(factories, [
    	"TournamentStreamer",
    ]);
  2. Create in progress match name “Streamed Tournament” friend id streamer.id → { tournament }
    const { tournament } = await createInProgressMatch(factories, {
    	name: "Streamed Tournament",
    	friendId: streamer.id,
    });
  3. Replace all live stream user id streamer.id
    await factories.LiveStreamFactory.replaceAll([{ userId: streamer.id }]);
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. item badge “Streamed Tournament” reads “LIVE”
    await expect(sideNav.itemBadge("Streamed Tournament")).toHaveText("LIVE");
  2. item subtitle “Streamed Tournament” is not empty
    await expect(sideNav.itemSubtitle("Streamed Tournament")).not.toBeEmpty();
Act
  1. Click stream item “Streamed Tournament”
    await sideNav.streamItem("Streamed Tournament").click();
Assert
  1. the page URL is tournamentStreamsPage(tournament.id)
    await expect(page).toHaveURL(tournamentStreamsPage(tournament.id));
Tournament streams page
Assert
  1. first streams is visible
    await expect(
    	new TournamentStreamsPage(page).locators.streams.first(),
    ).toBeVisible();
Source
test("live tournament streams link to the tournament's streams page", async ({
	page,
	factories,
}) => {
	const [streamer] = await createNamedUsers(factories, [
		"TournamentStreamer",
	]);
	const { tournament } = await createInProgressMatch(factories, {
		name: "Streamed Tournament",
		friendId: streamer.id,
	});
	await factories.LiveStreamFactory.replaceAll([{ userId: streamer.id }]);

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.itemBadge("Streamed Tournament")).toHaveText("LIVE");
	await expect(sideNav.itemSubtitle("Streamed Tournament")).not.toBeEmpty();

	await sideNav.streamItem("Streamed Tournament").click();
	await expect(page).toHaveURL(tournamentStreamsPage(tournament.id));

	await expect(
		new TournamentStreamsPage(page).locators.streams.first(),
	).toBeVisible();
})

Renders/

Setup
Arrange
  1. Create live X rank streamer
    await createLiveXRankStreamer(factories);
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. item subtitle “TopPlayer” reads String(TOP_PLAYER_XP)
    await expect(sideNav.itemSubtitle("TopPlayer")).toHaveText(
    	String(TOP_PLAYER_XP),
    );
  2. stream item “TopPlayer” has “href” = twitchUrl(XRANK_TWITCH)
    await expect(sideNav.streamItem("TopPlayer")).toHaveAttribute(
    	"href",
    	twitchUrl(XRANK_TWITCH),
    );
Source
test("x rank streamers link straight to Twitch", async ({
	page,
	factories,
}) => {
	await createLiveXRankStreamer(factories);

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.itemSubtitle("TopPlayer")).toHaveText(
		String(TOP_PLAYER_XP),
	);
	await expect(sideNav.streamItem("TopPlayer")).toHaveAttribute(
		"href",
		twitchUrl(XRANK_TWITCH),
	);
})

Renders/

Setup
Arrange
  1. Create live X rank streamer
    await createLiveXRankStreamer(factories);
  2. Create tournament author Sendou name “Upcoming Tournament” start times inDays(2) tier 1
    await factories.TournamentFactory.create(
    	{
    		authorId: ADMIN_ID,
    		name: "Upcoming Tournament",
    		startTimes: [inDays(2)],
    	},
    	{ tier: 1 },
    );
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Assert
  1. sideNav.streamItem("TopPlayer"), sideNav.locators.upcomingDivider, sideNav.streamItem("Upcoming Tournament") top to bottom
    await expectTopToBottom([
    	sideNav.streamItem("TopPlayer"),
    	sideNav.locators.upcomingDivider,
    	sideNav.streamItem("Upcoming Tournament"),
    ]);
Side nav
Assert
  1. item tier “Upcoming Tournament” is visible
    await expect(sideNav.itemTier("Upcoming Tournament")).toBeVisible();
Act
  1. Save stream “Upcoming Tournament”
    await sideNav.saveStream("Upcoming Tournament");
Assert
  1. saved stream icon “Upcoming Tournament” is visible
    await expect(sideNav.savedStreamIcon("Upcoming Tournament")).toBeVisible();
  2. event item “Upcoming Tournament” count is 2
    await expect(sideNav.eventItem("Upcoming Tournament")).toHaveCount(2);
Act
  1. Save stream “Upcoming Tournament”
    await sideNav.saveStream("Upcoming Tournament");
Assert
  1. saved stream icon “Upcoming Tournament” count is 0
    await expect(sideNav.savedStreamIcon("Upcoming Tournament")).toHaveCount(0);
  2. event item “Upcoming Tournament” count is 1
    await expect(sideNav.eventItem("Upcoming Tournament")).toHaveCount(1);
Source
test("upcoming tournaments sit under the Upcoming divider and can be saved", async ({
	page,
	factories,
}) => {
	await createLiveXRankStreamer(factories);

	await factories.TournamentFactory.create(
		{
			authorId: ADMIN_ID,
			name: "Upcoming Tournament",
			startTimes: [inDays(2)],
		},
		{ tier: 1 },
	);

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expectTopToBottom([
		sideNav.streamItem("TopPlayer"),
		sideNav.locators.upcomingDivider,
		sideNav.streamItem("Upcoming Tournament"),
	]);
	await expect(sideNav.itemTier("Upcoming Tournament")).toBeVisible();

	await sideNav.saveStream("Upcoming Tournament");
	await expect(sideNav.savedStreamIcon("Upcoming Tournament")).toBeVisible();
	await expect(sideNav.eventItem("Upcoming Tournament")).toHaveCount(2);

	await sideNav.saveStream("Upcoming Tournament");
	await expect(sideNav.savedStreamIcon("Upcoming Tournament")).toHaveCount(0);
	await expect(sideNav.eventItem("Upcoming Tournament")).toHaveCount(1);
})

Renders/

Setup
Arrange
  1. Create named users “HighTierStreamer”, “LowTierStreamer”, “SendouQStreamer” → [highTierStreamer, lowTierStreamer, sendouQStreamer]
    const [highTierStreamer, lowTierStreamer, sendouQStreamer] =
    	await createNamedUsers(factories, [
    		"HighTierStreamer",
    		"LowTierStreamer",
    		"SendouQStreamer",
    	]);
  2. Create in progress match name “High Tier Tournament” friend id highTierStreamer.id tier 1
    await createInProgressMatch(factories, {
    	name: "High Tier Tournament",
    	friendId: highTierStreamer.id,
    	tier: 1,
    });
  3. Create in progress match name “Low Tier Tournament” friend id lowTierStreamer.id tier 3
    await createInProgressMatch(factories, {
    	name: "Low Tier Tournament",
    	friendId: lowTierStreamer.id,
    	tier: 3,
    });
  4. Create SQ match alpha user ids sendouQStreamer.id, ...(await createUserIds(factories, 3)) bravo user ids createUserIds(factories, 4)
    await factories.SQMatchFactory.create({
    	alphaUserIds: [
    		sendouQStreamer.id,
    		...(await createUserIds(factories, 3)),
    	],
    	bravoUserIds: await createUserIds(factories, 4),
    });
  5. Replace all live stream user id highTierStreamer.id, user id lowTierStreamer.id, user id sendouQStreamer.id
    await factories.LiveStreamFactory.replaceAll([
    	{ userId: highTierStreamer.id },
    	{ userId: lowTierStreamer.id },
    	{ userId: sendouQStreamer.id },
    ]);
  6. For each nth of 1, 2, 3
    for (const nth of [1, 2, 3]) {
    	await factories.TournamentFactory.create(
    		{
    			authorId: ADMIN_ID,
    			name: `Upcoming Tournament ${nth}`,
    			startTimes: [inDays(1)],
    		},
    		{ tier: 1 },
    	);
    }
    1. Create tournament author Sendou name `Upcoming Tournament ${nth}` start times inDays(1) tier 1
      await factories.TournamentFactory.create(
      	{
      		authorId: ADMIN_ID,
      		name: `Upcoming Tournament ${nth}`,
      		startTimes: [inDays(1)],
      	},
      	{ tier: 1 },
      );
NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. list items count is 5
    await expect(sideNav.locators.listItems).toHaveCount(5);
  2. sideNav.streamItem("High Tier Tournament"), sideNav.streamItem("Low Tier Tournament"), sideNav.locators.upcomingDivider top to bottom
    await expectTopToBottom([
    	sideNav.streamItem("High Tier Tournament"),
    	sideNav.streamItem("Low Tier Tournament"),
    	sideNav.locators.upcomingDivider,
    ]);
Source
test("shows at most five streams, best first", async ({
	page,
	factories,
}) => {
	const [highTierStreamer, lowTierStreamer, sendouQStreamer] =
		await createNamedUsers(factories, [
			"HighTierStreamer",
			"LowTierStreamer",
			"SendouQStreamer",
		]);

	await createInProgressMatch(factories, {
		name: "High Tier Tournament",
		friendId: highTierStreamer.id,
		tier: 1,
	});
	await createInProgressMatch(factories, {
		name: "Low Tier Tournament",
		friendId: lowTierStreamer.id,
		tier: 3,
	});
	await factories.SQMatchFactory.create({
		alphaUserIds: [
			sendouQStreamer.id,
			...(await createUserIds(factories, 3)),
		],
		bravoUserIds: await createUserIds(factories, 4),
	});
	await factories.LiveStreamFactory.replaceAll([
		{ userId: highTierStreamer.id },
		{ userId: lowTierStreamer.id },
		{ userId: sendouQStreamer.id },
	]);

	for (const nth of [1, 2, 3]) {
		await factories.TournamentFactory.create(
			{
				authorId: ADMIN_ID,
				name: `Upcoming Tournament ${nth}`,
				startTimes: [inDays(1)],
			},
			{ tier: 1 },
		);
	}

	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.locators.listItems).toHaveCount(5);
	await expectTopToBottom([
		sideNav.streamItem("High Tier Tournament"),
		sideNav.streamItem("Low Tier Tournament"),
		sideNav.locators.upcomingDivider,
	]);
})

Renders/

NN-ZAP
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. empty text NO_STREAMS_TEXT is visible
    await expect(new SideNav(page).emptyText(NO_STREAMS_TEXT)).toBeVisible();
Source
test("shows an empty state without streams", async ({ page }) => {
	await impersonate(page, NZAP_TEST_ID);
	await new FrontPage(page).goto();

	await expect(new SideNav(page).emptyText(NO_STREAMS_TEXT)).toBeVisible();
})

Renders//to/:id/to/:id/streams

Setup
Arrange
  1. Create named users “TournamentStreamer” → [streamer]
    const [streamer] = await createNamedUsers(factories, [
    	"TournamentStreamer",
    ]);
  2. Create in progress match name “Streamed Tournament” friend id streamer.id → { tournament }
    const { tournament } = await createInProgressMatch(factories, {
    	name: "Streamed Tournament",
    	friendId: streamer.id,
    });
  3. Replace all live stream user id streamer.id
    await factories.LiveStreamFactory.replaceAll([{ userId: streamer.id }]);
LOLogged out
Front page
Act
  1. Open the front page
    await new FrontPage(page).goto();
Side nav
Assert
  1. empty text NO_EVENTS_TEXT is visible
    await expect(sideNav.emptyText(NO_EVENTS_TEXT)).toBeVisible();
  2. empty text LOGGED_OUT_FRIENDS_TEXT is visible
    await expect(sideNav.emptyText(LOGGED_OUT_FRIENDS_TEXT)).toBeVisible();
Act
  1. Click stream item “Streamed Tournament”
    await sideNav.streamItem("Streamed Tournament").click();
Assert
  1. the page URL is tournamentStreamsPage(tournament.id)
    await expect(page).toHaveURL(tournamentStreamsPage(tournament.id));
  2. no error page
    await expectNoErrorPage(page);
Source
test("shows streams to logged out visitors", async ({ page, factories }) => {
	const [streamer] = await createNamedUsers(factories, [
		"TournamentStreamer",
	]);
	const { tournament } = await createInProgressMatch(factories, {
		name: "Streamed Tournament",
		friendId: streamer.id,
	});
	await factories.LiveStreamFactory.replaceAll([{ userId: streamer.id }]);

	await new FrontPage(page).goto();

	const sideNav = new SideNav(page);
	await expect(sideNav.emptyText(NO_EVENTS_TEXT)).toBeVisible();
	await expect(sideNav.emptyText(LOGGED_OUT_FRIENDS_TEXT)).toBeVisible();

	await sideNav.streamItem("Streamed Tournament").click();
	await expect(page).toHaveURL(tournamentStreamsPage(tournament.id));
	await expectNoErrorPage(page);
})