Move translations mapping to a helper

This extracts the code that maps scanner names to their translations
into a dedicated helper.
parent 75fd592a
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
export const augmentFeatures = (securityFeatures, complianceFeatures, features = []) => {
const featuresByType = features.reduce((acc, feature) => {
......@@ -24,3 +25,13 @@ export const augmentFeatures = (securityFeatures, complianceFeatures, features =
augmentedComplianceFeatures: complianceFeatures.map((feature) => augmentFeature(feature)),
};
};
/**
* Converts a list of security scanner IDs (such as SAST_IAC) into a list of their translated
* names defined in the SCANNER_NAMES_MAP constant (eg. IaC Scanning).
*
* @param {String[]} scannerNames
* @returns {String[]}
*/
export const translateScannerNames = (scannerNames = []) =>
scannerNames.map((scannerName) => SCANNER_NAMES_MAP[scannerName] || scannerName);
......@@ -9,7 +9,7 @@ import { preparePageInfo } from 'ee/security_dashboard/helpers';
import { VULNERABILITIES_PER_PAGE } from 'ee/security_dashboard/store/constants';
import { parseBoolean } from '~/lib/utils/common_utils';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
import { translateScannerNames } from '~/security_configuration/utils';
import VulnerabilityList from '../shared/vulnerability_list.vue';
import SecurityScannerAlert from './security_scanner_alert.vue';
......@@ -92,12 +92,11 @@ export default {
},
update({ project = {} }) {
const { available = [], enabled = [], pipelineRun = [] } = project?.securityScanners || {};
const translateScannerName = (scannerName) => SCANNER_NAMES_MAP[scannerName] || scannerName;
return {
available: available.map(translateScannerName),
enabled: enabled.map(translateScannerName),
pipelineRun: pipelineRun.map(translateScannerName),
available: translateScannerNames(available),
enabled: translateScannerNames(enabled),
pipelineRun: translateScannerNames(pipelineRun),
};
},
},
......
......@@ -4,7 +4,7 @@ import { difference } from 'lodash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
import { translateScannerNames } from '~/security_configuration/utils';
import ReportNotConfiguredProject from '../shared/empty_states/report_not_configured_project.vue';
import VulnerabilityReportTabs from '../shared/vulnerability_report/vulnerability_report_tabs.vue';
import projectVulnerabilitiesQuery from '../../graphql/queries/project_vulnerabilities.query.graphql';
......@@ -40,12 +40,11 @@ export default {
},
update({ project = {} }) {
const { available = [], enabled = [], pipelineRun = [] } = project?.securityScanners || {};
const translateScannerName = (scannerName) => SCANNER_NAMES_MAP[scannerName] || scannerName;
return {
available: available.map(translateScannerName),
enabled: enabled.map(translateScannerName),
pipelineRun: pipelineRun.map(translateScannerName),
available: translateScannerNames(available),
enabled: translateScannerNames(enabled),
pipelineRun: translateScannerNames(pipelineRun),
};
},
},
......
import { augmentFeatures } from '~/security_configuration/utils';
const mockSecurityFeatures = [
{
name: 'SAST',
type: 'SAST',
},
];
const mockComplianceFeatures = [
{
name: 'LICENSE_COMPLIANCE',
type: 'LICENSE_COMPLIANCE',
},
];
const mockFeaturesWithSecondary = [
{
name: 'DAST',
type: 'DAST',
secondary: {
type: 'DAST PROFILES',
name: 'DAST PROFILES',
import { augmentFeatures, translateScannerNames } from '~/security_configuration/utils';
import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
describe('augmentFeatures', () => {
const mockSecurityFeatures = [
{
name: 'SAST',
type: 'SAST',
},
},
];
const mockInvalidCustomFeature = [
{
foo: 'bar',
},
];
const mockValidCustomFeature = [
{
name: 'SAST',
type: 'SAST',
customField: 'customvalue',
},
];
const mockValidCustomFeatureSnakeCase = [
{
name: 'SAST',
type: 'SAST',
custom_field: 'customvalue',
},
];
const expectedOutputDefault = {
augmentedSecurityFeatures: mockSecurityFeatures,
augmentedComplianceFeatures: mockComplianceFeatures,
};
const expectedOutputSecondary = {
augmentedSecurityFeatures: mockSecurityFeatures,
augmentedComplianceFeatures: mockFeaturesWithSecondary,
};
const expectedOutputCustomFeature = {
augmentedSecurityFeatures: mockValidCustomFeature,
augmentedComplianceFeatures: mockComplianceFeatures,
};
describe('returns an object with augmentedSecurityFeatures and augmentedComplianceFeatures when', () => {
it('given an empty array', () => {
expect(augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, [])).toEqual(
expectedOutputDefault,
);
];
const mockComplianceFeatures = [
{
name: 'LICENSE_COMPLIANCE',
type: 'LICENSE_COMPLIANCE',
},
];
const mockFeaturesWithSecondary = [
{
name: 'DAST',
type: 'DAST',
secondary: {
type: 'DAST PROFILES',
name: 'DAST PROFILES',
},
},
];
const mockInvalidCustomFeature = [
{
foo: 'bar',
},
];
const mockValidCustomFeature = [
{
name: 'SAST',
type: 'SAST',
customField: 'customvalue',
},
];
const mockValidCustomFeatureSnakeCase = [
{
name: 'SAST',
type: 'SAST',
custom_field: 'customvalue',
},
];
const expectedOutputDefault = {
augmentedSecurityFeatures: mockSecurityFeatures,
augmentedComplianceFeatures: mockComplianceFeatures,
};
const expectedOutputSecondary = {
augmentedSecurityFeatures: mockSecurityFeatures,
augmentedComplianceFeatures: mockFeaturesWithSecondary,
};
const expectedOutputCustomFeature = {
augmentedSecurityFeatures: mockValidCustomFeature,
augmentedComplianceFeatures: mockComplianceFeatures,
};
describe('returns an object with augmentedSecurityFeatures and augmentedComplianceFeatures when', () => {
it('given an empty array', () => {
expect(augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, [])).toEqual(
expectedOutputDefault,
);
});
it('given an invalid populated array', () => {
expect(
augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockInvalidCustomFeature),
).toEqual(expectedOutputDefault);
});
it('features have secondary key', () => {
expect(augmentFeatures(mockSecurityFeatures, mockFeaturesWithSecondary, [])).toEqual(
expectedOutputSecondary,
);
});
it('given a valid populated array', () => {
expect(
augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockValidCustomFeature),
).toEqual(expectedOutputCustomFeature);
});
});
it('given an invalid populated array', () => {
expect(
augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockInvalidCustomFeature),
).toEqual(expectedOutputDefault);
describe('returns an object with camelcased keys', () => {
it('given a customfeature in snakecase', () => {
expect(
augmentFeatures(
mockSecurityFeatures,
mockComplianceFeatures,
mockValidCustomFeatureSnakeCase,
),
).toEqual(expectedOutputCustomFeature);
});
});
});
it('features have secondary key', () => {
expect(augmentFeatures(mockSecurityFeatures, mockFeaturesWithSecondary, [])).toEqual(
expectedOutputSecondary,
);
describe('translateScannerNames', () => {
it.each(['', undefined, null, 1, 'UNKNOWN_SCANNER_KEY'])('returns %p as is', (key) => {
expect(translateScannerNames([key])).toEqual([key]);
});
it('given a valid populated array', () => {
expect(
augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockValidCustomFeature),
).toEqual(expectedOutputCustomFeature);
it('returns an empty array if no input is provided', () => {
expect(translateScannerNames([])).toEqual([]);
});
});
describe('returns an object with camelcased keys', () => {
it('given a customfeature in snakecase', () => {
expect(
augmentFeatures(
mockSecurityFeatures,
mockComplianceFeatures,
mockValidCustomFeatureSnakeCase,
),
).toEqual(expectedOutputCustomFeature);
it('returns translated scanner names', () => {
expect(translateScannerNames(Object.keys(SCANNER_NAMES_MAP))).toEqual(
Object.values(SCANNER_NAMES_MAP),
);
});
});
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