Commit db6ad441 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '341932-update-policy-drawer-layout' into 'master'

Update policy_drawer_layout to standardize drawer

See merge request gitlab-org/gitlab!80687
parents b5daae7b 080d39fa
<script>
import { ENABLED_LABEL, NOT_ENABLED_LABEL } from './constants';
export default {
props: {
policy: {
type: Object,
required: false,
default: null,
},
},
computed: {
statusLabel() {
return this.policy?.enabled ? ENABLED_LABEL : NOT_ENABLED_LABEL;
},
},
};
</script>
<template>
<div>
<h5 class="gl-mt-3">{{ __('Type') }}</h5>
<p data-testid="policy-type">
<slot name="type"></slot>
</p>
<slot v-bind="{ statusLabel }"></slot>
</div>
</template>
......@@ -4,8 +4,8 @@ import { n__, s__ } from '~/locale';
import { removeUnnecessaryDashes } from '../../utils';
import { fromYaml, humanizeNetworkPolicy } from '../policy_editor/network_policy/lib';
import PolicyPreviewHuman from '../policy_editor/policy_preview_human.vue';
import BasePolicy from './base_policy.vue';
import PolicyInfoRow from './policy_info_row.vue';
import { ENABLED_LABEL, NOT_ENABLED_LABEL } from './constants';
export default {
i18n: {
......@@ -16,7 +16,6 @@ export default {
},
components: {
GlIntersperse,
BasePolicy,
PolicyPreviewHuman,
PolicyInfoRow,
},
......@@ -50,42 +49,46 @@ export default {
environmentLabel() {
return n__('Environment', 'Environments', this.environments.length);
},
statusLabel() {
return this.policy?.enabled ? ENABLED_LABEL : NOT_ENABLED_LABEL;
},
},
};
</script>
<template>
<base-policy :policy="policy">
<template #type>{{ $options.i18n.network }}</template>
<div>
<h5 class="gl-mt-3">{{ __('Type') }}</h5>
<p data-testid="policy-type">
{{ $options.i18n.network }}
</p>
<template #default="{ statusLabel }">
<policy-info-row :label="$options.i18n.summary">
<policy-preview-human :policy-description="humanizedPolicy" />
</policy-info-row>
<policy-info-row :label="$options.i18n.summary">
<policy-preview-human :policy-description="humanizedPolicy" />
</policy-info-row>
<div v-if="parsedYaml">
<policy-info-row
v-if="parsedYaml.description"
data-testid="description"
:label="$options.i18n.description"
>
{{ parsedYaml.description }}
</policy-info-row>
<div v-if="parsedYaml">
<policy-info-row
v-if="parsedYaml.description"
data-testid="description"
:label="$options.i18n.description"
>
{{ parsedYaml.description }}
</policy-info-row>
<policy-info-row :label="$options.i18n.status">{{ statusLabel }}</policy-info-row>
<policy-info-row :label="$options.i18n.status">{{ statusLabel }}</policy-info-row>
<policy-info-row
v-if="environments.length"
data-testid="environments"
:label="environmentLabel"
>
<gl-intersperse>
<span v-for="environment in environments" :key="environment.name">
{{ environment.name }}
</span>
</gl-intersperse>
</policy-info-row>
</div>
</template>
</base-policy>
<policy-info-row
v-if="environments.length"
data-testid="environments"
:label="environmentLabel"
>
<gl-intersperse>
<span v-for="environment in environments" :key="environment.name">
{{ environment.name }}
</span>
</gl-intersperse>
</policy-info-row>
</div>
</div>
</template>
import { s__ } from '~/locale';
export const DEFAULT_DESCRIPTION_LABEL = s__('SecurityOrchestration|No description');
export const DESCRIPTION_TITLE = s__('SecurityOrchestration|Description');
export const ENABLED_LABEL = s__('SecurityOrchestration|Enabled');
export const NOT_ENABLED_LABEL = s__('SecurityOrchestration|Not enabled');
export const TYPE_TITLE = s__('SecurityOrchestration|Policy Type');
export const STATUS_TITLE = s__('SecurityOrchestration|Status');
<script>
import { GlIcon } from '@gitlab/ui';
import {
DEFAULT_DESCRIPTION_LABEL,
DESCRIPTION_TITLE,
ENABLED_LABEL,
NOT_ENABLED_LABEL,
STATUS_TITLE,
TYPE_TITLE,
} from './constants';
import PolicyInfoRow from './policy_info_row.vue';
export default {
components: {
GlIcon,
PolicyInfoRow,
},
i18n: {
policyTypeTitle: TYPE_TITLE,
descriptionTitle: DESCRIPTION_TITLE,
defaultDescription: DEFAULT_DESCRIPTION_LABEL,
statusTitle: STATUS_TITLE,
},
props: {
description: {
type: String,
required: false,
default: '',
},
policy: {
type: Object,
required: false,
default: null,
},
type: {
type: String,
required: true,
},
},
computed: {
statusLabel() {
return this.policy?.enabled ? ENABLED_LABEL : NOT_ENABLED_LABEL;
},
},
};
</script>
<template>
<div>
<div data-testid="policy-summary">
<slot name="summary"></slot>
</div>
<policy-info-row data-testid="policy-type" :label="$options.i18n.policyTypeTitle">
{{ type }}
</policy-info-row>
<policy-info-row :label="$options.i18n.descriptionTitle">
<div v-if="description" data-testid="custom-description-text">
{{ description }}
</div>
<div v-else class="gl-text-gray-500" data-testid="default-description-text">
{{ $options.i18n.defaultDescription }}
</div>
</policy-info-row>
<policy-info-row :label="$options.i18n.statusTitle">
<div v-if="policy.enabled" class="gl-text-green-500" data-testid="enabled-status-text">
<gl-icon name="check-circle-filled" class="gl-mr-3" />{{ statusLabel }}
</div>
<div v-else class="gl-text-gray-500" data-testid="not-enabled-status-text">
{{ statusLabel }}
</div>
</policy-info-row>
</div>
</template>
<script>
import { GlIcon, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
import {
fromYaml,
humanizeActions,
humanizeRules,
} from '../policy_editor/scan_execution_policy/lib';
import BasePolicy from './base_policy.vue';
import PolicyDrawerLayout from './policy_drawer_layout.vue';
import PolicyInfoRow from './policy_info_row.vue';
export default {
i18n: {
action: s__('SecurityOrchestration|Action'),
description: s__('SecurityOrchestration|Description'),
latestScan: s__('SecurityOrchestration|Latest scan'),
rule: s__('SecurityOrchestration|Rule'),
scanExecution: s__('SecurityOrchestration|Scan execution'),
status: s__('SecurityOrchestration|Status'),
viewResults: s__('SecurityOrchestration|view results'),
},
components: {
GlIcon,
GlLink,
BasePolicy,
PolicyDrawerLayout,
PolicyInfoRow,
},
props: {
......@@ -50,47 +43,20 @@ export default {
</script>
<template>
<base-policy :policy="policy">
<template #type>{{ $options.i18n.scanExecution }}</template>
<policy-drawer-layout
key="scan_execution_policy"
:description="parsedYaml.description"
:policy="policy"
:type="$options.i18n.scanExecution"
>
<template v-if="parsedYaml" #summary>
<policy-info-row data-testid="policy-rules" :label="$options.i18n.rule">
<p v-for="rule in humanizedRules" :key="rule">{{ rule }}</p>
</policy-info-row>
<template #default="{ statusLabel }">
<div v-if="parsedYaml">
<policy-info-row
v-if="parsedYaml.description"
data-testid="policy-description"
:label="$options.i18n.description"
>
{{ parsedYaml.description }}
</policy-info-row>
<policy-info-row data-testid="policy-rules" :label="$options.i18n.rule">
<p v-for="rule in humanizedRules" :key="rule">{{ rule }}</p>
</policy-info-row>
<policy-info-row data-testid="policy-actions" :label="$options.i18n.action">
<p v-for="action in humanizedActions" :key="action">{{ action }}</p>
</policy-info-row>
<policy-info-row :label="$options.i18n.status">
<div v-if="policy.enabled" class="gl-text-green-500" data-testid="enabled-status-text">
<gl-icon name="check-circle-filled" class="gl-mr-3" />{{ statusLabel }}
</div>
<div v-else class="gl-text-gray-500" data-testid="not-enabled-status-text">
{{ statusLabel }}
</div>
</policy-info-row>
<policy-info-row
v-if="policy.latestScan"
data-testid="policy-latest-scan"
:label="$options.i18n.latestScan"
>
{{ policy.latestScan.date }}
<gl-link :href="policy.latestScan.pipelineUrl">
{{ $options.i18n.viewResults }}
</gl-link></policy-info-row
>
</div>
<policy-info-row data-testid="policy-actions" :label="$options.i18n.action">
<p v-for="action in humanizedActions" :key="action">{{ action }}</p>
</policy-info-row>
</template>
</base-policy>
</policy-drawer-layout>
</template>
<script>
import { s__ } from '~/locale';
import { fromYaml, humanizeRules, humanizeAction } from '../policy_editor/scan_result_policy/lib';
import BasePolicy from './base_policy.vue';
import PolicyDrawerLayout from './policy_drawer_layout.vue';
import PolicyInfoRow from './policy_info_row.vue';
export default {
i18n: {
action: s__('SecurityOrchestration|Action'),
description: s__('SecurityOrchestration|Description'),
rule: s__('SecurityOrchestration|Rule'),
scanResult: s__('SecurityOrchestration|Scan result'),
status: s__('SecurityOrchestration|Status'),
},
components: {
BasePolicy,
PolicyDrawerLayout,
PolicyInfoRow,
},
props: {
......@@ -46,32 +44,21 @@ export default {
</script>
<template>
<base-policy :policy="policy">
<template #type>{{ $options.i18n.scanResult }}</template>
<template #default="{ statusLabel }">
<div v-if="parsedYaml">
<policy-info-row
v-if="parsedYaml.description"
data-testid="policy-description"
:label="$options.i18n.description"
>
{{ parsedYaml.description }}
</policy-info-row>
<policy-info-row data-testid="policy-rules" :label="$options.i18n.rule">
<p>{{ humanizedAction }}</p>
<ul>
<li v-for="(rule, idx) in humanizedRules" :key="idx">
{{ rule }}
</li>
</ul>
</policy-info-row>
<policy-info-row :label="$options.i18n.status">
{{ statusLabel }}
</policy-info-row>
</div>
<policy-drawer-layout
key="scan_result_policy"
:description="parsedYaml.description"
:policy="policy"
:type="$options.i18n.scanResult"
>
<template v-if="parsedYaml" #summary>
<policy-info-row data-testid="policy-rules" :label="$options.i18n.rule">
<p>{{ humanizedAction }}</p>
<ul>
<li v-for="(rule, idx) in humanizedRules" :key="idx">
{{ rule }}
</li>
</ul>
</policy-info-row>
</template>
</base-policy>
</policy-drawer-layout>
</template>
......@@ -11,7 +11,9 @@ exports[`CiliumNetworkPolicy component supported YAML renders policy preview 1`]
<p
data-testid="policy-type"
>
Network
</p>
<policy-info-row-stub
......@@ -28,8 +30,8 @@ exports[`CiliumNetworkPolicy component supported YAML renders policy preview 1`]
label="Description"
>
test description
test description
</policy-info-row-stub>
<policy-info-row-stub
......@@ -54,7 +56,9 @@ exports[`CiliumNetworkPolicy component unsupported YAML renders policy preview 1
<p
data-testid="policy-type"
>
Network
</p>
<policy-info-row-stub
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PolicyDrawerLayout component enabled policy matches the snapshots 1`] = `
<div>
<div
data-testid="policy-summary"
>
<span
data-testid="summary-text"
>
Summary
</span>
</div>
<policy-info-row-stub
data-testid="policy-type"
label="Policy Type"
>
Scan Execution
</policy-info-row-stub>
<policy-info-row-stub
label="Description"
>
<div
data-testid="custom-description-text"
>
This policy enforces pipeline configuration to have a job with DAST scan
</div>
</policy-info-row-stub>
<policy-info-row-stub
label="Status"
>
<div
class="gl-text-green-500"
data-testid="enabled-status-text"
>
<gl-icon-stub
class="gl-mr-3"
name="check-circle-filled"
size="16"
/>
Enabled
</div>
</policy-info-row-stub>
</div>
`;
exports[`PolicyDrawerLayout component not enabled policy matches the snapshots 1`] = `
<div>
<div
data-testid="policy-summary"
>
<span
data-testid="summary-text"
>
Summary
</span>
</div>
<policy-info-row-stub
data-testid="policy-type"
label="Policy Type"
>
Scan Execution
</policy-info-row-stub>
<policy-info-row-stub
label="Description"
>
<div
class="gl-text-gray-500"
data-testid="default-description-text"
>
No description
</div>
</policy-info-row-stub>
<policy-info-row-stub
label="Status"
>
<div
class="gl-text-gray-500"
data-testid="not-enabled-status-text"
>
Not enabled
</div>
</policy-info-row-stub>
</div>
`;
import BasePolicy from 'ee/threat_monitoring/components/policy_drawer/base_policy.vue';
import {
ENABLED_LABEL,
NOT_ENABLED_LABEL,
} from 'ee/threat_monitoring/components/policy_drawer/constants';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('BasePolicy component', () => {
let wrapper;
const findPolicyType = () => wrapper.findByTestId('policy-type');
const findStatusLabel = () => wrapper.findByTestId('status-label');
const factory = (propsData = {}) => {
wrapper = shallowMountExtended(BasePolicy, {
propsData,
slots: {
type: 'Policy type',
},
scopedSlots: {
default: '<span data-testid="status-label">{{ props.statusLabel }}</span>',
},
});
};
afterEach(() => {
wrapper.destroy();
});
it('renders the policy type', () => {
factory();
expect(findPolicyType().text()).toBe('Policy type');
});
it.each`
description | enabled | expectedLabel
${ENABLED_LABEL} | ${true} | ${ENABLED_LABEL}
${NOT_ENABLED_LABEL} | ${false} | ${NOT_ENABLED_LABEL}
`('renders the status label when policy is $description', ({ enabled, expectedLabel }) => {
factory({
policy: {
enabled,
},
});
expect(findStatusLabel().text()).toBe(expectedLabel);
});
});
import { GlIntersperse } from '@gitlab/ui';
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 { toYaml } from 'ee/threat_monitoring/components/policy_editor/network_policy/lib';
import PolicyPreviewHuman from 'ee/threat_monitoring/components/policy_editor/policy_preview_human.vue';
......@@ -25,7 +24,6 @@ describe('CiliumNetworkPolicy component', () => {
...propsData,
},
stubs: {
BasePolicy,
GlIntersperse,
},
});
......
import PolicyDrawerLayout from 'ee/threat_monitoring/components/policy_drawer/policy_drawer_layout.vue';
import {
DEFAULT_DESCRIPTION_LABEL,
ENABLED_LABEL,
NOT_ENABLED_LABEL,
} from 'ee/threat_monitoring/components/policy_drawer/constants';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mockScanExecutionPolicy } from '../../mocks/mock_data';
describe('PolicyDrawerLayout component', () => {
let wrapper;
const DESCRIPTION = 'This policy enforces pipeline configuration to have a job with DAST scan';
const TYPE = 'Scan Execution';
const findCustomDescription = () => wrapper.findByTestId('custom-description-text');
const findDefaultDescription = () => wrapper.findByTestId('default-description-text');
const findEnabledText = () => wrapper.findByTestId('enabled-status-text');
const findNotEnabledText = () => wrapper.findByTestId('not-enabled-status-text');
const componentStatusText = (status) => (status ? 'does' : 'does not');
const factory = (propsData = {}) => {
wrapper = shallowMountExtended(PolicyDrawerLayout, {
propsData: {
type: TYPE,
...propsData,
},
scopedSlots: {
summary: `<span data-testid="summary-text">Summary</span>`,
},
});
};
afterEach(() => {
wrapper.destroy();
});
describe.each`
context | props | enabled | hasDescription
${'enabled policy'} | ${{ policy: mockScanExecutionPolicy, description: DESCRIPTION }} | ${true} | ${true}
${'not enabled policy'} | ${{ policy: { ...mockScanExecutionPolicy, enabled: false } }} | ${false} | ${false}
`('$context', ({ enabled, hasDescription, props }) => {
beforeEach(() => {
factory(props);
});
it.each`
component | status | finder | exists | text
${'custom description'} | ${componentStatusText(hasDescription)} | ${findCustomDescription} | ${hasDescription} | ${DESCRIPTION}
${'default description'} | ${componentStatusText(!hasDescription)} | ${findDefaultDescription} | ${!hasDescription} | ${DEFAULT_DESCRIPTION_LABEL}
${'enabled text'} | ${componentStatusText(enabled)} | ${findEnabledText} | ${enabled} | ${ENABLED_LABEL}
${'not enabled text'} | ${componentStatusText(!enabled)} | ${findNotEnabledText} | ${!enabled} | ${NOT_ENABLED_LABEL}
`('$status render the $component', ({ exists, finder, text }) => {
const component = finder();
expect(component.exists()).toBe(exists);
if (exists) {
expect(component.text()).toBe(text);
}
});
it('matches the snapshots', () => {
expect(wrapper.element).toMatchSnapshot();
});
});
});
import BasePolicy from 'ee/threat_monitoring/components/policy_drawer/base_policy.vue';
import PolicyDrawerLayout from 'ee/threat_monitoring/components/policy_drawer/policy_drawer_layout.vue';
import ScanExecutionPolicy from 'ee/threat_monitoring/components/policy_drawer/scan_execution_policy.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
mockSecretDetectionScanExecutionManifest,
mockScanExecutionPolicy,
} from '../../mocks/mock_data';
import { mockScanExecutionPolicy } from '../../mocks/mock_data';
describe('ScanExecutionPolicy component', () => {
let wrapper;
const findActions = () => wrapper.findByTestId('policy-actions');
const findDescription = () => wrapper.findByTestId('policy-description');
const findLatestScan = () => wrapper.findByTestId('policy-latest-scan');
const findRules = () => wrapper.findByTestId('policy-rules');
const findEnabledText = () => wrapper.findByTestId('enabled-status-text');
const findNotEnabledText = () => wrapper.findByTestId('not-enabled-status-text');
const factory = ({ propsData } = {}) => {
wrapper = shallowMountExtended(ScanExecutionPolicy, {
propsData,
stubs: {
BasePolicy,
PolicyDrawerLayout,
},
});
};
......@@ -35,12 +28,9 @@ describe('ScanExecutionPolicy component', () => {
});
it.each`
component | finder | text
${'actions'} | ${findActions} | ${''}
${'rules'} | ${findRules} | ${''}
${'description'} | ${findDescription} | ${'This policy enforces pipeline configuration to have a job with DAST scan'}
${'latest scan'} | ${findLatestScan} | ${''}
${'enabled text'} | ${findEnabledText} | ${''}
component | finder | text
${'actions'} | ${findActions} | ${''}
${'rules'} | ${findRules} | ${''}
`('does render the policy $component', ({ finder, text }) => {
const component = finder();
expect(component.exists()).toBe(true);
......@@ -49,36 +39,4 @@ describe('ScanExecutionPolicy component', () => {
}
});
});
describe('not enabled policy', () => {
beforeEach(() => {
factory({ propsData: { policy: { ...mockScanExecutionPolicy, enabled: false } } });
});
it('does render the policy not enabled text', () => {
expect(findNotEnabledText().exists()).toBe(true);
});
});
describe('empty policy', () => {
beforeEach(() => {
factory({
propsData: {
policy: {
...mockScanExecutionPolicy,
latestScan: undefined,
yaml: mockSecretDetectionScanExecutionManifest,
},
},
});
});
it.each`
component | finder
${'description'} | ${findDescription}
${'latest scan'} | ${findLatestScan}
`('does render the policy $component', ({ finder }) => {
expect(finder().exists()).toBe(false);
});
});
});
import BasePolicy from 'ee/threat_monitoring/components/policy_drawer/base_policy.vue';
import PolicyDrawerLayout from 'ee/threat_monitoring/components/policy_drawer/policy_drawer_layout.vue';
import ScanResultPolicy from 'ee/threat_monitoring/components/policy_drawer/scan_result_policy.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mockScanResultPolicy } from '../../mocks/mock_data';
......@@ -6,14 +6,13 @@ import { mockScanResultPolicy } from '../../mocks/mock_data';
describe('ScanResultPolicy component', () => {
let wrapper;
const findDescription = () => wrapper.findByTestId('policy-description');
const findRules = () => wrapper.findByTestId('policy-rules');
const factory = ({ propsData } = {}) => {
wrapper = shallowMountExtended(ScanResultPolicy, {
propsData,
stubs: {
BasePolicy,
PolicyDrawerLayout,
},
});
};
......@@ -27,16 +26,8 @@ describe('ScanResultPolicy component', () => {
factory({ propsData: { policy: mockScanResultPolicy } });
});
it.each`
component | finder | text
${'rules'} | ${findRules} | ${''}
${'description'} | ${findDescription} | ${'This policy enforces critical vulnerability CS approvals'}
`('does render the policy $component', ({ finder, text }) => {
const component = finder();
expect(component.exists()).toBe(true);
if (text) {
expect(component.text()).toBe(text);
}
it('does render the policy rules', () => {
expect(findRules().exists()).toBe(true);
});
});
});
......@@ -32418,9 +32418,6 @@ msgstr ""
msgid "SecurityOrchestration|Invalid policy type"
msgstr ""
msgid "SecurityOrchestration|Latest scan"
msgstr ""
msgid "SecurityOrchestration|Latest scan run against %{agent}"
msgstr ""
......@@ -32430,6 +32427,9 @@ msgstr ""
msgid "SecurityOrchestration|New policy"
msgstr ""
msgid "SecurityOrchestration|No description"
msgstr ""
msgid "SecurityOrchestration|No rules defined - policy will not run."
msgstr ""
......@@ -32442,6 +32442,9 @@ msgstr ""
msgid "SecurityOrchestration|Policies"
msgstr ""
msgid "SecurityOrchestration|Policy Type"
msgstr ""
msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
msgstr ""
......@@ -32586,9 +32589,6 @@ msgstr ""
msgid "SecurityOrchestration|users with ids"
msgstr ""
msgid "SecurityOrchestration|view results"
msgstr ""
msgid "SecurityOrchestration|vulnerabilities"
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