SatelliteHR e2e — issues found
15 Oct 2026, 00:14 IST · qa.satellitehr.com · Attendance & Leave + Feedback tracker · full test report · BUGS.md · bugs.json
2 new failures · 0 regressions · 11 open issues · 7 sheet gaps · 0 no longer reproduce · 2 working
90 tests: 65 passed · 23 failed · 2 skipped · run failed
| Issue | Description | Module | Submodule | Status | Expected result | Actual result | Total test coverage |
|---|---|---|---|---|---|---|---|
| New | No logged issue: web clock-in and clock-out record the day against the shift (rows 1–3) | Attendance | Clock in / out | New failure — triage | web clock-in and clock-out record the day against the shift (rows 1–3) | expect(locator).toBeVisible() failed
Locator: getByRole('dialog').filter({ hasText: /Clocking in at/ }).last().getByText(/Today:/)
Expected: visible
Timeout: 30000ms
Error: element(s) not found full errorweb clock-in and clock-out record the day against the shift (rows 1–3) Error: expect(locator).toBeVisible() failed
Locator: getByRole('dialog').filter({ hasText: /Clocking in at/ }).last().getByText(/Today:/)
Expected: visible
Timeout: 30000ms
Error: element(s) not found
Call log:
- Expect "toBeVisible" getByRole('dialog').filter({ hasText: /Clocking in at/ }).last().getByText(/Today:/) with timeout 30000ms
- waiting for getByRole('dialog').filter({ hasText: /Clocking in at/ }).last().getByText(/Today:/)
- found getByRole('dialog').filter({ hasText: 'Start today\'s clock' }), intercepting action to run the handler
- locator handler has finished, waiting for getByRole('dialog').filter({ hasText: 'Start today\'s clock' }) to be hidden
- interception handler has finished, continuing | 1 test: 1 failtests
|
| New | No logged issue: policy set matches the reviewed baseline | Leave | Policies | New failure — triage | policy set matches the reviewed baseline | expect(string).toMatchSnapshot(expected) failed
@@ -144,11 +144,11 @@
"name": "Paid Time Off — handbook 16.1",
"accrual": {
"rate": 1.25,
"frequency": "monthly",
"proration": true,
+ "startNextMonth": true
},
"carryForward": { full errorpolicy set matches the reviewed baseline Error: expect(string).toMatchSnapshot(expected) failed
@@ -144,11 +144,11 @@
"name": "Paid Time Off — handbook 16.1",
"accrual": {
"rate": 1.25,
"frequency": "monthly",
"proration": true,
- "waitingDays": 30
+ "startNextMonth": true
},
"carryForward": {
"maxDays": 30
}, | 1 test: 1 failtests
|
| ISS-422 | Punch times are stored 5½ hours ahead (IST wall time saved as UTC) | Attendance | clock-in | Open — reproduces | Store real UTC (05:16:51Z), or store local time without a Z, together with the employee's time zone. | server "now" 2026-10-15T00:14:28Z vs real UTC 2026-10-14T18:44:28.537Z
expect(received).toBeLessThan(expected)
Expected: < 10
Received: 329.99105 full errorISS-422 · punch times are stored as real UTC Error: server "now" 2026-10-15T00:14:28Z vs real UTC 2026-10-14T18:44:28.537Z expect(received).toBeLessThan(expected) Expected: < 10 Received: 329.99105 | 1 test: 1 failtests
|
| ISS-444 | Managers, department heads and HR SPOC are offered Bulk assign and roster edits, but every save is refused (403) with no message | Attendance | Shifts & rosters | Open — reproduces | Either give these roles roster rights (the sheet has reporting managers build and assign the roster, and HR SPOC configure shifts), or hide Bulk assign / Upload roster / chip editing for them. In any case, show the refusal in the dialog. | expect(received).toBe(expected) // Object.is equality
Expected: false
Received: true full errorISS-444 · mgr can save the roster it is shown (rows 36–37) Error: expect(received).toBe(expected) // Object.is equality Expected: false Received: true ISS-444 · dh can save the roster it is shown (rows 36–37) Error: expect(received).toBe(expected) // Object.is equality Expected: false Received: true ISS-444 · spoc can save the roster it is shown (rows 36–37) Error: expect(received).toBe(expected) // Object.is equality Expected: false Received: true | 3 tests: 3 failtests
|
| ISS-445 | My attendance says "Off today — enjoy the day" on a working day, and a holiday gets a rostered shift | Attendance | My attendance | Open — reproduces | "Your shift" shows today's rostered shift on a working day; bulk assign skips holidays (or warns), and the schedule shows the holiday. | expect(locator).not.toContainText(expected) failed
Locator: locator('#main-content').getByText('Your shift', { exact: true }).locator('xpath=ancestor::*[3]')
Expected pattern: not /Off today/
Received string: "Your shiftFrom your team’s work scheduleSwap a shiftOff today — enjoy the dayGeneral hoursSwap with QA Employee Two · in 6 days · cancelledSwap with QA Employee Two · 12 Nov · cancelledSwap … morewith QA Employee Two · 22 Oct · rejectedSwap with QA Employee Two · 12 Nov · approvedSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 29 Oct · cancelledSwap with QA Employee Two · 4 Nov · rejectedSwap with QA Employee Two · 11 Nov · approvedSwap with QA Employee Two · 11 Nov · cancelledSwap with QA Employee Two · 16 Nov · cancelledSwap with QA Employee Two · 27 Oct · rejectedSwap with QA Employee Two · 26 Oct · cancelledSwap with QA Employee Two · 28 Oct · cancelledSwap with QA Employee Two · 17 Nov · cancelledSwap with QA Employee Two · 4 Nov · rejectedSwap with QA Employee Two · 18 Nov · approvedSwap with QA Employee Two · 3 Nov · cancelledSwap with QA Employee Two · 18 Nov · cancelledSwap with QA Employee Two · 11 Nov · rejectedSwap with QA Employee Two · 23 Oct · approvedSwap with QA Employee Two · 23 Oct · approvedSwap with QA Employee Two · 22 Oct · cancelledSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 22 Oct · rejectedSwap with QA Employee Two · in 6 days · approved" Timeout: 30000ms 63 × locator resolved to <div class="rounded-lg border border-edge bg-surface shadow-xs">…</div>full errorISS-445 · "Your shift" shows the shift on a working day, not "Off today" Error: expect(locator).not.toContainText(expected) failed
Locator: locator('#main-content').getByText('Your shift', { exact: true }).locator('xpath=ancestor::*[3]')
Expected pattern: not /Off today/
Received string: "Your shiftFrom your team’s work scheduleSwap a shiftOff today — enjoy the dayGeneral hoursSwap with QA Employee Two · in 6 days · cancelledSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 22 Oct · rejectedSwap with QA Employee Two · 12 Nov · approvedSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 29 Oct · cancelledSwap with QA Employee Two · 4 Nov · rejectedSwap with QA Employee Two · 11 Nov · approvedSwap with QA Employee Two · 11 Nov · cancelledSwap with QA Employee Two · 16 Nov · cancelledSwap with QA Employee Two · 27 Oct · rejectedSwap with QA Employee Two · 26 Oct · cancelledSwap with QA Employee Two · 28 Oct · cancelledSwap with QA Employee Two · 17 Nov · cancelledSwap with QA Employee Two · 4 Nov · rejectedSwap with QA Employee Two · 18 Nov · approvedSwap with QA Employee Two · 3 Nov · cancelledSwap with QA Employee Two · 18 Nov · cancelledSwap with QA Employee Two · 11 Nov · rejectedSwap with QA Employee Two · 23 Oct · approvedSwap with QA Employee Two · 23 Oct · approvedSwap with QA Employee Two · 22 Oct · cancelledSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 22 Oct · rejectedSwap with QA Employee Two · in 6 days · approved"
Timeout: 30000ms
Call log:
- Expect "not toContainText" locator('#main-content').getByText('Your shift', { exact: true }).locator('xpath=ancestor::*[3]') with timeout 30000ms
- waiting for locator('#main-content').getByText('Your shift', { exact: true }).locator('xpath=ancestor::*[3]')
63 × locator resolved to <div class="rounded-lg border border-edge bg-surface shadow-xs">…</div>
- unexpected value "Your shiftFrom your team’s work scheduleSwap a shiftOff today — enjoy the dayGeneral hoursSwap with QA Employee Two · in 6 days · cancelledSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 22 Oct · rejectedSwap with QA Employee Two · 12 Nov · approvedSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 29 Oct · cancelledSwap with QA Employee Two · 4 Nov · rejectedSwap with QA Employee Two · 11 Nov · approvedSwap with QA Employee Two · 11 Nov · cancelledSwap with QA Employee Two · 16 Nov · cancelledSwap with QA Employee Two · 27 Oct · rejectedSwap with QA Employee Two · 26 Oct · cancelledSwap with QA Employee Two · 28 Oct · cancelledSwap with QA Employee Two · 17 Nov · cancelledSwap with QA Employee Two · 4 Nov · rejectedSwap with QA Employee Two · 18 Nov · approvedSwap with QA Employee Two · 3 Nov · cancelledSwap with QA Employee Two · 18 Nov · cancelledSwap with QA Employee Two · 11 Nov · rejectedSwap with QA Employee Two · 23 Oct · approvedSwap with QA Employee Two · 23 Oct · approvedSwap with QA Employee Two · 22 Oct · cancelledSwap with QA Employee Two · 12 Nov · cancelledSwap with QA Employee Two · 22 Oct · rejectedSwap with QA Employee Two · in 6 days · approved" | 1 test: 1 failtests
|
| ISS-437/439 | (follow-up to ISS-437) The manager-approved request with unpaid days ends as "Rejected" after the posting retries run out | Leave | ledger posting | Open — reproduces | The request is posted as 1.25 days PTO + 1.75 days loss of pay and ends Approved. A system failure after approval should never look like the manager's rejection. | timed out waiting for request decided full errorISS-437/439 · approved leave with confirmed unpaid days is posted and stays approved (row 15) Error: timed out waiting for request decided | 1 test: 1 failtests
|
| ISS-440 | Balances show a male employee with 182 days of Maternity Leave, and annual leave types credited twice | Leave | balances & accrual | Open — reproduces | Gender-restricted types are credited only to eligible employees, and each annual entitlement is credited once per year (Wedding 7, Floating 2, Bereavement 10). | expect(received).toEqual(expected) // deep equality
- Expected - 1
+ Received + 6
- Array []
+ Array [
+ "Aarav Krishnamurthy.: maternity 182",
+ "Kavya Raghunathan: paternity 5",
+ "Test Interviewer One: paternity 5",
+ "Test Interviewer Two: maternity 182",
+ ] full errorISS-440 · nobody is credited leave types restricted to another gender, or more than the yearly entitlement Error: expect(received).toEqual(expected) // deep equality - Expected - 1 + Received + 6 - Array [] + Array [ + "Aarav Krishnamurthy.: maternity 182", + "Kavya Raghunathan: paternity 5", + "Test Interviewer One: paternity 5", + "Test Interviewer Two: maternity 182", + ] | 1 test: 1 failtests
|
| ISS-446 | PTO credited in the joining month despite the policy's 30-day wait (and shown rounded as 1.3d) | Leave | accrual | Open — reproduces | No PTO credit before the waiting period ends (first credit 1 Nov for a 1 Oct joiner); ledger amounts shown to two decimals. | expect(received).toEqual(expected) // deep equality
- Expected - 1
+ Received + 3
- Array []
+ Array [
+ "2026-10-09 1.25 policy_entitlement:2026-10",
+ ] full errorISS-446 · no PTO is credited before the policy’s waiting period ends Error: expect(received).toEqual(expected) // deep equality - Expected - 1 + Received + 3 - Array [] + Array [ + "2026-10-09 1.25 policy_entitlement:2026-10", + ] | 1 test: 1 failtests
|
| ISS-447 | Service Leave's policy form can't show its anniversary rule: blank accrual, "Entitlement can't be negative", list says "—d / year" | Leave | policies | Open — reproduces | The form supports the rule it stores: anniversary accrual, days per year of service, a yearly maximum, expiry months, and shows "2 days per year of service, up to 10" in the list. | expect(locator).toHaveCount(expected) failed
Locator: getByRole('dialog').filter({ hasText: /Edit policy/ }).last().getByText(/Entitlement can't be negative/)
Expected: 0
Received: 1
Timeout: 30000ms
62 × locator resolved to 1 element full errorISS-447 · the Service Leave policy form shows its rule without a validation error Error: expect(locator).toHaveCount(expected) failed
Locator: getByRole('dialog').filter({ hasText: /Edit policy/ }).last().getByText(/Entitlement can't be negative/)
Expected: 0
Received: 1
Timeout: 30000ms
Call log:
- Expect "toHaveCount" getByRole('dialog').filter({ hasText: /Edit policy/ }).last().getByText(/Entitlement can't be negative/) with timeout 30000ms
- waiting for getByRole('dialog').filter({ hasText: /Edit policy/ }).last().getByText(/Entitlement can't be negative/)
62 × locator resolved to 1 element
- unexpected value "1" | 1 test: 1 failtests
|
| ISS-450 | PTO policy changed on the tenant: the 30-day waiting period was replaced by "start next month", and the October credit stays | Leave | policies | Open — reproduces | Changes to the policy rules are intended and reviewed, and the 30-day wait (handbook / sheet rows 48–51) is kept or replaced on purpose. Credits that conflict with the current rule are reversed. | expect(received).toMatchObject(expected)
- Expected - 1
+ Received + 0
Object {
"frequency": "monthly",
"rate": 1.25,
- "waitingDays": 30,
} full errorPTO: 1.25 days a month after 30 days, carry-forward 30, LOP fallback (rows 48–51, 60) Error: expect(received).toMatchObject(expected)
- Expected - 1
+ Received + 0
Object {
"frequency": "monthly",
"rate": 1.25,
- "waitingDays": 30,
} | 1 test: 1 failtests
|
| ISS-453 | A pending Leave Without Pay request can't be withdrawn: "Protected run… forced by the platform tier" | Leave | my leave | Open — reproduces | Sheet row 18: an employee can withdraw any pending request at once. A platform-enforced workflow may stop the company from editing or rerouting the run, but not stop the requester from withdrawing it. If withdrawal really isn't allowed, don't offer "Cancel thi… mores request", and explain it in plain words. | timed out waiting for request withdrawn full errorISS-453 · a pending Leave Without Pay request can be withdrawn (row 18) Error: timed out waiting for request withdrawn | 1 test: 1 failtests
|
| ISS-441 | "Request comp-off" (earning a day for weekend work) is rejected for having no comp-off balance | Overtime & comp-off | Comp-Off Request workflow | Open — reproduces | A request to earn comp-off goes to the reporting manager (and HR head, per the sheet), and on approval credits the day to the Comp-off balance with its 90-day expiry. | expect(received).toBe(expected) // Object.is equality
Expected: false
Received: true
timed out waiting for manager task full errorISS-441 · earning comp-off does not require an existing comp-off balance Error: expect(received).toBe(expected) // Object.is equality Expected: false Received: true ISS-441 · a request to earn comp-off for a weekend reaches the manager (rows 29–30) Error: timed out waiting for manager task | 2 tests: 2 failtests
|
| ISS-452 | (update to ISS-436) Long leave now reaches the department head, but its 3-day threshold is still not a parameter | Workflows | leave approval | Open — reproduces | lv.long_leave_days is listed with its value (3) and source, like the other lv.* parameters, so changing it is a recorded settings change. | expect(received).toContain(expected) // indexOf
Expected value: "lv.long_leave_days"
Received array: ["ext.ceo_pack_sla", "ext.clearance_trigger", "ext.counteroffer_issue_sla", "ext.counteroffer_response_sla", "ext.damage_assessment_sla", "ext.escalate_to_hr_sla", "ext.exit_docs_sla", "ext.ffs_clear_sla", "ext.ffs_gratuity_target", "ext.ffs_l1", …] full errorISS-452 · the long-leave threshold used by leave approval is a visible parameter Error: expect(received).toContain(expected) // indexOf Expected value: "lv.long_leave_days" Received array: ["ext.ceo_pack_sla", "ext.clearance_trigger", "ext.counteroffer_issue_sla", "ext.counteroffer_response_sla", "ext.damage_assessment_sla", "ext.escalate_to_hr_sla", "ext.exit_docs_sla", "ext.ffs_clear_sla", "ext.ffs_gratuity_target", "ext.ffs_l1", …] | 1 test: 1 failtests
|
| GAPS row 33 GAPS.md row 33 | HR SPOC has no balance-adjust right on this tenant (GAPS.md row 33) | Access | Roles & permissions | Gap — not supported | HR SPOC can adjust special leave balances | expect(received).toBe(expected) // Object.is equality
Expected: false
Received: true full errorGAPS row 33 · HR SPOC can adjust special leave balances Error: expect(received).toBe(expected) // Object.is equality Expected: false Received: true | 1 test: 1 failtests
|
| GAPS row 34 GAPS.md row 34 | HR SPOC is view-only on leave policies on this tenant (GAPS.md row 34) | Access | Roles & permissions | Gap — not supported | HR SPOC can change leave configuration | expect(received).toBe(expected) // Object.is equality
Expected: false
Received: true full errorGAPS row 34 · HR SPOC can change leave configuration Error: expect(received).toBe(expected) // Object.is equality Expected: false Received: true | 1 test: 1 failtests
|
| GAPS row 22 GAPS.md row 22 | Back-dated WFH is accepted and sent to the manager (GAPS.md row 22) | Attendance | Work from home | Gap — not supported | back-dated work from home is refused | expect(received).toBeGreaterThanOrEqual(expected)
Expected: >= 400
Received: 201 full errorGAPS row 22 · back-dated work from home is refused Error: expect(received).toBeGreaterThanOrEqual(expected) Expected: >= 400 Received: 201 | 1 test: 1 failtests
|
| GAPS row 25 GAPS.md row 25 | No HR SPOC step in the WFH workflow (GAPS.md row 25) | Attendance | Work from home | Gap — not supported | long WFH gets an HR SPOC review | timed out waiting for HR SPOC task full errorGAPS row 25 · long WFH gets an HR SPOC review Error: timed out waiting for HR SPOC task | 1 test: 1 failtests
|
| GAPS row 42 GAPS.md row 42 | Eligibility does not check identical shifts (GAPS.md row 42) | Attendance | Shift swap | Gap — not supported | a swap between identical shifts is refused | expect(received).toBeGreaterThanOrEqual(expected)
Expected: >= 400
Received: 201 full errorGAPS row 42 · a swap between identical shifts is refused Error: expect(received).toBeGreaterThanOrEqual(expected) Expected: >= 400 Received: 201 | 1 test: 1 failtests
|
| GAPS row 43 GAPS.md row 43 | No peer acceptance: the swap goes straight to the manager (GAPS.md row 43) | Attendance | Shift swap | Gap — not supported | the teammate is asked to accept a swap first | timed out waiting for teammate task full errorGAPS row 43 · the teammate is asked to accept a swap first Error: timed out waiting for teammate task | 1 test: 1 failtests
|
| GAPS row 1 | Half-day cut-off is 4 hours on this tenant; the sheet asks for 8 (GAPS.md row 1) | Leave | Policies | Gap — not supported | days under 8 hours count as half days | expect(received).toBe(expected) // Object.is equality
Expected: 8
Received: 4 full errorGAPS row 1 · days under 8 hours count as half days Error: expect(received).toBe(expected) // Object.is equality Expected: 8 Received: 4 | 1 test: 1 failtests
|
| ISS-451 | "Correct a day" says nothing when the server refuses the request (e.g. a day before joining); the picker offers those days | Attendance | regularization | Fixed — regression check passes | The server's message is shown in the drawer. Days before the joining date are disabled in the picker. | As expected: 1 check passed. | 1 test: 1 passtests
|
| ISS-436 | Leave of three days or more skips the department head (parameter lv.long_leave_days is not defined) | Leave | Annual Leave Approval workflow | Fixed — regression check passes | With 3 consecutive days the request goes to Department head approval (sheet row 14: 2 levels for ≥ 3 days). The parameter should exist (default 3), or the designer should refuse to publish a condition that names a missing parameter. | As expected: 1 check passed. | 1 test: 1 passtests
|
Test coverage by module
| Module | Submodule | Tests | Passed | Failed | Not run | Issues covered |
|---|---|---|---|---|---|---|
| Access | Roles & permissions | 11 | 6 | 5 | 0 | 3 |
| Attendance | Clock in / out | 1 | 0 | 1 | 0 | 0 |
| Attendance | Regularization | 3 | 3 | 0 | 0 | 1 |
| Attendance | Settings | 1 | 1 | 0 | 0 | 0 |
| Attendance | Shift swap | 4 | 2 | 2 | 0 | 2 |
| Attendance | Shifts & roster | 1 | 1 | 0 | 0 | 0 |
| Attendance | Work from home | 6 | 4 | 2 | 0 | 2 |
| General | Pages load | 18 | 18 | 0 | 0 | 0 |
| Home | Dashboard | 1 | 1 | 0 | 0 | 0 |
| Leave | Approval & cancellation | 3 | 3 | 0 | 0 | 0 |
| Leave | Approval routing | 1 | 1 | 0 | 0 | 1 |
| Leave | Balances | 1 | 1 | 0 | 0 | 0 |
| Leave | Comp-off | 3 | 0 | 1 | 2 | 2 |
| Leave | Policies | 7 | 4 | 3 | 0 | 2 |
| Leave | Request validation | 1 | 1 | 0 | 0 | 0 |
| Leave | Requests | 2 | 0 | 2 | 0 | 2 |
| Leave & Attendance | Data integrity | 5 | 0 | 5 | 0 | 5 |
| Reports | Downloads | 2 | 2 | 0 | 0 | 0 |
| Workflows | Leave & attendance workflows | 19 | 17 | 2 | 0 | 2 |
| Total | 90 | 65 | 23 | 2 | 22 |