diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 978e6731e9d0375b5ac6caf57009000984cc7f71..50266e2c43414afe6c026097a4b854ef57b4acaa 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -171,14 +171,10 @@ export default { return true; } - return ( - !this.sastReportsInInlineDiff || - (!this.codequalityReportAvailable && !this.sastReportAvailable) - ); + return !this.codequalityReportAvailable && !this.sastReportAvailable; }, update(data) { const { codequalityReportsComparer, sastReport } = data?.project?.mergeRequest || {}; - this.activeProject = data?.project?.mergeRequest?.project; if ( (sastReport?.status === FINDINGS_STATUS_PARSED || !this.sastReportAvailable) && @@ -307,9 +303,6 @@ export default { resourceId() { return convertToGraphQLId('MergeRequest', this.getNoteableData.id); }, - sastReportsInInlineDiff() { - return this.glFeatures.sastReportsInInlineDiff; - }, }, watch: { commit(newCommit, oldCommit) { @@ -347,10 +340,6 @@ export default { isLoading: 'adjustView', }, mounted() { - if (this.endpointCodequality) { - this.setCodequalityEndpoint(this.endpointCodequality); - } - if (this.shouldShow) { this.fetchData(); } @@ -423,14 +412,12 @@ export default { ...mapActions(['startTaskList']), ...mapActions('diffs', [ 'moveToNeighboringCommit', - 'setCodequalityEndpoint', 'fetchDiffFilesMeta', 'fetchDiffFilesBatch', 'fetchFileByFile', 'loadCollapsedDiff', 'setFileForcedOpen', 'fetchCoverageFiles', - 'fetchCodequality', 'rereadNoteHash', 'startRenderDiffsQueue', 'assignDiscussionsToDiff', @@ -576,10 +563,6 @@ export default { this.fetchCoverageFiles(); } - if (this.endpointCodequality && !this.sastReportsInInlineDiff) { - this.fetchCodequality(); - } - if (!this.isNotesFetched) { notesEventHub.$emit('fetchNotesData'); } diff --git a/app/assets/javascripts/diffs/components/diff_inline_findings.vue b/app/assets/javascripts/diffs/components/diff_inline_findings.vue deleted file mode 100644 index 59f920407762fa2678dc5c32d0300c75bb07ed67..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/diffs/components/diff_inline_findings.vue +++ /dev/null @@ -1,32 +0,0 @@ -<script> -import DiffInlineFindingsItem from './diff_inline_findings_item.vue'; - -export default { - components: { DiffInlineFindingsItem }, - props: { - title: { - type: String, - required: true, - }, - findings: { - type: Array, - required: true, - }, - }, -}; -</script> - -<template> - <div> - <h4 data-testid="diff-inline-findings-heading" class="gl-my-0 gl-font-base gl-font-regular"> - {{ title }} - </h4> - <ul class="gl-list-style-none gl-mb-0 gl-p-0"> - <diff-inline-findings-item - v-for="finding in findings" - :key="finding.description" - :finding="finding" - /> - </ul> - </div> -</template> diff --git a/app/assets/javascripts/diffs/components/diff_inline_findings_item.vue b/app/assets/javascripts/diffs/components/diff_inline_findings_item.vue deleted file mode 100644 index 8a30d6ee7f84fa8a22ae12535890968bbb9ded61..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/diffs/components/diff_inline_findings_item.vue +++ /dev/null @@ -1,39 +0,0 @@ -<script> -import { GlIcon } from '@gitlab/ui'; -import { getSeverity } from '~/ci/reports/utils'; - -export default { - components: { GlIcon }, - - props: { - finding: { - type: Object, - required: true, - }, - }, - computed: { - enhancedFinding() { - return getSeverity(this.finding); - }, - listText() { - return `${this.finding.severity} - ${this.finding.description}`; - }, - }, -}; -</script> - -<template> - <li class="gl-py-1 gl-font-regular gl-display-flex"> - <span class="gl-mr-3"> - <gl-icon - :size="12" - :name="enhancedFinding.name" - :class="enhancedFinding.class" - class="inline-findings-severity-icon" - /> - </span> - <span data-testid="description-plain-text" class="gl-display-flex"> - {{ listText }} - </span> - </li> -</template> diff --git a/app/assets/javascripts/diffs/components/diff_line.vue b/app/assets/javascripts/diffs/components/diff_line.vue deleted file mode 100644 index 4867a21493f8aeee8b9581aff3170201948b04f3..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/diffs/components/diff_line.vue +++ /dev/null @@ -1,32 +0,0 @@ -<script> -import InlineFindings from './inline_findings.vue'; - -export default { - components: { - InlineFindings, - }, - props: { - line: { - type: Object, - required: true, - }, - }, - computed: { - parsedCodeQuality() { - return (this.line.left ?? this.line.right)?.codequality; - }, - codeQualityLineNumber() { - return this.parsedCodeQuality[0]?.line; - }, - }, - methods: { - hideInlineFindings() { - this.$emit('hideInlineFindings', this.codeQualityLineNumber); - }, - }, -}; -</script> - -<template> - <inline-findings :code-quality="parsedCodeQuality" @hideInlineFindings="hideInlineFindings" /> -</template> diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue index a9da77104d41d27dccfa6c0f4e2018e62b53de49..58049929ac8f6be269fd6ba575fb115cf0ab7e82 100644 --- a/app/assets/javascripts/diffs/components/diff_row.vue +++ b/app/assets/javascripts/diffs/components/diff_row.vue @@ -24,8 +24,8 @@ import * as utils from './diff_row_utils'; export default { DiffGutterAvatars, - InlineFindingsFlagSwitcher: () => - import('ee_component/diffs/components/inline_findings_flag_switcher.vue'), + InlineFindingsGutterIconDropdown: () => + import('ee_component/diffs/components/inline_findings_gutter_icon_dropdown.vue'), // Temporary mixin for migration from Vue.js 2 to @vue/compat mixins: [compatFunctionalMixin], @@ -80,11 +80,6 @@ export default { type: Function, required: true, }, - inlineFindingsExpanded: { - type: Boolean, - required: false, - default: false, - }, }, classNameMap: memoize( (props) => { @@ -336,9 +331,8 @@ export default { :class="$options.parallelViewLeftLineType(props)" > <component - :is="$options.InlineFindingsFlagSwitcher" + :is="$options.InlineFindingsGutterIconDropdown" v-if="$options.showCodequalityLeft(props) || $options.showSecurityLeft(props)" - :inline-findings-expanded="props.inlineFindingsExpanded" :code-quality="props.line.left.codequality" :sast="props.line.left.sast" :file-path="props.filePath" @@ -478,7 +472,7 @@ export default { :class="$options.classNameMapCellRight(props)" > <component - :is="$options.InlineFindingsFlagSwitcher" + :is="$options.InlineFindingsGutterIconDropdown" v-if="$options.showCodequalityRight(props) || $options.showSecurityRight(props)" :code-quality="props.line.right.codequality" :sast="props.line.right.sast" diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue index 641616a34f5302afc3e4db21d09a3b75522c6f9a..83984cdf0d0f170dd2461a9c05c33574483c582e 100644 --- a/app/assets/javascripts/diffs/components/diff_view.vue +++ b/app/assets/javascripts/diffs/components/diff_view.vue @@ -10,7 +10,6 @@ import { getCommentedLines } from '~/notes/components/multiline_comment_utils'; import { hide } from '~/tooltips'; import { pickDirection } from '../utils/diff_line'; import DiffCommentCell from './diff_comment_cell.vue'; -import DiffLine from './diff_line.vue'; import DiffExpansionCell from './diff_expansion_cell.vue'; import DiffRow from './diff_row.vue'; import { isHighlighted } from './diff_row_utils'; @@ -19,7 +18,6 @@ export default { components: { DiffExpansionCell, DiffRow, - DiffLine, DiffCommentCell, DraftNote, }, @@ -48,11 +46,6 @@ export default { default: false, }, }, - data() { - return { - inlineFindingsExpandedLines: [], - }; - }, idState() { return { dragStart: null, @@ -87,9 +80,6 @@ export default { this.sastDiff?.added?.length > 0 ); }, - sastReportsInInlineDiff() { - return this.glFeatures.sastReportsInInlineDiff; - }, }, created() { this.onDragOverThrottled = throttle((line) => this.onDragOver(line), 100, { leading: true }); @@ -109,19 +99,6 @@ export default { } this.idState.dragStart = line; }, - hideInlineFindings(line) { - const index = this.inlineFindingsExpandedLines.indexOf(line); - if (index > -1) { - this.inlineFindingsExpandedLines.splice(index, 1); - } - }, - toggleCodeQualityFindings(line) { - if (!this.inlineFindingsExpandedLines.includes(line)) { - this.inlineFindingsExpandedLines.push(line); - } else { - this.hideInlineFindings(line); - } - }, onDragOver(line) { if (line.chunk !== this.idState.dragStart.chunk) return; @@ -266,12 +243,10 @@ export default { :is-last-highlighted-line="isLastHighlightedLine(line) || index === commentedLines.endLine" :inline="inline" :index="index" - :inline-findings-expanded="inlineFindingsExpandedLines.includes(getCodeQualityLine(line))" :file-line-coverage="fileLineCoverage" :coverage-loaded="coverageLoaded" @showCommentForm="(code) => singleLineComment(code, line)" @setHighlightedRow="setHighlightedRow" - @toggleCodeQualityFindings="toggleCodeQualityFindings" @toggleLineDiscussions=" ({ lineCode, expanded }) => toggleLineDiscussions({ lineCode, fileHash: diffFile.file_hash, expanded }) @@ -280,15 +255,6 @@ export default { @startdragging="onStartDragging" @stopdragging="onStopDragging" /> - <!-- Don't display InlineFindings expanded section when sastReportsInInlineDiff is false --> - <diff-line - v-if=" - inlineFindingsExpandedLines.includes(getCodeQualityLine(line)) && !sastReportsInInlineDiff - " - :key="line.line_code" - :line="line" - @hideInlineFindings="hideInlineFindings" - /> <div v-if="line.renderCommentRow" :key="`dcr-${line.line_code || index}`" diff --git a/app/assets/javascripts/diffs/components/inline_findings.vue b/app/assets/javascripts/diffs/components/inline_findings.vue deleted file mode 100644 index efceedd11416a2f7df4e1cf68a97a5cb16ef5891..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/diffs/components/inline_findings.vue +++ /dev/null @@ -1,41 +0,0 @@ -<script> -import { GlButton } from '@gitlab/ui'; -import { NEW_CODE_QUALITY_FINDINGS, NEW_SAST_FINDINGS } from '../i18n'; -import DiffInlineFindings from './diff_inline_findings.vue'; - -export default { - i18n: { - newCodeQualityFindings: NEW_CODE_QUALITY_FINDINGS, - newSastFindings: NEW_SAST_FINDINGS, - }, - components: { GlButton, DiffInlineFindings }, - props: { - codeQuality: { - type: Array, - required: true, - }, - }, -}; -</script> - -<template> - <div - data-testid="inline-findings" - class="gl-relative inline-findings-list gl-border-top-1 gl-border-bottom-1 gl-bg-gray-10 gl-text-black-normal gl-pl-5 gl-pt-4 gl-pb-4" - > - <diff-inline-findings - v-if="codeQuality.length" - :title="$options.i18n.newCodeQualityFindings" - :findings="codeQuality" - /> - - <gl-button - data-testid="inline-findings-close" - category="tertiary" - size="small" - icon="close" - class="gl-absolute gl-right-2 gl-top-2" - @click="$emit('hideInlineFindings')" - /> - </div> -</template> diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js index 303f010e56f3ee6e2279026ef0ab789de5841fd7..9acfda93303d0a625304bc3b8413db9662d537cf 100644 --- a/app/assets/javascripts/diffs/index.js +++ b/app/assets/javascripts/diffs/index.js @@ -34,7 +34,6 @@ export default function initDiffsApp(store = notesStore) { projectPath: dataset.projectPath || '', iid: dataset.iid || '', endpointCoverage: dataset.endpointCoverage || '', - endpointCodequality: dataset.endpointCodequality || '', codequalityReportAvailable: parseBoolean(dataset.codequalityReportAvailable), sastReportAvailable: parseBoolean(dataset.sastReportAvailable), helpPagePath: dataset.helpPagePath, diff --git a/app/assets/javascripts/diffs/store/modules/index.js b/app/assets/javascripts/diffs/store/modules/index.js index 169502a957b4725f3070cd3e8c1c91c6d0cafc51..95371eb8dbdbf4fd44c5e2d1ba49fbd8cc0bf225 100644 --- a/app/assets/javascripts/diffs/store/modules/index.js +++ b/app/assets/javascripts/diffs/store/modules/index.js @@ -1,7 +1,7 @@ -import * as actions from 'ee_else_ce/diffs/store/actions'; import * as getters from 'ee_else_ce/diffs/store/getters'; import createState from 'ee_else_ce/diffs/store/modules/diff_state'; import mutations from 'ee_else_ce/diffs/store/mutations'; +import * as actions from '../actions'; export default () => ({ namespaced: true, diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index c3faec4c8ecb369112f9c4b1a1d69fffd456c4ad..c937c1e83b6884b3a255cf3921a9d4b18e62791c 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -40,7 +40,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action only: [:show, :diffs] do push_frontend_feature_flag(:core_security_mr_widget_counts, project) push_frontend_feature_flag(:moved_mr_sidebar, project) - push_frontend_feature_flag(:sast_reports_in_inline_diff, project) push_frontend_feature_flag(:mr_experience_survey, project) push_frontend_feature_flag(:ci_job_failures_in_mr, project) push_frontend_feature_flag(:mr_pipelines_graphql, project) diff --git a/doc/development/merge_request_concepts/diffs/frontend.md b/doc/development/merge_request_concepts/diffs/frontend.md index aeb1ba452a38671897405217edf039b9c566e1de..ee17023dae5a8b005313d21c447bc9d281beff83 100644 --- a/doc/development/merge_request_concepts/diffs/frontend.md +++ b/doc/development/merge_request_concepts/diffs/frontend.md @@ -90,7 +90,7 @@ This chart contains several types of items: AB["batch_comments~~draft_note.vue"] AC["diffs~~diff_comment_cell.vue"] AD["diffs~~diff_gutter_avatars.vue"] - AE["ee-diffs~~inline_findings_flag_switcher.vue"] + AE["ee-diffs~~inline_findings_gutter_icon_dropdown.vue"] AF["notes~~noteable_note.vue"] AG["notes~~note_actions.vue"] AH["notes~~note_body.vue"] diff --git a/ee/app/assets/javascripts/diffs/components/inline_findings_flag_switcher.vue b/ee/app/assets/javascripts/diffs/components/inline_findings_flag_switcher.vue deleted file mode 100644 index 325b4d8e3afcc0ac0656ba5b11f7ce12fe820bbb..0000000000000000000000000000000000000000 --- a/ee/app/assets/javascripts/diffs/components/inline_findings_flag_switcher.vue +++ /dev/null @@ -1,63 +0,0 @@ -<script> -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import InlineFindingsGutterIcon from 'ee_component/diffs/components/inline_findings_gutter_icon.vue'; -import InlineFindingsGutterIconDropdown from 'ee_component/diffs/components/inline_findings_gutter_icon_dropdown.vue'; - -export default { - components: { - InlineFindingsGutterIcon, - InlineFindingsGutterIconDropdown, - }, - mixins: [glFeatureFlagsMixin()], - props: { - inlineFindingsExpanded: { - type: Boolean, - required: false, - default: false, - }, - filePath: { - type: String, - required: true, - }, - codeQuality: { - type: Array, - required: false, - default: () => [], - }, - sast: { - type: Array, - required: false, - default: () => [], - }, - }, - computed: { - sastReportsInInlineDiff() { - return this.glFeatures.sastReportsInInlineDiff; - }, - }, - methods: { - showInlineFindingsEvent() { - this.$emit('showInlineFindings'); - }, - }, -}; -</script> - -<template> - <div v-if="sastReportsInInlineDiff"> - <inline-findings-gutter-icon-dropdown - :code-quality="codeQuality" - :sast="sast" - :file-path="filePath" - /> - </div> - <div v-else> - <inline-findings-gutter-icon - :inline-findings-expanded="inlineFindingsExpanded" - :code-quality="codeQuality" - :sast="sast" - :file-path="filePath" - @showInlineFindings="showInlineFindingsEvent" - /> - </div> -</template> diff --git a/ee/app/assets/javascripts/diffs/components/inline_findings_gutter_icon.vue b/ee/app/assets/javascripts/diffs/components/inline_findings_gutter_icon.vue deleted file mode 100644 index fd74d212e32151710ae10b92ca26ef7f31b4269d..0000000000000000000000000000000000000000 --- a/ee/app/assets/javascripts/diffs/components/inline_findings_gutter_icon.vue +++ /dev/null @@ -1,127 +0,0 @@ -<script> -import { GlIcon, GlTooltip } from '@gitlab/ui'; -import { n__ } from '~/locale'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import { getSeverity } from '~/ci/reports/utils'; -import { CODE_QUALITY_SCALE_KEY } from '~/ci/reports/constants'; -import { scaleFindings } from './inline_findings_gutter_icon_utils'; - -const inlineFindingsCountThreshold = 3; - -export default { - components: { - GlIcon, - GlTooltip, - }, - mixins: [glFeatureFlagsMixin()], - props: { - inlineFindingsExpanded: { - type: Boolean, - required: false, - default: false, - }, - filePath: { - type: String, - required: true, - }, - codeQuality: { - type: Array, - required: false, - default: () => [], - }, - }, - data() { - return { - isHoveringFirstIcon: false, - }; - }, - computed: { - scaledCodeQuality() { - return getSeverity(this.codeQuality.map((e) => scaleFindings(e, CODE_QUALITY_SCALE_KEY))); - }, - codeQualityTooltipTextCollapsed() { - return n__('1 Code Quality finding', '%d Code Quality findings', this.codeQuality.length); - }, - showMoreCount() { - return this.moreCount && this.isHoveringFirstIcon; - }, - line() { - return this.scaledCodeQuality[0].line; - }, - moreCount() { - return this.scaledCodeQuality.length > inlineFindingsCountThreshold - ? this.scaledCodeQuality.length - inlineFindingsCountThreshold - : 0; - }, - firstItem() { - return { ...this.scaledCodeQuality[0], filePath: this.filePath }; - }, - inlineFindingsSubItems() { - return this.scaledCodeQuality.slice(1, inlineFindingsCountThreshold); - }, - }, -}; -</script> - -<template> - <div - v-if="scaledCodeQuality.length" - class="gl-z-index-1 gl-relative" - @click="$emit('showInlineFindings')" - > - <div v-if="!inlineFindingsExpanded" class="gl-display-inline-flex"> - <span ref="inlineFindingsIcon" class="gl-z-index-200"> - <gl-icon - :id="`inline-findings-${firstItem.filePath}:${firstItem.line}`" - ref="firstInlineFindingsIcon" - :key="firstItem.description" - :size="16" - :name="firstItem.name" - :class="firstItem.class" - class="gl-hover-cursor-pointer gl-relative gl-top-1 inline-findings-severity-icon gl-vertical-align-baseline!" - @mouseenter="isHoveringFirstIcon = true" - @mouseleave="isHoveringFirstIcon = false" - /> - </span> - <span class="inline-findings-transition-container gl-display-inline-flex"> - <transition-group name="icons"> - <!-- - The TransitionGroup Component will only apply its classes when first-level children are added/removed to the DOM. - So to make TransitionGroup work there is no other way to use v-if-with-v-for in this case. - --> - <!-- eslint-disable vue/no-use-v-if-with-v-for --> - <gl-icon - v-for="item in inlineFindingsSubItems" - v-if="isHoveringFirstIcon" - :key="item.description" - :name="item.name" - :class="item.class" - class="gl-hover-cursor-pointer gl-relative gl-top-1 inline-findings-severity-icon gl-absolute gl-left-0" - /> - <!-- eslint-enable --> - </transition-group> - <transition name="more-count"> - <div - v-if="showMoreCount" - class="more-count gl-px-2 gl-w-auto gl-absolute gl-left-0 gl-relative gl-top-1" - data-testid="inlineFindingsMoreCount" - > - <p class="gl-mb-0 gl-display-block gl-w-3 more-count-copy">{{ moreCount }}</p> - </div> - </transition> - </span> - </div> - <button v-else class="inline-findings-collapse gl-mx-n2"> - <gl-icon :size="12" name="collapse" /> - </button> - <!-- Only show tooltip when indicator is not expanded - a) to stay consistent with other collapsed icon on the same page - b) because the tooltip would be misaligned hence the negative margin - --> - <gl-tooltip v-if="!$props.inlineFindingsExpanded" :target="() => $refs.inlineFindingsIcon"> - <span v-if="codeQuality.length" class="gl-display-block">{{ - codeQualityTooltipTextCollapsed - }}</span> - </gl-tooltip> - </div> -</template> diff --git a/ee/app/assets/javascripts/diffs/store/actions.js b/ee/app/assets/javascripts/diffs/store/actions.js deleted file mode 100644 index adb6b16a13f8dd3a6cb463820c8731deeb059991..0000000000000000000000000000000000000000 --- a/ee/app/assets/javascripts/diffs/store/actions.js +++ /dev/null @@ -1,80 +0,0 @@ -import Visibility from 'visibilityjs'; -import { createAlert } from '~/alert'; -import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status'; -import Poll from '~/lib/utils/poll'; -import { __ } from '~/locale'; -import { MAX_RETRIES, RETRY_DELAY } from './constants'; - -import * as types from './mutation_types'; - -export * from '~/diffs/store/actions'; - -let codequalityPoll; - -export const setCodequalityEndpoint = ({ commit }, endpoint) => { - commit(types.SET_CODEQUALITY_ENDPOINT, endpoint); -}; - -export const clearCodequalityPoll = () => { - codequalityPoll = null; -}; - -export const stopCodequalityPolling = () => { - if (codequalityPoll) codequalityPoll.stop(); -}; - -export const restartCodequalityPolling = () => { - if (codequalityPoll) codequalityPoll.restart(); -}; - -export const fetchCodequality = ({ commit, state, dispatch }) => { - let retryCount = 0; - - codequalityPoll = new Poll({ - resource: { - getCodequalityDiffReports: (endpoint) => axios.get(endpoint), - }, - data: state.endpointCodequality, - method: 'getCodequalityDiffReports', - successCallback: ({ status, data }) => { - retryCount = 0; - if (status === HTTP_STATUS_OK) { - commit(types.SET_CODEQUALITY_DATA, data); - - dispatch('stopCodequalityPolling'); - } - }, - errorCallback: ({ response }) => { - if (response.status === HTTP_STATUS_BAD_REQUEST) { - // we could get a 400 status response temporarily during report processing - // so we retry up to MAX_RETRIES times in case the reports are on their way - // and stop polling if we get 400s consistently - if (retryCount < MAX_RETRIES) { - codequalityPoll.makeDelayedRequest(RETRY_DELAY); - retryCount += 1; - } else { - codequalityPoll.stop(); - } - } else { - retryCount = 0; - dispatch('stopCodequalityPolling'); - createAlert({ - message: __('An unexpected error occurred while loading the code quality diff.'), - }); - } - }, - }); - - if (!Visibility.hidden()) { - codequalityPoll.makeRequest(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - dispatch('restartCodequalityPolling'); - } else { - dispatch('stopCodequalityPolling'); - } - }); -}; diff --git a/ee/app/assets/stylesheets/framework/diffs.scss b/ee/app/assets/stylesheets/framework/diffs.scss index 6d4e4a2dceb3496a0720c481d0057efbf8ba5404..5a6e31b8252d53f8e4a5825ec769ec5ac18c014a 100644 --- a/ee/app/assets/stylesheets/framework/diffs.scss +++ b/ee/app/assets/stylesheets/framework/diffs.scss @@ -48,11 +48,6 @@ filter: drop-shadow(0 1px 0.5px #fff) drop-shadow(1px 0 0.5px #fff) drop-shadow(0 -1px 0.5px #fff) drop-shadow(-1px 0 0.5px #fff); } - // this rule needs to be removed together when the sastReportsInInlineDiff flag is removed https://gitlab.com/gitlab-org/gitlab/-/issues/410191 - .more-count-copy { - line-height: $code-line-height; - } - .more-count-copy-dropdown { line-height: 0.11; } diff --git a/ee/spec/frontend/diffs/components/app_spec.js b/ee/spec/frontend/diffs/components/app_spec.js index 0214cdedeee4085b25dff46de6be67d7740fdf97..0a123f9c541974e3475e5695a4f59f4a133df35d 100644 --- a/ee/spec/frontend/diffs/components/app_spec.js +++ b/ee/spec/frontend/diffs/components/app_spec.js @@ -24,13 +24,11 @@ jest.mock('~/mr_notes/stores', () => jest.requireActual('helpers/mocks/mr_notes/ Vue.use(VueApollo); describe('diffs/components/app', () => { - let mockDispatch; let fakeApollo; const createComponent = ( props = {}, baseConfig = {}, - flags = {}, queryHandler = codeQualityNewErrorsHandler, ) => { store.reset(); @@ -63,17 +61,10 @@ describe('diffs/components/app', () => { ...baseConfig, }); - mockDispatch = jest.spyOn(store, 'dispatch'); - fakeApollo = createMockApollo([[getMRCodequalityAndSecurityReports, queryHandler]]); shallowMount(App, { apolloProvider: fakeApollo, - provide: { - glFeatures: { - ...flags, - }, - }, propsData: { endpointCoverage: `${TEST_HOST}/diff/endpointCoverage`, endpointCodequality: '', @@ -89,165 +80,108 @@ describe('diffs/components/app', () => { }; describe('EE codequality diff', () => { - describe('sastReportsInInlineDiff flag off', () => { - it('fetches Code Quality data via REST and not via GraphQL when endpoint is provided', () => { - createComponent({ + it('polls Code Quality data via GraphQL and not via REST when codequalityReportAvailable is true', async () => { + createComponent( + { shouldShow: true, codequalityReportAvailable: true }, + {}, + codeQualityErrorAndParsed, + ); + await waitForPromises(); + expect(codeQualityErrorAndParsed).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); + + expect(codeQualityErrorAndParsed).toHaveBeenCalledTimes(2); + }); + + it('does not poll Code Quality data via GraphQL when codequalityReportAvailable is false', async () => { + createComponent( + { shouldShow: true, codequalityReportAvailable: false }, + {}, + codeQualityErrorAndParsed, + ); + await waitForPromises(); + expect(codeQualityErrorAndParsed).toHaveBeenCalledTimes(0); + }); + + it('stops polling when newErrors in response are defined', async () => { + createComponent( + { shouldShow: true, - endpointCodequality: `${TEST_HOST}/diff/endpointCodequality`, - }); - expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); - expect(mockDispatch).toHaveBeenCalledWith('diffs/fetchCodequality'); - }); - - it('does not fetch code quality data when endpoint is blank', () => { - createComponent({ shouldShow: true, endpointCodequality: '' }); - - expect(mockDispatch).not.toHaveBeenCalledWith('diffs/fetchCodequality'); - expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); - }); + codequalityReportAvailable: true, + }, + {}, + ); + + await waitForPromises(); + + expect(codeQualityNewErrorsHandler).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); + + expect(codeQualityNewErrorsHandler).toHaveBeenCalledTimes(1); }); - describe('sastReportsInInlineDiff flag on', () => { - it('polls Code Quality data via GraphQL and not via REST when codequalityReportAvailable is true', async () => { - createComponent( - { shouldShow: true, codequalityReportAvailable: true }, - {}, - { sastReportsInInlineDiff: true }, - codeQualityErrorAndParsed, - ); - await waitForPromises(); - expect(codeQualityErrorAndParsed).toHaveBeenCalledTimes(1); - expect(mockDispatch).not.toHaveBeenCalledWith('diffs/fetchCodequality'); - jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); - - expect(codeQualityErrorAndParsed).toHaveBeenCalledTimes(2); - }); - - it('does not poll Code Quality data via GraphQL when codequalityReportAvailable is false', async () => { - createComponent( - { shouldShow: true, codequalityReportAvailable: false }, - {}, - { sastReportsInInlineDiff: true }, - codeQualityErrorAndParsed, - ); - await waitForPromises(); - expect(codeQualityErrorAndParsed).toHaveBeenCalledTimes(0); - expect(mockDispatch).not.toHaveBeenCalledWith('diffs/fetchCodequality'); - }); - - it('stops polling when newErrors in response are defined', async () => { - createComponent( - { - shouldShow: true, - codequalityReportAvailable: true, - }, - {}, - { sastReportsInInlineDiff: true }, - ); - - await waitForPromises(); - - expect(codeQualityNewErrorsHandler).toHaveBeenCalledTimes(1); - jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); - - expect(codeQualityNewErrorsHandler).toHaveBeenCalledTimes(1); - }); - - it('does not fetch code quality data when endpoint is blank', () => { - createComponent( - { shouldShow: false, endpointCodequality: '' }, - {}, - { sastReportsInInlineDiff: true }, - ); - expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); - expect(mockDispatch).not.toHaveBeenCalledWith('diffs/fetchCodequality'); - }); + it('does not fetch code quality data when endpoint is blank', () => { + createComponent({ shouldShow: false, endpointCodequality: '' }, {}); + expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); }); }); describe('EE SAST diff', () => { - describe('sastReportsInInlineDiff flag off', () => { - it('does not fetch SAST data when sastReportAvailable is true', () => { - createComponent({ shouldShow: true, sastReportAvailable: true }); - expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); - }); + it('polls SAST data when sastReportAvailable is true', async () => { + createComponent( + { shouldShow: true, sastReportAvailable: true }, + {}, + SASTParsingAndParsedHandler, + ); + await waitForPromises(); + + expect(SASTParsingAndParsedHandler).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); + + expect(SASTParsingAndParsedHandler).toHaveBeenCalledTimes(2); + }); + + it('stops polling when sastReport status is PARSED', async () => { + createComponent( + { + shouldShow: true, + sastReportAvailable: true, + }, + {}, + SASTParsedHandler, + ); + + await waitForPromises(); + + expect(SASTParsedHandler).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); + + expect(SASTParsedHandler).toHaveBeenCalledTimes(1); + }); + + it('stops polling on request error', async () => { + createComponent({ shouldShow: true, sastReportAvailable: true }, {}, requestError); + await waitForPromises(); + + expect(requestError).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); + + expect(requestError).toHaveBeenCalledTimes(1); + }); + + it('stops polling on response status error', async () => { + createComponent({ shouldShow: true, sastReportAvailable: true }, {}, SASTErrorHandler); + await waitForPromises(); - it('does not fetch SAST data when sastReportAvailable is false', () => { - createComponent({ shouldShow: false, sastReportAvailable: false }); + expect(SASTErrorHandler).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); - expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); - }); + expect(SASTErrorHandler).toHaveBeenCalledTimes(1); }); - describe('sastReportsInInlineDiff flag on', () => { - it('polls SAST data when sastReportAvailable is true', async () => { - createComponent( - { shouldShow: true, sastReportAvailable: true }, - {}, - { sastReportsInInlineDiff: true }, - SASTParsingAndParsedHandler, - ); - await waitForPromises(); - - expect(SASTParsingAndParsedHandler).toHaveBeenCalledTimes(1); - jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); - - expect(SASTParsingAndParsedHandler).toHaveBeenCalledTimes(2); - }); - - it('stops polling when sastReport status is PARSED', async () => { - createComponent( - { - shouldShow: true, - sastReportAvailable: true, - }, - {}, - { sastReportsInInlineDiff: true }, - SASTParsedHandler, - ); - - await waitForPromises(); - - expect(SASTParsedHandler).toHaveBeenCalledTimes(1); - jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); - - expect(SASTParsedHandler).toHaveBeenCalledTimes(1); - }); - - it('stops polling on request error', async () => { - createComponent( - { shouldShow: true, sastReportAvailable: true }, - {}, - { sastReportsInInlineDiff: true }, - requestError, - ); - await waitForPromises(); - - expect(requestError).toHaveBeenCalledTimes(1); - jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); - - expect(requestError).toHaveBeenCalledTimes(1); - }); - - it('stops polling on response status error', async () => { - createComponent( - { shouldShow: true, sastReportAvailable: true }, - {}, - { sastReportsInInlineDiff: true }, - SASTErrorHandler, - ); - await waitForPromises(); - - expect(SASTErrorHandler).toHaveBeenCalledTimes(1); - jest.advanceTimersByTime(FINDINGS_POLL_INTERVAL); - - expect(SASTErrorHandler).toHaveBeenCalledTimes(1); - }); - - it('does not fetch SAST data when sastReportAvailable is false', () => { - createComponent({ shouldShow: false }, {}, { sastReportsInInlineDiff: true }); - expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); - }); + it('does not fetch SAST data when sastReportAvailable is false', () => { + createComponent({ shouldShow: false }, {}); + expect(codeQualityNewErrorsHandler).not.toHaveBeenCalled(); }); }); }); diff --git a/ee/spec/frontend/diffs/components/inline_findings_flag_switcher_spec.js b/ee/spec/frontend/diffs/components/inline_findings_flag_switcher_spec.js deleted file mode 100644 index db6315df1217243dc82d7e5b53c996a9ffa1b352..0000000000000000000000000000000000000000 --- a/ee/spec/frontend/diffs/components/inline_findings_flag_switcher_spec.js +++ /dev/null @@ -1,56 +0,0 @@ -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import inlineFindingsFlagSwitcher from 'ee/diffs/components/inline_findings_flag_switcher.vue'; -import InlineFindingsGutterIcon from 'ee_component/diffs/components/inline_findings_gutter_icon.vue'; -import InlineFindingsGutterIconDropdown from 'ee_component/diffs/components/inline_findings_gutter_icon_dropdown.vue'; - -let wrapper; - -const findInlineFindingsGutterIcon = () => wrapper.findComponent(InlineFindingsGutterIcon); -const findInlineFindingsGutterIconDropdown = () => - wrapper.findComponent(InlineFindingsGutterIconDropdown); - -const createComponent = (props = {}, flag) => { - const payload = { - provide: { - glFeatures: { - sastReportsInInlineDiff: flag, - }, - }, - propsData: props, - }; - wrapper = shallowMountExtended(inlineFindingsFlagSwitcher, payload); -}; - -describe('EE inlineFindingsflagSwitcher', () => { - describe('default', () => { - beforeEach(() => { - createComponent({ filePath: 'test' }, true); - }); - - it('renders component without errors', () => { - expect(wrapper.exists()).toBe(true); - }); - }); - - describe('sastReportsInInlineDiff true', () => { - beforeEach(() => { - createComponent({ filePath: 'test' }, true); - }); - - it('renders InlineFindingsGutterIconDropdown', () => { - expect(findInlineFindingsGutterIconDropdown().exists()).toBe(true); - expect(findInlineFindingsGutterIcon().exists()).toBe(false); - }); - }); - - describe('sastReportsInInlineDiff false', () => { - beforeEach(() => { - createComponent({ filePath: 'test' }, false); - }); - - it('renders InlineFindingsGutterIconDropdown', () => { - expect(findInlineFindingsGutterIconDropdown().exists()).toBe(false); - expect(findInlineFindingsGutterIcon().exists()).toBe(true); - }); - }); -}); diff --git a/ee/spec/frontend/diffs/components/inline_findings_gutter_icon_spec.js b/ee/spec/frontend/diffs/components/inline_findings_gutter_icon_spec.js deleted file mode 100644 index 0a767ed0a983fd62bcf5b591f2fb7d6b176caada..0000000000000000000000000000000000000000 --- a/ee/spec/frontend/diffs/components/inline_findings_gutter_icon_spec.js +++ /dev/null @@ -1,172 +0,0 @@ -import { GlIcon, GlTooltip } from '@gitlab/ui'; -import { nextTick } from 'vue'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import inlineFindingsGutterIcon from 'ee/diffs/components/inline_findings_gutter_icon.vue'; -import store from '~/mr_notes/stores'; -import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/ci/reports/codequality_report/constants'; - -import { - fiveCodeQualityFindings, - threeCodeQualityFindings, - singularCodeQualityFinding, - filePath, -} from '../../../../../spec/frontend/diffs/mock_data/inline_findings'; - -jest.mock('~/mr_notes/stores', () => jest.requireActual('helpers/mocks/mr_notes/stores')); - -let wrapper; -const findIcon = () => wrapper.findComponent(GlIcon); -const findIcons = () => wrapper.findAllComponents(GlIcon); -const findFirstIcon = () => wrapper.findComponent({ ref: 'firstInlineFindingsIcon' }); - -let codequalityDiff; - -const createComponent = (props = {}) => { - store.reset(); - store.state.diffs.codequalityDiff = codequalityDiff; - - const payload = { - propsData: props, - mocks: { - $store: store, - }, - }; - wrapper = shallowMountExtended(inlineFindingsGutterIcon, payload); -}; - -describe('EE inlineFindingsGutterIcon', () => { - const containsATooltip = (container) => container.findComponent(GlTooltip).exists(); - - it.each` - severity - ${'info'} - ${'minor'} - ${'major'} - ${'critical'} - ${'blocker'} - ${'unknown'} - `('shows icon for $severity degradation', ({ severity }) => { - createComponent({ filePath: 'index.js', codeQuality: [{ severity }] }); - - expect(findIcon().exists()).toBe(true); - expect(findIcon().attributes()).toMatchObject({ - class: expect.stringContaining(SEVERITY_CLASSES[severity]), - name: SEVERITY_ICONS[severity], - size: '16', - }); - }); - - describe('code Quality gutter icon', () => { - describe('with no findings', () => { - beforeEach(() => { - createComponent({ filePath: 'test' }, true); - }); - - it('renders component without errors', () => { - expect(wrapper.exists()).toBe(true); - }); - }); - - describe('with maximum 3 code Quality findings', () => { - beforeEach(() => { - createComponent({ filePath, codeQuality: threeCodeQualityFindings }); - }); - - it('contains a tooltip', () => { - expect(containsATooltip(wrapper)).toBe(true); - }); - - it('displays correct popover text with multiple codequality findings', () => { - expect(wrapper.findComponent(GlTooltip).text()).toContain('3 Code Quality findings'); - }); - - it('emits showInlineFindings event on click', () => { - wrapper.trigger('click'); - expect(wrapper.emitted('showInlineFindings')).toHaveLength(1); - }); - - it('displays first icon with correct severity', () => { - const icons = findIcons(); - expect(icons).toHaveLength(1); - expect(icons.at(0).props('name')).toBe('severity-low'); - }); - - it('displays correct amount of icons with correct severity on hover', async () => { - findFirstIcon().vm.$emit('mouseenter'); - await nextTick(); - const icons = findIcons(); - expect(icons).toHaveLength(3); - expect(icons.at(0).props('name')).toBe('severity-low'); - expect(icons.at(1).props('name')).toBe('severity-medium'); - expect(icons.at(2).props('name')).toBe('severity-info'); - }); - - it('does not display more count', () => { - expect(wrapper.findByTestId('inlineFindingsMoreCount').exists()).toBe(false); - }); - }); - - describe('with more than 3 codequality findings', () => { - beforeEach(() => { - createComponent({ filePath, codeQuality: fiveCodeQualityFindings }); - }); - - it('displays first icon with correct severity', () => { - const icons = findIcons(); - expect(icons).toHaveLength(1); - expect(icons.at(0).props('name')).toBe('severity-low'); - }); - - it('displays correct amount of icons with correct severity + more count on hover', async () => { - findFirstIcon().vm.$emit('mouseenter'); - await nextTick(); - const icons = findIcons(); - expect(icons).toHaveLength(3); - expect(icons.at(0).props('name')).toBe('severity-low'); - expect(icons.at(1).props('name')).toBe('severity-medium'); - expect(icons.at(2).props('name')).toBe('severity-info'); - expect(wrapper.findByTestId('inlineFindingsMoreCount').exists()).toBe(true); - }); - }); - - describe('with singular finding', () => { - it('displays correct popover text with singular codequality finding', () => { - createComponent({ filePath, codeQuality: singularCodeQualityFinding }); - expect(wrapper.findComponent(GlTooltip).text()).toContain('1 Code Quality finding'); - }); - - it('does not trigger "first-icon-hovered" class when firstInlineFindingsIcon is hovered', async () => { - createComponent({ filePath, codeQuality: singularCodeQualityFinding }); - findFirstIcon().vm.$emit('mouseenter'); - await nextTick(); - expect(wrapper.findAll('.first-icon-hovered')).toHaveLength(0); - }); - }); - - describe('indicator icon', () => { - describe('with inlineFindingsExpanded prop false', () => { - beforeEach(() => { - createComponent({ filePath, codeQuality: singularCodeQualityFinding }); - }); - - it('shows severity icon with correct tooltip', () => { - expect(wrapper.findComponent(GlTooltip).text()).toContain('1 Code Quality finding'); - expect(wrapper.findComponent(GlIcon).props('name')).toBe('severity-low'); - }); - }); - describe('with inlineFindingsExpanded prop true', () => { - beforeEach(() => { - createComponent({ - filePath, - codeQuality: singularCodeQualityFinding, - inlineFindingsExpanded: true, - }); - }); - - it('shows collapse icon', () => { - expect(wrapper.findComponent(GlIcon).props('name')).toBe('collapse'); - }); - }); - }); - }); -}); diff --git a/ee/spec/frontend/diffs/store/actions_spec.js b/ee/spec/frontend/diffs/store/actions_spec.js deleted file mode 100644 index 04de618e7717ba05e85ff7b90fc9315548acf433..0000000000000000000000000000000000000000 --- a/ee/spec/frontend/diffs/store/actions_spec.js +++ /dev/null @@ -1,121 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; -import { - setCodequalityEndpoint, - clearCodequalityPoll, - stopCodequalityPolling, - fetchCodequality, -} from 'ee/diffs/store/actions'; -import { RETRY_DELAY } from 'ee/diffs/store/constants'; -import * as types from 'ee/diffs/store/mutation_types'; -import testAction from 'helpers/vuex_action_helper'; -import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/alert'; -import axios from '~/lib/utils/axios_utils'; -import { - HTTP_STATUS_BAD_REQUEST, - HTTP_STATUS_INTERNAL_SERVER_ERROR, - HTTP_STATUS_OK, -} from '~/lib/utils/http_status'; -import Poll from '~/lib/utils/poll'; - -jest.mock('~/alert'); - -describe('EE DiffsStoreActions', () => { - describe('setCodequalityEndpoint', () => { - it('should set given endpoint', async () => { - const endpoint = '/codequality_mr_diff.json'; - - await testAction( - setCodequalityEndpoint, - { endpoint }, - {}, - [{ type: types.SET_CODEQUALITY_ENDPOINT, payload: { endpoint } }], - [], - ); - }); - }); - - describe('fetchCodequality', () => { - let mock; - const endpointCodequality = '/codequality_mr_diff.json'; - - beforeEach(() => { - mock = new MockAdapter(axios); - }); - - afterEach(() => { - stopCodequalityPolling(); - clearCodequalityPoll(); - }); - - it('should commit SET_CODEQUALITY_DATA with received response and stop polling', async () => { - const data = { - files: { 'app.js': [{ line: 1, description: 'Unexpected alert.', severity: 'minor' }] }, - }; - - mock.onGet(endpointCodequality).reply(HTTP_STATUS_OK, { data }); - - await testAction( - fetchCodequality, - {}, - { endpointCodequality }, - [{ type: types.SET_CODEQUALITY_DATA, payload: { data } }], - [{ type: 'stopCodequalityPolling' }], - ); - }); - - describe('with 400 status response', () => { - let pollDelayedRequest; - let pollStop; - - beforeEach(() => { - pollDelayedRequest = jest.spyOn(Poll.prototype, 'makeDelayedRequest'); - pollStop = jest.spyOn(Poll.prototype, 'stop'); - - mock.onGet(endpointCodequality).reply(HTTP_STATUS_BAD_REQUEST); - }); - - it('should not show an alert message', async () => { - await testAction(fetchCodequality, {}, { endpointCodequality }, [], []); - - expect(createAlert).not.toHaveBeenCalled(); - }); - - it('should retry five times with a delay, then stop polling', async () => { - await testAction(fetchCodequality, {}, { endpointCodequality }, [], []); - - expect(pollDelayedRequest).toHaveBeenCalledTimes(1); - expect(pollStop).toHaveBeenCalledTimes(0); - - for (let i = 0; i < 4; i += 1) { - jest.advanceTimersByTime(RETRY_DELAY); - // eslint-disable-next-line no-await-in-loop - await waitForPromises(); - } - - expect(pollDelayedRequest).toHaveBeenCalledTimes(5); - - jest.advanceTimersByTime(RETRY_DELAY); - await waitForPromises(); - - expect(pollStop).toHaveBeenCalledTimes(1); - }); - }); - - it('with unexpected error should stop polling and show an alert message', async () => { - mock.onGet(endpointCodequality).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); - - await testAction( - fetchCodequality, - {}, - { endpointCodequality }, - [], - [{ type: 'stopCodequalityPolling' }], - ); - expect(createAlert).toHaveBeenCalledTimes(1); - expect(createAlert).toHaveBeenCalledWith({ - message: 'An unexpected error occurred while loading the code quality diff.', - }); - }); - }); -}); diff --git a/locale/gitlab.pot b/locale/gitlab.pot index ab5f54db55f68dbac78cd806dfc0aac2deda6b9a..d925ac87c1da8e5d054ece201b88c773deb8bc47 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1585,11 +1585,6 @@ msgstr "" msgid "0 B" msgstr "" -msgid "1 Code Quality finding" -msgid_plural "%d Code Quality findings" -msgstr[0] "" -msgstr[1] "" - msgid "1 Day" msgid_plural "%d Days" msgstr[0] "" @@ -5517,9 +5512,6 @@ msgstr "" msgid "An unexpected error occurred while communicating with the Web Terminal." msgstr "" -msgid "An unexpected error occurred while loading the code quality diff." -msgstr "" - msgid "An unexpected error occurred while starting the Web Terminal." msgstr "" diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js index 4676f56c47ee9a295299cfffebcd5dfd533d9958..5e0dfd8bd091763b9cabe07ceead38b0c00021d6 100644 --- a/spec/frontend/diffs/components/app_spec.js +++ b/spec/frontend/diffs/components/app_spec.js @@ -195,10 +195,6 @@ describe('diffs/components/app', () => { describe('codequality diff', () => { it('does not fetch code quality data on FOSS', () => { createComponent(); - jest.spyOn(wrapper.vm, 'fetchCodequality'); - wrapper.vm.fetchData(false); - - expect(wrapper.vm.fetchCodequality).not.toHaveBeenCalled(); expect(codeQualityAndSastQueryHandlerSuccess).not.toHaveBeenCalled(); }); }); diff --git a/spec/frontend/diffs/components/diff_inline_findings_item_spec.js b/spec/frontend/diffs/components/diff_inline_findings_item_spec.js deleted file mode 100644 index cda3273d51e0e88b401d0f8a3c7c9360f916eea3..0000000000000000000000000000000000000000 --- a/spec/frontend/diffs/components/diff_inline_findings_item_spec.js +++ /dev/null @@ -1,38 +0,0 @@ -import { GlIcon } from '@gitlab/ui'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import DiffInlineFindingsItem from '~/diffs/components/diff_inline_findings_item.vue'; -import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/ci/reports/codequality_report/constants'; -import { multipleFindingsArrCodeQualityScale } from '../mock_data/inline_findings'; - -let wrapper; - -const [codeQualityFinding] = multipleFindingsArrCodeQualityScale; -const findIcon = () => wrapper.findComponent(GlIcon); -const findDescriptionPlainText = () => wrapper.findByTestId('description-plain-text'); - -describe('DiffCodeQuality', () => { - const createWrapper = () => { - return shallowMountExtended(DiffInlineFindingsItem, { - propsData: { - finding: codeQualityFinding, - }, - }); - }; - - it('shows icon for given degradation', () => { - wrapper = createWrapper(); - expect(findIcon().exists()).toBe(true); - - expect(findIcon().attributes()).toMatchObject({ - class: `inline-findings-severity-icon ${SEVERITY_CLASSES[codeQualityFinding.severity]}`, - name: SEVERITY_ICONS[codeQualityFinding.severity], - size: '12', - }); - }); - - it('should render severity + description in plain text', () => { - wrapper = createWrapper(); - expect(findDescriptionPlainText().text()).toContain(codeQualityFinding.severity); - expect(findDescriptionPlainText().text()).toContain(codeQualityFinding.description); - }); -}); diff --git a/spec/frontend/diffs/components/diff_inline_findings_spec.js b/spec/frontend/diffs/components/diff_inline_findings_spec.js deleted file mode 100644 index f654a2e2d4f1d82083bdeafeba393a2c8bb9db96..0000000000000000000000000000000000000000 --- a/spec/frontend/diffs/components/diff_inline_findings_spec.js +++ /dev/null @@ -1,33 +0,0 @@ -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import DiffInlineFindings from '~/diffs/components/diff_inline_findings.vue'; -import DiffInlineFindingsItem from '~/diffs/components/diff_inline_findings_item.vue'; -import { NEW_CODE_QUALITY_FINDINGS } from '~/diffs/i18n'; -import { multipleFindingsArrCodeQualityScale } from '../mock_data/inline_findings'; - -let wrapper; -const heading = () => wrapper.findByTestId('diff-inline-findings-heading'); -const diffInlineFindingsItems = () => wrapper.findAllComponents(DiffInlineFindingsItem); - -describe('DiffInlineFindings', () => { - const createWrapper = () => { - return shallowMountExtended(DiffInlineFindings, { - propsData: { - title: NEW_CODE_QUALITY_FINDINGS, - findings: multipleFindingsArrCodeQualityScale, - }, - }); - }; - - it('renders the title correctly', () => { - wrapper = createWrapper(); - expect(heading().text()).toBe(NEW_CODE_QUALITY_FINDINGS); - }); - - it('renders the correct number of DiffInlineFindingsItem components with correct props', () => { - wrapper = createWrapper(); - expect(diffInlineFindingsItems()).toHaveLength(multipleFindingsArrCodeQualityScale.length); - expect(diffInlineFindingsItems().wrappers[0].props('finding')).toEqual( - wrapper.props('findings')[0], - ); - }); -}); diff --git a/spec/frontend/diffs/components/diff_line_spec.js b/spec/frontend/diffs/components/diff_line_spec.js deleted file mode 100644 index 501bd0757c860329279147aad4ecb5c9acdeef88..0000000000000000000000000000000000000000 --- a/spec/frontend/diffs/components/diff_line_spec.js +++ /dev/null @@ -1,65 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import DiffLine from '~/diffs/components/diff_line.vue'; -import InlineFindings from '~/diffs/components/inline_findings.vue'; - -const EXAMPLE_LINE_NUMBER = 3; -const EXAMPLE_DESCRIPTION = 'example description'; -const EXAMPLE_SEVERITY = 'example severity'; - -const left = { - line: { - left: { - codequality: [ - { - line: EXAMPLE_LINE_NUMBER, - description: EXAMPLE_DESCRIPTION, - severity: EXAMPLE_SEVERITY, - }, - ], - }, - }, -}; - -const right = { - line: { - right: { - codequality: [ - { - line: EXAMPLE_LINE_NUMBER, - description: EXAMPLE_DESCRIPTION, - severity: EXAMPLE_SEVERITY, - }, - ], - }, - }, -}; - -const mockData = [right, left]; - -describe('DiffLine', () => { - const createWrapper = (propsData) => { - return shallowMount(DiffLine, { propsData }); - }; - - it('should emit event when hideInlineFindings is called', () => { - const wrapper = createWrapper(right); - - wrapper.findComponent(InlineFindings).vm.$emit('hideInlineFindings'); - expect(wrapper.emitted()).toEqual({ - hideInlineFindings: [[EXAMPLE_LINE_NUMBER]], - }); - }); - - mockData.forEach((element) => { - it('should set correct props for InlineFindings', () => { - const wrapper = createWrapper(element); - expect(wrapper.findComponent(InlineFindings).props('codeQuality')).toEqual([ - { - line: EXAMPLE_LINE_NUMBER, - description: EXAMPLE_DESCRIPTION, - severity: EXAMPLE_SEVERITY, - }, - ]); - }); - }); -}); diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js index 2c8f751804e9cf0e42cf9cae88eb46f2be4c2fcf..2d42c0780b54cb0dd11dce85f8b0b74bd563d4aa 100644 --- a/spec/frontend/diffs/components/diff_view_spec.js +++ b/spec/frontend/diffs/components/diff_view_spec.js @@ -1,11 +1,9 @@ import { shallowMount } from '@vue/test-utils'; -import Vue, { nextTick } from 'vue'; +import Vue from 'vue'; // eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import { throttle } from 'lodash'; import DiffView from '~/diffs/components/diff_view.vue'; -import DiffLine from '~/diffs/components/diff_line.vue'; -import { diffCodeQuality } from '../mock_data/inline_findings'; jest.mock('lodash/throttle', () => jest.fn((fn) => fn)); const lodash = jest.requireActual('lodash'); @@ -19,7 +17,7 @@ describe('DiffView', () => { const setSelectedCommentPosition = jest.fn(); const getDiffRow = (wrapper) => wrapper.findComponent(DiffRow).vm; - const createWrapper = ({ props, flag = false } = {}) => { + const createWrapper = ({ props } = {}) => { Vue.use(Vuex); const batchComments = { @@ -51,21 +49,10 @@ describe('DiffView', () => { diffFile: { file_hash: '123' }, diffLines: [], ...props, - provide: { - glFeatures: { - sastReportsInInlineDiff: flag, - }, - }, - }; - - const provide = { - glFeatures: { - sastReportsInInlineDiff: flag, - }, }; const stubs = { DiffExpansionCell, DiffRow, DiffCommentCell, DraftNote }; - return shallowMount(DiffView, { propsData, provide, store, stubs }); + return shallowMount(DiffView, { propsData, store, stubs }); }; beforeEach(() => { @@ -76,32 +63,6 @@ describe('DiffView', () => { throttle.mockReset(); }); - it('does not render a diff-line component when there is no finding', () => { - const wrapper = createWrapper(); - expect(wrapper.findComponent(DiffLine).exists()).toBe(false); - }); - - it('does render a diff-line component with the correct props when there is a finding', async () => { - const wrapper = createWrapper({ props: diffCodeQuality }); - wrapper.findComponent(DiffRow).vm.$emit('toggleCodeQualityFindings', 2); - await nextTick(); - expect(wrapper.findComponent(DiffLine).props('line')).toBe(diffCodeQuality.diffLines[2]); - }); - - it('does not render a diff-line component when there is a finding and sastReportsInInlineDiff flag is true', async () => { - const wrapper = createWrapper({ props: diffCodeQuality, flag: true }); - wrapper.findComponent(DiffRow).vm.$emit('toggleCodeQualityFindings', 2); - await nextTick(); - expect(wrapper.findComponent(DiffLine).exists()).toBe(false); - }); - - it('does render a diff-line component when there is a finding and sastReportsInInlineDiff flag is false', async () => { - const wrapper = createWrapper({ props: diffCodeQuality }); - wrapper.findComponent(DiffRow).vm.$emit('toggleCodeQualityFindings', 2); - await nextTick(); - expect(wrapper.findComponent(DiffLine).exists()).toBe(true); - }); - it.each` type | side | container | sides | total ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDrafts: [], renderDiscussion: true }, right: { lineDrafts: [], renderDiscussion: true } }} | ${2} diff --git a/spec/frontend/diffs/components/inline_findings_spec.js b/spec/frontend/diffs/components/inline_findings_spec.js deleted file mode 100644 index 102287a23b6a17f52badbefb13bbbd66373394db..0000000000000000000000000000000000000000 --- a/spec/frontend/diffs/components/inline_findings_spec.js +++ /dev/null @@ -1,33 +0,0 @@ -import { mountExtended } from 'helpers/vue_test_utils_helper'; -import InlineFindings from '~/diffs/components/inline_findings.vue'; -import DiffInlineFindings from '~/diffs/components/diff_inline_findings.vue'; -import { NEW_CODE_QUALITY_FINDINGS } from '~/diffs/i18n'; -import { threeCodeQualityFindings } from '../mock_data/inline_findings'; - -let wrapper; - -const diffInlineFindings = () => wrapper.findComponent(DiffInlineFindings); - -describe('InlineFindings', () => { - const createWrapper = () => { - return mountExtended(InlineFindings, { - propsData: { - codeQuality: threeCodeQualityFindings, - }, - }); - }; - - it('hides details and throws hideInlineFindings event on close click', async () => { - wrapper = createWrapper(); - expect(wrapper.findByTestId('inline-findings').exists()).toBe(true); - - await wrapper.findByTestId('inline-findings-close').trigger('click'); - expect(wrapper.emitted('hideInlineFindings')).toHaveLength(1); - }); - - it('renders diff inline findings component with correct props for codequality array', () => { - wrapper = createWrapper(); - expect(diffInlineFindings().props('title')).toBe(NEW_CODE_QUALITY_FINDINGS); - expect(diffInlineFindings().props('findings')).toBe(threeCodeQualityFindings); - }); -}); diff --git a/spec/frontend/diffs/utils/diff_line_spec.js b/spec/frontend/diffs/utils/diff_line_spec.js deleted file mode 100644 index adcb4a4433c02d8ca309f86e2711e37b0d73803b..0000000000000000000000000000000000000000 --- a/spec/frontend/diffs/utils/diff_line_spec.js +++ /dev/null @@ -1,30 +0,0 @@ -import { pickDirection } from '~/diffs/utils/diff_line'; - -describe('diff_line utilities', () => { - describe('pickDirection', () => { - const left = { - line_code: 'left', - }; - const right = { - line_code: 'right', - }; - const defaultLine = { - left, - right, - }; - - it.each` - code | pick | line | pickDescription - ${'left'} | ${left} | ${defaultLine} | ${'the left line'} - ${'right'} | ${right} | ${defaultLine} | ${'the right line'} - ${'junk'} | ${left} | ${defaultLine} | ${'the default: the left line'} - ${'junk'} | ${right} | ${{ right }} | ${"the right line if there's no left line to default to"} - ${'right'} | ${left} | ${{ left }} | ${"the left line when there isn't a right line to match"} - `( - 'when provided a line and a line code `$code`, picks $pickDescription', - ({ code, line, pick }) => { - expect(pickDirection({ line, code })).toBe(pick); - }, - ); - }); -});