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
38cf8d53
Commit
38cf8d53
authored
Mar 28, 2018
by
Filipa Lacerda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds vuex store for security reports
parent
1aec54db
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
2691 additions
and
42 deletions
+2691
-42
ee/app/assets/javascripts/vue_shared/security_reports/store/actions.js
.../javascripts/vue_shared/security_reports/store/actions.js
+197
-0
ee/app/assets/javascripts/vue_shared/security_reports/store/getters.js
.../javascripts/vue_shared/security_reports/store/getters.js
+126
-0
ee/app/assets/javascripts/vue_shared/security_reports/store/index.js
...ts/javascripts/vue_shared/security_reports/store/index.js
+17
-0
ee/app/assets/javascripts/vue_shared/security_reports/store/mutation_types.js
...ripts/vue_shared/security_reports/store/mutation_types.js
+30
-0
ee/app/assets/javascripts/vue_shared/security_reports/store/mutations.js
...avascripts/vue_shared/security_reports/store/mutations.js
+256
-0
ee/app/assets/javascripts/vue_shared/security_reports/store/state.js
...ts/javascripts/vue_shared/security_reports/store/state.js
+63
-0
ee/app/assets/javascripts/vue_shared/security_reports/store/utils.js
...ts/javascripts/vue_shared/security_reports/store/utils.js
+137
-0
spec/javascripts/helpers/vuex_action_helper.js
spec/javascripts/helpers/vuex_action_helper.js
+22
-1
spec/javascripts/vue_shared/security_reports/mock_data.js
spec/javascripts/vue_shared/security_reports/mock_data.js
+161
-41
spec/javascripts/vue_shared/security_reports/store/actions_spec.js
...scripts/vue_shared/security_reports/store/actions_spec.js
+764
-0
spec/javascripts/vue_shared/security_reports/store/getters_spec.js
...scripts/vue_shared/security_reports/store/getters_spec.js
+498
-0
spec/javascripts/vue_shared/security_reports/store/mutations_spec.js
...ripts/vue_shared/security_reports/store/mutations_spec.js
+283
-0
spec/javascripts/vue_shared/security_reports/store/utils_spec.js
...vascripts/vue_shared/security_reports/store/utils_spec.js
+137
-0
No files found.
ee/app/assets/javascripts/vue_shared/security_reports/store/actions.js
0 → 100644
View file @
38cf8d53
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
*
as
types
from
'
./mutation_types
'
;
export
const
setHeadBlobPath
=
({
commit
},
blobPath
)
=>
commit
(
types
.
SET_HEAD_BLOB_PATH
,
blobPath
);
export
const
setBaseBlobPath
=
({
commit
},
blobPath
)
=>
{
commit
(
types
.
SET_BASE_BLOB_PATH
,
blobPath
);
};
/**
* SAST
*/
export
const
setSastHeadPath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_SAST_HEAD_PATH
,
path
);
export
const
setSastBasePath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_SAST_BASE_PATH
,
path
);
export
const
requestSastReports
=
({
commit
})
=>
commit
(
types
.
REQUEST_SAST_REPORTS
);
export
const
receiveSastReports
=
({
commit
},
response
)
=>
commit
(
types
.
RECEIVE_SAST_REPORTS
,
response
);
export
const
receiveSastError
=
({
commit
},
error
)
=>
commit
(
types
.
RECEIVE_SAST_REPORTS_ERROR
,
error
);
export
const
fetchSastReports
=
({
state
,
dispatch
})
=>
{
const
base
=
state
.
sast
.
paths
.
base
;
const
head
=
state
.
sast
.
paths
.
head
;
dispatch
(
'
requestSastReports
'
);
if
(
head
&&
base
)
{
Promise
.
all
([
axios
.
get
(
head
),
axios
.
get
(
base
)])
.
then
(
values
=>
{
dispatch
(
'
receiveSastReports
'
,
{
head
:
values
[
0
].
data
,
base
:
values
[
1
].
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveSastError
'
);
});
}
else
if
(
head
&&
!
base
)
{
axios
.
get
(
head
)
.
then
(
response
=>
{
dispatch
(
'
receiveSastReports
'
,
{
head
:
response
.
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveSastError
'
);
});
}
};
/**
* SAST CONTAINER
*/
export
const
setSastContainerHeadPath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_SAST_CONTAINER_HEAD_PATH
,
path
);
export
const
setSastContainerBasePath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_SAST_CONTAINER_BASE_PATH
,
path
);
export
const
requestSastContainerReports
=
({
commit
})
=>
commit
(
types
.
REQUEST_SAST_CONTAINER_REPORTS
);
export
const
receiveSastContainerReports
=
({
commit
},
response
)
=>
commit
(
types
.
RECEIVE_SAST_CONTAINER_REPORTS
,
response
);
export
const
receiveSastContainerError
=
({
commit
},
error
)
=>
commit
(
types
.
RECEIVE_SAST_CONTAINER_ERROR
,
error
);
export
const
fetchSastContainerReports
=
({
state
,
dispatch
})
=>
{
const
base
=
state
.
sastContainer
.
paths
.
base
;
const
head
=
state
.
sastContainer
.
paths
.
head
;
dispatch
(
'
requestSastContainerReports
'
);
if
(
head
&&
base
)
{
Promise
.
all
([
axios
.
get
(
head
),
axios
.
get
(
base
)])
.
then
(
values
=>
{
dispatch
(
'
receiveSastContainerReports
'
,
{
head
:
values
[
0
].
data
,
base
:
values
[
1
].
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveSastContainerError
'
);
});
}
else
{
axios
.
get
(
head
)
.
then
(
response
=>
{
dispatch
(
'
receiveSastContainerReports
'
,
{
head
:
response
.
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveSastContainerError
'
);
});
}
};
/**
* DAST
*/
export
const
setDastHeadPath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_DAST_HEAD_PATH
,
path
);
export
const
setDastBasePath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_DAST_BASE_PATH
,
path
);
export
const
requestDastReports
=
({
commit
})
=>
commit
(
types
.
REQUEST_DAST_REPORTS
);
export
const
receiveDastReports
=
({
commit
},
response
)
=>
commit
(
types
.
RECEIVE_DAST_REPORTS
,
response
);
export
const
receiveDastError
=
({
commit
},
error
)
=>
commit
(
types
.
RECEIVE_DAST_ERROR
,
error
);
export
const
fetchDastReports
=
({
state
,
dispatch
})
=>
{
const
base
=
state
.
dast
.
paths
.
base
;
const
head
=
state
.
dast
.
paths
.
head
;
dispatch
(
'
requestDastReports
'
);
if
(
head
&&
base
)
{
Promise
.
all
([
axios
.
get
(
head
),
axios
.
get
(
base
)])
.
then
(
values
=>
{
dispatch
(
'
receiveDastReports
'
,
{
head
:
values
[
0
].
data
,
base
:
values
[
1
].
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveDastError
'
);
});
}
else
{
axios
.
get
(
head
)
.
then
(
response
=>
{
dispatch
(
'
receiveDastReports
'
,
{
head
:
response
.
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveDastError
'
);
});
}
};
/**
* DEPENDENCY SCANNING
*/
export
const
setDependencyScanningHeadPath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_DEPENDENCY_SCANNING_HEAD_PATH
,
path
);
export
const
setDependencyScanningBasePath
=
({
commit
},
path
)
=>
commit
(
types
.
SET_DEPENDENCY_SCANNING_BASE_PATH
,
path
);
export
const
requestDependencyScanningReports
=
({
commit
})
=>
commit
(
types
.
REQUEST_DEPENDENCY_SCANNING_REPORTS
);
export
const
receiveDependencyScanningReports
=
({
commit
},
response
)
=>
commit
(
types
.
RECEIVE_DEPENDENCY_SCANNING_REPORTS
,
response
);
export
const
receiveDependencyScanningError
=
({
commit
},
error
)
=>
commit
(
types
.
RECEIVE_DEPENDENCY_SCANNING_ERROR
,
error
);
export
const
fetchDependencyScanningReports
=
({
state
,
dispatch
})
=>
{
const
base
=
state
.
dependencyScanning
.
paths
.
base
;
const
head
=
state
.
dependencyScanning
.
paths
.
head
;
dispatch
(
'
requestDependencyScanningReports
'
);
if
(
head
&&
base
)
{
Promise
.
all
([
axios
.
get
(
head
),
axios
.
get
(
base
)])
.
then
(
values
=>
{
dispatch
(
'
receiveDependencyScanningReports
'
,
{
head
:
values
[
0
].
data
,
base
:
values
[
1
].
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveDependencyScanningError
'
);
});
}
else
{
axios
.
get
(
head
)
.
then
(
response
=>
{
dispatch
(
'
receiveDependencyScanningReports
'
,
{
head
:
response
.
data
,
});
})
.
catch
(()
=>
{
dispatch
(
'
receiveDependencyScanningError
'
);
});
}
};
ee/app/assets/javascripts/vue_shared/security_reports/store/getters.js
0 → 100644
View file @
38cf8d53
import
{
n__
,
s__
}
from
'
~/locale
'
;
import
{
textBuilder
,
statusIcon
}
from
'
./utils
'
;
export
const
groupedSastText
=
state
=>
{
const
{
sast
}
=
state
;
return
textBuilder
(
'
SAST
'
,
sast
.
paths
,
sast
.
newIssues
.
length
,
sast
.
resolvedIssues
.
length
,
sast
.
allIssues
.
length
,
);
};
export
const
groupedSastContainerText
=
state
=>
{
const
{
sastContainer
}
=
state
;
return
textBuilder
(
'
Container scanning
'
,
sastContainer
.
paths
,
sastContainer
.
newIssues
.
length
,
sastContainer
.
resolvedIssues
.
length
,
);
};
export
const
groupedDastText
=
state
=>
{
const
{
dast
}
=
state
;
return
textBuilder
(
'
DAST
'
,
dast
.
paths
,
dast
.
newIssues
.
length
,
dast
.
resolvedIssues
.
length
);
};
export
const
groupedDependencyText
=
state
=>
{
const
{
dependencyScanning
}
=
state
;
return
textBuilder
(
'
Dependency scanning
'
,
dependencyScanning
.
paths
,
dependencyScanning
.
newIssues
.
length
,
dependencyScanning
.
resolvedIssues
.
length
,
);
};
export
const
groupedSummaryText
=
(
state
,
getters
)
=>
{
const
{
added
,
fixed
}
=
state
.
summaryCounts
;
// All reports returned error
if
(
getters
.
allReportsHaveError
)
{
return
s__
(
'
ciReport|Security scanning failed loading any results
'
);
}
// No base is present in any report
if
(
getters
.
noBaseInAllReports
)
{
if
(
added
>
0
)
{
return
n__
(
'
Security scanning was unable to compare existing and new vulnerabilities. It detected %d vulnerability
'
,
'
Security scanning was unable to compare existing and new vulnerabilities. It detected %d vulnerabilities
'
,
added
,
);
}
return
s__
(
'
Security scanning was unable to compare existing and new vulnerabilities. It detected no vulnerabilities.
'
,
);
}
const
text
=
[
s__
(
'
ciReport|Security scanning
'
)];
if
(
getters
.
areReportsLoading
)
{
text
.
push
(
'
(in progress)
'
);
}
if
(
added
>
0
&&
fixed
===
0
)
{
text
.
push
(
n__
(
'
detected %d new vulnerability
'
,
'
detected %d new vulnerabilities
'
,
added
));
}
if
(
added
>
0
&&
fixed
>
0
)
{
text
.
push
(
`
${
n__
(
'
detected %d new vulnerability
'
,
'
detected %d new vulnerabilities
'
,
added
)}
${
n__
(
'
and %d fixed vulnerability
'
,
'
and %d fixed vulnerabilities
'
,
fixed
,
)}
`
,
);
}
if
(
added
===
0
&&
fixed
>
0
)
{
text
.
push
(
n__
(
'
detected %d fixed vulnerability
'
,
'
detected %d fixed vulnerabilities
'
,
fixed
));
}
if
(
added
===
0
&&
fixed
===
0
)
{
text
.
push
(
s__
(
'
detected no vulnerabilities
'
));
}
return
text
.
join
(
'
'
);
};
export
const
sastStatusIcon
=
state
=>
statusIcon
(
state
.
sast
.
hasError
,
state
.
sast
.
newIssues
.
length
);
export
const
sastContainerStatusIcon
=
state
=>
statusIcon
(
state
.
sastContainer
.
hasError
,
state
.
sastContainer
.
newIssues
.
length
);
export
const
dastStatusIcon
=
state
=>
statusIcon
(
state
.
dast
.
hasError
,
state
.
dast
.
newIssues
.
length
);
export
const
dependencyScanningStatusIcon
=
state
=>
statusIcon
(
state
.
dependencyScanning
.
hasError
,
state
.
dependencyScanning
.
newIssues
.
length
);
export
const
areReportsLoading
=
state
=>
state
.
sast
.
isLoading
||
state
.
dast
.
isLoading
||
state
.
sastContainer
.
isLoading
||
state
.
dependencyScanning
.
isLoading
;
export
const
allReportsHaveError
=
state
=>
state
.
sast
.
hasError
&&
state
.
dast
.
hasError
&&
state
.
sastContainer
.
hasError
&&
state
.
dependencyScanning
.
hasError
;
export
const
anyReportHasError
=
state
=>
state
.
sast
.
hasError
||
state
.
dast
.
hasError
||
state
.
sastContainer
.
hasError
||
state
.
dependencyScanning
.
hasError
;
export
const
noBaseInAllReports
=
state
=>
!
state
.
sast
.
paths
.
base
&&
!
state
.
dast
.
paths
.
base
&&
!
state
.
sastContainer
.
paths
.
base
&&
!
state
.
dependencyScanning
.
paths
.
base
;
ee/app/assets/javascripts/vue_shared/security_reports/store/index.js
0 → 100644
View file @
38cf8d53
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
*
as
actions
from
'
./actions
'
;
import
*
as
getters
from
'
./getters
'
;
import
mutations
from
'
./mutations
'
;
import
state
from
'
./state
'
;
Vue
.
use
(
Vuex
);
const
store
=
new
Vuex
.
Store
({
actions
,
getters
,
mutations
,
state
:
state
(),
});
export
default
store
;
ee/app/assets/javascripts/vue_shared/security_reports/store/mutation_types.js
0 → 100644
View file @
38cf8d53
export
const
SET_HEAD_BLOB_PATH
=
'
SET_HEAD_BLOB_PATH
'
;
export
const
SET_BASE_BLOB_PATH
=
'
SET_BASE_BLOB_PATH
'
;
// SAST
export
const
SET_SAST_HEAD_PATH
=
'
SET_SAST_HEAD_PATH
'
;
export
const
SET_SAST_BASE_PATH
=
'
SET_SAST_BASE_PATH
'
;
export
const
REQUEST_SAST_REPORTS
=
'
REQUEST_SAST_REPORTS
'
;
export
const
RECEIVE_SAST_REPORTS
=
'
RECEIVE_SAST_REPORTS
'
;
export
const
RECEIVE_SAST_REPORTS_ERROR
=
'
RECEIVE_SAST_REPORTS_ERROR
'
;
// SAST CONTAINER
export
const
SET_SAST_CONTAINER_HEAD_PATH
=
'
SET_SAST_CONTAINER_HEAD_PATH
'
;
export
const
SET_SAST_CONTAINER_BASE_PATH
=
'
SET_SAST_CONTAINER_BASE_PATH
'
;
export
const
REQUEST_SAST_CONTAINER_REPORTS
=
'
REQUEST_SAST_CONTAINER_REPORTS
'
;
export
const
RECEIVE_SAST_CONTAINER_REPORTS
=
'
RECEIVE_SAST_CONTAINER_REPORTS
'
;
export
const
RECEIVE_SAST_CONTAINER_ERROR
=
'
RECEIVE_SAST_CONTAINER_ERROR
'
;
// DAST
export
const
SET_DAST_HEAD_PATH
=
'
SET_DAST_HEAD_PATH
'
;
export
const
SET_DAST_BASE_PATH
=
'
SET_DAST_BASE_PATH
'
;
export
const
REQUEST_DAST_REPORTS
=
'
REQUEST_DAST_REPORTS
'
;
export
const
RECEIVE_DAST_REPORTS
=
'
RECEIVE_DAST_REPORTS
'
;
export
const
RECEIVE_DAST_ERROR
=
'
RECEIVE_DAST_ERROR
'
;
// DEPENDENCY_SCANNING
export
const
SET_DEPENDENCY_SCANNING_HEAD_PATH
=
'
SET_DEPENDENCY_SCANNING_HEAD_PATH
'
;
export
const
SET_DEPENDENCY_SCANNING_BASE_PATH
=
'
SET_DEPENDENCY_SCANNING_BASE_PATH
'
;
export
const
REQUEST_DEPENDENCY_SCANNING_REPORTS
=
'
REQUEST_DEPENDENCY_SCANNING_REPORTS
'
;
export
const
RECEIVE_DEPENDENCY_SCANNING_REPORTS
=
'
RECEIVE_DEPENDENCY_SCANNING_REPORTS
'
;
export
const
RECEIVE_DEPENDENCY_SCANNING_ERROR
=
'
RECEIVE_DEPENDENCY_SCANNING_ERROR
'
;
ee/app/assets/javascripts/vue_shared/security_reports/store/mutations.js
0 → 100644
View file @
38cf8d53
import
*
as
types
from
'
./mutation_types
'
;
import
{
parseSastIssues
,
filterByKey
,
parseSastContainer
,
parseDastIssues
,
getUnapprovedVulnerabilities
,
}
from
'
./utils
'
;
export
default
{
[
types
.
SET_HEAD_BLOB_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
blobPath
,
{
head
:
path
});
},
[
types
.
SET_BASE_BLOB_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
blobPath
,
{
base
:
path
});
},
// SAST
[
types
.
SET_SAST_HEAD_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
sast
.
paths
,
{
head
:
path
});
},
[
types
.
SET_SAST_BASE_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
sast
.
paths
,
{
base
:
path
});
},
[
types
.
REQUEST_SAST_REPORTS
](
state
)
{
Object
.
assign
(
state
.
sast
,
{
isLoading
:
true
});
},
/**
* Compares sast results and returns the formatted report
*
* Sast has 3 types of issues: newIssues, resolvedIssues and allIssues.
*
* When we have both base and head:
* - newIssues = head - base
* - resolvedIssues = base - head
* - allIssues = head - newIssues - resolvedIssues
*
* When we only have head
* - newIssues = head
* - resolvedIssues = 0
* - allIssues = 0
*/
[
types
.
RECEIVE_SAST_REPORTS
](
state
,
reports
)
{
if
(
reports
.
base
&&
reports
.
head
)
{
const
filterKey
=
'
cve
'
;
const
parsedHead
=
parseSastIssues
(
reports
.
head
,
state
.
blobPath
.
head
);
const
parsedBase
=
parseSastIssues
(
reports
.
base
,
state
.
blobPath
.
base
);
const
newIssues
=
filterByKey
(
parsedHead
,
parsedBase
,
filterKey
);
const
resolvedIssues
=
filterByKey
(
parsedBase
,
parsedHead
,
filterKey
);
const
allIssues
=
filterByKey
(
parsedHead
,
newIssues
.
concat
(
resolvedIssues
),
filterKey
);
Object
.
assign
(
state
.
sast
,
{
newIssues
,
resolvedIssues
,
allIssues
,
isLoading
:
false
,
});
Object
.
assign
(
state
.
summaryCounts
,
{
added
:
state
.
summaryCounts
.
added
+
newIssues
.
length
,
fixed
:
state
.
summaryCounts
.
fixed
+
resolvedIssues
.
length
,
});
}
else
if
(
reports
.
head
&&
!
reports
.
base
)
{
const
newIssues
=
parseSastIssues
(
reports
.
head
,
state
.
blobPath
.
head
);
Object
.
assign
(
state
.
sast
,
{
newIssues
,
isLoading
:
false
,
});
}
},
[
types
.
RECEIVE_SAST_REPORTS_ERROR
](
state
)
{
Object
.
assign
(
state
.
sast
,
{
isLoading
:
false
,
hasError
:
true
,
});
},
// SAST CONTAINER
[
types
.
SET_SAST_CONTAINER_HEAD_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
sastContainer
.
paths
,
{
head
:
path
});
},
[
types
.
SET_SAST_CONTAINER_BASE_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
sastContainer
.
paths
,
{
base
:
path
});
},
[
types
.
REQUEST_SAST_CONTAINER_REPORTS
](
state
)
{
Object
.
assign
(
state
.
sastContainer
,
{
isLoading
:
true
});
},
/**
* For sast container we only render unapproved vulnerabilities.
*/
[
types
.
RECEIVE_SAST_CONTAINER_REPORTS
](
state
,
reports
)
{
if
(
reports
.
base
&&
reports
.
head
)
{
const
headIssues
=
getUnapprovedVulnerabilities
(
parseSastContainer
(
reports
.
head
.
vulnerabilities
),
reports
.
head
.
unapproved
,
);
const
baseIssues
=
getUnapprovedVulnerabilities
(
parseSastContainer
(
reports
.
base
.
vulnerabilities
),
reports
.
base
.
unapproved
,
);
const
filterKey
=
'
vulnerability
'
;
const
newIssues
=
filterByKey
(
headIssues
,
baseIssues
,
filterKey
);
const
resolvedIssues
=
filterByKey
(
baseIssues
,
headIssues
,
filterKey
);
Object
.
assign
(
state
.
sastContainer
,
{
isLoading
:
false
,
newIssues
,
resolvedIssues
,
});
Object
.
assign
(
state
.
summaryCounts
,
{
added
:
state
.
summaryCounts
.
added
+
newIssues
.
length
,
fixed
:
state
.
summaryCounts
.
fixed
+
resolvedIssues
.
length
,
});
}
else
if
(
reports
.
head
&&
!
reports
.
base
)
{
Object
.
assign
(
state
.
sastContainer
,
{
isLoading
:
false
,
newIssues
:
getUnapprovedVulnerabilities
(
parseSastContainer
(
reports
.
head
.
vulnerabilities
),
reports
.
head
.
unapproved
,
),
});
}
},
[
types
.
RECEIVE_SAST_CONTAINER_ERROR
](
state
)
{
Object
.
assign
(
state
.
sastContainer
,
{
isLoading
:
false
,
hasError
:
true
,
});
},
// DAST
[
types
.
SET_DAST_HEAD_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
dast
.
paths
,
{
head
:
path
});
},
[
types
.
SET_DAST_BASE_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
dast
.
paths
,
{
base
:
path
});
},
[
types
.
REQUEST_DAST_REPORTS
](
state
)
{
Object
.
assign
(
state
.
dast
,
{
isLoading
:
true
});
},
[
types
.
RECEIVE_DAST_REPORTS
](
state
,
reports
)
{
if
(
reports
.
head
&&
reports
.
base
)
{
const
headIssues
=
parseDastIssues
(
reports
.
head
.
site
.
alerts
);
const
baseIssues
=
parseDastIssues
(
reports
.
base
.
site
.
alerts
);
const
filterKey
=
'
pluginid
'
;
const
newIssues
=
filterByKey
(
headIssues
,
baseIssues
,
filterKey
);
const
resolvedIssues
=
filterByKey
(
baseIssues
,
headIssues
,
filterKey
);
Object
.
assign
(
state
.
dast
,
{
isLoading
:
false
,
newIssues
,
resolvedIssues
,
});
Object
.
assign
(
state
.
summaryCounts
,
{
added
:
state
.
summaryCounts
.
added
+
newIssues
.
length
,
fixed
:
state
.
summaryCounts
.
fixed
+
resolvedIssues
.
length
,
});
}
else
if
(
reports
.
head
&&
!
reports
.
base
)
{
Object
.
assign
(
state
.
dast
,
{
isLoading
:
false
,
newIssues
:
parseDastIssues
(
reports
.
head
.
site
.
alerts
),
});
}
},
[
types
.
RECEIVE_DAST_ERROR
](
state
)
{
Object
.
assign
(
state
.
dast
,
{
isLoading
:
false
,
hasError
:
true
,
});
},
// DEPENDECY SCANNING
[
types
.
SET_DEPENDENCY_SCANNING_HEAD_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
dependencyScanning
.
paths
,
{
head
:
path
});
},
[
types
.
SET_DEPENDENCY_SCANNING_BASE_PATH
](
state
,
path
)
{
Object
.
assign
(
state
.
dependencyScanning
.
paths
,
{
base
:
path
});
},
[
types
.
REQUEST_DEPENDENCY_SCANNING_REPORTS
](
state
)
{
Object
.
assign
(
state
.
dependencyScanning
,
{
isLoading
:
true
});
},
/**
* Compares dependency scanning results and returns the formatted report
*
* Dependency report has 3 types of issues, newIssues, resolvedIssues and allIssues.
*
* When we have both base and head:
* - newIssues = head - base
* - resolvedIssues = base - head
* - allIssues = head - newIssues - resolvedIssues
*
* When we only have head
* - newIssues = head
* - resolvedIssues = 0
* - allIssues = 0
*/
[
types
.
RECEIVE_DEPENDENCY_SCANNING_REPORTS
](
state
,
reports
)
{
if
(
reports
.
base
&&
reports
.
head
)
{
const
filterKey
=
'
cve
'
;
const
parsedHead
=
parseSastIssues
(
reports
.
head
,
state
.
blobPath
.
head
);
const
parsedBase
=
parseSastIssues
(
reports
.
base
,
state
.
blobPath
.
base
);
const
newIssues
=
filterByKey
(
parsedHead
,
parsedBase
,
filterKey
);
const
resolvedIssues
=
filterByKey
(
parsedBase
,
parsedHead
,
filterKey
);
const
allIssues
=
filterByKey
(
parsedHead
,
newIssues
.
concat
(
resolvedIssues
),
filterKey
);
Object
.
assign
(
state
.
dependencyScanning
,
{
newIssues
,
resolvedIssues
,
allIssues
,
isLoading
:
false
,
});
Object
.
assign
(
state
.
summaryCounts
,
{
added
:
state
.
summaryCounts
.
added
+
newIssues
.
length
,
fixed
:
state
.
summaryCounts
.
fixed
+
resolvedIssues
.
length
,
});
}
else
{
Object
.
assign
(
state
.
dependencyScanning
,
{
newIssues
:
parseSastIssues
(
reports
.
head
,
state
.
blobPath
.
head
),
isLoading
:
false
,
});
}
},
[
types
.
RECEIVE_DEPENDENCY_SCANNING_ERROR
](
state
)
{
Object
.
assign
(
state
.
dependencyScanning
,
{
isLoading
:
false
,
hasError
:
true
,
});
},
};
ee/app/assets/javascripts/vue_shared/security_reports/store/state.js
0 → 100644
View file @
38cf8d53
export
default
()
=>
({
summaryCounts
:
{
added
:
0
,
fixed
:
0
,
},
blobPath
:
{
head
:
null
,
base
:
null
,
},
sast
:
{
paths
:
{
head
:
null
,
base
:
null
,
},
isLoading
:
false
,
hasError
:
false
,
newIssues
:
[],
resolvedIssues
:
[],
allIssues
:
[],
},
sastContainer
:
{
paths
:
{
head
:
null
,
base
:
null
,
},
isLoading
:
false
,
hasError
:
false
,
newIssues
:
[],
resolvedIssues
:
[],
},
dast
:
{
paths
:
{
head
:
null
,
base
:
null
,
},
isLoading
:
false
,
hasError
:
false
,
newIssues
:
[],
resolvedIssues
:
[],
},
dependencyScanning
:
{
paths
:
{
head
:
null
,
base
:
null
,
},
isLoading
:
false
,
hasError
:
false
,
newIssues
:
[],
resolvedIssues
:
[],
allIssues
:
[],
},
});
ee/app/assets/javascripts/vue_shared/security_reports/store/utils.js
0 → 100644
View file @
38cf8d53
import
{
stripHtml
}
from
'
~/lib/utils/text_utility
'
;
import
{
n__
,
s__
,
sprintf
}
from
'
~/locale
'
;
/**
* Maps SAST & Dependency scanning issues:
* { tool: String, message: String, url: String , cve: String ,
* file: String , solution: String, priority: String }
* to contain:
* { name: String, path: String, line: String, urlPath: String, priority: String }
* @param {Array} issues
* @param {String} path
*/
export
const
parseSastIssues
=
(
issues
=
[],
path
=
''
)
=>
issues
.
map
(
issue
=>
Object
.
assign
({},
issue
,
{
name
:
issue
.
message
,
path
:
issue
.
file
,
urlPath
:
issue
.
line
?
`
${
path
}
/
${
issue
.
file
}
#L
${
issue
.
line
}
`
:
`
${
path
}
/
${
issue
.
file
}
`
,
}),
);
/**
* Parses Sast Container results into a common format to allow to use the same Vue component
* And adds an external link
*
* @param {Array} data
* @returns {Array}
*/
export
const
parseSastContainer
=
(
data
=
[])
=>
data
.
map
(
el
=>
({
name
:
el
.
vulnerability
,
priority
:
el
.
severity
,
path
:
el
.
namespace
,
// external link to provide better description
nameLink
:
`https://cve.mitre.org/cgi-bin/cvename.cgi?name=
${
el
.
vulnerability
}
`
,
...
el
,
}));
export
const
parseDastIssues
=
(
issues
=
[])
=>
issues
.
map
(
issue
=>
({
parsedDescription
:
stripHtml
(
issue
.
desc
,
'
'
),
priority
:
issue
.
riskdesc
,
...
issue
,
}));
/**
* Compares two arrays by the given key and returns the difference
*
* @param {Array} firstArray
* @param {Array} secondArray
* @param {String} key
* @returns {Array}
*/
export
const
filterByKey
=
(
firstArray
=
[],
secondArray
=
[],
key
=
''
)
=>
firstArray
.
filter
(
item
=>
!
secondArray
.
find
(
el
=>
el
[
key
]
===
item
[
key
]));
export
const
getUnapprovedVulnerabilities
=
(
issues
=
[],
unapproved
=
[])
=>
issues
.
filter
(
item
=>
unapproved
.
find
(
el
=>
el
===
item
.
vulnerability
));
export
const
textBuilder
=
(
type
=
''
,
paths
=
{},
newIssues
=
0
,
resolvedIssues
=
0
,
allIssues
=
0
,
)
=>
{
// With no issues
if
(
newIssues
===
0
&&
resolvedIssues
===
0
&&
allIssues
===
0
)
{
return
sprintf
(
s__
(
'
ciReport|%{type} detected no security vulnerabilities
'
),
{
type
});
}
// with no new or fixed but with vulnerabilities
if
(
newIssues
===
0
&&
resolvedIssues
===
0
&&
allIssues
)
{
return
sprintf
(
s__
(
'
ciReport|%{type} detected no new security vulnerabilities
'
),
{
type
});
}
// with new issues and only head
if
(
newIssues
>
0
&&
!
paths
.
base
)
{
return
sprintf
(
n__
(
'
%{type} was unable to compare existing and new vulnerabilities. It detected %d vulnerability
'
,
'
%{type} was unable to compare existing and new vulnerabilities. It detected %d vulnerabilities
'
,
newIssues
,
),
{
type
},
);
}
// with head + base
if
(
paths
.
base
&&
paths
.
head
)
{
// with only new issues
if
(
newIssues
>
0
&&
resolvedIssues
===
0
)
{
return
sprintf
(
n__
(
'
%{type} detected %d new vulnerability
'
,
'
%{type} detected %d new vulnerabilities
'
,
newIssues
,
),
{
type
},
);
}
// with new and fixed issues
if
(
newIssues
>
0
&&
resolvedIssues
>
0
)
{
return
`
${
sprintf
(
n__
(
'
%{type} detected %d new vulnerability
'
,
'
%{type} detected %d new vulnerabilities
'
,
newIssues
,
),
{
type
},
)}
${
n__
(
'
and %d fixed vulnerability
'
,
'
and %d fixed vulnerabilities
'
,
resolvedIssues
)}
`
;
}
// with only fixed issues
if
(
newIssues
===
0
&&
resolvedIssues
>
0
)
{
return
sprintf
(
n__
(
'
%{type} detected %d fixed vulnerability
'
,
'
%{type} detected %d fixed vulnerabilities
'
,
resolvedIssues
,
),
{
type
},
);
}
}
return
''
;
};
export
const
statusIcon
=
(
failed
=
false
,
newIssues
=
0
,
neutralIssues
=
0
)
=>
{
if
(
failed
||
newIssues
>
0
||
neutralIssues
>
0
)
{
return
'
warning
'
;
}
return
'
success
'
;
};
spec/javascripts/helpers/vuex_action_helper.js
View file @
38cf8d53
...
...
@@ -26,8 +26,29 @@ export default (action, payload, state, expectedMutations, done) => {
}
};
// mock dispatch
const
dispatch
=
(
type
,
dispatchPayload
)
=>
{
const
mutation
=
expectedMutations
[
count
];
try
{
expect
(
mutation
.
type
).
to
.
equal
(
type
);
if
(
dispatchPayload
)
{
expect
(
mutation
.
payload
).
to
.
deep
.
equal
(
dispatchPayload
);
}
}
catch
(
error
)
{
done
(
error
);
}
count
++
;
if
(
count
>=
expectedMutations
.
length
)
{
done
();
}
};
// call the action with mocked store and arguments
action
({
commit
,
state
},
payload
);
action
({
commit
,
state
,
dispatch
},
payload
);
// check if no mutations should have been dispatched
if
(
expectedMutations
.
length
===
0
)
{
...
...
spec/javascripts/vue_shared/security_reports/mock_data.js
View file @
38cf8d53
This diff is collapsed.
Click to expand it.
spec/javascripts/vue_shared/security_reports/store/actions_spec.js
0 → 100644
View file @
38cf8d53
This diff is collapsed.
Click to expand it.
spec/javascripts/vue_shared/security_reports/store/getters_spec.js
0 → 100644
View file @
38cf8d53
This diff is collapsed.
Click to expand it.
spec/javascripts/vue_shared/security_reports/store/mutations_spec.js
0 → 100644
View file @
38cf8d53
import
state
from
'
ee/vue_shared/security_reports/store/state
'
;
import
mutations
from
'
ee/vue_shared/security_reports/store/mutations
'
;
import
*
as
types
from
'
ee/vue_shared/security_reports/store/mutation_types
'
;
import
{
sastIssues
,
sastIssuesBase
,
parsedSastIssuesHead
,
parsedSastBaseStore
,
dockerReport
,
dockerBaseReport
,
dockerNewIssues
,
dockerOnlyHeadParsed
,
dast
,
dastBase
,
parsedDastNewIssues
,
parsedDast
,
parsedSastIssuesStore
,
}
from
'
../mock_data
'
;
describe
(
'
security reports mutations
'
,
()
=>
{
let
stateCopy
;
beforeEach
(()
=>
{
stateCopy
=
state
();
});
describe
(
'
SET_HEAD_BLOB_PATH
'
,
()
=>
{
it
(
'
should set head blob path
'
,
()
=>
{
mutations
[
types
.
SET_HEAD_BLOB_PATH
](
stateCopy
,
'
head_blob_path
'
);
expect
(
stateCopy
.
blobPath
.
head
).
toEqual
(
'
head_blob_path
'
);
});
});
describe
(
'
SET_BASE_BLOB_PATH
'
,
()
=>
{
it
(
'
should set base blob path
'
,
()
=>
{
mutations
[
types
.
SET_BASE_BLOB_PATH
](
stateCopy
,
'
base_blob_path
'
);
expect
(
stateCopy
.
blobPath
.
base
).
toEqual
(
'
base_blob_path
'
);
});
});
describe
(
'
SET_SAST_HEAD_PATH
'
,
()
=>
{
it
(
'
should set sast head path
'
,
()
=>
{
mutations
[
types
.
SET_SAST_HEAD_PATH
](
stateCopy
,
'
sast_head_path
'
);
expect
(
stateCopy
.
sast
.
paths
.
head
).
toEqual
(
'
sast_head_path
'
);
});
});
describe
(
'
SET_SAST_BASE_PATH
'
,
()
=>
{
it
(
'
sets sast base path
'
,
()
=>
{
mutations
[
types
.
SET_SAST_BASE_PATH
](
stateCopy
,
'
sast_base_path
'
);
expect
(
stateCopy
.
sast
.
paths
.
base
).
toEqual
(
'
sast_base_path
'
);
});
});
describe
(
'
REQUEST_SAST_REPORTS
'
,
()
=>
{
it
(
'
should set sast loading flag to true
'
,
()
=>
{
mutations
[
types
.
REQUEST_SAST_REPORTS
](
stateCopy
);
expect
(
stateCopy
.
sast
.
isLoading
).
toEqual
(
true
);
});
});
describe
(
'
RECEIVE_SAST_REPORTS
'
,
()
=>
{
describe
(
'
with head and base
'
,
()
=>
{
it
(
'
should set new, fixed and all issues
'
,
()
=>
{
mutations
[
types
.
SET_BASE_BLOB_PATH
](
stateCopy
,
'
path
'
);
mutations
[
types
.
SET_HEAD_BLOB_PATH
](
stateCopy
,
'
path
'
);
mutations
[
types
.
RECEIVE_SAST_REPORTS
](
stateCopy
,
{
head
:
sastIssues
,
base
:
sastIssuesBase
,
});
expect
(
stateCopy
.
sast
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
sast
.
newIssues
).
toEqual
(
parsedSastIssuesHead
);
expect
(
stateCopy
.
sast
.
resolvedIssues
).
toEqual
(
parsedSastBaseStore
);
});
});
describe
(
'
with head
'
,
()
=>
{
it
(
'
should set new issues
'
,
()
=>
{
mutations
[
types
.
SET_HEAD_BLOB_PATH
](
stateCopy
,
'
path
'
);
mutations
[
types
.
RECEIVE_SAST_REPORTS
](
stateCopy
,
{
head
:
sastIssues
,
});
expect
(
stateCopy
.
sast
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
sast
.
newIssues
).
toEqual
(
parsedSastIssuesStore
);
});
});
});
describe
(
'
RECEIVE_SAST_REPORTS_ERROR
'
,
()
=>
{
it
(
'
should set loading flag to false and error flag to true for sast
'
,
()
=>
{
mutations
[
types
.
RECEIVE_SAST_REPORTS_ERROR
](
stateCopy
);
expect
(
stateCopy
.
sast
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
sast
.
hasError
).
toEqual
(
true
);
});
});
describe
(
'
SET_SAST_CONTAINER_HEAD_PATH
'
,
()
=>
{
it
(
'
should set sast container head path
'
,
()
=>
{
mutations
[
types
.
SET_SAST_CONTAINER_HEAD_PATH
](
stateCopy
,
'
head_path
'
);
expect
(
stateCopy
.
sastContainer
.
paths
.
head
).
toEqual
(
'
head_path
'
);
});
});
describe
(
'
SET_SAST_CONTAINER_BASE_PATH
'
,
()
=>
{
it
(
'
should set sast container base path
'
,
()
=>
{
mutations
[
types
.
SET_SAST_CONTAINER_BASE_PATH
](
stateCopy
,
'
base_path
'
);
expect
(
stateCopy
.
sastContainer
.
paths
.
base
).
toEqual
(
'
base_path
'
);
});
});
describe
(
'
REQUEST_SAST_CONTAINER_REPORTS
'
,
()
=>
{
it
(
'
should set sast container loading flag to true
'
,
()
=>
{
mutations
[
types
.
REQUEST_SAST_CONTAINER_REPORTS
](
stateCopy
);
expect
(
stateCopy
.
sastContainer
.
isLoading
).
toEqual
(
true
);
});
});
describe
(
'
RECEIVE_SAST_CONTAINER_REPORTS
'
,
()
=>
{
describe
(
'
with head and base
'
,
()
=>
{
it
(
'
should set new and resolved issues
'
,
()
=>
{
mutations
[
types
.
RECEIVE_SAST_CONTAINER_REPORTS
](
stateCopy
,
{
head
:
dockerReport
,
base
:
dockerBaseReport
,
});
expect
(
stateCopy
.
sastContainer
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
sastContainer
.
newIssues
).
toEqual
(
dockerNewIssues
);
expect
(
stateCopy
.
sastContainer
.
resolvedIssues
).
toEqual
([]);
});
});
describe
(
'
with head
'
,
()
=>
{
it
(
'
should set new issues
'
,
()
=>
{
mutations
[
types
.
RECEIVE_SAST_CONTAINER_REPORTS
](
stateCopy
,
{
head
:
dockerReport
,
});
expect
(
stateCopy
.
sastContainer
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
sastContainer
.
newIssues
).
toEqual
(
dockerOnlyHeadParsed
);
});
});
});
describe
(
'
RECEIVE_SAST_CONTAINER_ERROR
'
,
()
=>
{
it
(
'
should set sast container loading flag to false and error flag to true
'
,
()
=>
{
mutations
[
types
.
RECEIVE_SAST_CONTAINER_ERROR
](
stateCopy
);
expect
(
stateCopy
.
sastContainer
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
sastContainer
.
hasError
).
toEqual
(
true
);
});
});
describe
(
'
SET_DAST_HEAD_PATH
'
,
()
=>
{
it
(
'
should set dast head path
'
,
()
=>
{
mutations
[
types
.
SET_DAST_HEAD_PATH
](
stateCopy
,
'
head_path
'
);
expect
(
stateCopy
.
dast
.
paths
.
head
).
toEqual
(
'
head_path
'
);
});
});
describe
(
'
SET_DAST_BASE_PATH
'
,
()
=>
{
it
(
'
should set dast base path
'
,
()
=>
{
mutations
[
types
.
SET_DAST_BASE_PATH
](
stateCopy
,
'
base_path
'
);
expect
(
stateCopy
.
dast
.
paths
.
base
).
toEqual
(
'
base_path
'
);
});
});
describe
(
'
REQUEST_DAST_REPORTS
'
,
()
=>
{
it
(
'
should set dast loading flag to true
'
,
()
=>
{
mutations
[
types
.
REQUEST_DAST_REPORTS
](
stateCopy
);
expect
(
stateCopy
.
dast
.
isLoading
).
toEqual
(
true
);
});
});
describe
(
'
RECEIVE_DAST_REPORTS
'
,
()
=>
{
describe
(
'
with head and base
'
,
()
=>
{
it
(
'
sets new and resolved issues with the given data
'
,
()
=>
{
mutations
[
types
.
RECEIVE_DAST_REPORTS
](
stateCopy
,
{
head
:
dast
,
base
:
dastBase
,
});
expect
(
stateCopy
.
dast
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
dast
.
newIssues
).
toEqual
(
parsedDastNewIssues
);
expect
(
stateCopy
.
dast
.
resolvedIssues
).
toEqual
([]);
});
});
describe
(
'
with head
'
,
()
=>
{
it
(
'
sets new issues with the given data
'
,
()
=>
{
mutations
[
types
.
RECEIVE_DAST_REPORTS
](
stateCopy
,
{
head
:
dast
,
});
expect
(
stateCopy
.
dast
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
dast
.
newIssues
).
toEqual
(
parsedDast
);
});
});
});
describe
(
'
RECEIVE_DAST_ERROR
'
,
()
=>
{
it
(
'
should set dast loading flag to false and error flag to true
'
,
()
=>
{
mutations
[
types
.
RECEIVE_DAST_ERROR
](
stateCopy
);
expect
(
stateCopy
.
dast
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
dast
.
hasError
).
toEqual
(
true
);
});
});
describe
(
'
SET_DEPENDENCY_SCANNING_HEAD_PATH
'
,
()
=>
{
it
(
'
should set dependency scanning head path
'
,
()
=>
{
mutations
[
types
.
SET_DEPENDENCY_SCANNING_HEAD_PATH
](
stateCopy
,
'
head_path
'
);
expect
(
stateCopy
.
dependencyScanning
.
paths
.
head
).
toEqual
(
'
head_path
'
);
});
});
describe
(
'
SET_DEPENDENCY_SCANNING_BASE_PATH
'
,
()
=>
{
it
(
'
should set dependency scanning base path
'
,
()
=>
{
mutations
[
types
.
SET_DEPENDENCY_SCANNING_BASE_PATH
](
stateCopy
,
'
base_path
'
);
expect
(
stateCopy
.
dependencyScanning
.
paths
.
base
).
toEqual
(
'
base_path
'
);
});
});
describe
(
'
REQUEST_DEPENDENCY_SCANNING_REPORTS
'
,
()
=>
{
it
(
'
should set dependency scanning loading flag to true
'
,
()
=>
{
mutations
[
types
.
REQUEST_DEPENDENCY_SCANNING_REPORTS
](
stateCopy
);
expect
(
stateCopy
.
dependencyScanning
.
isLoading
).
toEqual
(
true
);
});
});
describe
(
'
RECEIVE_DEPENDENCY_SCANNING_REPORTS
'
,
()
=>
{
describe
(
'
with head and base
'
,
()
=>
{
it
(
'
should set new, fixed and all issues
'
,
()
=>
{
mutations
[
types
.
SET_BASE_BLOB_PATH
](
stateCopy
,
'
path
'
);
mutations
[
types
.
SET_HEAD_BLOB_PATH
](
stateCopy
,
'
path
'
);
mutations
[
types
.
RECEIVE_DEPENDENCY_SCANNING_REPORTS
](
stateCopy
,
{
head
:
sastIssues
,
base
:
sastIssuesBase
,
});
expect
(
stateCopy
.
dependencyScanning
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
dependencyScanning
.
newIssues
).
toEqual
(
parsedSastIssuesHead
);
expect
(
stateCopy
.
dependencyScanning
.
resolvedIssues
).
toEqual
(
parsedSastBaseStore
);
});
});
describe
(
'
with head
'
,
()
=>
{
it
(
'
should set new issues
'
,
()
=>
{
mutations
[
types
.
SET_HEAD_BLOB_PATH
](
stateCopy
,
'
path
'
);
mutations
[
types
.
RECEIVE_DEPENDENCY_SCANNING_REPORTS
](
stateCopy
,
{
head
:
sastIssues
,
});
expect
(
stateCopy
.
dependencyScanning
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
dependencyScanning
.
newIssues
).
toEqual
(
parsedSastIssuesStore
);
});
});
});
describe
(
'
RECEIVE_DEPENDENCY_SCANNING_ERROR
'
,
()
=>
{
it
(
'
should set dependency scanning loading flag to false and error flag to true
'
,
()
=>
{
mutations
[
types
.
RECEIVE_DEPENDENCY_SCANNING_ERROR
](
stateCopy
);
expect
(
stateCopy
.
dependencyScanning
.
isLoading
).
toEqual
(
false
);
expect
(
stateCopy
.
dependencyScanning
.
hasError
).
toEqual
(
true
);
});
});
});
spec/javascripts/vue_shared/security_reports/store/utils_spec.js
0 → 100644
View file @
38cf8d53
import
{
parseSastIssues
,
parseSastContainer
,
parseDastIssues
,
filterByKey
,
getUnapprovedVulnerabilities
,
textBuilder
,
statusIcon
,
}
from
'
ee/vue_shared/security_reports/store/utils
'
;
import
{
sastIssues
,
dockerReport
,
dast
,
parsedDast
}
from
'
../mock_data
'
;
describe
(
'
security reports utils
'
,
()
=>
{
describe
(
'
parseSastIssues
'
,
()
=>
{
it
(
'
should parse the received issues
'
,
()
=>
{
const
security
=
parseSastIssues
(
sastIssues
,
'
path
'
)[
0
];
expect
(
security
.
name
).
toEqual
(
sastIssues
[
0
].
message
);
expect
(
security
.
path
).
toEqual
(
sastIssues
[
0
].
file
);
});
});
describe
(
'
parseSastContainer
'
,
()
=>
{
it
(
'
parses sast container issues
'
,
()
=>
{
const
parsed
=
parseSastContainer
(
dockerReport
.
vulnerabilities
)[
0
];
expect
(
parsed
.
name
).
toEqual
(
dockerReport
.
vulnerabilities
[
0
].
vulnerability
);
expect
(
parsed
.
priority
).
toEqual
(
dockerReport
.
vulnerabilities
[
0
].
severity
);
expect
(
parsed
.
path
).
toEqual
(
dockerReport
.
vulnerabilities
[
0
].
namespace
);
expect
(
parsed
.
nameLink
).
toEqual
(
`https://cve.mitre.org/cgi-bin/cvename.cgi?name=
${
dockerReport
.
vulnerabilities
[
0
].
vulnerability
}
`
,
);
});
});
describe
(
'
parseDastIssues
'
,
()
=>
{
it
(
'
parsed dast report
'
,
()
=>
{
expect
(
parseDastIssues
(
dast
.
site
.
alerts
)).
toEqual
(
parsedDast
);
});
});
describe
(
'
filterByKey
'
,
()
=>
{
it
(
'
filters the array with the provided key
'
,
()
=>
{
const
array1
=
[{
id
:
'
1234
'
},
{
id
:
'
abg543
'
},
{
id
:
'
214swfA
'
}];
const
array2
=
[{
id
:
'
1234
'
},
{
id
:
'
abg543
'
},
{
id
:
'
453OJKs
'
}];
expect
(
filterByKey
(
array1
,
array2
,
'
id
'
)).
toEqual
([{
id
:
'
214swfA
'
}]);
});
});
describe
(
'
getUnapprovedVulnerabilities
'
,
()
=>
{
it
(
'
return unapproved vulnerabilities
'
,
()
=>
{
const
unapproved
=
getUnapprovedVulnerabilities
(
dockerReport
.
vulnerabilities
,
dockerReport
.
unapproved
,
);
expect
(
unapproved
.
length
).
toEqual
(
dockerReport
.
unapproved
.
length
);
expect
(
unapproved
[
0
].
vulnerability
).
toEqual
(
dockerReport
.
unapproved
[
0
]);
expect
(
unapproved
[
1
].
vulnerability
).
toEqual
(
dockerReport
.
unapproved
[
1
]);
});
});
describe
(
'
textBuilder
'
,
()
=>
{
describe
(
'
with no issues
'
,
()
=>
{
it
(
'
should return no vulnerabiltities text
'
,
()
=>
{
expect
(
textBuilder
()).
toEqual
(
'
detected no security vulnerabilities
'
);
});
});
describe
(
'
with only `all` issues
'
,
()
=>
{
it
(
'
should return no new vulnerabiltities text
'
,
()
=>
{
expect
(
textBuilder
(
''
,
{},
0
,
0
,
1
)).
toEqual
(
'
detected no new security vulnerabilities
'
);
});
});
describe
(
'
with new issues and without base
'
,
()
=>
{
it
(
'
should return unable to compare text
'
,
()
=>
{
expect
(
textBuilder
(
''
,
{
head
:
'
foo
'
},
1
,
0
,
0
)).
toEqual
(
'
was unable to compare existing and new vulnerabilities. It detected 1 vulnerability
'
,
);
});
});
describe
(
'
with base and head
'
,
()
=>
{
describe
(
'
with only new issues
'
,
()
=>
{
it
(
'
should return new issues text
'
,
()
=>
{
expect
(
textBuilder
(
''
,
{
head
:
'
foo
'
,
base
:
'
foo
'
},
1
,
0
,
0
)).
toEqual
(
'
detected 1 new vulnerability
'
,
);
});
});
describe
(
'
with new and resolved issues
'
,
()
=>
{
it
(
'
should return new and fixed issues text
'
,
()
=>
{
expect
(
textBuilder
(
''
,
{
head
:
'
foo
'
,
base
:
'
foo
'
},
1
,
1
,
0
).
replace
(
/
\n
+
\s
+/m
,
'
'
),
).
toEqual
(
'
detected 1 new vulnerability and 1 fixed vulnerability
'
);
});
});
describe
(
'
with only resolved issues
'
,
()
=>
{
it
(
'
should return fixed issues text
'
,
()
=>
{
expect
(
textBuilder
(
''
,
{
head
:
'
foo
'
,
base
:
'
foo
'
},
0
,
1
,
0
)).
toEqual
(
'
detected 1 fixed vulnerability
'
,
);
});
});
});
});
describe
(
'
statusIcon
'
,
()
=>
{
describe
(
'
with failed report
'
,
()
=>
{
it
(
'
returns warning
'
,
()
=>
{
expect
(
statusIcon
(
true
)).
toEqual
(
'
warning
'
);
});
});
describe
(
'
with new issues
'
,
()
=>
{
it
(
'
returns warning
'
,
()
=>
{
expect
(
statusIcon
(
false
,
1
)).
toEqual
(
'
warning
'
);
});
});
describe
(
'
with neutral issues
'
,
()
=>
{
it
(
'
returns warning
'
,
()
=>
{
expect
(
statusIcon
(
false
,
0
,
1
)).
toEqual
(
'
warning
'
);
});
});
describe
(
'
without new or neutal issues
'
,
()
=>
{
it
(
'
returns success
'
,
()
=>
{
expect
(
statusIcon
()).
toEqual
(
'
success
'
);
});
});
});
});
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