S18 Added OR Tools rules for scheduling show
All checks were successful
Build, test and publish / verify (push) Successful in 6m12s
All checks were successful
Build, test and publish / verify (push) Successful in 6m12s
This commit is contained in:
@@ -31,6 +31,7 @@ async function confirmDelete(page: Page) {
|
||||
|
||||
test('manages a school, shared memberships and shows through the real REST API', async ({
|
||||
page,
|
||||
request,
|
||||
}) => {
|
||||
const schoolName = `E2E Studio ${Date.now()}`;
|
||||
const browserErrors: string[] = [];
|
||||
@@ -107,6 +108,26 @@ test('manages a school, shared memberships and shows through the real REST API',
|
||||
).toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/groups-desktop.png', fullPage: true });
|
||||
|
||||
// Two independent performances give Sam time to change between the shared groups.
|
||||
for (const name of ['Modern adults', 'Streetdance adults']) {
|
||||
const dancerResponse = await request.post(
|
||||
`${backend}/api/dance-schools/${schoolToDelete}/dancers`,
|
||||
{
|
||||
data: { name, birthDate: '1990-01-01' },
|
||||
},
|
||||
);
|
||||
const dancer = (await dancerResponse.json()) as { id: number };
|
||||
const groupResponse = await request.post(
|
||||
`${backend}/api/dance-schools/${schoolToDelete}/dance-groups`,
|
||||
{
|
||||
data: { category: name, type: 'REGULAR', startAge: 0, endAge: 99, styles: ['MODERN'] },
|
||||
},
|
||||
);
|
||||
const group = (await groupResponse.json()) as { id: number };
|
||||
await request.put(
|
||||
`${backend}/api/dance-schools/${schoolToDelete}/dance-groups/${group.id}/dancers/${dancer.id}`,
|
||||
);
|
||||
}
|
||||
await tab(page, 'Shows');
|
||||
await page.getByRole('button', { name: 'Show toevoegen' }).click();
|
||||
await page.getByRole('dialog').getByLabel('Naam', { exact: true }).fill('Zomershow');
|
||||
@@ -120,8 +141,19 @@ test('manages a school, shared memberships and shows through the real REST API',
|
||||
await expect(page.locator('.date-tile')).toContainText('jul 2027');
|
||||
page.once('dialog', (dialog) => dialog.accept());
|
||||
await page.getByRole('button', { name: /Schedule groups/ }).click();
|
||||
await expect(page.getByText('Planning voldoet aan alle optredensaantallen.')).toBeVisible();
|
||||
await expect(page.getByRole('status').filter({ hasText: 'Optimale balans.' })).toBeVisible();
|
||||
await expect(page.getByText('Planning voldoet aan alle harde regels.')).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole('status').filter({ hasText: 'Optimaal conceptrooster.' }),
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Indeling en volgorde bewerken' }).click();
|
||||
const scheduleDialog = page.getByRole('dialog');
|
||||
await scheduleDialog.getByRole('button', { name: 'Definitief maken' }).click();
|
||||
await expect(scheduleDialog.getByText('Definitief', { exact: false }).first()).toBeVisible();
|
||||
await scheduleDialog.getByRole('button', { name: 'Optreden verwijderen' }).first().click();
|
||||
await scheduleDialog.getByRole('button', { name: 'Concept opslaan' }).click();
|
||||
await expect(scheduleDialog.locator('.alert.error').first()).toBeVisible();
|
||||
await expect(scheduleDialog.getByRole('button', { name: 'Definitief maken' })).toBeDisabled();
|
||||
await scheduleDialog.getByRole('button', { name: 'Gereed', exact: true }).click();
|
||||
await page.getByRole('button', { name: 'Zomershow bewerken' }).click();
|
||||
await page.getByRole('button', { name: 'Dagdeel toevoegen', exact: true }).click();
|
||||
await page.getByLabel('Datum', { exact: true }).nth(1).fill('2027-07-02');
|
||||
@@ -148,7 +180,7 @@ test('manages a school, shared memberships and shows through the real REST API',
|
||||
await tab(page, 'Dansers');
|
||||
await page.getByRole('button', { name: 'Sam Testdanser verwijderen' }).click();
|
||||
await confirmDelete(page);
|
||||
await expect(page.getByText('De dansvloer is nog leeg')).toBeVisible();
|
||||
await expect(page.getByRole('cell', { name: 'Sam Testdanser', exact: true })).toHaveCount(0);
|
||||
await tab(page, 'Dansgroepen');
|
||||
await expect(page.getByText(/0 dansers/)).toHaveCount(2);
|
||||
await page.getByRole('button', { name: 'Hiphop Selectie verwijderen' }).click();
|
||||
@@ -166,6 +198,66 @@ test('manages a school, shared memberships and shows through the real REST API',
|
||||
expect(browserErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test('links a coach and finalizes performances spread across multiple dates', async ({
|
||||
page,
|
||||
request,
|
||||
}) => {
|
||||
const schoolResponse = await request.post(`${backend}/api/dance-schools`, {
|
||||
data: { name: `Coach show ${Date.now()}` },
|
||||
});
|
||||
const school = (await schoolResponse.json()) as School;
|
||||
schoolToDelete = school.id;
|
||||
const base = `${backend}/api/dance-schools/${school.id}`;
|
||||
const dancerResponse = await request.post(`${base}/dancers`, {
|
||||
data: { name: 'Dancing coach', birthDate: '1990-01-01' },
|
||||
});
|
||||
const dancer = (await dancerResponse.json()) as { id: number };
|
||||
const groupIds: number[] = [];
|
||||
for (const name of ['Preschool', 'Adults']) {
|
||||
const response = await request.post(`${base}/dance-groups`, {
|
||||
data: {
|
||||
category: name,
|
||||
type: name === 'Preschool' ? 'PRE_SCHOOLER' : 'REGULAR',
|
||||
startAge: 0,
|
||||
endAge: 99,
|
||||
styles: [],
|
||||
},
|
||||
});
|
||||
const group = (await response.json()) as { id: number };
|
||||
groupIds.push(group.id);
|
||||
await request.put(`${base}/dance-groups/${group.id}/dancers/${dancer.id}`);
|
||||
}
|
||||
const showResponse = await request.post(`${base}/shows`, {
|
||||
data: {
|
||||
name: 'Coach across dates',
|
||||
preferredDayParts: 1,
|
||||
dayParts: [
|
||||
{ date: '2027-06-01', type: 'AFTERNOON' },
|
||||
{ date: '2027-06-02', type: 'AFTERNOON' },
|
||||
],
|
||||
},
|
||||
});
|
||||
const show = (await showResponse.json()) as { id: number };
|
||||
await request.put(`${base}/shows/${show.id}/assignments`, {
|
||||
data: { assignments: groupIds.map((id) => [id]) },
|
||||
});
|
||||
await page.goto(`/schools/${school.id}/shows`);
|
||||
await expect(page.getByText(/exceeds x=1/)).toBeVisible();
|
||||
await tab(page, 'Dansers');
|
||||
await page.getByText('Coaches koppelen aan dansers', { exact: true }).click();
|
||||
await page.getByLabel('Danser als coach registreren').selectOption({ label: 'Dancing coach' });
|
||||
await expect(page.getByRole('combobox', { name: 'Dancing coach', exact: true })).toBeVisible();
|
||||
await tab(page, 'Shows');
|
||||
await expect(page.getByText('Planning voldoet aan alle harde regels.')).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Indeling en volgorde bewerken' }).click();
|
||||
await page.getByRole('dialog').getByRole('button', { name: 'Definitief maken' }).click();
|
||||
await expect(
|
||||
page.getByRole('dialog').getByRole('button', { name: 'Definitief maken' }),
|
||||
).toBeDisabled();
|
||||
const finalResponse = await request.get(`${base}/shows/${show.id}`);
|
||||
expect(((await finalResponse.json()) as { finalized: boolean }).finalized).toBe(true);
|
||||
});
|
||||
|
||||
test('shows a useful connection error and recovers on retry', async ({ page }) => {
|
||||
await page.route('**/api/dance-schools', (route) => route.abort('connectionfailed'));
|
||||
await page.goto('/schools');
|
||||
|
||||
Reference in New Issue
Block a user