Add payment module E2E tests for Social Protection#99
Add payment module E2E tests for Social Protection#99Shahzaibahmad97 wants to merge 10 commits intodevelopfrom
Conversation
Make login and logout resilient to already-authenticated state by checking the DOM before acting. Add enterDateInput command for MUI DatePicker fields and setFrontendModuleConfig for frontend-layer module configuration.
Introduce Cypress specs and command helpers for payment plan and payment cycle workflows. Payment plan coverage includes create, edit, search, delete, versioning, duplicate-code validation, advanced criteria, and group-profile smoke. Payment cycle coverage includes create, search, view-details, and required-field validation.
Pass beneficiary JSON schema during program creation so that advanced criteria fields (educated_level, able_bodied, etc.) are available in payment plan and payroll forms. Harden login command with cookie clearing and increased timeout. Add initial payroll spec and command helpers.
Payment plan: filter by benefit plan/program, multiple advanced criteria rows, calculation rule persistence. Payment cycle: ACTIVE/SUSPENDED creation, duplicate code block, status filter, read-only detail page, immediate search after create. Payroll: pending-approval status check, cross-domain integration smoke test.
Add a dedicated payment-point spec (16 tests) covering CRUD, the full location-level filter cascade (region, district, municipality, village), detail view, and filter reset. Add the matching command module (payment-point.commands.js) plus a payment-cycle config fixture used by the new suites. Expand payroll.cy.js with the timesheet calcrule integration flow: enroll individuals directly as Active, create a project with locations and the new "Allow beneficiaries to enroll in multiple projects" flag, assign beneficiaries, enter time entries, complete the project, wire a timesheet payment plan + ACTIVE payment cycle, and create the payroll. Fix cypress.config.js updateCSV task to preserve rows with an empty group_code so standalone individuals stay eligible for individual program enrollment. Update individuals.csv with 20 standalone individuals (HEAD role, R1 location codes) to support those flows. Strengthen shared support commands: assertion helpers for detail fields, autocomplete partial-match assertion, safer login/logout on stale sessions, better task-group and project helpers (assignBeneficiariesToProject, enterProjectTimeEntries, updateProjectStatus, approveLatestPaymentCycleTask), and a calculationParams-aware payment plan form filler.
Extract form, searcher, location, and constants into dedicated support modules, then move every payment domain (cycle, plan, point, payroll) plus tasks/programs/registry/UI commands onto them. Replace the stale "N X Found" post-search text waits with GraphQL-intercept aliasing (aliasGraphqlQuery + awaitSearcherRefresh) to eliminate filter/row-assert races, scope the payroll delete confirmation click to [role="dialog"] so the delete mutation fires reliably, move filterPayrolls' visitPending into its options object, and drop an unused payment-cycle fixture.
Adds the payroll-reconciliation Cypress spec covering both calc rule families (social-protection cash transfer and timesheet base-day-rate) end-to-end through the full PENDING_APPROVAL -> APPROVE_FOR_PAYMENT -> RECONCILED state machine, including UI-driven CSV download/edit/upload and the "Approve and Close" + payroll_reconciliation task approval that gates the terminal RECONCILED transition. Also fixes a payment-plan picker regression where long benefit-plan names were mangled during entry: the picker now searches by the unique 8-char program code (planData/fillPaymentPlanForm/assertPaymentPlanDetailFields all gain a benefitPlanCode parameter, preferred over name when present). New helpers: - payroll: parseReconciliationCsv, buildReconciliationCsv, downloadReconciliationFromUI, uploadReconciliationFromUI, approveAndClosePayrollFromSummary, approvePayrollReconciliationTask, approveAcceptPayrollTask, assertReconciliationSummary - programs: enterProjectTimeEntriesPerBeneficiary (per-beneficiary per-day work-percent entry against the timesheet project grid) Payment-cycle spec gains two tests: date-range filter coverage and an assertion that the payroll form's PaymentCyclePicker excludes non-ACTIVE cycles. .gitignore: ignore generated reconciliation CSV scratch directory and local dev artifacts.
|
There was a problem hiding this comment.
Pull request overview
Adds a Payments-domain Cypress E2E suite and refactors Cypress support code into domain-scoped command modules to improve reuse and reduce test flakiness across openIMIS Social Protection workflows.
Changes:
- Introduces Payments E2E specs covering payment plans, payment cycles, payment points, payrolls, and payroll reconciliation flows.
- Replaces the monolithic
cypress/support/commands.jswith domain-scopedcypress/support/commands/*modules plus shared helpers/constants. - Hardens/shared-izes common UI interactions (MUI date picker navigation, searcher refresh via GraphQL intercepts, journal-based save/wait helpers, task-approval helpers).
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| cypress/support/helpers/date.js | Adds shared date formatting helper used by program assertions. |
| cypress/support/e2e.js | Loads the new commands barrel from cypress/support/commands. |
| cypress/support/constants.js | Centralizes shared constants (timeouts, statuses, calc-rule labels). |
| cypress/support/commands/ui.commands.js | Adds reusable MUI UI helpers (inputs/selects/autocomplete/date-picker navigation). |
| cypress/support/commands/tasks.commands.js | Adds task-group setup + generic maker-checker task approval helpers. |
| cypress/support/commands/searcher.commands.js | Adds GraphQL-alias-based searcher refresh + row-action helpers to reduce flakiness. |
| cypress/support/commands/registry.commands.js | Adds/updates helpers for seeding individuals/households and counting standalone individuals. |
| cypress/support/commands/programs.commands.js | Extends program flows (schema support, project timesheet grid helpers). |
| cypress/support/commands/payments/payroll.commands.js | Adds payroll + reconciliation CSV download/upload + reconciliation summary helpers. |
| cypress/support/commands/payments/payment-point.commands.js | Adds payment point CRUD + filtering helpers. |
| cypress/support/commands/payments/payment-plan.commands.js | Adds payment plan CRUD, filtering, advanced criteria helpers. |
| cypress/support/commands/payments/payment-cycle.commands.js | Adds payment cycle CRUD/filter helpers including ACTIVE via task workflow. |
| cypress/support/commands/payments/index.js | Registers all payments-domain commands. |
| cypress/support/commands/location.commands.js | Adds unified location selection helper across mixed MUI widgets. |
| cypress/support/commands/index.js | Barrel that registers all command modules. |
| cypress/support/commands/grievance.commands.js | Moves grievance-related commands into a dedicated module. |
| cypress/support/commands/form.commands.js | Adds shared save/journal helpers (save click, await journal, assertions). |
| cypress/support/commands/auth.commands.js | Hardens login/logout + admin-interface login/logout. |
| cypress/support/commands/admin.commands.js | Adds admin UI helpers including frontend module config creation. |
| cypress/support/commands.js | Removes the prior monolithic Cypress commands file. |
| cypress/fixtures/individuals.csv | Adds standalone individuals rows needed for individual-program enrollment tests. |
| cypress/e2e/payroll.cy.js | Adds payroll workflow E2E coverage including timesheet payroll integration. |
| cypress/e2e/payroll-reconciliation.cy.js | Adds reconciliation state-machine E2E coverage (cash-transfer + timesheet). |
| cypress/e2e/payment-point.cy.js | Adds payment point E2E coverage (create/filter/edit/delete). |
| cypress/e2e/payment-plan.cy.js | Adds payment plan E2E coverage (criteria, versions, delete/history, date filters, timesheet rule). |
| cypress/e2e/payment-cycle.cy.js | Adds payment cycle E2E coverage including ACTIVE approval workflow and date filtering. |
| cypress.config.js | Preserves empty group_code while randomizing CSV so standalone individuals remain available. |
| .gitignore | Ignores Cypress videos and generated fixtures; adds common local env/editor ignores. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Use canonical /front/AllTasks URL in tasks.commands.js to match programs.commands.js and the URL the SPA actually serves at localhost:3000/front/AllTasks. Avoids relying on React Router's case-insensitive default. - Complete the truncated comment block above deletePayrollFromList so the warning about unscoped Ok matching is a full sentence.
|




Description
Adds Cypress E2E test coverage for the Payments domain — payment plans, payment cycles, payment points, payrolls, and payroll reconciliation. This PR also includes a foundational refactor of the monolithic
commands.jsinto domain-scoped modules and hardens shared support commands (login/logout resilience, MUI date input helper, frontend module config, searcher + form helpers, constants module).Type of Change
Related Issue(s) / Task(s)
Refactor: Command Module Split
cypress/support/commands.jsinto domain-scoped modules undercommands/(auth, admin, ui, form, searcher, location, programs, registry, tasks, grievance, payments)commands/index.jsregisters all modulesdate.jshelper (getTodayFormatted)constants.js(TIMEOUTS,CALC_RULES,PAYROLL_STATUS,PAYMENT_CYCLE_STATUS)cypress/support/commands/COMMANDS.mdandcypress/support/commands/payments/COMMANDS.mdso spec authors can pick existing helpers instead of re-implementing UI stepsRefactor: Shared Support Command Enhancements
cy.login()— check DOM for already-authenticated state before entering credentials; clear cookies for clean state; increased timeout to 30s; handle/front/login,/front, and authenticated redirect states as valid entrypointscy.logout()— handle already-logged-out state gracefully (assert login screen if already on it)cy.logoutAdminInterface()— guard against missing logout button (link or button element)enterDateInput/selectDateFromCalendarcommands that navigate the MUI DatePicker calendar popupsetFrontendModuleConfigcommand for frontend-layer module configurationchooseMuiAutocompletegeneric helper for MUI autocomplete fieldschooseFirstMuiSelect,toggleMuiCheckbox,assertMuiInputDisabled,assertMuiSelectValue,assertMuiAutoComplete,assertMuiInputNotEmptyhelperssaveClick,saveAndAwaitJournal,assertSave,assertSaveDisabled,assertSaveEnabled,waitForJournalProgress,assertJournalFirstEntryContains,assertJournalNoFail,createClickform helpersaliasGraphqlQuery+awaitSearcherRefresh(GraphQL-intercept aliasing replaces stale "N X Found" post-search text waits),resetSearcherFilters,assertTableRowVisible,assertTableRowNotVisible,openRowAction,openRowActionIfPresentchooseLocation+chooseLocationLevellocation-cascade helpersProgram / Project Enhancements
createProgramaccepts an optional 5thschemaparameter to set the beneficiary JSON schema during program creationeducated_level,able_bodied,number_of_children) passed to individual programs, enabling advanced criteria in payment plan and payroll formsenterProjectTimeEntriesPerBeneficiary(projectPath, daysByText)— sets per-beneficiary, per-day work-percent values against the timesheet project grid (token-based row matching tolerates first/last name in separate<td>cells; re-queries DOM on every cell to avoid stale-handle flakes from MUI table re-renders)Payment Plan —
payment-plan.cy.jsTest Cases (15 tests)
dateValidFrom/dateValidTo)Behaviour change — picker now uses program code, not name
The Program autocomplete on the payment plan form was failing intermittently because long benefit-plan names get visually truncated/mangled while typing into the MUI input. The picker now searches by the unique 8-char program code, with the human-readable name kept only for display assertions. This means:
planData(label, benefitPlanCode, benefitPlanName)— code is now the primary keyfillPaymentPlanForm({ ..., benefitPlanCode, benefitPlanName })—benefitPlanCodeis preferred when present, falls back tobenefitPlanNamefor legacy callersassertPaymentPlanDetailFields({ ..., benefitPlanCode, benefitPlanName })— same fallback patternCommand Helpers
cy.openCreatePaymentPlan()cy.fillPaymentPlanForm(...)cy.savePaymentPlan(mutationLabel?)cy.createPaymentPlan(...)cy.filterPaymentPlans(...)cy.resetPaymentPlanFilters()cy.assertPaymentPlanDetailFields(...)cy.assertPaymentPlanRowVisible(...)/cy.assertPaymentPlanRowNotVisible(...)cy.openPaymentPlanForEditFromList(...)cy.replacePaymentPlanFromList(...)cy.deletePaymentPlan(...)Payment Cycle —
payment-cycle.cy.jsTest Cases (13 tests)
PaymentCyclePickerexcludes non-ACTIVE cycles (asserts a PENDING cycle never appears in the autocomplete options on the payroll create form, since the picker queriespaymentCycle(status: ACTIVE))Command Helpers
cy.openCreatePaymentCycle()cy.fillPaymentCycleForm(...)cy.savePaymentCycle()coreAlertdialog and returns to listcy.createPaymentCycle(...)cy.filterPaymentCycles({ code, status, dateFrom, dateTo })cy.resetPaymentCycleFilters()cy.assertPaymentCycleDetailFields(...)cy.assertPaymentCycleRowVisible(...)/cy.assertPaymentCycleRowNotVisible(...)cy.openPaymentCycleForViewFromList(...)Payment Point —
payment-point.cy.jsTest Cases (16 tests, all passing)
Validates required fields, creates with full location hierarchy, verifies detail page, filters by name / PPM / Region / Region+District / Region+District+Municipality / full hierarchy, wrong-Region-no-match, cascading Region→District options, reset filters, view via eye icon, edits name, deletes from list, deletes from detail page.
Command Helpers
cy.openCreatePaymentPoint(),cy.fillPaymentPointForm(...),cy.savePaymentPoint(),cy.createPaymentPoint(...)cy.filterPaymentPoints(...),cy.resetPaymentPointFilters()cy.assertPaymentPointDetailFields(...),cy.assertPaymentPointRowVisible(...),cy.assertPaymentPointRowNotVisible(...)cy.openPaymentPointForViewFromList(...),cy.deletePaymentPointFromList(...)Payroll —
payroll.cy.jsTest Cases (12 tests)
Required-field validation, create + assert, search, view, delete (with
payroll_deletetask approval), pending list visibility, PENDING APPROVAL status assertion, summary dialog open/close, payment plan → cycle → payroll integration smoke, status filter, reset filters, timesheet-calcrule end-to-end.Command Helpers (existing)
cy.openCreatePayroll(),cy.fillPayrollForm(...),cy.savePayroll(),cy.createPayroll(...)cy.filterPayrolls(...),cy.resetPayrollFilters()cy.assertPayrollDetailFields(...),cy.assertPayrollRowVisible(...),cy.assertPayrollRowNotVisible(...)cy.openPayrollForViewFromList(...),cy.deletePayrollFromList(...)cy.openPayrollPendingSummary(...)/front/payrollsPendingcy.approveTaskFromList(...),cy.approveLatestPaymentCycleTask(),cy.ensurePermissiveTaskGroup(),cy.ensurePaymentCycleTaskGroup(...)Payroll Reconciliation —
payroll-reconciliation.cy.jsEnd-to-end coverage of the reconciliation state machine for both calc-rule families. Each test takes a payroll from
PENDING_APPROVALthroughAPPROVE_FOR_PAYMENTtoRECONCILED, including UI-driven CSV download, edit, and re-upload, plus the Approve and Close dialog action that creates thepayroll_reconciliationtask whose approval gates the final RECONCILED transition.Test Cases (4 implemented)
Cash transfer / social-protection calcrule:
social_protection-calcrule payment plan withStrategyOfflinePayment, creates a payroll, approves theaccept_payrolltask, downloads the reconciliation CSV from the UI, marks every row Paid=Yes with a unique receipt, re-uploads through the dialog, asserts the per-beneficiary amounts on the summary dialog, clicks Approve and Close, approves the resultingpayroll_reconciliationtask, and asserts payroll status = RECONCILED.Timesheet / base-day-rate calcrule:
timesheet-calcrule program (Base Day Rate = 100) with 4 beneficiaries assigned to a project; usesenterProjectTimeEntriesPerBeneficiaryto seed different day patterns per individual: full days (10), partial days (4 + half-days), zero days, mixed half-days. Verifies each beneficiary'sAmount = effective_days × BDRon the summary dialog (e.g., 5 days = 500, 10 days = 1000, mixed half-days = 400, etc.).payroll_reconciliationtask approval flow, and asserts payroll status = RECONCILED. (This stage previously appeared to be "missing" because the close+approve sequence was buried in nested.thenblocks; it is now lifted to outer scope so the flow mirrors the cash-transfer test.)Command Helpers
cy.parseReconciliationCsv(text){ headers, rows }from a reconciliation CSV string (handles the BE's 11-column layout)cy.buildReconciliationCsv(rows, headers?){ ... }rows back into CSV text usingRECONCILIATION_CSV_HEADERSordercy.downloadReconciliationFromUI()GET /api/payroll/csv_reconciliation/, returns{ headers, rows, csvText }cy.uploadReconciliationFromUI(payrollName, csvText)cypress/fixtures/_generated/recon_<safe>_<timestamp>.csv, opens the Upload Payment Data dialog, attaches the file, interceptsPOST /api/payroll/import_payroll_reconciliation/, surfaces backend error bodies on non-2xx responses. The timestamp suffix avoids the BE's "File already exists at the specified path" rejection on re-uploadcy.approveAcceptPayrollTask(payrollName)accept_payrolltask that transitions PENDING_APPROVAL → APPROVE_FOR_PAYMENTcy.approveAndClosePayrollFromSummary(payrollName)/front/payrollsApproved, opens the row's summary dialog and clicks Approve and Close (this is the action that creates thepayroll_reconciliationtask — the bit the original test design missed)cy.approvePayrollReconciliationTask(payrollName)payroll_reconciliationtask that finally transitions APPROVE_FOR_PAYMENT → RECONCILEDcy.assertReconciliationSummary(payrollName, { selected, total, totalAmount, totalDelivered })[role="dialog"]and asserts the four summary metrics (uses.should('exist')notbe.visiblebecause the dialog cards exist in DOM but aren't reported as visible by headless Electron)Reconciliation flow notes (for future contributors)
BenefitConsumption.status— it does not transition the payroll itself. The payroll → RECONCILED transition is gated on a user clicking Approve and Close on the summary dialog, which creates thepayroll_reconciliationtask. Approving that task is what flips the payroll's status.RELAY_CONNECTION_MAX_LIMIT=100— beneficiary GraphQL queries must usefirst: 100.APPROVE_FOR_PAYMENT, with underscores), not the UI label (APPROVE FOR PAYMENT). Compare against the literal enum.Demo
To be added after test runs are recorded.
Checklist
commands/<domain>.commands.js)after()hooks (payment plans, programs, payment points, payrolls where applicable)COMMANDS.md) added undercypress/support/commands/andcypress/support/commands/payments/so future spec authors can pick existing helpers instead of re-implementing UI flows