Posting A post is made as a team or as a pick-up of users the author picks, who are saved for later posts. Its card shows the start window and the tournament whose maps are played, and marks a post only an association can see.
a post limited to an association is marked as such and its owner can delete it Renders/ /scrims /scrims/new
Anything adder New scrim post page Scrims page Arrange
Create named users “Pickup One” , “Pickup Two” , “Pickup Three”
await createNamedUsers (factories, PICKUP_NAMES );Create association user N-ZAP name “Inkling Alliance”
await factories.AssociationFactory .create ({
userId: NZAP_TEST_ID ,
name: ASSOCIATION_NAME ,
});Act
Go to “/”
await navigate ({ page, url: "/" });Anything adder Act
Add “scrimPost”
await new AnythingAdder (page).add ("scrimPost" );New scrim post page Act
Select pickup users “Pickup One” , “Pickup Two” , “Pickup Three”
await newPost.selectPickupUsers (PICKUP_NAMES );Select visibility “Inkling Alliance”
await newPost.selectVisibility (ASSOCIATION_NAME );Fill Text with “Test scrim”
await newPost.form.fill ("postText" , "Test scrim" );Save
await newPost.save ();Scrims page Assert
limited visibility popover is visible
await expect (scrims.locators.limitedVisibilityPopover).toBeVisible ();Act
Delete first post
await scrims.deleteFirstPost ();Assert
delete buttons count is 0
await expect (scrims.locators.deleteButtons).toHaveCount (0 );Source test ("a post limited to an association is marked as such and its owner can delete it" , async ({
page,
factories,
}) => {
await createNamedUsers (factories, PICKUP_NAMES );
await factories.AssociationFactory .create ({
userId: NZAP_TEST_ID ,
name: ASSOCIATION_NAME ,
});
await impersonate (page, NZAP_TEST_ID );
await navigate ({ page, url: "/" });
await new AnythingAdder (page).add ("scrimPost" );
const newPost = new NewScrimPostPage (page);
await newPost.selectPickupUsers (PICKUP_NAMES );
await newPost.selectVisibility (ASSOCIATION_NAME );
await newPost.form.fill ("postText" , "Test scrim" );
await newPost.save ();
const scrims = new ScrimsPage (page);
await expect (scrims.locators.limitedVisibilityPopover).toBeVisible ();
await scrims.deleteFirstPost ();
await expect (scrims.locators.deleteButtons).toHaveCount (0 );
})reuses a pick-up saved from an earlier scrim post Renders/scrims /scrims/new
New scrim post page Scrims page Arrange
Create named users “Pickup One” , “Pickup Two” , “Pickup Three”
await createNamedUsers (factories, PICKUP_NAMES );New scrim post page Act
Open the new scrim post page
await newPost.goto ();Select pickup users “Pickup One” , “Pickup Two” , “Pickup Three”
await newPost.selectPickupUsers (PICKUP_NAMES );Save
await newPost.save ();Open the new scrim post page
await newPost.goto ();Select saved pickup “Pickup One” , “Pickup Two” , “Pickup Three”
await newPost.selectSavedPickup (PICKUP_NAMES );Assert
For each [index, userName] of PICKUP_NAMES .entries ()
for (const [index, userName] of PICKUP_NAMES .entries ()) {
await expect (newPost.pickupUser (index + 2 )).toContainText (userName);
}pickup user index + 2 contains userName
await expect (newPost.pickupUser (index + 2 )).toContainText (userName);Act
Save
await newPost.save ();Scrims page Assert
delete buttons count is 2
await expect (scrims.locators.deleteButtons).toHaveCount (2 );Source test ("reuses a pick-up saved from an earlier scrim post" , async ({
page,
factories,
}) => {
await createNamedUsers (factories, PICKUP_NAMES );
await impersonate (page, NZAP_TEST_ID );
const newPost = new NewScrimPostPage (page);
await newPost.goto ();
await newPost.selectPickupUsers (PICKUP_NAMES );
await newPost.save ();
await newPost.goto ();
await newPost.selectSavedPickup (PICKUP_NAMES );
for (const [index, userName] of PICKUP_NAMES .entries ()) {
await expect (newPost.pickupUser (index + 2 )).toContainText (userName);
}
await newPost.save ();
const scrims = new ScrimsPage (page);
await expect (scrims.locators.deleteButtons).toHaveCount (2 );
})a post's start window and tournament maps show on its card Renders/scrims /scrims/new
New scrim post page Scrims page Arrange
Create team for Sendou
await createTeamFor (factories, ADMIN_ID );Create tournament
await createTournament (factories);New scrim post page Act
Open the new scrim post page
await newPost.goto ();Set Start to tomorrowEvening ()
await newPost.form.setDateTime ("at" , tomorrowEvening ());Select “+2 hours” for Start time flexibility
await newPost.form.select ("rangeEnd" , "+2hours" );Select tournament maps “Swim or Sink”
await newPost.selectTournamentMaps (TOURNAMENT_NAME );Save
await newPost.save ();Scrims page Assert
post “+2h” is visible
await expect (scrims.post ("+2h" )).toBeVisible ();tournament popover is visible
await expect (scrims.locators.tournamentPopover).toBeVisible ();Source test ("a post's start window and tournament maps show on its card" , async ({
page,
factories,
}) => {
await createTeamFor (factories, ADMIN_ID );
await createTournament (factories);
await impersonate (page, ADMIN_ID );
const newPost = new NewScrimPostPage (page);
await newPost.goto ();
await newPost.form.setDateTime ("at" , tomorrowEvening ());
await newPost.form.select ("rangeEnd" , "+2hours" );
await newPost.selectTournamentMaps (TOURNAMENT_NAME );
await newPost.save ();
const scrims = new ScrimsPage (page);
await expect (scrims.post ("+2h" )).toBeVisible ();
await expect (scrims.locators.tournamentPopover).toBeVisible ();
})Requests Other teams request a post from the Available tab, picking the start when the post has a start window, and can withdraw the request while it is pending. The post's owner is notified of each request.
requests a post and withdraws the request Renders/scrims
Scrims page Scrim request modal Scrims page Arrange
Repeat for (let postNth = 0 ; postNth < 2 ; postNth++)
for (let postNth = 0 ; postNth < 2 ; postNth++) {
await factories.ScrimPostFactory .create ({
users: await createGroup (factories),
});
}Create scrim post users createGroup (factories)
await factories.ScrimPostFactory .create ({
users: await createGroup (factories),
});Create team for N-ZAP
await createTeamFor (factories, NZAP_TEST_ID );Scrims page Act
Open the scrims page
await scrims.goto ();Open tab “available”
await scrims.openTab ("available" );Assert
request buttons count is 2
await expect (scrims.locators.requestButtons).toHaveCount (2 );Act
Request first → request
const request = await scrims.requestFirst ();Scrim request modal Act
Send
await request.send ();Scrims page Assert
request buttons count is 1
await expect (scrims.locators.requestButtons).toHaveCount (1 );Act
Show pending requests
await scrims.showPendingRequests ();Cancel pending request
await scrims.cancelPendingRequest ();Assert
request buttons count is 2
await expect (scrims.locators.requestButtons).toHaveCount (2 );Source test ("requests a post and withdraws the request" , async ({
page,
factories,
}) => {
for (let postNth = 0 ; postNth < 2 ; postNth++) {
await factories.ScrimPostFactory .create ({
users: await createGroup (factories),
});
}
await createTeamFor (factories, NZAP_TEST_ID );
await impersonate (page, NZAP_TEST_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
await scrims.openTab ("available" );
await expect (scrims.locators.requestButtons).toHaveCount (2 );
const request = await scrims.requestFirst ();
await request.send ();
await expect (scrims.locators.requestButtons).toHaveCount (1 );
await scrims.showPendingRequests ();
await scrims.cancelPendingRequest ();
await expect (scrims.locators.requestButtons).toHaveCount (2 );
})a request to a post with a start window picks the start and can carry a message Renders/scrims
N-ZAP requests it with a pick-up, a start and a message Sendou is notified and sees the message Arrange
at = tomorrowEvening ()
const at = tomorrowEvening ();Create scrim post users createGroup (factories, ADMIN_ID ) starts at dateToDatabaseTimestamp (at) range ends at dateToDatabaseTimestamp (addHours (at, 2 )) is scheduled for future true
await factories.ScrimPostFactory .create ({
users: await createGroup (factories, ADMIN_ID ),
startsAt: dateToDatabaseTimestamp (at),
rangeEndsAt: dateToDatabaseTimestamp (addHours (at, 2 )),
isScheduledForFuture: true ,
});Create named users “Pickup One” , “Pickup Two” , “Pickup Three”
await createNamedUsers (factories, PICKUP_NAMES );1 N-ZAP requests it with a pick-up, a start and a message
Scrims page Act
Open the scrims page
await scrims.goto ();Open tab “available”
await scrims.openTab ("available" );Request first → request
const request = await scrims.requestFirst ();Scrim request modal Act
Select pickup users “Pickup One” , “Pickup Two” , “Pickup Three”
await request.selectPickupUsers (PICKUP_NAMES );Select start time 1
await request.selectStartTime (1 );Fill Message with “Ready to scrim! Let's do this.”
await request.form.fill ("message" , REQUEST_MESSAGE );Send
await request.send ();2 Sendou is notified and sees the message
Scrims page Act
Open the scrims page
await scrims.goto ();Notification popover Act
Open
await notifications.open ();Assert
notification “N-ZAP requested a scrim” is visible
await expect (
notifications.notification ("N-ZAP requested a scrim" ),
).toBeVisible ();Act
Close
await notifications.close ();Scrims page Assert
post “Ready to scrim! Let's do this.” is visible
await expect (scrims.post (REQUEST_MESSAGE )).toBeVisible ();Source test ("a request to a post with a start window picks the start and can carry a message" , async ({
page,
factories,
}) => {
const at = tomorrowEvening ();
await factories.ScrimPostFactory .create ({
users: await createGroup (factories, ADMIN_ID ),
startsAt: dateToDatabaseTimestamp (at),
rangeEndsAt: dateToDatabaseTimestamp (addHours (at, 2 )),
isScheduledForFuture: true ,
});
await createNamedUsers (factories, PICKUP_NAMES );
await test.step ("N-ZAP requests it with a pick-up, a start and a message" , async () => {
await impersonate (page, NZAP_TEST_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
await scrims.openTab ("available" );
const request = await scrims.requestFirst ();
await request.selectPickupUsers (PICKUP_NAMES );
await request.selectStartTime (1 );
await request.form.fill ("message" , REQUEST_MESSAGE );
await request.send ();
});
await test.step ("Sendou is notified and sees the message" , async () => {
await impersonate (page, ADMIN_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
const notifications = new NotificationPopover (page);
await notifications.open ();
await expect (
notifications.notification ("N-ZAP requested a scrim" ),
).toBeVisible ();
await notifications.close ();
await expect (scrims.post (REQUEST_MESSAGE )).toBeVisible ();
});
})Accepting Accepting a request books the scrim: it moves to the Booked tab with a page of its own, the requester is notified and the owner's other pending posts starting within an hour of it are deleted.
accepting resolves the request notification and notifies the requester Renders/ /scrims /scrims/:id
Scrims page Notification popover Scrims page Notification popover Scrims page Scrim page Notification popover Arrange
Create post with request owner Sendou requester N-ZAP → post
const post = await createPostWithRequest (factories, {
ownerUserId: ADMIN_ID ,
requesterUserId: NZAP_TEST_ID ,
});Create notification notification type “SCRIM_NEW_REQUEST” meta from N-ZAP from username “N-ZAP” scrim post id post.id users user Sendou
await factories.NotificationFactory .create ({
notification: {
type : "SCRIM_NEW_REQUEST" ,
meta: {
fromUserId: NZAP_TEST_ID ,
fromUsername: "N-ZAP" ,
scrimPostId: post.id,
},
},
users: [{ userId: ADMIN_ID }],
});Scrims page Act
Open the scrims page
await scrims.goto ();Notification popover Assert
bell dot is visible
await expect (notifications.locators.bellDot).toBeVisible ();Scrims page Act
Accept first request
await scrims.acceptFirstRequest ();Notification popover Assert
accepting settled the post, resolving the request notification without the bell having been opened
bell dot is hidden
await expect (notifications.locators.bellDot).toBeHidden ();Scrims page Act
Open tab “booked”
await scrims.openTab ("booked" );Assert
contact links count is 1
await expect (scrims.locators.contactLinks).toHaveCount (1 );Act
Open first booked scrim → scrim
const scrim = await scrims.openFirstBookedScrim ();Scrim page Assert
subtitle is visible
await expect (scrim.locators.subtitle).toBeVisible ();Act
Go to “/”
await navigate ({ page, url: "/" });Notification popover Act
Open
await notifications.open ();Open notification “New scrim scheduled vs.”
await notifications.openNotification ("New scrim scheduled vs." );Assert
the page URL is scrimPage (post.id)
await expect (page).toHaveURL (scrimPage (post.id));Source test ("accepting resolves the request notification and notifies the requester" , async ({
page,
factories,
}) => {
const post = await createPostWithRequest (factories, {
ownerUserId: ADMIN_ID ,
requesterUserId: NZAP_TEST_ID ,
});
await factories.NotificationFactory .create ({
notification: {
type : "SCRIM_NEW_REQUEST" ,
meta: {
fromUserId: NZAP_TEST_ID ,
fromUsername: "N-ZAP" ,
scrimPostId: post.id,
},
},
users: [{ userId: ADMIN_ID }],
});
await impersonate (page, ADMIN_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
const notifications = new NotificationPopover (page);
await expect (notifications.locators.bellDot).toBeVisible ();
await scrims.acceptFirstRequest ();
// accepting settled the post, resolving the request notification without
// the bell having been opened
await expect (notifications.locators.bellDot).toBeHidden ();
await scrims.openTab ("booked" );
await expect (scrims.locators.contactLinks).toHaveCount (1 );
const scrim = await scrims.openFirstBookedScrim ();
await expect (scrim.locators.subtitle).toBeVisible ();
// the requester got notified of the scheduled scrim, linking to its page
await impersonate (page, NZAP_TEST_ID );
await navigate ({ page, url: "/" });
await notifications.open ();
await notifications.openNotification ("New scrim scheduled vs." );
await expect (page).toHaveURL (scrimPage (post.id));
})auto-cancels overlapping pending scrims when a scrim is booked Renders/scrims /scrims/new
Scrims page Scrim request modal Scrims page Arrange
Create team for Sendou
await createTeamFor (factories, ADMIN_ID );Create team for N-ZAP
await createTeamFor (factories, NZAP_TEST_ID );bookedAt = tomorrowEvening ()
const bookedAt = tomorrowEvening ();within ±1h of the booked time
overlappingAt = setMinutes (bookedAt, 30 )
const overlappingAt = setMinutes (bookedAt, 30 );farAwayAt = setHours (bookedAt, 22 )
const farAwayAt = setHours (bookedAt, 22 );Act
For each [at, text] of bookedAt, “Booked post” , overlappingAt, “Overlapping post” , farAwayAt, “Far away post”
for (const [at, text] of [
[bookedAt, "Booked post" ],
[overlappingAt, "Overlapping post" ],
[farAwayAt, "Far away post" ],
] as const ) {
await newPost.goto ();
await newPost.form.setDateTime ("at" , at);
await newPost.form.fill ("postText" , text);
await newPost.save ();
}Open the new scrim post page
await newPost.goto ();Set Start to at
await newPost.form.setDateTime ("at" , at);Fill Text with text
await newPost.form.fill ("postText" , text);Save
await newPost.save ();Scrims page Act
Open the scrims page
await scrims.goto ();Open tab “available”
await scrims.openTab ("available" );Request first → request
const request = await scrims.requestFirst ();Scrim request modal Act
Send
await request.send ();Scrims page Act
Open the scrims page
await scrims.goto ();Accept first request
await scrims.acceptFirstRequest ();Open tab “owned”
await scrims.openTab ("owned" );Assert
post “Far away post” is visible
await expect (scrims.post ("Far away post" )).toBeVisible ();post “Overlapping post” is not visible
await isNotVisible (scrims.post ("Overlapping post" ));Source test ("auto-cancels overlapping pending scrims when a scrim is booked" , async ({
page,
factories,
}) => {
await createTeamFor (factories, ADMIN_ID );
await createTeamFor (factories, NZAP_TEST_ID );
const bookedAt = tomorrowEvening ();
// within ±1h of the booked time
const overlappingAt = setMinutes (bookedAt, 30 );
// outside the ±1h window
const farAwayAt = setHours (bookedAt, 22 );
await impersonate (page, ADMIN_ID );
const newPost = new NewScrimPostPage (page);
for (const [at, text] of [
[bookedAt, "Booked post" ],
[overlappingAt, "Overlapping post" ],
[farAwayAt, "Far away post" ],
] as const ) {
await newPost.goto ();
await newPost.form.setDateTime ("at" , at);
await newPost.form.fill ("postText" , text);
await newPost.save ();
}
// N-ZAP requests the earliest (soon-to-be-booked) post
await impersonate (page, NZAP_TEST_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
await scrims.openTab ("available" );
const request = await scrims.requestFirst ();
await request.send ();
// the author accepts the request, booking the scrim
await impersonate (page, ADMIN_ID );
await scrims.goto ();
await scrims.acceptFirstRequest ();
await scrims.openTab ("owned" );
await expect (scrims.post ("Far away post" )).toBeVisible ();
await isNotVisible (scrims.post ("Overlapping post" ));
})Canceling A booked scrim is canceled from its page with a reason, and is then shown as canceled.
cancels a scrim and shows canceled status Renders/scrims /scrims/:id
Scrims page Scrim page Scrims page Arrange
Create post with request owner Sendou at addHours (new Date (), 4 )
await createPostWithRequest (factories, {
ownerUserId: ADMIN_ID ,
at: addHours (new Date (), 4 ),
});Scrims page Act
Open the scrims page
await scrims.goto ();accepting is what makes the scrim's own page accessible
Accept first request
await scrims.acceptFirstRequest ();Open tab “booked”
await scrims.openTab ("booked" );Open first booked scrim → scrim
const scrim = await scrims.openFirstBookedScrim ();Scrim page Act
Cancel “Oops something came up”
await scrim.cancel ("Oops something came up" );Scrims page Act
Open the scrims page
await scrims.goto ();Assert
canceled label is visible
await expect (scrims.locators.canceledLabel).toBeVisible ();Source test ("cancels a scrim and shows canceled status" , async ({
page,
factories,
}) => {
await createPostWithRequest (factories, {
ownerUserId: ADMIN_ID ,
at: addHours (new Date (), 4 ),
});
await impersonate (page, ADMIN_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
// accepting is what makes the scrim's own page accessible
await scrims.acceptFirstRequest ();
await scrims.openTab ("booked" );
const scrim = await scrims.openFirstBookedScrim ();
await scrim.cancel ("Oops something came up" );
await scrims.goto ();
await expect (scrims.locators.canceledLabel).toBeVisible ();
})Filters Filters (here LUTI divisions) narrow the Available tab and can be saved as the user's default. Once the user edits the filters the page's own wins over the saved default.
filters by div and sets the filter as default Renders/scrims
Scrims page Arrange
Create scrim post users createGroup (factories) max div serializeLutiDiv ("1" ) min div serializeLutiDiv ("2" )
await factories.ScrimPostFactory .create ({
users: await createGroup (factories),
maxDiv: serializeLutiDiv ("1" ),
minDiv: serializeLutiDiv ("2" ),
});Scrims page Act
Open the scrims page
await scrims.goto ();Open tab “available”
await scrims.openTab ("available" );Assert
request buttons count is 1
await expect (scrims.locators.requestButtons).toHaveCount (1 );Act
a div range the post's own range falls outside of
Filter by divs max “5” min “6”
await scrims.filterByDivs ({ max: "5" , min: "6" });Assert
request buttons count is 0
await expect (scrims.locators.requestButtons).toHaveCount (0 );Act
Save filters as default
await scrims.saveFiltersAsDefault ();Open the scrims page
await scrims.goto ();Open tab “available”
await scrims.openTab ("available" );Assert
remembers selection via user preferences
request buttons count is 0
await expect (scrims.locators.requestButtons).toHaveCount (0 );Act
Remove divs filter
await scrims.removeDivsFilter ();Assert
removing the filter sticks instead of falling back to the saved default
request buttons count is 1
await expect (scrims.locators.requestButtons).toHaveCount (1 );Act
Reload
await scrims.reload ();Assert
request buttons count is 1
await expect (scrims.locators.requestButtons).toHaveCount (1 );Source test ("filters by div and sets the filter as default" , async ({
page,
factories,
}) => {
await factories.ScrimPostFactory .create ({
users: await createGroup (factories),
maxDiv: serializeLutiDiv ("1" ),
minDiv: serializeLutiDiv ("2" ),
});
await impersonate (page, NZAP_TEST_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
await scrims.openTab ("available" );
await expect (scrims.locators.requestButtons).toHaveCount (1 );
// a div range the post's own range falls outside of
await scrims.filterByDivs ({ max: "5" , min: "6" });
await expect (scrims.locators.requestButtons).toHaveCount (0 );
await scrims.saveFiltersAsDefault ();
await scrims.goto ();
await scrims.openTab ("available" );
// remembers selection via user preferences
await expect (scrims.locators.requestButtons).toHaveCount (0 );
await scrims.removeDivsFilter ();
// removing the filter sticks instead of falling back to the saved default
await expect (scrims.locators.requestButtons).toHaveCount (1 );
await scrims.reload ();
await expect (scrims.locators.requestButtons).toHaveCount (1 );
})Map-by-map Once booked, each side submits a map list (the post's tournament or a map pool) and maps are generated one at a time from the lists, each reported map generating the next. The latest report can be undone and the current map swapped for a replay of the previous one. Stats count the reported maps from the viewer's side.
Renders/scrims/:id
Sendou submits the post's tournament as Alpha's list, generating the first map N-ZAP adds a map pool as Bravo's list Each reported winner generates the next map Undo un-reports the latest map and removes the one it generated Replay swaps the current map for the previous one Sendou swaps Alpha's list for a map pool Stats count the four reported maps Arrange
Create tournament → tournament
const tournament = await createTournament (factories);Create post with request owner Sendou requester N-ZAP maps tournament id tournament.id is accepted true → post
const post = await createPostWithRequest (factories, {
ownerUserId: ADMIN_ID ,
requesterUserId: NZAP_TEST_ID ,
mapsTournamentId: tournament.id,
isAccepted: true ,
});1 Sendou submits the post's tournament as Alpha's list, generating the first map
Scrim page Act
Open the scrim page post.id
await scrim.goto (post.id);Open tab “action”
await scrim.openTab ("action" );Assert
map list form is visible
await expect (scrim.locators.mapListForm).toBeVisible ();Act
the post's tournament is the author's default source, so no tournament search is needed; the first map list submitted collapses the map-list manager
Submit map list
await scrim.submitMapList ();Assert
report score button is visible
await expect (scrim.locators.reportScoreButton).toBeVisible ();Act
Open map list manager
await scrim.openMapListManager ();Assert
map list row “ALPHA” contains “Swim or Sink”
await expect (scrim.mapListRow ("ALPHA" )).toContainText (TOURNAMENT_NAME );2 N-ZAP adds a map pool as Bravo's list
Scrim page Act
Open the scrim page post.id
await scrim.goto (post.id);Open tab “action”
await scrim.openTab ("action" );Submit pool map list “sz:3a14000;tc:2c98000”
await scrim.submitPoolMapList (TEST_POOL_SERIALIZED );Assert
report score button is visible
await expect (scrim.locators.reportScoreButton).toBeVisible ();map list row “BRAVO” contains “Pool”
await expect (scrim.mapListRow ("BRAVO" )).toContainText ("Pool" );3 Each reported winner generates the next map
Scrim page Act
Report map winner “ALPHA”
await scrim.reportMapWinner ("ALPHA" );Assert
report score button is visible
await expect (scrim.locators.reportScoreButton).toBeVisible ();Act
Report map winner “BRAVO”
await scrim.reportMapWinner ("BRAVO" );Assert
report score button is visible
await expect (scrim.locators.reportScoreButton).toBeVisible ();4 Undo un-reports the latest map and removes the one it generated
Scrim page Act
Report map winner “ALPHA”
await scrim.reportMapWinner ("ALPHA" );Assert
undo map button is visible
await expect (scrim.locators.undoMapButton).toBeVisible ();Act
Undo map
await scrim.undoMap ();Assert
report score button is visible
await expect (scrim.locators.reportScoreButton).toBeVisible ();5 Replay swaps the current map for the previous one
Scrim page Act
Report map winner “BRAVO”
await scrim.reportMapWinner ("BRAVO" );Assert
replay map button is visible
await expect (scrim.locators.replayMapButton).toBeVisible ();Act
Replay map
await scrim.replayMap ();Report map winner “ALPHA”
await scrim.reportMapWinner ("ALPHA" );6 Sendou swaps Alpha's list for a map pool
Scrim page Act
Open the scrim page post.id
await scrim.goto (post.id);Open tab “action”
await scrim.openTab ("action" );Open map list manager
await scrim.openMapListManager ();Remove own map list “ALPHA”
await scrim.removeOwnMapList ("ALPHA" );Assert
map list form is visible
await expect (scrim.locators.mapListForm).toBeVisible ();Act
Submit pool map list “sz:3a14000;tc:2c98000”
await scrim.submitPoolMapList (TEST_POOL_SERIALIZED );Assert
map list row “ALPHA” contains “Pool”
await expect (scrim.mapListRow ("ALPHA" )).toContainText ("Pool" );7 Stats count the four reported maps
Scrim page Act
Open tab “stats”
await scrim.openTab ("stats" );Assert
stats root is visible
await expect (scrim.locators.statsRoot).toBeVisible ();Act
2 wins & 2 losses from Sendou's point of view
Show mode stats of all maps
await scrim.showModeStatsOfAllMaps ();Assert
reported map count is 4
expect (await scrim.reportedMapCount ()).toBe (4 );Source test ("plays a scrim map by map" , async ({ page, factories }) => {
const tournament = await createTournament (factories);
const post = await createPostWithRequest (factories, {
ownerUserId: ADMIN_ID ,
requesterUserId: NZAP_TEST_ID ,
mapsTournamentId: tournament.id,
isAccepted: true ,
});
const scrim = new ScrimPage (page);
await test.step ("Sendou submits the post's tournament as Alpha's list, generating the first map" , async () => {
await impersonate (page, ADMIN_ID );
await scrim.goto (post.id);
await scrim.openTab ("action" );
await expect (scrim.locators.mapListForm).toBeVisible ();
// the post's tournament is the author's default source, so no tournament search is
// needed; the first map list submitted collapses the map-list manager
await scrim.submitMapList ();
await expect (scrim.locators.reportScoreButton).toBeVisible ();
await scrim.openMapListManager ();
await expect (scrim.mapListRow ("ALPHA" )).toContainText (TOURNAMENT_NAME );
});
await test.step ("N-ZAP adds a map pool as Bravo's list" , async () => {
// N-ZAP has no list yet, so the map-list manager is already expanded on mount
await impersonate (page, NZAP_TEST_ID );
await scrim.goto (post.id);
await scrim.openTab ("action" );
await scrim.submitPoolMapList (TEST_POOL_SERIALIZED );
await expect (scrim.locators.reportScoreButton).toBeVisible ();
await expect (scrim.mapListRow ("BRAVO" )).toContainText ("Pool" );
});
await test.step ("Each reported winner generates the next map" , async () => {
await scrim.reportMapWinner ("ALPHA" );
await expect (scrim.locators.reportScoreButton).toBeVisible ();
await scrim.reportMapWinner ("BRAVO" );
await expect (scrim.locators.reportScoreButton).toBeVisible ();
});
await test.step ("Undo un-reports the latest map and removes the one it generated" , async () => {
await scrim.reportMapWinner ("ALPHA" );
await expect (scrim.locators.undoMapButton).toBeVisible ();
await scrim.undoMap ();
await expect (scrim.locators.reportScoreButton).toBeVisible ();
});
await test.step ("Replay swaps the current map for the previous one" , async () => {
await scrim.reportMapWinner ("BRAVO" );
await expect (scrim.locators.replayMapButton).toBeVisible ();
await scrim.replayMap ();
await scrim.reportMapWinner ("ALPHA" );
});
await test.step ("Sendou swaps Alpha's list for a map pool" , async () => {
await impersonate (page, ADMIN_ID );
await scrim.goto (post.id);
await scrim.openTab ("action" );
await scrim.openMapListManager ();
await scrim.removeOwnMapList ("ALPHA" );
await expect (scrim.locators.mapListForm).toBeVisible ();
await scrim.submitPoolMapList (TEST_POOL_SERIALIZED );
await expect (scrim.mapListRow ("ALPHA" )).toContainText ("Pool" );
});
await test.step ("Stats count the four reported maps" , async () => {
await scrim.openTab ("stats" );
await expect (scrim.locators.statsRoot).toBeVisible ();
// 2 wins & 2 losses from Sendou's point of view
await scrim.showModeStatsOfAllMaps ();
expect (await scrim.reportedMapCount ()).toBe (4 );
});
})Availability The members' weekly availability suggests starts when posting and shows how much of the viewer's roster could play each post. A slot one player short of a full team is still offered, as one to grab a sub for.
picks a start and its flexibility from the roster's shared free time Renders/scrims/new
New scrim post page Arrange
Create team for N-ZAP → { memberUserIds }
const { memberUserIds } = await createTeamFor (factories, NZAP_TEST_ID );evening = nextWeekSlot (WEDNESDAY , "18:00" , "23:00" )
const evening = nextWeekSlot (WEDNESDAY , "18:00" , "23:00" );For each userId of memberUserIds.slice (0 , memberUserIds.length - 1 )
for (const userId of memberUserIds.slice (0 , memberUserIds.length - 1 )) {
await factories.AvailabilityWeekFactory .create ({
userId,
weekStartsAt: nextWeek ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [evening],
});
}Create availability week userId week starts at nextWeek ().startsAt timezone MACHINE_TIMEZONE slots evening
await factories.AvailabilityWeekFactory .create ({
userId,
weekStartsAt: nextWeek ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [evening],
});New scrim post page Act
Open the new scrim post page
await newPost.goto ();Click next week toggle
await newPost.locators.nextWeekToggle.click ();Assert
the roster's last member never filled the week in, so the shared evening is one player short of a full team
schedule unknown is visible
await expect (newPost.locators.scheduleUnknown).toBeVisible ();slot = schedule slots
const slot = newPost.locators.scheduleSlots;slot count is 1
await expect (slot).toHaveCount (1 );slot has “data-tier” = “ONE_SHORT”
await expect (slot).toHaveAttribute ("data-tier" , "ONE_SHORT" );Act
Click slot
await slot.click ();Assert
18:00, with the flexibility that still leaves an hour of the window to play whichever start is settled on, capped at the longest option
start input has value /T18 :00 $/
await expect (newPost.startInput).toHaveValue (/T18 :00 $/);flexibility has value “+3hours”
await expect (newPost.locators.flexibility).toHaveValue ("+3hours" );slot has “data-picked” = “true”
await expect (slot).toHaveAttribute ("data-picked" , "true" );Source test ("picks a start and its flexibility from the roster's shared free time" , async ({
page,
factories,
}) => {
const { memberUserIds } = await createTeamFor (factories, NZAP_TEST_ID );
const evening = nextWeekSlot (WEDNESDAY , "18:00" , "23:00" );
for (const userId of memberUserIds.slice (0 , memberUserIds.length - 1 )) {
await factories.AvailabilityWeekFactory .create ({
userId,
weekStartsAt: nextWeek ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [evening],
});
}
await impersonate (page, NZAP_TEST_ID );
await setTimezoneCookie (page);
const newPost = new NewScrimPostPage (page);
await newPost.goto ();
await newPost.locators.nextWeekToggle.click ();
// the roster's last member never filled the week in, so the shared
// evening is one player short of a full team
await expect (newPost.locators.scheduleUnknown).toBeVisible ();
const slot = newPost.locators.scheduleSlots;
await expect (slot).toHaveCount (1 );
await expect (slot).toHaveAttribute ("data-tier" , "ONE_SHORT" );
await slot.click ();
// 18:00, with the flexibility that still leaves an hour of the window
// to play whichever start is settled on, capped at the longest option
await expect (newPost.startInput).toHaveValue (/T18 :00 $/);
await expect (newPost.locators.flexibility).toHaveValue ("+3hours" );
await expect (slot).toHaveAttribute ("data-picked" , "true" );
})shows how much of the viewer's roster could play a post Renders/scrims
Scrims page Arrange
Create team for N-ZAP → { memberUserIds }
const { memberUserIds } = await createTeamFor (factories, NZAP_TEST_ID );evening = nextWeekSlot (WEDNESDAY , "18:00" , "23:00" )
const evening = nextWeekSlot (WEDNESDAY , "18:00" , "23:00" );withoutSchedule = memberUserIds[memberUserIds.length - 1 ]
const withoutSchedule = memberUserIds[memberUserIds.length - 1 ];For each userId of memberUserIds.filter ( (candidate) => candidate !== withoutSchedule, )
for (const userId of memberUserIds.filter (
(candidate) => candidate !== withoutSchedule,
)) {
await factories.AvailabilityWeekFactory .create ({
userId,
weekStartsAt: nextWeek ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [evening],
});
}Create availability week userId week starts at nextWeek ().startsAt timezone MACHINE_TIMEZONE slots evening
await factories.AvailabilityWeekFactory .create ({
userId,
weekStartsAt: nextWeek ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [evening],
});Create scrim post users createGroup (factories) starts at evening.startsAt is scheduled for future true
await factories.ScrimPostFactory .create ({
users: await createGroup (factories),
startsAt: evening.startsAt,
isScheduledForFuture: true ,
});Scrims page Act
Open the scrims page
await scrims.goto ();Open tab “available”
await scrims.openTab ("available" );Assert
fit indicator contains “3/4 available”
await expect (scrims.locators.fitIndicator).toContainText ("3/4 available" );Act
Click fit indicator
await scrims.locators.fitIndicator.click ();Assert
availability row N-ZAP has “data-status” = “available”
await expect (scrims.availabilityRow (NZAP_TEST_ID )).toHaveAttribute (
"data-status" ,
"available" ,
);availability row withoutSchedule has “data-status” = “unknown”
await expect (scrims.availabilityRow (withoutSchedule)).toHaveAttribute (
"data-status" ,
"unknown" ,
);Act
Press Escape
await page.keyboard.press ("Escape" );Request first
await scrims.requestFirst ();Assert
the same breakdown, for the slot the request would be made for
availability row N-ZAP has “data-status” = “available”
await expect (scrims.availabilityRow (NZAP_TEST_ID )).toHaveAttribute (
"data-status" ,
"available" ,
);Source test ("shows how much of the viewer's roster could play a post" , async ({
page,
factories,
}) => {
const { memberUserIds } = await createTeamFor (factories, NZAP_TEST_ID );
const evening = nextWeekSlot (WEDNESDAY , "18:00" , "23:00" );
const withoutSchedule = memberUserIds[memberUserIds.length - 1 ];
for (const userId of memberUserIds.filter (
(candidate) => candidate !== withoutSchedule,
)) {
await factories.AvailabilityWeekFactory .create ({
userId,
weekStartsAt: nextWeek ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [evening],
});
}
await factories.ScrimPostFactory .create ({
users: await createGroup (factories),
startsAt: evening.startsAt,
isScheduledForFuture: true ,
});
await impersonate (page, NZAP_TEST_ID );
const scrims = new ScrimsPage (page);
await scrims.goto ();
await scrims.openTab ("available" );
await expect (scrims.locators.fitIndicator).toContainText ("3/4 available" );
await scrims.locators.fitIndicator.click ();
await expect (scrims.availabilityRow (NZAP_TEST_ID )).toHaveAttribute (
"data-status" ,
"available" ,
);
await expect (scrims.availabilityRow (withoutSchedule)).toHaveAttribute (
"data-status" ,
"unknown" ,
);
await page.keyboard.press ("Escape" );
await scrims.requestFirst ();
// the same breakdown, for the slot the request would be made for
await expect (scrims.availabilityRow (NZAP_TEST_ID )).toHaveAttribute (
"data-status" ,
"available" ,
);
})createNamedUserse2e/scrims.spec.ts:605
function createNamedUsers (factories: Factories , names: string []) {
return factories.UserFactory .createMany (names.length, (index) => ({
discordName: names[index],
}));
}AnythingAdder.adde2e/pages/layout/anything-adder.ts:28
No JSDoc
async add (item: AddableItem ) {
await this .locators.menuButton.click ();
await this .page.getByTestId (`menu-item-${item}` ).click ();
}NewScrimPostPage.selectPickupUserse2e/pages/scrims/new-scrim-post-page.ts:37
async selectPickupUsers (userNames: string []) {
await this .selectWith ("Pick-up" );
for (const [index, userName] of userNames.entries ()) {
await selectUser ({
page: this .page,
labelName: `User ${index + 2}` ,
userName,
});
}
}NewScrimPostPage.selectVisibilitye2e/pages/scrims/new-scrim-post-page.ts:72
async selectVisibility (associationName: string ) {
await this .page
.getByLabel ("Visibility" )
.selectOption ({ label: associationName });
}scrimsNewFormSchema.postTextapp/features/scrims/scrims-schemas.ts:332
postText: textAreaOptional ({
label: "labels.text" ,
maxLength: MAX_SCRIM_POST_TEXT_LENGTH ,
}) NewScrimPostPage.savee2e/pages/scrims/new-scrim-post-page.ts:83
No JSDoc
async save () {
await submit (this .page);
}ScrimsPage.locators.limitedVisibilityPopovere2e/pages/scrims/scrims-page.ts:42
No JSDoc
page.getByTestId ("limited-visibility-popover" ) ScrimsPage.deleteFirstPoste2e/pages/scrims/scrims-page.ts:134
No JSDoc
async deleteFirstPost () {
await this .locators.deleteButtons.first ().click ();
await modalClickConfirmButton (this .page);
}ScrimsPage.locators.deleteButtonse2e/pages/scrims/scrims-page.ts:40
No JSDoc
page.getByRole ("button" , { name: "Delete" }) AnythingAddere2e/pages/layout/anything-adder.ts:17
NewScrimPostPagee2e/pages/scrims/new-scrim-post-page.ts:12
No JSDoc
ScrimsPagee2e/pages/scrims/scrims-page.ts:24
No JSDoc
NewScrimPostPage.gotoe2e/pages/scrims/new-scrim-post-page.ts:32
No JSDoc
async goto () {
await navigate ({ page: this .page, url: newScrimPostPage () });
}NewScrimPostPage.selectSavedPickupe2e/pages/scrims/new-scrim-post-page.ts:50
async selectSavedPickup (userNames: string []) {
await this .selectWith (`Pick-up ${userNames.join(", ")}` );
}NewScrimPostPage.pickupUsere2e/pages/scrims/new-scrim-post-page.ts:62
pickupUser (nth: number ) {
return this .page.getByLabel (`User ${nth}` );
}createTeamFore2e/scrims.spec.ts:616
No JSDoc
async function createTeamFor (factories: Factories , userId: number ) {
const teammates = await factories.UserFactory .createMany (GROUP_SIZE - 1 );
return factories.TeamFactory .create ({
memberUserIds: [userId, ...teammates.map ((user) => user.id)],
});
}createTournamente2e/scrims.spec.ts:595
function createTournament (factories: Factories ) {
return factories.TournamentFactory .create ({
authorId: ADMIN_ID ,
name: TOURNAMENT_NAME ,
startTimes: [dateToDatabaseTimestamp (addDays (new Date (), 1 ))],
mapPoolMaps: TOURNAMENT_MAP_POOL ,
});
}scrimsNewFormSchema.atapp/features/scrims/scrims-schemas.ts:299
at: datetime ({
label: "labels.start" ,
bottomText: "bottomTexts.scrimStart" ,
min: () => sub (new Date (), { days: 1 }),
max: () => add (new Date (), { days: 15 }),
minMessage: "errors.dateInPast" ,
maxMessage: "errors.dateTooFarInFuture" ,
}) scrimsNewFormSchema.rangeEndapp/features/scrims/scrims-schemas.ts:307
rangeEnd: selectOptional ({
label: "labels.scrimStartFlexibility" ,
bottomText: "bottomTexts.scrimStartFlexibility" ,
items: [...rangeEndItems],
}) NewScrimPostPage.selectTournamentMapse2e/pages/scrims/new-scrim-post-page.ts:78
No JSDoc
async selectTournamentMaps (tournamentName: string ) {
await this .form.select ("maps" , "TOURNAMENT" );
await selectTournament ({ page: this .page, query: tournamentName });
}ScrimsPage.poste2e/pages/scrims/scrims-page.ts:63
No JSDoc
post (text: string ) {
return this .page.getByText (text);
}ScrimsPage.locators.tournamentPopovere2e/pages/scrims/scrims-page.ts:43
No JSDoc
page.getByTestId ("tournament-popover-trigger" ) ScrimsPage.gotoe2e/pages/scrims/scrims-page.ts:54
No JSDoc
async goto () {
await navigate ({ page: this .page, url: scrimsPage () });
}ScrimsPage.openTabe2e/pages/scrims/scrims-page.ts:105
No JSDoc
async openTab (tab: Tab ) {
await this .page.getByRole ("tab" , { name: TAB_NAMES [tab] }).click ();
}ScrimsPage.locators.requestButtonse2e/pages/scrims/scrims-page.ts:34
No JSDoc
page.getByTestId ("request-scrim-button" ) ScrimsPage.requestFirste2e/pages/scrims/scrims-page.ts:114
No JSDoc
async requestFirst () {
await this .locators.requestButtons.first ().click ();
return new ScrimRequestModal (this .page);
}ScrimRequestModal.sende2e/pages/scrims/scrims-page.ts:173
No JSDoc
async send () {
await submit (this .page);
}ScrimsPage.showPendingRequestse2e/pages/scrims/scrims-page.ts:120
async showPendingRequests () {
await this .locators.togglePendingRequestsButton.first ().click ();
}ScrimsPage.cancelPendingRequeste2e/pages/scrims/scrims-page.ts:124
No JSDoc
async cancelPendingRequest () {
await this .locators.viewRequestButtons.first ().click ();
await this .page.getByRole ("button" , { name: "Cancel" }).click ();
}ScrimRequestModale2e/pages/scrims/scrims-page.ts:146
ScrimRequestModal.selectPickupUserse2e/pages/scrims/scrims-page.ts:156
async selectPickupUsers (userNames: string []) {
for (const [index, userName] of userNames.entries ()) {
await selectUser ({
page: this .page,
labelName: `User ${index + 2}` ,
userName,
});
}
}ScrimRequestModal.selectStartTimee2e/pages/scrims/scrims-page.ts:167
async selectStartTime (nth: number ) {
await this .page
.getByLabel (this .form.getLabel ("at" ))
.selectOption ({ index: nth });
}scrimRequestFormSchema.messageapp/features/scrims/scrims-schemas.ts:269
message: textAreaOptional ({
label: "labels.scrimRequestMessage" ,
maxLength: SCRIM .REQUEST_MESSAGE_MAX_LENGTH ,
}) NotificationPopover.opene2e/pages/layout/notification-popover.ts:37
No JSDoc
async open () {
// the popover is closed on navigation, which would also close one opened
// after a click on a notification navigated but before the page rendered
await waitForNavigationRendered (this .page);
await expect (this .locators.shownPopover).toHaveCount (0 );
await this .locators.openButton.click ();
await expect (this .locators.shownPopover).toHaveCount (1 );
}NotificationPopover.notificatione2e/pages/layout/notification-popover.ts:50
No JSDoc
notification (text: string ) {
return this .locators.items.filter ({ hasText: text });
}NotificationPopover.closee2e/pages/layout/notification-popover.ts:46
No JSDoc
async close () {
await this .page.keyboard.press ("Escape" );
}NotificationPopovere2e/pages/layout/notification-popover.ts:6
createPostWithRequeste2e/scrims.spec.ts:656
async function createPostWithRequest (
factories: Factories ,
{
ownerUserId,
requesterUserId,
at,
mapsTournamentId,
isAccepted,
}: {
ownerUserId: number ;
requesterUserId?: number ;
at?: Date ;
mapsTournamentId?: number ;
isAccepted?: boolean ;
// … NotificationPopover.locators.bellDote2e/pages/layout/notification-popover.ts:29
this .page.getByTestId ("notifications-bell-dot" )ScrimsPage.acceptFirstRequeste2e/pages/scrims/scrims-page.ts:129
No JSDoc
async acceptFirstRequest () {
await this .locators.acceptRequestButtons.first ().click ();
await modalClickConfirmButton (this .page);
}ScrimsPage.locators.contactLinkse2e/pages/scrims/scrims-page.ts:41
No JSDoc
page.getByRole ("link" , { name: "Contact" }) ScrimsPage.openFirstBookedScrime2e/pages/scrims/scrims-page.ts:139
No JSDoc
async openFirstBookedScrim () {
await this .locators.contactLinks.first ().click ();
return new ScrimPage (this .page);
}ScrimPage.locators.subtitlee2e/pages/scrims/scrim-page.ts:46
No JSDoc
page.getByText ("Scheduled scrim" ) NotificationPopover.openNotificatione2e/pages/layout/notification-popover.ts:54
No JSDoc
async openNotification (text: string ) {
await this .notification (text).click ();
}ScrimPagee2e/pages/scrims/scrim-page.ts:31
isNotVisiblee2e/helpers/playwright.ts:745
No JSDoc
export function isNotVisible (locator: Locator ) {
return expect (locator).toHaveCount (0 );
}ScrimPage.cancele2e/pages/scrims/scrim-page.ts:119
No JSDoc
async cancel (reason: string ) {
await this .page.getByRole ("button" , { name: "Cancel" }).click ();
await this .cancelForm.fill ("reason" , reason);
await submit (this .page, "cancel-scrim-submit" );
}ScrimsPage.locators.canceledLabele2e/pages/scrims/scrims-page.ts:44
No JSDoc
page.getByText ("Canceled" , { exact: true }) ScrimsPage.filterByDivse2e/pages/scrims/scrims-page.ts:68
async filterByDivs ({ max, min }: { max: string ; min: string }) {
await this .page.keyboard.press ("Escape" );
await this .openDivsFilter ();
await this .page.getByLabel ("Max div" ).selectOption (max);
await this .page.getByLabel ("Min div" ).selectOption (min);
await this .page.keyboard.press ("Escape" );
}ScrimsPage.saveFiltersAsDefaulte2e/pages/scrims/scrims-page.ts:83
async saveFiltersAsDefault () {
await waitForPOSTResponse (this .page, () =>
this .locators.saveFiltersAsDefaultButton.click (),
);
}ScrimsPage.removeDivsFiltere2e/pages/scrims/scrims-page.ts:77
async removeDivsFilter () {
await this .page.keyboard.press ("Escape" );
await this .page.getByTestId ("divs-filter-remove" ).click ();
}ScrimsPage.reloade2e/pages/scrims/scrims-page.ts:58
No JSDoc
async reload () {
await this .page.reload ();
await expectIsHydrated (this .page);
}ScrimPage.gotoe2e/pages/scrims/scrim-page.ts:61
No JSDoc
async goto (scrimId: number ) {
await navigate ({ page: this .page, url: scrimPage (scrimId) });
}ScrimPage.openTabe2e/pages/scrims/scrim-page.ts:65
No JSDoc
async openTab (tab: Tab ) {
await this .page.getByRole ("tab" , { name: TAB_NAMES [tab] }).click ();
}ScrimPage.locators.mapListForme2e/pages/scrims/scrim-page.ts:47
No JSDoc
page.getByTestId ("scrim-map-list-form" ) ScrimPage.submitMapListe2e/pages/scrims/scrim-page.ts:74
async submitMapList () {
await waitForPOSTResponse (this .page, () => this .mapListForm.submit ());
}ScrimPage.locators.reportScoreButtone2e/pages/scrims/scrim-page.ts:51
No JSDoc
page.getByTestId ("report-score-button" ) ScrimPage.openMapListManagere2e/pages/scrims/scrim-page.ts:88
async openMapListManager () {
await this .locators.manageMapListsButton.click ();
}ScrimPage.mapListRowe2e/pages/scrims/scrim-page.ts:69
No JSDoc
mapListRow (side: Side ) {
return this .page.getByTestId (`map-list-row-${side}` );
}ScrimPage.submitPoolMapListe2e/pages/scrims/scrim-page.ts:78
No JSDoc
async submitPoolMapList (serializedPool: string ) {
await this .page.getByRole ("radio" , { name: "Map pool" }).click ();
await this .page
.getByRole ("button" , { name: "Paste from a map pool link" })
.click ();
await this .page.getByLabel ("Map pool link" ).fill (serializedPool);
await this .submitMapList ();
}ScrimPage.reportMapWinnere2e/pages/scrims/scrim-page.ts:101
No JSDoc
async reportMapWinner (winner: Side ) {
// the report of the previous map leaves the radios selected until the
// loader revalidation swaps the next map in
await expect (this .locators.selectedWinner).toHaveCount (0 );
await this .page.getByTestId (WINNER_RADIO_TEST_IDS [winner]).click ();
await submit (this .page, "report-score-button" );
}ScrimPage.locators.undoMapButtone2e/pages/scrims/scrim-page.ts:52
No JSDoc
page.getByTestId ("undo-map-button" ) ScrimPage.undoMape2e/pages/scrims/scrim-page.ts:110
No JSDoc
async undoMap () {
await submit (this .page, "undo-map-button" );
}ScrimPage.locators.replayMapButtone2e/pages/scrims/scrim-page.ts:53
No JSDoc
page.getByTestId ("replay-map-button" ) ScrimPage.replayMape2e/pages/scrims/scrim-page.ts:115
async replayMap () {
await submit (this .page, "replay-map-button" );
}ScrimPage.removeOwnMapListe2e/pages/scrims/scrim-page.ts:92
No JSDoc
async removeOwnMapList (side: Side ) {
await this .mapListRow (side)
.getByLabel (/Remove list/i)
.click ();
await waitForPOSTResponse (this .page, () =>
submit (this .page, "confirm-button" ),
);
}ScrimPage.locators.statsRoote2e/pages/scrims/scrim-page.ts:54
No JSDoc
page.getByTestId ("scrim-stats-root" ) ScrimPage.showModeStatsOfAllMapse2e/pages/scrims/scrim-page.ts:126
async showModeStatsOfAllMaps () {
await this .locators.statsRoot.getByText ("Mode" , { exact: true }).click ();
await this .page.getByRole ("switch" ).click ({ force: true });
}ScrimPage.reportedMapCounte2e/pages/scrims/scrim-page.ts:132
async reportedMapCount () {
const wins = await this .locators.statsRoot
.locator ("tbody tr td:nth-child(2)" )
.allInnerTexts ();
const losses = await this .locators.statsRoot
.locator ("tbody tr td:nth-child(3)" )
.allInnerTexts ();
return [...wins, ...losses].reduce (
(total, cell) => total + Number (cell),
0 ,
);
}NewScrimPostPage.locators.nextWeekTogglee2e/pages/scrims/new-scrim-post-page.ts:26
No JSDoc
page.locator (
'label[for="chip-radio-scrim-schedule-week-next"]' ,
) NewScrimPostPage.locators.scheduleUnknowne2e/pages/scrims/new-scrim-post-page.ts:23
No JSDoc
page.getByTestId ("scrim-schedule-unknown" ) NewScrimPostPage.locators.scheduleSlotse2e/pages/scrims/new-scrim-post-page.ts:22
No JSDoc
page.getByTestId ("scrim-schedule-slot" ) NewScrimPostPage.startInpute2e/pages/scrims/new-scrim-post-page.ts:67
get startInput () {
return this .page.getByLabel (/^Start *\*?$/);
} NewScrimPostPage.locators.flexibilitye2e/pages/scrims/new-scrim-post-page.ts:24
No JSDoc
page.getByLabel ("Start time flexibility" ) ScrimsPage.locators.fitIndicatore2e/pages/scrims/scrims-page.ts:45
No JSDoc
page.getByTestId ("scrim-fit-indicator" ) ScrimsPage.availabilityRowe2e/pages/scrims/scrims-page.ts:101
availabilityRow (userId: number ) {
return this .page.getByTestId (`availability-row-${userId}` );
}