Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Error when deleting the last sub-resource from a resource in policy editor #13620

Merged
merged 3 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ import { PolicyResourceFields } from './PolicyResourceFields';
import { textMock } from '@studio/testing/mocks/i18nMock';
import { PolicyEditorContext } from '../../../../../../contexts/PolicyEditorContext';
import { PolicyRuleContext } from '../../../../../../contexts/PolicyRuleContext';
import { mockPolicyEditorContextValue } from '../../../../../../../test/mocks/policyEditorContextMock';
import { mockPolicyRuleContextValue } from '../../../../../../../test/mocks/policyRuleContextMock';
import {
mockPolicyEditorContextValue,
mockPolicyEditorContextValueWithSingleNarrowingPolicy,
} from '../../../../../../../test/mocks/policyEditorContextMock';
import {
mockPolicyRuleContextValue,
mockPolicyRuleContextValueWithSingleNarrowingPolicy,
} from '../../../../../../../test/mocks/policyRuleContextMock';
import { mockResource11 } from '../../../../../../../test/mocks/policySubResourceMocks';

const mockValudNewText = '45';
Expand All @@ -23,7 +29,7 @@ describe('PolicyResourceFields', () => {
afterEach(jest.clearAllMocks);

it('sets text fields to readonly when "canEditTypeAndId" is false', () => {
renderPolicyResourceFields({ canEditTypeAndId: false });
renderPolicyResourceFieldsWithMultipleNarrowingPolicies({ canEditTypeAndId: false });

const idInput = screen.getByLabelText(textMock('policy_editor.narrowing_list_field_id'));
expect(idInput).toHaveAttribute('readonly');
Expand All @@ -33,7 +39,7 @@ describe('PolicyResourceFields', () => {
});

it('sets text fields to not be readonly when "canEditTypeAndId" is true', () => {
renderPolicyResourceFields();
renderPolicyResourceFieldsWithMultipleNarrowingPolicies();

const idInput = screen.getByLabelText(textMock('policy_editor.narrowing_list_field_id'));
expect(idInput).not.toHaveAttribute('readonly');
Expand All @@ -44,7 +50,7 @@ describe('PolicyResourceFields', () => {

it('calls "setPolicyRules" when id input values change', async () => {
const user = userEvent.setup();
renderPolicyResourceFields();
renderPolicyResourceFieldsWithMultipleNarrowingPolicies();

const idInput = screen.getByLabelText(textMock('policy_editor.narrowing_list_field_id'));

Expand All @@ -57,7 +63,7 @@ describe('PolicyResourceFields', () => {

it('calls "setPolicyRules" when type input values change', async () => {
const user = userEvent.setup();
renderPolicyResourceFields();
renderPolicyResourceFieldsWithMultipleNarrowingPolicies();

const typeInput = screen.getByLabelText(textMock('policy_editor.narrowing_list_field_type'));

Expand All @@ -70,7 +76,7 @@ describe('PolicyResourceFields', () => {

it('calls "savePolicy" when input fields lose focus', async () => {
const user = userEvent.setup();
renderPolicyResourceFields();
renderPolicyResourceFieldsWithMultipleNarrowingPolicies();

const typeInput = screen.getByLabelText(textMock('policy_editor.narrowing_list_field_type'));

Expand All @@ -79,8 +85,18 @@ describe('PolicyResourceFields', () => {
expect(mockPolicyEditorContextValue.savePolicy).toHaveBeenCalledTimes(1);
});

it('hides the delete button when "canEditTypeAndId" is false', () => {
renderPolicyResourceFields({ canEditTypeAndId: false });
it('renders the delete button when there are multiple narrowing policies', () => {
renderPolicyResourceFieldsWithMultipleNarrowingPolicies();

const deleteButton = screen.queryByRole('button', {
name: textMock('policy_editor.narrowing_list_field_delete'),
});

expect(deleteButton).toBeInTheDocument();
});

it('hides the delete button when there is only a single narrowing policy', () => {
renderPolicyResourceFieldsWithSingleNarrowingPolicy();

const deleteButton = screen.queryByRole('button', {
name: textMock('policy_editor.narrowing_list_field_delete'),
Expand All @@ -91,7 +107,7 @@ describe('PolicyResourceFields', () => {

it('calls "setPolicyRules" and "savePolicy" when delete button is clicked', async () => {
const user = userEvent.setup();
renderPolicyResourceFields();
renderPolicyResourceFieldsWithMultipleNarrowingPolicies();

const deleteButton = screen.getByRole('button', {
name: textMock('policy_editor.narrowing_list_field_delete'),
Expand All @@ -104,9 +120,19 @@ describe('PolicyResourceFields', () => {
expect(mockPolicyEditorContextValue.setPolicyRules).toHaveBeenCalledTimes(1);
expect(mockPolicyEditorContextValue.savePolicy).toHaveBeenCalledTimes(1);
});

it('hides the delete button when there are multiple narrowing policies and "canEditTypeAndId" is false', () => {
renderPolicyResourceFieldsWithMultipleNarrowingPolicies({ canEditTypeAndId: false });

const deleteButton = screen.queryByRole('button', {
name: textMock('policy_editor.narrowing_list_field_delete'),
});

expect(deleteButton).not.toBeInTheDocument();
});
});

const renderPolicyResourceFields = (
const renderPolicyResourceFieldsWithMultipleNarrowingPolicies = (
policyResourceFieldsProps: Partial<PolicyResourceFieldsProps> = {},
) => {
return render(
Expand All @@ -117,3 +143,15 @@ const renderPolicyResourceFields = (
</PolicyEditorContext.Provider>,
);
};

const renderPolicyResourceFieldsWithSingleNarrowingPolicy = (
policyResourceFieldsProps: Partial<PolicyResourceFieldsProps> = {},
) => {
return render(
<PolicyEditorContext.Provider value={mockPolicyEditorContextValueWithSingleNarrowingPolicy}>
<PolicyRuleContext.Provider value={mockPolicyRuleContextValueWithSingleNarrowingPolicy}>
<PolicyResourceFields {...defaultProps} {...policyResourceFieldsProps} />
</PolicyRuleContext.Provider>
</PolicyEditorContext.Provider>,
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const PolicyResourceFields = ({
const { savePolicy, setPolicyRules, policyRules } = usePolicyEditorContext();
const { policyRule } = usePolicyRuleContext();

const isMultipleNarrowingResources = policyRule.resources[resourceIndex].length > 1;

const handleInputChange = (field: 'id' | 'type', value: string) => {
const updatedResources = [...policyRule.resources];
updatedResources[resourceIndex][resourceNarrowingIndex] = {
Expand Down Expand Up @@ -95,7 +97,7 @@ export const PolicyResourceFields = ({
</div>
</div>
<div className={classes.buttonWrapper}>
{canEditTypeAndId && (
{canEditTypeAndId && isMultipleNarrowingResources && (
<StudioButton
aria-disabled={!canEditTypeAndId}
color='danger'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { type PolicyEditorContextProps } from '../../src/contexts/PolicyEditorContext';
import { mockActions } from './policyActionMocks';
import { mockPolicyRuleCards } from './policyRuleMocks';
import {
mockPolicyRuleCards,
mockPolicyRuleCardWithSingleNarrowingPolicy,
} from './policyRuleMocks';
import { mockSubjects } from './policySubjectMocks';
import { type PolicyEditorUsage } from '../../src/types';
import { mockResourecId1 } from './policySubResourceMocks';
Expand All @@ -19,3 +22,15 @@ export const mockPolicyEditorContextValue: PolicyEditorContextProps = {
resourceId: mockResourecId1,
savePolicy: jest.fn(),
};

export const mockPolicyEditorContextValueWithSingleNarrowingPolicy: PolicyEditorContextProps = {
policyRules: [mockPolicyRuleCardWithSingleNarrowingPolicy],
setPolicyRules: jest.fn(),
actions: mockActions,
subjects: mockSubjects,
usageType: mockUsageType,
resourceType: mockResourceType,
showAllErrors: false,
resourceId: mockResourecId1,
savePolicy: jest.fn(),
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { type PolicyRuleContextProps } from '../../src/contexts/PolicyRuleContext';
import { mockPolicyRuleCard1 } from './policyRuleMocks';
import {
mockPolicyRuleCard1,
mockPolicyRuleCardWithSingleNarrowingPolicy,
} from './policyRuleMocks';
import { type PolicyError } from '../../src/types';

const policyError: PolicyError = {
Expand All @@ -15,3 +18,11 @@ export const mockPolicyRuleContextValue: PolicyRuleContextProps = {
policyError,
setPolicyError: jest.fn(),
};

export const mockPolicyRuleContextValueWithSingleNarrowingPolicy: PolicyRuleContextProps = {
policyRule: mockPolicyRuleCardWithSingleNarrowingPolicy,
showAllErrors: false,
uniqueId: 'id',
policyError,
setPolicyError: jest.fn(),
};
14 changes: 13 additions & 1 deletion frontend/packages/policy-editor/test/mocks/policyRuleMocks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { PolicyRule, PolicyRuleCard } from '../../src/types';
import { mockAction1, mockAction2, mockAction4 } from './policyActionMocks';
import { mockPolicyResources, mockPolicyRuleResources } from './policySubResourceMocks';
import {
mockPolicyResources,
mockPolicyRuleResources,
mockPolicyRuleResourcesWithSingleNarrowingPolicy,
} from './policySubResourceMocks';
import {
mockSubjectBackendString1,
mockSubjectBackendString3,
Expand All @@ -10,6 +14,7 @@ import {

export const mockRuleId1: string = 'r1';
export const mockRuleId2: string = 'r2';
export const mockRuleId3: string = 'r3';

export const mockPolicyRuleCard1: PolicyRuleCard = {
ruleId: mockRuleId1,
Expand All @@ -25,6 +30,13 @@ export const mockPolicyRuleCard2: PolicyRuleCard = {
actions: [],
resources: [[]],
};
export const mockPolicyRuleCardWithSingleNarrowingPolicy: PolicyRuleCard = {
ruleId: mockRuleId3,
description: '',
subject: [mockSubjectId1, mockSubjectId3],
actions: [mockAction1.actionId, mockAction2.actionId, mockAction4.actionId],
resources: mockPolicyRuleResourcesWithSingleNarrowingPolicy,
};
export const mockPolicyRuleCards: PolicyRuleCard[] = [mockPolicyRuleCard1, mockPolicyRuleCard2];

export const mockPolicyRule1: PolicyRule = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const mockResource2: PolicyRuleResource[] = [mockResource21];
export const mockResource3: PolicyRuleResource[] = [mockResource31, mockResource32];

export const mockPolicyRuleResources: PolicyRuleResource[][] = [mockResource1, mockResource2];
export const mockPolicyRuleResourcesWithSingleNarrowingPolicy: PolicyRuleResource[][] = [
mockResource2,
mockResource2,
];

export const mockPolicyResourceBackendString1: string = `${mockResourceType1}:${mockResourecId1}`;
export const mockPolicyResourceBackendString2: string = `${mockResourceType2}:${mockResourecId2}`;
Expand Down