refactor(yachts): rename schema + consolidate tests per project conventions

This commit is contained in:
Matt Ciaccio
2026-04-23 23:35:30 +02:00
parent 899e588a0c
commit 27d438929b
5 changed files with 83 additions and 59 deletions

View File

@@ -0,0 +1 @@
{"sessionId":"fd05cbd7-d695-4a70-9223-4b25f3369829","pid":88534,"acquiredAt":1776866083076}

Submodule client-portal updated: e2d31815cf...84f89f9409

View File

@@ -39,7 +39,7 @@ export const transferOwnershipSchema = z.object({
transferNotes: z.string().optional(), transferNotes: z.string().optional(),
}); });
export const listYachtsQuery = baseListQuerySchema.extend({ export const listYachtsSchema = baseListQuerySchema.extend({
ownerType: z.enum(['client', 'company']).optional(), ownerType: z.enum(['client', 'company']).optional(),
ownerId: z.string().optional(), ownerId: z.string().optional(),
status: z.enum(['active', 'retired', 'sold_away']).optional(), status: z.enum(['active', 'retired', 'sold_away']).optional(),
@@ -49,4 +49,4 @@ export const listYachtsQuery = baseListQuerySchema.extend({
export type CreateYachtInput = z.infer<typeof createYachtSchema>; export type CreateYachtInput = z.infer<typeof createYachtSchema>;
export type UpdateYachtInput = z.infer<typeof updateYachtSchema>; export type UpdateYachtInput = z.infer<typeof updateYachtSchema>;
export type TransferOwnershipInput = z.infer<typeof transferOwnershipSchema>; export type TransferOwnershipInput = z.infer<typeof transferOwnershipSchema>;
export type ListYachtsInput = z.infer<typeof listYachtsQuery>; export type ListYachtsInput = z.infer<typeof listYachtsSchema>;

View File

@@ -1,10 +1,11 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { createClientSchema, updateClientSchema } from '@/lib/validators/clients'; import { createClientSchema, updateClientSchema } from '@/lib/validators/clients';
import { createInterestSchema, updateInterestSchema, changeStageSchema } from '@/lib/validators/interests'; import { createInterestSchema, changeStageSchema } from '@/lib/validators/interests';
import { updateBerthSchema, updateBerthStatusSchema } from '@/lib/validators/berths'; import { updateBerthSchema, updateBerthStatusSchema } from '@/lib/validators/berths';
import { createInvoiceSchema } from '@/lib/validators/invoices'; import { createInvoiceSchema } from '@/lib/validators/invoices';
import { createWebhookSchema, updateWebhookSchema } from '@/lib/validators/webhooks'; import { createWebhookSchema, updateWebhookSchema } from '@/lib/validators/webhooks';
import { createFieldSchema, updateFieldSchema } from '@/lib/validators/custom-fields'; import { createFieldSchema, updateFieldSchema } from '@/lib/validators/custom-fields';
import { createYachtSchema, transferOwnershipSchema } from '@/lib/validators/yachts';
// ─── Client schemas ─────────────────────────────────────────────────────────── // ─── Client schemas ───────────────────────────────────────────────────────────
@@ -92,12 +93,24 @@ describe('createInterestSchema', () => {
}); });
it('rejects invalid pipelineStage', () => { it('rejects invalid pipelineStage', () => {
const result = createInterestSchema.safeParse({ clientId: 'c1', pipelineStage: 'unknown_stage' }); const result = createInterestSchema.safeParse({
clientId: 'c1',
pipelineStage: 'unknown_stage',
});
expect(result.success).toBe(false); expect(result.success).toBe(false);
}); });
it('accepts all valid pipeline stages', () => { it('accepts all valid pipeline stages', () => {
const stages = ['open', 'details_sent', 'in_communication', 'visited', 'signed_eoi_nda', 'deposit_10pct', 'contract', 'completed']; const stages = [
'open',
'details_sent',
'in_communication',
'visited',
'signed_eoi_nda',
'deposit_10pct',
'contract',
'completed',
];
for (const stage of stages) { for (const stage of stages) {
const result = createInterestSchema.safeParse({ clientId: 'c1', pipelineStage: stage }); const result = createInterestSchema.safeParse({ clientId: 'c1', pipelineStage: stage });
expect(result.success, `stage "${stage}" should be valid`).toBe(true); expect(result.success, `stage "${stage}" should be valid`).toBe(true);
@@ -138,11 +151,15 @@ describe('updateBerthSchema', () => {
describe('updateBerthStatusSchema', () => { describe('updateBerthStatusSchema', () => {
it('accepts valid status with reason', () => { it('accepts valid status with reason', () => {
expect(updateBerthStatusSchema.safeParse({ status: 'available', reason: 'Freed up' }).success).toBe(true); expect(
updateBerthStatusSchema.safeParse({ status: 'available', reason: 'Freed up' }).success,
).toBe(true);
}); });
it('rejects invalid status', () => { it('rejects invalid status', () => {
expect(updateBerthStatusSchema.safeParse({ status: 'occupied', reason: 'reason' }).success).toBe(false); expect(
updateBerthStatusSchema.safeParse({ status: 'occupied', reason: 'reason' }).success,
).toBe(false);
}); });
it('rejects missing reason', () => { it('rejects missing reason', () => {
@@ -220,7 +237,10 @@ describe('createWebhookSchema', () => {
}); });
it('rejects http URL (must be HTTPS)', () => { it('rejects http URL (must be HTTPS)', () => {
const result = createWebhookSchema.safeParse({ ...validWebhook, url: 'http://example.com/hook' }); const result = createWebhookSchema.safeParse({
...validWebhook,
url: 'http://example.com/hook',
});
expect(result.success).toBe(false); expect(result.success).toBe(false);
if (!result.success) { if (!result.success) {
const messages = result.error.issues.map((i) => i.message); const messages = result.error.issues.map((i) => i.message);
@@ -288,7 +308,10 @@ describe('createFieldSchema', () => {
}); });
it('rejects fieldName with spaces', () => { it('rejects fieldName with spaces', () => {
const result = createFieldSchema.safeParse({ ...validTextField, fieldName: 'preferred marina' }); const result = createFieldSchema.safeParse({
...validTextField,
fieldName: 'preferred marina',
});
expect(result.success).toBe(false); expect(result.success).toBe(false);
}); });
@@ -343,3 +366,52 @@ describe('updateFieldSchema', () => {
// it cannot be used to mutate fieldType. // it cannot be used to mutate fieldType.
}); });
}); });
// ─── Yacht schemas ────────────────────────────────────────────────────────────
describe('createYachtSchema', () => {
it('rejects empty name', () => {
const result = createYachtSchema.safeParse({
name: '',
owner: { type: 'client', id: 'c1' },
});
expect(result.success).toBe(false);
});
it('requires owner', () => {
const result = createYachtSchema.safeParse({ name: 'Sea Breeze' });
expect(result.success).toBe(false);
});
it('rejects invalid yearBuilt', () => {
const result = createYachtSchema.safeParse({
name: 'Sea Breeze',
owner: { type: 'client', id: 'c1' },
yearBuilt: 1700,
});
expect(result.success).toBe(false);
});
it('accepts minimal valid input', () => {
const result = createYachtSchema.safeParse({
name: 'Sea Breeze',
owner: { type: 'client', id: 'c1' },
});
expect(result.success).toBe(true);
});
});
describe('transferOwnershipSchema', () => {
it('requires newOwner + effectiveDate', () => {
expect(transferOwnershipSchema.safeParse({}).success).toBe(false);
});
it('accepts valid input', () => {
const result = transferOwnershipSchema.safeParse({
newOwner: { type: 'company', id: 'co1' },
effectiveDate: new Date(),
transferReason: 'sale',
});
expect(result.success).toBe(true);
});
});

View File

@@ -1,49 +0,0 @@
import { describe, it, expect } from 'vitest';
import { createYachtSchema, transferOwnershipSchema } from '@/lib/validators/yachts';
describe('createYachtSchema', () => {
it('rejects empty name', () => {
const result = createYachtSchema.safeParse({
name: '',
owner: { type: 'client', id: 'c1' },
});
expect(result.success).toBe(false);
});
it('requires owner', () => {
const result = createYachtSchema.safeParse({ name: 'Sea Breeze' });
expect(result.success).toBe(false);
});
it('rejects invalid yearBuilt', () => {
const result = createYachtSchema.safeParse({
name: 'Sea Breeze',
owner: { type: 'client', id: 'c1' },
yearBuilt: 1700,
});
expect(result.success).toBe(false);
});
it('accepts minimal valid input', () => {
const result = createYachtSchema.safeParse({
name: 'Sea Breeze',
owner: { type: 'client', id: 'c1' },
});
expect(result.success).toBe(true);
});
});
describe('transferOwnershipSchema', () => {
it('requires newOwner + effectiveDate', () => {
expect(transferOwnershipSchema.safeParse({}).success).toBe(false);
});
it('accepts valid input', () => {
const result = transferOwnershipSchema.safeParse({
newOwner: { type: 'company', id: 'co1' },
effectiveDate: new Date(),
transferReason: 'sale',
});
expect(result.success).toBe(true);
});
});