Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
369d3ae0
Commit
369d3ae0
authored
Oct 07, 2020
by
Savas Vedova
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Redesign solution card in vulnerability details
- Add changelog
parent
7a0a24ba
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
231 additions
and
109 deletions
+231
-109
ee/app/assets/javascripts/vue_shared/security_reports/components/modal.vue
...ascripts/vue_shared/security_reports/components/modal.vue
+1
-1
ee/app/assets/javascripts/vue_shared/security_reports/components/solution_card.vue
.../vue_shared/security_reports/components/solution_card.vue
+11
-32
ee/app/assets/javascripts/vue_shared/security_reports/components/solution_card_vuex.vue
...shared/security_reports/components/solution_card_vuex.vue
+70
-0
ee/app/assets/javascripts/vulnerabilities/components/footer.vue
.../assets/javascripts/vulnerabilities/components/footer.vue
+0
-1
ee/changelogs/unreleased/218485-update-solution-part.yml
ee/changelogs/unreleased/218485-update-solution-part.yml
+5
-0
ee/spec/frontend/vue_shared/security_reports/components/modal_spec.js
...tend/vue_shared/security_reports/components/modal_spec.js
+1
-1
ee/spec/frontend/vue_shared/security_reports/components/solution_card_spec.js
..._shared/security_reports/components/solution_card_spec.js
+39
-73
ee/spec/frontend/vue_shared/security_reports/components/solution_card_vuex_spec.js
...ed/security_reports/components/solution_card_vuex_spec.js
+104
-0
ee/spec/frontend/vulnerabilities/footer_spec.js
ee/spec/frontend/vulnerabilities/footer_spec.js
+0
-1
No files found.
ee/app/assets/javascripts/vue_shared/security_reports/components/modal.vue
View file @
369d3ae0
...
...
@@ -5,7 +5,7 @@ import DismissalCommentModalFooter from 'ee/vue_shared/security_reports/componen
import
IssueNote
from
'
ee/vue_shared/security_reports/components/issue_note.vue
'
;
import
MergeRequestNote
from
'
ee/vue_shared/security_reports/components/merge_request_note.vue
'
;
import
ModalFooter
from
'
ee/vue_shared/security_reports/components/modal_footer.vue
'
;
import
SolutionCard
from
'
ee/vue_shared/security_reports/components/solution_card.vue
'
;
import
SolutionCard
from
'
ee/vue_shared/security_reports/components/solution_card
_vuex
.vue
'
;
import
VulnerabilityDetails
from
'
ee/vue_shared/security_reports/components/vulnerability_details.vue
'
;
import
DeprecatedModal2
from
'
~/vue_shared/components/deprecated_modal_2.vue
'
;
import
{
__
}
from
'
~/locale
'
;
...
...
ee/app/assets/javascripts/vue_shared/security_reports/components/solution_card.vue
View file @
369d3ae0
<
script
>
import
{
GlIcon
}
from
'
@gitlab/ui
'
;
export
default
{
name
:
'
SolutionCard
'
,
components
:
{
GlIcon
},
props
:
{
solution
:
{
type
:
String
,
...
...
@@ -25,11 +21,6 @@ export default {
default
:
false
,
required
:
false
,
},
isStandaloneVulnerability
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
solutionText
()
{
...
...
@@ -42,29 +33,17 @@ export default {
};
</
script
>
<
template
>
<div
class=
"card my-4"
>
<div
v-if=
"solutionText"
class=
"card-body d-flex align-items-center"
>
<div
class=
"col-auto d-flex align-items-center pl-0"
:class=
"
{ 'col-md-2': !isStandaloneVulnerability }"
>
<div
class=
"circle-icon-container pr-3"
aria-hidden=
"true"
><gl-icon
name=
"bulb"
/></div>
<strong
class=
"text-right flex-grow-1"
>
{{
s__
(
'
ciReport|Solution
'
)
}}
:
</strong>
</div>
<span
class=
"flex-shrink-1 pl-0"
:class=
"
{ 'col-md-10': !isStandaloneVulnerability }">
{{
solutionText
}}
</span>
<div
v-if=
"solutionText"
class=
"md my-4"
>
<h3>
{{
s__
(
'
ciReport|Solution
'
)
}}
</h3>
<div
ref=
"solution-text"
>
{{
solutionText
}}
<template
v-if=
"showCreateMergeRequestMsg"
>
{{
s__
(
'
ciReport|Create a merge request to implement this solution, or download and apply the patch manually.
'
,
)
}}
</
template
>
</div>
<template
v-if=
"showCreateMergeRequestMsg"
>
<div
class=
"card-footer"
:class=
"
{ 'border-0': !solutionText }">
<em
class=
"text-secondary"
>
{{
s__
(
'
ciReport|Create a merge request to implement this solution, or download and apply the patch manually.
'
,
)
}}
</em>
</div>
</
template
>
</div>
</template>
ee/app/assets/javascripts/vue_shared/security_reports/components/solution_card_vuex.vue
0 → 100644
View file @
369d3ae0
<
script
>
import
{
GlIcon
}
from
'
@gitlab/ui
'
;
export
default
{
name
:
'
SolutionCard
'
,
components
:
{
GlIcon
},
props
:
{
solution
:
{
type
:
String
,
default
:
''
,
required
:
false
,
},
remediation
:
{
type
:
Object
,
default
:
null
,
required
:
false
,
},
hasDownload
:
{
type
:
Boolean
,
default
:
false
,
required
:
false
,
},
hasMr
:
{
type
:
Boolean
,
default
:
false
,
required
:
false
,
},
isStandaloneVulnerability
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
solutionText
()
{
return
(
this
.
remediation
&&
this
.
remediation
.
summary
)
||
this
.
solution
;
},
showCreateMergeRequestMsg
()
{
return
!
this
.
hasMr
&&
Boolean
(
this
.
remediation
)
&&
this
.
hasDownload
;
},
},
};
</
script
>
<
template
>
<div
class=
"card my-4"
>
<div
v-if=
"solutionText"
class=
"card-body d-flex align-items-center"
>
<div
class=
"col-auto d-flex align-items-center pl-0"
:class=
"
{ 'col-md-2': !isStandaloneVulnerability }"
>
<div
class=
"circle-icon-container pr-3"
aria-hidden=
"true"
><gl-icon
name=
"bulb"
/></div>
<strong
class=
"text-right flex-grow-1"
>
{{
s__
(
'
ciReport|Solution
'
)
}}
:
</strong>
</div>
<span
class=
"flex-shrink-1 pl-0"
:class=
"
{ 'col-md-10': !isStandaloneVulnerability }">
{{
solutionText
}}
</span>
</div>
<template
v-if=
"showCreateMergeRequestMsg"
>
<div
class=
"card-footer"
:class=
"
{ 'border-0': !solutionText }">
<em
class=
"text-secondary"
>
{{
s__
(
'
ciReport|Create a merge request to implement this solution, or download and apply the patch manually.
'
,
)
}}
</em>
</div>
</
template
>
</div>
</template>
ee/app/assets/javascripts/vulnerabilities/components/footer.vue
View file @
369d3ae0
...
...
@@ -67,7 +67,6 @@ export default {
remediation
,
hasDownload
,
hasMr
,
isStandaloneVulnerability
:
true
,
};
},
hasSolution
()
{
...
...
ee/changelogs/unreleased/218485-update-solution-part.yml
0 → 100644
View file @
369d3ae0
---
title
:
Redesign solution card in vulnerability details page
merge_request
:
44408
author
:
type
:
other
ee/spec/frontend/vue_shared/security_reports/components/modal_spec.js
View file @
369d3ae0
import
Vue
from
'
vue
'
;
import
component
from
'
ee/vue_shared/security_reports/components/modal.vue
'
;
import
createState
from
'
ee/vue_shared/security_reports/store/state
'
;
import
SolutionCard
from
'
ee/vue_shared/security_reports/components/solution_card.vue
'
;
import
SolutionCard
from
'
ee/vue_shared/security_reports/components/solution_card
_vuex
.vue
'
;
import
IssueNote
from
'
ee/vue_shared/security_reports/components/issue_note.vue
'
;
import
MergeRequestNote
from
'
ee/vue_shared/security_reports/components/merge_request_note.vue
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
...
...
ee/spec/frontend/vue_shared/security_reports/components/solution_card_spec.js
View file @
369d3ae0
import
Vue
from
'
vue
'
;
import
component
from
'
ee/vue_shared/security_reports/components/solution_card.vue
'
;
import
{
trimText
}
from
'
helpers/text_helper
'
;
import
SolutionCard
from
'
ee/vue_shared/security_reports/components/solution_card.vue
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
s__
}
from
'
~/locale
'
;
describe
(
'
Solution Card
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
const
solution
=
'
Upgrade to XYZ
'
;
const
remediation
=
{
summary
:
'
Update to 123
'
,
fixes
:
[],
diff
:
'
SGVsbG8gR2l0TGFi
'
};
let
wrapper
;
const
findSolutionText
=
()
=>
wrapper
.
find
({
ref
:
'
solution-text
'
});
const
findSolutionTitle
=
()
=>
wrapper
.
find
(
'
h3
'
);
const
createComponent
=
({
propsData
}
=
{})
=>
{
wrapper
=
shallowMount
(
SolutionCard
,
{
propsData
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
computed properties
'
,
()
=>
{
describe
(
'
solutionText
'
,
()
=>
{
it
(
'
takes the value of solution
'
,
()
=>
{
const
propsData
=
{
solution
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
expect
(
wrapper
.
vm
.
solutionText
).
toEqual
(
solution
);
});
it
(
'
takes the summary from a remediation
'
,
()
=>
{
const
propsData
=
{
remediation
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
expect
(
wrapper
.
vm
.
solutionText
).
toEqual
(
remediation
.
summary
);
});
describe
(
'
with solution
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
propsData
:
{
solution
}
});
});
it
(
'
takes the summary from a remediation, if both are defined
'
,
()
=>
{
const
propsData
=
{
remediation
,
solution
}
;
wrapper
=
shallowMount
(
Component
,
{
propsData
});
it
(
'
renders the solution title
'
,
()
=>
{
expect
(
findSolutionTitle
().
text
()).
toBe
(
'
Solution
'
)
;
});
expect
(
wrapper
.
vm
.
solutionText
).
toEqual
(
remediation
.
summary
);
}
);
it
(
'
renders the solution text
'
,
()
=>
{
expect
(
findSolutionText
().
text
()).
toBe
(
solution
);
});
});
describe
(
'
rendering
'
,
()
=>
{
describe
(
'
with solution
'
,
()
=>
{
beforeEach
(()
=>
{
const
propsData
=
{
solution
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
});
it
(
'
renders the solution text and label
'
,
()
=>
{
expect
(
trimText
(
wrapper
.
find
(
'
.card-body
'
).
text
())).
toContain
(
`Solution:
${
solution
}
`
);
});
it
(
'
does not render the card footer
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
exists
()).
toBe
(
false
);
});
describe
(
'
with remediation
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
propsData
:
{
remediation
,
hasRemediation
:
true
}
});
});
it
(
'
does not render the download link
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
a
'
).
exists
()).
toBe
(
false
);
});
it
(
'
renders the solution text
'
,
()
=>
{
expect
(
findSolutionText
().
text
()).
toBe
(
remediation
.
summary
);
});
describe
(
'
with
remediation
'
,
()
=>
{
describe
(
'
with
download patch
'
,
()
=>
{
beforeEach
(()
=>
{
const
propsData
=
{
remediation
,
hasRemediation
:
true
}
;
wrapper
=
shallowMount
(
Component
,
{
propsData
}
);
wrapper
.
setProps
({
hasDownload
:
true
})
;
return
wrapper
.
vm
.
$nextTick
(
);
});
it
(
'
renders the solution text and label
'
,
()
=>
{
expect
(
trimText
(
wrapper
.
find
(
'
.card-body
'
).
text
())).
toContain
(
`Solution:
${
remediation
.
summary
}
`
,
it
(
'
renders the create a merge request to implement this solution message
'
,
()
=>
{
expect
(
findSolutionText
().
text
()).
toContain
(
s__
(
'
ciReport|Create a merge request to implement this solution, or download and apply the patch manually.
'
,
),
);
});
});
describe
(
'
with download patch
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
.
setProps
({
hasDownload
:
true
});
return
wrapper
.
vm
.
$nextTick
();
});
it
(
'
does not render the download and apply solution message when there is a file download and a merge request already exists
'
,
()
=>
{
wrapper
.
setProps
({
hasMr
:
true
});
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
exists
()).
toBe
(
false
);
});
});
it
(
'
renders the create a merge request to implement this solution message
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
text
()).
toContain
(
s__
(
'
ciReport|Create a merge request to implement this solution, or download and apply the patch manually.
'
,
),
);
});
});
describe
(
'
without download patch
'
,
()
=>
{
it
(
'
does not render the card footer
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
exists
()).
toBe
(
false
);
});
describe
(
'
without download patch
'
,
()
=>
{
it
(
'
does not render the create a merge request to implement this solution message
'
,
()
=>
{
expect
(
findSolutionText
().
text
()).
not
.
toContain
(
s__
(
'
ciReport|Create a merge request to implement this solution, or download and apply the patch manually.
'
,
),
);
});
});
});
...
...
ee/spec/frontend/vue_shared/security_reports/components/solution_card_vuex_spec.js
0 → 100644
View file @
369d3ae0
import
Vue
from
'
vue
'
;
import
component
from
'
ee/vue_shared/security_reports/components/solution_card_vuex.vue
'
;
import
{
trimText
}
from
'
helpers/text_helper
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
s__
}
from
'
~/locale
'
;
describe
(
'
Solution Card
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
const
solution
=
'
Upgrade to XYZ
'
;
const
remediation
=
{
summary
:
'
Update to 123
'
,
fixes
:
[],
diff
:
'
SGVsbG8gR2l0TGFi
'
};
let
wrapper
;
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
computed properties
'
,
()
=>
{
describe
(
'
solutionText
'
,
()
=>
{
it
(
'
takes the value of solution
'
,
()
=>
{
const
propsData
=
{
solution
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
expect
(
wrapper
.
vm
.
solutionText
).
toEqual
(
solution
);
});
it
(
'
takes the summary from a remediation
'
,
()
=>
{
const
propsData
=
{
remediation
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
expect
(
wrapper
.
vm
.
solutionText
).
toEqual
(
remediation
.
summary
);
});
it
(
'
takes the summary from a remediation, if both are defined
'
,
()
=>
{
const
propsData
=
{
remediation
,
solution
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
expect
(
wrapper
.
vm
.
solutionText
).
toEqual
(
remediation
.
summary
);
});
});
});
describe
(
'
rendering
'
,
()
=>
{
describe
(
'
with solution
'
,
()
=>
{
beforeEach
(()
=>
{
const
propsData
=
{
solution
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
});
it
(
'
renders the solution text and label
'
,
()
=>
{
expect
(
trimText
(
wrapper
.
find
(
'
.card-body
'
).
text
())).
toContain
(
`Solution:
${
solution
}
`
);
});
it
(
'
does not render the card footer
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
exists
()).
toBe
(
false
);
});
it
(
'
does not render the download link
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
a
'
).
exists
()).
toBe
(
false
);
});
});
describe
(
'
with remediation
'
,
()
=>
{
beforeEach
(()
=>
{
const
propsData
=
{
remediation
,
hasRemediation
:
true
};
wrapper
=
shallowMount
(
Component
,
{
propsData
});
});
it
(
'
renders the solution text and label
'
,
()
=>
{
expect
(
trimText
(
wrapper
.
find
(
'
.card-body
'
).
text
())).
toContain
(
`Solution:
${
remediation
.
summary
}
`
,
);
});
describe
(
'
with download patch
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
.
setProps
({
hasDownload
:
true
});
return
wrapper
.
vm
.
$nextTick
();
});
it
(
'
does not render the download and apply solution message when there is a file download and a merge request already exists
'
,
()
=>
{
wrapper
.
setProps
({
hasMr
:
true
});
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
exists
()).
toBe
(
false
);
});
});
it
(
'
renders the create a merge request to implement this solution message
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
text
()).
toContain
(
s__
(
'
ciReport|Create a merge request to implement this solution, or download and apply the patch manually.
'
,
),
);
});
});
describe
(
'
without download patch
'
,
()
=>
{
it
(
'
does not render the card footer
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.card-footer
'
).
exists
()).
toBe
(
false
);
});
});
});
});
});
ee/spec/frontend/vulnerabilities/footer_spec.js
View file @
369d3ae0
...
...
@@ -68,7 +68,6 @@ describe('Vulnerability Footer', () => {
remediation
:
properties
.
remediations
[
0
],
hasDownload
:
true
,
hasMr
:
vulnerability
.
has_mr
,
isStandaloneVulnerability
:
true
,
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment