import assert from "node:assert/strict"; import { randomUUID } from "node:crypto"; import type { InterventionTemplateDTO } from "@metis/companies/common"; import { InterventionTemplateResponseSchema, InterventionTemplatesSchema, } from "@metis/companies/common"; type Request = (path: string, body?: unknown, origin?: string, token?: string) => Promise; export async function verifyInterventionTemplates( request: Request, companyId: string, otherId: string, migrate: () => Promise ) { const path = "/intervention-templates/global"; const list = InterventionTemplatesSchema.parse(await (await request(path)).json()); assert.equal(list.templates.length, 6); assert.ok(list.templates.every((template) => template.companyId === null)); const values = { name: "Procedimiento de prueba", description: "Prueba", active: true, steps: [ { id: randomUUID(), title: "Primer paso", instructions: "", required: false }, { id: randomUUID(), title: "Segundo paso", instructions: "Verificar", required: true }, ], }; const body = { values, requestKey: randomUUID(), expectedRevisionId: null }; async function save(url: string, payload: unknown, status = 201) { const response = await request(url, payload); assert.equal(response.status, status, await response.clone().text()); return InterventionTemplateResponseSchema.parse(await response.json()).template; } const created = await save(path, body); assert.equal(created.id[14], "7"); assert.equal(created.history.length, 1); assert.equal((await save(path, body)).id, created.id); assert.equal((await request(path, { ...body, values: { ...values, name: "Otro" } })).status, 409); assert.equal((await request(path, { ...body, requestKey: randomUUID() })).status, 409); assert.equal((await request(`/intervention-templates/${companyId}`, body)).status, 409); const local = await save(`/intervention-templates/${companyId}`, { ...body, requestKey: randomUUID(), }); assert.equal(local.companyId, companyId); const scoped = InterventionTemplatesSchema.parse( await (await request(`/intervention-templates/${companyId}`)).json() ); assert.ok(scoped.templates.some((item) => item.id === created.id)); assert.ok(scoped.templates.some((item) => item.id === local.id)); const other = InterventionTemplatesSchema.parse( await (await request(`/intervention-templates/${otherId}`)).json() ); assert.ok(other.templates.every((item) => item.companyId === null)); const updateBody = (template: InterventionTemplateDTO) => ({ values: { ...template.values, active: false, steps: [...template.values.steps].reverse() }, requestKey: randomUUID(), expectedRevisionId: template.history.at(-1)?.id, }); assert.equal( ( await request( `/intervention-templates/${companyId}/${created.id}/update`, updateBody(created) ) ).status, 404 ); assert.equal( (await request(`/intervention-templates/${otherId}/${local.id}/update`, updateBody(local))) .status, 404 ); const updated = await save(`${path}/${created.id}/update`, updateBody(created), 200); assert.equal(updated.history.length, 2); assert.equal(updated.values.active, false); assert.equal(updated.history[0]?.values.active, true); assert.equal(updated.values.steps[0]?.id, values.steps[1]?.id); const same = await save( `${path}/${created.id}/update`, { ...body, values: updated.values, expectedRevisionId: updated.history.at(-1)?.id }, 200 ); assert.equal(same.history.length, 2); assert.equal((await request(`${path}/${created.id}/update`, updateBody(created))).status, 409); const responses = await Promise.all( ["Una edición", "Otra edición"].map((description) => request(`${path}/${created.id}/update`, { ...updateBody(updated), values: { ...updated.values, description }, }) ) ); assert.deepEqual(responses.map((response) => response.status).sort(), [200, 409]); assert.equal( (await request(path, { ...body, requestKey: randomUUID(), values: { ...values, steps: [] } })) .status, 400 ); assert.equal((await request(path, { ...body, unknown: true })).status, 400); assert.equal((await request(`${path}?unknown=1`)).status, 400); assert.equal((await request(`/intervention-templates/${randomUUID()}`)).status, 404); assert.equal((await request(path, body, "http://evil.example")).status, 403); assert.equal((await request(path, body, undefined, "invalid")).status, 403); const seed = list.templates[0]; assert.ok(seed); const modifiedSeed = await save( `${path}/${seed.id}/update`, { ...updateBody(seed), values: { ...seed.values, active: false, description: "Cambio conservado tras migración" }, }, 200 ); await migrate(); await migrate(); const afterMigration = InterventionTemplatesSchema.parse(await (await request(path)).json()); const retained = afterMigration.templates.find((item) => item.id === seed.id); assert.deepEqual(retained, modifiedSeed); assert.equal(afterMigration.templates.length, 7); }