metis-desk/apps/server/src/work-profiles.integration.ts
2026-10-05 09:53:29 +02:00

188 lines
6.8 KiB
TypeScript

import assert from "node:assert/strict";
import { InventoryResponseSchema } from "@metis/assets/common";
import {
type AccessFieldsDTO,
AccessResponseSchema,
CompanyResponseSchema,
WorkProfileResponseSchema,
WorkProfilesResponseSchema,
} from "@metis/companies/common";
import type { Sequelize } from "sequelize";
import { z } from "zod/v4";
type Request = (path: string, body?: unknown, origin?: string, token?: string) => Promise<Response>;
export async function verifyWorkProfiles(
request: Request,
companyId: string,
otherId: string,
database: Sequelize
) {
const path = `/work-profiles/${companyId}`;
const inventory = InventoryResponseSchema.parse(
await (await request(`/assets/${companyId}`)).json()
);
const first = inventory.assets[0];
const second = inventory.assets[1];
assert.ok(first && second);
for (const item of [first, second]) {
if (item.values.status === "retired") {
assert.equal(
(
await request(`/assets/${companyId}/${item.id}/update`, {
values: { ...item.values, status: "available" },
})
).status,
200
);
}
}
const fields = {
name: "Persona perfiles",
position: null,
email: null,
phone: null,
active: true,
isContact: false,
};
const people = await request(`/companies/${companyId}/people`, fields);
assert.equal(people.status, 201);
const person = CompanyResponseSchema.parse(await people.json()).company.people.at(-1);
assert.ok(person);
const foreign = CompanyResponseSchema.parse(await (await request(`/companies/${otherId}`)).json())
.company.people[0];
assert.ok(foreign);
const input = {
name: "Perfil Ana",
personId: person.id,
assetId: first.id,
accountId: null,
active: true,
notes: null,
};
const save = async (values: unknown, id?: string) => {
const response = await request(path + (id ? `/${id}/update` : ""), { values });
assert.equal(response.status, id ? 200 : 201, await response.clone().text());
return WorkProfileResponseSchema.parse(await response.json()).profile;
};
const error = async (values: unknown, code: string, id?: string, status = 409) => {
const response = await request(path + (id ? `/${id}/update` : ""), { values });
assert.equal(response.status, status, await response.clone().text());
assert.equal(z.object({ code: z.string() }).parse(await response.json()).code, code);
};
await error({ ...input, personId: foreign.id }, "PROFILE_REFERENCE_NOT_FOUND", undefined, 404);
await error({ ...input, actorId: person.id }, "INVALID_REQUEST", undefined, 400);
assert.equal((await request(path, { values: input }, "https://other.example")).status, 403);
assert.equal((await request(path, { values: input }, undefined, "a".repeat(64))).status, 403);
const responses = await Promise.all([
request(path, { values: input }),
request(path, { values: input }),
]);
assert.deepEqual(responses.map((response) => response.status).sort(), [201, 409]);
const response = responses.find((response) => response.status === 201);
assert.ok(response);
const created = WorkProfileResponseSchema.parse(await response.json()).profile;
assert.equal(created.id.charAt(14), "7");
assert.equal(created.history[0]?.id.charAt(14), "7");
assert.ok(created.history[0]?.actorName);
assert.deepEqual(await save(input, created.id), created);
const another = await save({ ...input, assetId: second.id });
assert.equal(another.values.personId, created.values.personId);
const otherPersonResponse = await request(`/companies/${companyId}/people`, {
...fields,
name: "Otra persona perfiles",
});
const otherPerson = CompanyResponseSchema.parse(
await otherPersonResponse.json()
).company.people.at(-1);
assert.ok(otherPerson);
await save({ ...input, personId: otherPerson.id });
await error({ ...input, assetId: second.id }, "PROFILE_TARGET_IMMUTABLE", created.id);
const createAccess = async (values: AccessFieldsDTO) => {
const res = await request(`/access/${companyId}`, { values });
assert.equal(res.status, 201, await res.clone().text());
const item = AccessResponseSchema.parse(await res.json()).items.at(-1);
assert.ok(item);
return item;
};
const system = await createAccess({ kind: "system", name: "Dominio perfiles", active: true });
const account = await createAccess({
kind: "account",
systemId: system.id,
environmentId: null,
login: "ana-perfil",
usage: "personal",
active: true,
expiresOn: null,
notes: null,
});
await error({ ...input, accountId: account.id }, "PROFILE_REFERENCE_UNAVAILABLE", created.id);
await createAccess({
kind: "account_person",
accountId: account.id,
personId: person.id,
startDate: new Date().toISOString().slice(0, 10),
endDate: null,
configuration: "pending",
});
const withAccount = await save({ ...input, accountId: account.id }, created.id);
assert.equal(withAccount.history.length, 2);
assert.equal(withAccount.history[0]?.values.accountId, null);
assert.equal(
(
await request(`/access/${companyId}/${account.id}/update`, {
values: { ...account.values, active: false },
})
).status,
200
);
const reviewed = WorkProfilesResponseSchema.parse(
await (await request(path)).json()
).profiles.find((item) => item.id === created.id);
assert.equal(reviewed?.needsReview, true);
const archived = await save({ ...withAccount.values, active: false }, created.id);
assert.equal(archived.needsReview, false);
await error(withAccount.values, "PROFILE_REFERENCE_UNAVAILABLE", created.id);
const replacement = await save(input);
assert.notEqual(replacement.id, created.id);
assert.equal(
(await request(`/work-profiles/${otherId}/${created.id}/update`, { values: input })).status,
404
);
assert.equal(
WorkProfilesResponseSchema.parse(await (await request(`/work-profiles/${otherId}`)).json())
.profiles.length,
0
);
await database.query("UPDATE work_profiles SET currentKey=NULL WHERE id=:id", {
replacements: { id: replacement.id },
});
try {
assert.equal((await request(path)).status, 500);
} finally {
await database.query("UPDATE work_profiles SET currentKey=:key WHERE id=:id", {
replacements: { id: replacement.id, key: [person.id, first.id].join(":") },
});
}
const listed = WorkProfilesResponseSchema.parse(await (await request(path)).json());
assert.deepEqual(
listed.profiles.find((item) => item.id === created.id),
archived
);
assert.equal(
(
await request(`/companies/${companyId}/people/${person.id}/update`, {
...fields,
active: false,
})
).status,
200
);
assert.equal(
WorkProfilesResponseSchema.parse(await (await request(path)).json()).profiles.find(
(item) => item.id === replacement.id
)?.needsReview,
true
);
}