Skip to content

Plus voting · E2E tests

1 module · 2 exports · 1 repository · 3 e2e tests · 3 routes

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

Plus Server

member suggests a user, members vote and results decide the memberships

SendouN-ZAPsuggestedplus.spec.ts:35

Renders/plus/plus/suggestions/plus/suggestions/comment/:tier/:userId/plus/suggestions/new/plus/voting/plus/voting/results

LOLogged out
Act
  1. a long flow: runs past two thirds of the default timeout under load

    Slow
    test.slow();
Arrange
  1. Grant user Sendou plus tier 1
    await factories.UserFactory.grant(ADMIN_ID, { plusTier: 1 });
  2. Grant user N-ZAP plus tier 1
    await factories.UserFactory.grant(NZAP_TEST_ID, { plusTier: 1 });
  3. Create user discord name “SuggestedSue” discord id “1000000000000000001” profile null → suggested
    const suggested = await factories.UserFactory.create({
    	discordName: SUGGESTED_NAME,
    	discordId: SUGGESTED_DISCORD_ID,
    	profile: null,
    });
SSendou
Plus suggestions page
Act
  1. Open the plus suggestions page
    await suggestions.goto();
Assert
  1. no suggestions is visible
    await expect(suggestions.locators.noSuggestions).toBeVisible();
New suggestion page
Act
  1. Open the new suggestion page
    await newSuggestion.goto();
Assert
  1. heading is visible
    await expect(newSuggestion.locators.heading).toBeVisible();
Act
  1. Suggest username “SuggestedSue” comment “Great player and even better person”
    await newSuggestion.suggest({
    	username: SUGGESTED_NAME,
    	comment: SUGGESTION_TEXT,
    });
Plus suggestions page
Assert
  1. suggested user “SuggestedSue” is visible
    await expect(suggestions.suggestedUser(SUGGESTED_NAME)).toBeVisible();
Act
  1. Open comments 1
    await suggestions.openComments(1);
Assert
  1. comment “Great player and even better person” is visible
    await expect(suggestions.comment(SUGGESTION_TEXT)).toBeVisible();
Act
  1. Edit comment “Great player and even better person”, “Great player and an amazing person”
    await suggestions.editComment(SUGGESTION_TEXT, EDITED_SUGGESTION_TEXT);
  2. Open comments 1
    await suggestions.openComments(1);
Assert
  1. comment “Great player and an amazing person” is visible
    await expect(suggestions.comment(EDITED_SUGGESTION_TEXT)).toBeVisible();
NN-ZAP
Plus suggestions page
Act
  1. Open the plus suggestions page
    await suggestions.goto();
  2. Click comment link
    await suggestions.locators.commentLink.click();
Suggestion comment page
Assert
  1. heading username “SuggestedSue” tier 1 is visible
    await expect(
    	commentPage.heading({ username: SUGGESTED_NAME, tier: 1 }),
    ).toBeVisible();
Act
  1. Comment “Seconding, deserves the spot”
    await commentPage.comment(FOLLOW_UP_COMMENT_TEXT);
Plus suggestions page
Act
  1. Open comments 2
    await suggestions.openComments(2);
Assert
  1. comment “Seconding, deserves the spot” is visible
    await expect(suggestions.comment(FOLLOW_UP_COMMENT_TEXT)).toBeVisible();
Act
  1. Delete comment “Seconding, deserves the spot”
    await suggestions.deleteComment(FOLLOW_UP_COMMENT_TEXT);
Assert
  1. comments summary 1 is visible
    await expect(suggestions.commentsSummary(1)).toBeVisible();
Act
  1. Set plus voting active true
    await setPlusVotingActive(page, true);
  2. Run routine “NotifyPlusServerVoting”
    await runRoutine(page, "NotifyPlusServerVoting");
  3. Open the plus suggestions page
    await suggestions.goto();
Notification popover
Act
  1. Open
    await notifications.open();
  2. Open notification “Plus Server voting of season”
    await notifications.openNotification("Plus Server voting of season");
Assert
  1. the page URL is PLUS_VOTING_PAGE
    await expect(page).toHaveURL(PLUS_VOTING_PAGE);
