Skip to content

Commit 93efe8e

Browse files
Best2Twoaudiodude
authored andcommitted
Add e2e tests for scheduled ZIM generations (#930)
- Add scheduling form UI tests (checkbox, dropdowns, email pre-fill) - Add submission payload tests (scheduled_repetitions included/excluded) - Add active schedule warning tests (display, interval, date, delete) - Add schedule + REQUESTED status tests (warning hidden) - Add MyLists 'Manage Schedule' button tests - Add fixture files for schedule scenarios
1 parent 60e2aee commit 93efe8e

File tree

5 files changed

+303
-6
lines changed

5 files changed

+303
-6
lines changed

wp1-frontend/cypress/e2e/myLists.cy.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe('the user selection list page', () => {
77
fixture: 'list_data.json',
88
}).as('list');
99
cy.intercept('v1/oauth/identify', { fixture: 'identity.json' }).as(
10-
'login',
10+
'login'
1111
);
1212
cy.visit('/#/selections/user');
1313
cy.wait('@login');
@@ -17,7 +17,7 @@ describe('the user selection list page', () => {
1717
it('successfully loads', () => {});
1818

1919
it('displays the datatables view', () => {
20-
cy.get('.dataTables_info').contains('Showing 1 to 12 of 12 entries');
20+
cy.get('.dataTables_info').contains('Showing 1 to 13 of 13 entries');
2121
});
2222

2323
it('displays list and its contents', () => {
@@ -247,6 +247,28 @@ describe('the user selection list page', () => {
247247
});
248248
});
249249
});
250+
251+
describe('when the builder has an active schedule', () => {
252+
it('displays the Manage Schedule button', () => {
253+
cy.contains('td', 'scheduled zim')
254+
.parent('tr')
255+
.within(() => {
256+
cy.get('td').eq(7).should('contain', 'Manage Schedule');
257+
});
258+
});
259+
260+
it('navigates to the zim page when Manage Schedule is clicked', () => {
261+
cy.contains('td', 'scheduled zim')
262+
.parent('tr')
263+
.within(() => {
264+
cy.contains('button', 'Manage Schedule').click();
265+
});
266+
cy.url().should(
267+
'eq',
268+
'http://localhost:5173/#/selections/sched-builder-001/zim'
269+
);
270+
});
271+
});
250272
});
251273

