Files
carmanagement/apps/api/src/lib/storage.test.ts
T
2026-06-10 00:40:19 -04:00

63 lines
2.4 KiB
TypeScript

import fs from 'fs'
import os from 'os'
import path from 'path'
import { afterEach, describe, expect, it } from 'vitest'
import {
assertStorageConfiguration,
deleteImage,
getPrivateStorageRoot,
getProtectedCustomerLicenseImageUrl,
getPublicStorageRoot,
getStorageRoot,
resolveStoredFilePath,
uploadImage,
} from './storage'
const originalEnv = { ...process.env }
describe('storage', () => {
afterEach(() => {
process.env = { ...originalEnv }
})
it('uses FILE_STORAGE_ROOT when configured and builds protected customer license URLs from dashboard URL', () => {
process.env.FILE_STORAGE_ROOT = '/tmp/rdg-storage'
process.env.DASHBOARD_URL = 'https://dashboard.rentaldrivego.test/dashboard/'
expect(getStorageRoot()).toBe('/tmp/rdg-storage')
expect(getPublicStorageRoot()).toBe('/tmp/rdg-storage/public')
expect(getPrivateStorageRoot()).toBe('/tmp/rdg-storage/private')
expect(getProtectedCustomerLicenseImageUrl('customer_1')).toBe('https://dashboard.rentaldrivego.test/dashboard/api/v1/customers/customer_1/license-image')
})
it('rejects implicit in-app storage in production', () => {
delete process.env.FILE_STORAGE_ROOT
process.env.NODE_ENV = 'production'
expect(() => assertStorageConfiguration()).toThrow('FILE_STORAGE_ROOT must be set in production')
})
it('uploads, resolves, and deletes files under the configured storage root', async () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'rdg-storage-'))
process.env.FILE_STORAGE_ROOT = root
process.env.API_URL = 'https://api.rentaldrivego.test/'
const url = await uploadImage(Buffer.from('image-bytes'), 'customers/licenses', 'customer_1')
expect(url).toBe('https://api.rentaldrivego.test/storage/customers/licenses/customer_1.jpg')
const filePath = resolveStoredFilePath(url)
expect(filePath).toBe(path.join(root, 'private/customers/licenses/customer_1.jpg'))
expect(fs.readFileSync(filePath!, 'utf8')).toBe('image-bytes')
await deleteImage(url)
expect(fs.existsSync(filePath!)).toBe(false)
})
it('ignores non-storage URLs when resolving or deleting files', async () => {
process.env.FILE_STORAGE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'rdg-storage-'))
expect(resolveStoredFilePath('https://cdn.test/not-storage/file.jpg')).toBeNull()
await expect(deleteImage('https://cdn.test/not-storage/file.jpg')).resolves.toBeUndefined()
})
})