1222 lines
54 KiB
Plaintext
1222 lines
54 KiB
Plaintext
|
||
> 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
|
||
|
||
[33mThe CJS build of Vite's Node API is deprecated. See https://vite.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.[39m
|
||
|
||
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
|