test schedule progress split
This commit is contained in:
parent
8b8e6622a9
commit
ea74ce545e
1 changed files with 185 additions and 16 deletions
|
|
@ -121,6 +121,55 @@ const completedScheduleDetail = {
|
|||
},
|
||||
}
|
||||
|
||||
const splitScheduleDetail = {
|
||||
schedule: {
|
||||
...scheduleDetail.schedule,
|
||||
targetDate: '2026-08-13',
|
||||
assignmentCount: 4,
|
||||
days: [
|
||||
scheduleDetail.schedule.days[0],
|
||||
scheduleDetail.schedule.days[1],
|
||||
{
|
||||
date: '2026-08-12',
|
||||
assignments: [
|
||||
{
|
||||
id: 2,
|
||||
completedAt: '2026-08-11T08:30:00+00:00',
|
||||
element: {
|
||||
name: 'Chapter 1',
|
||||
kind: 'Chapter_sections-v2',
|
||||
path: ['Exodus', 'Shemot', 'Chapter 1'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
completedAt: null,
|
||||
element: {
|
||||
name: 'Chapter 1',
|
||||
kind: 'Chapter_sections-v2',
|
||||
path: ['Leviticus', 'Vayikra', 'Chapter 1'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: '2026-08-13',
|
||||
assignments: [
|
||||
{
|
||||
id: 4,
|
||||
completedAt: '2026-08-11T09:45:00+00:00',
|
||||
element: {
|
||||
name: 'Chapter 1',
|
||||
kind: 'Chapter_sections-v2',
|
||||
path: ['Numbers', 'Bamidbar', 'Chapter 1'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
function interceptAuthenticatedUser(): void {
|
||||
cy.intercept('GET', '**/api/me', {
|
||||
statusCode: 200,
|
||||
|
|
@ -159,9 +208,12 @@ describe('set scheduling', () => {
|
|||
cy.location('pathname').should('equal', '/sets/41/schedules/new')
|
||||
cy.get('h1').should('have.text', 'Schedule Bible')
|
||||
cy.get('#schedule-level option').then(($options) => {
|
||||
expect([...$options].map((option) => option.textContent?.trim())).to.deep.equal(
|
||||
['Choose a level', 'book (2)', 'portion (2)', 'Chapter_sections-v2 (2)'],
|
||||
)
|
||||
expect([...$options].map((option) => option.textContent?.trim())).to.deep.equal([
|
||||
'Choose a level',
|
||||
'book (2)',
|
||||
'portion (2)',
|
||||
'Chapter_sections-v2 (2)',
|
||||
])
|
||||
})
|
||||
cy.get('#schedule-level').select('3')
|
||||
cy.get('#schedule-start-date').type('2026-08-10')
|
||||
|
|
@ -184,6 +236,14 @@ describe('set scheduling', () => {
|
|||
'contain.text',
|
||||
'Exodus / Shemot / Chapter 1',
|
||||
)
|
||||
cy.get('[data-assignment-section="completed"]')
|
||||
.should('not.have.attr', 'open')
|
||||
.find('summary')
|
||||
.click()
|
||||
cy.get('[data-assignment-section="completed"]').should(
|
||||
'contain.text',
|
||||
'No assignments completed yet.',
|
||||
)
|
||||
})
|
||||
|
||||
it('validates the schedule form before submitting', () => {
|
||||
|
|
@ -248,6 +308,69 @@ describe('set scheduling', () => {
|
|||
cy.get('h1').should('have.text', 'Schedule not found')
|
||||
})
|
||||
|
||||
it('splits assignments by progress while preserving the schedule timeline', () => {
|
||||
cy.clock(new Date(2026, 7, 11, 12).getTime(), ['Date'])
|
||||
cy.intercept('GET', '**/api/schedules/73', {
|
||||
statusCode: 200,
|
||||
body: splitScheduleDetail,
|
||||
}).as('schedule')
|
||||
|
||||
cy.visit('/schedules/73')
|
||||
cy.wait('@me')
|
||||
cy.wait('@schedule')
|
||||
|
||||
cy.get('[data-assignment-section="remaining"]')
|
||||
.should('have.attr', 'data-assignment-count', '2')
|
||||
.within(() => {
|
||||
cy.get('h2').should('have.text', 'Remaining')
|
||||
cy.get('[data-schedule-day]').then(($days) => {
|
||||
expect([...$days].map((day) => day.getAttribute('data-schedule-date'))).to.deep.equal([
|
||||
'2026-08-10',
|
||||
'2026-08-11',
|
||||
'2026-08-12',
|
||||
])
|
||||
})
|
||||
cy.get('[data-schedule-date="2026-08-10"]')
|
||||
.should('contain.text', 'Overdue')
|
||||
.and('contain.text', 'Genesis / Creation / Chapter 1')
|
||||
cy.get('[data-schedule-date="2026-08-11"]')
|
||||
.should('contain.text', 'Rest day')
|
||||
.and('not.contain.text', 'Overdue')
|
||||
cy.get('[data-schedule-date="2026-08-12"]')
|
||||
.should('contain.text', 'Leviticus / Vayikra / Chapter 1')
|
||||
.and('not.contain.text', 'Exodus / Shemot / Chapter 1')
|
||||
cy.get('[data-schedule-date="2026-08-13"]').should('not.exist')
|
||||
})
|
||||
|
||||
cy.get('[data-assignment-section="completed"]')
|
||||
.should('have.attr', 'data-assignment-count', '2')
|
||||
.and('not.have.attr', 'open')
|
||||
.within(() => {
|
||||
cy.get('summary').should('contain.text', 'Completed').click()
|
||||
cy.get('[data-schedule-day]').then(($days) => {
|
||||
expect([...$days].map((day) => day.getAttribute('data-schedule-date'))).to.deep.equal([
|
||||
'2026-08-12',
|
||||
'2026-08-13',
|
||||
])
|
||||
})
|
||||
cy.get('[data-schedule-date="2026-08-12"]')
|
||||
.should('contain.text', 'Exodus / Shemot / Chapter 1')
|
||||
.and('not.contain.text', 'Leviticus / Vayikra / Chapter 1')
|
||||
cy.get('[data-schedule-date="2026-08-13"]').should(
|
||||
'contain.text',
|
||||
'Numbers / Bamidbar / Chapter 1',
|
||||
)
|
||||
cy.contains('Rest day').should('not.exist')
|
||||
})
|
||||
|
||||
cy.viewport(375, 667)
|
||||
cy.document().then((document) => {
|
||||
expect(document.documentElement.scrollWidth).to.be.at.most(
|
||||
document.documentElement.clientWidth,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('completes and reopens assignments from the schedule', () => {
|
||||
const completedAt = '2026-08-15T12:30:00+00:00'
|
||||
cy.intercept('GET', '**/api/schedules/73', {
|
||||
|
|
@ -278,26 +401,26 @@ describe('set scheduling', () => {
|
|||
cy.wait('@me')
|
||||
cy.wait('@schedule')
|
||||
|
||||
cy.get('[data-schedule-assignment="2"]').within(() => {
|
||||
cy.get('[data-assignment-section="completed"] summary').click()
|
||||
cy.get('[data-assignment-section="completed"] [data-schedule-assignment="2"]').within(() => {
|
||||
cy.contains('Completed').should('be.visible')
|
||||
cy.get('time')
|
||||
.should('have.attr', 'datetime', '2026-08-15T09:30:00+00:00')
|
||||
.and('have.text', formatCompletionTime('2026-08-15T09:30:00+00:00'))
|
||||
cy.contains('button', 'Reopen').click()
|
||||
})
|
||||
cy.wait('@reopenAssignment')
|
||||
cy.get('[data-schedule-assignment="2"]')
|
||||
.should('contain.text', 'Not completed')
|
||||
.and('not.contain.text', 'Completed')
|
||||
.within(() => {
|
||||
cy.contains('button', 'Mark complete').should('be.enabled')
|
||||
})
|
||||
|
||||
cy.get('[data-schedule-assignment="1"]').within(() => {
|
||||
cy.get('[data-assignment-section="remaining"] [data-schedule-assignment="1"]').within(() => {
|
||||
cy.contains('button', 'Mark complete').click()
|
||||
cy.contains('button', 'Saving...').should('be.disabled')
|
||||
})
|
||||
cy.wait('@completeAssignment')
|
||||
cy.get('[data-assignment-section="remaining"]')
|
||||
.should('have.attr', 'data-assignment-count', '0')
|
||||
.and('contain.text', 'All assignments are complete.')
|
||||
.and('contain.text', 'Rest day')
|
||||
cy.get('[data-assignment-section="completed"]')
|
||||
.should('have.attr', 'data-assignment-count', '2')
|
||||
.within(() => {
|
||||
cy.get('[data-schedule-assignment="1"]').within(() => {
|
||||
cy.contains('Completed').should('be.visible')
|
||||
cy.get('time')
|
||||
|
|
@ -306,6 +429,52 @@ describe('set scheduling', () => {
|
|||
cy.contains('button', 'Reopen').should('be.enabled')
|
||||
})
|
||||
})
|
||||
cy.get('[data-completion-announcement]').should('have.text', 'Assignment moved to Completed.')
|
||||
|
||||
cy.get('[data-assignment-section="completed"] [data-schedule-assignment="2"]').within(() => {
|
||||
cy.contains('button', 'Reopen').click()
|
||||
})
|
||||
cy.wait('@reopenAssignment')
|
||||
cy.get('[data-assignment-section="remaining"]')
|
||||
.should('have.attr', 'data-assignment-count', '1')
|
||||
.find('[data-schedule-assignment="2"]')
|
||||
.should('contain.text', 'Not completed')
|
||||
.and('not.contain.text', 'Completed')
|
||||
.within(() => {
|
||||
cy.contains('button', 'Mark complete').should('be.enabled')
|
||||
})
|
||||
cy.get('[data-assignment-section="completed"]')
|
||||
.should('have.attr', 'data-assignment-count', '1')
|
||||
.find('[data-schedule-assignment="2"]')
|
||||
.should('not.exist')
|
||||
cy.get('[data-completion-announcement]').should('have.text', 'Assignment moved to Remaining.')
|
||||
})
|
||||
|
||||
it('keeps an assignment in place when a completion request fails', () => {
|
||||
cy.intercept('GET', '**/api/schedules/73', {
|
||||
statusCode: 200,
|
||||
body: scheduleDetail,
|
||||
}).as('schedule')
|
||||
cy.intercept('PATCH', '**/api/assignments/1', {
|
||||
statusCode: 500,
|
||||
}).as('completeAssignment')
|
||||
|
||||
cy.visit('/schedules/73')
|
||||
cy.wait('@me')
|
||||
cy.wait('@schedule')
|
||||
|
||||
cy.get('[data-assignment-section="remaining"] [data-schedule-assignment="1"]')
|
||||
.contains('button', 'Mark complete')
|
||||
.click()
|
||||
cy.wait('@completeAssignment')
|
||||
|
||||
cy.get('[data-assignment-section="remaining"] [data-schedule-assignment="1"]')
|
||||
.should('be.visible')
|
||||
.and('contain.text', "We couldn't update this assignment.")
|
||||
cy.get('[data-assignment-section="completed"]')
|
||||
.find('[data-schedule-assignment="1"]')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
it('lists the users schedules on the dashboard', () => {
|
||||
cy.intercept('GET', '**/api/sets', {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue