diff --git a/mvp/b2c/src/lib/validation/signup.ts b/mvp/b2c/src/lib/validation/signup.ts new file mode 100644 index 0000000..c60488b --- /dev/null +++ b/mvp/b2c/src/lib/validation/signup.ts @@ -0,0 +1,21 @@ +import { z } from 'zod'; + +export const signupSchema = z.object({ + nombre: z.string().trim().min(1, 'Indica tu nombre.'), + email: z.string().trim().toLowerCase().email('Email no válido.'), + empresa: z.string().trim().min(1, 'Indica el nombre de tu empresa.'), + provincia: z.string().trim().min(1, 'Indica tu provincia.'), + password: z.string().min(8, 'La contraseña debe tener al menos 8 caracteres.'), + optInMarketing: z.union([z.literal('on'), z.literal('')]).optional(), +}); + +export type SignupInput = z.infer; + +export function slugify(value: string): string { + return value + .normalize('NFD') + .replace(/[̀-ͯ]/g, '') + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, ''); +} diff --git a/mvp/b2c/tests/validation/signup.test.ts b/mvp/b2c/tests/validation/signup.test.ts new file mode 100644 index 0000000..11480aa --- /dev/null +++ b/mvp/b2c/tests/validation/signup.test.ts @@ -0,0 +1,25 @@ +import { describe, it, expect } from 'vitest'; +import { signupSchema, slugify } from '@/lib/validation/signup'; + +describe('signupSchema', () => { + it('acepta un alta válida y normaliza email a minúsculas', () => { + const r = signupSchema.safeParse({ + nombre: 'Ana', email: 'Ana@X.com', empresa: 'Reformas Ana', + provincia: 'Madrid', password: 'Segura2026', optInMarketing: 'on', + }); + expect(r.success).toBe(true); + if (r.success) expect(r.data.email).toBe('ana@x.com'); + }); + + it('rechaza email inválido y contraseña corta', () => { + expect(signupSchema.safeParse({ + nombre: 'Ana', email: 'no-mail', empresa: 'X', provincia: 'Madrid', password: '123', + }).success).toBe(false); + }); +}); + +describe('slugify', () => { + it('genera slug url-safe sin acentos', () => { + expect(slugify('Reformas Ándalus, S.L.')).toBe('reformas-andalus-s-l'); + }); +});