Commit 8cb9f02e authored by Phil Hughes's avatar Phil Hughes

Merge branch '49614-dynamic-component-in-report-issue-ee' into 'master'

Use new extendable report_issues.vue (gitlab-ce!20843)

See merge request gitlab-org/gitlab-ee!6667
parents 6eca39f8 87482577
export const STATUS_FAILED = 'failed';
export const STATUS_SUCCESS = 'success';
export const STATUS_NEUTRAL = 'neutral';
export const components = {};
export const componentNames = {};
<script>
import Icon from '~/vue_shared/components/icon.vue';
import {
STATUS_FAILED,
STATUS_NEUTRAL,
STATUS_SUCCESS,
} from '~/vue_shared/components/reports/constants';
export default {
name: 'IssueStatusIcon',
components: {
Icon,
},
props: {
// failed || success
status: {
type: String,
required: true,
},
},
computed: {
iconName() {
if (this.isStatusFailed) {
return 'status_failed_borderless';
} else if (this.isStatusSuccess) {
return 'status_success_borderless';
}
return 'status_created_borderless';
},
isStatusFailed() {
return this.status === STATUS_FAILED;
},
isStatusSuccess() {
return this.status === STATUS_SUCCESS;
},
isStatusNeutral() {
return this.status === STATUS_NEUTRAL;
},
},
};
</script>
<template>
<div
:class="{
failed: isStatusFailed,
success: isStatusSuccess,
neutral: isStatusNeutral,
}"
class="report-block-list-icon"
>
<icon
:name="iconName"
:size="32"
/>
</div>
</template>
<script> <script>
import IssuesBlock from '~/vue_shared/components/reports/report_issues.vue'; import IssuesBlock from '~/vue_shared/components/reports/report_issues.vue';
import {
STATUS_SUCCESS,
STATUS_FAILED,
STATUS_NEUTRAL,
} from '~/vue_shared/components/reports/constants';
import { componentNames } from 'ee/vue_shared/components/reports/issue_body';
import SastContainerInfo from 'ee/vue_shared/security_reports/components/sast_container_info.vue'; import SastContainerInfo from 'ee/vue_shared/security_reports/components/sast_container_info.vue';
import { SAST_CONTAINER } from 'ee/vue_shared/security_reports/store/constants';
/** /**
* Renders block of issues * Renders block of issues
...@@ -13,7 +18,10 @@ export default { ...@@ -13,7 +18,10 @@ export default {
IssuesBlock, IssuesBlock,
SastContainerInfo, SastContainerInfo,
}, },
sastContainer: SAST_CONTAINER, componentNames,
success: STATUS_SUCCESS,
failed: STATUS_FAILED,
neutral: STATUS_NEUTRAL,
props: { props: {
unresolvedIssues: { unresolvedIssues: {
type: Array, type: Array,
...@@ -35,9 +43,10 @@ export default { ...@@ -35,9 +43,10 @@ export default {
required: false, required: false,
default: () => [], default: () => [],
}, },
type: { component: {
type: String, type: String,
required: true, required: false,
default: '',
}, },
}, },
data() { data() {
...@@ -45,11 +54,6 @@ export default { ...@@ -45,11 +54,6 @@ export default {
isFullReportVisible: false, isFullReportVisible: false,
}; };
}, },
computed: {
unresolvedIssuesStatus() {
return this.type === 'license' ? 'neutral' : 'failed';
},
},
methods: { methods: {
openFullReport() { openFullReport() {
this.isFullReportVisible = true; this.isFullReportVisible = true;
...@@ -59,38 +63,37 @@ export default { ...@@ -59,38 +63,37 @@ export default {
</script> </script>
<template> <template>
<div class="report-block-container"> <div class="report-block-container">
<sast-container-info v-if="type === $options.sastContainer" /> <sast-container-info v-if="component === $options.componentNames.SastContainerIssueBody" />
<issues-block <issues-block
v-if="unresolvedIssues.length" v-if="unresolvedIssues.length"
:type="type" :component="component"
:status="unresolvedIssuesStatus"
:issues="unresolvedIssues" :issues="unresolvedIssues"
:status="$options.failed"
class="js-mr-code-new-issues" class="js-mr-code-new-issues"
/> />
<issues-block <issues-block
v-if="isFullReportVisible" v-if="isFullReportVisible"
:type="type" :component="component"
:issues="allIssues" :issues="allIssues"
:status="$options.failed"
class="js-mr-code-all-issues" class="js-mr-code-all-issues"
status="failed"
/> />
<issues-block <issues-block
v-if="neutralIssues.length" v-if="neutralIssues.length"
:type="type" :component="component"
:issues="neutralIssues" :issues="neutralIssues"
:status="$options.neutral"
class="js-mr-code-non-issues" class="js-mr-code-non-issues"
status="neutral"
/> />
<issues-block <issues-block
v-if="resolvedIssues.length" v-if="resolvedIssues.length"
:type="type" :component="component"
:issues="resolvedIssues" :issues="resolvedIssues"
:status="$options.success"
class="js-mr-code-resolved-issues" class="js-mr-code-resolved-issues"
status="success"
/> />
<button <button
......
<script> <script>
import Icon from '~/vue_shared/components/icon.vue'; import IssueStatusIcon from '~/vue_shared/components/reports/issue_status_icon.vue';
import { components, componentNames } from 'ee/vue_shared/components/reports/issue_body';
import PerformanceIssue from 'ee/vue_merge_request_widget/components/performance_issue_body.vue';
import CodequalityIssue from 'ee/vue_merge_request_widget/components/codequality_issue_body.vue';
import LicenseIssue from 'ee/vue_merge_request_widget/components/license_issue_body.vue';
import SastIssue from 'ee/vue_shared/security_reports/components/sast_issue_body.vue';
import SastContainerIssue from 'ee/vue_shared/security_reports/components/sast_container_issue_body.vue';
import DastIssue from 'ee/vue_shared/security_reports/components/dast_issue_body.vue';
import { SAST, DAST, SAST_CONTAINER } from 'ee/vue_shared/security_reports/store/constants';
export default { export default {
name: 'ReportIssues', name: 'ReportIssues',
components: { components: {
Icon, IssueStatusIcon,
SastIssue, ...components,
SastContainerIssue,
DastIssue,
PerformanceIssue,
CodequalityIssue,
LicenseIssue,
}, },
props: { props: {
issues: { issues: {
type: Array, type: Array,
required: true, required: true,
}, },
// security || codequality || performance || docker || dast || license component: {
type: {
type: String, type: String,
required: true, required: false,
default: '',
validator: value => value === '' || Object.values(componentNames).includes(value),
}, },
// failed || success // failed || success
status: { status: {
...@@ -36,44 +25,6 @@ export default { ...@@ -36,44 +25,6 @@ export default {
required: true, required: true,
}, },
}, },
computed: {
iconName() {
if (this.isStatusFailed) {
return 'status_failed_borderless';
} else if (this.isStatusSuccess) {
return 'status_success_borderless';
}
return 'status_created_borderless';
},
isStatusFailed() {
return this.status === 'failed';
},
isStatusSuccess() {
return this.status === 'success';
},
isStatusNeutral() {
return this.status === 'neutral';
},
isTypeCodequality() {
return this.type === 'codequality';
},
isTypePerformance() {
return this.type === 'performance';
},
isTypeLicense() {
return this.type === 'license';
},
isTypeSast() {
return this.type === SAST;
},
isTypeSastContainer() {
return this.type === SAST_CONTAINER;
},
isTypeDast() {
return this.type === DAST;
},
},
}; };
</script> </script>
<template> <template>
...@@ -85,60 +36,16 @@ export default { ...@@ -85,60 +36,16 @@ export default {
:key="index" :key="index"
class="report-block-list-issue" class="report-block-list-issue"
> >
<div <issue-status-icon
:class="{ :status="issue.status || status"
failed: isStatusFailed, class="append-right-5"
success: isStatusSuccess,
neutral: isStatusNeutral,
}"
class="report-block-list-icon append-right-5"
>
<icon
v-if="isTypeLicense"
:size="24"
name="status_created_borderless"
css-classes="prepend-left-4"
/>
<icon
v-else
:name="iconName"
:size="32"
/>
</div>
<sast-issue
v-if="isTypeSast"
:issue="issue"
:status="status"
/>
<dast-issue
v-else-if="isTypeDast"
:issue="issue"
:issue-index="index"
:status="status"
/>
<sast-container-issue
v-else-if="isTypeSastContainer"
:issue="issue"
:status="status"
/>
<codequality-issue
v-else-if="isTypeCodequality"
:is-status-success="isStatusSuccess"
:issue="issue"
/>
<performance-issue
v-else-if="isTypePerformance"
:issue="issue"
/> />
<license-issue <component
v-else-if="isTypeLicense" v-if="component"
:is="component"
:issue="issue" :issue="issue"
:status="issue.status || status"
/> />
</li> </li>
</ul> </ul>
......
...@@ -21,7 +21,7 @@ export default { ...@@ -21,7 +21,7 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
type: { component: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
...@@ -183,8 +183,9 @@ export default { ...@@ -183,8 +183,9 @@ export default {
<issues-list <issues-list
:unresolved-issues="unresolvedIssues" :unresolved-issues="unresolvedIssues"
:resolved-issues="resolvedIssues" :resolved-issues="resolvedIssues"
:neutral-issues="neutralIssues"
:all-issues="allIssues" :all-issues="allIssues"
:type="type" :component="component"
/> />
</slot> </slot>
</div> </div>
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Fixed: [name] in [link]:[line] * Fixed: [name] in [link]:[line]
*/ */
import ReportLink from '~/vue_shared/components/reports/report_link.vue'; import ReportLink from '~/vue_shared/components/reports/report_link.vue';
import { STATUS_SUCCESS } from '~/vue_shared/components/reports/constants';
export default { export default {
name: 'CodequalityIssueBody', name: 'CodequalityIssueBody',
...@@ -11,10 +12,9 @@ export default { ...@@ -11,10 +12,9 @@ export default {
components: { components: {
ReportLink, ReportLink,
}, },
props: { props: {
isStatusSuccess: { status: {
type: Boolean, type: String,
required: true, required: true,
}, },
issue: { issue: {
...@@ -22,6 +22,11 @@ export default { ...@@ -22,6 +22,11 @@ export default {
required: true, required: true,
}, },
}, },
computed: {
isStatusSuccess() {
return this.status === STATUS_SUCCESS;
},
},
}; };
</script> </script>
<template> <template>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
export default { export default {
name: 'LicenseIssueBody',
props: { props: {
issue: { issue: {
type: Object, type: Object,
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import ReportSection from '~/vue_shared/components/reports/report_section.vue'; import ReportSection from '~/vue_shared/components/reports/report_section.vue';
import GroupedSecurityReportsApp from 'ee/vue_shared/security_reports/grouped_security_reports_app.vue'; import GroupedSecurityReportsApp from 'ee/vue_shared/security_reports/grouped_security_reports_app.vue';
import reportsMixin from 'ee/vue_shared/security_reports/mixins/reports_mixin'; import reportsMixin from 'ee/vue_shared/security_reports/mixins/reports_mixin';
import { componentNames } from 'ee/vue_shared/components/reports/issue_body';
import { n__, s__, __, sprintf } from '~/locale'; import { n__, s__, __, sprintf } from '~/locale';
import CEWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue'; import CEWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
...@@ -17,6 +18,7 @@ export default { ...@@ -17,6 +18,7 @@ export default {
}, },
extends: CEWidgetOptions, extends: CEWidgetOptions,
mixins: [reportsMixin], mixins: [reportsMixin],
componentNames,
data() { data() {
return { return {
isLoadingCodequality: false, isLoadingCodequality: false,
...@@ -255,8 +257,8 @@ export default { ...@@ -255,8 +257,8 @@ export default {
:unresolved-issues="mr.codeclimateMetrics.newIssues" :unresolved-issues="mr.codeclimateMetrics.newIssues"
:resolved-issues="mr.codeclimateMetrics.resolvedIssues" :resolved-issues="mr.codeclimateMetrics.resolvedIssues"
:has-issues="hasCodequalityIssues" :has-issues="hasCodequalityIssues"
:component="$options.componentNames.CodequalityIssueBody"
class="js-codequality-widget mr-widget-border-top" class="js-codequality-widget mr-widget-border-top"
type="codequality"
/> />
<report-section <report-section
v-if="shouldRenderPerformance" v-if="shouldRenderPerformance"
...@@ -268,8 +270,8 @@ export default { ...@@ -268,8 +270,8 @@ export default {
:resolved-issues="mr.performanceMetrics.improved" :resolved-issues="mr.performanceMetrics.improved"
:neutral-issues="mr.performanceMetrics.neutral" :neutral-issues="mr.performanceMetrics.neutral"
:has-issues="hasPerformanceMetrics" :has-issues="hasPerformanceMetrics"
:component="$options.componentNames.PerformanceIssueBody"
class="js-performance-widget mr-widget-border-top" class="js-performance-widget mr-widget-border-top"
type="performance"
/> />
<grouped-security-reports-app <grouped-security-reports-app
v-if="shouldRenderSecurityReport" v-if="shouldRenderSecurityReport"
...@@ -299,10 +301,10 @@ export default { ...@@ -299,10 +301,10 @@ export default {
:loading-text="translateText('license management').loading" :loading-text="translateText('license management').loading"
:error-text="translateText('license management').error" :error-text="translateText('license management').error"
:success-text="licenseReportText" :success-text="licenseReportText"
:unresolved-issues="mr.licenseReport" :neutral-issues="mr.licenseReport"
:has-issues="hasLicenseReportIssues" :has-issues="hasLicenseReportIssues"
:component="$options.componentNames.LicenseIssueBody"
class="js-license-report-widget mr-widget-border-top" class="js-license-report-widget mr-widget-border-top"
type="license"
/> />
<div class="mr-section-container"> <div class="mr-section-container">
<div class="mr-widget-section"> <div class="mr-widget-section">
......
import {
components as componentsCE,
componentNames as componentNamesCE,
} from '~/vue_shared/components/reports/issue_body';
import PerformanceIssueBody from 'ee/vue_merge_request_widget/components/performance_issue_body.vue';
import CodequalityIssueBody from 'ee/vue_merge_request_widget/components/codequality_issue_body.vue';
import LicenseIssueBody from 'ee/vue_merge_request_widget/components/license_issue_body.vue';
import SastIssueBody from 'ee/vue_shared/security_reports/components/sast_issue_body.vue';
import SastContainerIssueBody from 'ee/vue_shared/security_reports/components/sast_container_issue_body.vue';
import DastIssueBody from 'ee/vue_shared/security_reports/components/dast_issue_body.vue';
export const components = {
...componentsCE,
PerformanceIssueBody,
CodequalityIssueBody,
LicenseIssueBody,
SastContainerIssueBody,
SastIssueBody,
DastIssueBody,
};
export const componentNames = {
...componentNamesCE,
PerformanceIssueBody: PerformanceIssueBody.name,
CodequalityIssueBody: CodequalityIssueBody.name,
LicenseIssueBody: LicenseIssueBody.name,
SastContainerIssueBody: SastContainerIssueBody.name,
SastIssueBody: SastIssueBody.name,
DastIssueBody: DastIssueBody.name,
};
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import ModalOpenName from '~/vue_shared/components/reports/modal_open_name.vue'; import ModalOpenName from '~/vue_shared/components/reports/modal_open_name.vue';
export default { export default {
name: 'SastIssueBody', name: 'DastIssueBody',
components: { components: {
ModalOpenName, ModalOpenName,
}, },
...@@ -16,11 +16,6 @@ export default { ...@@ -16,11 +16,6 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
issueIndex: {
type: Number,
required: true,
},
// failed || success // failed || success
status: { status: {
type: String, type: String,
......
...@@ -3,8 +3,8 @@ import { mapActions, mapState, mapGetters } from 'vuex'; ...@@ -3,8 +3,8 @@ import { mapActions, mapState, mapGetters } from 'vuex';
import ReportSection from '~/vue_shared/components/reports/report_section.vue'; import ReportSection from '~/vue_shared/components/reports/report_section.vue';
import SummaryRow from '~/vue_shared/components/reports/summary_row.vue'; import SummaryRow from '~/vue_shared/components/reports/summary_row.vue';
import IssuesList from '~/vue_shared/components/reports/issues_list.vue'; import IssuesList from '~/vue_shared/components/reports/issues_list.vue';
import { componentNames } from 'ee/vue_shared/components/reports/issue_body';
import IssueModal from './components/modal.vue'; import IssueModal from './components/modal.vue';
import { SAST, DAST, SAST_CONTAINER } from './store/constants';
import securityReportsMixin from './mixins/security_report_mixin'; import securityReportsMixin from './mixins/security_report_mixin';
import createStore from './store'; import createStore from './store';
...@@ -111,9 +111,7 @@ export default { ...@@ -111,9 +111,7 @@ export default {
required: true, required: true,
}, },
}, },
sast: SAST, componentNames,
dast: DAST,
sastContainer: SAST_CONTAINER,
computed: { computed: {
...mapState(['sast', 'sastContainer', 'dast', 'dependencyScanning', 'summaryCounts']), ...mapState(['sast', 'sastContainer', 'dast', 'dependencyScanning', 'summaryCounts']),
...mapGetters([ ...mapGetters([
...@@ -229,7 +227,7 @@ export default { ...@@ -229,7 +227,7 @@ export default {
:unresolved-issues="sast.newIssues" :unresolved-issues="sast.newIssues"
:resolved-issues="sast.resolvedIssues" :resolved-issues="sast.resolvedIssues"
:all-issues="sast.allIssues" :all-issues="sast.allIssues"
:type="$options.sast" :component="$options.componentNames.SastIssueBody"
class="js-sast-issue-list report-block-group-list" class="js-sast-issue-list report-block-group-list"
/> />
</template> </template>
...@@ -248,7 +246,7 @@ export default { ...@@ -248,7 +246,7 @@ export default {
:unresolved-issues="dependencyScanning.newIssues" :unresolved-issues="dependencyScanning.newIssues"
:resolved-issues="dependencyScanning.resolvedIssues" :resolved-issues="dependencyScanning.resolvedIssues"
:all-issues="dependencyScanning.allIssues" :all-issues="dependencyScanning.allIssues"
:type="$options.sast" :component="$options.componentNames.SastIssueBody"
class="js-dss-issue-list report-block-group-list" class="js-dss-issue-list report-block-group-list"
/> />
</template> </template>
...@@ -265,7 +263,7 @@ export default { ...@@ -265,7 +263,7 @@ export default {
v-if="sastContainer.newIssues.length || sastContainer.resolvedIssues.length" v-if="sastContainer.newIssues.length || sastContainer.resolvedIssues.length"
:unresolved-issues="sastContainer.newIssues" :unresolved-issues="sastContainer.newIssues"
:neutral-issues="sastContainer.resolvedIssues" :neutral-issues="sastContainer.resolvedIssues"
:type="$options.sastContainer" :component="$options.componentNames.SastContainerIssueBody"
class="report-block-group-list" class="report-block-group-list"
/> />
</template> </template>
...@@ -282,7 +280,7 @@ export default { ...@@ -282,7 +280,7 @@ export default {
v-if="dast.newIssues.length || dast.resolvedIssues.length" v-if="dast.newIssues.length || dast.resolvedIssues.length"
:unresolved-issues="dast.newIssues" :unresolved-issues="dast.newIssues"
:resolved-issues="dast.resolvedIssues" :resolved-issues="dast.resolvedIssues"
:type="$options.dast" :component="$options.componentNames.DastIssueBody"
class="report-block-group-list" class="report-block-group-list"
/> />
</template> </template>
......
...@@ -3,7 +3,7 @@ import { mapActions, mapState } from 'vuex'; ...@@ -3,7 +3,7 @@ import { mapActions, mapState } from 'vuex';
import { s__, sprintf, n__ } from '~/locale'; import { s__, sprintf, n__ } from '~/locale';
import createFlash from '~/flash'; import createFlash from '~/flash';
import ReportSection from '~/vue_shared/components/reports/report_section.vue'; import ReportSection from '~/vue_shared/components/reports/report_section.vue';
import { SAST, DAST, SAST_CONTAINER } from './store/constants'; import { componentNames } from 'ee/vue_shared/components/reports/issue_body';
import IssueModal from './components/modal.vue'; import IssueModal from './components/modal.vue';
import mixin from './mixins/security_report_mixin'; import mixin from './mixins/security_report_mixin';
import reportsMixin from './mixins/reports_mixin'; import reportsMixin from './mixins/reports_mixin';
...@@ -88,9 +88,7 @@ export default { ...@@ -88,9 +88,7 @@ export default {
required: true, required: true,
}, },
}, },
sast: SAST, componentNames,
dast: DAST,
sastContainer: SAST_CONTAINER,
computed: { computed: {
...mapState(['sast', 'dependencyScanning', 'sastContainer', 'dast']), ...mapState(['sast', 'dependencyScanning', 'sastContainer', 'dast']),
...@@ -216,7 +214,7 @@ export default { ...@@ -216,7 +214,7 @@ export default {
<report-section <report-section
v-if="sastHeadPath" v-if="sastHeadPath"
:always-open="alwaysOpen" :always-open="alwaysOpen"
:type="$options.sast" :component="$options.componentNames.SastIssueBody"
:status="checkReportStatus(sast.isLoading, sast.hasError)" :status="checkReportStatus(sast.isLoading, sast.hasError)"
:loading-text="translateText('SAST').loading" :loading-text="translateText('SAST').loading"
:error-text="translateText('SAST').error" :error-text="translateText('SAST').error"
...@@ -230,7 +228,7 @@ export default { ...@@ -230,7 +228,7 @@ export default {
<report-section <report-section
v-if="dependencyScanningHeadPath" v-if="dependencyScanningHeadPath"
:always-open="alwaysOpen" :always-open="alwaysOpen"
:type="$options.sast" :component="$options.componentNames.SastIssueBody"
:status="checkReportStatus(dependencyScanning.isLoading, dependencyScanning.hasError)" :status="checkReportStatus(dependencyScanning.isLoading, dependencyScanning.hasError)"
:loading-text="translateText('Dependency scanning').loading" :loading-text="translateText('Dependency scanning').loading"
:error-text="translateText('Dependency scanning').error" :error-text="translateText('Dependency scanning').error"
...@@ -244,7 +242,7 @@ export default { ...@@ -244,7 +242,7 @@ export default {
<report-section <report-section
v-if="sastContainerHeadPath" v-if="sastContainerHeadPath"
:always-open="alwaysOpen" :always-open="alwaysOpen"
:type="$options.sastContainer" :component="$options.componentNames.SastContainerIssueBody"
:status="checkReportStatus(sastContainer.isLoading, sastContainer.hasError)" :status="checkReportStatus(sastContainer.isLoading, sastContainer.hasError)"
:loading-text="translateText('Container scanning').loading" :loading-text="translateText('Container scanning').loading"
:error-text="translateText('Container scanning').error" :error-text="translateText('Container scanning').error"
...@@ -258,7 +256,7 @@ export default { ...@@ -258,7 +256,7 @@ export default {
<report-section <report-section
v-if="dastHeadPath" v-if="dastHeadPath"
:always-open="alwaysOpen" :always-open="alwaysOpen"
:type="$options.dast" :component="$options.componentNames.DastIssueBody"
:status="checkReportStatus(dast.isLoading, dast.hasError)" :status="checkReportStatus(dast.isLoading, dast.hasError)"
:loading-text="translateText('DAST').loading" :loading-text="translateText('DAST').loading"
:error-text="translateText('DAST').error" :error-text="translateText('DAST').error"
......
import Vue from 'vue'; import Vue from 'vue';
import component from 'ee/vue_merge_request_widget/components/codequality_issue_body.vue'; import component from 'ee/vue_merge_request_widget/components/codequality_issue_body.vue';
import mountComponent from '../../helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
import {
STATUS_FAILED,
STATUS_NEUTRAL,
STATUS_SUCCESS,
} from '~/vue_shared/components/reports/constants';
describe('sast issue body', () => { describe('code quality issue body issue body', () => {
let vm; let vm;
const Component = Vue.extend(component); const Component = Vue.extend(component);
...@@ -22,7 +27,7 @@ describe('sast issue body', () => { ...@@ -22,7 +27,7 @@ describe('sast issue body', () => {
it('renders fixed label', () => { it('renders fixed label', () => {
vm = mountComponent(Component, { vm = mountComponent(Component, {
issue: codequalityIssue, issue: codequalityIssue,
isStatusSuccess: true, status: STATUS_SUCCESS,
}); });
expect(vm.$el.textContent.trim()).toContain('Fixed'); expect(vm.$el.textContent.trim()).toContain('Fixed');
...@@ -33,7 +38,7 @@ describe('sast issue body', () => { ...@@ -33,7 +38,7 @@ describe('sast issue body', () => {
it('renders fixed label', () => { it('renders fixed label', () => {
vm = mountComponent(Component, { vm = mountComponent(Component, {
issue: codequalityIssue, issue: codequalityIssue,
isStatusSuccess: false, status: STATUS_FAILED,
}); });
expect(vm.$el.textContent.trim()).not.toContain('Fixed'); expect(vm.$el.textContent.trim()).not.toContain('Fixed');
...@@ -44,7 +49,7 @@ describe('sast issue body', () => { ...@@ -44,7 +49,7 @@ describe('sast issue body', () => {
it('renders name', () => { it('renders name', () => {
vm = mountComponent(Component, { vm = mountComponent(Component, {
issue: codequalityIssue, issue: codequalityIssue,
isStatusSuccess: false, status: STATUS_NEUTRAL,
}); });
expect(vm.$el.textContent.trim()).toContain(codequalityIssue.name); expect(vm.$el.textContent.trim()).toContain(codequalityIssue.name);
...@@ -55,15 +60,11 @@ describe('sast issue body', () => { ...@@ -55,15 +60,11 @@ describe('sast issue body', () => {
it('renders name', () => { it('renders name', () => {
vm = mountComponent(Component, { vm = mountComponent(Component, {
issue: codequalityIssue, issue: codequalityIssue,
isStatusSuccess: false, status: STATUS_NEUTRAL,
}); });
expect(vm.$el.querySelector('a').getAttribute('href')).toEqual( expect(vm.$el.querySelector('a').getAttribute('href')).toEqual(codequalityIssue.urlPath);
codequalityIssue.urlPath, expect(vm.$el.querySelector('a').textContent.trim()).toEqual(codequalityIssue.path);
);
expect(vm.$el.querySelector('a').textContent.trim()).toEqual(
codequalityIssue.path,
);
}); });
}); });
}); });
import Vue from 'vue'; import Vue from 'vue';
import component from 'ee/vue_merge_request_widget/components/performance_issue_body.vue'; import component from 'ee/vue_merge_request_widget/components/performance_issue_body.vue';
import mountComponent from '../../helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('performance issue body', () => { describe('performance issue body', () => {
let vm; let vm;
......
import Vue from 'vue'; import Vue from 'vue';
import reportIssues from '~/vue_shared/components/reports/report_issues.vue'; import reportIssues from '~/vue_shared/components/reports/report_issues.vue';
import { STATUS_FAILED, STATUS_SUCCESS } from '~/vue_shared/components/reports/constants';
import { componentNames } from 'ee/vue_shared/components/reports/issue_body';
import store from 'ee/vue_shared/security_reports/store'; import store from 'ee/vue_shared/security_reports/store';
import mountComponent, { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; import mountComponent, { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { import { codequalityParsedIssues } from 'spec/vue_mr_widget/mock_data';
codequalityParsedIssues,
} from 'spec/vue_mr_widget/mock_data';
import { import {
sastParsedIssues, sastParsedIssues,
dockerReportParsed, dockerReportParsed,
...@@ -28,8 +28,8 @@ describe('Report issues', () => { ...@@ -28,8 +28,8 @@ describe('Report issues', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponent(ReportIssues, { vm = mountComponent(ReportIssues, {
issues: codequalityParsedIssues, issues: codequalityParsedIssues,
type: 'codequality', component: componentNames.CodequalityIssueBody,
status: 'success', status: STATUS_SUCCESS,
}); });
}); });
...@@ -49,8 +49,8 @@ describe('Report issues', () => { ...@@ -49,8 +49,8 @@ describe('Report issues', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponent(ReportIssues, { vm = mountComponent(ReportIssues, {
issues: codequalityParsedIssues, issues: codequalityParsedIssues,
type: 'codequality', component: componentNames.CodequalityIssueBody,
status: 'failed', status: STATUS_FAILED,
}); });
}); });
...@@ -68,8 +68,8 @@ describe('Report issues', () => { ...@@ -68,8 +68,8 @@ describe('Report issues', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponent(ReportIssues, { vm = mountComponent(ReportIssues, {
issues: sastParsedIssues, issues: sastParsedIssues,
type: 'SAST', component: componentNames.SastIssueBody,
status: 'failed', status: STATUS_FAILED,
}); });
}); });
...@@ -82,8 +82,8 @@ describe('Report issues', () => { ...@@ -82,8 +82,8 @@ describe('Report issues', () => {
it('should render location', () => { it('should render location', () => {
vm = mountComponent(ReportIssues, { vm = mountComponent(ReportIssues, {
issues: sastParsedIssues, issues: sastParsedIssues,
type: 'SAST', component: componentNames.SastIssueBody,
status: 'failed', status: STATUS_FAILED,
}); });
expect(vm.$el.querySelector('.report-block-list li').textContent).toContain('in'); expect(vm.$el.querySelector('.report-block-list li').textContent).toContain('in');
...@@ -97,8 +97,8 @@ describe('Report issues', () => { ...@@ -97,8 +97,8 @@ describe('Report issues', () => {
issues: [{ issues: [{
title: 'foo', title: 'foo',
}], }],
type: 'SAST', component: componentNames.SastIssueBody,
status: 'failed', status: STATUS_SUCCESS,
}); });
expect(vm.$el.querySelector('.report-block-list li').textContent).not.toContain('in'); expect(vm.$el.querySelector('.report-block-list li').textContent).not.toContain('in');
...@@ -110,8 +110,8 @@ describe('Report issues', () => { ...@@ -110,8 +110,8 @@ describe('Report issues', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponent(ReportIssues, { vm = mountComponent(ReportIssues, {
issues: dockerReportParsed.unapproved, issues: dockerReportParsed.unapproved,
type: 'SAST_CONTAINER', component: componentNames.SastContainerIssueBody,
status: 'failed', status: STATUS_FAILED,
}); });
}); });
...@@ -142,8 +142,8 @@ describe('Report issues', () => { ...@@ -142,8 +142,8 @@ describe('Report issues', () => {
vm = mountComponentWithStore(ReportIssues, { store, vm = mountComponentWithStore(ReportIssues, { store,
props: { props: {
issues: parsedDast, issues: parsedDast,
type: 'DAST', component: componentNames.DastIssueBody,
status: 'failed', status: STATUS_FAILED,
}, },
}); });
}); });
......
// eslint-disable-next-line import/prefer-default-export
export const fullReport = {
status: 'SUCCESS',
successText: 'SAST improved on 1 security vulnerability and degraded on 1 security vulnerability',
errorText: 'Failed to load security report',
hasIssues: true,
loadingText: 'Loading security report',
resolvedIssues: [
{
cve: 'CVE-2016-9999',
file: 'Gemfile.lock',
message: 'Test Information Leak Vulnerability in Action View',
title: 'Test Information Leak Vulnerability in Action View',
path: 'Gemfile.lock',
solution:
'upgrade to >= 5.0.0.beta1.1, >= 4.2.5.1, ~> 4.2.5, >= 4.1.14.1, ~> 4.1.14, ~> 3.2.22.1',
tool: 'bundler_audit',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
urlPath: '/Gemfile.lock',
},
],
unresolvedIssues: [
{
cve: 'CVE-2014-7829',
file: 'Gemfile.lock',
message: 'Arbitrary file existence disclosure in Action Pack',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
tool: 'bundler_audit',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
urlPath: '/Gemfile.lock',
},
],
allIssues: [
{
cve: 'CVE-2016-0752',
file: 'Gemfile.lock',
message: 'Possible Information Leak Vulnerability in Action View',
title: 'Possible Information Leak Vulnerability in Action View',
path: 'Gemfile.lock',
solution:
'upgrade to >= 5.0.0.beta1.1, >= 4.2.5.1, ~> 4.2.5, >= 4.1.14.1, ~> 4.1.14, ~> 3.2.22.1',
tool: 'bundler_audit',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
urlPath: '/Gemfile.lock',
},
],
};
import Vue from 'vue';
import reportSection from '~/vue_shared/components/reports/report_section.vue';
import { componentNames } from 'ee/vue_shared/components/reports/issue_body';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { fullReport } from './report_section_mock_data';
describe('Report section', () => {
let vm;
const ReportSection = Vue.extend(reportSection);
afterEach(() => {
vm.$destroy();
});
describe('With full report', () => {
beforeEach(() => {
vm = mountComponent(ReportSection, {
component: componentNames.SastIssueBody,
...fullReport,
});
});
it('should render full report section', done => {
vm.$el.querySelector('button').click();
Vue.nextTick(() => {
expect(vm.$el.querySelector('.js-expand-full-list').textContent.trim()).toEqual(
'Show complete code vulnerabilities report',
);
done();
});
});
it('should expand full list when clicked and hide the show all button', done => {
vm.$el.querySelector('button').click();
Vue.nextTick(() => {
vm.$el.querySelector('.js-expand-full-list').click();
Vue.nextTick(() => {
expect(vm.$el.querySelector('.js-mr-code-all-issues').textContent.trim()).toContain(
'Possible Information Leak Vulnerability in Action View',
);
done();
});
});
});
});
});
...@@ -23,7 +23,7 @@ describe('Report section', () => { ...@@ -23,7 +23,7 @@ describe('Report section', () => {
describe('computed', () => { describe('computed', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponent(ReportSection, { vm = mountComponent(ReportSection, {
type: 'codequality', component: '',
status: 'SUCCESS', status: 'SUCCESS',
loadingText: 'Loading codeclimate report', loadingText: 'Loading codeclimate report',
errorText: 'foo', errorText: 'foo',
...@@ -89,7 +89,7 @@ describe('Report section', () => { ...@@ -89,7 +89,7 @@ describe('Report section', () => {
describe('when it is loading', () => { describe('when it is loading', () => {
it('should render loading indicator', () => { it('should render loading indicator', () => {
vm = mountComponent(ReportSection, { vm = mountComponent(ReportSection, {
type: 'codequality', component: '',
status: 'LOADING', status: 'LOADING',
loadingText: 'Loading codeclimate report', loadingText: 'Loading codeclimate report',
errorText: 'foo', errorText: 'foo',
...@@ -103,7 +103,7 @@ describe('Report section', () => { ...@@ -103,7 +103,7 @@ describe('Report section', () => {
describe('with success status', () => { describe('with success status', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponent(ReportSection, { vm = mountComponent(ReportSection, {
type: 'codequality', component: '',
status: 'SUCCESS', status: 'SUCCESS',
loadingText: 'Loading codeclimate report', loadingText: 'Loading codeclimate report',
errorText: 'foo', errorText: 'foo',
...@@ -161,7 +161,7 @@ describe('Report section', () => { ...@@ -161,7 +161,7 @@ describe('Report section', () => {
describe('with failed request', () => { describe('with failed request', () => {
it('should render error indicator', () => { it('should render error indicator', () => {
vm = mountComponent(ReportSection, { vm = mountComponent(ReportSection, {
type: 'codequality', component: '',
status: 'ERROR', status: 'ERROR',
loadingText: 'Loading codeclimate report', loadingText: 'Loading codeclimate report',
errorText: 'Failed to load codeclimate report', errorText: 'Failed to load codeclimate report',
...@@ -171,87 +171,4 @@ describe('Report section', () => { ...@@ -171,87 +171,4 @@ describe('Report section', () => {
expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report'); expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report');
}); });
}); });
describe('With full report', () => {
beforeEach(() => {
vm = mountComponent(ReportSection, {
status: 'SUCCESS',
successText:
'SAST improved on 1 security vulnerability and degraded on 1 security vulnerability',
type: 'SAST',
errorText: 'Failed to load security report',
hasIssues: true,
loadingText: 'Loading security report',
resolvedIssues: [
{
cve: 'CVE-2016-9999',
file: 'Gemfile.lock',
message: 'Test Information Leak Vulnerability in Action View',
title: 'Test Information Leak Vulnerability in Action View',
path: 'Gemfile.lock',
solution:
'upgrade to >= 5.0.0.beta1.1, >= 4.2.5.1, ~> 4.2.5, >= 4.1.14.1, ~> 4.1.14, ~> 3.2.22.1',
tool: 'bundler_audit',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
urlPath: '/Gemfile.lock',
},
],
unresolvedIssues: [
{
cve: 'CVE-2014-7829',
file: 'Gemfile.lock',
message: 'Arbitrary file existence disclosure in Action Pack',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
tool: 'bundler_audit',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
urlPath: '/Gemfile.lock',
},
],
allIssues: [
{
cve: 'CVE-2016-0752',
file: 'Gemfile.lock',
message: 'Possible Information Leak Vulnerability in Action View',
title: 'Possible Information Leak Vulnerability in Action View',
path: 'Gemfile.lock',
solution:
'upgrade to >= 5.0.0.beta1.1, >= 4.2.5.1, ~> 4.2.5, >= 4.1.14.1, ~> 4.1.14, ~> 3.2.22.1',
tool: 'bundler_audit',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
urlPath: '/Gemfile.lock',
},
],
});
});
it('should render full report section', done => {
vm.$el.querySelector('button').click();
Vue.nextTick(() => {
expect(vm.$el.querySelector('.js-expand-full-list').textContent.trim()).toEqual(
'Show complete code vulnerabilities report',
);
done();
});
});
it('should expand full list when clicked and hide the show all button', done => {
vm.$el.querySelector('button').click();
Vue.nextTick(() => {
vm.$el.querySelector('.js-expand-full-list').click();
Vue.nextTick(() => {
expect(vm.$el.querySelector('.js-mr-code-all-issues').textContent.trim()).toContain(
'Possible Information Leak Vulnerability in Action View',
);
done();
});
});
});
});
}); });
import Vue from 'vue'; import Vue from 'vue';
import component from 'ee/vue_shared/security_reports/components/sast_issue_body.vue'; import component from 'ee/vue_shared/security_reports/components/sast_issue_body.vue';
import mountComponent from '../../../helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { STATUS_FAILED } from '~/vue_shared/components/reports/constants';
describe('sast issue body', () => { describe('sast issue body', () => {
let vm; let vm;
...@@ -23,7 +24,7 @@ describe('sast issue body', () => { ...@@ -23,7 +24,7 @@ describe('sast issue body', () => {
confidence: 'Low', confidence: 'Low',
}; };
const status = 'failed'; const status = STATUS_FAILED;
afterEach(() => { afterEach(() => {
vm.$destroy(); vm.$destroy();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment