fix api tests
Build & Deploy / Build & Push Docker Image (push) Successful in 2m52s
Test / Type Check (all packages) (push) Successful in 55s
Build & Deploy / Deploy to VPS (push) Successful in 3s
Test / API Unit Tests (push) Successful in 47s
Test / Homepage Unit Tests (push) Successful in 41s
Test / Storefront Unit Tests (push) Successful in 41s
Test / Admin Unit Tests (push) Successful in 40s
Test / Dashboard Unit Tests (push) Successful in 41s
Test / API Integration Tests (push) Successful in 1m1s
Build & Deploy / Build & Push Docker Image (push) Successful in 2m52s
Test / Type Check (all packages) (push) Successful in 55s
Build & Deploy / Deploy to VPS (push) Successful in 3s
Test / API Unit Tests (push) Successful in 47s
Test / Homepage Unit Tests (push) Successful in 41s
Test / Storefront Unit Tests (push) Successful in 41s
Test / Admin Unit Tests (push) Successful in 40s
Test / Dashboard Unit Tests (push) Successful in 41s
Test / API Integration Tests (push) Successful in 1m1s
This commit is contained in:
@@ -13,7 +13,8 @@ env:
|
|||||||
NODE_VERSION: "20"
|
NODE_VERSION: "20"
|
||||||
# TODO: Remove after installing internal CA certificate on the runner
|
# TODO: Remove after installing internal CA certificate on the runner
|
||||||
GIT_SSL_NO_VERIFY: "true"
|
GIT_SSL_NO_VERIFY: "true"
|
||||||
REGISTRY_HOST: 10.0.0.4
|
REGISTRY_HOST: 192.168.3.80
|
||||||
|
DEPLOY_REGISTRY_HOST: 10.0.0.4
|
||||||
DOCKERFILE_PATH: Dockerfile.production
|
DOCKERFILE_PATH: Dockerfile.production
|
||||||
DOCKER_PLATFORM: linux/amd64
|
DOCKER_PLATFORM: linux/amd64
|
||||||
DEPLOY_ROOT: /opt/rentaldrivego
|
DEPLOY_ROOT: /opt/rentaldrivego
|
||||||
@@ -41,7 +42,7 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
with:
|
with:
|
||||||
buildkitd-config-inline: |
|
buildkitd-config-inline: |
|
||||||
[registry."10.0.0.4"]
|
[registry."192.168.3.80"]
|
||||||
insecure = true
|
insecure = true
|
||||||
|
|
||||||
- name: Docker image metadata
|
- name: Docker image metadata
|
||||||
@@ -188,10 +189,10 @@ jobs:
|
|||||||
ssh "${{ secrets.VPS_USER }}@${{ secrets.VPS_IP }}" "
|
ssh "${{ secrets.VPS_USER }}@${{ secrets.VPS_IP }}" "
|
||||||
set -e
|
set -e
|
||||||
cd '$DEPLOY_ROOT'
|
cd '$DEPLOY_ROOT'
|
||||||
APP_IMAGE='$IMAGE_REPOSITORY' \
|
APP_IMAGE='$DEPLOY_REGISTRY_HOST/$IMAGE_REPOSITORY' \
|
||||||
APP_VERSION='${{ gitea.sha }}' \
|
APP_VERSION='${{ gitea.sha }}' \
|
||||||
IMAGE_TAG='${{ gitea.sha }}' \
|
IMAGE_TAG='${{ gitea.sha }}' \
|
||||||
REGISTRY_HOST='$REGISTRY_HOST' \
|
REGISTRY_HOST='$DEPLOY_REGISTRY_HOST' \
|
||||||
REGISTRY_USER='${{ secrets.REGISTRY_USERNAME }}' \
|
REGISTRY_USER='${{ secrets.REGISTRY_USERNAME }}' \
|
||||||
REGISTRY_PASSWORD=\$(printf '%s' '$REGISTRY_PASSWORD_B64' | base64 -d) \
|
REGISTRY_PASSWORD=\$(printf '%s' '$REGISTRY_PASSWORD_B64' | base64 -d) \
|
||||||
bash scripts/docker-prod-deploy.sh
|
bash scripts/docker-prod-deploy.sh
|
||||||
|
|||||||
@@ -59,11 +59,19 @@ import * as service from './site.service'
|
|||||||
|
|
||||||
const company = { id: 'company_1', slug: 'atlas', email: 'office@example.test', contractSettings: { depositRequired: true }, brand: { publicEmail: 'hello@example.test' } }
|
const company = { id: 'company_1', slug: 'atlas', email: 'office@example.test', contractSettings: { depositRequired: true }, brand: { publicEmail: 'hello@example.test' } }
|
||||||
|
|
||||||
|
function futureDateRange(startOffsetDays: number, durationDays: number) {
|
||||||
|
const start = new Date(Date.now() + startOffsetDays * 24 * 60 * 60 * 1000)
|
||||||
|
const end = new Date(start.getTime() + durationDays * 24 * 60 * 60 * 1000)
|
||||||
|
return { start, end }
|
||||||
|
}
|
||||||
|
|
||||||
function bookingBody(overrides: Record<string, unknown> = {}) {
|
function bookingBody(overrides: Record<string, unknown> = {}) {
|
||||||
|
const { start, end } = futureDateRange(30, 3)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
vehicleId: 'vehicle_1',
|
vehicleId: 'vehicle_1',
|
||||||
startDate: '2026-07-01T00:00:00.000Z',
|
startDate: start.toISOString(),
|
||||||
endDate: '2026-07-04T00:00:00.000Z',
|
endDate: end.toISOString(),
|
||||||
firstName: 'Nora',
|
firstName: 'Nora',
|
||||||
lastName: 'Renter',
|
lastName: 'Renter',
|
||||||
email: 'nora@example.test',
|
email: 'nora@example.test',
|
||||||
@@ -103,6 +111,11 @@ describe('site.service public booking/payment boundaries', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('calculates booking totals from base rate, free-day promo, pricing rules, insurance and additional drivers', async () => {
|
it('calculates booking totals from base rate, free-day promo, pricing rules, insurance and additional drivers', async () => {
|
||||||
|
const body = bookingBody({
|
||||||
|
promoCodeUsed: 'FREEDAY',
|
||||||
|
selectedInsurancePolicyIds: ['insurance_1'],
|
||||||
|
additionalDrivers: [{ firstName: 'Second' }],
|
||||||
|
})
|
||||||
vi.mocked(repo.findVehicleById).mockResolvedValue({ id: 'vehicle_1', companyId: 'company_1', dailyRate: 500, category: 'SUV' } as never)
|
vi.mocked(repo.findVehicleById).mockResolvedValue({ id: 'vehicle_1', companyId: 'company_1', dailyRate: 500, category: 'SUV' } as never)
|
||||||
vi.mocked(repo.upsertCustomer).mockResolvedValue({ id: 'customer_1' } as never)
|
vi.mocked(repo.upsertCustomer).mockResolvedValue({ id: 'customer_1' } as never)
|
||||||
vi.mocked(repo.findOfferByPromoCode).mockResolvedValue({ id: 'offer_1', type: 'FREE_DAY', discountValue: 1 } as never)
|
vi.mocked(repo.findOfferByPromoCode).mockResolvedValue({ id: 'offer_1', type: 'FREE_DAY', discountValue: 1 } as never)
|
||||||
@@ -111,8 +124,8 @@ describe('site.service public booking/payment boundaries', () => {
|
|||||||
id: 'reservation_1',
|
id: 'reservation_1',
|
||||||
bookingReference: 'BK-2026-AB12CD',
|
bookingReference: 'BK-2026-AB12CD',
|
||||||
status: 'DRAFT',
|
status: 'DRAFT',
|
||||||
startDate: new Date('2026-07-01T10:00:00.000Z'),
|
startDate: new Date(body.startDate),
|
||||||
endDate: new Date('2026-07-04T10:00:00.000Z'),
|
endDate: new Date(body.endDate),
|
||||||
pickupLocation: 'Casablanca',
|
pickupLocation: 'Casablanca',
|
||||||
returnLocation: 'Casablanca',
|
returnLocation: 'Casablanca',
|
||||||
vehicle: { make: 'Dacia', model: 'Duster', year: 2024 },
|
vehicle: { make: 'Dacia', model: 'Duster', year: 2024 },
|
||||||
@@ -125,11 +138,7 @@ describe('site.service public booking/payment boundaries', () => {
|
|||||||
paymentStatus: 'UNPAID',
|
paymentStatus: 'UNPAID',
|
||||||
} as never)
|
} as never)
|
||||||
|
|
||||||
const result = await service.createBooking('atlas', bookingBody({
|
const result = await service.createBooking('atlas', body)
|
||||||
promoCodeUsed: 'FREEDAY',
|
|
||||||
selectedInsurancePolicyIds: ['insurance_1'],
|
|
||||||
additionalDrivers: [{ firstName: 'Second' }],
|
|
||||||
}))
|
|
||||||
|
|
||||||
expect(repo.createReservation).toHaveBeenCalledWith(expect.objectContaining({
|
expect(repo.createReservation).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
totalDays: 3,
|
totalDays: 3,
|
||||||
|
|||||||
@@ -82,6 +82,12 @@ import {
|
|||||||
|
|
||||||
const SLUG = 'test-company'
|
const SLUG = 'test-company'
|
||||||
|
|
||||||
|
function futureDateRange(startOffsetDays: number, durationDays: number) {
|
||||||
|
const start = new Date(Date.now() + startOffsetDays * 24 * 60 * 60 * 1000)
|
||||||
|
const end = new Date(start.getTime() + durationDays * 24 * 60 * 60 * 1000)
|
||||||
|
return { start, end }
|
||||||
|
}
|
||||||
|
|
||||||
function makeCompany(overrides: object = {}) {
|
function makeCompany(overrides: object = {}) {
|
||||||
return {
|
return {
|
||||||
id: 'co-1', slug: SLUG, name: 'Test Co', phone: null, email: 'co@test.com',
|
id: 'co-1', slug: SLUG, name: 'Test Co', phone: null, email: 'co@test.com',
|
||||||
@@ -173,10 +179,11 @@ describe('validatePromoCode', () => {
|
|||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────
|
// ────────────────────────────────────────────────────────────────────────────
|
||||||
describe('createBooking', () => {
|
describe('createBooking', () => {
|
||||||
|
const { start: bookingStart, end: bookingEnd } = futureDateRange(30, 3)
|
||||||
const baseBody = {
|
const baseBody = {
|
||||||
vehicleId: 'v-1',
|
vehicleId: 'v-1',
|
||||||
startDate: '2026-07-01T00:00:00.000Z',
|
startDate: bookingStart.toISOString(),
|
||||||
endDate: '2026-07-04T00:00:00.000Z',
|
endDate: bookingEnd.toISOString(),
|
||||||
firstName: 'Ali', lastName: 'Ben', email: 'ali@test.com',
|
firstName: 'Ali', lastName: 'Ben', email: 'ali@test.com',
|
||||||
phone: '+212600000000',
|
phone: '+212600000000',
|
||||||
pickupLocation: 'Casablanca',
|
pickupLocation: 'Casablanca',
|
||||||
@@ -194,8 +201,8 @@ describe('createBooking', () => {
|
|||||||
id: 'r-1',
|
id: 'r-1',
|
||||||
bookingReference: 'BK-2026-ABC123',
|
bookingReference: 'BK-2026-ABC123',
|
||||||
status: 'DRAFT',
|
status: 'DRAFT',
|
||||||
startDate: new Date('2026-07-01T00:00:00.000Z'),
|
startDate: bookingStart,
|
||||||
endDate: new Date('2026-07-04T00:00:00.000Z'),
|
endDate: bookingEnd,
|
||||||
pickupLocation: 'Casablanca',
|
pickupLocation: 'Casablanca',
|
||||||
returnLocation: 'Casablanca',
|
returnLocation: 'Casablanca',
|
||||||
vehicle: { make: 'Toyota', model: 'Camry', year: 2022 },
|
vehicle: { make: 'Toyota', model: 'Camry', year: 2022 },
|
||||||
|
|||||||
Reference in New Issue
Block a user