Commit fc3c2872 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'refactor-training-vulner-det-page' into 'master'

Refactor vulnerability training component

See merge request gitlab-org/gitlab!78225
parents 09083bab 9f21f67f
......@@ -6,7 +6,6 @@ import convertReportType from 'ee/vue_shared/security_reports/store/utils/conver
import { SUPPORTING_MESSAGE_TYPES } from 'ee/vulnerabilities/constants';
import { s__, __ } from '~/locale';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import DetailItem from './detail_item.vue';
import VulnerabilityDetailSection from './vulnerability_detail_section.vue';
import VulnerabilityTraining from './vulnerability_training.vue';
......@@ -25,7 +24,6 @@ export default {
directives: {
SafeHtml: GlSafeHtmlDirective,
},
mixins: [glFeatureFlagsMixin()],
props: {
vulnerability: {
type: Object,
......@@ -152,9 +150,6 @@ export default {
hasResponses() {
return Boolean(this.hasResponse || this.hasRecordedResponse);
},
hasTraining() {
return this.glFeatures.secureVulnerabilityTraining && this.vulnerability.identifiers?.length;
},
},
methods: {
getHeadersAsCodeBlockLines(headers) {
......@@ -381,6 +376,6 @@ export default {
</ul>
</template>
<vulnerability-training v-if="hasTraining" :identifiers="vulnerability.identifiers" />
<vulnerability-training :identifiers="vulnerability.identifiers" />
</div>
</template>
<script>
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SUPPORTED_REFERENCE_SCHEMA } from '../constants';
export const i18n = {
......@@ -12,6 +13,7 @@ export const i18n = {
export default {
i18n,
mixins: [glFeatureFlagsMixin()],
props: {
identifiers: {
type: Array,
......@@ -19,20 +21,23 @@ export default {
},
},
computed: {
hasTraining() {
return this.glFeatures.secureVulnerabilityTraining && this.identifiers?.length;
},
isSupportedReferenceSchema() {
return this.referenceSchemas.some(
return this.referenceSchemas?.some(
(referenceSchema) => referenceSchema?.toLowerCase() === SUPPORTED_REFERENCE_SCHEMA.cwe,
);
},
referenceSchemas() {
return this.identifiers.map((identifier) => identifier?.externalType);
return this.identifiers?.map((identifier) => identifier?.externalType);
},
},
};
</script>
<template>
<div>
<div v-if="hasTraining">
<h3>{{ $options.i18n.trainingTitle }}</h3>
<p class="gl-text-gray-600!" data-testid="description">
{{ $options.i18n.trainingDescription }}
......
......@@ -15,26 +15,21 @@ describe('Vulnerability Details', () => {
reportType: 'Some report type',
description: 'vulnerability description',
descriptionHtml: 'vulnerability description <code>sample</code>',
identifiers: [],
};
const createWrapper = (vulnerabilityOverrides, { secureVulnerabilityTraining = true } = {}) => {
const createWrapper = (vulnerabilityOverrides) => {
const propsData = {
vulnerability: { ...vulnerability, ...vulnerabilityOverrides },
};
wrapper = mount(VulnerabilityDetails, {
propsData,
provide: {
glFeatures: {
secureVulnerabilityTraining,
},
},
});
};
const getById = (id) => wrapper.find(`[data-testid="${id}"]`);
const getAllById = (id) => wrapper.findAll(`[data-testid="${id}"]`);
const getText = (id) => getById(id).text();
const findVulnerabilityTraining = () => wrapper.findComponent(VulnerabilityTraining);
afterEach(() => {
wrapper.destroy();
......@@ -198,6 +193,14 @@ describe('Vulnerability Details', () => {
assetsData.forEach(checkIdentifier);
});
it('renders the vulnerabilityTraining component', () => {
const identifiers = [{ externalType: 'cwe' }, { externalType: 'cve' }];
createWrapper({ identifiers });
expect(wrapper.findComponent(VulnerabilityTraining).props()).toMatchObject({
identifiers,
});
});
describe('file link', () => {
const file = () => getById('file').find(GlLink);
......@@ -406,26 +409,4 @@ describe('Vulnerability Details', () => {
expect(getSectionData('recorded-response')).toEqual(expectedData);
});
});
describe('vulnerability training', () => {
it('renders the component', () => {
const identifiers = [{ externalType: 'cwe' }, { externalType: 'cve' }];
createWrapper({ identifiers });
expect(wrapper.findComponent(VulnerabilityTraining).props()).toMatchObject({
identifiers,
});
});
it('does not render the component when there are no identifiers', () => {
createWrapper();
expect(findVulnerabilityTraining().exists()).toBe(false);
});
});
describe('when secureVulnerabilityTraining feature flag is disabled', () => {
it('does not render the VulnerabilityTraining component', () => {
createWrapper(undefined, { secureVulnerabilityTraining: false });
expect(findVulnerabilityTraining().exists()).toBe(false);
});
});
});
......@@ -11,12 +11,17 @@ const defaultProps = {
describe('VulnerabilityTraining component', () => {
let wrapper;
const createComponent = (props = {}) => {
const createComponent = (props = {}, { secureVulnerabilityTraining = true } = {}) => {
wrapper = shallowMountExtended(VulnerabilityTraining, {
propsData: {
...defaultProps,
...props,
},
provide: {
glFeatures: {
secureVulnerabilityTraining,
},
},
});
};
......@@ -40,6 +45,11 @@ describe('VulnerabilityTraining component', () => {
it('displays the description', () => {
expect(findDescription().text()).toBe(i18n.trainingDescription);
});
it('does not render component when there are no identifiers', () => {
createComponent({ identifiers: [] });
expect(wrapper.html()).toBeFalsy();
});
});
describe('training availability message', () => {
......@@ -58,4 +68,11 @@ describe('VulnerabilityTraining component', () => {
expect(findUnavailableMessage().exists()).toBe(exists);
});
});
describe('when secureVulnerabilityTraining feature flag is disabled', () => {
it('does not render the VulnerabilityTraining component', () => {
createComponent({}, { secureVulnerabilityTraining: false });
expect(wrapper.html()).toBeFalsy();
});
});
});
......@@ -13,4 +13,5 @@ export const mockVulnerability = {
project: {
full_path: '/project_full_path',
},
identifiers: [],
};
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