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
d599ea23
Commit
d599ea23
authored
Mar 31, 2020
by
Savas Vedova
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a GraphQL based counts component
Refactor the component to support either GQL or Vuex
parent
61a6f61d
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
335 additions
and
77 deletions
+335
-77
ee/app/assets/javascripts/security_dashboard/components/first_class_project_dashboard.vue
...ty_dashboard/components/first_class_project_dashboard.vue
+5
-0
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_vuex.vue
...security_dashboard/components/security_dashboard_vuex.vue
+1
-1
ee/app/assets/javascripts/security_dashboard/components/vulnerability_count_list.vue
...ecurity_dashboard/components/vulnerability_count_list.vue
+35
-48
ee/app/assets/javascripts/security_dashboard/components/vulnerability_count_list_layout.vue
..._dashboard/components/vulnerability_count_list_layout.vue
+69
-0
ee/app/assets/javascripts/security_dashboard/components/vulnerability_count_list_vuex.vue
...ty_dashboard/components/vulnerability_count_list_vuex.vue
+22
-0
ee/app/assets/javascripts/security_dashboard/graphql/project_vulnerability_severities_count.graphql
...rd/graphql/project_vulnerability_severities_count.graphql
+10
-0
ee/spec/frontend/security_dashboard/components/security_dashboard_vuex_spec.js
...rity_dashboard/components/security_dashboard_vuex_spec.js
+1
-1
ee/spec/frontend/security_dashboard/components/vulnerability_count_list_layout_spec.js
...hboard/components/vulnerability_count_list_layout_spec.js
+73
-0
ee/spec/frontend/security_dashboard/components/vulnerability_count_list_spec.js
...ity_dashboard/components/vulnerability_count_list_spec.js
+58
-24
ee/spec/frontend/security_dashboard/components/vulnerability_count_list_vuex_spec.js
...ashboard/components/vulnerability_count_list_vuex_spec.js
+61
-0
locale/gitlab.pot
locale/gitlab.pot
+0
-3
No files found.
ee/app/assets/javascripts/security_dashboard/components/first_class_project_dashboard.vue
View file @
d599ea23
<
script
>
import
SecurityDashboardLayout
from
'
ee/security_dashboard/components/security_dashboard_layout.vue
'
;
import
VulnerabilitiesCountList
from
'
ee/security_dashboard/components/vulnerability_count_list.vue
'
;
import
ProjectVulnerabilitiesApp
from
'
ee/vulnerabilities/components/project_vulnerabilities_app.vue
'
;
export
default
{
components
:
{
SecurityDashboardLayout
,
ProjectVulnerabilitiesApp
,
VulnerabilitiesCountList
,
},
props
:
{
dashboardDocumentation
:
{
...
...
@@ -26,6 +28,9 @@ export default {
<
template
>
<security-dashboard-layout>
<template
#header
>
<vulnerabilities-count-list
:project-full-path=
"projectFullPath"
/>
</
template
>
<project-vulnerabilities-app
:dashboard-documentation=
"dashboardDocumentation"
:empty-state-svg-path=
"emptyStateSvgPath"
...
...
ee/app/assets/javascripts/security_dashboard/components/security_dashboard_vuex.vue
View file @
d599ea23
...
...
@@ -6,7 +6,7 @@ import Filters from './filters.vue';
import
SecurityDashboardLayout
from
'
./security_dashboard_layout.vue
'
;
import
SecurityDashboardTable
from
'
./security_dashboard_table.vue
'
;
import
VulnerabilityChart
from
'
./vulnerability_chart.vue
'
;
import
VulnerabilityCountList
from
'
./vulnerability_count_list.vue
'
;
import
VulnerabilityCountList
from
'
./vulnerability_count_list
_vuex
.vue
'
;
import
VulnerabilitySeverity
from
'
./vulnerability_severity.vue
'
;
import
LoadingError
from
'
./loading_error.vue
'
;
...
...
ee/app/assets/javascripts/security_dashboard/components/vulnerability_count_list.vue
View file @
d599ea23
<
script
>
import
{
mapGetters
,
mapState
}
from
'
vuex
'
;
import
VulnerabilityCount
from
'
./vulnerability_count.vue
'
;
import
{
CRITICAL
,
HIGH
,
MEDIUM
,
LOW
}
from
'
../store/modules/vulnerabilities/constants
'
;
const
SEVERITIES
=
[
CRITICAL
,
HIGH
,
MEDIUM
,
LOW
];
import
vulnerabilitySeveritiesCountQuery
from
'
../graphql/project_vulnerability_severities_count.graphql
'
;
import
VulnerabilityCountListLayout
from
'
./vulnerability_count_list_layout.vue
'
;
export
default
{
components
:
{
VulnerabilityCount
,
VulnerabilityCountListLayout
,
},
props
:
{
projectFullPath
:
{
type
:
String
,
required
:
true
,
},
},
data
:
()
=>
({
queryError
:
false
,
vulnerabilitiesCount
:
{},
}),
computed
:
{
...
mapGetters
(
'
vulnerabilities
'
,
[
'
dashboardCountError
'
,
'
dashboardError
'
]),
...
mapState
(
'
vulnerabilities
'
,
[
'
isLoadingVulnerabilitiesCount
'
,
'
vulnerabilitiesCount
'
]),
counts
()
{
return
SEVERITIES
.
map
(
severity
=>
{
const
count
=
this
.
vulnerabilitiesCount
[
severity
]
||
0
;
return
{
severity
,
count
};
});
isLoading
()
{
return
this
.
$apollo
.
queries
.
vulnerabilitiesCount
.
loading
;
},
},
apollo
:
{
vulnerabilitiesCount
:
{
query
:
vulnerabilitySeveritiesCountQuery
,
variables
()
{
return
{
fullPath
:
this
.
projectFullPath
};
},
update
:
({
project
})
=>
project
.
vulnerabilitySeveritiesCount
,
result
()
{
this
.
queryError
=
false
;
},
error
()
{
this
.
queryError
=
true
;
},
},
},
};
</
script
>
<
template
>
<div
class=
"vulnerabilities-count-list mb-5 mt-4"
>
<div
class=
"flash-container"
>
<div
v-if=
"dashboardError"
class=
"flash-alert"
>
<div
class=
"flash-text container-fluid container-limited limit-container-width"
>
{{
s__
(
'
Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again.
'
,
)
}}
</div>
</div>
</div>
<div
class=
"row"
>
<div
v-for=
"count in counts"
:key=
"count.severity"
class=
"col-md col-sm-6 js-count"
>
<vulnerability-count
:severity=
"count.severity"
:count=
"count.count"
:is-loading=
"isLoadingVulnerabilitiesCount"
/>
</div>
</div>
<div
class=
"flash-container"
>
<div
v-if=
"dashboardCountError"
class=
"flash-alert"
>
<div
class=
"flash-text container-fluid container-limited limit-container-width"
>
{{
s__
(
'
Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again.
'
,
)
}}
</div>
</div>
</div>
</div>
<vulnerability-count-list-layout
:show-error=
"queryError"
:is-loading=
"isLoading"
:vulnerabilities-count=
"vulnerabilitiesCount"
/>
</
template
>
ee/app/assets/javascripts/security_dashboard/components/vulnerability_count_list_layout.vue
0 → 100644
View file @
d599ea23
<
script
>
import
{
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
CRITICAL
,
HIGH
,
MEDIUM
,
LOW
}
from
'
../store/modules/vulnerabilities/constants
'
;
import
VulnerabilityCount
from
'
./vulnerability_count.vue
'
;
const
SEVERITIES
=
[
CRITICAL
,
HIGH
,
MEDIUM
,
LOW
];
export
default
{
components
:
{
VulnerabilityCount
,
GlAlert
,
},
props
:
{
showError
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isLoading
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
vulnerabilitiesCount
:
{
type
:
Object
,
required
:
true
,
},
},
data
()
{
return
{
showAlert
:
this
.
showError
,
};
},
computed
:
{
counts
()
{
return
SEVERITIES
.
map
(
severity
=>
({
severity
,
count
:
this
.
vulnerabilitiesCount
[
severity
]
||
0
,
}));
},
},
methods
:
{
onErrorDismiss
()
{
this
.
showAlert
=
false
;
},
},
};
</
script
>
<
template
>
<div
class=
"vulnerabilities-count-list mb-5 mt-4"
>
<gl-alert
v-if=
"showAlert"
class=
"mb-4"
variant=
"danger"
@
dismiss=
"onErrorDismiss"
>
{{
s__
(
'
Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again.
'
,
)
}}
</gl-alert>
<div
class=
"row"
>
<div
v-for=
"count in counts"
:key=
"count.severity"
class=
"col-md col-sm-6"
>
<vulnerability-count
:severity=
"count.severity"
:count=
"count.count"
:is-loading=
"isLoading"
/>
</div>
</div>
</div>
</
template
>
ee/app/assets/javascripts/security_dashboard/components/vulnerability_count_list_vuex.vue
0 → 100644
View file @
d599ea23
<
script
>
import
{
mapGetters
,
mapState
}
from
'
vuex
'
;
import
VulnerabilityCountListLayout
from
'
./vulnerability_count_list_layout.vue
'
;
export
default
{
components
:
{
VulnerabilityCountListLayout
,
},
computed
:
{
...
mapGetters
(
'
vulnerabilities
'
,
[
'
dashboardCountError
'
]),
...
mapState
(
'
vulnerabilities
'
,
[
'
isLoadingVulnerabilitiesCount
'
,
'
vulnerabilitiesCount
'
]),
},
};
</
script
>
<
template
>
<vulnerability-count-list-layout
:show-error=
"dashboardCountError"
:is-loading=
"isLoadingVulnerabilitiesCount"
:vulnerabilities-count=
"vulnerabilitiesCount"
/>
</
template
>
ee/app/assets/javascripts/security_dashboard/graphql/project_vulnerability_severities_count.graphql
0 → 100644
View file @
d599ea23
query
vulnerabilitySeveritiesCount
(
$fullPath
:
ID
!)
{
project
(
fullPath
:
$fullPath
)
{
vulnerabilitySeveritiesCount
{
critical
high
low
medium
}
}
}
ee/spec/frontend/security_dashboard/components/security_dashboard_vuex_spec.js
View file @
d599ea23
...
...
@@ -8,7 +8,7 @@ import IssueModal from 'ee/vue_shared/security_reports/components/modal.vue';
import
SecurityDashboardTable
from
'
ee/security_dashboard/components/security_dashboard_table.vue
'
;
import
SecurityDashboardLayout
from
'
ee/security_dashboard/components/security_dashboard_layout.vue
'
;
import
VulnerabilityChart
from
'
ee/security_dashboard/components/vulnerability_chart.vue
'
;
import
VulnerabilityCountList
from
'
ee/security_dashboard/components/vulnerability_count_list.vue
'
;
import
VulnerabilityCountList
from
'
ee/security_dashboard/components/vulnerability_count_list
_vuex
.vue
'
;
import
VulnerabilitySeverity
from
'
ee/security_dashboard/components/vulnerability_severity.vue
'
;
import
LoadingError
from
'
ee/security_dashboard/components/loading_error.vue
'
;
...
...
ee/spec/frontend/security_dashboard/components/vulnerability_count_list_layout_spec.js
0 → 100644
View file @
d599ea23
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlAlert
}
from
'
@gitlab/ui
'
;
import
VulnerabilityCountListLayout
from
'
ee/security_dashboard/components/vulnerability_count_list_layout.vue
'
;
import
VulnerabilityCount
from
'
ee/security_dashboard/components/vulnerability_count.vue
'
;
describe
(
'
Vulnerabilities count list component
'
,
()
=>
{
let
wrapper
;
const
findAlert
=
()
=>
wrapper
.
find
(
GlAlert
);
const
findVulnerability
=
()
=>
wrapper
.
findAll
(
VulnerabilityCount
);
const
createWrapper
=
({
propsData
}
=
{})
=>
{
return
shallowMount
(
VulnerabilityCountListLayout
,
{
propsData
,
stubs
:
{
GlAlert
,
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
when loading
'
,
()
=>
{
it
(
'
passes the isLoading prop to the counts
'
,
()
=>
{
wrapper
=
createWrapper
({
propsData
:
{
isLoading
:
true
,
vulnerabilitiesCount
:
{}
}
});
findVulnerability
().
wrappers
.
forEach
(
component
=>
{
expect
(
component
.
props
(
'
isLoading
'
)).
toBe
(
true
);
});
});
});
describe
(
'
when loaded and has a list of vulnerability counts
'
,
()
=>
{
const
vulnerabilitiesCount
=
{
critical
:
5
,
medium
:
3
};
beforeEach
(()
=>
{
wrapper
=
createWrapper
({
propsData
:
{
vulnerabilitiesCount
}
});
});
it
(
'
sets the isLoading prop false and passes it down
'
,
()
=>
{
findVulnerability
().
wrappers
.
forEach
(
component
=>
{
expect
(
component
.
props
(
'
isLoading
'
)).
toBe
(
false
);
});
});
it
(
'
shows the counts
'
,
()
=>
{
const
vulnerabilites
=
findVulnerability
();
const
critical
=
vulnerabilites
.
at
(
0
);
const
high
=
vulnerabilites
.
at
(
1
);
const
medium
=
vulnerabilites
.
at
(
2
);
expect
(
critical
.
props
(
'
severity
'
)).
toBe
(
'
critical
'
);
expect
(
critical
.
props
(
'
count
'
)).
toBe
(
5
);
expect
(
high
.
props
(
'
severity
'
)).
toBe
(
'
high
'
);
expect
(
high
.
props
(
'
count
'
)).
toBe
(
0
);
expect
(
medium
.
props
(
'
severity
'
)).
toBe
(
'
medium
'
);
expect
(
medium
.
props
(
'
count
'
)).
toBe
(
3
);
});
});
describe
(
'
when loaded and has an error
'
,
()
=>
{
it
(
'
shows the error message
'
,
()
=>
{
wrapper
=
createWrapper
({
propsData
:
{
showError
:
true
,
vulnerabilitiesCount
:
{}
}
});
expect
(
findAlert
().
text
()).
toBe
(
'
Error fetching the vulnerability counts. Please check your network connection and try again.
'
,
);
});
});
});
ee/spec/frontend/security_dashboard/components/vulnerability_count_list_spec.js
View file @
d599ea23
import
Vue
from
'
vue
'
;
import
component
from
'
ee/security_dashboard/components/vulnerability_count_list.vue
'
;
import
createStore
from
'
ee/security_dashboard/store
'
;
import
{
mountComponentWithStore
}
from
'
helpers/vue_mount_component_helper
'
;
import
{
resetStore
}
from
'
../helpers
'
;
import
mockData
from
'
../store/modules/vulnerabilities/data/mock_data_vulnerabilities_count.json
'
;
describe
(
'
Vulnerability Count List
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
const
store
=
createStore
();
let
vm
;
beforeEach
(()
=>
{
store
.
dispatch
(
'
vulnerabilities/receiveVulnerabilitiesCountSuccess
'
,
{
data
:
mockData
});
vm
=
mountComponentWithStore
(
Component
,
{
store
});
});
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
VulnerabilityCountList
from
'
ee/security_dashboard/components/vulnerability_count_list.vue
'
;
import
VulnerabilityCountListLayout
from
'
ee/security_dashboard/components/vulnerability_count_list_layout.vue
'
;
describe
(
'
Vulnerabilities count list component
'
,
()
=>
{
let
wrapper
;
const
findVulnerabilityLayout
=
()
=>
wrapper
.
find
(
VulnerabilityCountListLayout
);
const
createWrapper
=
({
query
}
=
{})
=>
{
return
shallowMount
(
VulnerabilityCountList
,
{
propsData
:
{
projectFullPath
:
'
/root/security-project
'
,
},
mocks
:
{
$apollo
:
{
queries
:
{
vulnerabilitiesCount
:
query
}
},
},
});
};
afterEach
(()
=>
{
vm
.
$destroy
();
resetStore
(
store
);
wrapper
.
destroy
();
});
it
(
'
should fetch the counts for each severity
'
,
()
=>
{
const
firstCount
=
vm
.
$el
.
querySelector
(
'
.js-count
'
);
describe
(
'
when loading
'
,
()
=>
{
it
(
'
passes down to the loading indicator
'
,
()
=>
{
wrapper
=
createWrapper
({
query
:
{
loading
:
true
}
});
expect
(
findVulnerabilityLayout
().
props
(
'
isLoading
'
)).
toBe
(
true
);
});
});
describe
(
'
when counts are loaded
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createWrapper
({
query
:
{
loading
:
false
}
});
wrapper
.
setData
({
vulnerabilitiesCount
:
{
critical
:
5
,
high
:
3
,
low
:
19
,
},
});
});
expect
(
firstCount
.
textContent
).
toContain
(
'
Critical
'
);
expect
(
firstCount
.
textContent
).
toContain
(
mockData
.
critical
);
it
(
'
sets the loading indicator false and passes it down
'
,
()
=>
{
expect
(
findVulnerabilityLayout
().
props
(
'
isLoading
'
)).
toBe
(
false
);
});
it
(
'
should load the vulnerabilities and pass them down to the layout
'
,
()
=>
{
expect
(
findVulnerabilityLayout
().
props
(
'
vulnerabilitiesCount
'
)).
toEqual
({
critical
:
5
,
high
:
3
,
low
:
19
,
});
});
});
it
(
'
should render a counter for each severity
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-count
'
)).
toHaveLength
(
vm
.
counts
.
length
);
describe
(
'
when there is an error
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createWrapper
({
query
:
{}
});
wrapper
.
setData
({
queryError
:
true
});
});
it
(
'
should tell the layout to display an error
'
,
()
=>
{
expect
(
findVulnerabilityLayout
().
props
(
'
showError
'
)).
toBe
(
true
);
});
});
});
ee/spec/frontend/security_dashboard/components/vulnerability_count_list_vuex_spec.js
0 → 100644
View file @
d599ea23
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
VulnerabilityCountListVuex
from
'
ee/security_dashboard/components/vulnerability_count_list_vuex.vue
'
;
import
createStore
from
'
ee/security_dashboard/store
'
;
import
VulnerabilityCountListLayout
from
'
ee/security_dashboard/components/vulnerability_count_list_layout.vue
'
;
import
{
resetStore
}
from
'
../helpers
'
;
import
mockData
from
'
../store/modules/vulnerabilities/data/mock_data_vulnerabilities_count.json
'
;
describe
(
'
Vulnerability Count List
'
,
()
=>
{
const
projectFullPath
=
'
root/security-imports
'
;
const
store
=
createStore
();
let
wrapper
;
const
findVulnerabilityCountListLayout
=
()
=>
wrapper
.
find
(
VulnerabilityCountListLayout
);
beforeEach
(()
=>
{
wrapper
=
shallowMount
(
VulnerabilityCountListVuex
,
{
store
,
propsData
:
{
projectFullPath
,
},
});
});
afterEach
(()
=>
{
wrapper
.
destroy
();
resetStore
(
store
);
});
it
(
'
should pass down the data to the layout
'
,
()
=>
{
store
.
dispatch
(
'
vulnerabilities/receiveVulnerabilitiesCountSuccess
'
,
{
data
:
mockData
});
return
wrapper
.
vm
.
$nextTick
(()
=>
{
const
layout
=
findVulnerabilityCountListLayout
();
expect
(
layout
.
props
(
'
isLoading
'
)).
toBe
(
false
);
expect
(
layout
.
props
(
'
showError
'
)).
toBe
(
false
);
expect
(
layout
.
props
(
'
vulnerabilitiesCount
'
)).
toEqual
(
mockData
);
});
});
it
(
'
should pass down the loading flag when vulnerabilities are loading
'
,
()
=>
{
store
.
dispatch
(
'
vulnerabilities/requestVulnerabilitiesCount
'
);
return
wrapper
.
vm
.
$nextTick
(()
=>
{
const
layout
=
findVulnerabilityCountListLayout
();
expect
(
layout
.
props
(
'
isLoading
'
)).
toBe
(
true
);
expect
(
layout
.
props
(
'
showError
'
)).
toBe
(
false
);
expect
(
layout
.
props
(
'
vulnerabilitiesCount
'
)).
toEqual
({});
});
});
it
(
'
should pass down the error flag when vulnerabilities are loading
'
,
()
=>
{
store
.
dispatch
(
'
vulnerabilities/receiveVulnerabilitiesCountError
'
);
return
wrapper
.
vm
.
$nextTick
(()
=>
{
const
layout
=
findVulnerabilityCountListLayout
();
expect
(
layout
.
props
(
'
isLoading
'
)).
toBe
(
false
);
expect
(
layout
.
props
(
'
showError
'
)).
toBe
(
true
);
expect
(
layout
.
props
(
'
vulnerabilitiesCount
'
)).
toEqual
({});
});
});
});
locale/gitlab.pot
View file @
d599ea23
...
...
@@ -17631,9 +17631,6 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
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