From 1dec2c0d6bfe20e4c8c75023004b00fc8ece3251 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Feb 2026 17:05:56 +0000 Subject: [PATCH 1/3] Initial plan From 74c35dd4badbf0c5a67a9612477e0e2cb8613573 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Feb 2026 17:12:22 +0000 Subject: [PATCH 2/3] Add comprehensive ContactField permission tests Co-authored-by: stephenhand <1694716+stephenhand@users.noreply.github.com> --- .../src/___tests__/permissions/rules.test.ts | 260 ++++++++++++++++++ 1 file changed, 260 insertions(+) diff --git a/plugin-hrm-form/src/___tests__/permissions/rules.test.ts b/plugin-hrm-form/src/___tests__/permissions/rules.test.ts index b48602fc4d..8e0e8a0192 100644 --- a/plugin-hrm-form/src/___tests__/permissions/rules.test.ts +++ b/plugin-hrm-form/src/___tests__/permissions/rules.test.ts @@ -25,6 +25,7 @@ import { actionsMaps, CaseActions, ContactActions, + ContactFieldActions, PermissionActions, ProfileActions, ProfileSectionActions, @@ -612,3 +613,262 @@ describe('ViewIdentifiersAction', () => { }, ); }); + +describe('ContactFieldActions', () => { + afterEach(() => { + cleanupInitializedCan(); + }); + + const mockContact = { twilioWorkerId: 'owner', createdAt: new Date().toISOString() }; + const testField = 'rawJson.childInformation.name'; + const otherField = 'rawJson.childInformation.age'; + + each( + Object.values(ContactFieldActions) + .flatMap(action => [ + // Test 1: Fields not specified by a 'field' condition in any condition set are always allowed + { + action, + conditionsSets: [ + ['isSupervisor'], + [{ field: otherField }], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'field is not specified in any condition set - should be allowed', + }, + { + action, + conditionsSets: [ + [{ field: otherField }], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'field is not specified (only other field specified) - should be allowed', + }, + // Test 2: Condition sets with no field condition will allow any field if they evaluate to true + { + action, + conditionsSets: [ + ['everyone'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'no field condition, everyone condition evaluates to true', + }, + { + action, + conditionsSets: [ + ['isSupervisor'], + ], + workerSid: 'not owner', + isSupervisor: true, + field: testField, + expectedResult: true, + expectedDescription: 'no field condition, isSupervisor condition evaluates to true', + }, + { + action, + conditionsSets: [ + ['isOwner'], + ], + workerSid: 'owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'no field condition, isOwner condition evaluates to true', + }, + // Test 3: If condition sets with no field condition evaluate to false, but there are no condition sets + // with a field condition matching the field being checked, the action should be allowed + { + action, + conditionsSets: [ + ['isSupervisor'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'no field-specific conditions exist, so field is allowed even though isSupervisor is false', + }, + { + action, + conditionsSets: [ + ['isOwner'], + ['isSupervisor'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'no field-specific conditions exist, field is allowed even though conditions are false', + }, + { + action, + conditionsSets: [ + ['isSupervisor'], + [{ field: otherField }], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'field has no specific conditions (only other field specified), allowed even though isSupervisor is false', + }, + // Test 4: Multiple field conditions in the same set specifying different fields means + // that condition set will be filtered out, demonstrating it can't restrict a field on its own + { + action, + conditionsSets: [ + [{ field: testField }, { field: otherField }], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'multiple different field conditions in same set gets filtered out, no field-specific conditions remain, so allowed', + }, + { + action, + conditionsSets: [ + [{ field: testField }, { field: otherField }], + ['everyone'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'conflicting field conditions get filtered out, everyone condition allows', + }, + { + action, + conditionsSets: [ + [{ field: testField }, { field: otherField }], + ['isSupervisor'], + ], + workerSid: 'not owner', + isSupervisor: true, + field: testField, + expectedResult: true, + expectedDescription: 'conflicting field conditions get filtered out, isSupervisor allows', + }, + { + action, + conditionsSets: [ + [{ field: testField }, { field: otherField }], + ['isSupervisor'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'conflicting field conditions get filtered out, no field-specific conditions remain even though isSupervisor is false, so allowed', + }, + { + action, + conditionsSets: [ + [{ field: testField }, { field: otherField }], + [{ field: testField }, 'isOwner'], + ], + workerSid: 'owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'conflicting field conditions filtered out, but valid field condition with isOwner passes', + }, + { + action, + conditionsSets: [ + [{ field: testField }, { field: otherField }], + [{ field: testField }, 'isOwner'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: false, + expectedDescription: 'conflicting field conditions filtered out, valid field condition exists but isOwner is false', + }, + // Additional comprehensive tests + { + action, + conditionsSets: [ + [{ field: testField }, 'isOwner'], + ], + workerSid: 'owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'field condition matches and isOwner is true', + }, + { + action, + conditionsSets: [ + [{ field: testField }, 'isOwner'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: false, + expectedDescription: 'field condition matches but isOwner is false', + }, + { + action, + conditionsSets: [ + [{ field: testField }], + ['isSupervisor'], + ], + workerSid: 'not owner', + isSupervisor: true, + field: testField, + expectedResult: true, + expectedDescription: 'field condition in first set, isSupervisor in second set evaluates to true', + }, + { + action, + conditionsSets: [ + [{ field: testField }], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'only field condition with no additional conditions - always true', + }, + { + action, + conditionsSets: [ + [{ field: otherField }, 'everyone'], + ], + workerSid: 'not owner', + isSupervisor: false, + field: testField, + expectedResult: true, + expectedDescription: 'other field condition with everyone - field not specified so allowed', + }, + ]) + .map(addPrettyPrintConditions), + ).test( + `Should return $expectedResult for action $action when $expectedDescription and conditionsSets are $prettyConditionsSets`, + async ({ action, conditionsSets, workerSid, isSupervisor, field, expectedResult }) => { + const rules = buildRules(conditionsSets, 'contactField'); + fetchPermissionRulesSpy.mockResolvedValue(rules); + + mockPartialConfiguration({ + workerSid, + isSupervisor, + }); + + await validateAndSetPermissionRules(); + + const can = getInitializedCan(); + + expect(can(action, { contact: mockContact, field })).toBe(expectedResult); + }, + ); +}); From 5bbc33b6e59651e5028d22c03a599f8a5e4c84c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Feb 2026 17:13:33 +0000 Subject: [PATCH 3/3] Fix ESLint formatting issues in rules.test.ts Co-authored-by: stephenhand <1694716+stephenhand@users.noreply.github.com> --- .../src/___tests__/permissions/rules.test.ts | 97 ++++++------------- 1 file changed, 31 insertions(+), 66 deletions(-) diff --git a/plugin-hrm-form/src/___tests__/permissions/rules.test.ts b/plugin-hrm-form/src/___tests__/permissions/rules.test.ts index 8e0e8a0192..0e3e4721eb 100644 --- a/plugin-hrm-form/src/___tests__/permissions/rules.test.ts +++ b/plugin-hrm-form/src/___tests__/permissions/rules.test.ts @@ -629,10 +629,7 @@ describe('ContactFieldActions', () => { // Test 1: Fields not specified by a 'field' condition in any condition set are always allowed { action, - conditionsSets: [ - ['isSupervisor'], - [{ field: otherField }], - ], + conditionsSets: [['isSupervisor'], [{ field: otherField }]], workerSid: 'not owner', isSupervisor: false, field: testField, @@ -641,9 +638,7 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - [{ field: otherField }], - ], + conditionsSets: [[{ field: otherField }]], workerSid: 'not owner', isSupervisor: false, field: testField, @@ -653,9 +648,7 @@ describe('ContactFieldActions', () => { // Test 2: Condition sets with no field condition will allow any field if they evaluate to true { action, - conditionsSets: [ - ['everyone'], - ], + conditionsSets: [['everyone']], workerSid: 'not owner', isSupervisor: false, field: testField, @@ -664,9 +657,7 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - ['isSupervisor'], - ], + conditionsSets: [['isSupervisor']], workerSid: 'not owner', isSupervisor: true, field: testField, @@ -675,34 +666,28 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - ['isOwner'], - ], + conditionsSets: [['isOwner']], workerSid: 'owner', isSupervisor: false, field: testField, expectedResult: true, expectedDescription: 'no field condition, isOwner condition evaluates to true', }, - // Test 3: If condition sets with no field condition evaluate to false, but there are no condition sets + // Test 3: If condition sets with no field condition evaluate to false, but there are no condition sets // with a field condition matching the field being checked, the action should be allowed { action, - conditionsSets: [ - ['isSupervisor'], - ], + conditionsSets: [['isSupervisor']], workerSid: 'not owner', isSupervisor: false, field: testField, expectedResult: true, - expectedDescription: 'no field-specific conditions exist, so field is allowed even though isSupervisor is false', + expectedDescription: + 'no field-specific conditions exist, so field is allowed even though isSupervisor is false', }, { action, - conditionsSets: [ - ['isOwner'], - ['isSupervisor'], - ], + conditionsSets: [['isOwner'], ['isSupervisor']], workerSid: 'not owner', isSupervisor: false, field: testField, @@ -711,35 +696,29 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - ['isSupervisor'], - [{ field: otherField }], - ], + conditionsSets: [['isSupervisor'], [{ field: otherField }]], workerSid: 'not owner', isSupervisor: false, field: testField, expectedResult: true, - expectedDescription: 'field has no specific conditions (only other field specified), allowed even though isSupervisor is false', + expectedDescription: + 'field has no specific conditions (only other field specified), allowed even though isSupervisor is false', }, - // Test 4: Multiple field conditions in the same set specifying different fields means + // Test 4: Multiple field conditions in the same set specifying different fields means // that condition set will be filtered out, demonstrating it can't restrict a field on its own { action, - conditionsSets: [ - [{ field: testField }, { field: otherField }], - ], + conditionsSets: [[{ field: testField }, { field: otherField }]], workerSid: 'not owner', isSupervisor: false, field: testField, expectedResult: true, - expectedDescription: 'multiple different field conditions in same set gets filtered out, no field-specific conditions remain, so allowed', + expectedDescription: + 'multiple different field conditions in same set gets filtered out, no field-specific conditions remain, so allowed', }, { action, - conditionsSets: [ - [{ field: testField }, { field: otherField }], - ['everyone'], - ], + conditionsSets: [[{ field: testField }, { field: otherField }], ['everyone']], workerSid: 'not owner', isSupervisor: false, field: testField, @@ -748,10 +727,7 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - [{ field: testField }, { field: otherField }], - ['isSupervisor'], - ], + conditionsSets: [[{ field: testField }, { field: otherField }], ['isSupervisor']], workerSid: 'not owner', isSupervisor: true, field: testField, @@ -760,15 +736,13 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - [{ field: testField }, { field: otherField }], - ['isSupervisor'], - ], + conditionsSets: [[{ field: testField }, { field: otherField }], ['isSupervisor']], workerSid: 'not owner', isSupervisor: false, field: testField, expectedResult: true, - expectedDescription: 'conflicting field conditions get filtered out, no field-specific conditions remain even though isSupervisor is false, so allowed', + expectedDescription: + 'conflicting field conditions get filtered out, no field-specific conditions remain even though isSupervisor is false, so allowed', }, { action, @@ -780,7 +754,8 @@ describe('ContactFieldActions', () => { isSupervisor: false, field: testField, expectedResult: true, - expectedDescription: 'conflicting field conditions filtered out, but valid field condition with isOwner passes', + expectedDescription: + 'conflicting field conditions filtered out, but valid field condition with isOwner passes', }, { action, @@ -792,14 +767,13 @@ describe('ContactFieldActions', () => { isSupervisor: false, field: testField, expectedResult: false, - expectedDescription: 'conflicting field conditions filtered out, valid field condition exists but isOwner is false', + expectedDescription: + 'conflicting field conditions filtered out, valid field condition exists but isOwner is false', }, // Additional comprehensive tests { action, - conditionsSets: [ - [{ field: testField }, 'isOwner'], - ], + conditionsSets: [[{ field: testField }, 'isOwner']], workerSid: 'owner', isSupervisor: false, field: testField, @@ -808,9 +782,7 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - [{ field: testField }, 'isOwner'], - ], + conditionsSets: [[{ field: testField }, 'isOwner']], workerSid: 'not owner', isSupervisor: false, field: testField, @@ -819,10 +791,7 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - [{ field: testField }], - ['isSupervisor'], - ], + conditionsSets: [[{ field: testField }], ['isSupervisor']], workerSid: 'not owner', isSupervisor: true, field: testField, @@ -831,9 +800,7 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - [{ field: testField }], - ], + conditionsSets: [[{ field: testField }]], workerSid: 'not owner', isSupervisor: false, field: testField, @@ -842,9 +809,7 @@ describe('ContactFieldActions', () => { }, { action, - conditionsSets: [ - [{ field: otherField }, 'everyone'], - ], + conditionsSets: [[{ field: otherField }, 'everyone']], workerSid: 'not owner', isSupervisor: false, field: testField,