54 KiB
54 KiB
> rentaldrivego@1.0.0 test:api
> npm run test --workspace @rentaldrivego/api
> @rentaldrivego/api@1.0.0 pretest
> npm run build --workspace @rentaldrivego/types
> @rentaldrivego/types@1.0.0 build
> tsc
> @rentaldrivego/api@1.0.0 test
> vitest run
The CJS build of Vite's Node API is deprecated. See https://vite.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.
RUN v1.6.1 /Volumes/ExternalApps/Documents/car_management_system/apps/api
❯ src/modules/site/site.service.boundary.test.ts (5 tests | 3 failed) 14ms
❯ src/modules/site/site.service.boundary.test.ts > site.service public booking/payment boundaries > calculates booking totals from base rate, free-day promo, pricing rules, insurance and additional drivers
→ Cannot read properties of undefined (reading 'catch')
❯ src/modules/site/site.service.boundary.test.ts > site.service public booking/payment boundaries > rejects payment initialization for already-paid reservations before provider calls
→ expected AppError: Booking access token is required { …(3) } to match object { statusCode: 409, …(1) }
(3 matching properties omitted from actual)
❯ src/modules/site/site.service.boundary.test.ts > site.service public booking/payment boundaries > blocks payment when the primary or additional driver license requires review
→ expected AppError: Booking access token is required { …(3) } to match object { statusCode: 409, …(1) }
(3 matching properties omitted from actual)
✓ src/modules/marketplace/marketplace.test.ts (16 tests) 17ms
✓ src/modules/vehicles/vehicle.pricing.service.test.ts (7 tests) 8ms
✓ src/modules/payments/payment.service.test.ts (7 tests) 8ms
✓ src/modules/subscriptions/subscription.service.edge.test.ts (7 tests) 8ms
✓ src/modules/reservations/reservation.test.ts (14 tests) 11ms
✓ src/modules/vehicles/vehicle.test.ts (15 tests) 10ms
❯ src/modules/site/site.test.ts (13 tests | 5 failed) 20ms
❯ src/modules/site/site.test.ts > createBooking > creates a booking and returns reservation with requiresManualApproval flag
→ [vitest] No "createReservationPublicAccess" export is defined on the "./site.repo" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:
❯ src/modules/site/site.test.ts > initPayment — payment guard paths > throws AppError when reservation is already paid
→ expected AppError: Booking access token is required { …(3) } to match object { error: 'already_paid' }
(3 matching properties omitted from actual)
❯ src/modules/site/site.test.ts > initPayment — payment guard paths > throws AppError when license review is required
→ expected AppError: Booking access token is required { …(3) } to match object { error: 'license_review_required' }
(3 matching properties omitted from actual)
❯ src/modules/site/site.test.ts > initPayment — payment guard paths > throws AppError when PayPal is not configured
→ expected AppError: Booking access token is required { …(3) } to match object { error: 'provider_not_configured' }
(3 matching properties omitted from actual)
❯ src/modules/site/site.test.ts > initPayment — payment guard paths > returns checkoutUrl when PayPal is configured
→ Booking access token is required
✓ src/modules/menu/menu.service.test.ts (2 tests) 4ms
❯ src/modules/menu/menu.service.boundary.test.ts (7 tests | 4 failed) 13ms
❯ src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > rejects external links that are not HTTPS before any write
→ expected AppError: External links must use HTTPS. { …(3) } to match object { statusCode: 400, …(1) }
(3 matching properties omitted from actual)
❯ src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > rejects duplicate routes under the same parent with a conflict error
→ expected AppError: Parent menu item was not found. { …(3) } to match object { statusCode: 409, …(1) }
(3 matching properties omitted from actual)
❯ src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > protects required menu items from non-super-admin disable attempts
→ expected AppError: Required system items can only … { …(3) } to match object { statusCode: 403, code: 'forbidden' }
(3 matching properties omitted from actual)
❯ src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > rejects company assignments when any company is cancelled or missing
→ expected AppError: Menu items can only be assigned… { …(3) } to match object { statusCode: 400, …(1) }
(3 matching properties omitted from actual)
✓ src/services/containerService.test.ts (4 tests) 8ms
✓ src/middleware/requireAdminAuth.test.ts (9 tests) 7ms
✓ src/modules/customers/customer.test.ts (12 tests) 38ms
✓ src/modules/reservations/reservation.lifecycle.service.test.ts (5 tests) 6ms
✓ src/modules/reviews/review.service.test.ts (5 tests) 8ms
✓ src/modules/auth/auth.company.service.test.ts (6 tests) 6ms
✓ src/modules/customers/customer.edge.test.ts (6 tests) 6ms
✓ src/modules/analytics/analytics.service.test.ts (4 tests) 5ms
✓ src/modules/auth/auth.employee.service.edge.test.ts (8 tests) 8ms
❯ src/tests/api/auth-middleware.api.test.ts (8 tests | 2 failed) 55ms
❯ src/tests/api/auth-middleware.api.test.ts > auth middleware API boundaries > rejects employee-protected routes when a renter token is used
→ expected { error: 'invalid_token', …(2) } to deeply equal { error: 'invalid_token', …(2) }
❯ src/tests/api/auth-middleware.api.test.ts > auth middleware API boundaries > allows valid admin tokens through protected admin read routes
→ expected 403 to be 200 // Object.is equality
❯ src/tests/api/public-validation.api.test.ts (8 tests | 1 failed) 58ms
❯ src/tests/api/public-validation.api.test.ts > public validation API contracts > defaults site payment currency to MAD for valid public payment requests
→ expected 400 to be 200 // Object.is equality
✓ src/tests/api/auth-boundaries.api.test.ts (7 tests) 60ms
✓ src/tests/api/operations.api.test.ts (10 tests) 73ms
✓ src/modules/companies/company.service.edge.test.ts (7 tests) 8ms
✓ src/tests/api/customer-notification-analytics.api.test.ts (7 tests) 79ms
✓ src/tests/api/operations-validation.api.test.ts (6 tests) 60ms
✓ src/tests/api/company-configuration.api.test.ts (7 tests) 90ms
✓ src/modules/customers/customer.service.boundary.test.ts (6 tests) 6ms
✓ src/middleware/requireApiKey.test.ts (6 tests) 10ms
✓ src/modules/reservations/reservation.inspection.service.test.ts (5 tests) 8ms
✓ src/modules/companies/company.test.ts (10 tests) 7ms
✓ src/services/notificationService.test.ts (3 tests) 5ms
✓ src/services/financialReportService.test.ts (4 tests) 9ms
✓ src/modules/marketplace/marketplace.repo.edge.test.ts (6 tests) 6ms
✓ src/middleware/requireCompanyAuth.test.ts (6 tests) 9ms
❯ src/tests/api/employee-marketplace-notification.api.test.ts (0 test)
✓ src/services/paypalService.test.ts (4 tests) 12ms
✓ src/modules/vehicles/vehicle.service.edge.test.ts (5 tests) 6ms
✓ src/modules/subscriptions/subscription.repo.edge.test.ts (6 tests) 8ms
✓ src/services/vehicleAvailabilityService.test.ts (5 tests) 6ms
stderr | src/services/notificationLocalizationService.boundary.test.ts > notificationLocalizationService formatting and fallback boundaries > throws a clear error when neither requested nor fallback templates exist
[Notifications] Missing fr template for missing.template/EMAIL; falling back to en.
✓ src/services/notificationLocalizationService.boundary.test.ts (8 tests) 15ms
✓ src/modules/site/site.repo.edge.test.ts (5 tests) 5ms
✓ src/modules/marketplace/marketplace.service.edge.test.ts (5 tests) 5ms
✓ src/middleware/requireRenterAuth.test.ts (6 tests) 8ms
✓ src/services/pricingRuleService.test.ts (3 tests) 5ms
✓ src/modules/subscriptions/subscription.entitlement.test.ts (5 tests) 13ms
❯ src/tests/api/feedback-offer-boundaries.api.test.ts (0 test)
✓ src/modules/vehicles/vehicle.schemas.test.ts (7 tests) 7ms
❯ src/tests/api/subscription-team-boundaries.api.test.ts (0 test)
❯ src/tests/api/admin-billing.api.test.ts (6 tests | 5 failed) 73ms
❯ src/tests/api/admin-billing.api.test.ts > admin billing API contracts > coerces list filters and requires finance access
→ expected 403 to be 200 // Object.is equality
❯ src/tests/api/admin-billing.api.test.ts > admin billing API contracts > rejects oversized billing pagination before service execution
→ expected 403 to be 400 // Object.is equality
❯ src/tests/api/admin-billing.api.test.ts > admin billing API contracts > streams invoice PDFs with content headers from the service boundary
→ expected 403 to be 200 // Object.is equality
❯ src/tests/api/admin-billing.api.test.ts > admin billing API contracts > passes parsed account updates with admin identity and request ip
→ expected 403 to be 200 // Object.is equality
❯ src/tests/api/admin-billing.api.test.ts > admin billing API contracts > rejects malformed draft invoice payloads before invoice creation
→ expected 403 to be 400 // Object.is equality
✓ src/modules/auth/auth.company.repo.test.ts (1 test) 6ms
✓ src/modules/vehicles/vehicle.repo.edge.test.ts (5 tests) 7ms
✓ src/tests/api/vehicle-pricing.api.test.ts (5 tests) 68ms
✓ src/modules/notifications/notification.repo.edge.test.ts (6 tests) 10ms
✓ src/modules/offers/offer.repo.edge.test.ts (5 tests) 7ms
✓ src/modules/notifications/notification.service.test.ts (4 tests) 5ms
✓ src/modules/companies/company.repo.edge.test.ts (6 tests) 6ms
✓ src/services/amanpayService.test.ts (4 tests) 14ms
✓ src/modules/companies/company.presenter.test.ts (14 tests) 4ms
✓ src/modules/auth/auth.schemas.test.ts (3 tests) 5ms
❯ src/tests/api/admin-menu-boundaries.api.test.ts (5 tests | 5 failed) 76ms
❯ src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > rejects menu item creation with blank labels before service execution
→ expected 403 to be 400 // Object.is equality
❯ src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > passes normalized menu item creation payload with admin actor
→ expected 403 to be 201 // Object.is equality
❯ src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > rejects invalid menu status bodies before mutation
→ expected 403 to be 400 // Object.is equality
❯ src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > requires admin privileges for menu mutations while support can preview
→ expected 403 to be 200 // Object.is equality
❯ src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > coerces audit-log pagination defaults and caps oversized limits
→ expected 403 to be 200 // Object.is equality
✓ src/modules/reservations/reservation.repo.edge.test.ts (4 tests) 4ms
✓ src/modules/complaints/complaint.service.test.ts (5 tests) 5ms
✓ src/modules/offers/offer.service.test.ts (5 tests) 4ms
✓ src/modules/auth/auth.role-specific-schemas.test.ts (5 tests) 5ms
✓ src/modules/reservations/reservation.presenter.boundary.test.ts (6 tests) 4ms
❯ src/http/errors/errorMiddleware.test.ts (10 tests | 1 failed) 10ms
❯ src/http/errors/errorMiddleware.test.ts > errorMiddleware > falls back to a 500 internal error response
→ expected "spy" to be called with arguments: [ { error: 'internal_error', …(2) } ]
Received:
1st spy call:
Array [
Object {
"error": "internal_error",
- "message": "boom",
+ "message": "Internal server error",
+ "requestId": undefined,
"statusCode": 500,
},
]
Number of calls: 1
✓ src/modules/reservations/reservation.document.service.test.ts (3 tests) 2ms
✓ src/modules/auth/auth.presenter.test.ts (4 tests) 3ms
✓ src/modules/reservations/reservation.photo.service.test.ts (4 tests) 4ms
✓ src/modules/auth/auth.renter.service.test.ts (5 tests) 5ms
✓ src/modules/operations.schemas.test.ts (2 tests) 6ms
✓ src/services/notificationLocalizationService.test.ts (3 tests) 5ms
stderr | src/services/notificationLocalizationService.test.ts > notificationLocalizationService > falls back to English when a localized template is missing
[Notifications] Missing ar template for booking.confirmed/EMAIL; falling back to en.
❯ src/tests/api/payments.api.test.ts (5 tests | 2 failed) 94ms
❯ src/tests/api/payments.api.test.ts > payments API contract > accepts valid AmanPay webhooks and delegates the exact payload
→ expected "spy" to be called with arguments: [ { transaction_id: 'txn_1', …(1) } ]
Received:
1st spy call:
Array [
Object {
"status": "PAID",
"transaction_id": "txn_1",
},
+ "{\"transaction_id\":\"txn_1\",\"status\":\"PAID\"}",
]
Number of calls: 1
❯ src/tests/api/payments.api.test.ts > payments API contract > accepts verified PayPal webhooks and delegates handling
→ expected "spy" to be called with arguments: [ { …(2) } ]
Received:
1st spy call:
Array [
Object {
"event_type": "PAYMENT.CAPTURE.COMPLETED",
"resource": Object {
"id": "capture_1",
},
},
+ "{\"event_type\":\"PAYMENT.CAPTURE.COMPLETED\",\"resource\":{\"id\":\"capture_1\"}}",
]
Number of calls: 1
❯ src/modules/site/site.schemas.test.ts (4 tests | 1 failed) 12ms
❯ src/modules/site/site.schemas.test.ts > site.schemas > rejects malformed availability and payment payloads at the schema layer
→ [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"accessToken"
],
"message": "Required"
}
]
✓ src/services/insuranceService.test.ts (2 tests) 4ms
✓ src/tests/api/site-webhook-boundaries.api.test.ts (5 tests) 116ms
✓ src/modules/companies/company.schemas.edge.test.ts (3 tests) 8ms
✓ src/services/additionalDriverService.test.ts (3 tests) 5ms
✓ src/middleware/rateLimiter.test.ts (3 tests) 11ms
✓ src/modules/payments/payment.repo.edge.test.ts (5 tests) 7ms
✓ src/modules/reservations/reservation.schemas.edge.test.ts (3 tests) 7ms
✓ src/lib/storage.test.ts (4 tests) 4ms
❯ src/tests/api/subscriptions.api.test.ts (5 tests | 1 failed) 65ms
❯ src/tests/api/subscriptions.api.test.ts > subscriptions public API > accepts verified PayPal webhooks and delegates handling to the subscription service
→ expected "spy" to be called with arguments: [ { …(2) } ]
Received:
1st spy call:
Array [
Object {
"event_type": "PAYMENT.CAPTURE.COMPLETED",
"resource": Object {
"id": "capture_1",
},
},
+ "{\"event_type\":\"PAYMENT.CAPTURE.COMPLETED\",\"resource\":{\"id\":\"capture_1\"}}",
]
Number of calls: 1
✓ src/modules/complaints/complaint.repo.edge.test.ts (4 tests) 4ms
❯ src/lib/emailTranslations.test.ts (5 tests | 1 failed) 8ms
❯ src/lib/emailTranslations.test.ts > emailTranslations > formats dates with the locale-specific formatter
→ expected '2 فبراير 2026' to contain '٢٠٢٦'
✓ src/middleware/requireSubscription.test.ts (4 tests) 5ms
✓ src/services/licenseValidationService.test.ts (4 tests) 6ms
✓ src/modules/reviews/review.repo.edge.test.ts (4 tests) 7ms
✓ src/modules/admin/admin.repo.edge.test.ts (3 tests) 8ms
✓ src/modules/subscriptions/subscription.schemas.edge.test.ts (4 tests) 3ms
❯ src/services/platformContentService.test.ts (2 tests | 2 failed) 14ms
❯ src/services/platformContentService.test.ts > platformContentService > returns cloned default homepage content when the file does not exist or cannot be parsed
→ process.chdir() is not supported in workers
→ process.chdir() is not supported in workers
❯ src/services/platformContentService.test.ts > platformContentService > saves only the marketplace homepage field while preserving unrelated platform content fields
→ process.chdir() is not supported in workers
→ process.chdir() is not supported in workers
✓ src/modules/auth/auth.employee.service.test.ts (2 tests) 659ms
✓ src/services/teamService.test.ts (1 test) 3ms
✓ src/middleware/requireTenant.test.ts (3 tests) 3ms
✓ src/modules/auth/auth.employee.repo.edge.test.ts (5 tests) 7ms
✓ src/tests/api/api-foundation.api.test.ts (6 tests) 79ms
✓ src/swagger/openapi.boundary.test.ts (3 tests) 4ms
✓ src/modules/customers/customer.schemas.contract.test.ts (5 tests) 5ms
❯ src/services/invoicePdfService.test.ts (2 tests | 1 failed) 11ms
❯ src/services/invoicePdfService.test.ts > invoicePdfService > builds stable legacy invoice numbers from the creation year and id suffix
→ expected 'INV-2026-SHORT' to be 'INV-2027-SHORT' // Object.is equality
✓ src/modules/customers/customer.repo.boundary.test.ts (3 tests) 10ms
✓ src/middleware/authHelpers.test.ts (5 tests) 4ms
✓ src/modules/admin/admin.menu.schemas.test.ts (4 tests) 5ms
✓ src/modules/admin/admin.billing.schemas.test.ts (4 tests) 5ms
✓ src/modules/marketplace/marketplace.schemas.test.ts (4 tests) 8ms
❯ src/tests/e2e/vehicle-pricing-boundaries.e2e.test.ts (1 test | 1 failed) 50ms
❯ src/tests/e2e/vehicle-pricing-boundaries.e2e.test.ts > vehicle pricing e2e boundaries > rejects anonymous and malformed pricing requests without invoking pricing services
→ expected 401 to be 400 // Object.is equality
✓ src/modules/reservations/reservation.additional-driver.service.test.ts (2 tests) 3ms
✓ src/tests/e2e/operations-validation-smoke.e2e.test.ts (1 test) 53ms
✓ src/tests/e2e/public-validation-smoke.e2e.test.ts (1 test) 109ms
✓ src/modules/subscriptions/subscription.policy.test.ts (4 tests) 5ms
✓ src/modules/site/site.presenter.test.ts (2 tests) 3ms
✓ src/middleware/requireRole.test.ts (3 tests) 4ms
❯ src/http/upload/upload.test.ts (4 tests | 3 failed) 7ms
❯ src/http/upload/upload.test.ts > upload assertions > accepts a single image file and narrows the route input
→ expected [Function] to not throw an error but 'ValidationError: Unsupported or spoof…' was thrown
❯ src/http/upload/upload.test.ts > upload assertions > rejects non-image single file uploads
→ expected [Function] to throw error including 'Only image uploads are supported' but got 'Unsupported or spoofed image file'
❯ src/http/upload/upload.test.ts > upload assertions > accepts multiple image files and rejects empty or mixed batches
→ expected [Function] to not throw an error but 'ValidationError: Unsupported or spoof…' was thrown
✓ src/modules/team/team.service.test.ts (2 tests) 3ms
✓ src/modules/team/team.schemas.edge.test.ts (3 tests) 3ms
✓ src/modules/payments/payment.schemas.edge.test.ts (2 tests) 4ms
✓ src/modules/customers/customer.presenter.test.ts (2 tests) 3ms
✓ src/modules/offers/offer.schemas.edge.test.ts (4 tests) 6ms
✓ src/tests/e2e/customer-boundaries.e2e.test.ts (1 test) 61ms
✓ src/http/respond/respond.test.ts (3 tests) 5ms
✓ src/modules/notifications/notification.schemas.edge.test.ts (3 tests) 5ms
✓ src/modules/admin/admin.service.test.ts (1 test) 3ms
✓ src/modules/complaints/complaint.schemas.edge.test.ts (5 tests) 6ms
✓ src/modules/reservations/reservation.pricing.service.test.ts (3 tests) 2ms
❯ src/tests/e2e/admin-billing-boundaries.e2e.test.ts (1 test | 1 failed) 36ms
❯ src/tests/e2e/admin-billing-boundaries.e2e.test.ts > admin billing e2e boundaries > rejects anonymous billing access and malformed invoice creation without touching services
→ expected 401 to be 400 // Object.is equality
✓ src/tests/e2e/subscriptions-public.e2e.test.ts (1 test) 64ms
✓ src/modules/reservations/reservation.presenter.test.ts (1 test) 1ms
✓ src/modules/vehicles/vehicle.presenter.edge.test.ts (2 tests) 2ms
✓ src/http/validate/validate.test.ts (3 tests) 7ms
❯ src/tests/e2e/admin-menu-boundaries.e2e.test.ts (0 test)
✓ src/modules/auth/auth.employee.repo.test.ts (2 tests) 2ms
✓ src/tests/e2e/api-smoke.e2e.test.ts (1 test) 58ms
✓ src/modules/admin/admin.presenter.test.ts (3 tests) 2ms
✓ src/tests/e2e/site-webhook-boundaries.e2e.test.ts (1 test) 44ms
✓ src/modules/reviews/review.schemas.edge.test.ts (4 tests) 4ms
✓ src/tests/e2e/storage-boundaries.e2e.test.ts (1 test) 33ms
✓ src/modules/marketplace/marketplace.presenter.test.ts (1 test) 2ms
✓ src/lib/isDatabaseUnavailable.test.ts (3 tests) 2ms
✓ src/modules/analytics/analytics.schemas.edge.test.ts (3 tests) 6ms
✓ src/modules/admin/admin.repo.test.ts (1 test) 3ms
✓ src/tests/e2e/payments-webhook-public.e2e.test.ts (1 test) 29ms
✓ src/tests/e2e/protected-auth-boundaries.e2e.test.ts (1 test) 35ms
✓ src/tests/e2e/operations-auth-boundaries.e2e.test.ts (1 test) 43ms
✓ src/tests/e2e/feedback-offer-boundaries.e2e.test.ts (1 test) 34ms
✓ src/tests/e2e/employee-marketplace-boundaries.e2e.test.ts (2 tests) 40ms
✓ src/tests/e2e/auth-public-disabled.e2e.test.ts (1 test) 27ms
✓ src/tests/e2e/subscription-team-boundaries.e2e.test.ts (1 test) 23ms
✓ src/tests/e2e/company-configuration-boundaries.e2e.test.ts (1 test) 17ms
⎯⎯⎯⎯⎯⎯ Failed Suites 4 ⎯⎯⎯⎯⎯⎯⎯
FAIL src/tests/api/employee-marketplace-notification.api.test.ts [ src/tests/api/employee-marketplace-notification.api.test.ts ]
FAIL src/tests/api/feedback-offer-boundaries.api.test.ts [ src/tests/api/feedback-offer-boundaries.api.test.ts ]
FAIL src/tests/api/subscription-team-boundaries.api.test.ts [ src/tests/api/subscription-team-boundaries.api.test.ts ]
Error: [vitest] No "requireCompanyDocumentAuth" export is defined on the "../../middleware/requireCompanyAuth" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:
vi.mock("../../middleware/requireCompanyAuth", async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})
❯ src/modules/customers/customer.routes.ts:14:34
12| const router = Router()
13|
14| router.get('/:id/license-image', requireCompanyDocumentAuth, requireTe…
| ^
15| try {
16| const { id } = parseParams(idParamSchema, req)
❯ src/app.ts:21:32
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/45]⎯
FAIL src/tests/e2e/admin-menu-boundaries.e2e.test.ts [ src/tests/e2e/admin-menu-boundaries.e2e.test.ts ]
Error: [vitest] No "requireFreshAdmin2FA" export is defined on the "../../middleware/requireAdminAuth" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:
vi.mock("../../middleware/requireAdminAuth", async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})
❯ src/modules/admin/admin.routes.ts:99:70
97| })
98|
99| router.post('/auth/2fa/recovery-codes/regenerate', requireAdminAuth, r…
| ^
100| try {
101| ok(res, await service.regenerateRecoveryCodes(req.admin.id))
❯ src/app.ts:18:32
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/45]⎯
⎯⎯⎯⎯⎯⎯ Failed Tests 39 ⎯⎯⎯⎯⎯⎯⎯
FAIL src/lib/emailTranslations.test.ts > emailTranslations > formats dates with the locale-specific formatter
AssertionError: expected '2 فبراير 2026' to contain '٢٠٢٦'
- Expected
+ Received
- ٢٠٢٦
+ 2 فبراير 2026
❯ src/lib/emailTranslations.test.ts:67:68
65| expect(formatDate(new Date('2026-02-03T00:00:00.000Z'), 'en')).toC…
66| expect(formatDate(new Date('2026-02-03T00:00:00.000Z'), 'fr')).toC…
67| expect(formatDate(new Date('2026-02-03T00:00:00.000Z'), 'ar')).toC…
| ^
68| })
69| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/45]⎯
FAIL src/services/invoicePdfService.test.ts > invoicePdfService > builds stable legacy invoice numbers from the creation year and id suffix
AssertionError: expected 'INV-2026-SHORT' to be 'INV-2027-SHORT' // Object.is equality
- Expected
+ Received
- INV-2027-SHORT
+ INV-2026-SHORT
❯ src/services/invoicePdfService.test.ts:23:79
21| it('builds stable legacy invoice numbers from the creation year and …
22| expect(buildInvoiceNumber('invoice_abcdef', new Date('2026-06-09T1…
23| expect(buildInvoiceNumber('short', new Date('2027-01-01T00:00:00.0…
| ^
24| })
25|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/45]⎯
FAIL src/services/platformContentService.test.ts > platformContentService > returns cloned default homepage content when the file does not exist or cannot be parsed
FAIL src/services/platformContentService.test.ts > platformContentService > saves only the marketplace homepage field while preserving unrelated platform content fields
TypeError: process.chdir() is not supported in workers
❯ src/services/platformContentService.test.ts:19:13
17| tempDir = await mkdtemp(path.join(os.tmpdir(), 'rdg-platform-conte…
18| await import('fs/promises').then((fs) => fs.mkdir(path.join(tempDi…
19| process.chdir(path.join(tempDir, 'apps/api'))
| ^
20| })
21|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'ERR_WORKER_UNSUPPORTED_OPERATION' }
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/45]⎯
FAIL src/services/platformContentService.test.ts > platformContentService > returns cloned default homepage content when the file does not exist or cannot be parsed
FAIL src/services/platformContentService.test.ts > platformContentService > saves only the marketplace homepage field while preserving unrelated platform content fields
TypeError: process.chdir() is not supported in workers
❯ src/services/platformContentService.test.ts:23:13
21|
22| afterEach(async () => {
23| process.chdir(originalCwd)
| ^
24| await rm(tempDir, { recursive: true, force: true })
25| vi.resetModules()
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'ERR_WORKER_UNSUPPORTED_OPERATION' }
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/45]⎯
FAIL src/http/errors/errorMiddleware.test.ts > errorMiddleware > falls back to a 500 internal error response
AssertionError: expected "spy" to be called with arguments: [ { error: 'internal_error', …(2) } ]
Received:
1st spy call:
Array [
Object {
"error": "internal_error",
- "message": "boom",
+ "message": "Internal server error",
+ "requestId": undefined,
"statusCode": 500,
},
]
Number of calls: 1
❯ src/http/errors/errorMiddleware.test.ts:95:22
93|
94| expect(res.status).toHaveBeenCalledWith(500)
95| expect(res.json).toHaveBeenCalledWith({ error: 'internal_error', m…
| ^
96|
97| spy.mockRestore()
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/45]⎯
FAIL src/http/upload/upload.test.ts > upload assertions > accepts a single image file and narrows the route input
AssertionError: expected [Function] to not throw an error but 'ValidationError: Unsupported or spoof…' was thrown
- Expected:
undefined
+ Received:
"ValidationError: Unsupported or spoofed image file"
❯ src/http/upload/upload.test.ts:21:47
19| describe('upload assertions', () => {
20| it('accepts a single image file and narrows the route input', () => {
21| expect(() => assertImageFile(file())).not.toThrow()
| ^
22| })
23|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/45]⎯
FAIL src/http/upload/upload.test.ts > upload assertions > rejects non-image single file uploads
AssertionError: expected [Function] to throw error including 'Only image uploads are supported' but got 'Unsupported or spoofed image file'
- Expected
+ Received
- Only image uploads are supported
+ Unsupported or spoofed image file
❯ src/http/upload/upload.test.ts:30:103
28|
29| it('rejects non-image single file uploads', () => {
30| expect(() => assertImageFile(file({ mimetype: 'application/pdf', o…
| ^
31| })
32|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/45]⎯
FAIL src/http/upload/upload.test.ts > upload assertions > accepts multiple image files and rejects empty or mixed batches
AssertionError: expected [Function] to not throw an error but 'ValidationError: Unsupported or spoof…' was thrown
- Expected:
undefined
+ Received:
"ValidationError: Unsupported or spoofed image file"
❯ src/http/upload/upload.test.ts:34:102
32|
33| it('accepts multiple image files and rejects empty or mixed batches'…
34| expect(() => assertImageFiles([file({ originalname: 'front.png', m…
| ^
35| expect(() => assertImageFiles([], 'inspection photos')).toThrow('A…
36| expect(() => assertImageFiles([
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/45]⎯
FAIL src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > rejects external links that are not HTTPS before any write
AssertionError: expected AppError: External links must use HTTPS. { …(3) } to match object { statusCode: 400, …(1) }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "code": "validation_error",
"statusCode": 400,
}
❯ src/modules/menu/menu.service.boundary.test.ts:45:5
43|
44| it('rejects external links that are not HTTPS before any write', asy…
45| await expect(createMenuItem({
| ^
46| label: 'Docs',
47| itemType: 'EXTERNAL_LINK',
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[11/45]⎯
FAIL src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > rejects duplicate routes under the same parent with a conflict error
AssertionError: expected AppError: Parent menu item was not found. { …(3) } to match object { statusCode: 409, …(1) }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "code": "duplicate_menu_route",
- "statusCode": 409,
+ "statusCode": 400,
}
❯ src/modules/menu/menu.service.boundary.test.ts:58:5
56| vi.mocked(prisma.menuItem.findFirst).mockResolvedValue({ id: 'item…
57|
58| await expect(createMenuItem({
| ^
59| label: 'Fleet',
60| itemType: 'INTERNAL_PAGE',
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/45]⎯
FAIL src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > protects required menu items from non-super-admin disable attempts
AssertionError: expected AppError: Required system items can only … { …(3) } to match object { statusCode: 403, code: 'forbidden' }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "code": "forbidden",
"statusCode": 403,
}
❯ src/modules/menu/menu.service.boundary.test.ts:121:5
119| vi.mocked(prisma.menuItem.findUniqueOrThrow).mockResolvedValue({ i…
120|
121| await expect(setMenuItemStatus('item_core', false, admin)).rejects…
| ^
122|
123| expect(prisma.menuItem.update).not.toHaveBeenCalled()
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[13/45]⎯
FAIL src/modules/menu/menu.service.boundary.test.ts > menu.service mutation boundaries > rejects company assignments when any company is cancelled or missing
AssertionError: expected AppError: Menu items can only be assigned… { …(3) } to match object { statusCode: 400, …(1) }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "code": "validation_error",
"statusCode": 400,
}
❯ src/modules/menu/menu.service.boundary.test.ts:149:5
147| vi.mocked(prisma.company.findMany).mockResolvedValue([{ id: 'compa…
148|
149| await expect(assignMenuItemToCompanies('item_1', [
| ^
150| { companyId: 'company_1' },
151| { companyId: 'company_cancelled' },
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[14/45]⎯
FAIL src/modules/site/site.schemas.test.ts > site.schemas > rejects malformed availability and payment payloads at the schema layer
ZodError: [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"accessToken"
],
"message": "Required"
}
]
❯ Object.get error [as error] ../../node_modules/zod/v3/types.js:39:31
❯ ZodObject.parse ../../node_modules/zod/v3/types.js:114:22
❯ src/modules/site/site.schemas.test.ts:53:22
51| expect(() => availabilitySchema.parse({ vehicleId: 'not-cuid', sta…
52| expect(() => paySchema.parse({ provider: 'STRIPE', successUrl: 'ht…
53| expect(paySchema.parse({ provider: 'PAYPAL', successUrl: 'https://…
| ^
54| })
55|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { issues: [ { code: 'invalid_type', expected: 'string', received: 'undefined', path: [ 'accessToken' ], message: 'Required' } ], addIssue: 'Function<anonymous>', addIssues: 'Function<anonymous>', errors: [ { code: 'invalid_type', expected: 'string', received: 'undefined', path: [ 'accessToken' ], message: 'Required' } ], format: 'Function<format>', isEmpty: false, flatten: 'Function<flatten>', formErrors: { formErrors: [], fieldErrors: { accessToken: [ 'Required' ] } } }
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[15/45]⎯
FAIL src/modules/site/site.service.boundary.test.ts > site.service public booking/payment boundaries > calculates booking totals from base rate, free-day promo, pricing rules, insurance and additional drivers
TypeError: Cannot read properties of undefined (reading 'catch')
❯ Module.createBooking src/modules/site/site.service.ts:223:45
221| }
222| if (body.licenseExpiry) {
223| await validateAndFlagLicense(customer.id).catch(() => null)
| ^
224| }
225|
❯ src/modules/site/site.service.boundary.test.ts:107:20
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[16/45]⎯
FAIL src/modules/site/site.service.boundary.test.ts > site.service public booking/payment boundaries > rejects payment initialization for already-paid reservations before provider calls
AssertionError: expected AppError: Booking access token is required { …(3) } to match object { statusCode: 409, …(1) }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "code": "already_paid",
- "statusCode": 409,
+ "statusCode": 403,
}
❯ src/modules/site/site.service.boundary.test.ts:131:5
129| vi.mocked(repo.findReservationForPayment).mockResolvedValue({ paym…
130|
131| await expect(service.initPayment('atlas', 'reservation_1', {
| ^
132| provider: 'AMANPAY',
133| successUrl: 'https://example.test/success',
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[17/45]⎯
FAIL src/modules/site/site.service.boundary.test.ts > site.service public booking/payment boundaries > blocks payment when the primary or additional driver license requires review
AssertionError: expected AppError: Booking access token is required { …(3) } to match object { statusCode: 409, …(1) }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "code": "license_review_required",
- "statusCode": 409,
+ "statusCode": 403,
}
❯ src/modules/site/site.service.boundary.test.ts:150:5
148| } as never)
149|
150| await expect(service.initPayment('atlas', 'reservation_1', {
| ^
151| provider: 'PAYPAL',
152| successUrl: 'https://example.test/success',
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[18/45]⎯
FAIL src/modules/site/site.test.ts > createBooking > creates a booking and returns reservation with requiresManualApproval flag
Error: [vitest] No "createReservationPublicAccess" export is defined on the "./site.repo" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:
vi.mock("./site.repo", async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})
❯ Module.createBooking src/modules/site/site.service.ts:227:14
225|
226| const publicAccess = generatePublicAccessToken()
227| await repo.createReservationPublicAccess(
| ^
228| reservation.id,
229| publicAccess.tokenHash,
❯ src/modules/site/site.test.ts:175:20
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[19/45]⎯
FAIL src/modules/site/site.test.ts > initPayment — payment guard paths > throws AppError when reservation is already paid
AssertionError: expected AppError: Booking access token is required { …(3) } to match object { error: 'already_paid' }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "error": "already_paid",
+ "error": "booking_token_required",
}
❯ src/modules/site/site.test.ts:211:5
209| vi.mocked(validateLicense).mockReturnValue({ status: 'VALID', requ…
210|
211| await expect(initPayment(SLUG, 'r-1', payBody)).rejects.toMatchObj…
| ^
212| })
213|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[20/45]⎯
FAIL src/modules/site/site.test.ts > initPayment — payment guard paths > throws AppError when license review is required
AssertionError: expected AppError: Booking access token is required { …(3) } to match object { error: 'license_review_required' }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "error": "license_review_required",
+ "error": "booking_token_required",
}
❯ src/modules/site/site.test.ts:224:5
222| vi.mocked(validateLicense).mockReturnValue({ status: 'VALID', requ…
223|
224| await expect(initPayment(SLUG, 'r-1', payBody)).rejects.toMatchObj…
| ^
225| })
226|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[21/45]⎯
FAIL src/modules/site/site.test.ts > initPayment — payment guard paths > throws AppError when PayPal is not configured
AssertionError: expected AppError: Booking access token is required { …(3) } to match object { error: 'provider_not_configured' }
(3 matching properties omitted from actual)
- Expected
+ Received
Object {
- "error": "provider_not_configured",
+ "error": "booking_token_required",
}
❯ src/modules/site/site.test.ts:238:5
236| vi.mocked(paypalSvc.isConfigured).mockReturnValue(false)
237|
238| await expect(initPayment(SLUG, 'r-1', payBody)).rejects.toMatchObj…
| ^
239| })
240|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[22/45]⎯
FAIL src/modules/site/site.test.ts > initPayment — payment guard paths > returns checkoutUrl when PayPal is configured
AppError: Booking access token is required
❯ assertPublicBookingAccess src/modules/site/site.service.ts:244:21
242|
243| async function assertPublicBookingAccess(reservationId: string, token:…
244| if (!token) throw new AppError('Booking access token is required', 4…
| ^
245| const access = await repo.findReservationPublicAccess(reservationId,…
246| if (!access) throw new AppError('Booking not found', 404, 'not_found…
❯ Module.initPayment src/modules/site/site.service.ts:260:9
❯ src/modules/site/site.test.ts:254:20
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { statusCode: 403, error: 'booking_token_required', data: undefined }
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[23/45]⎯
FAIL src/tests/api/admin-billing.api.test.ts > admin billing API contracts > coerces list filters and requires finance access
AssertionError: expected 403 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 403
❯ src/tests/api/admin-billing.api.test.ts:56:24
54| .set('Authorization', 'Bearer admin-token')
55|
56| expect(res.status).toBe(200)
| ^
57| expect(adminService.getBilling).toHaveBeenCalledWith({
58| q: 'atlas',
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[24/45]⎯
FAIL src/tests/api/admin-billing.api.test.ts > admin billing API contracts > rejects oversized billing pagination before service execution
AssertionError: expected 403 to be 400 // Object.is equality
- Expected
+ Received
- 400
+ 403
❯ src/tests/api/admin-billing.api.test.ts:71:24
69| .set('Authorization', 'Bearer admin-token')
70|
71| expect(res.status).toBe(400)
| ^
72| expect(adminService.getBilling).not.toHaveBeenCalled()
73| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[25/45]⎯
FAIL src/tests/api/admin-billing.api.test.ts > admin billing API contracts > streams invoice PDFs with content headers from the service boundary
AssertionError: expected 403 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 403
❯ src/tests/api/admin-billing.api.test.ts:85:24
83| .set('Authorization', 'Bearer admin-token')
84|
85| expect(res.status).toBe(200)
| ^
86| expect(res.header['content-type']).toContain('application/pdf')
87| expect(res.header['content-disposition']).toContain('INV-2026-0000…
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[26/45]⎯
FAIL src/tests/api/admin-billing.api.test.ts > admin billing API contracts > passes parsed account updates with admin identity and request ip
AssertionError: expected 403 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 403
❯ src/tests/api/admin-billing.api.test.ts:99:24
97| .send({ billingEmail: 'billing@example.test', invoiceTerms: 'NET…
98|
99| expect(res.status).toBe(200)
| ^
100| expect(adminService.updateBillingAccount).toHaveBeenCalledWith(
101| 'billing_account_1',
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[27/45]⎯
FAIL src/tests/api/admin-billing.api.test.ts > admin billing API contracts > rejects malformed draft invoice payloads before invoice creation
AssertionError: expected 403 to be 400 // Object.is equality
- Expected
+ Received
- 400
+ 403
❯ src/tests/api/admin-billing.api.test.ts:114:24
112| .send({ invoiceType: 'MANUAL', lineItems: [] })
113|
114| expect(res.status).toBe(400)
| ^
115| expect(adminService.createBillingInvoice).not.toHaveBeenCalled()
116| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[28/45]⎯
FAIL src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > rejects menu item creation with blank labels before service execution
AssertionError: expected 403 to be 400 // Object.is equality
- Expected
+ Received
- 400
+ 403
❯ src/tests/api/admin-menu-boundaries.api.test.ts:51:24
49| .send({ label: ' ', itemType: 'INTERNAL_PAGE', routeOrUrl: '/f…
50|
51| expect(res.status).toBe(400)
| ^
52| expect(menuService.createMenuItem).not.toHaveBeenCalled()
53| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[29/45]⎯
FAIL src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > passes normalized menu item creation payload with admin actor
AssertionError: expected 403 to be 201 // Object.is equality
- Expected
+ Received
- 201
+ 403
❯ src/tests/api/admin-menu-boundaries.api.test.ts:63:24
61| .send({ label: ' Fleet ', itemType: 'INTERNAL_PAGE', routeOrUrl:…
62|
63| expect(res.status).toBe(201)
| ^
64| expect(menuService.createMenuItem).toHaveBeenCalledWith(
65| expect.objectContaining({ label: 'Fleet', itemType: 'INTERNAL_PA…
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[30/45]⎯
FAIL src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > rejects invalid menu status bodies before mutation
AssertionError: expected 403 to be 400 // Object.is equality
- Expected
+ Received
- 400
+ 403
❯ src/tests/api/admin-menu-boundaries.api.test.ts:76:24
74| .send({ isActive: 'false' })
75|
76| expect(res.status).toBe(400)
| ^
77| expect(menuService.setMenuItemStatus).not.toHaveBeenCalled()
78| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[31/45]⎯
FAIL src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > requires admin privileges for menu mutations while support can preview
AssertionError: expected 403 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 403
❯ src/tests/api/admin-menu-boundaries.api.test.ts:94:31
92| .set('Authorization', 'Bearer admin-token')
93| .send({ companyId: 'company_1', role: 'MANAGER' })
94| expect(previewRes.status).toBe(200)
| ^
95| expect(menuService.previewCompanyMenu).toHaveBeenCalledWith({ comp…
96| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[32/45]⎯
FAIL src/tests/api/admin-menu-boundaries.api.test.ts > admin menu API contracts > coerces audit-log pagination defaults and caps oversized limits
AssertionError: expected 403 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 403
❯ src/tests/api/admin-menu-boundaries.api.test.ts:104:31
102| .get('/api/v1/admin/menu-audit-logs')
103| .set('Authorization', 'Bearer admin-token')
104| expect(defaultRes.status).toBe(200)
| ^
105| expect(menuService.listMenuAuditLogs).toHaveBeenCalledWith({ page:…
106|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[33/45]⎯
FAIL src/tests/api/auth-middleware.api.test.ts > auth middleware API boundaries > rejects employee-protected routes when a renter token is used
AssertionError: expected { error: 'invalid_token', …(2) } to deeply equal { error: 'invalid_token', …(2) }
- Expected
+ Received
Object {
"error": "invalid_token",
- "message": "Invalid token type for this endpoint",
+ "message": "Invalid or expired session token",
"statusCode": 401,
}
❯ src/tests/api/auth-middleware.api.test.ts:72:22
70|
71| expect(res.status).toBe(401)
72| expect(res.body).toEqual({ error: 'invalid_token', message: 'Inval…
| ^
73| expect(prisma.employee.findUnique).not.toHaveBeenCalled()
74| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[34/45]⎯
FAIL src/tests/api/auth-middleware.api.test.ts > auth middleware API boundaries > allows valid admin tokens through protected admin read routes
AssertionError: expected 403 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 403
❯ src/tests/api/auth-middleware.api.test.ts:146:24
144| const res = await request(app).get('/api/v1/admin/companies').set(…
145|
146| expect(res.status).toBe(200)
| ^
147| expect(res.body).toEqual({ data: { data: [{ id: 'company_1' }], pa…
148| expect(adminService.listCompanies).toHaveBeenCalledWith({ page: 1,…
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[35/45]⎯
FAIL src/tests/api/payments.api.test.ts > payments API contract > accepts valid AmanPay webhooks and delegates the exact payload
AssertionError: expected "spy" to be called with arguments: [ { transaction_id: 'txn_1', …(1) } ]
Received:
1st spy call:
Array [
Object {
"status": "PAID",
"transaction_id": "txn_1",
},
+ "{\"transaction_id\":\"txn_1\",\"status\":\"PAID\"}",
]
Number of calls: 1
❯ src/tests/api/payments.api.test.ts:68:42
66| expect(res.status).toBe(200)
67| expect(res.body).toEqual({ received: true })
68| expect(service.handleAmanpayWebhook).toHaveBeenCalledWith(payload)
| ^
69| })
70|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[36/45]⎯
FAIL src/tests/api/payments.api.test.ts > payments API contract > accepts verified PayPal webhooks and delegates handling
AssertionError: expected "spy" to be called with arguments: [ { …(2) } ]
Received:
1st spy call:
Array [
Object {
"event_type": "PAYMENT.CAPTURE.COMPLETED",
"resource": Object {
"id": "capture_1",
},
},
+ "{\"event_type\":\"PAYMENT.CAPTURE.COMPLETED\",\"resource\":{\"id\":\"capture_1\"}}",
]
Number of calls: 1
❯ src/tests/api/payments.api.test.ts:96:41
94| expect(res.status).toBe(200)
95| expect(res.body).toEqual({ received: true })
96| expect(service.handlePaypalWebhook).toHaveBeenCalledWith(payload)
| ^
97| })
98|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[37/45]⎯
FAIL src/tests/api/public-validation.api.test.ts > public validation API contracts > defaults site payment currency to MAD for valid public payment requests
AssertionError: expected 400 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 400
❯ src/tests/api/public-validation.api.test.ts:111:24
109| })
110|
111| expect(res.status).toBe(200)
| ^
112| expect(siteService.initPayment).toHaveBeenCalledWith('atlas-cars',…
113| provider: 'PAYPAL',
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[38/45]⎯
FAIL src/tests/api/subscriptions.api.test.ts > subscriptions public API > accepts verified PayPal webhooks and delegates handling to the subscription service
AssertionError: expected "spy" to be called with arguments: [ { …(2) } ]
Received:
1st spy call:
Array [
Object {
"event_type": "PAYMENT.CAPTURE.COMPLETED",
"resource": Object {
"id": "capture_1",
},
},
+ "{\"event_type\":\"PAYMENT.CAPTURE.COMPLETED\",\"resource\":{\"id\":\"capture_1\"}}",
]
Number of calls: 1
❯ src/tests/api/subscriptions.api.test.ts:103:41
101| expect(res.status).toBe(200)
102| expect(res.body).toEqual({ received: true })
103| expect(service.handlePaypalWebhook).toHaveBeenCalledWith(payload)
| ^
104| })
105| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[39/45]⎯
FAIL src/tests/e2e/admin-billing-boundaries.e2e.test.ts > admin billing e2e boundaries > rejects anonymous billing access and malformed invoice creation without touching services
AssertionError: expected 401 to be 400 // Object.is equality
- Expected
+ Received
- 400
+ 401
❯ src/tests/e2e/admin-billing-boundaries.e2e.test.ts:37:30
35| .send({ invoiceType: 'MADE_UP', lineItems: [{ quantity: 0, unitA…
36|
37| expect(malformed.status).toBe(400)
| ^
38| expect(adminService.createBillingInvoice).not.toHaveBeenCalled()
39| })
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[40/45]⎯
FAIL src/tests/e2e/vehicle-pricing-boundaries.e2e.test.ts > vehicle pricing e2e boundaries > rejects anonymous and malformed pricing requests without invoking pricing services
AssertionError: expected 401 to be 400 // Object.is equality
- Expected
+ Received
- 400
+ 401
❯ src/tests/e2e/vehicle-pricing-boundaries.e2e.test.ts:53:36
51| .send({ pricingMode: 'AUTOMATIC', baseDailyRate: -50 })
52|
53| expect(malformedConfig.status).toBe(400)
| ^
54| expect(vehicleService.updateVehiclePricing).not.toHaveBeenCalled()
55|
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[41/45]⎯
Test Files 21 failed | 127 passed (148)
Tests 39 failed | 601 passed (640)
Start at 23:32:27
Duration 6.99s (transform 2.58s, setup 8ms, collect 30.38s, tests 3.22s, environment 16ms, prepare 10.35s)
npm error Lifecycle script `test` failed with error:
npm error code 1
npm error path /Volumes/ExternalApps/Documents/car_management_system/apps/api
npm error workspace @rentaldrivego/api@1.0.0
npm error location /Volumes/ExternalApps/Documents/car_management_system/apps/api
npm error command failed
npm error command sh -c vitest run