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
04752cbf
Commit
04752cbf
authored
Apr 20, 2021
by
Savas Vedova
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move project level vulnerabilities to vulnerability report component
parent
cb9173ef
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
181 additions
and
362 deletions
+181
-362
ee/app/assets/javascripts/security_dashboard/components/empty_states/reports_not_configured.vue
...hboard/components/empty_states/reports_not_configured.vue
+2
-8
ee/app/assets/javascripts/security_dashboard/components/first_class_project_security_dashboard.vue
...ard/components/first_class_project_security_dashboard.vue
+0
-95
ee/app/assets/javascripts/security_dashboard/components/project_security_charts.vue
...security_dashboard/components/project_security_charts.vue
+1
-5
ee/app/assets/javascripts/security_dashboard/components/vulnerability_report.vue
...ts/security_dashboard/components/vulnerability_report.vue
+77
-23
ee/app/assets/javascripts/security_dashboard/security_charts_init.js
...ts/javascripts/security_dashboard/security_charts_init.js
+1
-1
ee/app/assets/javascripts/security_dashboard/vulnerability_report_init.js
...vascripts/security_dashboard/vulnerability_report_init.js
+6
-14
ee/spec/frontend/security_dashboard/components/empty_states/reports_not_configured_spec.js
...rd/components/empty_states/reports_not_configured_spec.js
+2
-2
ee/spec/frontend/security_dashboard/components/first_class_project_security_dashboard_spec.js
...components/first_class_project_security_dashboard_spec.js
+0
-212
ee/spec/frontend/security_dashboard/components/project_security_charts_spec.js
...rity_dashboard/components/project_security_charts_spec.js
+1
-1
ee/spec/frontend/security_dashboard/components/vulnerability_report_spec.js
...ecurity_dashboard/components/vulnerability_report_spec.js
+91
-1
No files found.
ee/app/assets/javascripts/security_dashboard/components/empty_states/reports_not_configured.vue
View file @
04752cbf
...
...
@@ -6,13 +6,7 @@ export default {
components
:
{
GlEmptyState
,
},
inject
:
[
'
emptyStateSvgPath
'
,
'
securityConfigurationPath
'
],
props
:
{
helpPath
:
{
type
:
String
,
required
:
true
,
},
},
inject
:
[
'
emptyStateSvgPath
'
,
'
securityConfigurationPath
'
,
'
securityDashboardHelpPath
'
],
i18n
:
{
title
:
s__
(
'
SecurityReports|Monitor vulnerabilities in your project
'
),
description
:
s__
(
...
...
@@ -32,6 +26,6 @@ export default {
:primary-button-text=
"$options.i18n.primaryButtonText"
:primary-button-link=
"securityConfigurationPath"
:secondary-button-text=
"$options.i18n.secondaryButtonText"
:secondary-button-link=
"
h
elpPath"
:secondary-button-link=
"
securityDashboardH
elpPath"
/>
</
template
>
ee/app/assets/javascripts/security_dashboard/components/first_class_project_security_dashboard.vue
deleted
100644 → 0
View file @
cb9173ef
<
script
>
import
Cookies
from
'
js-cookie
'
;
import
glFeatureFlagsMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
AutoFixUserCallout
from
'
./auto_fix_user_callout.vue
'
;
import
CsvExportButton
from
'
./csv_export_button.vue
'
;
import
ReportsNotConfigured
from
'
./empty_states/reports_not_configured.vue
'
;
import
Filters
from
'
./first_class_vulnerability_filters.vue
'
;
import
ProjectPipelineStatus
from
'
./project_pipeline_status.vue
'
;
import
ProjectVulnerabilitiesApp
from
'
./project_vulnerabilities.vue
'
;
import
SecurityDashboardLayout
from
'
./security_dashboard_layout.vue
'
;
import
SurveyRequestBanner
from
'
./survey_request_banner.vue
'
;
import
VulnerabilitiesCountList
from
'
./vulnerability_count_list.vue
'
;
export
default
{
components
:
{
AutoFixUserCallout
,
ProjectPipelineStatus
,
ProjectVulnerabilitiesApp
,
ReportsNotConfigured
,
SecurityDashboardLayout
,
VulnerabilitiesCountList
,
CsvExportButton
,
Filters
,
SurveyRequestBanner
,
},
mixins
:
[
glFeatureFlagsMixin
()],
inject
:
[
'
dashboardDocumentation
'
,
'
autoFixDocumentation
'
,
'
projectFullPath
'
],
props
:
{
securityDashboardHelpPath
:
{
type
:
String
,
required
:
true
,
},
pipeline
:
{
type
:
Object
,
required
:
false
,
default
:
()
=>
({}),
},
},
data
()
{
const
shouldShowAutoFixUserCallout
=
this
.
glFeatures
.
securityAutoFix
&&
!
Cookies
.
get
(
'
auto_fix_user_callout_dismissed
'
);
return
{
filters
:
null
,
shouldShowAutoFixUserCallout
,
};
},
methods
:
{
handleFilterChange
(
filters
)
{
this
.
filters
=
filters
;
},
handleAutoFixUserCalloutClose
()
{
Cookies
.
set
(
'
auto_fix_user_callout_dismissed
'
,
'
true
'
);
this
.
shouldShowAutoFixUserCallout
=
false
;
},
},
};
</
script
>
<
template
>
<div>
<survey-request-banner
class=
"gl-mt-5"
/>
<template
v-if=
"pipeline.id"
>
<auto-fix-user-callout
v-if=
"shouldShowAutoFixUserCallout"
:help-page-path=
"autoFixDocumentation"
@
close=
"handleAutoFixUserCalloutClose"
/>
<security-dashboard-layout>
<template
#header
>
<div
class=
"gl-mt-6 gl-display-flex"
>
<h4
class=
"gl-flex-grow-1 gl-my-0"
>
{{
s__
(
'
SecurityReports|Vulnerability Report
'
)
}}
</h4>
<csv-export-button
/>
</div>
<project-pipeline-status
:pipeline=
"pipeline"
/>
<vulnerabilities-count-list
class=
"gl-mt-6"
:full-path=
"projectFullPath"
:filters=
"filters"
/>
</
template
>
<
template
#sticky
>
<filters
@
filterChange=
"handleFilterChange"
/>
</
template
>
<project-vulnerabilities-app
:dashboard-documentation=
"dashboardDocumentation"
:filters=
"filters"
/>
</security-dashboard-layout>
</template>
<reports-not-configured
v-else
:help-path=
"securityDashboardHelpPath"
/>
</div>
</template>
ee/app/assets/javascripts/security_dashboard/components/project_security_charts.vue
View file @
04752cbf
...
...
@@ -40,10 +40,6 @@ export default {
required
:
false
,
default
:
false
,
},
helpPath
:
{
type
:
String
,
required
:
true
,
},
},
apollo
:
{
trendsByDay
:
{
...
...
@@ -180,7 +176,7 @@ export default {
<
template
>
<security-charts-layout
ref=
"layout"
>
<template
v-if=
"shouldShowEmptyState"
#empty-state
>
<dashboard-not-configured
:help-path=
"helpPath"
/>
<dashboard-not-configured
/>
</
template
>
<
template
v-else-if=
"shouldShowCharts"
#default
>
<gl-line-chart
...
...
ee/app/assets/javascripts/security_dashboard/components/vulnerability_report.vue
View file @
04752cbf
<
script
>
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
GroupSecurityVulnerabilities
from
'
ee/security_dashboard/components/first_class_group_security_dashboard_vulnerabilities.vue
'
;
import
InstanceSecurityVulnerabilities
from
'
ee/security_dashboard/components/first_class_instance_security_dashboard_vulnerabilities.vue
'
;
import
Cookies
from
'
js-cookie
'
;
import
Filters
from
'
ee/security_dashboard/components/first_class_vulnerability_filters.vue
'
;
import
SecurityDashboardLayout
from
'
ee/security_dashboard/components/security_dashboard_layout.vue
'
;
import
{
DASHBOARD_TYPES
}
from
'
ee/security_dashboard/store/constants
'
;
import
{
s__
}
from
'
~/locale
'
;
import
glFeatureFlagsMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
vulnerableProjectsGroupQuery
from
'
../graphql/queries/vulnerable_projects_group.query.graphql
'
;
import
vulnerableProjectsInstanceQuery
from
'
../graphql/queries/vulnerable_projects_instance.query.graphql
'
;
import
AutoFixUserCallout
from
'
./auto_fix_user_callout.vue
'
;
import
CsvExportButton
from
'
./csv_export_button.vue
'
;
import
DashboardNotConfiguredGroup
from
'
./empty_states/group_dashboard_not_configured.vue
'
;
import
DashboardNotConfiguredInstance
from
'
./empty_states/instance_dashboard_not_configured.vue
'
;
import
DashboardNotConfiguredProject
from
'
./empty_states/reports_not_configured.vue
'
;
import
GroupSecurityVulnerabilities
from
'
./first_class_group_security_dashboard_vulnerabilities.vue
'
;
import
InstanceSecurityVulnerabilities
from
'
./first_class_instance_security_dashboard_vulnerabilities.vue
'
;
import
ProjectPipelineStatus
from
'
./project_pipeline_status.vue
'
;
import
ProjectSecurityVulnerabilities
from
'
./project_vulnerabilities.vue
'
;
import
SurveyRequestBanner
from
'
./survey_request_banner.vue
'
;
import
VulnerabilitiesCountList
from
'
./vulnerability_count_list.vue
'
;
export
default
{
components
:
{
AutoFixUserCallout
,
SecurityDashboardLayout
,
GroupSecurityVulnerabilities
,
InstanceSecurityVulnerabilities
,
ProjectSecurityVulnerabilities
,
Filters
,
CsvExportButton
,
SurveyRequestBanner
,
DashboardNotConfiguredGroup
,
DashboardNotConfiguredInstance
,
DashboardNotConfiguredProject
,
ProjectPipelineStatus
,
GlLoadingIcon
,
VulnerabilitiesCountList
,
},
inject
:
[
'
groupFullPath
'
,
'
dashboardType
'
],
mixins
:
[
glFeatureFlagsMixin
()],
inject
:
[
'
groupFullPath
'
,
'
projectFullPath
'
,
'
dashboardType
'
,
'
dashboardDocumentation
'
,
'
autoFixDocumentation
'
,
'
projectFullPath
'
,
],
props
:
{
pipeline
:
{
type
:
Object
,
required
:
false
,
default
:
()
=>
({}),
},
},
queries
:
{
[
DASHBOARD_TYPES
.
GROUP
]:
vulnerableProjectsGroupQuery
,
[
DASHBOARD_TYPES
.
INSTANCE
]:
vulnerableProjectsInstanceQuery
,
...
...
@@ -51,30 +76,49 @@ export default {
},
},
data
()
{
const
shouldShowAutoFixUserCallout
=
this
.
dashboardType
===
DASHBOARD_TYPES
.
PROJECT
&&
this
.
glFeatures
.
securityAutoFix
&&
!
Cookies
.
get
(
this
.
$options
.
autoFixUserCalloutCookieName
);
return
{
filters
:
null
,
projects
:
[],
shouldShowAutoFixUserCallout
,
};
},
computed
:
{
projectsWereFetched
()
{
return
!
this
.
$apollo
.
queries
.
projects
?.
loading
;
},
fullPath
()
{
return
this
.
groupFullPath
||
this
.
projectFullPath
;
},
isGroup
()
{
return
this
.
dashboardType
===
DASHBOARD_TYPES
.
GROUP
;
},
isInstance
()
{
return
this
.
dashboardType
===
DASHBOARD_TYPES
.
INSTANCE
;
},
hasNoProjects
()
{
return
this
.
projects
.
length
===
0
&&
this
.
projectsWereFetched
;
isProject
()
{
return
this
.
dashboardType
===
DASHBOARD_TYPES
.
PROJECT
;
},
isDashboardConfigured
()
{
return
this
.
isProject
?
Boolean
(
this
.
pipeline
?.
id
)
:
this
.
projects
.
length
>
0
&&
this
.
projectsWereFetched
;
},
},
methods
:
{
handleFilterChange
(
filters
)
{
this
.
filters
=
filters
;
},
handleAutoFixUserCalloutClose
()
{
Cookies
.
set
(
this
.
$options
.
autoFixUserCalloutCookieName
,
'
true
'
);
this
.
shouldShowAutoFixUserCallout
=
false
;
},
},
autoFixUserCalloutCookieName
:
'
auto_fix_user_callout_dismissed
'
,
i18n
:
{
title
:
s__
(
'
SecurityReports|Vulnerability Report
'
),
},
...
...
@@ -84,27 +128,37 @@ export default {
<
template
>
<div>
<gl-loading-icon
v-if=
"!projectsWereFetched"
size=
"lg"
class=
"gl-mt-6"
/>
<template
v-else-if=
"
hasNoProjects
"
>
<template
v-else-if=
"
!isDashboardConfigured
"
>
<survey-request-banner
class=
"gl-mt-5"
/>
<dashboard-not-configured-group
v-if=
"isGroup"
/>
<dashboard-not-configured-instance
v-else-if=
"isInstance"
/>
<dashboard-not-configured-project
v-else-if=
"isProject"
/>
</
template
>
<
template
v-else
>
<auto-fix-user-callout
v-if=
"shouldShowAutoFixUserCallout"
:help-page-path=
"autoFixDocumentation"
@
close=
"handleAutoFixUserCalloutClose"
/>
<security-dashboard-layout>
<template
#header
>
<survey-request-banner
class=
"gl-mt-5"
/>
<header
class=
"gl-my-6 gl-display-flex gl-align-items-center"
>
<h2
class=
"gl-flex-grow-1 gl-my-0"
>
{{
$options
.
i18n
.
title
}}
</h2>
<csv-export-button
/>
</header>
<project-pipeline-status
v-if=
"isProject"
class=
"gl-mb-6"
:pipeline=
"pipeline"
/>
<vulnerabilities-count-list
:full-path=
"fullPath"
:filters=
"filters"
/>
</
template
>
<
template
#sticky
>
<filters
:projects=
"projects"
@
filterChange=
"handleFilterChange"
/>
</
template
>
<group-security-vulnerabilities
v-if=
"isGroup"
:filters=
"filters"
/>
<instance-security-vulnerabilities
v-else-if=
"isInstance"
:filters=
"filters"
/>
<project-security-vulnerabilities
v-else-if=
"isProject"
:filters=
"filters"
/>
</security-dashboard-layout>
</template>
<security-dashboard-layout
v-else
>
<
template
#header
>
<survey-request-banner
class=
"gl-mt-5"
/>
<header
class=
"gl-my-6 gl-display-flex gl-align-items-center"
>
<h2
class=
"gl-flex-grow-1 gl-my-0"
>
{{
$options
.
i18n
.
title
}}
</h2>
<csv-export-button
/>
</header>
<vulnerabilities-count-list
:full-path=
"groupFullPath"
:filters=
"filters"
/>
</
template
>
<
template
#sticky
>
<filters
:projects=
"projects"
@
filterChange=
"handleFilterChange"
/>
</
template
>
<group-security-vulnerabilities
v-if=
"isGroup"
:filters=
"filters"
/>
<instance-security-vulnerabilities
v-if=
"isInstance"
:filters=
"filters"
/>
</security-dashboard-layout>
</div>
</template>
ee/app/assets/javascripts/security_dashboard/security_charts_init.js
View file @
04752cbf
...
...
@@ -35,6 +35,7 @@ export default (el, dashboardType) => {
groupFullPath
:
el
.
dataset
.
groupFullPath
,
securityConfigurationPath
:
el
.
dataset
.
securityConfigurationPath
,
surveyRequestSvgPath
:
el
.
dataset
.
surveyRequestSvgPath
,
securityDashboardHelpPath
:
el
.
dataset
.
securityDashboardHelpPath
,
};
let
component
;
...
...
@@ -49,7 +50,6 @@ export default (el, dashboardType) => {
component
=
ProjectSecurityCharts
;
props
.
projectFullPath
=
el
.
dataset
.
projectFullPath
;
props
.
hasVulnerabilities
=
parseBoolean
(
el
.
dataset
.
hasVulnerabilities
);
props
.
helpPath
=
el
.
dataset
.
securityDashboardHelpPath
;
}
const
router
=
createRouter
();
...
...
ee/app/assets/javascripts/security_dashboard/vulnerability_report_init.js
View file @
04752cbf
import
Vue
from
'
vue
'
;
import
{
DASHBOARD_TYPES
}
from
'
ee/security_dashboard/store/constants
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
FirstClassProjectSecurityDashboard
from
'
./components/first_class_project_security_dashboard.vue
'
;
import
UnavailableState
from
'
./components/unavailable_state.vue
'
;
import
VulnerabilityReport
from
'
./components/vulnerability_report.vue
'
;
import
apolloProvider
from
'
./graphql/provider
'
;
...
...
@@ -62,10 +61,15 @@ export default (el, dashboardType) => {
emptyStateSvgPath
,
notEnabledScannersHelpPath
,
noPipelineRunScannersHelpPath
,
instanceDashboardSettingsPath
,
securityDashboardHelpPath
,
securityConfigurationPath
,
surveyRequestSvgPath
,
vulnerabilitiesExportEndpoint
,
groupFullPath
,
projectFullPath
,
autoFixDocumentation
,
autoFixMrsPath
,
hasVulnerabilities
:
parseBoolean
(
hasVulnerabilities
),
scanners
:
scanners
?
JSON
.
parse
(
scanners
)
:
[],
hasJiraVulnerabilitiesIntegrationEnabled
:
parseBoolean
(
...
...
@@ -74,16 +78,12 @@ export default (el, dashboardType) => {
};
const
props
=
{
securityDashboardHelpPath
,
projectAddEndpoint
,
projectListEndpoint
,
dashboardType
,
};
let
component
;
if
(
dashboardType
===
DASHBOARD_TYPES
.
PROJECT
)
{
component
=
FirstClassProjectSecurityDashboard
;
props
.
pipeline
=
{
createdAt
:
pipelineCreatedAt
,
id
:
pipelineId
,
...
...
@@ -91,14 +91,6 @@ export default (el, dashboardType) => {
securityBuildsFailedCount
:
Number
(
pipelineSecurityBuildsFailedCount
),
securityBuildsFailedPath
:
pipelineSecurityBuildsFailedPath
,
};
provide
.
projectFullPath
=
projectFullPath
;
provide
.
autoFixDocumentation
=
autoFixDocumentation
;
provide
.
autoFixMrsPath
=
autoFixMrsPath
;
}
else
if
(
dashboardType
===
DASHBOARD_TYPES
.
GROUP
)
{
component
=
VulnerabilityReport
;
}
else
if
(
dashboardType
===
DASHBOARD_TYPES
.
INSTANCE
)
{
provide
.
instanceDashboardSettingsPath
=
instanceDashboardSettingsPath
;
component
=
VulnerabilityReport
;
}
const
router
=
createRouter
();
...
...
@@ -111,7 +103,7 @@ export default (el, dashboardType) => {
apolloProvider
,
provide
,
render
(
createElement
)
{
return
createElement
(
componen
t
,
{
props
});
return
createElement
(
VulnerabilityRepor
t
,
{
props
});
},
});
};
ee/spec/frontend/security_dashboard/components/empty_states/reports_not_configured_spec.js
View file @
04752cbf
...
...
@@ -3,17 +3,17 @@ import ReportsNotConfigured from 'ee/security_dashboard/components/empty_states/
describe
(
'
reports not configured empty state
'
,
()
=>
{
let
wrapper
;
const
helpPath
=
'
/help
'
;
const
emptyStateSvgPath
=
'
/placeholder.svg
'
;
const
securityConfigurationPath
=
'
/configuration
'
;
const
securityDashboardHelpPath
=
'
/help
'
;
const
createComponent
=
()
=>
{
wrapper
=
shallowMount
(
ReportsNotConfigured
,
{
provide
:
{
emptyStateSvgPath
,
securityConfigurationPath
,
securityDashboardHelpPath
,
},
propsData
:
{
helpPath
},
});
};
...
...
ee/spec/frontend/security_dashboard/components/first_class_project_security_dashboard_spec.js
deleted
100644 → 0
View file @
cb9173ef
import
{
GlBanner
}
from
'
@gitlab/ui
'
;
import
{
within
}
from
'
@testing-library/dom
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
Cookies
from
'
js-cookie
'
;
import
AutoFixUserCallout
from
'
ee/security_dashboard/components/auto_fix_user_callout.vue
'
;
import
CsvExportButton
from
'
ee/security_dashboard/components/csv_export_button.vue
'
;
import
ReportsNotConfigured
from
'
ee/security_dashboard/components/empty_states/reports_not_configured.vue
'
;
import
FirstClassProjectSecurityDashboard
from
'
ee/security_dashboard/components/first_class_project_security_dashboard.vue
'
;
import
Filters
from
'
ee/security_dashboard/components/first_class_vulnerability_filters.vue
'
;
import
ProjectPipelineStatus
from
'
ee/security_dashboard/components/project_pipeline_status.vue
'
;
import
ProjectVulnerabilitiesApp
from
'
ee/security_dashboard/components/project_vulnerabilities.vue
'
;
import
SecurityDashboardLayout
from
'
ee/security_dashboard/components/security_dashboard_layout.vue
'
;
import
SurveyRequestBanner
from
'
ee/security_dashboard/components/survey_request_banner.vue
'
;
import
VulnerabilityCountList
from
'
ee/security_dashboard/components/vulnerability_count_list.vue
'
;
const
props
=
{
notEnabledScannersHelpPath
:
'
/help/docs/
'
,
noPipelineRunScannersHelpPath
:
'
/new/pipeline
'
,
pipeline
:
{
createdAt
:
'
2020-10-06T20:08:07Z
'
,
id
:
'
214
'
,
path
:
'
/mixed-vulnerabilities/dependency-list-test-01/-/pipelines/214
'
,
},
securityDashboardHelpPath
:
'
/security/dashboard/help-path
'
,
};
const
provide
=
{
projectFullPath
:
'
/group/project
'
,
dashboardDocumentation
:
'
/help/docs
'
,
autoFixDocumentation
:
'
/auto/fix/documentation
'
,
emptyStateSvgPath
:
'
/svgs/empty/svg
'
,
glFeatures
:
{
securityAutoFix
:
true
,
},
};
const
filters
=
{
foo
:
'
bar
'
};
describe
(
'
First class Project Security Dashboard component
'
,
()
=>
{
let
wrapper
;
const
findFilters
=
()
=>
wrapper
.
findComponent
(
Filters
);
const
findProjectPipelineStatus
=
()
=>
wrapper
.
findComponent
(
ProjectPipelineStatus
);
const
findVulnerabilities
=
()
=>
wrapper
.
findComponent
(
ProjectVulnerabilitiesApp
);
const
findVulnerabilityCountList
=
()
=>
wrapper
.
findComponent
(
VulnerabilityCountList
);
const
findUnconfiguredState
=
()
=>
wrapper
.
findComponent
(
ReportsNotConfigured
);
const
findCsvExportButton
=
()
=>
wrapper
.
findComponent
(
CsvExportButton
);
const
findAutoFixUserCallout
=
()
=>
wrapper
.
findComponent
(
AutoFixUserCallout
);
const
findSurveyRequestBanner
=
()
=>
wrapper
.
findComponent
(
SurveyRequestBanner
);
const
createComponent
=
(
options
)
=>
{
wrapper
=
shallowMount
(
FirstClassProjectSecurityDashboard
,
{
propsData
:
{
...
props
,
...
options
.
props
,
},
provide
,
stubs
:
{
SecurityDashboardLayout
,
GlBanner
},
...
options
,
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
on render when there are vulnerabilities
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
hasVulnerabilities
:
true
},
data
:
()
=>
({
filters
}),
});
});
it
(
'
should render the header correctly
'
,
()
=>
{
expect
(
within
(
wrapper
.
element
).
getByRole
(
'
heading
'
,
{
name
:
'
Vulnerability Report
'
}),
).
not
.
toBe
(
null
);
});
it
(
'
should render the vulnerabilities
'
,
()
=>
{
expect
(
findVulnerabilities
().
exists
()).
toBe
(
true
);
});
it
(
'
should pass down the properties correctly to the vulnerabilities
'
,
()
=>
{
expect
(
findVulnerabilities
().
props
()).
toEqual
({
projectFullPath
:
props
.
projectFullPath
,
filters
,
});
});
it
(
'
should pass down the properties correctly to the vulnerability count list
'
,
()
=>
{
expect
(
findVulnerabilityCountList
().
props
()).
toEqual
({
fullPath
:
provide
.
projectFullPath
,
filters
,
});
});
it
(
'
should render the filters component
'
,
()
=>
{
expect
(
findFilters
().
exists
()).
toBe
(
true
);
});
it
(
'
does not display the unconfigured state
'
,
()
=>
{
expect
(
findUnconfiguredState
().
exists
()).
toBe
(
false
);
});
it
(
'
should display the csv export button
'
,
()
=>
{
expect
(
findCsvExportButton
().
props
(
'
vulnerabilitiesExportEndpoint
'
)).
toEqual
(
props
.
vulnerabilitiesExportEndpoint
,
);
});
it
(
'
should display the project pipeline status
'
,
()
=>
{
expect
(
findProjectPipelineStatus
()).
toExist
();
});
it
(
'
should show the survey request banner
'
,
()
=>
{
expect
(
findSurveyRequestBanner
().
exists
()).
toBe
(
true
);
});
});
describe
(
'
auto-fix user callout
'
,
()
=>
{
describe
(
'
feature flag disabled
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
hasVulnerabilities
:
true
},
provide
:
{
...
provide
,
glFeatures
:
{
securityAutoFix
:
false
,
},
},
});
});
it
(
'
does not show user callout
'
,
()
=>
{
expect
(
findAutoFixUserCallout
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
cookie not set
'
,
()
=>
{
beforeEach
(()
=>
{
jest
.
spyOn
(
Cookies
,
'
set
'
);
createComponent
({
props
:
{
hasVulnerabilities
:
true
},
});
});
it
(
'
shows user callout by default
'
,
()
=>
{
expect
(
findAutoFixUserCallout
().
exists
()).
toBe
(
true
);
});
it
(
'
when dismissed, hides the user callout and sets the cookie
'
,
async
()
=>
{
await
findAutoFixUserCallout
().
vm
.
$emit
(
'
close
'
);
expect
(
findAutoFixUserCallout
().
exists
()).
toBe
(
false
);
expect
(
Cookies
.
set
).
toHaveBeenCalledWith
(
'
auto_fix_user_callout_dismissed
'
,
'
true
'
);
});
});
describe
(
'
cookie set
'
,
()
=>
{
beforeEach
(()
=>
{
jest
.
doMock
(
'
js-cookie
'
,
()
=>
({
get
:
jest
.
fn
().
mockReturnValue
(
true
),
}));
createComponent
({
props
:
{
hasVulnerabilities
:
true
},
});
});
it
(
'
does not show user callout
'
,
()
=>
{
expect
(
findAutoFixUserCallout
().
exists
()).
toBe
(
false
);
});
});
});
describe
(
'
with filter data
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
hasVulnerabilities
:
true
,
},
data
()
{
return
{
filters
};
},
});
});
it
(
'
should pass the filter data down to the vulnerabilities
'
,
()
=>
{
expect
(
findVulnerabilities
().
props
().
filters
).
toEqual
(
filters
);
});
});
describe
(
'
when there is no vulnerability
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
pipeline
:
{
id
:
undefined
},
},
});
});
it
(
'
displays the unconfigured state
'
,
()
=>
{
expect
(
findUnconfiguredState
().
exists
()).
toBe
(
true
);
});
it
(
'
shows the survey request banner
'
,
()
=>
{
expect
(
findSurveyRequestBanner
().
exists
()).
toBe
(
true
);
});
});
});
ee/spec/frontend/security_dashboard/components/project_security_charts_spec.js
View file @
04752cbf
...
...
@@ -137,7 +137,7 @@ describe('Project Security Charts component', () => {
});
it
(
'
should display the empty state
'
,
()
=>
{
expect
(
findEmptyState
().
props
()).
toEqual
({
helpPath
}
);
expect
(
findEmptyState
().
exists
()).
toBe
(
true
);
});
it
(
'
should not display the chart
'
,
()
=>
{
...
...
ee/spec/frontend/security_dashboard/components/vulnerability_report_spec.js
View file @
04752cbf
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Cookies
from
'
js-cookie
'
;
import
{
nextTick
}
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
AutoFixUserCallout
from
'
ee/security_dashboard/components/auto_fix_user_callout.vue
'
;
import
CsvExportButton
from
'
ee/security_dashboard/components/csv_export_button.vue
'
;
import
DashboardNotConfiguredGroup
from
'
ee/security_dashboard/components/empty_states/group_dashboard_not_configured.vue
'
;
import
DashboardNotConfiguredInstance
from
'
ee/security_dashboard/components/empty_states/instance_dashboard_not_configured.vue
'
;
import
DashboardNotConfiguredProject
from
'
ee/security_dashboard/components/empty_states/reports_not_configured.vue
'
;
import
GroupVulnerabilities
from
'
ee/security_dashboard/components/first_class_group_security_dashboard_vulnerabilities.vue
'
;
import
InstanceVulnerabilities
from
'
ee/security_dashboard/components/first_class_instance_security_dashboard_vulnerabilities.vue
'
;
import
Filters
from
'
ee/security_dashboard/components/first_class_vulnerability_filters.vue
'
;
import
ProjectPipelineStatus
from
'
ee/security_dashboard/components/project_pipeline_status.vue
'
;
import
ProjectVulnerabilities
from
'
ee/security_dashboard/components/project_vulnerabilities.vue
'
;
import
SecurityDashboardLayout
from
'
ee/security_dashboard/components/security_dashboard_layout.vue
'
;
import
SurveyRequestBanner
from
'
ee/security_dashboard/components/survey_request_banner.vue
'
;
import
VulnerabilitiesCountList
from
'
ee/security_dashboard/components/vulnerability_count_list.vue
'
;
...
...
@@ -24,12 +29,17 @@ describe('Vulnerability Report', () => {
const
findSurveyRequestBanner
=
()
=>
wrapper
.
findComponent
(
SurveyRequestBanner
);
const
findInstanceVulnerabilities
=
()
=>
wrapper
.
findComponent
(
InstanceVulnerabilities
);
const
findGroupVulnerabilities
=
()
=>
wrapper
.
findComponent
(
GroupVulnerabilities
);
const
findProjectVulnerabilities
=
()
=>
wrapper
.
findComponent
(
ProjectVulnerabilities
);
const
findCsvExportButton
=
()
=>
wrapper
.
findComponent
(
CsvExportButton
);
const
findGroupEmptyState
=
()
=>
wrapper
.
findComponent
(
DashboardNotConfiguredGroup
);
const
findInstanceEmptyState
=
()
=>
wrapper
.
findComponent
(
DashboardNotConfiguredInstance
);
const
findProjectEmptyState
=
()
=>
wrapper
.
findComponent
(
DashboardNotConfiguredProject
);
const
findLoadingIcon
=
()
=>
wrapper
.
findComponent
(
GlLoadingIcon
);
const
findFilters
=
()
=>
wrapper
.
findComponent
(
Filters
);
const
findVulnerabilitiesCountList
=
()
=>
wrapper
.
findComponent
(
VulnerabilitiesCountList
);
const
findProjectPipelineStatus
=
()
=>
wrapper
.
findComponent
(
ProjectPipelineStatus
);
const
findAutoFixUserCallout
=
()
=>
wrapper
.
findComponent
(
AutoFixUserCallout
);
const
findHeader
=
()
=>
wrapper
.
find
(
'
h2
'
);
const
createWrapper
=
({
data
=
{},
mocks
,
propsData
,
provide
,
apolloProvider
})
=>
{
...
...
@@ -45,7 +55,14 @@ describe('Vulnerability Report', () => {
data
:
()
=>
data
,
mocks
,
propsData
,
provide
:
{
groupFullPath
:
undefined
,
...
provide
},
provide
:
{
groupFullPath
:
undefined
,
projectFullPath
:
undefined
,
autoFixDocumentation
:
undefined
,
dashboardDocumentation
:
'
path/to/documentation
'
,
securityDashboardHelpPath
:
'
path/to/project/documentation
'
,
...
provide
,
},
stubs
:
{
SecurityDashboardLayout
},
});
};
...
...
@@ -119,6 +136,10 @@ describe('Vulnerability Report', () => {
it
(
'
shows the vulnerability count list and passes the filters prop
'
,
()
=>
{
expect
(
findVulnerabilitiesCountList
().
props
(
'
filters
'
)).
toBe
(
filters
);
});
it
(
'
does not show project pipeline status
'
,
()
=>
{
expect
(
findProjectPipelineStatus
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
when initialized - group level
'
,
()
=>
{
...
...
@@ -168,6 +189,7 @@ describe('Vulnerability Report', () => {
it
(
'
only renders the empty state
'
,
()
=>
{
expect
(
findGroupEmptyState
().
exists
()).
toBe
(
true
);
expect
(
findInstanceEmptyState
().
exists
()).
toBe
(
false
);
expect
(
findProjectEmptyState
().
exists
()).
toBe
(
false
);
expect
(
findCsvExportButton
().
exists
()).
toBe
(
false
);
expect
(
findFilters
().
exists
()).
toBe
(
false
);
expect
(
findVulnerabilitiesCountList
().
exists
()).
toBe
(
false
);
...
...
@@ -201,4 +223,72 @@ describe('Vulnerability Report', () => {
expect
(
findSurveyRequestBanner
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
when initialized - project level
'
,
()
=>
{
const
createProjectWrapper
=
({
securityAutoFix
}
=
{})
=>
createWrapper
({
provide
:
{
dashboardType
:
DASHBOARD_TYPES
.
PROJECT
,
autoFixDocumentation
:
'
path/to/help-page
'
,
glFeatures
:
{
securityAutoFix
,
},
},
propsData
:
{
pipeline
:
{
id
:
'
591
'
,
},
},
apolloProvider
:
createApolloProvider
(),
});
it
(
'
does not show user callout when feature flag is disabled
'
,
()
=>
{
wrapper
=
createProjectWrapper
({
securityAutoFix
:
false
});
expect
(
findAutoFixUserCallout
().
exists
()).
toBe
(
false
);
});
it
(
'
shows user callout when the cookie is not set and hides it when dismissed
'
,
async
()
=>
{
jest
.
spyOn
(
Cookies
,
'
set
'
);
wrapper
=
createProjectWrapper
({
securityAutoFix
:
true
});
const
autoFixUserCallOut
=
findAutoFixUserCallout
();
expect
(
autoFixUserCallOut
.
exists
()).
toBe
(
true
);
await
autoFixUserCallOut
.
vm
.
$emit
(
'
close
'
);
expect
(
autoFixUserCallOut
.
exists
()).
toBe
(
false
);
expect
(
Cookies
.
set
).
toHaveBeenCalledWith
(
wrapper
.
vm
.
$options
.
autoFixUserCalloutCookieName
,
'
true
'
,
);
});
it
(
'
does not show user callout when the cookie is set
'
,
()
=>
{
jest
.
doMock
(
'
js-cookie
'
,
()
=>
({
get
:
jest
.
fn
().
mockReturnValue
(
true
)
}));
wrapper
=
createProjectWrapper
({
securityAutoFix
:
true
});
expect
(
findAutoFixUserCallout
().
exists
()).
toBe
(
false
);
});
it
(
'
shows the project pipeline status
'
,
()
=>
{
wrapper
=
createProjectWrapper
();
expect
(
findProjectPipelineStatus
().
exists
()).
toBe
(
true
);
});
it
(
'
renders the vulnerabilities
'
,
()
=>
{
wrapper
=
createProjectWrapper
();
expect
(
findProjectVulnerabilities
().
exists
()).
toBe
(
true
);
});
});
describe
(
'
when uninitialized - project level
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createWrapper
({
provide
:
{
dashboardType
:
DASHBOARD_TYPES
.
PROJECT
,
},
apolloProvider
:
createApolloProvider
(),
});
});
it
(
'
renders empty project state
'
,
()
=>
{
expect
(
findProjectEmptyState
().
exists
()).
toBe
(
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