Plus voting page
Assert
  1. upvote button is visible
    await expect(voting.locators.upvoteButton).toBeVisible();
Act
  1. Upvote current
    await voting.upvoteCurrent();
  2. Upvote current
    await voting.upvoteCurrent();
  3. Submit votes
    await voting.submitVotes();
Assert
  1. voted alert is visible
    await expect(voting.locators.votedAlert).toBeVisible();
Act
  1. Set plus voting active false
    await setPlusVotingActive(page, false);
  2. Open the plus voting page
    await voting.goto();
Assert
  1. voting starts info is visible
    await expect(voting.locators.votingStartsInfo).toBeVisible();
Ssuggested
Plus suggestions page
Act
  1. Open the plus suggestions page
    await suggestions.goto();
Notification popover
Act
  1. Open
    await notifications.open();
Assert
  1. notification “You were suggested to +1” is visible
    await expect(
    	notifications.notification("You were suggested to +1"),
    ).toBeVisible();
Act
  1. Close
    await notifications.close();
Plus suggestions page
Act
  1. Delete own suggestion
    await suggestions.deleteOwnSuggestion();
Assert
  1. no suggestions is visible
    await expect(suggestions.locators.noSuggestions).toBeVisible();
Arrange
  1. completedVoting = lastCompletedVoting(new Date())
    const completedVoting = lastCompletedVoting(new Date());
  2. Create user discord name “FalterFred” discord id “1000000000000000002” profile null → failer
    const failer = await factories.UserFactory.create({
    	discordName: FAILER_NAME,
    	discordId: FAILER_DISCORD_ID,
    	profile: null,
    });
  3. Create plus suggestion author Sendou suggested id suggested.id tier 1 ...completedVoting
    await factories.PlusSuggestionFactory.create({
    	authorId: ADMIN_ID,
    	suggestedId: suggested.id,
    	tier: 1,
    	...completedVoting,
    });
  4. Create plus vote author Sendou voted N-ZAP score PLUS_UPVOTE
    await factories.PlusVoteFactory.create({
    	authorId: ADMIN_ID,
    	votedId: NZAP_TEST_ID,
    	score: PLUS_UPVOTE,
    });
  5. Create plus vote author Sendou voted id suggested.id score PLUS_UPVOTE
    await factories.PlusVoteFactory.create({
    	authorId: ADMIN_ID,
    	votedId: suggested.id,
    	score: PLUS_UPVOTE,
    });
  6. Create plus vote author Sendou voted id failer.id score PLUS_DOWNVOTE
    await factories.PlusVoteFactory.create({
    	authorId: ADMIN_ID,
    	votedId: failer.id,
    	score: PLUS_DOWNVOTE,
    });
  7. Sync tiers plus vote
    await factories.PlusVoteFactory.syncTiers();
Plus voting results page
Act
  1. Open the plus voting results page
    await results.goto();
Assert
  1. heading is visible
    await expect(results.locators.heading).toBeVisible();
  2. own result tier 1 passed true is visible
    await expect(results.ownResult({ tier: 1, passed: true })).toBeVisible();
  3. passed heading 2 is visible
    await expect(results.passedHeading(2)).toBeVisible();
  4. failed heading 1 is visible
    await expect(results.failedHeading(1)).toBeVisible();
  5. user result “N-ZAP” is visible
    await expect(results.userResult("N-ZAP")).toBeVisible();
  6. suggested marker “SuggestedSue” is visible
    await expect(results.suggestedMarker(SUGGESTED_NAME)).toBeVisible();
  7. user result “FalterFred” is visible
    await expect(results.userResult(FAILER_NAME)).toBeVisible();
Act
  1. Get “/plus/list”, headers "Lohi token" process.env.LOHI_TOKEN ?? "salmon" → plusListResponse
    const plusListResponse = await page.request.get("/plus/list", {
    	headers: { "Lohi-Token": process.env.LOHI_TOKEN ?? "salmon" },
    });
Assert
  1. plusListResponse.ok() is true
    expect(plusListResponse.ok()).toBe(true);
  2. plusList = plusListResponse.json()
    const plusList = (await plusListResponse.json()) as {
    	users: Record<string, number>;
    };
  3. plusList.users[SUGGESTED_DISCORD_ID] is 1
    expect(plusList.users[SUGGESTED_DISCORD_ID]).toBe(1);
  4. a non-suggested member who fails the vote drops one tier instead of out

    plusList.users[FAILER_DISCORD_ID] is 2
    expect(plusList.users[FAILER_DISCORD_ID]).toBe(2);
