5-step profile wizard (name/type, services, area, tone, palette preview) saved to extras.sitesmithProfile and sent with every Sitesmith request. Regenerate this section rewrites the selected block for the business as a single undo step. Refs #58 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
53 lines
2.3 KiB
TypeScript
53 lines
2.3 KiB
TypeScript
import { describe, test, expect } from 'vitest';
|
|
import {
|
|
EMPTY_PROFILE, normalizeProfile, validateProfile, isProfileComplete, profileToPrompt, profileSummary,
|
|
} from './sitesmith-profile';
|
|
|
|
const good: any = { business_name: 'Acme', business_type: 'Plumber', services: ['Drains', 'Leaks'], area: 'Austin', tone: 'bold' };
|
|
|
|
describe('sitesmith-profile', () => {
|
|
test('EMPTY_PROFILE is incomplete and names every required field', () => {
|
|
const v = validateProfile(EMPTY_PROFILE);
|
|
expect(v.ok).toBe(false);
|
|
expect(Object.keys(v.errors).sort()).toEqual(['business_name', 'business_type', 'services']);
|
|
});
|
|
|
|
test('complete profile validates; area and notes are optional', () => {
|
|
expect(isProfileComplete({ ...good, area: '' })).toBe(true);
|
|
expect(validateProfile(good).ok).toBe(true);
|
|
});
|
|
|
|
test('whitespace-only answers do not count', () => {
|
|
expect(isProfileComplete({ ...good, business_name: ' ' })).toBe(false);
|
|
expect(isProfileComplete({ ...good, services: [' ', ''] })).toBe(false);
|
|
});
|
|
|
|
test('normalize drops unknown keys, dedupes/trims services, falls back on a bad tone', () => {
|
|
const n = normalizeProfile({ ...good, services: [' Drains ', 'Drains', 7, ''], tone: 'loud', evil: '<x>' })!;
|
|
expect(n.services).toEqual(['Drains']);
|
|
expect(n.tone).toBe('friendly');
|
|
expect(n).not.toHaveProperty('evil');
|
|
expect(n).not.toHaveProperty('notes');
|
|
expect(normalizeProfile('nope')).toBeNull();
|
|
expect(normalizeProfile([])).toBeNull();
|
|
});
|
|
|
|
test('normalized profile stays under the 2000-char backend cap even for huge input', () => {
|
|
const big = 'x'.repeat(5000);
|
|
const n = normalizeProfile({ business_name: big, business_type: big, services: Array(50).fill(big).map((s, i) => s + i), area: big, tone: 'calm', notes: big })!;
|
|
expect(JSON.stringify(n).length).toBeLessThan(2000);
|
|
});
|
|
|
|
test('profileToPrompt carries name, type, services, area and tone', () => {
|
|
const line = profileToPrompt(normalizeProfile(good)!);
|
|
expect(line).toContain('Acme is a Plumber');
|
|
expect(line).toContain('Drains, Leaks');
|
|
expect(line).toContain('Austin');
|
|
expect(line).toContain('Tone: bold');
|
|
});
|
|
|
|
test('profileSummary skips an empty area', () => {
|
|
expect(profileSummary(normalizeProfile({ ...good, area: '' })!)).toBe('Acme · Plumber');
|
|
});
|
|
});
|