test reschedule form

This commit is contained in:
Yisroel Baum 2026-08-19 22:48:03 +03:00
parent 7576ccaf09
commit 6ab6ed801a
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9

View file

@ -184,6 +184,103 @@ const splitScheduleDetail = {
},
}
const rescheduleSourceDetail = {
schedule: {
...scheduleDetail.schedule,
startDate: '2026-08-10',
targetDate: '2026-08-20',
assignmentCount: 4,
days: [
{
date: '2026-08-10',
assignments: [
{
...scheduleDetail.schedule.days[0]?.assignments[0],
completedAt: '2026-08-11T08:30:00+00:00',
},
],
},
{
date: '2026-08-18',
assignments: [
{
id: 2,
completedAt: null,
element: {
name: 'Chapter 2',
kind: 'Chapter_sections-v2',
path: ['Genesis', 'Creation', 'Chapter 2'],
},
},
],
},
{
date: '2026-08-19',
assignments: [
{
id: 3,
completedAt: null,
element: {
name: 'Chapter 3',
kind: 'Chapter_sections-v2',
path: ['Genesis', 'Creation', 'Chapter 3'],
},
},
],
},
{
date: '2026-08-20',
assignments: [
{
id: 4,
completedAt: null,
element: {
name: 'Chapter 4',
kind: 'Chapter_sections-v2',
path: ['Genesis', 'Creation', 'Chapter 4'],
},
},
],
},
],
},
}
const rescheduledDetail = {
schedule: {
...rescheduleSourceDetail.schedule,
startDate: '2026-08-15',
targetDate: '2026-08-16',
days: [
rescheduleSourceDetail.schedule.days[0],
{
date: '2026-08-15',
assignments: [rescheduleSourceDetail.schedule.days[1]?.assignments[0]],
},
{
date: '2026-08-16',
assignments: [
rescheduleSourceDetail.schedule.days[2]?.assignments[0],
rescheduleSourceDetail.schedule.days[3]?.assignments[0],
],
},
],
},
}
const fullyCompletedScheduleDetail = {
schedule: {
...scheduleDetail.schedule,
days: scheduleDetail.schedule.days.map((day) => ({
...day,
assignments: day.assignments.map((assignment) => ({
...assignment,
completedAt: '2026-08-15T09:30:00+00:00',
})),
})),
},
}
function interceptAuthenticatedUser(): void {
cy.intercept('GET', '**/api/me', {
statusCode: 200,
@ -458,6 +555,99 @@ describe('set scheduling', () => {
})
})
it('reschedules unfinished assignments while preserving completed work', () => {
cy.clock(new Date(2026, 7, 15, 12).getTime(), ['Date'])
cy.intercept('GET', '**/api/schedules/73', {
statusCode: 200,
body: rescheduleSourceDetail,
}).as('schedule')
cy.intercept('PATCH', '**/api/schedules/73', (request) => {
expect(request.headers.accept).to.equal('application/json')
expect(request.body).to.deep.equal({
startDate: '2026-08-15',
targetDate: '2026-08-16',
workloadPlacement: 'end',
})
request.reply({ statusCode: 200, body: rescheduledDetail })
}).as('reschedule')
cy.visit('/schedules/73')
cy.wait('@me')
cy.wait('@schedule')
cy.get('[data-reschedule-form]').should('not.exist')
cy.get('[data-reschedule-toggle]').should('have.text', 'Reschedule remaining').click()
cy.get('#reschedule-start-date').should('have.value', '2026-08-15')
cy.get('#reschedule-target-date').should('have.value', '2026-08-20')
cy.get('[data-workload-placement]').should('not.exist')
cy.get('#reschedule-target-date').clear().type('2026-08-16')
cy.get('[data-workload-placement]').should('be.visible').within(() => {
cy.get('input[value="middle"]').should('be.checked')
cy.get('input[value="end"]').check()
})
cy.get('[data-reschedule-form]').submit()
cy.wait('@reschedule')
cy.get('[data-reschedule-form]').should('not.exist')
cy.get('[data-reschedule-announcement]').should(
'have.text',
'3 remaining assignments rescheduled.',
)
cy.contains('4 Chapter_sections-v2 assignments across 2 days').should('be.visible')
cy.get('.schedule-range').should('contain.text', 'Aug 15, 2026 to Aug 16, 2026')
cy.get('[data-assignment-section="remaining"] [data-schedule-day]').then(($days) => {
expect([...$days].map((day) => day.getAttribute('data-schedule-date'))).to.deep.equal([
'2026-08-15',
'2026-08-16',
])
})
cy.get('[data-assignment-section="completed"] summary').click()
cy.get('[data-assignment-section="completed"] [data-schedule-day]')
.should('have.length', 1)
.and('have.attr', 'data-schedule-date', '2026-08-10')
cy.get('[data-reschedule-toggle]').click()
cy.get('#reschedule-start-date').should('have.value', '2026-08-15')
cy.get('#reschedule-target-date').should('have.value', '2026-08-16')
})
it('uses today for an expired target and validates before rescheduling', () => {
cy.clock(new Date(2026, 7, 15, 12).getTime(), ['Date'])
cy.intercept('GET', '**/api/schedules/73', {
statusCode: 200,
body: scheduleDetail,
}).as('schedule')
cy.intercept('PATCH', '**/api/schedules/73').as('reschedule')
cy.visit('/schedules/73')
cy.wait('@me')
cy.wait('@schedule')
cy.get('[data-reschedule-toggle]').click()
cy.get('#reschedule-start-date').should('have.value', '2026-08-15')
cy.get('#reschedule-target-date').should('have.value', '2026-08-15')
cy.get('#reschedule-target-date').clear().type('2026-08-14')
cy.get('[data-reschedule-form]').submit()
cy.get('#reschedule-target-date-error').should(
'have.text',
'Target date cannot be before the start date.',
)
cy.get('@reschedule.all').should('have.length', 0)
})
it('does not offer rescheduling after all assignments are complete', () => {
cy.intercept('GET', '**/api/schedules/73', {
statusCode: 200,
body: fullyCompletedScheduleDetail,
}).as('schedule')
cy.visit('/schedules/73')
cy.wait('@me')
cy.wait('@schedule')
cy.get('[data-reschedule-toggle]').should('not.exist')
})
it('completes and reopens assignments from the schedule', () => {
const completedAt = '2026-08-15T12:30:00+00:00'
cy.intercept('GET', '**/api/schedules/73', {