252274
describe('when the user is not logged in', () => {

wp1-frontend/cypress/e2e/zimFile.cy.js

Lines changed: 235 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ describe('the zim file creation page', () => {
44
describe('when the user is logged in', () => {
55
beforeEach(() => {
66
cy.intercept('v1/oauth/identify', { fixture: 'identity.json' }).as(
7-
'identity',
7+
'identity'
88
);
99
});
1010

@@ -32,7 +32,7 @@ describe('the zim file creation page', () => {
3232
fixture: 'zim_status_not_requested.json',
3333
}).as('status');
3434
cy.intercept('POST', 'v1/builders/1/zim', { statusCode: 204 }).as(
35-
'create',
35+
'create'
3636
);
3737
cy.visit('/#/selections/1/zim');
3838
cy.wait('@identity');
@@ -59,7 +59,7 @@ describe('the zim file creation page', () => {
5959
cy.get('#zimtitle').type(longTitle);
6060
cy.get('#zimtitle').should(
6161
'have.value',
62-
longTitle.substring(0, 30),
62+
longTitle.substring(0, 30)
6363
);
6464
});
6565

@@ -75,7 +75,7 @@ describe('the zim file creation page', () => {
7575
cy.get('#desc').click();
7676
cy.get('#longdesc').click();
7777
cy.get('#long-desc-group > .invalid-feedback').should(
78-
'not.be.visible',
78+
'not.be.visible'
7979
);
8080
});
8181

@@ -254,6 +254,237 @@ describe('the zim file creation page', () => {
254254
cy.get('#request').should('not.have.attr', 'disabled');
255255
});
256256
});
257+
258+
describe('scheduling form UI', () => {
259+
beforeEach(() => {
260+
cy.intercept('v1/builders/1/zim/status', {
261+
fixture: 'zim_status_not_requested.json',
262+
}).as('status');
263+
cy.intercept('GET', 'v1/oauth/email', {
264+
body: { email: 'test@example.org' },
265+
}).as('email');
266+
cy.visit('/#/selections/1/zim');
267+
cy.wait('@identity');
268+
cy.wait('@builder');
269+
cy.wait('@status');
270+
});
271+
272+
it('shows the scheduling checkbox unchecked by default', () => {
273+
cy.get('#enableScheduling').should('be.visible');
274+
cy.get('#enableScheduling').should('not.be.checked');
275+
});
276+
277+
it('does not show scheduling options when checkbox is unchecked', () => {
278+
cy.get('#repetitionPeriod').should('not.exist');
279+
cy.get('#numberOfRepetitions').should('not.exist');
280+
cy.get('#scheduleEmail').should('not.exist');
281+
});
282+
283+
it('shows scheduling options when checkbox is checked', () => {
284+
cy.get('#enableScheduling').check();
285+
cy.get('#repetitionPeriod').should('be.visible');
286+
cy.get('#numberOfRepetitions').should('be.visible');
287+
cy.get('#scheduleEmail').should('be.visible');
288+
});
289+
290+
it('shows the correct period options (1, 3, 6)', () => {
291+
cy.get('#enableScheduling').check();
292+
cy.get('#repetitionPeriod option').should('have.length', 3);
293+
cy.get('#repetitionPeriod option').eq(0).should('have.value', '1');
294+
cy.get('#repetitionPeriod option').eq(1).should('have.value', '3');
295+
cy.get('#repetitionPeriod option').eq(2).should('have.value', '6');
296+
});
297+
298+
it('shows the correct repetition options (1, 2, 3)', () => {
299+
cy.get('#enableScheduling').check();
300+
cy.get('#numberOfRepetitions option').should('have.length', 3);
301+
cy.get('#numberOfRepetitions option')
302+
.eq(0)
303+
.should('have.value', '1');
304+
cy.get('#numberOfRepetitions option')
305+
.eq(1)
306+
.should('have.value', '2');
307+
cy.get('#numberOfRepetitions option')
308+
.eq(2)
309+
.should('have.value', '3');
310+
});
311+
312+
it('pre-fills the schedule email from the user email endpoint', () => {
313+
cy.get('#enableScheduling').check();
314+
cy.get('#scheduleEmail').should('have.value', 'test@example.org');
315+
});
316+
});
317+
318+
describe('submitting with scheduling enabled', () => {
319+
beforeEach(() => {
320+
cy.intercept('v1/builders/1/zim/status', {
321+
fixture: 'zim_status_not_requested.json',
322+
}).as('status');
323+
cy.intercept('GET', 'v1/oauth/email', {
324+
body: { email: '' },
325+
}).as('email');
326+
cy.intercept('POST', 'v1/builders/1/zim', { statusCode: 204 }).as(
327+
'create'
328+
);
329+
cy.visit('/#/selections/1/zim');
330+
cy.wait('@identity');
331+
cy.wait('@builder');
332+
cy.wait('@status');
333+
});
334+
335+
it('includes scheduled_repetitions in the request body', () => {
336+
cy.get('#zimtitle').click();
337+
cy.get('#zimtitle').clear();
338+
cy.get('#zimtitle').type('Scheduled Title');
339+
cy.get('#desc').click();
340+
cy.get('#desc').clear();
341+
cy.get('#desc').type('Test description');
342+
cy.get('#enableScheduling').check();
343+
cy.get('#repetitionPeriod').select('3');
344+
cy.get('#numberOfRepetitions').select('2');
345+
cy.get('#scheduleEmail').clear();
346+
cy.get('#scheduleEmail').type('user@example.org');
347+
cy.get('#request').click();
348+
cy.wait('@create').then((interception) => {
349+
expect(interception.request.body).to.have.property(
350+
'scheduled_repetitions'
351+
);
352+
expect(
353+
interception.request.body.scheduled_repetitions
354+
).to.deep.equal({
355+
repetition_period_in_months: 3,
356+
number_of_repetitions: 2,
357+
email: 'user@example.org',
358+
});
359+
});
360+
});
361+
362+
it('submits without email when email is empty', () => {
363+
cy.get('#zimtitle').click();
364+
cy.get('#zimtitle').clear();
365+
cy.get('#zimtitle').type('Scheduled Title');
366+
cy.get('#desc').click();
367+
cy.get('#desc').clear();
368+
cy.get('#desc').type('Test description');
369+
cy.get('#enableScheduling').check();
370+
cy.get('#repetitionPeriod').select('1');
371+
cy.get('#numberOfRepetitions').select('1');
372+
cy.get('#scheduleEmail').clear();
373+
cy.get('#request').click();
374+
cy.wait('@create').then((interception) => {
375+
expect(interception.request.body).to.have.property(
376+
'scheduled_repetitions'
377+
);
378+
expect(
379+
interception.request.body.scheduled_repetitions
380+
).to.not.have.property('email');
381+
});
382+
});
383+
384+
it('does not include scheduled_repetitions when scheduling is disabled', () => {
385+
cy.get('#zimtitle').click();
386+
cy.get('#zimtitle').clear();
387+
cy.get('#zimtitle').type('No Schedule Title');
388+
cy.get('#desc').click();
389+
cy.get('#desc').clear();
390+
cy.get('#desc').type('Test description');
391+
cy.get('#request').click();
392+
cy.wait('@create').then((interception) => {
393+
expect(interception.request.body).to.not.have.property(
394+
'scheduled_repetitions'
395+
);
396+
});
397+
});
398+
});
399+
400+
describe('when there is an active schedule', () => {
401+
beforeEach(() => {
402+
cy.intercept('v1/builders/1/zim/status', {
403+
fixture: 'zim_status_with_schedule.json',
404+
}).as('status');
405+
cy.visit('/#/selections/1/zim');
406+
cy.wait('@identity');
407+
cy.wait('@builder');
408+
cy.wait('@status');
409+
});
410+
411+
it('displays the active schedule warning', () => {
412+
cy.contains('Active Schedule Found').should('be.visible');
413+
});
414+
415+
it('shows the correct interval in the warning', () => {
416+
cy.contains('3 months').should('be.visible');
417+
});
418+
419+
it('shows the next generation date', () => {
420+
cy.contains('June 1, 2026').should('be.visible');
421+
});
422+
423+
it('shows the Delete Schedule button', () => {
424+
cy.contains('button', 'Delete Schedule').should('be.visible');
425+
cy.contains('button', 'Delete Schedule').should(
426+
'not.have.attr',
427+
'disabled'
428+
);
429+
});
430+
431+
it('does not show the request form', () => {
432+
cy.get('#desc').should('not.exist');
433+
cy.get('#longdesc').should('not.exist');
434+
cy.get('#request').should('not.exist');
435+
});
436+
437+
describe('when the Delete Schedule button is clicked', () => {
438+
beforeEach(() => {
439+
cy.intercept('DELETE', 'v1/builders/1/schedule', {
440+
statusCode: 200,
441+
body: {},
442+
}).as('deleteSchedule');
443+
// After deletion, status returns without schedule
444+
cy.intercept('v1/builders/1/zim/status', {
445+
fixture: 'zim_status_not_requested.json',
446+
}).as('statusAfterDelete');
447+
});
448+
449+
it('sends the DELETE request', () => {
450+
cy.contains('button', 'Delete Schedule').click();
451+
cy.wait('@deleteSchedule');
452+
});
453+
454+
it('shows the request form after deletion', () => {
455+
cy.contains('button', 'Delete Schedule').click();
456+
cy.wait('@deleteSchedule');
457+
cy.wait('@statusAfterDelete');
458+
cy.get('#desc').should('be.visible');
459+
cy.get('#longdesc').should('be.visible');
460+
});
461+
});
462+
});
463+
464+
describe('when there is an active schedule and ZIM is REQUESTED', () => {
465+
beforeEach(() => {
466+
cy.intercept('v1/builders/1/zim/status', {
467+
fixture: 'zim_status_with_schedule_requested.json',
468+
}).as('status');
469+
cy.visit('/#/selections/1/zim');
470+
cy.wait('@identity');
471+
cy.wait('@builder');
472+
cy.wait('@status');
473+
});
474+
475+
it('does not show the active schedule warning', () => {
476+
cy.contains('Active Schedule Found').should('not.exist');
477+
});
478+
479+
it('shows the Download ZIM button disabled', () => {
480+
cy.get('#download').should('be.visible');
481+
cy.get('#download').should('have.attr', 'disabled');
482+
});
483+
484+
it('shows the spinner', () => {
485+
cy.get('#loader').should('be.visible');
486+
});
487+
});
257488
});
258489

259490
describe('and the selection is over the article limit', () => {

wp1-frontend/cypress/fixtures/list_data.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,28 @@
215215
"z_updated_at": 1687108510,
216216
"z_url": "http://localhost:5000/v1/builders/dcea7035-cc69-471e-b0e6-08dfbafd5e7c/zim/latest",
217217
"z_is_deleted": true
218+
},
219+
{
220+
"created_at": 1685646000,
221+
"id": "sched-builder-001",
222+
"model": "wp1.selection.models.simple",
223+
"name": "scheduled zim",
224+
"project": "en.wikipedia.org",
225+
"s_content_type": "text/tab-separated-values",
226+
"s_extension": "tsv",
227+
"s_id": "sched-sel-001",
228+
"s_status": "OK",
229+
"s_updated_at": 1685646500,
230+
"s_url": "https://www.example.fake/sched-sel-001",
231+
"updated_at": 1685646150,
232+
"z_updated_at": null,
233+
"z_url": null,
234+
"z_status": "NOT_REQUESTED",
235+
"z_is_deleted": null,
236+
"active_schedule": {
237+
"interval_months": 3,
238+
"next_generation_date": "2026-06-01"
239+
}
218240
}
219241
]
220242
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"status": "NOT_REQUESTED",
3+
"error_url": "https://error.fake/404",
4+
"is_deleted": false,
5+
"description": null,
6+
"long_description": null,
7+
"active_schedule": {
8+
"interval_months": 3,
9+
"next_generation_date": "2026-06-01"
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"status": "REQUESTED",
3+
"error_url": "https://error.fake/404",
4+
"is_deleted": false,
5+
"description": "Description for test",
6+
"long_description": "Long Description for test",
7+
"active_schedule": {
8+
"interval_months": 1,
9+
"next_generation_date": "2026-04-15"
10+
}
11+
}

0 commit comments

Comments
 (0)