Commit 58b89ffb authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '341932-update-policy-drawer-with-tabs' into 'master'

Update policy drawer to include tabs

See merge request gitlab-org/gitlab!78608
parents 8888908f 325bb7aa
...@@ -3,7 +3,7 @@ import { GlIntersperse } from '@gitlab/ui'; ...@@ -3,7 +3,7 @@ import { GlIntersperse } from '@gitlab/ui';
import { n__, s__ } from '~/locale'; import { n__, s__ } from '~/locale';
import { removeUnnecessaryDashes } from '../../utils'; import { removeUnnecessaryDashes } from '../../utils';
import { fromYaml, humanizeNetworkPolicy } from '../policy_editor/network_policy/lib'; import { fromYaml, humanizeNetworkPolicy } from '../policy_editor/network_policy/lib';
import PolicyPreview from '../policy_editor/policy_preview.vue'; import PolicyPreviewHuman from '../policy_editor/policy_preview_human.vue';
import BasePolicy from './base_policy.vue'; import BasePolicy from './base_policy.vue';
import PolicyInfoRow from './policy_info_row.vue'; import PolicyInfoRow from './policy_info_row.vue';
...@@ -12,11 +12,12 @@ export default { ...@@ -12,11 +12,12 @@ export default {
description: s__('SecurityOrchestration|Description'), description: s__('SecurityOrchestration|Description'),
network: s__('NetworkPolicies|Network'), network: s__('NetworkPolicies|Network'),
status: s__('SecurityOrchestration|Status'), status: s__('SecurityOrchestration|Status'),
summary: s__('SecurityOrchestration|Summary'),
}, },
components: { components: {
GlIntersperse, GlIntersperse,
BasePolicy, BasePolicy,
PolicyPreview, PolicyPreviewHuman,
PolicyInfoRow, PolicyInfoRow,
}, },
props: { props: {
...@@ -58,6 +59,10 @@ export default { ...@@ -58,6 +59,10 @@ export default {
<template #type>{{ $options.i18n.network }}</template> <template #type>{{ $options.i18n.network }}</template>
<template #default="{ statusLabel }"> <template #default="{ statusLabel }">
<policy-info-row :label="$options.i18n.summary">
<policy-preview-human :policy-description="humanizedPolicy" />
</policy-info-row>
<div v-if="parsedYaml"> <div v-if="parsedYaml">
<policy-info-row <policy-info-row
v-if="parsedYaml.description" v-if="parsedYaml.description"
...@@ -81,13 +86,6 @@ export default { ...@@ -81,13 +86,6 @@ export default {
</gl-intersperse> </gl-intersperse>
</policy-info-row> </policy-info-row>
</div> </div>
<policy-preview
class="gl-mt-4"
:initial-tab="initialTab"
:policy-yaml="policyYaml"
:policy-description="humanizedPolicy"
/>
</template> </template>
</base-policy> </base-policy>
</template> </template>
<script> <script>
import { GlButton, GlDrawer } from '@gitlab/ui'; import { GlButton, GlDrawer, GlTabs, GlTab } from '@gitlab/ui';
import { DRAWER_Z_INDEX } from '~/lib/utils/constants'; import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
import { getContentWrapperHeight, removeUnnecessaryDashes } from '../../utils'; import { getContentWrapperHeight, removeUnnecessaryDashes } from '../../utils';
import { POLICIES_LIST_CONTAINER_CLASS, POLICY_TYPE_COMPONENT_OPTIONS } from '../constants'; import { POLICIES_LIST_CONTAINER_CLASS, POLICY_TYPE_COMPONENT_OPTIONS } from '../constants';
...@@ -17,6 +17,8 @@ export default { ...@@ -17,6 +17,8 @@ export default {
components: { components: {
GlButton, GlButton,
GlDrawer, GlDrawer,
GlTab,
GlTabs,
PolicyYamlEditor: () => PolicyYamlEditor: () =>
import(/* webpackChunkName: 'policy_yaml_editor' */ '../policy_yaml_editor.vue'), import(/* webpackChunkName: 'policy_yaml_editor' */ '../policy_yaml_editor.vue'),
CiliumNetworkPolicy, CiliumNetworkPolicy,
...@@ -70,7 +72,7 @@ export default { ...@@ -70,7 +72,7 @@ export default {
v-on="$listeners" v-on="$listeners"
> >
<template v-if="policy" #title> <template v-if="policy" #title>
<h3 class="gl-my-0">{{ policy.name }}</h3> <h4 class="gl-my-0 gl-mr-3">{{ policy.name }}</h4>
</template> </template>
<template v-if="policy" #header> <template v-if="policy" #header>
<gl-button <gl-button
...@@ -82,15 +84,27 @@ export default { ...@@ -82,15 +84,27 @@ export default {
>{{ s__('NetworkPolicies|Edit policy') }}</gl-button >{{ s__('NetworkPolicies|Edit policy') }}</gl-button
> >
</template> </template>
<div v-if="policy"> <gl-tabs v-if="policy" class="gl-p-0!" justified content-class="gl-py-0" lazy>
<component :is="policyComponent" v-if="policyComponent" :policy="policy" /> <gl-tab title="Details" class="gl-mt-5 gl-ml-6 gl-mr-3">
<div v-else> <component :is="policyComponent" v-if="policyComponent" :policy="policy" />
<h5>{{ s__('NetworkPolicies|Policy definition') }}</h5> <div v-else>
<p> <h5>{{ s__('NetworkPolicies|Policy definition') }}</h5>
{{ s__("NetworkPolicies|Define this policy's location, conditions and actions.") }} <p>
</p> {{ s__("NetworkPolicies|Define this policy's location, conditions and actions.") }}
<policy-yaml-editor :value="policyYaml" data-testid="policy-yaml-editor" /> </p>
</div> <policy-yaml-editor
</div> :value="policyYaml"
data-testid="policy-yaml-editor-default-component"
/>
</div>
</gl-tab>
<gl-tab v-if="policyComponent" title="Yaml">
<policy-yaml-editor
class="gl-h-100vh"
:value="policyYaml"
data-testid="policy-yaml-editor-tab-content"
/>
</gl-tab>
</gl-tabs>
</gl-drawer> </gl-drawer>
</template> </template>
...@@ -328,7 +328,10 @@ export default { ...@@ -328,7 +328,10 @@ export default {
:id="$options.policyPreviewHumanCollapseId" :id="$options.policyPreviewHumanCollapseId"
v-model="isPolicyPreviewHumanVisible" v-model="isPolicyPreviewHumanVisible"
> >
<policy-preview-human :policy-description="humanizedPolicy" /> <policy-preview-human
class="gl-bg-gray-10 gl-py-3 gl-px-4"
:policy-description="humanizedPolicy"
/>
</gl-collapse> </gl-collapse>
</div> </div>
</template> </template>
......
<script>
import { GlTabs, GlTab } from '@gitlab/ui';
import { PARSING_ERROR_MESSAGE } from './constants';
import PolicyPreviewHuman from './policy_preview_human.vue';
export default {
i18n: {
PARSING_ERROR_MESSAGE,
},
components: {
GlTabs,
GlTab,
PolicyPreviewHuman,
},
props: {
policyYaml: {
type: String,
required: true,
},
policyDescription: {
type: String,
required: false,
default: '',
},
initialTab: {
type: Number,
required: false,
default: 0,
},
},
data() {
return { selectedTab: this.initialTab };
},
};
</script>
<template>
<gl-tabs v-model="selectedTab" content-class="gl-pt-0">
<gl-tab :title="s__('NetworkPolicies|Rule')">
<policy-preview-human
:class="{
'gl-border-t-none! gl-rounded-top-left-none gl-rounded-top-right-none': Boolean(
policyDescription,
),
}"
:policy-description="policyDescription"
/>
</gl-tab>
<gl-tab :title="s__('NetworkPolicies|.yaml')">
<pre class="gl-bg-white gl-rounded-top-left-none gl-rounded-top-right-none gl-border-t-none"
>{{ policyYaml }}
</pre>
</gl-tab>
</gl-tabs>
</template>
...@@ -24,11 +24,7 @@ export default { ...@@ -24,11 +24,7 @@ export default {
</script> </script>
<template> <template>
<div <div v-if="policyDescription" v-safe-html:[$options.safeHtmlConfig]="policyDescription"></div>
v-if="policyDescription"
v-safe-html:[$options.safeHtmlConfig]="policyDescription"
class="gl-bg-gray-10 gl-py-3 gl-px-4"
></div>
<div v-else> <div v-else>
<gl-alert variant="info" :dismissible="false"> <gl-alert variant="info" :dismissible="false">
{{ $options.i18n.PARSING_ERROR_MESSAGE }} {{ $options.i18n.PARSING_ERROR_MESSAGE }}
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CiliumNetworkPolicy component supported YAML renders policy preview tabs 1`] = ` exports[`CiliumNetworkPolicy component supported YAML renders policy preview 1`] = `
<div> <div>
<h5 <h5
class="gl-mt-3" class="gl-mt-3"
...@@ -14,6 +14,14 @@ exports[`CiliumNetworkPolicy component supported YAML renders policy preview tab ...@@ -14,6 +14,14 @@ exports[`CiliumNetworkPolicy component supported YAML renders policy preview tab
Network Network
</p> </p>
<policy-info-row-stub
label="Summary"
>
<policy-preview-human-stub
policydescription="Deny all traffic"
/>
</policy-info-row-stub>
<div> <div>
<policy-info-row-stub <policy-info-row-stub
data-testid="description" data-testid="description"
...@@ -32,26 +40,10 @@ exports[`CiliumNetworkPolicy component supported YAML renders policy preview tab ...@@ -32,26 +40,10 @@ exports[`CiliumNetworkPolicy component supported YAML renders policy preview tab
<!----> <!---->
</div> </div>
<policy-preview-stub
class="gl-mt-4"
initialtab="0"
policydescription="Deny all traffic"
policyyaml="apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
description: test description
metadata:
name: test-policy
spec:
endpointSelector:
matchLabels:
network-policy.gitlab.com/disabled_by: gitlab
"
/>
</div> </div>
`; `;
exports[`CiliumNetworkPolicy component unsupported YAML renders policy preview tabs 1`] = ` exports[`CiliumNetworkPolicy component unsupported YAML renders policy preview 1`] = `
<div> <div>
<h5 <h5
class="gl-mt-3" class="gl-mt-3"
...@@ -65,12 +57,12 @@ exports[`CiliumNetworkPolicy component unsupported YAML renders policy preview t ...@@ -65,12 +57,12 @@ exports[`CiliumNetworkPolicy component unsupported YAML renders policy preview t
Network Network
</p> </p>
<!----> <policy-info-row-stub
label="Summary"
>
<policy-preview-human-stub />
</policy-info-row-stub>
<policy-preview-stub <!---->
class="gl-mt-4"
initialtab="1"
policyyaml="unsupportedPrimaryKey: test"
/>
</div> </div>
`; `;
...@@ -2,7 +2,7 @@ import { GlIntersperse } from '@gitlab/ui'; ...@@ -2,7 +2,7 @@ import { GlIntersperse } from '@gitlab/ui';
import BasePolicy from 'ee/threat_monitoring/components/policy_drawer/base_policy.vue'; import BasePolicy from 'ee/threat_monitoring/components/policy_drawer/base_policy.vue';
import CiliumNetworkPolicy from 'ee/threat_monitoring/components/policy_drawer/cilium_network_policy.vue'; import CiliumNetworkPolicy from 'ee/threat_monitoring/components/policy_drawer/cilium_network_policy.vue';
import { toYaml } from 'ee/threat_monitoring/components/policy_editor/network_policy/lib'; import { toYaml } from 'ee/threat_monitoring/components/policy_editor/network_policy/lib';
import PolicyPreview from 'ee/threat_monitoring/components/policy_editor/policy_preview.vue'; import PolicyPreviewHuman from 'ee/threat_monitoring/components/policy_editor/policy_preview_human.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('CiliumNetworkPolicy component', () => { describe('CiliumNetworkPolicy component', () => {
...@@ -15,7 +15,7 @@ describe('CiliumNetworkPolicy component', () => { ...@@ -15,7 +15,7 @@ describe('CiliumNetworkPolicy component', () => {
}); });
const unsupportedYaml = 'unsupportedPrimaryKey: test'; const unsupportedYaml = 'unsupportedPrimaryKey: test';
const findPolicyPreview = () => wrapper.findComponent(PolicyPreview); const findPolicyPreview = () => wrapper.findComponent(PolicyPreviewHuman);
const findDescription = () => wrapper.findByTestId('description'); const findDescription = () => wrapper.findByTestId('description');
const findEnvironments = () => wrapper.findByTestId('environments'); const findEnvironments = () => wrapper.findByTestId('environments');
...@@ -40,7 +40,7 @@ describe('CiliumNetworkPolicy component', () => { ...@@ -40,7 +40,7 @@ describe('CiliumNetworkPolicy component', () => {
factory({ propsData: { policy: { yaml: supportedYaml } } }); factory({ propsData: { policy: { yaml: supportedYaml } } });
}); });
it('renders policy preview tabs', () => { it('renders policy preview', () => {
expect(wrapper.find('div').element).toMatchSnapshot(); expect(wrapper.find('div').element).toMatchSnapshot();
}); });
...@@ -50,12 +50,7 @@ describe('CiliumNetworkPolicy component', () => { ...@@ -50,12 +50,7 @@ describe('CiliumNetworkPolicy component', () => {
}); });
it('does render the policy preview', () => { it('does render the policy preview', () => {
expect(findPolicyPreview().exists()).toBe(true); expect(findPolicyPreview().props('policyDescription')).toBe('Deny all traffic');
expect(findPolicyPreview().props()).toStrictEqual({
initialTab: 0,
policyDescription: 'Deny all traffic',
policyYaml: supportedYaml,
});
}); });
}); });
...@@ -64,7 +59,7 @@ describe('CiliumNetworkPolicy component', () => { ...@@ -64,7 +59,7 @@ describe('CiliumNetworkPolicy component', () => {
factory({ propsData: { policy: { yaml: unsupportedYaml } } }); factory({ propsData: { policy: { yaml: unsupportedYaml } } });
}); });
it('renders policy preview tabs', () => { it('renders policy preview', () => {
expect(wrapper.find('div').element).toMatchSnapshot(); expect(wrapper.find('div').element).toMatchSnapshot();
}); });
...@@ -74,11 +69,7 @@ describe('CiliumNetworkPolicy component', () => { ...@@ -74,11 +69,7 @@ describe('CiliumNetworkPolicy component', () => {
it('does render the policy preview', () => { it('does render the policy preview', () => {
expect(findPolicyPreview().exists()).toBe(true); expect(findPolicyPreview().exists()).toBe(true);
expect(findPolicyPreview().props()).toStrictEqual({ expect(findPolicyPreview().props('policyDescription')).toBe(null);
initialTab: 1,
policyDescription: null,
policyYaml: unsupportedYaml,
});
}); });
}); });
......
import { GlButton, GlDrawer, GlTabs, GlTab } from '@gitlab/ui';
import { POLICY_TYPE_COMPONENT_OPTIONS } from 'ee/threat_monitoring/components/constants'; import { POLICY_TYPE_COMPONENT_OPTIONS } from 'ee/threat_monitoring/components/constants';
import CiliumNetworkPolicy from 'ee/threat_monitoring/components/policy_drawer/cilium_network_policy.vue'; import CiliumNetworkPolicy from 'ee/threat_monitoring/components/policy_drawer/cilium_network_policy.vue';
import PolicyDrawer from 'ee/threat_monitoring/components/policy_drawer/policy_drawer.vue'; import PolicyDrawer from 'ee/threat_monitoring/components/policy_drawer/policy_drawer.vue';
import ScanExecutionPolicy from 'ee/threat_monitoring/components/policy_drawer/scan_execution_policy.vue'; import ScanExecutionPolicy from 'ee/threat_monitoring/components/policy_drawer/scan_execution_policy.vue';
import { mountExtended } from 'helpers/vue_test_utils_helper'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { import {
mockNetworkPoliciesResponse, mockNetworkPoliciesResponse,
mockCiliumPolicy, mockCiliumPolicy,
...@@ -14,22 +15,25 @@ const [mockGenericPolicy] = mockNetworkPoliciesResponse; ...@@ -14,22 +15,25 @@ const [mockGenericPolicy] = mockNetworkPoliciesResponse;
describe('PolicyDrawer component', () => { describe('PolicyDrawer component', () => {
let wrapper; let wrapper;
const factory = ({ propsData } = {}) => { const factory = ({ mountFn = shallowMountExtended, propsData, stubs = {} } = {}) => {
wrapper = mountExtended(PolicyDrawer, { wrapper = mountFn(PolicyDrawer, {
propsData: { propsData: {
editPolicyPath: '/policies/policy/edit?environment_id=-1', editPolicyPath: '/policies/policy/edit?environment_id=-1',
open: true, open: true,
...propsData, ...propsData,
}, },
stubs: { PolicyYamlEditor: true }, stubs: { PolicyYamlEditor: true, ...stubs },
}); });
}; };
// Finders // Finders
const findEditButton = () => wrapper.findByTestId('edit-button'); const findEditButton = () => wrapper.findByTestId('edit-button');
const findPolicyEditor = () => wrapper.findByTestId('policy-yaml-editor'); const findAllTabs = () => wrapper.findAllComponents(GlTab);
const findCiliumNetworkPolicy = () => wrapper.findComponent(CiliumNetworkPolicy); const findCiliumNetworkPolicy = () => wrapper.findComponent(CiliumNetworkPolicy);
const findScanExecutionPolicy = () => wrapper.findComponent(ScanExecutionPolicy); const findScanExecutionPolicy = () => wrapper.findComponent(ScanExecutionPolicy);
const findDefaultComponentPolicyEditor = () =>
wrapper.findByTestId('policy-yaml-editor-default-component');
const findTabPolicyEditor = () => wrapper.findByTestId('policy-yaml-editor-tab-content');
// Shared assertions // Shared assertions
const itRendersEditButton = () => { const itRendersEditButton = () => {
...@@ -47,7 +51,7 @@ describe('PolicyDrawer component', () => { ...@@ -47,7 +51,7 @@ describe('PolicyDrawer component', () => {
describe('by default', () => { describe('by default', () => {
beforeEach(() => { beforeEach(() => {
factory(); factory({ stubs: { GlDrawer } });
}); });
it('does not render edit button', () => { it('does not render edit button', () => {
...@@ -58,6 +62,7 @@ describe('PolicyDrawer component', () => { ...@@ -58,6 +62,7 @@ describe('PolicyDrawer component', () => {
describe('given a generic network policy', () => { describe('given a generic network policy', () => {
beforeEach(() => { beforeEach(() => {
factory({ factory({
mountFn: mountExtended,
propsData: { propsData: {
policy: mockGenericPolicy, policy: mockGenericPolicy,
}, },
...@@ -65,9 +70,7 @@ describe('PolicyDrawer component', () => { ...@@ -65,9 +70,7 @@ describe('PolicyDrawer component', () => {
}); });
it('renders network policy editor with manifest', () => { it('renders network policy editor with manifest', () => {
const policyEditor = findPolicyEditor(); expect(findDefaultComponentPolicyEditor().attributes('value')).toBe(mockGenericPolicy.yaml);
expect(policyEditor.exists()).toBe(true);
expect(policyEditor.attributes('value')).toBe(mockGenericPolicy.yaml);
}); });
itRendersEditButton(); itRendersEditButton();
...@@ -84,6 +87,11 @@ describe('PolicyDrawer component', () => { ...@@ -84,6 +87,11 @@ describe('PolicyDrawer component', () => {
policy: mock, policy: mock,
policyType, policyType,
}, },
stubs: {
GlButton,
GlDrawer,
GlTabs,
},
}); });
}); });
...@@ -91,6 +99,14 @@ describe('PolicyDrawer component', () => { ...@@ -91,6 +99,14 @@ describe('PolicyDrawer component', () => {
expect(finder().exists()).toBe(true); expect(finder().exists()).toBe(true);
}); });
it('renders the tabs', () => {
expect(findAllTabs()).toHaveLength(2);
});
it('renders the policy editor', () => {
expect(findTabPolicyEditor().attributes('value')).toBe(mock.yaml);
});
itRendersEditButton(); itRendersEditButton();
}); });
}); });
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PolicyPreview component with policy description renders policy preview tabs 1`] = `
<gl-tabs-stub
contentclass="gl-pt-0"
queryparamname="tab"
theme="indigo"
value="0"
>
<gl-tab-stub
title="Rule"
titlelinkclass=""
>
<policy-preview-human-stub
class="gl-border-t-none! gl-rounded-top-left-none gl-rounded-top-right-none"
policydescription="<strong>bar</strong><br><div>test</div><script></script>"
/>
</gl-tab-stub>
<gl-tab-stub
title=".yaml"
titlelinkclass=""
>
<pre
class="gl-bg-white gl-rounded-top-left-none gl-rounded-top-right-none gl-border-t-none"
>
foo
</pre>
</gl-tab-stub>
</gl-tabs-stub>
`;
import { GlTabs } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import PolicyPreviewHuman from 'ee/threat_monitoring/components/policy_editor/policy_preview_human.vue';
import PolicyPreview from 'ee/threat_monitoring/components/policy_editor/policy_preview.vue';
describe('PolicyPreview component', () => {
let wrapper;
const findTabs = () => wrapper.findComponent(GlTabs);
const findPolicyPreviewHuman = () => wrapper.findComponent(PolicyPreviewHuman);
const factory = ({ propsData } = {}) => {
wrapper = shallowMount(PolicyPreview, {
propsData: {
...propsData,
},
});
};
afterEach(() => {
wrapper.destroy();
});
describe('with policy description', () => {
const policyDescription = '<strong>bar</strong><br><div>test</div><script></script>';
beforeEach(() => {
factory({
propsData: {
policyYaml: 'foo',
policyDescription,
},
});
});
it('renders policy preview tabs', () => {
expect(findTabs().element).toMatchSnapshot();
});
it('renders the policy preview human', () => {
expect(findPolicyPreviewHuman().props('policyDescription')).toBe(policyDescription);
});
it('renders the first tab', () => {
expect(findTabs().attributes().value).toEqual('0');
});
describe('initial tab', () => {
it('selects initial tab', () => {
factory({
propsData: {
policyYaml: 'foo',
policyDescription: 'bar',
initialTab: 1,
},
});
expect(findTabs().attributes().value).toEqual('1');
});
});
});
describe('without policy description', () => {
beforeEach(() => {
factory({
propsData: {
policyYaml: 'foo',
},
});
});
});
});
...@@ -23616,9 +23616,6 @@ msgstr "" ...@@ -23616,9 +23616,6 @@ msgstr ""
msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port" msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
msgstr "" msgstr ""
msgid "NetworkPolicies|.yaml"
msgstr ""
msgid "NetworkPolicies|.yaml mode" msgid "NetworkPolicies|.yaml mode"
msgstr "" msgstr ""
...@@ -23697,9 +23694,6 @@ msgstr "" ...@@ -23697,9 +23694,6 @@ msgstr ""
msgid "NetworkPolicies|Policy definition" msgid "NetworkPolicies|Policy definition"
msgstr "" msgstr ""
msgid "NetworkPolicies|Rule"
msgstr ""
msgid "NetworkPolicies|Rule mode" msgid "NetworkPolicies|Rule mode"
msgstr "" msgstr ""
...@@ -31944,6 +31938,9 @@ msgstr "" ...@@ -31944,6 +31938,9 @@ msgstr ""
msgid "SecurityOrchestration|Status" msgid "SecurityOrchestration|Status"
msgstr "" msgstr ""
msgid "SecurityOrchestration|Summary"
msgstr ""
msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}." msgid "SecurityOrchestration|The %{scanners} %{severities} in an open merge request targeting %{branches}."
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment