Events filters between tabs and navigates to an event Renders/events /to/:id /to/:id/info
Events page Arrange
startsAt = dateToDatabaseTimestamp (addHours (new Date (), 2 ))
const startsAt = dateToDatabaseTimestamp (addHours (new Date (), 2 ));Create tournament author Sendou name “Joined Tournament” start times startsAt → joinedTournament
const joinedTournament = await factories.TournamentFactory .create ({
authorId: ADMIN_ID ,
name: JOINED_TOURNAMENT_NAME ,
startTimes: [startsAt],
});Create tournament team tournament id joinedTournament.id member user ids N-ZAP
await factories.TournamentTeamFactory .create ({
tournamentId: joinedTournament.id,
memberUserIds: [NZAP_TEST_ID ],
});Create tournament author N-ZAP name “Organized Tournament” start times startsAt
await factories.TournamentFactory .create ({
authorId: NZAP_TEST_ID ,
name: ORGANIZED_TOURNAMENT_NAME ,
startTimes: [startsAt],
});Create scrim post startsAt users user N-ZAP is owner 1
await factories.ScrimPostFactory .create ({
startsAt,
users: [{ userId: NZAP_TEST_ID , isOwner: 1 }],
});Events page Act
Open the events page
await events.goto ();Assert
title is visible
await expect (events.locators.title).toBeVisible ();the first non-empty category is shown by default
event link “Joined Tournament” is visible
await expect (events.eventLink (JOINED_TOURNAMENT_NAME )).toBeVisible ();Act
Open view “scrims”
await events.openView ("scrims" );Assert
event link “Looking for scrim” is visible
await expect (events.eventLink ("Looking for scrim" )).toBeVisible ();Act
Open view “saved”
await events.openView ("saved" );Assert
empty category text is visible
await expect (events.locators.emptyCategoryText).toBeVisible ();Act
Open view “hosting”
await events.openView ("hosting" );Event link “Organized Tournament” → hostedEvent
const hostedEvent = events.eventLink (ORGANIZED_TOURNAMENT_NAME );Assert
hostedEvent is visible
await expect (hostedEvent).toBeVisible ();Act
Click hostedEvent
await hostedEvent.click ();Assert
the page URL is not /\/events/
await expect (page).not.toHaveURL (/\/events/);Source test ("filters between tabs and navigates to an event" , async ({
page,
factories,
}) => {
const startsAt = dateToDatabaseTimestamp (addHours (new Date (), 2 ));
const joinedTournament = await factories.TournamentFactory .create ({
authorId: ADMIN_ID ,
name: JOINED_TOURNAMENT_NAME ,
startTimes: [startsAt],
});
await factories.TournamentTeamFactory .create ({
tournamentId: joinedTournament.id,
memberUserIds: [NZAP_TEST_ID ],
});
await factories.TournamentFactory .create ({
authorId: NZAP_TEST_ID ,
name: ORGANIZED_TOURNAMENT_NAME ,
startTimes: [startsAt],
});
await factories.ScrimPostFactory .create ({
startsAt,
users: [{ userId: NZAP_TEST_ID , isOwner: 1 }],
});
await impersonate (page, NZAP_TEST_ID );
const events = new EventsPage (page);
await events.goto ();
await expect (events.locators.title).toBeVisible ();
// the first non-empty category is shown by default
await expect (events.eventLink (JOINED_TOURNAMENT_NAME )).toBeVisible ();
await events.openView ("scrims" );
await expect (events.eventLink ("Looking for scrim" )).toBeVisible ();
await events.openView ("saved" );
await expect (events.locators.emptyCategoryText).toBeVisible ();
await events.openView ("hosting" );
const hostedEvent = events.eventLink (ORGANIZED_TOURNAMENT_NAME );
await expect (hostedEvent).toBeVisible ();
await hostedEvent.click ();
await expect (page).not.toHaveURL (/\/events/);
})My schedule saves a week, edits it and submits an empty week Renders/events
Events page Events page Act
Open the events page
await events.goto ();Assert
week not filled marker “current” is visible
await expect (events.weekNotFilledMarker ("current" )).toBeVisible ();Act
Click day edit button 2
await events.dayEditButton (WEDNESDAY ).click ();popover = day editor popover
const popover = events.locators.dayEditorPopover;Fill popover.getByLabel ("Start" ) with “18:00”
await popover.getByLabel ("Start" ).fill ("18:00" );Fill popover.getByLabel ("End" ) with “22:00”
await popover.getByLabel ("End" ).fill ("22:00" );Fill popover.getByLabel ("Note" ) with “Leaving early”
await popover.getByLabel ("Note" ).fill ("Leaving early" );Press Escape
await page.keyboard.press ("Escape" );Assert
availability bars count is 1
await expect (events.locators.availabilityBars).toHaveCount (1 );Act
leaving the page with the unsaved week warns first
Click link “Find an event to join on the calendar!”
await page
.getByRole ("link" , { name: "Find an event to join on the calendar!" })
.click ();Wait for
await page.getByText ("Unsaved changes" ).waitFor ();Click button “Cancel”
await page.getByRole ("button" , { name: "Cancel" }).click ();Assert
the page URL is /\/events/
await expect (page).toHaveURL (/\/events/);Act
Click save week button
await events.locators.saveWeekButton.click ();Assert
text “Availability saved” is in the page
await expect (page.getByText ("Availability saved" )).toBeAttached ();Act
Open the events page
await events.goto ();Assert
availability bars count is 1
await expect (events.locators.availabilityBars).toHaveCount (1 );week not filled marker “current” is not visible
await isNotVisible (events.weekNotFilledMarker ("current" ));week not filled marker “next” is visible
await expect (events.weekNotFilledMarker ("next" )).toBeVisible ();Act
Click day edit button 2
await events.dayEditButton (WEDNESDAY ).click ();Assert
popover.getByLabel ("Note" ) has value “Leaving early”
await expect (popover.getByLabel ("Note" )).toHaveValue ("Leaving early" );Act
deleting the only range commits instantly: the popover closes and the bar disappears without waiting for a popover close + save
Click popover.getByRole ("button" , { name: "Delete" })
await popover.getByRole ("button" , { name: "Delete" }).click ();Assert
day editor popover is not visible
await isNotVisible (events.locators.dayEditorPopover);availability bars is not visible
await isNotVisible (events.locators.availabilityBars);Act
Click save week button
await events.locators.saveWeekButton.click ();Click element “confirm-button”
await page.getByTestId ("confirm-button" ).click ();Assert
text “Availability saved” is in the page
await expect (page.getByText ("Availability saved" )).toBeAttached ();Act
an empty submitted week is "unavailable all week", not missing
Open the events page
await events.goto ();Assert
availability bars is not visible
await isNotVisible (events.locators.availabilityBars);week not filled marker “current” is not visible
await isNotVisible (events.weekNotFilledMarker ("current" ));Source test ("saves a week, edits it and submits an empty week" , async ({ page }) => {
await impersonate (page, ADMIN_ID );
await setTimezoneCookie (page);
const events = new EventsPage (page);
await events.goto ();
await expect (events.weekNotFilledMarker ("current" )).toBeVisible ();
await events.dayEditButton (WEDNESDAY ).click ();
const popover = events.locators.dayEditorPopover;
await popover.getByLabel ("Start" ).fill ("18:00" );
await popover.getByLabel ("End" ).fill ("22:00" );
await popover.getByLabel ("Note" ).fill ("Leaving early" );
await page.keyboard.press ("Escape" );
await expect (events.locators.availabilityBars).toHaveCount (1 );
// leaving the page with the unsaved week warns first
await page
.getByRole ("link" , { name: "Find an event to join on the calendar!" })
.click ();
await page.getByText ("Unsaved changes" ).waitFor ();
await page.getByRole ("button" , { name: "Cancel" }).click ();
await expect (page).toHaveURL (/\/events/);
await events.locators.saveWeekButton.click ();
await expect (page.getByText ("Availability saved" )).toBeAttached ();
await events.goto ();
await expect (events.locators.availabilityBars).toHaveCount (1 );
await isNotVisible (events.weekNotFilledMarker ("current" ));
await expect (events.weekNotFilledMarker ("next" )).toBeVisible ();
await events.dayEditButton (WEDNESDAY ).click ();
await expect (popover.getByLabel ("Note" )).toHaveValue ("Leaving early" );
// deleting the only range commits instantly: the popover closes and the
// bar disappears without waiting for a popover close + save
await popover.getByRole ("button" , { name: "Delete" }).click ();
await isNotVisible (events.locators.dayEditorPopover);
await isNotVisible (events.locators.availabilityBars);
await events.locators.saveWeekButton.click ();
await page.getByTestId ("confirm-button" ).click ();
await expect (page.getByText ("Availability saved" )).toBeAttached ();
// an empty submitted week is "unavailable all week", not missing
await events.goto ();
await isNotVisible (events.locators.availabilityBars);
await isNotVisible (events.weekNotFilledMarker ("current" ));
})crosses over to the team schedule and back, keeping the week Renders/events /t/:customUrl /t/:customUrl/schedule
Events page Team schedule page Events page Arrange
Create team name “Team Olive” member user ids Sendou → { customUrl }
const { customUrl } = await factories.TeamFactory .create ({
name: "Team Olive" ,
memberUserIds: [ADMIN_ID ],
});Events page Act
Open the events page
await events.goto ();the week the editor is showing carries over to the team schedule
Click next week toggle
await events.locators.nextWeekToggle.click ();Click team schedule link
await events.locators.teamScheduleLink.click ();Assert
the page URL is new RegExp (`/t/${customUrl}/schedule\\?week=next` )
await expect (page).toHaveURL (
new RegExp (`/t/${customUrl}/schedule\\?week=next` ),
);Team schedule page Assert
heatmap is visible
await expect (schedule.locators.heatmap).toBeVisible ();Act
the week the schedule is showing carries over to the editor
Click edit availability link
await schedule.locators.editAvailabilityLink.click ();Assert
the page URL is /\/events\?week=next/
await expect (page).toHaveURL (/\/events\?week=next/);Events page Assert
week not filled marker “next” is visible
await expect (events.weekNotFilledMarker ("next" )).toBeVisible ();Source test ("crosses over to the team schedule and back, keeping the week" , async ({
page,
factories,
}) => {
const { customUrl } = await factories.TeamFactory .create ({
name: "Team Olive" ,
memberUserIds: [ADMIN_ID ],
});
await impersonate (page, ADMIN_ID );
await setTimezoneCookie (page);
const events = new EventsPage (page);
await events.goto ();
// the week the editor is showing carries over to the team schedule
await events.locators.nextWeekToggle.click ();
await events.locators.teamScheduleLink.click ();
await expect (page).toHaveURL (
new RegExp (`/t/${customUrl}/schedule\\?week=next` ),
);
const schedule = new TeamSchedulePage (page);
await expect (schedule.locators.heatmap).toBeVisible ();
// the week the schedule is showing carries over to the editor
await schedule.locators.editAvailabilityLink.click ();
await expect (page).toHaveURL (/\/events\?week=next/);
await expect (events.weekNotFilledMarker ("next" )).toBeVisible ();
})shows a commitment as a locked block on the editor Renders/events
Events page Arrange
currentWeek = Availability .weekRange (new Date (), MACHINE_TIMEZONE )
const currentWeek = Availability .weekRange (new Date (), MACHINE_TIMEZONE );wednesday = Availability .dateInTimezone ( currentWeek.startsAt + WEDNESDAY * DAY_SECONDS +…
const wednesday = Availability .dateInTimezone (
currentWeek.startsAt + WEDNESDAY * DAY_SECONDS + DAY_SECONDS / 2 ,
MACHINE_TIMEZONE ,
);Create team member user ids Sendou → team
const team = await factories.TeamFactory .create ({
memberUserIds: [ADMIN_ID ],
});Create team event team id team.id author Sendou name “VoD review” starts at Availability .localToTimestamp ({ date: wednesday, time: "20:00" , timezone: MAC … ends at Availability .localToTimestamp ({ date: wednesday, time: "21:30" , timezone: MAC …
await factories.TeamEventFactory .create ({
teamId: team.id,
authorId: ADMIN_ID ,
name: "VoD review" ,
startsAt: Availability .localToTimestamp ({
date: wednesday,
time: "20:00" ,
timezone: MACHINE_TIMEZONE ,
}),
endsAt: Availability .localToTimestamp ({
date: wednesday,
time: "21:30" ,
timezone: MACHINE_TIMEZONE ,
}),
});Events page Act
Open the events page
await events.goto ();Assert
first commitments is visible
await expect (events.locators.commitments.first ()).toBeVisible ();first commitments reads “VoD review”
await expect (events.locators.commitments.first ()).toHaveText ("VoD review" );Source test ("shows a commitment as a locked block on the editor" , async ({
page,
factories,
}) => {
const currentWeek = Availability .weekRange (new Date (), MACHINE_TIMEZONE );
const wednesday = Availability .dateInTimezone (
currentWeek.startsAt + WEDNESDAY * DAY_SECONDS + DAY_SECONDS / 2 ,
MACHINE_TIMEZONE ,
);
const team = await factories.TeamFactory .create ({
memberUserIds: [ADMIN_ID ],
});
await factories.TeamEventFactory .create ({
teamId: team.id,
authorId: ADMIN_ID ,
name: "VoD review" ,
startsAt: Availability .localToTimestamp ({
date: wednesday,
time: "20:00" ,
timezone: MACHINE_TIMEZONE ,
}),
endsAt: Availability .localToTimestamp ({
date: wednesday,
time: "21:30" ,
timezone: MACHINE_TIMEZONE ,
}),
});
await impersonate (page, ADMIN_ID );
await setTimezoneCookie (page);
const events = new EventsPage (page);
await events.goto ();
await expect (events.locators.commitments.first ()).toBeVisible ();
await expect (events.locators.commitments.first ()).toHaveText ("VoD review" );
})paints a range reaching past the hours the tracks show Renders/events
Events page Events page Act
Open the events page
await events.goto ();the tracks end at 2 AM until they are expanded; the paint runs past their right edge and the window widens to fit what it produced
Paint availability 2 , 0.5 , 1.25
await events.paintAvailability (WEDNESDAY , 0.5 , 1.25 );Assert
availability bars has “title” = “8:00 PM – 5:00 AM”
await expect (events.locators.availabilityBars).toHaveAttribute (
"title" ,
"8:00 PM – 5:00 AM" ,
);Source test ("paints a range reaching past the hours the tracks show" , async ({
page,
}) => {
await impersonate (page, ADMIN_ID );
await setTimezoneCookie (page);
const events = new EventsPage (page);
await events.goto ();
// the tracks end at 2 AM until they are expanded; the paint runs past
// their right edge and the window widens to fit what it produced
await events.paintAvailability (WEDNESDAY , 0.5 , 1.25 );
await expect (events.locators.availabilityBars).toHaveAttribute (
"title" ,
"8:00 PM – 5:00 AM" ,
);
})opens the day editor on the click following a drag Renders/events
Events page Events page Act
Open the events page
await events.goto ();Paint availability 2 , 0.3 , 0.5
await events.paintAvailability (WEDNESDAY , 0.3 , 0.5 );the drag ends with a click of its own, which must not open the popover without swallowing the click that comes after it either
Drag availability bar events.locators.availabilityBars, 60
await events.dragAvailabilityBar (events.locators.availabilityBars, 60 );Assert
day editor popover is not visible
await isNotVisible (events.locators.dayEditorPopover);Act
Click availability bars
await events.locators.availabilityBars.click ();Assert
day editor popover is visible
await expect (events.locators.dayEditorPopover).toBeVisible ();Source test ("opens the day editor on the click following a drag" , async ({
page,
}) => {
await impersonate (page, ADMIN_ID );
await setTimezoneCookie (page);
const events = new EventsPage (page);
await events.goto ();
await events.paintAvailability (WEDNESDAY , 0.3 , 0.5 );
// the drag ends with a click of its own, which must not open the popover
// without swallowing the click that comes after it either
await events.dragAvailabilityBar (events.locators.availabilityBars, 60 );
await isNotVisible (events.locators.dayEditorPopover);
await events.locators.availabilityBars.click ();
await expect (events.locators.dayEditorPopover).toBeVisible ();
})copies last week's ranges into the current week Renders/events
Events page Arrange
lastWeekRange = Availability .weekRange ( subWeeks (new Date (), 1 ), MACHINE_TIMEZONE , )
const lastWeekRange = Availability .weekRange (
subWeeks (new Date (), 1 ),
MACHINE_TIMEZONE ,
);lastWednesday = Availability .dateInTimezone ( lastWeekRange.startsAt + WEDNESDAY * DAY_SECONDS …
const lastWednesday = Availability .dateInTimezone (
lastWeekRange.startsAt + WEDNESDAY * DAY_SECONDS + DAY_SECONDS / 2 ,
MACHINE_TIMEZONE ,
);Create availability week user Sendou week starts at lastWeekRange.startsAt timezone MACHINE_TIMEZONE slots starts at Availability .localToTimestamp ({ date: lastWednesday, time: "19:00" , timezone:… ends at Availability .localToTimestamp ({ date: lastWednesday, time: "21:00" , timezone:…
await factories.AvailabilityWeekFactory .create ({
userId: ADMIN_ID ,
weekStartsAt: lastWeekRange.startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [
{
startsAt: Availability .localToTimestamp ({
date: lastWednesday,
time: "19:00" ,
timezone: MACHINE_TIMEZONE ,
}),
endsAt: Availability .localToTimestamp ({
date: lastWednesday,
time: "21:00" ,
timezone: MACHINE_TIMEZONE ,
}),
},
],
});Events page Act
Open the events page
await events.goto ();Assert
availability bars is not visible
await isNotVisible (events.locators.availabilityBars);Act
Click copy last week button
await events.locators.copyLastWeekButton.click ();Assert
availability bars count is 1
await expect (events.locators.availabilityBars).toHaveCount (1 );Act
Click save week button
await events.locators.saveWeekButton.click ();Assert
text “Availability saved” is in the page
await expect (page.getByText ("Availability saved" )).toBeAttached ();Source test ("copies last week's ranges into the current week" , async ({
page,
factories,
}) => {
const lastWeekRange = Availability .weekRange (
subWeeks (new Date (), 1 ),
MACHINE_TIMEZONE ,
);
const lastWednesday = Availability .dateInTimezone (
lastWeekRange.startsAt + WEDNESDAY * DAY_SECONDS + DAY_SECONDS / 2 ,
MACHINE_TIMEZONE ,
);
await factories.AvailabilityWeekFactory .create ({
userId: ADMIN_ID ,
weekStartsAt: lastWeekRange.startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [
{
startsAt: Availability .localToTimestamp ({
date: lastWednesday,
time: "19:00" ,
timezone: MACHINE_TIMEZONE ,
}),
endsAt: Availability .localToTimestamp ({
date: lastWednesday,
time: "21:00" ,
timezone: MACHINE_TIMEZONE ,
}),
},
],
});
await impersonate (page, ADMIN_ID );
await setTimezoneCookie (page);
const events = new EventsPage (page);
await events.goto ();
await isNotVisible (events.locators.availabilityBars);
await events.locators.copyLastWeekButton.click ();
await expect (events.locators.availabilityBars).toHaveCount (1 );
await events.locators.saveWeekButton.click ();
await expect (page.getByText ("Availability saved" )).toBeAttached ();
})Schedule visibility stops friends seeing the schedule, then opens it up to a team joined later Renders/events /friends /t/:customUrl /t/:customUrl/schedule
Friends page Events page Friends page Team schedule page Events page Team schedule page Friends page Arrange
Create named users “Teammate” → [teammate]
const [teammate] = await createNamedUsers (factories, ["Teammate" ]);N-ZAP is a friend and deliberately not a teammate, so only the friends toggle reaches them
Create friendship user one Sendou user two N-ZAP
await factories.FriendshipFactory .create ({
userOneId: ADMIN_ID ,
userTwoId: NZAP_TEST_ID ,
});Create availability week user Sendou week starts at weekRange ().startsAt timezone MACHINE_TIMEZONE slots daySlot (WEDNESDAY , "18:00" , "22:00" )
await factories.AvailabilityWeekFactory .create ({
userId: ADMIN_ID ,
weekStartsAt: weekRange ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [daySlot (WEDNESDAY , "18:00" , "22:00" )],
});Friends page Act
Open the friends page
await friends.goto ();Assert
schedule button Sendou is visible
await expect (friends.scheduleButton (ADMIN_ID )).toBeVisible ();Events page Act
Open the events page
await events.goto ();Assert
nothing restricted yet, so the editor says nothing about who is left out
not shared with is not visible
await isNotVisible (events.locators.notSharedWith);Act
Set schedule visibility uncheck “All friends”
await events.setScheduleVisibility ({ uncheck: [ALL_FRIENDS ] });Assert
visibility button reads “Limited”
await expect (events.locators.visibilityButton).toHaveText ("Limited" );not shared with reads “· Not shared with friends”
await expect (events.locators.notSharedWith).toHaveText (
"· Not shared with friends" ,
);Friends page Act
Open the friends page
await friends.goto ();Assert
schedule button Sendou is not visible
await isNotVisible (friends.scheduleButton (ADMIN_ID ));Arrange
joined after the visibility was saved, so it starts outside the allow-list
Create team name “Team Olive” member user ids teammate.id, Sendou → team
const team = await factories.TeamFactory .create ({
name: "Team Olive" ,
memberUserIds: [teammate.id, ADMIN_ID ],
});Team schedule page Act
Open the team schedule page team.customUrl
await schedule.goto (team.customUrl);Click grid view tab
await schedule.locators.gridViewTab.click ();Assert
cell range Sendou , 2 is not visible
await isNotVisible (schedule.cellRange (ADMIN_ID , WEDNESDAY ));Events page Act
Open the events page
await events.goto ();Assert
the team joined after the save is outside the allow-list, and named as such
not shared with reads “· Not shared with friends and Team Olive”
await expect (events.locators.notSharedWith).toHaveText (
"· Not shared with friends and Team Olive" ,
);Act
Set schedule visibility check “Team Olive”
await events.setScheduleVisibility ({ check: ["Team Olive" ] });Assert
not shared with reads “· Not shared with friends”
await expect (events.locators.notSharedWith).toHaveText (
"· Not shared with friends" ,
);Team schedule page Act
Open the team schedule page team.customUrl
await schedule.goto (team.customUrl);Click grid view tab
await schedule.locators.gridViewTab.click ();Assert
cell range Sendou , 2 is visible
await expect (schedule.cellRange (ADMIN_ID , WEDNESDAY )).toBeVisible ();Friends page Act
Open the friends page
await friends.goto ();Assert
schedule button Sendou is not visible
await isNotVisible (friends.scheduleButton (ADMIN_ID ));Source test ("stops friends seeing the schedule, then opens it up to a team joined later" , async ({
page,
factories,
}) => {
const [teammate] = await createNamedUsers (factories, ["Teammate" ]);
// N-ZAP is a friend and deliberately not a teammate, so only the friends toggle reaches them
await factories.FriendshipFactory .create ({
userOneId: ADMIN_ID ,
userTwoId: NZAP_TEST_ID ,
});
await factories.AvailabilityWeekFactory .create ({
userId: ADMIN_ID ,
weekStartsAt: weekRange ().startsAt,
timezone: MACHINE_TIMEZONE ,
slots: [daySlot (WEDNESDAY , "18:00" , "22:00" )],
});
const friends = new FriendsPage (page);
await impersonate (page, NZAP_TEST_ID );
await setTimezoneCookie (page);
await friends.goto ();
await expect (friends.scheduleButton (ADMIN_ID )).toBeVisible ();
const events = new EventsPage (page);
await impersonate (page, ADMIN_ID );
await events.goto ();
// nothing restricted yet, so the editor says nothing about who is left out
await isNotVisible (events.locators.notSharedWith);
await events.setScheduleVisibility ({ uncheck: [ALL_FRIENDS ] });
await expect (events.locators.visibilityButton).toHaveText ("Limited" );
await expect (events.locators.notSharedWith).toHaveText (
"· Not shared with friends" ,
);
await impersonate (page, NZAP_TEST_ID );
await friends.goto ();
await isNotVisible (friends.scheduleButton (ADMIN_ID ));
// joined after the visibility was saved, so it starts outside the allow-list
const team = await factories.TeamFactory .create ({
name: "Team Olive" ,
memberUserIds: [teammate.id, ADMIN_ID ],
});
const schedule = new TeamSchedulePage (page);
await impersonate (page, teammate.id);
await setTimezoneCookie (page);
await schedule.goto (team.customUrl);
await schedule.locators.gridViewTab.click ();
await isNotVisible (schedule.cellRange (ADMIN_ID , WEDNESDAY ));
await impersonate (page, ADMIN_ID );
await events.goto ();
// the team joined after the save is outside the allow-list, and named as such
await expect (events.locators.notSharedWith).toHaveText (
"· Not shared with friends and Team Olive" ,
);
await events.setScheduleVisibility ({ check: ["Team Olive" ] });
await expect (events.locators.notSharedWith).toHaveText (
"· Not shared with friends" ,
);
await impersonate (page, teammate.id);
await schedule.goto (team.customUrl);
await schedule.locators.gridViewTab.click ();
await expect (schedule.cellRange (ADMIN_ID , WEDNESDAY )).toBeVisible ();
// adding the team did not quietly restore the friends sharing the dialog opened with
await impersonate (page, NZAP_TEST_ID );
await friends.goto ();
await isNotVisible (friends.scheduleButton (ADMIN_ID ));
})EventsPage.gotoe2e/pages/calendar/events-page.ts:82
No JSDoc
async goto () {
await navigate ({ page: this .page, url: EVENTS_PAGE });
}EventsPage.locators.titlee2e/pages/calendar/events-page.ts:23
No JSDoc
page.getByRole ("heading" , { name: "My events" }) EventsPage.eventLinke2e/pages/calendar/events-page.ts:117
No JSDoc
eventLink (name: string ) {
return this .main.getByRole ("link" , { name });
}EventsPage.openViewe2e/pages/calendar/events-page.ts:111
async openView (view: keyof typeof VIEW_LABELS ) {
await this .locators.viewTabs
.getByRole ("link" , { name: new RegExp (`^${VIEW_LABELS[view]}` ) })
.click ();
}EventsPage.locators.emptyCategoryTexte2e/pages/calendar/events-page.ts:25
No JSDoc
page.getByText ("No events in this category" ) EventsPagee2e/pages/calendar/events-page.ts:14
EventsPage.weekNotFilledMarkere2e/pages/calendar/events-page.ts:43
weekNotFilledMarker (week: "current" | "next" ) {
return this .page.getByTestId (`week-not-filled-${week}` );
}EventsPage.dayEditButtone2e/pages/calendar/events-page.ts:48
dayEditButton (dayIndex: number ) {
return this .page.getByTestId (`availability-day-edit-${dayIndex}` );
}EventsPage.locators.dayEditorPopovere2e/pages/calendar/events-page.ts:31
No JSDoc
page.getByRole ("dialog" ) EventsPage.locators.availabilityBarse2e/pages/calendar/events-page.ts:27
No JSDoc
page.getByTestId ("availability-bar" ) EventsPage.locators.saveWeekButtone2e/pages/calendar/events-page.ts:29
No JSDoc
page.getByTestId ("save-week-button" ) isNotVisiblee2e/helpers/playwright.ts:745
No JSDoc
export function isNotVisible (locator: Locator ) {
return expect (locator).toHaveCount (0 );
}EventsPage.locators.nextWeekTogglee2e/pages/calendar/events-page.ts:36
No JSDoc
page.locator (
'label[for="chip-radio-my-schedule-week-next"]' ,
) EventsPage.locators.teamScheduleLinke2e/pages/calendar/events-page.ts:32
No JSDoc
page.getByTestId ("team-schedule-link" ) TeamSchedulePage.locators.heatmape2e/pages/team/team-schedule-page.ts:13
No JSDoc
page.getByTestId ("schedule-heatmap" ) TeamSchedulePage.locators.editAvailabilityLinke2e/pages/team/team-schedule-page.ts:22
No JSDoc
page.getByTestId ("edit-availability-link" ) TeamSchedulePagee2e/pages/team/team-schedule-page.ts:5
No JSDoc
EventsPage.locators.commitmentse2e/pages/calendar/events-page.ts:28
No JSDoc
page.getByTestId ("availability-commitment" ) EventsPage.paintAvailabilitye2e/pages/calendar/events-page.ts:53
async paintAvailability (dayIndex: number , from : number , to: number ) {
const track = this .page.getByTestId (`availability-track-${dayIndex}` );
const box = await track.boundingBox ();
if (!box) {
throw new Error ("Missing bounding box for the day track" );
}
const y = box.y + box.height / 2 ;
await this .page.mouse.move (box.x + box.width * from , y);
await this .page.mouse.down ();
await this .page.mouse.move (box.x + box.width * to, y, { steps: 10 });
await this .page.mouse.up ();
}EventsPage.dragAvailabilityBare2e/pages/calendar/events-page.ts:68
async dragAvailabilityBar (bar: Locator , deltaX: number ) {
const box = await bar.boundingBox ();
if (!box) {
throw new Error ("Missing bounding box for the availability bar" );
}
const x = box.x + box.width / 2 ;
const y = box.y + box.height / 2 ;
await this .page.mouse.move (x, y);
await this .page.mouse.down ();
await this .page.mouse.move (x + deltaX, y, { steps: 10 });
await this .page.mouse.up ();
}EventsPage.locators.copyLastWeekButtone2e/pages/calendar/events-page.ts:30
No JSDoc
page.getByTestId ("copy-last-week-button" ) createNamedUserse2e/helpers/sidebar.ts:29
export function createNamedUsers (
factories: Factories ,
names: string [],
overrides?: { twitch?: string },
) {
return factories.UserFactory .createMany (names.length, (index) => ({
...overrides,
discordName: names[index],
}));
}FriendsPage.gotoe2e/pages/friends/friends-page.ts:35
No JSDoc
async goto () {
await navigate ({ page: this .page, url: FRIENDS_PAGE });
}FriendsPage.scheduleButtone2e/pages/friends/friends-page.ts:70
No JSDoc
scheduleButton (userId: number ) {
return this .page.getByTestId (`friend-schedule-button-${userId}` );
}EventsPage.locators.notSharedWithe2e/pages/calendar/events-page.ts:34
No JSDoc
page.getByTestId ("schedule-not-shared-with" ) EventsPage.setScheduleVisibilitye2e/pages/calendar/events-page.ts:90
async setScheduleVisibility ({
check = [],
uncheck = [],
}: {
check?: Array <string >;
uncheck?: Array <string >;
}) {
await this .locators.visibilityButton.click ();
const dialog = this .page.getByRole ("dialog" );
for (const name of uncheck) {
await dialog.getByRole ("checkbox" , { name, exact: true }).uncheck ();
}
for (const name of check) {
// … EventsPage.locators.visibilityButtone2e/pages/calendar/events-page.ts:33
No JSDoc
page.getByTestId ("schedule-visibility-button" ) TeamSchedulePage.gotoe2e/pages/team/team-schedule-page.ts:31
No JSDoc
async goto (customUrl: string ) {
await navigate ({
page: this .page,
url: `${teamPage(customUrl)}/schedule` ,
});
}TeamSchedulePage.locators.gridViewTabe2e/pages/team/team-schedule-page.ts:27
No JSDoc
page.getByRole ("tab" , { name: "Grid" }) TeamSchedulePage.cellRangee2e/pages/team/team-schedule-page.ts:42
No JSDoc
cellRange (userId: number , dayIndex: number ) {
return this .cell (userId, dayIndex).getByTestId ("schedule-range" );
}FriendsPagee2e/pages/friends/friends-page.ts:13