Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/modules/codeGenerator/templates/CodeTemplate.tenant-scope.test.ts
T

79 lines
3.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import ActivityApiTemplate from "./routes/api/CodeTemplate.Routes.Activity.Api";
import EditApiTemplate from "./routes/api/CodeTemplate.Routes.Edit.Api";
import ShareApiTemplate from "./routes/api/CodeTemplate.Routes.Share.Api";
import TagsApiTemplate from "./routes/api/CodeTemplate.Routes.Tags.Api";
import ServiceTemplate from "./services/CodeTemplate.Service";
import type { EntityWithDetails } from "~/utils/db/entities/entities.db.server";
const entity = {
name: "tickets",
title: "Tickets",
titlePlural: "Tickets",
prefix: "TCK",
hasTasks: true,
properties: [],
} as unknown as EntityWithDetails;
describe("generated entity route tenant scope", () => {
it("generates edit actions through scoped services and validates task row ownership", () => {
const source = EditApiTemplate.generate({ entity });
expect(source).not.toContain('import { getRowById } from "~/utils/db/entities/rows.db.server"');
expect(source).toContain("const item = await TicketsService.get(params.id!, {");
expect(source).toContain("tenantId,");
expect(source).toContain("userId,");
expect(source).toContain("getRowTaskInRow({ id: taskId, rowId: item.row.id })");
expect(source).toContain("updateRowTaskInRow({ id: taskId, rowId: item.row.id }");
expect(source).toContain("deleteRowTaskInRow({ id: taskId, rowId: item.row.id })");
expect(source).toContain("if (!task)");
expect(source).not.toContain("getRowTask(taskId)");
expect(source).toContain("to: item.row.createdByUser");
expect(source).toContain("tenantId,");
expect(source.match(/if \(!rowPermissions\.canUpdate\)/g)).toHaveLength(3);
expect(source).toContain('return Response.json({ error: t("shared.unauthorized") }, { status: 403 });');
expect(source).not.toContain('Response.json({ error: t("shared.notFound"), status: 404 })');
expect(source).not.toContain('Response.json({ error: t("shared.unauthorized"), status: 404 })');
});
it("generates update services through RowsApi tenant and permission checks", () => {
const source = ServiceTemplate.generate({ entity });
expect(source).not.toContain("getRowById");
expect(source).toContain("const { item: row, rowPermissions } = await RowsApi.get(id, {");
expect(source).toContain("tenantId: session.tenantId");
expect(source).toContain("userId: session.userId");
expect(source).toContain("if (!row || !rowPermissions.canUpdate)");
});
it("generates activity comment mutations with row-scoped lookups", () => {
const source = ActivityApiTemplate.generate({ entity });
expect(source).toContain("tenantId,");
expect(source).toContain("getRowCommentInRow({ id: rowCommentId, rowId: rowData.item.id })");
expect(source).toContain("updateRowCommentInRow({ id: rowCommentId, rowId: rowData.item.id }");
expect(source).toContain('t("models.row.activity.errors.commentForbidden")');
expect(source).toContain('t("models.row.activity.errors.updateCommentForbidden")');
expect(source).toContain('t("models.row.activity.errors.deleteCommentForbidden")');
expect(source).toContain('t("notifications.messages.row.commented"');
expect(source).not.toContain("getRowComment(rowCommentId)");
expect(source).not.toContain("You don't have access");
expect(source).not.toContain("commented on");
});
it("generates missing-record responses with HTTP status init", () => {
const sources = [
EditApiTemplate.generate({ entity }),
TagsApiTemplate.generate({ entity }),
ShareApiTemplate.generate({ entity }),
ActivityApiTemplate.generate({ entity }),
];
for (const source of sources) {
expect(source).not.toContain('Response.json({ error: t("shared.notFound"), status: 404 })');
expect(source).not.toContain('Response.json({ error: t("shared.unauthorized"), status: 403 })');
}
});
});