Source
test("member suggests a user, members vote and results decide the memberships", async ({
	page,
	factories,
}) => {
	// a long flow: runs past two thirds of the default timeout under load
	test.slow();
	await factories.UserFactory.grant(ADMIN_ID, { plusTier: 1 });
	await factories.UserFactory.grant(NZAP_TEST_ID, { plusTier: 1 });
	const suggested = await factories.UserFactory.create({
		discordName: SUGGESTED_NAME,
		discordId: SUGGESTED_DISCORD_ID,
		profile: null,
	});

	await impersonate(page);

	const suggestions = new PlusSuggestionsPage(page);
	await suggestions.goto();
	await expect(suggestions.locators.noSuggestions).toBeVisible();

	const newSuggestion = new NewSuggestionPage(page);
	await newSuggestion.goto();
	await expect(newSuggestion.locators.heading).toBeVisible();
	await newSuggestion.suggest({
		username: SUGGESTED_NAME,
		comment: SUGGESTION_TEXT,
	});

	await expect(suggestions.suggestedUser(SUGGESTED_NAME)).toBeVisible();
	await suggestions.openComments(1);
	await expect(suggestions.comment(SUGGESTION_TEXT)).toBeVisible();

	await suggestions.editComment(SUGGESTION_TEXT, EDITED_SUGGESTION_TEXT);
	await suggestions.openComments(1);
	await expect(suggestions.comment(EDITED_SUGGESTION_TEXT)).toBeVisible();

	await impersonate(page, NZAP_TEST_ID);
	await suggestions.goto();
	await suggestions.locators.commentLink.click();

	const commentPage = new SuggestionCommentPage(page);
	await expect(
		commentPage.heading({ username: SUGGESTED_NAME, tier: 1 }),
	).toBeVisible();
	await commentPage.comment(FOLLOW_UP_COMMENT_TEXT);

	await suggestions.openComments(2);
	await expect(suggestions.comment(FOLLOW_UP_COMMENT_TEXT)).toBeVisible();

	await suggestions.deleteComment(FOLLOW_UP_COMMENT_TEXT);
	await expect(suggestions.commentsSummary(1)).toBeVisible();

	await setPlusVotingActive(page, true);
	await runRoutine(page, "NotifyPlusServerVoting");

	await suggestions.goto();
	const notifications = new NotificationPopover(page);
	await notifications.open();
	await notifications.openNotification("Plus Server voting of season");
	await expect(page).toHaveURL(PLUS_VOTING_PAGE);

	const voting = new PlusVotingPage(page);
	await expect(voting.locators.upvoteButton).toBeVisible();
	await voting.upvoteCurrent();
	await voting.upvoteCurrent();
	await voting.submitVotes();
	await expect(voting.locators.votedAlert).toBeVisible();

	await setPlusVotingActive(page, false);
	await voting.goto();
	await expect(voting.locators.votingStartsInfo).toBeVisible();

	await impersonate(page, suggested.id);
	await suggestions.goto();
	await notifications.open();
	await expect(
		notifications.notification("You were suggested to +1"),
	).toBeVisible();
	await notifications.close();

	await suggestions.deleteOwnSuggestion();
	await expect(suggestions.locators.noSuggestions).toBeVisible();

	const completedVoting = lastCompletedVoting(new Date());
	const failer = await factories.UserFactory.create({
		discordName: FAILER_NAME,
		discordId: FAILER_DISCORD_ID,
		profile: null,
	});
	await factories.PlusSuggestionFactory.create({
		authorId: ADMIN_ID,
		suggestedId: suggested.id,
		tier: 1,
		...completedVoting,
	});
	await factories.PlusVoteFactory.create({
		authorId: ADMIN_ID,
		votedId: NZAP_TEST_ID,
		score: PLUS_UPVOTE,
	});
	await factories.PlusVoteFactory.create({
		authorId: ADMIN_ID,
		votedId: suggested.id,
		score: PLUS_UPVOTE,
	});
	await factories.PlusVoteFactory.create({
		authorId: ADMIN_ID,
		votedId: failer.id,
		score: PLUS_DOWNVOTE,
	});
	await factories.PlusVoteFactory.syncTiers();

	const results = new PlusVotingResultsPage(page);
	await results.goto();
	await expect(results.locators.heading).toBeVisible();
	await expect(results.ownResult({ tier: 1, passed: true })).toBeVisible();
	await expect(results.passedHeading(2)).toBeVisible();
	await expect(results.failedHeading(1)).toBeVisible();
	await expect(results.userResult("N-ZAP")).toBeVisible();
	await expect(results.suggestedMarker(SUGGESTED_NAME)).toBeVisible();
	await expect(results.userResult(FAILER_NAME)).toBeVisible();

	const plusListResponse = await page.request.get("/plus/list", {
		headers: { "Lohi-Token": process.env.LOHI_TOKEN ?? "salmon" },
	});
	expect(plusListResponse.ok()).toBe(true);
	const plusList = (await plusListResponse.json()) as {
		users: Record<string, number>;
	};
	expect(plusList.users[SUGGESTED_DISCORD_ID]).toBe(1);
	// a non-suggested member who fails the vote drops one tier instead of out
	expect(plusList.users[FAILER_DISCORD_ID]).toBe(2);
})

