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
09340785
Commit
09340785
authored
Oct 22, 2021
by
Daniel Tian
Committed by
Savas Vedova
Oct 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new group vulnerability report and vulnerability counts components
parent
a42a6d5e
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
244 additions
and
1 deletion
+244
-1
ee/app/assets/javascripts/security_dashboard/components/group/vulnerability_report_development.vue
...ard/components/group/vulnerability_report_development.vue
+46
-0
ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_counts.vue
...rity_dashboard/components/shared/vulnerability_counts.vue
+52
-0
ee/app/assets/javascripts/security_dashboard/vulnerability_report_init.js
...vascripts/security_dashboard/vulnerability_report_init.js
+7
-1
ee/app/assets/stylesheets/pages/security/vulnerability_report.scss
...sets/stylesheets/pages/security/vulnerability_report.scss
+6
-0
ee/spec/frontend/security_dashboard/components/group/vulnerability_report_development_spec.js
...components/group/vulnerability_report_development_spec.js
+72
-0
ee/spec/frontend/security_dashboard/components/shared/vulnerability_counts_spec.js
..._dashboard/components/shared/vulnerability_counts_spec.js
+61
-0
No files found.
ee/app/assets/javascripts/security_dashboard/components/group/vulnerability_report_development.vue
0 → 100644
View file @
09340785
<
script
>
import
countsQuery
from
'
ee/security_dashboard/graphql/queries/vulnerability_severities_count.query.graphql
'
;
import
createFlash
from
'
~/flash
'
;
import
{
s__
}
from
'
~/locale
'
;
import
VulnerabilityCounts
from
'
../shared/vulnerability_counts.vue
'
;
export
default
{
components
:
{
VulnerabilityCounts
},
inject
:
[
'
groupFullPath
'
],
data
()
{
return
{
counts
:
{},
};
},
apollo
:
{
counts
:
{
query
:
countsQuery
,
variables
()
{
return
{
fullPath
:
this
.
groupFullPath
,
isGroup
:
true
,
};
},
update
({
group
})
{
return
group
.
vulnerabilitySeveritiesCount
;
},
error
()
{
createFlash
({
message
:
s__
(
'
SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again.
'
,
),
});
},
},
},
computed
:
{
isCountsLoading
()
{
return
this
.
$apollo
.
queries
.
counts
.
loading
;
},
},
};
</
script
>
<
template
>
<vulnerability-counts
:counts=
"counts"
:is-loading=
"isCountsLoading"
/>
</
template
>
ee/app/assets/javascripts/security_dashboard/components/shared/vulnerability_counts.vue
0 → 100644
View file @
09340785
<
script
>
import
{
GlCard
,
GlSkeletonLoading
}
from
'
@gitlab/ui
'
;
import
SeverityBadge
from
'
ee/vue_shared/security_reports/components/severity_badge.vue
'
;
import
{
SEVERITIES
}
from
'
ee/security_dashboard/store/modules/vulnerabilities/constants
'
;
export
default
{
components
:
{
GlCard
,
GlSkeletonLoading
,
SeverityBadge
},
props
:
{
counts
:
{
type
:
Object
,
required
:
true
,
},
isLoading
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
severityCounts
()
{
return
SEVERITIES
.
map
((
severity
)
=>
({
severity
,
count
:
this
.
counts
[
severity
]
||
0
,
}));
},
},
};
</
script
>
<
template
>
<div
class=
"vulnerability-counts gl-font-weight-bold gl-text-center"
>
<gl-card
v-for=
"
{ severity, count } in severityCounts"
:key="severity"
:data-testid="severity"
header-class="gl-p-3"
body-class="gl-font-size-h2"
>
<template
#header
>
<severity-badge
:severity=
"severity"
class=
"gl-text-center!"
/>
</
template
>
<
template
#default
>
<gl-skeleton-loading
v-if=
"isLoading"
:lines=
"1"
class=
"gl-display-flex gl-align-items-center"
/>
<span
v-else
>
{{
count
}}
</span>
</
template
>
</gl-card>
</div>
</template>
ee/app/assets/javascripts/security_dashboard/vulnerability_report_init.js
View file @
09340785
...
...
@@ -6,6 +6,7 @@ import VulnerabilityReport from './components/shared/vulnerability_report.vue';
import
apolloProvider
from
'
./graphql/provider
'
;
import
createRouter
from
'
./router
'
;
import
createStore
from
'
./store
'
;
import
GroupVulnerabilityReport
from
'
./components/group/vulnerability_report_development.vue
'
;
export
default
(
el
,
dashboardType
)
=>
{
if
(
!
el
)
{
...
...
@@ -100,6 +101,11 @@ export default (el, dashboardType) => {
const
router
=
createRouter
();
const
store
=
createStore
({
dashboardType
});
const
component
=
gon
.
features
?.
operationalVulnerabilities
&&
dashboardType
===
DASHBOARD_TYPES
.
GROUP
?
GroupVulnerabilityReport
:
VulnerabilityReport
;
return
new
Vue
({
el
,
store
,
...
...
@@ -107,7 +113,7 @@ export default (el, dashboardType) => {
apolloProvider
,
provide
,
render
(
createElement
)
{
return
createElement
(
VulnerabilityRepor
t
);
return
createElement
(
componen
t
);
},
});
};
ee/app/assets/stylesheets/pages/security/vulnerability_report.scss
View file @
09340785
...
...
@@ -3,3 +3,9 @@
grid-template-columns
:
repeat
(
auto-fill
,
minmax
(
12rem
,
1fr
));
grid-gap
:
$gl-spacing-scale-5
;
}
.vulnerability-counts
{
@include
gl-display-grid
;
grid-template-columns
:
repeat
(
auto-fit
,
minmax
(
7rem
,
1fr
));
grid-gap
:
$gl-spacing-scale-7
;
}
ee/spec/frontend/security_dashboard/components/group/vulnerability_report_development_spec.js
0 → 100644
View file @
09340785
import
{
createLocalVue
}
from
'
@vue/test-utils
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
{
nextTick
}
from
'
vue
'
;
import
VulnerabilityReportDevelopment
from
'
ee/security_dashboard/components/group/vulnerability_report_development.vue
'
;
import
VulnerabilityCounts
from
'
ee/security_dashboard/components/shared/vulnerability_counts.vue
'
;
import
{
shallowMountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
countsQuery
from
'
ee/security_dashboard/graphql/queries/vulnerability_severities_count.query.graphql
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
const
localVue
=
createLocalVue
();
localVue
.
use
(
VueApollo
);
const
counts
=
{
critical
:
1
,
high
:
2
,
info
:
3
,
low
:
4
,
medium
:
5
,
unknown
:
6
};
const
groupFullPath
=
'
path
'
;
const
countsRequestHandler
=
jest
.
fn
().
mockResolvedValue
({
data
:
{
group
:
{
vulnerabilitySeveritiesCount
:
counts
,
},
},
});
describe
(
'
Vulnerability counts component
'
,
()
=>
{
let
wrapper
;
const
createWrapper
=
({
queries
})
=>
{
wrapper
=
shallowMountExtended
(
VulnerabilityReportDevelopment
,
{
localVue
,
apolloProvider
:
createMockApollo
(
queries
),
provide
:
{
groupFullPath
},
});
};
const
findVulnerabilityCounts
=
()
=>
wrapper
.
findComponent
(
VulnerabilityCounts
);
afterEach
(()
=>
{
wrapper
.
destroy
();
countsRequestHandler
.
mockClear
();
});
describe
(
'
vulnerability counts query
'
,
()
=>
{
it
(
'
calls the counts query once with the expected data
'
,
()
=>
{
createWrapper
({
queries
:
[[
countsQuery
,
countsRequestHandler
]]
});
expect
(
countsRequestHandler
).
toHaveBeenCalledTimes
(
1
);
expect
(
countsRequestHandler
).
toHaveBeenCalledWith
(
expect
.
objectContaining
({
isGroup
:
true
,
fullPath
:
groupFullPath
,
}),
);
});
it
(
'
passes the isLoading prop with the expected values
'
,
async
()
=>
{
createWrapper
({
queries
:
[[
countsQuery
,
countsRequestHandler
]]
});
expect
(
findVulnerabilityCounts
().
props
(
'
isLoading
'
)).
toBe
(
true
);
await
nextTick
();
expect
(
findVulnerabilityCounts
().
props
(
'
isLoading
'
)).
toBe
(
false
);
});
it
(
'
passes the results of the counts query to the vulnerability counts component
'
,
async
()
=>
{
createWrapper
({
queries
:
[[
countsQuery
,
countsRequestHandler
]]
});
await
nextTick
();
expect
(
findVulnerabilityCounts
().
props
(
'
counts
'
)).
toMatchObject
(
counts
);
});
});
});
ee/spec/frontend/security_dashboard/components/shared/vulnerability_counts_spec.js
0 → 100644
View file @
09340785
import
{
GlCard
,
GlSkeletonLoading
}
from
'
@gitlab/ui
'
;
import
VulnerabilityCounts
from
'
ee/security_dashboard/components/shared/vulnerability_counts.vue
'
;
import
{
mountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
{
CRITICAL
,
HIGH
,
MEDIUM
,
INFO
,
LOW
,
UNKNOWN
,
SEVERITIES
,
}
from
'
ee/security_dashboard/store/modules/vulnerabilities/constants
'
;
import
{
SEVERITY_LEVELS
}
from
'
ee/security_dashboard/store/constants
'
;
describe
(
'
Vulnerability counts component
'
,
()
=>
{
let
wrapper
;
const
createWrapper
=
(
props
)
=>
{
wrapper
=
mountExtended
(
VulnerabilityCounts
,
{
propsData
:
props
,
});
};
const
findCards
=
()
=>
wrapper
.
findAllComponents
(
GlCard
);
const
findCardWithSeverity
=
(
severity
)
=>
wrapper
.
findByTestId
(
severity
);
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
should show a skeleton loading component for each count when the isLoading prop is true
'
,
()
=>
{
createWrapper
({
isLoading
:
true
,
counts
:
{}
});
findCards
().
wrappers
.
forEach
((
card
)
=>
{
expect
(
card
.
findComponent
(
GlSkeletonLoading
).
exists
()).
toBe
(
true
);
});
});
it
(
'
should show a card for each severity with the correct count
'
,
()
=>
{
const
counts
=
{
[
CRITICAL
]:
1
,
[
HIGH
]:
2
,
[
MEDIUM
]:
3
,
[
LOW
]:
4
,
[
INFO
]:
5
,
[
UNKNOWN
]:
6
};
createWrapper
({
counts
});
// Check that there are exactly the same number of cards as there are severities.
expect
(
findCards
()).
toHaveLength
(
Object
.
keys
(
counts
).
length
);
Object
.
entries
(
counts
).
forEach
(([
severity
,
count
])
=>
{
const
cardText
=
findCardWithSeverity
(
severity
).
text
();
expect
(
cardText
).
toContain
(
SEVERITY_LEVELS
[
severity
]);
expect
(
cardText
).
toContain
(
count
);
});
});
it
(
'
should show zero for the count when there is no value for that severity
'
,
()
=>
{
createWrapper
({
counts
:
{}
});
SEVERITIES
.
forEach
((
severity
)
=>
{
expect
(
findCardWithSeverity
(
severity
).
text
()).
toContain
(
'
0
'
);
});
});
});
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