Skip to content

Commit e4ca764

Browse files
authored
Merge pull request #2692 from trycompai/main
[comp] Production Deploy
2 parents 59afbed + 5e30bfb commit e4ca764

18 files changed

Lines changed: 3013 additions & 220 deletions

apps/api/src/policies/policies.controller.spec.ts

Lines changed: 220 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,17 @@ jest.mock('@db', () => ({
5656
FindingType: {
5757
soc2: 'soc2',
5858
iso27001: 'iso27001',
59+
hipaa: 'hipaa',
60+
gdpr: 'gdpr',
61+
nist: 'nist',
5962
},
63+
FindingStatus: {
64+
open: 'open',
65+
closed: 'closed',
66+
},
67+
PhaseCompletionType: {},
68+
TimelinePhaseStatus: {},
69+
TimelineStatus: {},
6070
}));
6171

6272
jest.mock('@trigger.dev/sdk', () => ({
@@ -394,14 +404,39 @@ describe('PoliciesController', () => {
394404
});
395405

396406
describe('getPolicyControls', () => {
397-
it('should return mapped and all controls', async () => {
407+
it('returns mapped and all controls with framework names derived from requirementsMapped', async () => {
398408
const { db } = require('@db');
399409
const mappedControls = [
400-
{ id: 'ctrl_1', name: 'Control 1', description: 'desc' },
410+
{
411+
id: 'ctrl_1',
412+
name: 'Control 1',
413+
description: 'desc',
414+
requirementsMapped: [
415+
{
416+
frameworkInstance: {
417+
id: 'fi_1',
418+
framework: { id: 'fw_soc2', name: 'SOC 2' },
419+
customFramework: null,
420+
},
421+
},
422+
{
423+
frameworkInstance: {
424+
id: 'fi_2',
425+
framework: null,
426+
customFramework: { id: 'cfw_1', name: 'Internal Policy' },
427+
},
428+
},
429+
],
430+
},
401431
];
402432
const allControls = [
403-
{ id: 'ctrl_1', name: 'Control 1', description: 'desc' },
404-
{ id: 'ctrl_2', name: 'Control 2', description: 'desc2' },
433+
...mappedControls,
434+
{
435+
id: 'ctrl_2',
436+
name: 'Control 2',
437+
description: 'desc2',
438+
requirementsMapped: [],
439+
},
405440
];
406441
db.policy.findFirst.mockResolvedValue({
407442
id: 'pol_1',
@@ -415,12 +450,80 @@ describe('PoliciesController', () => {
415450
mockAuthContext,
416451
);
417452

418-
expect(result.mappedControls).toEqual(mappedControls);
419-
expect(result.allControls).toEqual(allControls);
453+
expect(result.mappedControls).toEqual([
454+
{
455+
id: 'ctrl_1',
456+
name: 'Control 1',
457+
description: 'desc',
458+
frameworks: [
459+
{ id: 'fw_soc2', name: 'SOC 2' },
460+
{ id: 'cfw_1', name: 'Internal Policy' },
461+
],
462+
},
463+
]);
464+
expect(result.allControls).toEqual([
465+
{
466+
id: 'ctrl_1',
467+
name: 'Control 1',
468+
description: 'desc',
469+
frameworks: [
470+
{ id: 'fw_soc2', name: 'SOC 2' },
471+
{ id: 'cfw_1', name: 'Internal Policy' },
472+
],
473+
},
474+
{
475+
id: 'ctrl_2',
476+
name: 'Control 2',
477+
description: 'desc2',
478+
frameworks: [],
479+
},
480+
]);
420481
expect(result.authType).toBe('session');
421482
});
422483

423-
it('should return empty mappedControls when policy not found', async () => {
484+
it('dedupes frameworks when the same FrameworkInstance is reachable via multiple RequirementMaps', async () => {
485+
const { db } = require('@db');
486+
const controls = [
487+
{
488+
id: 'ctrl_1',
489+
name: 'Control 1',
490+
description: 'desc',
491+
requirementsMapped: [
492+
{
493+
frameworkInstance: {
494+
id: 'fi_1',
495+
framework: { id: 'fw_soc2', name: 'SOC 2' },
496+
customFramework: null,
497+
},
498+
},
499+
{
500+
frameworkInstance: {
501+
id: 'fi_1',
502+
framework: { id: 'fw_soc2', name: 'SOC 2' },
503+
customFramework: null,
504+
},
505+
},
506+
],
507+
},
508+
];
509+
db.policy.findFirst.mockResolvedValue({
510+
id: 'pol_1',
511+
controls,
512+
});
513+
db.control.findMany.mockResolvedValue(controls);
514+
515+
const result = await controller.getPolicyControls(
516+
'pol_1',
517+
orgId,
518+
mockAuthContext,
519+
);
520+
521+
expect(result.mappedControls[0].frameworks).toEqual([
522+
{ id: 'fw_soc2', name: 'SOC 2' },
523+
]);
524+
});
525+
526+
it('returns empty mappedControls when policy is not found', async () => {
424527
const { db } = require('@db');
425528
db.policy.findFirst.mockResolvedValue(null);
426529
db.control.findMany.mockResolvedValue([]);
@@ -433,6 +536,33 @@ describe('PoliciesController', () => {
433536

434537
expect(result.mappedControls).toEqual([]);
435538
});
539+
540+
it('scopes the requirementsMapped query to the caller organization', async () => {
541+
const { db } = require('@db');
542+
db.policy.findFirst.mockResolvedValue({ id: 'pol_1', controls: [] });
543+
db.control.findMany.mockResolvedValue([]);
544+
545+
await controller.getPolicyControls('pol_1', orgId, mockAuthContext);
546+
547+
expect(db.policy.findFirst).toHaveBeenCalledWith(
548+
expect.objectContaining({
549+
where: { id: 'pol_1', organizationId: orgId, archivedAt: null },
550+
select: expect.objectContaining({
551+
controls: expect.objectContaining({
552+
where: { archivedAt: null },
553+
select: expect.objectContaining({
554+
requirementsMapped: expect.objectContaining({
555+
where: {
556+
archivedAt: null,
557+
frameworkInstance: { organizationId: orgId },
558+
},
559+
}),
560+
}),
561+
}),
562+
}),
563+
}),
564+
);
565+
});
436566
});
437567

438568
describe('addPolicyControls', () => {
@@ -724,4 +854,87 @@ describe('PoliciesController', () => {
724854
expect(result.data).toEqual(mockResult);
725855
});
726856
});
857+
858+
describe('getPolicyEvidenceTasks', () => {
859+
it('returns tasks grouped by control, excluding archived tasks', async () => {
860+
const { db } = require('@db');
861+
db.policy.findFirst.mockResolvedValue({
862+
id: 'pol_1',
863+
controls: [
864+
{
865+
id: 'ctl_1',
866+
name: 'Access Controls',
867+
tasks: [
868+
{
869+
id: 'tsk_1',
870+
title: 'Enable 2FA',
871+
status: 'in_progress',
872+
frequency: 'monthly',
873+
department: 'it',
874+
automationStatus: 'MANUAL',
875+
assigneeId: 'mem_1',
876+
},
877+
],
878+
},
879+
{
880+
id: 'ctl_2',
881+
name: 'Monitoring',
882+
tasks: [],
883+
},
884+
],
885+
});
886+
887+
const result = await controller.getPolicyEvidenceTasks(
888+
'pol_1',
889+
orgId,
890+
mockAuthContext,
891+
);
892+
893+
expect(db.policy.findFirst).toHaveBeenCalledWith({
894+
where: { id: 'pol_1', organizationId: orgId, archivedAt: null },
895+
select: expect.objectContaining({
896+
id: true,
897+
controls: expect.objectContaining({
898+
where: { archivedAt: null, organizationId: orgId },
899+
select: expect.objectContaining({
900+
tasks: expect.objectContaining({
901+
where: { archivedAt: null, organizationId: orgId },
902+
}),
903+
}),
904+
}),
905+
}),
906+
});
907+
expect(result.data).toEqual([
908+
{
909+
control: { id: 'ctl_1', name: 'Access Controls' },
910+
tasks: [
911+
{
912+
id: 'tsk_1',
913+
title: 'Enable 2FA',
914+
status: 'in_progress',
915+
frequency: 'monthly',
916+
department: 'it',
917+
automationStatus: 'MANUAL',
918+
assigneeId: 'mem_1',
919+
},
920+
],
921+
},
922+
{
923+
control: { id: 'ctl_2', name: 'Monitoring' },
924+
tasks: [],
925+
},
926+
]);
927+
expect(result.count).toBe(1);
928+
expect(result.authType).toBe('session');
929+
});
930+
931+
it('throws NotFoundException when policy is not in caller org', async () => {
932+
const { db } = require('@db');
933+
db.policy.findFirst.mockResolvedValue(null);
934+
935+
await expect(
936+
controller.getPolicyEvidenceTasks('pol_404', orgId, mockAuthContext),
937+
).rejects.toThrow('Policy not found');
938+
});
939+
});
727940
});

0 commit comments

Comments
 (0)