Files
mercadodevida/project/src/app/tests/brands.itest.ts
2026-08-17 22:23:10 +02:00

101 lines
3.3 KiB
TypeScript

import type { DestinationStream } from 'pino';
import type pg from 'pg';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { buildApp } from '../build-app.js';
import { createPool } from '../../infrastructure/db/pool.js';
import { createLogger } from '../../infrastructure/logging/logger.js';
import {
getTestDbUrl,
recreateDatabase,
runMigrations,
} from '../../infrastructure/db/tests/db-test-support.js';
import { SESSION_COOKIE_NAME } from '../../modules/identity/index.js';
const hasDb = Boolean(process.env.TEST_DATABASE_URL);
function silentLogger() {
const destination: DestinationStream = { write: () => undefined };
return createLogger({ level: 'info', destination });
}
function cookieValue(setCookieHeader: string | string[] | undefined): string {
const raw = Array.isArray(setCookieHeader) ? setCookieHeader[0] : setCookieHeader;
expect(raw).toBeDefined();
const pair = (raw as string).split(';')[0] as string;
return pair.slice(pair.indexOf('=') + 1);
}
describe.skipIf(!hasDb)('brands flows (real PostgreSQL)', () => {
const url = hasDb ? getTestDbUrl() : '';
let pool: pg.Pool;
let app: Awaited<ReturnType<typeof buildApp>>;
let adminCookie = '';
beforeAll(async () => {
await recreateDatabase(url);
await runMigrations(url, 'up');
pool = createPool(url);
app = await buildApp({ logger: silentLogger(), pool, cookieSecure: true });
const user = { email: 'brands-admin@example.com', password: 'correct horse battery staple' };
const registered = await app.inject({
method: 'POST',
url: '/auth/register',
headers: { 'content-type': 'application/json' },
payload: user,
});
expect(registered.statusCode).toBe(201);
const id = (registered.json() as { id: string }).id;
await pool.query('UPDATE identity_users SET role = $1 WHERE id = $2', ['admin', id]);
const login = await app.inject({
method: 'POST',
url: '/auth/login',
headers: { 'content-type': 'application/json' },
payload: user,
});
expect(login.statusCode).toBe(200);
adminCookie = cookieValue(login.headers['set-cookie']);
});
afterAll(async () => {
await app.close();
await pool.end();
});
it('returns HTTP 409 for duplicate brand slug (AC1)', async () => {
const payload = {
name: 'NaturGreen',
slug: 'naturgreen',
seoTitle: 'NaturGreen marca ecológica',
seoDescription: 'Productos ecológicos NaturGreen',
};
const first = await app.inject({
method: 'POST',
url: '/brands',
headers: { 'content-type': 'application/json' },
cookies: { [SESSION_COOKIE_NAME]: adminCookie },
payload,
});
expect(first.statusCode).toBe(201);
const duplicate = await app.inject({
method: 'POST',
url: '/brands',
headers: { 'content-type': 'application/json' },
cookies: { [SESSION_COOKIE_NAME]: adminCookie },
payload,
});
expect(duplicate.statusCode).toBe(409);
expect(duplicate.json().error.code).toBe('BRAND_SLUG_EXISTS');
});
it('serves public brand URL by slug (AC3)', async () => {
const response = await app.inject({ method: 'GET', url: '/marca/naturgreen' });
expect(response.statusCode).toBe(200);
expect(response.json()).toMatchObject({ slug: 'naturgreen', url: '/marca/naturgreen' });
});
});