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
9041c27c
Commit
9041c27c
authored
Nov 02, 2018
by
Sam Beckham
Committed by
Phil Hughes
Nov 02, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add modals and actions for the vulnerabilities in the Group security dashboard
parent
c3a5223b
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1312 additions
and
206 deletions
+1312
-206
ee/app/assets/javascripts/security_dashboard/components/app.vue
.../assets/javascripts/security_dashboard/components/app.vue
+19
-3
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_action_buttons.vue
...ashboard/components/security_dashboard_action_buttons.vue
+0
-62
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_table.vue
...ecurity_dashboard/components/security_dashboard_table.vue
+2
-1
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_table_row.vue
...ity_dashboard/components/security_dashboard_table_row.vue
+28
-15
ee/app/assets/javascripts/security_dashboard/components/vulnerability_action_buttons.vue
...ity_dashboard/components/vulnerability_action_buttons.vue
+114
-0
ee/app/assets/javascripts/security_dashboard/components/vulnerability_issue_link.vue
...ecurity_dashboard/components/vulnerability_issue_link.vue
+3
-3
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/actions.js
...curity_dashboard/store/modules/vulnerabilities/actions.js
+124
-6
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/mutation_types.js
...dashboard/store/modules/vulnerabilities/mutation_types.js
+14
-0
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/mutations.js
...rity_dashboard/store/modules/vulnerabilities/mutations.js
+89
-0
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/state.js
...security_dashboard/store/modules/vulnerabilities/state.js
+24
-0
ee/changelogs/unreleased/6709-group-security-dashboard-vulnerabilites-fe-ee.yml
...ed/6709-group-security-dashboard-vulnerabilites-fe-ee.yml
+5
-0
ee/spec/javascripts/security_dashboard/components/security_dashboard_action_buttons_spec.js
...oard/components/security_dashboard_action_buttons_spec.js
+0
-60
ee/spec/javascripts/security_dashboard/components/security_dashboard_table_row_spec.js
...dashboard/components/security_dashboard_table_row_spec.js
+40
-26
ee/spec/javascripts/security_dashboard/components/security_dashboard_table_spec.js
...ity_dashboard/components/security_dashboard_table_spec.js
+3
-1
ee/spec/javascripts/security_dashboard/components/vulnerability_action_buttons_spec.js
...dashboard/components/vulnerability_action_buttons_spec.js
+147
-0
ee/spec/javascripts/security_dashboard/store/vulnerabilities/actions_spec.js
.../security_dashboard/store/vulnerabilities/actions_spec.js
+366
-9
ee/spec/javascripts/security_dashboard/store/vulnerabilities/data/mock_data_vulnerabilities.json
...store/vulnerabilities/data/mock_data_vulnerabilities.json
+6
-0
ee/spec/javascripts/security_dashboard/store/vulnerabilities/data/mock_data_vulnerabilities_count.json
...vulnerabilities/data/mock_data_vulnerabilities_count.json
+0
-0
ee/spec/javascripts/security_dashboard/store/vulnerabilities/mutations_spec.js
...ecurity_dashboard/store/vulnerabilities/mutations_spec.js
+268
-11
locale/gitlab.pot
locale/gitlab.pot
+60
-9
No files found.
ee/app/assets/javascripts/security_dashboard/components/app.vue
View file @
9041c27c
<
script
>
import
{
mapActions
,
mapGetters
,
mapState
}
from
'
vuex
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
spriteIcon
}
from
'
~/lib/utils/common_utils
'
;
import
Tabs
from
'
~/vue_shared/components/tabs/tabs
'
;
import
Tab
from
'
~/vue_shared/components/tabs/tab.vue
'
;
import
IssueModal
from
'
ee/vue_shared/security_reports/components/modal.vue
'
;
import
SecurityDashboardTable
from
'
./security_dashboard_table.vue
'
;
import
VulnerabilityCountList
from
'
./vulnerability_count_list.vue
'
;
import
SvgBlankState
from
'
~/pipelines/components/blank_state.vue
'
;
...
...
@@ -16,6 +18,7 @@ export default {
},
components
:
{
Icon
,
IssueModal
,
SecurityDashboardTable
,
SvgBlankState
,
Tab
,
...
...
@@ -46,7 +49,7 @@ export default {
},
computed
:
{
...
mapGetters
(
'
vulnerabilities
'
,
[
'
vulnerabilitiesCountByReportType
'
]),
...
mapState
(
'
vulnerabilities
'
,
[
'
hasError
'
]),
...
mapState
(
'
vulnerabilities
'
,
[
'
hasError
'
,
'
modal
'
]),
sastCount
()
{
return
this
.
vulnerabilitiesCountByReportType
(
'
sast
'
);
},
...
...
@@ -66,7 +69,7 @@ export default {
<span class="vertical-align-middle">
${
s__
(
'
Security Reports|Security Dashboard Documentation
'
,
)}
</span>
${
gl
.
utils
.
spriteIcon
(
'
external-link
'
,
'
s16 vertical-align-middle
'
)}
${
spriteIcon
(
'
external-link
'
,
'
s16 vertical-align-middle
'
)}
</a>
`
,
html
:
true
,
...
...
@@ -83,6 +86,9 @@ export default {
'
setVulnerabilitiesCountEndpoint
'
,
'
setVulnerabilitiesEndpoint
'
,
'
fetchVulnerabilitiesCount
'
,
'
createIssue
'
,
'
dismissVulnerability
'
,
'
undoDismissal
'
,
]),
},
};
...
...
@@ -90,6 +96,7 @@ export default {
<
template
>
<div>
<div
class=
"flash-container"
></div>
<svg-blank-state
v-if=
"hasError"
:svg-path=
"errorStateSvgPath"
...
...
@@ -110,7 +117,8 @@ export default {
</span>
<span
v-popover=
"popoverOptions"
class=
"text-muted ml-1"
class=
"text-muted prepend-left-4"
:aria-label=
"__('help')"
>
<icon
name=
"question"
...
...
@@ -124,6 +132,14 @@ export default {
/>
</tab>
</tabs>
<issue-modal
:modal=
"modal"
:can-create-issue-permission=
"true"
:can-create-feedback-permission=
"true"
@
createNewIssue=
"createIssue({ vulnerability: modal.vulnerability })"
@
dismissIssue=
"dismissVulnerability({ vulnerability: modal.vulnerability })"
@
revertDismissIssue=
"undoDismissal({ vulnerability: modal.vulnerability })"
/>
</div>
</div>
</template>
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_action_buttons.vue
deleted
100644 → 0
View file @
c3a5223b
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
export
default
{
name
:
'
SecurityDashboardActionButtons
'
,
components
:
{
Icon
,
},
props
:
{
vulnerability
:
{
type
:
Object
,
required
:
true
,
},
},
methods
:
{
openModal
()
{
// TODO: Open the modal
},
newIssue
()
{
this
.
$store
.
dispatch
(
'
newIssue
'
,
this
.
vulnerability
);
},
dismissVulnerability
()
{
this
.
$store
.
dispatch
(
'
dismissVulnerability
'
,
this
.
vulnerability
);
},
},
};
</
script
>
<
template
>
<div>
<button
:aria-label=
"s__('Reports|More info')"
class=
"btn btn-secondary js-more-info"
type=
"button"
@
click=
"openModal()"
>
<icon
name=
"external-link"
/>
</button>
<button
:aria-label=
"s__('Reports|New Issue')"
class=
"btn btn-inverted btn-info js-new-issue"
type=
"button"
@
click=
"newIssue()"
>
<icon
name=
"issue-new"
/>
</button>
<button
:aria-label=
"s__('Reports|Dismiss Vulnerability')"
class=
"btn btn-inverted btn-remove js-dismiss-vulnerability"
type=
"button"
@
click=
"dismissVulnerability()"
>
<icon
name=
"cancel"
/>
</button>
</div>
</
template
>
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_table.vue
View file @
9041c27c
...
...
@@ -19,7 +19,7 @@ export default {
this
.
fetchVulnerabilities
();
},
methods
:
{
...
mapActions
(
'
vulnerabilities
'
,
[
'
fetchVulnerabilities
'
]),
...
mapActions
(
'
vulnerabilities
'
,
[
'
fetchVulnerabilities
'
,
'
openModal
'
]),
},
};
</
script
>
...
...
@@ -63,6 +63,7 @@ export default {
v-for=
"vulnerability in vulnerabilities"
:key=
"vulnerability.id"
:vulnerability=
"vulnerability"
@
openModal=
"openModal(
{ vulnerability })"
/>
<pagination
...
...
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_table_row.vue
View file @
9041c27c
<
script
>
import
{
mapActions
}
from
'
vuex
'
;
import
{
GlSkeletonLoading
}
from
'
@gitlab-org/gitlab-ui
'
;
import
SeverityBadge
from
'
ee/vue_shared/security_reports/components/severity_badge.vue
'
;
import
SecurityDashboardActionButtons
from
'
./security_dashboard
_action_buttons.vue
'
;
import
VulnerabilityActionButtons
from
'
./vulnerability
_action_buttons.vue
'
;
import
VulnerabilityIssueLink
from
'
./vulnerability_issue_link.vue
'
;
export
default
{
name
:
'
SecurityDashboardTableRow
'
,
components
:
{
SeverityBadge
,
SecurityDashboardActionButtons
,
GlSkeletonLoading
,
VulnerabilityActionButtons
,
VulnerabilityIssueLink
,
},
props
:
{
...
...
@@ -31,17 +32,26 @@ export default {
severity
()
{
return
this
.
vulnerability
.
severity
||
'
'
;
},
project
Namespac
e
()
{
project
FullNam
e
()
{
const
{
project
}
=
this
.
vulnerability
;
return
project
&&
project
.
full_name
?
project
.
full_name
:
null
;
return
project
&&
project
.
full_name
;
},
isDismissed
()
{
return
this
.
vulnerability
.
dismissal_feedback
;
return
Boolean
(
this
.
vulnerability
.
dismissal_feedback
)
;
},
hasIssue
()
{
return
this
.
vulnerability
.
issue_feedback
;
return
Boolean
(
this
.
vulnerability
.
issue_feedback
);
},
canDismissVulnerability
()
{
return
Boolean
(
this
.
vulnerability
.
vulnerability_feedback_url
);
},
canCreateIssue
()
{
return
this
.
canDismissVulnerability
&&
!
this
.
hasIssue
;
},
},
methods
:
{
...
mapActions
(
'
vulnerabilities
'
,
[
'
openModal
'
]),
},
};
</
script
>
...
...
@@ -73,8 +83,11 @@ export default {
:lines=
"2"
/>
<div
v-else
>
<strike
v-if=
"isDismissed"
>
{{
vulnerability
.
name
}}
</strike>
<span
v-else
>
{{
vulnerability
.
name
}}
</span>
<span
class=
"js-vulnerability-info"
:class=
"
{ strikethrough: isDismissed }"
@click="openModal({ vulnerability })"
>
{{
vulnerability
.
name
}}
</span>
<vulnerability-issue-link
v-if=
"hasIssue"
:issue=
"vulnerability.issue_feedback"
...
...
@@ -82,9 +95,9 @@ export default {
/>
<br
/>
<span
v-if=
"project
Namespac
e"
v-if=
"project
FullNam
e"
class=
"vulnerability-namespace"
>
{{
project
Namespac
e
}}
{{
project
FullNam
e
}}
</span>
</div>
</div>
...
...
@@ -98,12 +111,10 @@ export default {
{{
s__
(
'
Reports|Confidence
'
)
}}
</div>
<div
class=
"table-mobile-content text-capitalize"
>
<strike
v-if=
"isDismissed"
>
{{
confidence
}}
</strike>
<span
v-else
>
{{
confidence
}}
</span>
<span
:class=
"
{ strikethrough: isDismissed }">
{{
confidence
}}
</span>
</div>
</div>
<!-- This is hidden till we can hook up the actions
<div
class=
"table-section section-20"
>
<div
class=
"table-mobile-header"
...
...
@@ -112,12 +123,14 @@ export default {
{{
s__
(
'
Reports|Actions
'
)
}}
</div>
<div
class=
"table-mobile-content vulnerabilities-action-buttons"
>
<
security-dashboard
-action-buttons
<
vulnerability
-action-buttons
:vulnerability=
"vulnerability"
:can-create-issue=
"canCreateIssue"
:can-dismiss-vulnerability=
"canDismissVulnerability"
:is-dismissed=
"isDismissed"
/>
</div>
</div>
-->
</div>
</
template
>
...
...
ee/app/assets/javascripts/security_dashboard/components/vulnerability_action_buttons.vue
0 → 100644
View file @
9041c27c
<
script
>
import
{
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
GlTooltipDirective
}
from
'
@gitlab-org/gitlab-ui
'
;
import
LoadingButton
from
'
~/vue_shared/components/loading_button.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
export
default
{
name
:
'
SecurityDashboardActionButtons
'
,
components
:
{
Icon
,
LoadingButton
,
},
directives
:
{
GlTooltip
:
GlTooltipDirective
,
},
props
:
{
vulnerability
:
{
type
:
Object
,
required
:
true
,
},
canCreateIssue
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
canDismissVulnerability
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isDismissed
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
...
mapState
(
'
vulnerabilities
'
,
[
'
isCreatingIssue
'
,
'
isDismissingVulnerability
'
]),
},
methods
:
{
...
mapActions
(
'
vulnerabilities
'
,
[
'
openModal
'
,
'
createIssue
'
,
'
dismissVulnerability
'
,
'
undoDismissal
'
,
]),
handleCreateIssue
()
{
const
{
vulnerability
}
=
this
;
this
.
createIssue
({
vulnerability
,
flashError
:
true
});
},
handleDismissVulnerability
()
{
const
{
vulnerability
}
=
this
;
this
.
dismissVulnerability
({
vulnerability
,
flashError
:
true
});
},
handleUndoDismissal
()
{
const
{
vulnerability
}
=
this
;
this
.
undoDismissal
({
vulnerability
,
flashError
:
true
});
},
},
};
</
script
>
<
template
>
<div>
<button
key=
"more-info"
v-gl-tooltip
:aria-label=
"s__('Security Reports|More info')"
:title=
"s__('Security Reports|More info')"
class=
"btn btn-secondary js-more-info"
type=
"button"
@
click=
"openModal(
{ vulnerability })"
>
<icon
name=
"information"
/>
</button>
<loading-button
v-if=
"canCreateIssue"
key=
"create-issue"
v-gl-tooltip
:aria-label=
"s__('Security Reports|New Issue')"
:loading=
"isCreatingIssue"
:title=
"s__('Security Reports|New Issue')"
container-class=
"btn btn-inverted btn-success js-create-issue"
type=
"button"
@
click=
"handleCreateIssue"
>
<icon
name=
"issue-new"
/>
</loading-button>
<template
v-if=
"canDismissVulnerability"
>
<loading-button
v-if=
"isDismissed"
key=
"undo-dismissal"
:label=
"s__('Security Reports|Undo Dismissal')"
:loading=
"isDismissingVulnerability"
container-class=
"btn btn-inverted btn-warning js-undo-dismissal"
type=
"button"
@
click=
"handleUndoDismissal"
/>
<loading-button
v-else
key=
"dismiss-vulnerability"
v-gl-tooltip
:aria-label=
"s__('Security Reports|Dismiss Vulnerability')"
:loading=
"isDismissingVulnerability"
:title=
"s__('Security Reports|Dismiss Vulnerability')"
container-class=
"btn btn-inverted btn-warning js-dismiss-vulnerability"
type=
"button"
@
click=
"handleDismissVulnerability"
>
<icon
name=
"cancel"
/>
</loading-button>
</
template
>
</div>
</template>
ee/app/assets/javascripts/security_dashboard/components/vulnerability_issue_link.vue
View file @
9041c27c
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
{
GlTooltipDirective
}
from
'
@gitlab-org/gitlab-ui
'
;
export
default
{
name
:
'
VulnerabilityIssueLink
'
,
...
...
@@ -8,7 +8,7 @@ export default {
Icon
,
},
directives
:
{
Tooltip
,
GlTooltip
:
GlTooltipDirective
,
},
props
:
{
issue
:
{
...
...
@@ -31,7 +31,7 @@ export default {
<
template
>
<div
class=
"d-inline"
>
<icon
v-tooltip
v-
gl-
tooltip
name=
"issues"
css-classes=
"text-success vertical-align-middle"
:title=
"s__('Security Dashboard|Issue Created')"
...
...
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/actions.js
View file @
9041c27c
import
$
from
'
jquery
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
*
as
types
from
'
./mutation_types
'
;
import
{
parseIntPagination
,
normalizeHeaders
}
from
'
~/lib/utils/common_utils
'
;
import
{
s__
}
from
'
~/locale
'
;
import
createFlash
from
'
~/flash
'
;
export
const
setVulnerabilitiesEndpoint
=
({
commit
},
endpoint
)
=>
{
commit
(
types
.
SET_VULNERABILITIES_ENDPOINT
,
endpoint
);
...
...
@@ -30,17 +33,19 @@ export const requestVulnerabilitiesCount = ({ commit }) => {
commit
(
types
.
REQUEST_VULNERABILITIES_COUNT
);
};
export
const
receiveVulnerabilitiesCountSuccess
=
({
commit
},
response
)
=>
{
commit
(
types
.
RECEIVE_VULNERABILITIES_COUNT_SUCCESS
,
response
.
data
);
export
const
receiveVulnerabilitiesCountSuccess
=
({
commit
},
{
data
}
)
=>
{
commit
(
types
.
RECEIVE_VULNERABILITIES_COUNT_SUCCESS
,
data
);
};
export
const
receiveVulnerabilitiesCountError
=
({
commit
})
=>
{
commit
(
types
.
RECEIVE_VULNERABILITIES_COUNT_ERROR
);
};
export
const
fetchVulnerabilities
=
({
state
,
dispatch
},
page
=
1
)
=>
{
export
const
fetchVulnerabilities
=
({
state
,
dispatch
},
page
Number
)
=>
{
dispatch
(
'
requestVulnerabilities
'
);
const
page
=
pageNumber
||
(
state
.
pageInfo
&&
state
.
pageInfo
.
page
)
||
1
;
axios
({
method
:
'
GET
'
,
url
:
state
.
vulnerabilitiesEndpoint
,
...
...
@@ -59,10 +64,10 @@ export const requestVulnerabilities = ({ commit }) => {
commit
(
types
.
REQUEST_VULNERABILITIES
);
};
export
const
receiveVulnerabilitiesSuccess
=
({
commit
},
response
=
{
})
=>
{
const
normalizedHeaders
=
normalizeHeaders
(
response
.
headers
);
export
const
receiveVulnerabilitiesSuccess
=
({
commit
},
{
headers
,
data
})
=>
{
const
normalizedHeaders
=
normalizeHeaders
(
headers
);
const
pageInfo
=
parseIntPagination
(
normalizedHeaders
);
const
vulnerabilities
=
response
.
data
;
const
vulnerabilities
=
data
;
commit
(
types
.
RECEIVE_VULNERABILITIES_SUCCESS
,
{
pageInfo
,
vulnerabilities
});
};
...
...
@@ -71,4 +76,117 @@ export const receiveVulnerabilitiesError = ({ commit }) => {
commit
(
types
.
RECEIVE_VULNERABILITIES_ERROR
);
};
export
const
openModal
=
({
commit
},
payload
=
{})
=>
{
$
(
'
#modal-mrwidget-security-issue
'
).
modal
(
'
show
'
);
commit
(
types
.
SET_MODAL_DATA
,
payload
);
};
export
const
createIssue
=
({
dispatch
},
{
vulnerability
,
flashError
})
=>
{
dispatch
(
'
requestCreateIssue
'
);
axios
.
post
(
vulnerability
.
vulnerability_feedback_url
,
{
vulnerability_feedback
:
{
feedback_type
:
'
issue
'
,
category
:
vulnerability
.
report_type
,
project_fingerprint
:
vulnerability
.
project_fingerprint
,
vulnerability_data
:
{
...
vulnerability
,
category
:
vulnerability
.
report_type
,
},
},
})
.
then
(({
data
})
=>
{
dispatch
(
'
receiveCreateIssueSuccess
'
,
data
);
})
.
catch
(()
=>
{
dispatch
(
'
receiveCreateIssueError
'
,
{
flashError
});
});
};
export
const
requestCreateIssue
=
({
commit
})
=>
{
commit
(
types
.
REQUEST_CREATE_ISSUE
);
};
export
const
receiveCreateIssueSuccess
=
({
commit
},
payload
)
=>
{
commit
(
types
.
RECEIVE_CREATE_ISSUE_SUCCESS
,
payload
);
};
export
const
receiveCreateIssueError
=
({
commit
})
=>
{
commit
(
types
.
RECEIVE_CREATE_ISSUE_ERROR
);
createFlash
(
s__
(
'
Security Reports|There was an error creating the issue.
'
));
};
export
const
dismissVulnerability
=
({
dispatch
},
{
vulnerability
,
flashError
})
=>
{
dispatch
(
'
requestDismissVulnerability
'
);
axios
.
post
(
vulnerability
.
vulnerability_feedback_url
,
{
vulnerability_feedback
:
{
feedback_type
:
'
dismissal
'
,
category
:
vulnerability
.
report_type
,
project_fingerprint
:
vulnerability
.
project_fingerprint
,
vulnerability_data
:
{
...
vulnerability
,
category
:
vulnerability
.
report_type
,
},
},
})
.
then
(({
data
})
=>
{
const
{
id
}
=
vulnerability
;
dispatch
(
'
receiveDismissVulnerabilitySuccess
'
,
{
id
,
data
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveDismissVulnerabilityError
'
,
{
flashError
});
});
};
export
const
requestDismissVulnerability
=
({
commit
})
=>
{
commit
(
types
.
REQUEST_DISMISS_VULNERABILITY
);
};
export
const
receiveDismissVulnerabilitySuccess
=
({
commit
},
payload
)
=>
{
commit
(
types
.
RECEIVE_DISMISS_VULNERABILITY_SUCCESS
,
payload
);
};
export
const
receiveDismissVulnerabilityError
=
({
commit
},
{
flashError
})
=>
{
commit
(
types
.
RECEIVE_DISMISS_VULNERABILITY_ERROR
);
if
(
flashError
)
{
createFlash
(
s__
(
'
Security Reports|There was an error dismissing the issue.
'
));
}
};
export
const
undoDismissal
=
({
dispatch
},
{
vulnerability
,
flashError
})
=>
{
const
{
vulnerability_feedback_url
,
dismissal_feedback
}
=
vulnerability
;
// eslint-disable-next-line camelcase
const
url
=
`
${
vulnerability_feedback_url
}
/
${
dismissal_feedback
.
id
}
`
;
dispatch
(
'
requestUndoDismissal
'
);
axios
.
delete
(
url
)
.
then
(()
=>
{
const
{
id
}
=
vulnerability
;
dispatch
(
'
receiveUndoDismissalSuccess
'
,
{
id
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveUndoDismissalError
'
,
{
flashError
});
});
};
export
const
requestUndoDismissal
=
({
commit
})
=>
{
commit
(
types
.
REQUEST_UNDO_DISMISSAL
);
};
export
const
receiveUndoDismissalSuccess
=
({
commit
},
payload
)
=>
{
commit
(
types
.
RECEIVE_UNDO_DISMISSAL_SUCCESS
,
payload
);
};
export
const
receiveUndoDismissalError
=
({
commit
},
{
flashError
})
=>
{
commit
(
types
.
RECEIVE_UNDO_DISMISSAL_ERROR
);
if
(
flashError
)
{
createFlash
(
s__
(
'
Security Reports|There was an error undoing this dismissal.
'
));
}
};
export
default
()
=>
{};
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/mutation_types.js
View file @
9041c27c
...
...
@@ -7,3 +7,17 @@ export const SET_VULNERABILITIES_COUNT_ENDPOINT = 'SET_VULNERABILITIES_COUNT_END
export
const
REQUEST_VULNERABILITIES_COUNT
=
'
REQUEST_VULNERABILITIES_COUNT
'
;
export
const
RECEIVE_VULNERABILITIES_COUNT_SUCCESS
=
'
RECEIVE_VULNERABILITIES_COUNT_SUCCESS
'
;
export
const
RECEIVE_VULNERABILITIES_COUNT_ERROR
=
'
RECEIVE_VULNERABILITIES_COUNT_ERROR
'
;
export
const
SET_MODAL_DATA
=
'
SET_MODAL_DATA
'
;
export
const
REQUEST_CREATE_ISSUE
=
'
REQUEST_CREATE_ISSUE
'
;
export
const
RECEIVE_CREATE_ISSUE_SUCCESS
=
'
RECEIVE_CREATE_ISSUE_SUCCESS
'
;
export
const
RECEIVE_CREATE_ISSUE_ERROR
=
'
RECEIVE_CREATE_ISSUE_ERROR
'
;
export
const
REQUEST_DISMISS_VULNERABILITY
=
'
REQUEST_DISMISS_VULNERABILITY
'
;
export
const
RECEIVE_DISMISS_VULNERABILITY_SUCCESS
=
'
RECEIVE_DISMISS_VULNERABILITY_SUCCESS
'
;
export
const
RECEIVE_DISMISS_VULNERABILITY_ERROR
=
'
RECEIVE_DISMISS_VULNERABILITY_ERROR
'
;
export
const
REQUEST_UNDO_DISMISSAL
=
'
REQUEST_UNDO_DISMISSAL
'
;
export
const
RECEIVE_UNDO_DISMISSAL_SUCCESS
=
'
RECEIVE_UNDO_DISMISSAL_SUCCESS
'
;
export
const
RECEIVE_UNDO_DISMISSAL_ERROR
=
'
RECEIVE_UNDO_DISMISSAL_ERROR
'
;
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/mutations.js
View file @
9041c27c
import
Vue
from
'
vue
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
*
as
types
from
'
./mutation_types
'
;
export
default
{
...
...
@@ -32,4 +35,90 @@ export default {
state
.
isLoadingVulnerabilitiesCount
=
false
;
state
.
hasError
=
true
;
},
[
types
.
SET_MODAL_DATA
](
state
,
payload
)
{
const
{
vulnerability
}
=
payload
;
Vue
.
set
(
state
.
modal
,
'
title
'
,
vulnerability
.
name
);
Vue
.
set
(
state
.
modal
.
data
.
description
,
'
value
'
,
vulnerability
.
description
);
Vue
.
set
(
state
.
modal
.
data
.
project
,
'
value
'
,
vulnerability
.
project
&&
vulnerability
.
project
.
full_name
,
);
Vue
.
set
(
state
.
modal
.
data
.
project
,
'
url
'
,
vulnerability
.
project
&&
vulnerability
.
project
.
full_path
,
);
Vue
.
set
(
state
.
modal
.
data
.
file
,
'
value
'
,
vulnerability
.
location
&&
vulnerability
.
location
.
file
);
Vue
.
set
(
state
.
modal
.
data
.
identifiers
,
'
value
'
,
vulnerability
.
identifiers
.
length
&&
vulnerability
.
identifiers
,
);
Vue
.
set
(
state
.
modal
.
data
.
severity
,
'
value
'
,
vulnerability
.
severity
);
Vue
.
set
(
state
.
modal
.
data
.
confidence
,
'
value
'
,
vulnerability
.
confidence
);
Vue
.
set
(
state
.
modal
.
data
.
solution
,
'
value
'
,
vulnerability
.
solution
);
Vue
.
set
(
state
.
modal
.
data
.
links
,
'
value
'
,
vulnerability
.
links
);
Vue
.
set
(
state
.
modal
.
data
.
instances
,
'
value
'
,
vulnerability
.
instances
);
Vue
.
set
(
state
.
modal
,
'
vulnerability
'
,
vulnerability
);
Vue
.
set
(
state
.
modal
.
vulnerability
,
'
hasIssue
'
,
Boolean
(
vulnerability
.
issue_feedback
));
Vue
.
set
(
state
.
modal
,
'
error
'
,
null
);
},
[
types
.
REQUEST_CREATE_ISSUE
](
state
)
{
state
.
isCreatingIssue
=
true
;
Vue
.
set
(
state
.
modal
,
'
isCreatingNewIssue
'
,
true
);
Vue
.
set
(
state
.
modal
,
'
error
'
,
null
);
},
[
types
.
RECEIVE_CREATE_ISSUE_SUCCESS
](
state
,
payload
)
{
// We don't cancel the loading state here because we're navigating away from the page
visitUrl
(
payload
.
issue_url
);
},
[
types
.
RECEIVE_CREATE_ISSUE_ERROR
](
state
)
{
state
.
isCreatingIssue
=
false
;
Vue
.
set
(
state
.
modal
,
'
isCreatingNewIssue
'
,
false
);
Vue
.
set
(
state
.
modal
,
'
error
'
,
'
There was an error creating the issue
'
);
},
[
types
.
REQUEST_DISMISS_VULNERABILITY
](
state
)
{
state
.
isDismissingVulnerability
=
true
;
Vue
.
set
(
state
.
modal
,
'
isDismissingVulnerability
'
,
true
);
Vue
.
set
(
state
.
modal
,
'
error
'
,
null
);
},
[
types
.
RECEIVE_DISMISS_VULNERABILITY_SUCCESS
](
state
,
payload
)
{
const
vulnerability
=
state
.
vulnerabilities
.
find
(
vuln
=>
vuln
.
id
===
payload
.
id
);
vulnerability
.
dismissal_feedback
=
payload
.
data
;
state
.
isDismissingVulnerability
=
false
;
Vue
.
set
(
state
.
modal
,
'
isDismissingVulnerability
'
,
false
);
Vue
.
set
(
state
.
modal
.
vulnerability
,
'
isDismissed
'
,
true
);
},
[
types
.
RECEIVE_DISMISS_VULNERABILITY_ERROR
](
state
)
{
state
.
isDismissingVulnerability
=
false
;
Vue
.
set
(
state
.
modal
,
'
isDismissingVulnerability
'
,
false
);
Vue
.
set
(
state
.
modal
,
'
error
'
,
s__
(
'
Security Reports|There was an error dismissing the vulnerability.
'
),
);
},
[
types
.
REQUEST_UNDO_DISMISSAL
](
state
)
{
state
.
isDismissingVulnerability
=
true
;
Vue
.
set
(
state
.
modal
,
'
isDismissingVulnerability
'
,
true
);
Vue
.
set
(
state
.
modal
,
'
error
'
,
null
);
},
[
types
.
RECEIVE_UNDO_DISMISSAL_SUCCESS
](
state
,
payload
)
{
const
vulnerability
=
state
.
vulnerabilities
.
find
(
vuln
=>
vuln
.
id
===
payload
.
id
);
vulnerability
.
dismissal_feedback
=
null
;
state
.
isDismissingVulnerability
=
false
;
Vue
.
set
(
state
.
modal
,
'
isDismissingVulnerability
'
,
false
);
Vue
.
set
(
state
.
modal
.
vulnerability
,
'
isDismissed
'
,
false
);
},
[
types
.
RECEIVE_UNDO_DISMISSAL_ERROR
](
state
)
{
state
.
isDismissingVulnerability
=
false
;
Vue
.
set
(
state
.
modal
,
'
isDismissingVulnerability
'
,
false
);
Vue
.
set
(
state
.
modal
,
'
error
'
,
s__
(
'
Security Reports|There was an error undoing the dismissal.
'
),
);
},
};
ee/app/assets/javascripts/security_dashboard/store/modules/vulnerabilities/state.js
View file @
9041c27c
import
{
s__
}
from
'
~/locale
'
;
export
default
()
=>
({
hasError
:
false
,
isLoadingVulnerabilities
:
true
,
...
...
@@ -7,4 +9,26 @@ export default () => ({
vulnerabilitiesCount
:
{},
vulnerabilitiesCountEndpoint
:
null
,
vulnerabilitiesEndpoint
:
null
,
activeVulnerability
:
null
,
modal
:
{
data
:
{
description
:
{
text
:
s__
(
'
Vulnerability|Description
'
)
},
project
:
{
text
:
s__
(
'
Vulnerability|Project
'
),
isLink
:
true
,
},
file
:
{
text
:
s__
(
'
Vulnerability|File
'
)
},
identifiers
:
{
text
:
s__
(
'
Vulnerability|Identifiers
'
)
},
severity
:
{
text
:
s__
(
'
Vulnerability|Severity
'
)
},
confidence
:
{
text
:
s__
(
'
Vulnerability|Confidence
'
)
},
solution
:
{
text
:
s__
(
'
Vulnerability|Solution
'
)
},
links
:
{
text
:
s__
(
'
Vulnerability|Links
'
)
},
instances
:
{
text
:
s__
(
'
Vulnerability|Instances
'
)
},
},
vulnerability
:
{},
isCreatingNewIssue
:
false
,
isDismissingVulnerability
:
false
,
},
isCreatingIssue
:
false
,
isDismissingVulnerability
:
false
,
});
ee/changelogs/unreleased/6709-group-security-dashboard-vulnerabilites-fe-ee.yml
0 → 100644
View file @
9041c27c
---
title
:
Add modals and actions to the vulnerabilities in the Group security dashboard
merge_request
:
7910
author
:
type
:
added
ee/spec/javascripts/security_dashboard/components/security_dashboard_action_buttons_spec.js
deleted
100644 → 0
View file @
c3a5223b
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
component
from
'
ee/security_dashboard/components/security_dashboard_action_buttons.vue
'
;
import
{
mountComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
describe
(
'
Security Dashboard Action Buttons
'
,
()
=>
{
let
vm
;
let
props
;
let
actions
;
beforeEach
(()
=>
{
props
=
{
vulnerability
:
{
id
:
123
}
};
actions
=
{
newIssue
:
jasmine
.
createSpy
(
'
newIssue
'
),
dismissVulnerability
:
jasmine
.
createSpy
(
'
dismissVulnerability
'
),
};
const
Component
=
Vue
.
extend
(
component
);
const
store
=
new
Vuex
.
Store
({
actions
});
vm
=
mountComponentWithStore
(
Component
,
{
props
,
store
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
should render three buttons
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.btn
'
)).
toHaveLength
(
3
);
});
describe
(
'
More Info Button
'
,
()
=>
{
it
(
'
should render the More info button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-more-info
'
)).
not
.
toBeNull
();
});
});
describe
(
'
New Issue Button
'
,
()
=>
{
it
(
'
should render the New Issue button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-new-issue
'
)).
not
.
toBeNull
();
});
it
(
'
should trigger the `newIssue` action when clicked
'
,
()
=>
{
vm
.
$el
.
querySelector
(
'
.js-new-issue
'
).
click
();
expect
(
actions
.
newIssue
).
toHaveBeenCalledTimes
(
1
);
});
});
describe
(
'
Dismiss Vulnerability Button
'
,
()
=>
{
it
(
'
should render the Dismiss Vulnerability button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-dismiss-vulnerability
'
)).
not
.
toBeNull
();
});
it
(
'
should trigger the `dismissVulnerability` action when clicked
'
,
()
=>
{
vm
.
$el
.
querySelector
(
'
.js-dismiss-vulnerability
'
).
click
();
expect
(
actions
.
dismissVulnerability
).
toHaveBeenCalledTimes
(
1
);
});
});
});
ee/spec/javascripts/security_dashboard/components/security_dashboard_table_row_spec.js
View file @
9041c27c
import
Vue
from
'
vue
'
;
import
component
from
'
ee/security_dashboard/components/security_dashboard_table_row.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
createStore
from
'
ee/security_dashboard/store
'
;
import
{
mountComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
mockDataVulnerabilities
from
'
../store/vulnerabilities/data/mock_data_vulnerabilities.json
'
;
describe
(
'
Security Dashboard Table Row
'
,
()
=>
{
let
vm
;
let
props
;
const
store
=
createStore
();
const
Component
=
Vue
.
extend
(
component
);
afterEach
(()
=>
{
vm
.
$destroy
();
});
describe
(
'
when loading
'
,
()
=>
{
beforeEach
(()
=>
{
props
=
{
isLoading
:
true
};
vm
=
mountComponent
(
Component
,
props
);
vm
=
mountComponentWithStore
(
Component
,
{
store
,
props
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
should display the skeleton loader
'
,
()
=>
{
...
...
@@ -33,16 +36,15 @@ describe('Security Dashboard Table Row', () => {
});
describe
(
'
when loaded
'
,
()
=>
{
beforeEach
(()
=>
{
const
vulnerability
=
{
severity
:
'
high
'
,
name
:
'
Test vulnerability
'
,
confidence
:
'
medium
'
,
project
:
{
full_name
:
'
project name
'
},
};
const
vulnerability
=
mockDataVulnerabilities
[
0
];
beforeEach
(()
=>
{
props
=
{
vulnerability
};
vm
=
mountComponent
(
Component
,
props
);
vm
=
mountComponentWithStore
(
Component
,
{
store
,
props
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
should not display the skeleton loader
'
,
()
=>
{
...
...
@@ -55,22 +57,34 @@ describe('Security Dashboard Table Row', () => {
);
});
it
(
'
should render the name
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.table-mobile-content
'
)[
1
].
textContent
).
toContain
(
props
.
vulnerability
.
name
,
);
});
it
(
'
should render the project namespace
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.table-mobile-content
'
)[
1
].
textContent
).
toContain
(
props
.
vulnerability
.
project
.
full_name
,
);
});
it
(
'
should render the confidence
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.table-mobile-content
'
)[
2
].
textContent
).
toContain
(
props
.
vulnerability
.
confidence
,
);
});
describe
(
'
the project name
'
,
()
=>
{
it
(
'
should render the name
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.table-mobile-content
'
)[
1
].
textContent
).
toContain
(
props
.
vulnerability
.
name
,
);
});
it
(
'
should render the project namespace
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.table-mobile-content
'
)[
1
].
textContent
).
toContain
(
props
.
vulnerability
.
project
.
full_name
,
);
});
it
(
'
should fire the openModal action when clicked
'
,
()
=>
{
spyOn
(
vm
.
$store
,
'
dispatch
'
);
vm
.
$el
.
querySelector
(
'
.js-vulnerability-info
'
).
click
();
expect
(
vm
.
$store
.
dispatch
).
toHaveBeenCalledWith
(
'
vulnerabilities/openModal
'
,
{
vulnerability
,
});
});
});
});
});
ee/spec/javascripts/security_dashboard/components/security_dashboard_table_spec.js
View file @
9041c27c
import
Vue
from
'
vue
'
;
import
MockAdapater
from
'
axios-mock-adapter
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
component
from
'
ee/security_dashboard/components/security_dashboard_table.vue
'
;
import
createStore
from
'
ee/security_dashboard/store
'
;
import
mockDataVulnerabilities
from
'
ee/security_dashboard/store/modules/vulnerabilities/mock_data_vulnerabilities.json
'
;
import
{
mountComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
waitForPromises
from
'
spec/helpers/wait_for_promises
'
;
import
{
resetStore
}
from
'
../helpers
'
;
import
mockDataVulnerabilities
from
'
../store/vulnerabilities/data/mock_data_vulnerabilities.json
'
;
describe
(
'
Security Dashboard Table
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
...
...
ee/spec/javascripts/security_dashboard/components/vulnerability_action_buttons_spec.js
0 → 100644
View file @
9041c27c
import
Vue
from
'
vue
'
;
import
component
from
'
ee/security_dashboard/components/vulnerability_action_buttons.vue
'
;
import
createStore
from
'
ee/security_dashboard/store
'
;
import
{
mountComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
resetStore
}
from
'
../helpers
'
;
import
mockDataVulnerabilities
from
'
../store/vulnerabilities/data/mock_data_vulnerabilities.json
'
;
describe
(
'
Security Dashboard Action Buttons
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
let
vm
;
let
store
;
let
props
;
beforeEach
(()
=>
{
store
=
createStore
();
});
afterEach
(()
=>
{
vm
.
$destroy
();
resetStore
(
store
);
});
describe
(
'
with a fresh vulnerability
'
,
()
=>
{
beforeEach
(()
=>
{
props
=
{
vulnerability
:
mockDataVulnerabilities
[
0
],
canCreateIssue
:
true
,
canDismissVulnerability
:
true
,
};
vm
=
mountComponentWithStore
(
Component
,
{
store
,
props
});
spyOn
(
vm
.
$store
,
'
dispatch
'
).
and
.
returnValue
(
Promise
.
resolve
());
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
should render three buttons
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.btn
'
)).
toHaveLength
(
3
);
});
describe
(
'
More Info Button
'
,
()
=>
{
let
button
;
beforeEach
(()
=>
{
button
=
vm
.
$el
.
querySelector
(
'
.js-more-info
'
);
});
it
(
'
should render the More info button
'
,
()
=>
{
expect
(
button
).
not
.
toBeNull
();
});
it
(
'
should emit an `openModal` event when clicked
'
,
()
=>
{
button
.
click
();
expect
(
vm
.
$store
.
dispatch
).
toHaveBeenCalledWith
(
'
vulnerabilities/openModal
'
,
{
vulnerability
:
mockDataVulnerabilities
[
0
],
});
});
});
describe
(
'
Create Issue Button
'
,
()
=>
{
let
button
;
beforeEach
(()
=>
{
button
=
vm
.
$el
.
querySelector
(
'
.js-create-issue
'
);
});
it
(
'
should render the create issue button
'
,
()
=>
{
expect
(
button
).
not
.
toBeNull
();
});
it
(
'
should emit an `createIssue` event when clicked
'
,
()
=>
{
button
.
click
();
expect
(
vm
.
$store
.
dispatch
).
toHaveBeenCalledWith
(
'
vulnerabilities/createIssue
'
,
{
vulnerability
:
mockDataVulnerabilities
[
0
],
flashError
:
true
,
});
});
});
describe
(
'
Dismiss Vulnerability Button
'
,
()
=>
{
let
button
;
beforeEach
(()
=>
{
button
=
vm
.
$el
.
querySelector
(
'
.js-dismiss-vulnerability
'
);
});
it
(
'
should render the dismiss vulnerability button
'
,
()
=>
{
expect
(
button
).
not
.
toBeNull
();
});
it
(
'
should emit an `dismissVulnerability` event when clicked
'
,
()
=>
{
button
.
click
();
expect
(
vm
.
$store
.
dispatch
).
toHaveBeenCalledWith
(
'
vulnerabilities/dismissVulnerability
'
,
{
vulnerability
:
mockDataVulnerabilities
[
0
],
flashError
:
true
,
});
});
});
});
describe
(
'
with a vulnerbility that has an issue
'
,
()
=>
{
beforeEach
(()
=>
{
props
=
{
vulnerability
:
mockDataVulnerabilities
[
3
],
};
vm
=
mountComponentWithStore
(
Component
,
{
store
,
props
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
should only render one button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.btn
'
)).
toHaveLength
(
1
);
});
it
(
'
should not render the create issue button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-create-issue
'
)).
toBeNull
();
});
});
describe
(
'
with a vulnerbility that has been dismissed
'
,
()
=>
{
beforeEach
(()
=>
{
props
=
{
vulnerability
:
mockDataVulnerabilities
[
2
],
};
vm
=
mountComponentWithStore
(
Component
,
{
store
,
props
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
should only render one button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.btn
'
)).
toHaveLength
(
1
);
});
it
(
'
should not render the dismiss vulnerability button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-dismiss-vulnerability
'
)).
toBeNull
();
});
});
});
ee/spec/javascripts/security_dashboard/store/vulnerabilities/actions_spec.js
View file @
9041c27c
...
...
@@ -3,15 +3,37 @@ import axios from '~/lib/utils/axios_utils';
import
testAction
from
'
spec/helpers/vuex_action_helper
'
;
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
import
mockDataVulnerabilities
from
'
ee/security_dashboard/store/modules/vulnerabilities/mock_data_vulnerabilities.json
'
;
import
mockDataVulnerabilitiesCount
from
'
ee/security_dashboard/store/modules/vulnerabilities/mock_data_vulnerabilities_count.json
'
;
import
initialState
from
'
ee/security_dashboard/store/modules/vulnerabilities/state
'
;
import
*
as
types
from
'
ee/security_dashboard/store/modules/vulnerabilities/mutation_types
'
;
import
*
as
actions
from
'
ee/security_dashboard/store/modules/vulnerabilities/actions
'
;
import
mockDataVulnerabilities
from
'
./data/mock_data_vulnerabilities.json
'
;
import
mockDataVulnerabilitiesCount
from
'
./data/mock_data_vulnerabilities_count.json
'
;
describe
(
'
vulnerabiliites count actions
'
,
()
=>
{
const
data
=
mockDataVulnerabilitiesCount
;
describe
(
'
setVulnerabilitiesCountEndpoint
'
,
()
=>
{
it
(
'
should commit the correct mutuation
'
,
done
=>
{
const
state
=
initialState
;
const
endpoint
=
'
fakepath.json
'
;
testAction
(
actions
.
setVulnerabilitiesCountEndpoint
,
endpoint
,
state
,
[
{
type
:
types
.
SET_VULNERABILITIES_COUNT_ENDPOINT
,
payload
:
endpoint
,
},
],
[],
done
,
);
});
});
describe
(
'
fetchVulnerabilitesCount
'
,
()
=>
{
let
mock
;
const
state
=
initialState
;
...
...
@@ -255,20 +277,102 @@ describe('vulnerabilities actions', () => {
);
});
});
});
describe
(
'
setVulnerabilitiesCountEndpoint
'
,
()
=>
{
it
(
'
should commit the correct mutuation
'
,
done
=>
{
describe
(
'
openModal
'
,
()
=>
{
it
(
'
should commit the SET_MODAL_DATA mutation
'
,
done
=>
{
const
state
=
initialState
;
const
vulnerability
=
mockDataVulnerabilities
[
0
];
testAction
(
actions
.
openModal
,
{
vulnerability
},
state
,
[
{
type
:
types
.
SET_MODAL_DATA
,
payload
:
{
vulnerability
},
},
],
[],
done
,
);
});
});
describe
(
'
issue creation
'
,
()
=>
{
describe
(
'
createIssue
'
,
()
=>
{
const
vulnerability
=
mockDataVulnerabilities
[
0
];
const
data
=
{
issue_url
:
'
fakepath.html
'
};
let
mock
;
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
});
afterEach
(()
=>
{
mock
.
restore
();
});
describe
(
'
on success
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onPost
(
vulnerability
.
vulnerability_feedback_url
).
replyOnce
(
200
,
{
data
});
});
it
(
'
should dispatch the request and success actions
'
,
done
=>
{
testAction
(
actions
.
createIssue
,
{
vulnerability
},
{},
[],
[
{
type
:
'
requestCreateIssue
'
},
{
type
:
'
receiveCreateIssueSuccess
'
,
payload
:
{
data
},
},
],
done
,
);
});
});
describe
(
'
on error
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onPost
(
vulnerability
.
vulnerability_feedback_url
).
replyOnce
(
404
,
{});
});
it
(
'
should dispatch the request and error actions
'
,
done
=>
{
const
flashError
=
false
;
testAction
(
actions
.
createIssue
,
{
vulnerability
,
flashError
},
{},
[],
[
{
type
:
'
requestCreateIssue
'
},
{
type
:
'
receiveCreateIssueError
'
,
payload
:
{
flashError
}
},
],
done
,
);
});
});
});
describe
(
'
receiveCreateIssueSuccess
'
,
()
=>
{
it
(
'
should commit the success mutation
'
,
done
=>
{
const
state
=
initialState
;
const
endpoint
=
'
fakepath.json
'
;
const
data
=
mockDataVulnerabilities
[
0
]
;
testAction
(
actions
.
setVulnerabilitiesCountEndpoint
,
endpoint
,
actions
.
receiveCreateIssueSuccess
,
{
data
}
,
state
,
[
{
type
:
types
.
SET_VULNERABILITIES_COUNT_ENDPOINT
,
payload
:
endpoint
,
type
:
types
.
RECEIVE_CREATE_ISSUE_SUCCESS
,
payload
:
{
data
}
,
},
],
[],
...
...
@@ -276,4 +380,257 @@ describe('vulnerabilities actions', () => {
);
});
});
describe
(
'
receiveCreateIssueError
'
,
()
=>
{
it
(
'
should commit the error mutation
'
,
done
=>
{
const
state
=
initialState
;
testAction
(
actions
.
receiveCreateIssueError
,
{},
state
,
[{
type
:
types
.
RECEIVE_CREATE_ISSUE_ERROR
}],
[],
done
,
);
});
});
describe
(
'
requestCreateIssue
'
,
()
=>
{
it
(
'
should commit the request mutation
'
,
done
=>
{
const
state
=
initialState
;
testAction
(
actions
.
requestCreateIssue
,
{},
state
,
[{
type
:
types
.
REQUEST_CREATE_ISSUE
}],
[],
done
,
);
});
});
});
describe
(
'
vulnerability dismissal
'
,
()
=>
{
describe
(
'
dismissVulnerability
'
,
()
=>
{
const
vulnerability
=
mockDataVulnerabilities
[
0
];
const
data
=
{
vulnerability
};
let
mock
;
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
});
afterEach
(()
=>
{
mock
.
restore
();
});
describe
(
'
on success
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onPost
(
vulnerability
.
vulnerability_feedback_url
).
replyOnce
(
200
,
data
);
});
it
(
'
should dispatch the request and success actions
'
,
done
=>
{
testAction
(
actions
.
dismissVulnerability
,
{
vulnerability
},
{},
[],
[
{
type
:
'
requestDismissVulnerability
'
},
{
type
:
'
receiveDismissVulnerabilitySuccess
'
,
payload
:
{
data
,
id
:
vulnerability
.
id
},
},
],
done
,
);
});
});
describe
(
'
on error
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onPost
(
vulnerability
.
vulnerability_feedback_url
).
replyOnce
(
404
,
{});
});
it
(
'
should dispatch the request and error actions
'
,
done
=>
{
const
flashError
=
false
;
testAction
(
actions
.
dismissVulnerability
,
{
vulnerability
,
flashError
},
{},
[],
[
{
type
:
'
requestDismissVulnerability
'
},
{
type
:
'
receiveDismissVulnerabilityError
'
,
payload
:
{
flashError
:
false
}
},
],
done
,
);
});
});
});
describe
(
'
receiveDismissVulnerabilitySuccess
'
,
()
=>
{
it
(
'
should commit the success mutation
'
,
done
=>
{
const
state
=
initialState
;
const
data
=
mockDataVulnerabilities
[
0
];
testAction
(
actions
.
receiveDismissVulnerabilitySuccess
,
{
data
},
state
,
[
{
type
:
types
.
RECEIVE_DISMISS_VULNERABILITY_SUCCESS
,
payload
:
{
data
},
},
],
[],
done
,
);
});
});
describe
(
'
receiveDismissVulnerabilityError
'
,
()
=>
{
it
(
'
should commit the error mutation
'
,
done
=>
{
const
state
=
initialState
;
testAction
(
actions
.
receiveDismissVulnerabilityError
,
{},
state
,
[{
type
:
types
.
RECEIVE_DISMISS_VULNERABILITY_ERROR
}],
[],
done
,
);
});
});
describe
(
'
requestDismissVulnerability
'
,
()
=>
{
it
(
'
should commit the request mutation
'
,
done
=>
{
const
state
=
initialState
;
testAction
(
actions
.
requestDismissVulnerability
,
{},
state
,
[{
type
:
types
.
REQUEST_DISMISS_VULNERABILITY
}],
[],
done
,
);
});
});
});
describe
(
'
undo vulnerability dismissal
'
,
()
=>
{
describe
(
'
undoDismissal
'
,
()
=>
{
const
vulnerability
=
mockDataVulnerabilities
[
2
];
const
url
=
`
${
vulnerability
.
vulnerability_feedback_url
}
/
${
vulnerability
.
dismissal_feedback
.
id
}
`
;
let
mock
;
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
});
afterEach
(()
=>
{
mock
.
restore
();
});
describe
(
'
on success
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onDelete
(
url
).
replyOnce
(
200
,
{});
});
it
(
'
should dispatch the request and success actions
'
,
done
=>
{
testAction
(
actions
.
undoDismissal
,
{
vulnerability
},
{},
[],
[
{
type
:
'
requestUndoDismissal
'
},
{
type
:
'
receiveUndoDismissalSuccess
'
,
payload
:
{
id
:
vulnerability
.
id
}
},
],
done
,
);
});
});
describe
(
'
on error
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onDelete
(
url
).
replyOnce
(
404
,
{});
});
it
(
'
should dispatch the request and error actions
'
,
done
=>
{
const
flashError
=
false
;
testAction
(
actions
.
undoDismissal
,
{
vulnerability
,
flashError
},
{},
[],
[
{
type
:
'
requestUndoDismissal
'
},
{
type
:
'
receiveUndoDismissalError
'
,
payload
:
{
flashError
:
false
}
},
],
done
,
);
});
});
});
describe
(
'
receiveUndoDismissalSuccess
'
,
()
=>
{
it
(
'
should commit the success mutation
'
,
done
=>
{
const
state
=
initialState
;
const
data
=
mockDataVulnerabilities
[
0
];
testAction
(
actions
.
receiveUndoDismissalSuccess
,
{
data
},
state
,
[
{
type
:
types
.
RECEIVE_UNDO_DISMISSAL_SUCCESS
,
payload
:
{
data
},
},
],
[],
done
,
);
});
});
describe
(
'
receiveUndoDismissalError
'
,
()
=>
{
it
(
'
should commit the error mutation
'
,
done
=>
{
const
state
=
initialState
;
testAction
(
actions
.
receiveUndoDismissalError
,
{},
state
,
[{
type
:
types
.
RECEIVE_UNDO_DISMISSAL_ERROR
}],
[],
done
,
);
});
});
describe
(
'
requestUndoDismissal
'
,
()
=>
{
it
(
'
should commit the request mutation
'
,
done
=>
{
const
state
=
initialState
;
testAction
(
actions
.
requestUndoDismissal
,
{},
state
,
[{
type
:
types
.
REQUEST_UNDO_DISMISSAL
}],
[],
done
,
);
});
});
});
ee/
app/assets/javascripts/security_dashboard/store/modules/vulnerabilities
/mock_data_vulnerabilities.json
→
ee/
spec/javascripts/security_dashboard/store/vulnerabilities/data
/mock_data_vulnerabilities.json
View file @
9041c27c
...
...
@@ -32,6 +32,7 @@
},
"dismissal_feedback"
:
null
,
"issue_feedback"
:
null
,
"vulnerability_feedback_url"
:
"https://example.com/vulnerability_feedback"
,
"description"
:
"The cipher does not provide data integrity update 1"
,
"solution"
:
"GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result."
,
"location"
:
{
...
...
@@ -81,6 +82,7 @@
},
"dismissal_feedback"
:
null
,
"issue_feedback"
:
null
,
"vulnerability_feedback_url"
:
"https://example.com/vulnerability_feedback"
,
"description"
:
"The cipher does not provide data integrity update 1"
,
"solution"
:
"GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result."
,
"location"
:
{
...
...
@@ -152,6 +154,7 @@
"project_fingerprint"
:
"4e5b6966dd100170b4b1ad599c7058cce91b57b4"
},
"issue_feedback"
:
null
,
"vulnerability_feedback_url"
:
"https://example.com/vulnerability_feedback"
,
"description"
:
"The cipher does not provide data integrity update 1"
,
"solution"
:
"GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result."
,
"location"
:
{
...
...
@@ -224,6 +227,7 @@
"branch"
:
"master"
,
"project_fingerprint"
:
"4e5b6966dd100170b4b1ad599c7058cce91b57b4"
},
"vulnerability_feedback_url"
:
"https://example.com/vulnerability_feedback"
,
"description"
:
"The cipher does not provide data integrity update 1"
,
"solution"
:
"GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result."
,
"location"
:
{
...
...
@@ -318,6 +322,7 @@
"branch"
:
"master"
,
"project_fingerprint"
:
"4e5b6966dd100170b4b1ad599c7058cce91b57b4"
},
"vulnerability_feedback_url"
:
"https://example.com/vulnerability_feedback"
,
"description"
:
"The cipher does not provide data integrity update 1"
,
"solution"
:
"GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result."
,
"location"
:
{
...
...
@@ -367,6 +372,7 @@
},
"dismissal_feedback"
:
null
,
"issue_feedback"
:
null
,
"vulnerability_feedback_url"
:
"https://example.com/vulnerability_feedback"
,
"description"
:
"The cipher does not provide data integrity update 1"
,
"solution"
:
"GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result."
,
"location"
:
{
...
...
ee/
app/assets/javascripts/security_dashboard/store/modules/vulnerabilities
/mock_data_vulnerabilities_count.json
→
ee/
spec/javascripts/security_dashboard/store/vulnerabilities/data
/mock_data_vulnerabilities_count.json
View file @
9041c27c
File moved
ee/spec/javascripts/security_dashboard/store/vulnerabilities/mutations_spec.js
View file @
9041c27c
import
initial
State
from
'
ee/security_dashboard/store/modules/vulnerabilities/state
'
;
import
create
State
from
'
ee/security_dashboard/store/modules/vulnerabilities/state
'
;
import
*
as
types
from
'
ee/security_dashboard/store/modules/vulnerabilities/mutation_types
'
;
import
mutations
from
'
ee/security_dashboard/store/modules/vulnerabilities/mutations
'
;
import
mockData
from
'
./data/mock_data_vulnerabilities.json
'
;
describe
(
'
vulnerabilities module mutations
'
,
()
=>
{
describe
(
'
SET_VULNERABILITIES_ENDPOINT
'
,
()
=>
{
it
(
'
should set `vulnerabilitiesEndpoint` to `fakepath.json`
'
,
()
=>
{
const
state
=
initialState
;
const
state
=
createState
()
;
const
endpoint
=
'
fakepath.json
'
;
mutations
[
types
.
SET_VULNERABILITIES_ENDPOINT
](
state
,
endpoint
);
...
...
@@ -19,7 +20,7 @@ describe('vulnerabilities module mutations', () => {
beforeEach
(()
=>
{
state
=
{
...
initialState
,
...
createState
()
,
hasError
:
true
,
};
mutations
[
types
.
REQUEST_VULNERABILITIES
](
state
);
...
...
@@ -40,10 +41,10 @@ describe('vulnerabilities module mutations', () => {
beforeEach
(()
=>
{
payload
=
{
vulnerabilities
:
[
1
,
2
,
3
,
4
,
5
]
,
vulnerabilities
:
mockData
,
pageInfo
:
{
a
:
1
,
b
:
2
,
c
:
3
},
};
state
=
initialState
;
state
=
createState
()
;
mutations
[
types
.
RECEIVE_VULNERABILITIES_SUCCESS
](
state
,
payload
);
});
...
...
@@ -62,7 +63,7 @@ describe('vulnerabilities module mutations', () => {
describe
(
'
RECEIVE_VULNERABILITIES_ERROR
'
,
()
=>
{
it
(
'
should set `isLoadingVulnerabilities` to `false`
'
,
()
=>
{
const
state
=
initialState
;
const
state
=
createState
()
;
mutations
[
types
.
RECEIVE_VULNERABILITIES_ERROR
](
state
);
...
...
@@ -72,7 +73,7 @@ describe('vulnerabilities module mutations', () => {
describe
(
'
SET_VULNERABILITIES_COUNT_ENDPOINT
'
,
()
=>
{
it
(
'
should set `vulnerabilitiesCountEndpoint` to `fakepath.json`
'
,
()
=>
{
const
state
=
initialState
;
const
state
=
createState
()
;
const
endpoint
=
'
fakepath.json
'
;
mutations
[
types
.
SET_VULNERABILITIES_COUNT_ENDPOINT
](
state
,
endpoint
);
...
...
@@ -86,7 +87,7 @@ describe('vulnerabilities module mutations', () => {
beforeEach
(()
=>
{
state
=
{
...
initialState
,
...
createState
()
,
hasError
:
true
,
};
mutations
[
types
.
REQUEST_VULNERABILITIES_COUNT
](
state
);
...
...
@@ -106,8 +107,8 @@ describe('vulnerabilities module mutations', () => {
let
state
;
beforeEach
(()
=>
{
payload
=
{
a
:
1
,
b
:
2
,
c
:
3
}
;
state
=
initialState
;
payload
=
mockData
;
state
=
createState
()
;
mutations
[
types
.
RECEIVE_VULNERABILITIES_COUNT_SUCCESS
](
state
,
payload
);
});
...
...
@@ -122,11 +123,267 @@ describe('vulnerabilities module mutations', () => {
describe
(
'
RECEIVE_VULNERABILITIES_COUNT_ERROR
'
,
()
=>
{
it
(
'
should set `isLoadingVulnerabilitiesCount` to `false`
'
,
()
=>
{
const
state
=
initialState
;
const
state
=
createState
()
;
mutations
[
types
.
RECEIVE_VULNERABILITIES_COUNT_ERROR
](
state
);
expect
(
state
.
isLoadingVulnerabilitiesCount
).
toBeFalsy
();
});
});
describe
(
'
SET_MODAL_DATA
'
,
()
=>
{
const
vulnerability
=
mockData
[
0
];
let
payload
;
let
state
;
beforeEach
(()
=>
{
state
=
createState
();
payload
=
{
vulnerability
};
mutations
[
types
.
SET_MODAL_DATA
](
state
,
payload
);
});
it
(
'
should set the modal title
'
,
()
=>
{
expect
(
state
.
modal
.
title
).
toEqual
(
vulnerability
.
name
);
});
it
(
'
should set the modal description
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
description
.
value
).
toEqual
(
vulnerability
.
description
);
});
it
(
'
should set the modal project
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
project
.
value
).
toEqual
(
vulnerability
.
project
.
full_name
);
expect
(
state
.
modal
.
data
.
project
.
url
).
toEqual
(
vulnerability
.
project
.
full_path
);
});
it
(
'
should set the modal file
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
file
.
value
).
toEqual
(
vulnerability
.
location
.
file
);
});
it
(
'
should set the modal identifiers
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
identifiers
.
value
).
toEqual
(
vulnerability
.
identifiers
);
});
it
(
'
should set the modal severity
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
severity
.
value
).
toEqual
(
vulnerability
.
severity
);
});
it
(
'
should set the modal confidence
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
confidence
.
value
).
toEqual
(
vulnerability
.
confidence
);
});
it
(
'
should set the modal solution
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
solution
.
value
).
toEqual
(
vulnerability
.
solution
);
});
it
(
'
should set the modal links
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
links
.
value
).
toEqual
(
vulnerability
.
links
);
});
it
(
'
should set the modal instances
'
,
()
=>
{
expect
(
state
.
modal
.
data
.
instances
.
value
).
toEqual
(
vulnerability
.
instances
);
});
it
(
'
should set the modal vulnerability
'
,
()
=>
{
expect
(
state
.
modal
.
vulnerability
).
toEqual
(
vulnerability
);
});
});
describe
(
'
REQUEST_CREATE_ISSUE
'
,
()
=>
{
let
state
;
beforeEach
(()
=>
{
state
=
createState
();
mutations
[
types
.
REQUEST_CREATE_ISSUE
](
state
);
});
it
(
'
should set isCreatingIssue to true
'
,
()
=>
{
expect
(
state
.
isCreatingIssue
).
toBe
(
true
);
});
it
(
'
should set isCreatingNewIssue in the modal data to true
'
,
()
=>
{
expect
(
state
.
modal
.
isCreatingNewIssue
).
toBe
(
true
);
});
it
(
'
should nullify the error state on the modal
'
,
()
=>
{
expect
(
state
.
modal
.
error
).
toBeNull
();
});
});
describe
(
'
RECEIVE_CREATE_ISSUE_SUCCESS
'
,
()
=>
{
it
(
'
should fire the visitUrl function on the issue URL
'
,
()
=>
{
const
state
=
createState
();
const
payload
=
{
issue_url
:
'
fakepath.html
'
};
const
visitUrl
=
spyOnDependency
(
mutations
,
'
visitUrl
'
);
mutations
[
types
.
RECEIVE_CREATE_ISSUE_SUCCESS
](
state
,
payload
);
expect
(
visitUrl
).
toHaveBeenCalledWith
(
payload
.
issue_url
);
});
});
describe
(
'
RECEIVE_CREATE_ISSUE_ERROR
'
,
()
=>
{
let
state
;
beforeEach
(()
=>
{
state
=
createState
();
mutations
[
types
.
RECEIVE_CREATE_ISSUE_ERROR
](
state
);
});
it
(
'
should set isCreatingIssue to false
'
,
()
=>
{
expect
(
state
.
isCreatingIssue
).
toBe
(
false
);
});
it
(
'
should set isCreatingNewIssue in the modal data to false
'
,
()
=>
{
expect
(
state
.
modal
.
isCreatingNewIssue
).
toBe
(
false
);
});
it
(
'
should set the error state on the modal
'
,
()
=>
{
expect
(
state
.
modal
.
error
).
toEqual
(
'
There was an error creating the issue
'
);
});
});
describe
(
'
REQUEST_DISMISS_VULNERABILITY
'
,
()
=>
{
let
state
;
beforeEach
(()
=>
{
state
=
createState
();
mutations
[
types
.
REQUEST_DISMISS_VULNERABILITY
](
state
);
});
it
(
'
should set isDismissingVulnerability to true
'
,
()
=>
{
expect
(
state
.
isDismissingVulnerability
).
toBe
(
true
);
});
it
(
'
should set isDismissingVulnerability in the modal data to true
'
,
()
=>
{
expect
(
state
.
modal
.
isDismissingVulnerability
).
toBe
(
true
);
});
it
(
'
should nullify the error state on the modal
'
,
()
=>
{
expect
(
state
.
modal
.
error
).
toBeNull
();
});
});
describe
(
'
RECEIVE_DISMISS_VULNERABILITY_SUCCESS
'
,
()
=>
{
let
state
;
let
payload
;
let
vulnerability
;
let
data
;
beforeEach
(()
=>
{
state
=
createState
();
state
.
vulnerabilities
=
mockData
;
[
vulnerability
]
=
mockData
;
data
=
{
name
:
'
dismissal feedback
'
};
payload
=
{
id
:
vulnerability
.
id
,
data
};
mutations
[
types
.
RECEIVE_DISMISS_VULNERABILITY_SUCCESS
](
state
,
payload
);
});
it
(
'
should set the dismissal feedback on the passed vulnerability
'
,
()
=>
{
expect
(
vulnerability
.
dismissal_feedback
).
toEqual
(
data
);
});
it
(
'
should set isDismissingVulnerability to false
'
,
()
=>
{
expect
(
state
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
should set isDismissingVulnerability on the modal to false
'
,
()
=>
{
expect
(
state
.
modal
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
shoulfd set isDissmissed on the modal vulnerability to be true
'
,
()
=>
{
expect
(
state
.
modal
.
vulnerability
.
isDismissed
).
toBe
(
true
);
});
});
describe
(
'
RECEIVE_DISMISS_VULNERABILITY_ERROR
'
,
()
=>
{
let
state
;
beforeEach
(()
=>
{
state
=
createState
();
mutations
[
types
.
RECEIVE_DISMISS_VULNERABILITY_ERROR
](
state
);
});
it
(
'
should set isDismissingVulnerability to false
'
,
()
=>
{
expect
(
state
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
should set isDismissingVulnerability in the modal data to false
'
,
()
=>
{
expect
(
state
.
modal
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
should set the error state on the modal
'
,
()
=>
{
expect
(
state
.
modal
.
error
).
toEqual
(
'
There was an error dismissing the vulnerability.
'
);
});
});
describe
(
'
REQUEST_UNDO_DISMISSAL
'
,
()
=>
{
let
state
;
beforeEach
(()
=>
{
state
=
createState
();
mutations
[
types
.
REQUEST_UNDO_DISMISSAL
](
state
);
});
it
(
'
should set isDismissingVulnerability to true
'
,
()
=>
{
expect
(
state
.
isDismissingVulnerability
).
toBe
(
true
);
});
it
(
'
should set isDismissingVulnerability in the modal data to true
'
,
()
=>
{
expect
(
state
.
modal
.
isDismissingVulnerability
).
toBe
(
true
);
});
it
(
'
should nullify the error state on the modal
'
,
()
=>
{
expect
(
state
.
modal
.
error
).
toBeNull
();
});
});
describe
(
'
RECEIVE_UNDO_DISMISSAL_SUCCESS
'
,
()
=>
{
let
state
;
let
payload
;
let
vulnerability
;
beforeEach
(()
=>
{
state
=
createState
();
state
.
vulnerabilities
=
mockData
;
[
vulnerability
]
=
mockData
;
payload
=
{
id
:
vulnerability
.
id
};
mutations
[
types
.
RECEIVE_UNDO_DISMISSAL_SUCCESS
](
state
,
payload
);
});
it
(
'
should set the dismissal feedback on the passed vulnerability
'
,
()
=>
{
expect
(
vulnerability
.
dismissal_feedback
).
toBeNull
();
});
it
(
'
should set isDismissingVulnerability to false
'
,
()
=>
{
expect
(
state
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
should set isDismissingVulnerability on the modal to false
'
,
()
=>
{
expect
(
state
.
modal
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
should set isDissmissed on the modal vulnerability to be false
'
,
()
=>
{
expect
(
state
.
modal
.
vulnerability
.
isDismissed
).
toBe
(
false
);
});
});
describe
(
'
RECEIVE_UNDO_DISMISSAL_ERROR
'
,
()
=>
{
let
state
;
beforeEach
(()
=>
{
state
=
createState
();
mutations
[
types
.
RECEIVE_UNDO_DISMISSAL_ERROR
](
state
);
});
it
(
'
should set isDismissingVulnerability to false
'
,
()
=>
{
expect
(
state
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
should set isDismissingVulnerability in the modal data to false
'
,
()
=>
{
expect
(
state
.
modal
.
isDismissingVulnerability
).
toBe
(
false
);
});
it
(
'
should set the error state on the modal
'
,
()
=>
{
expect
(
state
.
modal
.
error
).
toEqual
(
'
There was an error undoing the dismissal.
'
);
});
});
});
locale/gitlab.pot
View file @
9041c27c
...
...
@@ -6661,13 +6661,13 @@ msgstr ""
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
msgid "Reports|
Clas
s"
msgid "Reports|
Action
s"
msgstr ""
msgid "Reports|C
onfidence
"
msgid "Reports|C
lass
"
msgstr ""
msgid "Reports|
Dismiss Vulnerability
"
msgid "Reports|
Confidence
"
msgstr ""
msgid "Reports|Execution time"
...
...
@@ -6676,12 +6676,6 @@ msgstr ""
msgid "Reports|Failure"
msgstr ""
msgid "Reports|More info"
msgstr ""
msgid "Reports|New Issue"
msgstr ""
msgid "Reports|Severity"
msgstr ""
...
...
@@ -7017,12 +7011,39 @@ msgstr ""
msgid "Security Reports|At this time, the security dashboard only supports SAST."
msgstr ""
msgid "Security Reports|Dismiss Vulnerability"
msgstr ""
msgid "Security Reports|More info"
msgstr ""
msgid "Security Reports|New Issue"
msgstr ""
msgid "Security Reports|Security Dashboard Documentation"
msgstr ""
msgid "Security Reports|There was an error creating the issue."
msgstr ""
msgid "Security Reports|There was an error dismissing the issue."
msgstr ""
msgid "Security Reports|There was an error dismissing the vulnerability."
msgstr ""
msgid "Security Reports|There was an error fetching the dashboard. Please try again in a few moments or contact your support team."
msgstr ""
msgid "Security Reports|There was an error undoing the dismissal."
msgstr ""
msgid "Security Reports|There was an error undoing this dismissal."
msgstr ""
msgid "Security Reports|Undo Dismissal"
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
...
...
@@ -8696,6 +8717,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
msgid "Vulnerability|Confidence"
msgstr ""
msgid "Vulnerability|Description"
msgstr ""
msgid "Vulnerability|File"
msgstr ""
msgid "Vulnerability|Identifiers"
msgstr ""
msgid "Vulnerability|Instances"
msgstr ""
msgid "Vulnerability|Links"
msgstr ""
msgid "Vulnerability|Project"
msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
msgid "Vulnerability|Solution"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
...
...
@@ -9353,6 +9401,9 @@ msgstr ""
msgid "from"
msgstr ""
msgid "help"
msgstr ""
msgid "here"
msgstr ""
...
...
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