user without a plus tier cannot suggest, comment or vote

Renders/plus/plus/suggestions/plus/suggestions/comment/:tier/:userId/plus/suggestions/new/plus/voting

Setup
Arrange
  1. Grant user Sendou plus tier 1
    await factories.UserFactory.grant(ADMIN_ID, { plusTier: 1 });
  2. Create user discord name “SuggestedSue” discord id “1000000000000000001” profile null → suggested
    const suggested = await factories.UserFactory.create({
    	discordName: SUGGESTED_NAME,
    	discordId: SUGGESTED_DISCORD_ID,
    	profile: null,
    });
  3. Create plus suggestion author Sendou suggested id suggested.id tier 1 text “Great player and even better person”
    await factories.PlusSuggestionFactory.create({
    	authorId: ADMIN_ID,
    	suggestedId: suggested.id,
    	tier: 1,
    	text: SUGGESTION_TEXT,
    });
NN-ZAP
Plus suggestions page
Act
  1. Open the plus suggestions page
    await suggestions.goto();
Assert
  1. suggested user “SuggestedSue” is visible
    await expect(suggestions.suggestedUser(SUGGESTED_NAME)).toBeVisible();
  2. comment link is not visible
    await isNotVisible(suggestions.locators.commentLink);
New suggestion page
Act
  1. Open the new suggestion page
    await newSuggestion.goto();
Plus suggestions page
Assert
  1. no permissions alert is visible
    await expect(suggestions.locators.noPermissionsAlert).toBeVisible();
  2. heading is not visible
    await isNotVisible(newSuggestion.locators.heading);
Suggestion comment page
Act
  1. Open the suggestion comment page tier 1 user id suggested.id
    await commentPage.goto({ tier: 1, userId: suggested.id });
Assert
  1. the page URL is not /comment/
    await expect(page).not.toHaveURL(/comment/);
  2. heading username “SuggestedSue” tier 1 is not visible
    await isNotVisible(
    	commentPage.heading({ username: SUGGESTED_NAME, tier: 1 }),
    );
Act
  1. Set plus voting active true
    await setPlusVotingActive(page, true);
Plus voting page
Act
  1. Open the plus voting page
    await voting.goto();
Assert
  1. voting ongoing info is visible
    await expect(voting.locators.votingOngoingInfo).toBeVisible();
  2. upvote button is not visible
    await isNotVisible(voting.locators.upvoteButton);
Source
test("user without a plus tier cannot suggest, comment or vote", async ({
	page,
	factories,
}) => {
	await factories.UserFactory.grant(ADMIN_ID, { plusTier: 1 });
	const suggested = await factories.UserFactory.create({
		discordName: SUGGESTED_NAME,
		discordId: SUGGESTED_DISCORD_ID,
		profile: null,
	});
	await factories.PlusSuggestionFactory.create({
		authorId: ADMIN_ID,
		suggestedId: suggested.id,
		tier: 1,
		text: SUGGESTION_TEXT,
	});

	await impersonate(page, NZAP_TEST_ID);

	const suggestions = new PlusSuggestionsPage(page);
	await suggestions.goto();
	await expect(suggestions.suggestedUser(SUGGESTED_NAME)).toBeVisible();
	await isNotVisible(suggestions.locators.commentLink);

	const newSuggestion = new NewSuggestionPage(page);
	await newSuggestion.goto();
	await expect(suggestions.locators.noPermissionsAlert).toBeVisible();
	await isNotVisible(newSuggestion.locators.heading);

	const commentPage = new SuggestionCommentPage(page);
	await commentPage.goto({ tier: 1, userId: suggested.id });
	await expect(page).not.toHaveURL(/comment/);
	await isNotVisible(
		commentPage.heading({ username: SUGGESTED_NAME, tier: 1 }),
	);

	await setPlusVotingActive(page, true);

	const voting = new PlusVotingPage(page);
	await voting.goto();
	await expect(voting.locators.votingOngoingInfo).toBeVisible();
	await isNotVisible(voting.locators.upvoteButton);
})

Renders/plus/plus/voting

Setup
Arrange
  1. Grant user Sendou plus tier 1
    await factories.UserFactory.grant(ADMIN_ID, { plusTier: 1 });
  2. Grant user N-ZAP plus tier 1
    await factories.UserFactory.grant(NZAP_TEST_ID, { plusTier: 1 });
  3. For each user of factories.UserFactory.createMany(2)
    for (const user of await factories.UserFactory.createMany(2)) {
    	await factories.UserFactory.grant(user.id, { plusTier: 1 });
    }
    1. Grant user user.id plus tier 1
      await factories.UserFactory.grant(user.id, { plusTier: 1 });
SSendou
Act
  1. Set plus voting active true
    await setPlusVotingActive(page, true);
Plus voting page
Act
  1. Open the plus voting page
    await voting.goto();
Assert
  1. progress voted 0 total 3 is visible
    await expect(voting.progress({ voted: 0, total: 3 })).toBeVisible();
Act
  1. Vote with key “upvote”
    await voting.voteWithKey("upvote");
Assert
  1. progress voted 1 total 3 is visible
    await expect(voting.progress({ voted: 1, total: 3 })).toBeVisible();
Global search dialog
Act
  1. Open with shortcut
    await search.openWithShortcut();
  2. Type “sk”
    await search.type("sk");
Assert
  1. input has value “sk”
    await expect(search.locators.input).toHaveValue("sk");
Act
  1. Close
    await search.close();
Plus voting page
Assert
  1. progress voted 1 total 3 is visible
    await expect(voting.progress({ voted: 1, total: 3 })).toBeVisible();
Act
  1. Vote with key “downvote”
    await voting.voteWithKey("downvote");
Assert
  1. progress voted 2 total 3 is visible
    await expect(voting.progress({ voted: 2, total: 3 })).toBeVisible();
Source
test("votes with the S and K keys, but not while using global search", async ({
	page,
	factories,
}) => {
	await factories.UserFactory.grant(ADMIN_ID, { plusTier: 1 });
	await factories.UserFactory.grant(NZAP_TEST_ID, { plusTier: 1 });
	for (const user of await factories.UserFactory.createMany(2)) {
		await factories.UserFactory.grant(user.id, { plusTier: 1 });
	}

	await impersonate(page);
	await setPlusVotingActive(page, true);

	const voting = new PlusVotingPage(page);
	await voting.goto();
	await expect(voting.progress({ voted: 0, total: 3 })).toBeVisible();

	await voting.voteWithKey("upvote");
	await expect(voting.progress({ voted: 1, total: 3 })).toBeVisible();

	const search = new GlobalSearchDialog(page);
	await search.openWithShortcut();
	await search.type("sk");
	await expect(search.locators.input).toHaveValue("sk");
	await search.close();
	await expect(voting.progress({ voted: 1, total: 3 })).toBeVisible();

	await voting.voteWithKey("downvote");
	await expect(voting.progress({ voted: 2, total: 3 })).toBeVisible();
})