test assignment completion ui

This commit is contained in:
Yisroel Baum 2026-08-15 22:47:49 +03:00
parent 350d2ec0b7
commit 0d9e2fa71b
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
2 changed files with 155 additions and 0 deletions

View file

@ -74,6 +74,7 @@ const scheduleDetail = {
assignments: [
{
id: 1,
completedAt: null,
element: {
name: 'Chapter 1',
kind: 'Chapter_sections-v2',
@ -88,6 +89,7 @@ const scheduleDetail = {
assignments: [
{
id: 2,
completedAt: null,
element: {
name: 'Chapter 1',
kind: 'Chapter_sections-v2',
@ -100,6 +102,25 @@ const scheduleDetail = {
},
}
const completedScheduleDetail = {
schedule: {
...scheduleDetail.schedule,
days: [
scheduleDetail.schedule.days[0],
scheduleDetail.schedule.days[1],
{
...scheduleDetail.schedule.days[2],
assignments: [
{
...scheduleDetail.schedule.days[2]?.assignments[0],
completedAt: '2026-08-15T09:30:00+00:00',
},
],
},
],
},
}
function interceptAuthenticatedUser(): void {
cy.intercept('GET', '**/api/me', {
statusCode: 200,
@ -227,6 +248,65 @@ describe('set scheduling', () => {
cy.get('h1').should('have.text', 'Schedule not found')
})
it('completes and reopens assignments from the schedule', () => {
const completedAt = '2026-08-15T12:30:00+00:00'
cy.intercept('GET', '**/api/schedules/73', {
statusCode: 200,
body: completedScheduleDetail,
}).as('schedule')
cy.intercept('PATCH', '**/api/assignments/1', (request) => {
expect(request.body).to.deep.equal({ completed: true })
request.reply({
delay: 400,
statusCode: 200,
body: {
assignment: { id: 1, completedAt },
},
})
}).as('completeAssignment')
cy.intercept('PATCH', '**/api/assignments/2', (request) => {
expect(request.body).to.deep.equal({ completed: false })
request.reply({
statusCode: 200,
body: {
assignment: { id: 2, completedAt: null },
},
})
}).as('reopenAssignment')
cy.visit('/schedules/73')
cy.wait('@me')
cy.wait('@schedule')
cy.get('[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.contains('button', 'Mark complete').click()
cy.contains('button', 'Saving...').should('be.disabled')
})
cy.wait('@completeAssignment')
cy.get('[data-schedule-assignment="1"]').within(() => {
cy.contains('Completed').should('be.visible')
cy.get('time')
.should('have.attr', 'datetime', completedAt)
.and('have.text', formatCompletionTime(completedAt))
cy.contains('button', 'Reopen').should('be.enabled')
})
})
it('lists the users schedules on the dashboard', () => {
cy.intercept('GET', '**/api/sets', {
statusCode: 200,
@ -272,3 +352,10 @@ describe('set scheduling', () => {
cy.contains('a', 'Bible').should('have.attr', 'href', '/schedules/73')
})
})
function formatCompletionTime(value: string): string {
return new Intl.DateTimeFormat('en', {
dateStyle: 'medium',
timeStyle: 'short',
}).format(new Date(value))
}

View file

@ -113,6 +113,74 @@ describe("today's assignments", () => {
)
})
it('completes an assignment and keeps failures retryable', () => {
cy.intercept('GET', `**/api/assignments?date=${browserToday}`, {
statusCode: 200,
body: {
date: browserToday,
assignments: [
{
id: 12,
schedule: {
id: 73,
set: { name: 'Bible' },
},
element: {
name: 'Chapter 1',
kind: 'chapter',
path: ['Genesis', 'Chapter 1'],
},
},
],
},
}).as('todayAssignments')
let requestCount = 0
cy.intercept('PATCH', '**/api/assignments/12', (request) => {
requestCount += 1
request.alias = `completion${requestCount}`
expect(request.body).to.deep.equal({ completed: true })
if (requestCount === 1) {
request.reply({ delay: 400, statusCode: 500 })
return
}
request.reply({
delay: 400,
statusCode: 200,
body: {
assignment: {
id: 12,
completedAt: '2026-08-15T12:30:00+00:00',
},
},
})
})
cy.visit('/dashboard')
cy.wait('@me')
cy.wait('@todayAssignments')
cy.get('[data-today-assignment="12"]').within(() => {
cy.contains('button', 'Mark complete').click()
cy.contains('button', 'Completing...').should('be.disabled')
})
cy.wait('@completion1')
cy.get('[data-today-assignment="12"]')
.should('contain.text', "We couldn't update this assignment.")
.within(() => {
cy.contains('button', 'Mark complete').click()
cy.contains('button', 'Completing...').should('be.disabled')
})
cy.wait('@completion2')
cy.get('[data-today-assignment="12"]').should('not.exist')
cy.get('.today-assignments [role="status"]').should(
'contain.text',
'Nothing is assigned for today.',
)
})
it('retries independently after the request fails', () => {
let requestCount = 0
cy.intercept(