Commit c3979d9f authored by Alexander Turinske's avatar Alexander Turinske

Change scan_execution template to be more readable

- abstract out logic from template to computedProperties
- update humanizeActions method to use abstracted out shared
  logic
- update tests
- move
  ee/spec/.../policy_editor/scan_execution_policy/lib/utils_spec.js
  to ee/spec/.../policy_editor/utils_spec.js to match
  the file it is testing ee/.../policy_editor/utils.js
parent 0b5a0701
......@@ -43,6 +43,21 @@ export default {
return null;
}
},
hasOnlyOneAction() {
return this.humanizedActions.length === 1;
},
hasMultipleActions() {
return this.humanizedActions.length > 1;
},
firstAction() {
return this.hasOnlyOneAction ? this.humanizedActions[0] : '';
},
allButLastActions() {
return this.hasMultipleActions ? this.humanizedActions.slice(0, -1).join(', ') : '';
},
lastAction() {
return this.hasMultipleActions ? [...this.humanizedActions].pop() : '';
},
},
};
</script>
......@@ -58,20 +73,17 @@ export default {
<policy-info-row data-testid="policy-summary" :label="$options.i18n.summary">
<p>
<template v-if="!humanizedActions.length">{{ $options.i18n.noActionMessage }}</template>
<gl-sprintf
v-else-if="humanizedActions.length === 1"
:message="$options.i18n.singleActionMessage"
>
<gl-sprintf v-else-if="hasOnlyOneAction" :message="$options.i18n.singleActionMessage">
<template #action>
<strong>{{ humanizedActions[0] }}</strong>
<strong>{{ firstAction }}</strong>
</template>
</gl-sprintf>
<gl-sprintf v-else :message="$options.i18n.multipleActionMessage">
<template #actions>
<strong>{{ humanizedActions.slice(0, -1).join(', ') }}</strong>
<strong>{{ allButLastActions }}</strong>
</template>
<template #lastAction>
<strong>{{ humanizedActions[humanizedActions.length - 1] }}</strong>
<strong>{{ lastAction }}</strong>
</template>
</gl-sprintf>
</p>
......
import cronstrue from 'cronstrue/i18n';
import { convertToTitleCase, humanize } from '~/lib/utils/text_utility';
import { getPreferredLocales, sprintf, s__, n__ } from '~/locale';
import { NO_RULE_MESSAGE } from '../../constants';
import { convertScannersToTitleCase } from '../../utils';
/**
* Create a human-readable list of strings, adding the necessary punctuation and conjunctions
......@@ -65,7 +65,8 @@ const HUMANIZE_RULES_METHODS = {
* @returns {Array}
*/
export const humanizeActions = (actions) => {
return [...new Set(actions.map((a) => convertToTitleCase(humanize(a.scan))))];
const scanners = actions.map((a) => a.scan);
return [...new Set(convertScannersToTitleCase(scanners))];
};
/**
......
import { sprintf, s__, n__ } from '~/locale';
import { convertToTitleCase, humanize } from '~/lib/utils/text_utility';
import { NO_RULE_MESSAGE } from '../../constants';
import { convertScannersToTitleCase } from '../../utils';
/**
* Simple logic for indefinite articles which does not include the exceptions
......@@ -172,7 +172,7 @@ const humanizeRule = (rule) => {
),
{
scanners: humanizeItems({
items: rule.scanners.map((scanner) => convertToTitleCase(humanize(scanner))),
items: convertScannersToTitleCase(rule.scanners),
singular: s__('SecurityOrchestration|scanner finds'),
plural: s__('SecurityOrchestration|scanners find'),
}),
......
import { convertToTitleCase, humanize } from '~/lib/utils/text_utility';
import createPolicyProject from 'ee/threat_monitoring/graphql/mutations/create_policy_project.mutation.graphql';
import createScanExecutionPolicy from 'ee/threat_monitoring/graphql/mutations/create_scan_execution_policy.mutation.graphql';
import { gqClient } from 'ee/threat_monitoring/utils';
......@@ -123,3 +124,14 @@ export const assignSecurityPolicyProject = async (projectPath) => {
return { ...project, branch: project?.branch?.rootRef, errors };
};
/**
* Converts scanner strings to title case
* @param {Array} scanners (e.g. 'container_scanning', `dast`, etcetera)
* @returns {Array} (e.g. 'Container Scanning', `Dast`, etcetera)
*/
export const convertScannersToTitleCase = (scanners) => {
if (!Array.isArray(scanners)) return [];
return scanners.map((scanner) => convertToTitleCase(humanize(scanner)));
};
......@@ -4,24 +4,36 @@ exports[`ScanExecutionPolicy component default policy renders the correct policy
<div
data-testid="policy-summary"
>
<policy-info-row-stub
<div
data-testid="policy-summary"
label="Summary"
>
<p>
<gl-sprintf-stub
message="Runs a %{action} scan"
/>
</p>
<h5
class="gl-mt-6"
data-testid="label"
>
Summary
</h5>
<ul>
<li>
<p
data-testid="content"
>
<p>
Runs a
<strong>
Dast
</strong>
scan
</p>
<ul>
<li>
Scan to be performed on every pipeline on the main branch
</li>
</ul>
</policy-info-row-stub>
</li>
</ul>
</p>
</div>
</div>
`;
......@@ -29,24 +41,40 @@ exports[`ScanExecutionPolicy component multiple action policy renders the correc
<div
data-testid="policy-summary"
>
<policy-info-row-stub
<div
data-testid="policy-summary"
label="Summary"
>
<p>
<gl-sprintf-stub
message="Runs %{actions} and %{lastAction} scans"
/>
</p>
<h5
class="gl-mt-6"
data-testid="label"
>
Summary
</h5>
<ul>
<li>
<p
data-testid="content"
>
<p>
Runs
<strong>
Container Scanning, Secret Detection
</strong>
and
<strong>
Sast
</strong>
scans
</p>
<ul>
<li>
Scan to be performed on every pipeline on the main branch
</li>
</ul>
</policy-info-row-stub>
</li>
</ul>
</p>
</div>
</div>
`;
......@@ -54,21 +82,31 @@ exports[`ScanExecutionPolicy component no action policy renders the correct poli
<div
data-testid="policy-summary"
>
<policy-info-row-stub
<div
data-testid="policy-summary"
label="Summary"
>
<p>
No actions defined - policy will not run.
</p>
<h5
class="gl-mt-6"
data-testid="label"
>
Summary
</h5>
<ul>
<li>
<p
data-testid="content"
>
<p>
No actions defined - policy will not run.
</p>
<ul>
<li>
Scan to be performed on every pipeline on the main branch
</li>
</ul>
</policy-info-row-stub>
</li>
</ul>
</p>
</div>
</div>
`;
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 { mountExtended } from 'helpers/vue_test_utils_helper';
import {
mockScanExecutionPolicy,
mockScanExecutionManifestNoActions,
......@@ -10,14 +9,11 @@ import {
describe('ScanExecutionPolicy component', () => {
let wrapper;
const findSummary = () => wrapper.find('[data-testid="policy-summary"]');
const findSummary = () => wrapper.findByTestId('policy-summary');
const factory = ({ propsData } = {}) => {
wrapper = shallowMountExtended(ScanExecutionPolicy, {
wrapper = mountExtended(ScanExecutionPolicy, {
propsData,
stubs: {
PolicyDrawerLayout,
},
});
};
......
import {
assignSecurityPolicyProject,
modifyPolicy,
convertScannersToTitleCase,
} from 'ee/threat_monitoring/components/policy_editor/utils';
import { DEFAULT_ASSIGNED_POLICY_PROJECT } from 'ee/threat_monitoring/constants';
import createPolicyProject from 'ee/threat_monitoring/graphql/mutations/create_policy_project.mutation.graphql';
......@@ -102,3 +103,14 @@ describe('modifyPolicy', () => {
await expect(modifyPolicy(createSavePolicyInput())).rejects.toThrowError(error);
});
});
describe('convertScannersToTitleCase', () => {
it.each`
title | input | output
${'returns empty array for a non-array'} | ${{}} | ${[]}
${'returns empty array for an empty array'} | ${[]} | ${[]}
${'returns converted array'} | ${['dast', 'container_scanning', 'secret_detection']} | ${['Dast', 'Container Scanning', 'Secret Detection']}
`('$title', ({ input, output }) => {
expect(convertScannersToTitleCase(input)).toStrictEqual(output);
});
});
......@@ -85,6 +85,7 @@ rules:
actions:
- scan: container_scanning
- scan: secret_detection
- scan: sast
`;
export const mockDastScanExecutionObject = {
......
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