Commit a51cb94c authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '211870-one-issue-per-vulnerability' into 'master'

Add conditional render of create issue button

Closes #211870

See merge request gitlab-org/gitlab!28957
parents 264cc98c 8a6591da
...@@ -47,6 +47,7 @@ function createHeaderApp() { ...@@ -47,6 +47,7 @@ function createHeaderApp() {
const el = document.getElementById('js-vulnerability-management-app'); const el = document.getElementById('js-vulnerability-management-app');
const initialVulnerability = JSON.parse(el.dataset.vulnerabilityJson); const initialVulnerability = JSON.parse(el.dataset.vulnerabilityJson);
const pipeline = JSON.parse(el.dataset.pipelineJson); const pipeline = JSON.parse(el.dataset.pipelineJson);
const finding = JSON.parse(el.dataset.findingJson);
const { projectFingerprint, createIssueUrl } = el.dataset; const { projectFingerprint, createIssueUrl } = el.dataset;
...@@ -57,6 +58,7 @@ function createHeaderApp() { ...@@ -57,6 +58,7 @@ function createHeaderApp() {
h(HeaderApp, { h(HeaderApp, {
props: { props: {
initialVulnerability, initialVulnerability,
finding,
pipeline, pipeline,
projectFingerprint, projectFingerprint,
createIssueUrl, createIssueUrl,
......
...@@ -26,6 +26,10 @@ export default { ...@@ -26,6 +26,10 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
finding: {
type: Object,
required: true,
},
pipeline: { pipeline: {
type: Object, type: Object,
required: true, required: true,
...@@ -51,6 +55,9 @@ export default { ...@@ -51,6 +55,9 @@ export default {
}, },
computed: { computed: {
hasIssue() {
return Boolean(this.finding.issue_feedback?.issue_iid);
},
statusBoxStyle() { statusBoxStyle() {
// Get the badge variant based on the vulnerability state, defaulting to 'expired'. // Get the badge variant based on the vulnerability state, defaulting to 'expired'.
return VULNERABILITY_STATE_OBJECTS[this.vulnerability.state]?.statusBoxStyle || 'expired'; return VULNERABILITY_STATE_OBJECTS[this.vulnerability.state]?.statusBoxStyle || 'expired';
...@@ -172,6 +179,7 @@ export default { ...@@ -172,6 +179,7 @@ export default {
@change="changeVulnerabilityState" @change="changeVulnerabilityState"
/> />
<gl-deprecated-button <gl-deprecated-button
v-if="!hasIssue"
ref="create-issue-btn" ref="create-issue-btn"
class="ml-2" class="ml-2"
variant="success" variant="success"
......
...@@ -21,6 +21,9 @@ export default { ...@@ -21,6 +21,9 @@ export default {
}, },
}, },
computed: { computed: {
hasIssue() {
return Boolean(this.feedback?.issue_iid);
},
hasSolution() { hasSolution() {
return this.solutionInfo.solution || this.solutionInfo.hasRemediation; return this.solutionInfo.solution || this.solutionInfo.hasRemediation;
}, },
...@@ -35,7 +38,7 @@ export default { ...@@ -35,7 +38,7 @@ export default {
<li> <li>
<hr /> <hr />
</li> </li>
<li v-if="feedback" class="note card my-4 border-bottom"> <li v-if="hasIssue" class="note card my-4 border-bottom">
<div class="card-body"> <div class="card-body">
<issue-note :feedback="feedback" :project="project" /> <issue-note :feedback="feedback" :project="project" />
</div> </div>
......
...@@ -26,6 +26,17 @@ describe('Vulnerability management app', () => { ...@@ -26,6 +26,17 @@ describe('Vulnerability management app', () => {
state: 'detected', state: 'detected',
}; };
const defaultFinding = {
description: 'description',
identifiers: 'identifiers',
links: 'links',
location: 'location',
name: 'name',
issue_feedback: {
issue_iid: 12,
},
};
const dataset = { const dataset = {
createIssueUrl: 'create_issue_url', createIssueUrl: 'create_issue_url',
projectFingerprint: 'abc123', projectFingerprint: 'abc123',
...@@ -49,11 +60,12 @@ describe('Vulnerability management app', () => { ...@@ -49,11 +60,12 @@ describe('Vulnerability management app', () => {
const findResolutionAlert = () => wrapper.find(ResolutionAlert); const findResolutionAlert = () => wrapper.find(ResolutionAlert);
const findStatusDescription = () => wrapper.find(StatusDescription); const findStatusDescription = () => wrapper.find(StatusDescription);
const createWrapper = (vulnerability = {}) => { const createWrapper = (vulnerability = {}, finding = {}) => {
wrapper = shallowMount(App, { wrapper = shallowMount(App, {
propsData: { propsData: {
...dataset, ...dataset,
initialVulnerability: { ...defaultVulnerability, ...vulnerability }, initialVulnerability: { ...defaultVulnerability, ...vulnerability },
finding,
}, },
}); });
}; };
...@@ -98,10 +110,15 @@ describe('Vulnerability management app', () => { ...@@ -98,10 +110,15 @@ describe('Vulnerability management app', () => {
describe('create issue button', () => { describe('create issue button', () => {
beforeEach(createWrapper); beforeEach(createWrapper);
it('renders properly', () => { it('does display if there is not an issue already created', () => {
expect(findCreateIssueButton().exists()).toBe(true); expect(findCreateIssueButton().exists()).toBe(true);
}); });
it('does not display if there is an issue already created', () => {
createWrapper({}, defaultFinding);
expect(findCreateIssueButton().exists()).toBe(false);
});
it('calls create issue endpoint on click and redirects to new issue', () => { it('calls create issue endpoint on click and redirects to new issue', () => {
const issueUrl = '/group/project/issues/123'; const issueUrl = '/group/project/issues/123';
const spy = jest.spyOn(urlUtility, 'redirectTo'); const spy = jest.spyOn(urlUtility, 'redirectTo');
......
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