Commit 5e593937 authored by Phil Hughes's avatar Phil Hughes

Merge branch '55932-diff-viewer-refactor' into 'master'

Refactor MR FE components to rely on DiffViewer instead of DiffFile

Closes #55932

See merge request gitlab-org/gitlab-ce!24454
parents 8f209ed5 bf8f32da
<script> <script>
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue'; import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import EmptyFileViewer from '~/vue_shared/components/diff_viewer/viewers/empty_file.vue'; import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
import InlineDiffView from './inline_diff_view.vue'; import InlineDiffView from './inline_diff_view.vue';
import ParallelDiffView from './parallel_diff_view.vue'; import ParallelDiffView from './parallel_diff_view.vue';
import NoteForm from '../../notes/components/note_form.vue'; import NoteForm from '../../notes/components/note_form.vue';
...@@ -9,6 +10,7 @@ import ImageDiffOverlay from './image_diff_overlay.vue'; ...@@ -9,6 +10,7 @@ import ImageDiffOverlay from './image_diff_overlay.vue';
import DiffDiscussions from './diff_discussions.vue'; import DiffDiscussions from './diff_discussions.vue';
import { IMAGE_DIFF_POSITION_TYPE } from '../constants'; import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
import { getDiffMode } from '../store/utils'; import { getDiffMode } from '../store/utils';
import { diffViewerModes } from '~/ide/constants';
export default { export default {
components: { components: {
...@@ -18,7 +20,8 @@ export default { ...@@ -18,7 +20,8 @@ export default {
NoteForm, NoteForm,
DiffDiscussions, DiffDiscussions,
ImageDiffOverlay, ImageDiffOverlay,
EmptyFileViewer, NotDiffableViewer,
NoPreviewViewer,
}, },
props: { props: {
diffFile: { diffFile: {
...@@ -42,11 +45,17 @@ export default { ...@@ -42,11 +45,17 @@ export default {
diffMode() { diffMode() {
return getDiffMode(this.diffFile); return getDiffMode(this.diffFile);
}, },
diffViewerMode() {
return this.diffFile.viewer.name;
},
isTextFile() { isTextFile() {
return this.diffFile.viewer.name === 'text'; return this.diffViewerMode === diffViewerModes.text;
},
noPreview() {
return this.diffViewerMode === diffViewerModes.no_preview;
}, },
errorMessage() { notDiffable() {
return this.diffFile.viewer.error; return this.diffViewerMode === diffViewerModes.not_diffable;
}, },
diffFileCommentForm() { diffFileCommentForm() {
return this.getCommentFormForDiffFile(this.diffFile.file_hash); return this.getCommentFormForDiffFile(this.diffFile.file_hash);
...@@ -78,11 +87,10 @@ export default { ...@@ -78,11 +87,10 @@ export default {
<template> <template>
<div class="diff-content"> <div class="diff-content">
<div v-if="!errorMessage" class="diff-viewer"> <div class="diff-viewer">
<template v-if="isTextFile"> <template v-if="isTextFile">
<empty-file-viewer v-if="diffFile.empty" />
<inline-diff-view <inline-diff-view
v-else-if="isInlineView" v-if="isInlineView"
:diff-file="diffFile" :diff-file="diffFile"
:diff-lines="diffFile.highlighted_diff_lines || []" :diff-lines="diffFile.highlighted_diff_lines || []"
:help-page-path="helpPagePath" :help-page-path="helpPagePath"
...@@ -94,9 +102,12 @@ export default { ...@@ -94,9 +102,12 @@ export default {
:help-page-path="helpPagePath" :help-page-path="helpPagePath"
/> />
</template> </template>
<not-diffable-viewer v-else-if="notDiffable" />
<no-preview-viewer v-else-if="noPreview" />
<diff-viewer <diff-viewer
v-else v-else
:diff-mode="diffMode" :diff-mode="diffMode"
:diff-viewer-mode="diffViewerMode"
:new-path="diffFile.new_path" :new-path="diffFile.new_path"
:new-sha="diffFile.diff_refs.head_sha" :new-sha="diffFile.diff_refs.head_sha"
:old-path="diffFile.old_path" :old-path="diffFile.old_path"
...@@ -132,8 +143,5 @@ export default { ...@@ -132,8 +143,5 @@ export default {
</div> </div>
</diff-viewer> </diff-viewer>
</div> </div>
<div v-else class="diff-viewer">
<div class="nothing-here-block" v-html="errorMessage"></div>
</div>
</div> </div>
</template> </template>
...@@ -7,6 +7,7 @@ import { GlLoadingIcon } from '@gitlab/ui'; ...@@ -7,6 +7,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../../notes/event_hub'; import eventHub from '../../notes/event_hub';
import DiffFileHeader from './diff_file_header.vue'; import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue'; import DiffContent from './diff_content.vue';
import { diffViewerErrors } from '~/ide/constants';
export default { export default {
components: { components: {
...@@ -33,15 +34,14 @@ export default { ...@@ -33,15 +34,14 @@ export default {
return { return {
isLoadingCollapsedDiff: false, isLoadingCollapsedDiff: false,
forkMessageVisible: false, forkMessageVisible: false,
isCollapsed: this.file.viewer.collapsed || false,
renderIt: this.file.renderIt,
}; };
}, },
computed: { computed: {
...mapState('diffs', ['currentDiffFileId']), ...mapState('diffs', ['currentDiffFileId']),
...mapGetters(['isNotesFetched']), ...mapGetters(['isNotesFetched']),
...mapGetters('diffs', ['getDiffFileDiscussions']), ...mapGetters('diffs', ['getDiffFileDiscussions']),
isCollapsed() {
return this.file.collapsed || false;
},
viewBlobLink() { viewBlobLink() {
return sprintf( return sprintf(
__('You can %{linkStart}view the blob%{linkEnd} instead.'), __('You can %{linkStart}view the blob%{linkEnd} instead.'),
...@@ -52,19 +52,8 @@ export default { ...@@ -52,19 +52,8 @@ export default {
false, false,
); );
}, },
showExpandMessage() {
return (
this.isCollapsed ||
(!this.file.highlighted_diff_lines &&
!this.isLoadingCollapsedDiff &&
!this.file.too_large &&
this.file.text &&
!this.file.renamed_file &&
!this.file.mode_changed)
);
},
showLoadingIcon() { showLoadingIcon() {
return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed); return this.isLoadingCollapsedDiff || (!this.renderIt && !this.isCollapsed);
}, },
hasDiffLines() { hasDiffLines() {
return ( return (
...@@ -73,9 +62,15 @@ export default { ...@@ -73,9 +62,15 @@ export default {
this.file.parallel_diff_lines.length > 0 this.file.parallel_diff_lines.length > 0
); );
}, },
isFileTooLarge() {
return this.file.viewer.error === diffViewerErrors.too_large;
},
errorMessage() {
return this.file.viewer.error_message;
},
}, },
watch: { watch: {
'file.collapsed': function fileCollapsedWatch(newVal, oldVal) { isCollapsed: function fileCollapsedWatch(newVal, oldVal) {
if (!newVal && oldVal && !this.hasDiffLines) { if (!newVal && oldVal && !this.hasDiffLines) {
this.handleLoadCollapsedDiff(); this.handleLoadCollapsedDiff();
} }
...@@ -90,8 +85,8 @@ export default { ...@@ -90,8 +85,8 @@ export default {
if (!this.hasDiffLines) { if (!this.hasDiffLines) {
this.handleLoadCollapsedDiff(); this.handleLoadCollapsedDiff();
} else { } else {
this.file.collapsed = !this.file.collapsed; this.isCollapsed = !this.isCollapsed;
this.file.renderIt = true; this.renderIt = true;
} }
}, },
handleLoadCollapsedDiff() { handleLoadCollapsedDiff() {
...@@ -100,8 +95,8 @@ export default { ...@@ -100,8 +95,8 @@ export default {
this.loadCollapsedDiff(this.file) this.loadCollapsedDiff(this.file)
.then(() => { .then(() => {
this.isLoadingCollapsedDiff = false; this.isLoadingCollapsedDiff = false;
this.file.collapsed = false; this.isCollapsed = false;
this.file.renderIt = true; this.renderIt = true;
}) })
.then(() => { .then(() => {
requestIdleCallback( requestIdleCallback(
...@@ -164,21 +159,25 @@ export default { ...@@ -164,21 +159,25 @@ export default {
Cancel Cancel
</button> </button>
</div> </div>
<diff-content
v-if="!isCollapsed && file.renderIt"
:class="{ hidden: isCollapsed || file.too_large }"
:diff-file="file"
:help-page-path="helpPagePath"
/>
<gl-loading-icon v-if="showLoadingIcon" class="diff-content loading" /> <gl-loading-icon v-if="showLoadingIcon" class="diff-content loading" />
<div v-else-if="showExpandMessage" class="nothing-here-block diff-collapsed"> <template v-else>
{{ __('This diff is collapsed.') }} <div v-if="errorMessage" class="diff-viewer">
<a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">{{ <div class="nothing-here-block" v-html="errorMessage"></div>
__('Click to expand it.') </div>
}}</a> <div v-else-if="isCollapsed" class="nothing-here-block diff-collapsed">
</div> {{ __('This diff is collapsed.') }}
<div v-if="file.too_large" class="nothing-here-block diff-collapsed js-too-large-diff"> <a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">{{
__('Click to expand it.')
}}</a>
</div>
<diff-content
v-else
:class="{ hidden: isCollapsed || isFileTooLarge }"
:diff-file="file"
:help-page-path="helpPagePath"
/>
</template>
<div v-if="isFileTooLarge" class="nothing-here-block diff-collapsed js-too-large-diff">
{{ __('This source diff could not be displayed because it is too large.') }} {{ __('This source diff could not be displayed because it is too large.') }}
<span v-html="viewBlobLink"></span> <span v-html="viewBlobLink"></span>
</div> </div>
......
...@@ -8,6 +8,7 @@ import FileIcon from '~/vue_shared/components/file_icon.vue'; ...@@ -8,6 +8,7 @@ import FileIcon from '~/vue_shared/components/file_icon.vue';
import { GlTooltipDirective } from '@gitlab/ui'; import { GlTooltipDirective } from '@gitlab/ui';
import { truncateSha } from '~/lib/utils/text_utility'; import { truncateSha } from '~/lib/utils/text_utility';
import { __, s__, sprintf } from '~/locale'; import { __, s__, sprintf } from '~/locale';
import { diffViewerModes } from '~/ide/constants';
import EditButton from './edit_button.vue'; import EditButton from './edit_button.vue';
import DiffStats from './diff_stats.vue'; import DiffStats from './diff_stats.vue';
...@@ -118,6 +119,12 @@ export default { ...@@ -118,6 +119,12 @@ export default {
gfmCopyText() { gfmCopyText() {
return `\`${this.diffFile.file_path}\``; return `\`${this.diffFile.file_path}\``;
}, },
isFileRenamed() {
return this.diffFile.viewer.name === diffViewerModes.renamed;
},
isModeChanged() {
return this.diffFile.viewer.name === diffViewerModes.mode_changed;
},
}, },
mounted() { mounted() {
polyfillSticky(this.$refs.header); polyfillSticky(this.$refs.header);
...@@ -165,7 +172,7 @@ export default { ...@@ -165,7 +172,7 @@ export default {
aria-hidden="true" aria-hidden="true"
css-classes="js-file-icon append-right-5" css-classes="js-file-icon append-right-5"
/> />
<span v-if="diffFile.renamed_file"> <span v-if="isFileRenamed">
<strong <strong
v-gl-tooltip v-gl-tooltip
:title="diffFile.old_path" :title="diffFile.old_path"
...@@ -193,7 +200,7 @@ export default { ...@@ -193,7 +200,7 @@ export default {
css-class="btn-default btn-transparent btn-clipboard" css-class="btn-default btn-transparent btn-clipboard"
/> />
<small v-if="diffFile.mode_changed" ref="fileMode"> <small v-if="isModeChanged" ref="fileMode">
{{ diffFile.a_mode }}{{ diffFile.b_mode }} {{ diffFile.a_mode }}{{ diffFile.b_mode }}
</small> </small>
......
...@@ -17,6 +17,7 @@ import { ...@@ -17,6 +17,7 @@ import {
TREE_LIST_STORAGE_KEY, TREE_LIST_STORAGE_KEY,
WHITESPACE_STORAGE_KEY, WHITESPACE_STORAGE_KEY,
} from '../constants'; } from '../constants';
import { diffViewerModes } from '~/ide/constants';
export const setBaseConfig = ({ commit }, options) => { export const setBaseConfig = ({ commit }, options) => {
const { endpoint, projectPath } = options; const { endpoint, projectPath } = options;
...@@ -91,7 +92,7 @@ export const renderFileForDiscussionId = ({ commit, rootState, state }, discussi ...@@ -91,7 +92,7 @@ export const renderFileForDiscussionId = ({ commit, rootState, state }, discussi
commit(types.RENDER_FILE, file); commit(types.RENDER_FILE, file);
} }
if (file.collapsed) { if (file.viewer.collapsed) {
eventHub.$emit(`loadCollapsedDiff/${file.file_hash}`); eventHub.$emit(`loadCollapsedDiff/${file.file_hash}`);
scrollToElement(document.getElementById(file.file_hash)); scrollToElement(document.getElementById(file.file_hash));
} else { } else {
...@@ -105,7 +106,8 @@ export const startRenderDiffsQueue = ({ state, commit }) => { ...@@ -105,7 +106,8 @@ export const startRenderDiffsQueue = ({ state, commit }) => {
const checkItem = () => const checkItem = () =>
new Promise(resolve => { new Promise(resolve => {
const nextFile = state.diffFiles.find( const nextFile = state.diffFiles.find(
file => !file.renderIt && (!file.collapsed || !file.text), file =>
!file.renderIt && (!file.viewer.collapsed || !file.viewer.name === diffViewerModes.text),
); );
if (nextFile) { if (nextFile) {
......
...@@ -4,7 +4,8 @@ export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW ...@@ -4,7 +4,8 @@ export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW
export const isInlineView = state => state.diffViewType === INLINE_DIFF_VIEW_TYPE; export const isInlineView = state => state.diffViewType === INLINE_DIFF_VIEW_TYPE;
export const hasCollapsedFile = state => state.diffFiles.some(file => file.collapsed); export const hasCollapsedFile = state =>
state.diffFiles.some(file => file.viewer && file.viewer.collapsed);
export const commitId = state => (state.commit && state.commit.id ? state.commit.id : null); export const commitId = state => (state.commit && state.commit.id ? state.commit.id : null);
......
import _ from 'underscore'; import _ from 'underscore';
import { diffModes } from '~/ide/constants';
import { truncatePathMiddleToLength } from '~/lib/utils/text_utility'; import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
import { diffModes, diffViewerModes } from '~/ide/constants';
import { import {
LINE_POSITION_LEFT, LINE_POSITION_LEFT,
LINE_POSITION_RIGHT, LINE_POSITION_RIGHT,
...@@ -248,7 +248,8 @@ export function prepareDiffData(diffData) { ...@@ -248,7 +248,8 @@ export function prepareDiffData(diffData) {
Object.assign(file, { Object.assign(file, {
renderIt: showingLines < LINES_TO_BE_RENDERED_DIRECTLY, renderIt: showingLines < LINES_TO_BE_RENDERED_DIRECTLY,
collapsed: file.text && showingLines > MAX_LINES_TO_BE_RENDERED, collapsed:
file.viewer.name === diffViewerModes.text && showingLines > MAX_LINES_TO_BE_RENDERED,
discussions: [], discussions: [],
}); });
} }
...@@ -404,7 +405,9 @@ export const getDiffMode = diffFile => { ...@@ -404,7 +405,9 @@ export const getDiffMode = diffFile => {
const diffModeKey = Object.keys(diffModes).find(key => diffFile[`${key}_file`]); const diffModeKey = Object.keys(diffModes).find(key => diffFile[`${key}_file`]);
return ( return (
diffModes[diffModeKey] || diffModes[diffModeKey] ||
(diffFile.mode_changed && diffModes.mode_changed) || (diffFile.viewer &&
diffFile.viewer.name === diffViewerModes.mode_changed &&
diffViewerModes.mode_changed) ||
diffModes.replaced diffModes.replaced
); );
}; };
...@@ -24,6 +24,22 @@ export const diffModes = { ...@@ -24,6 +24,22 @@ export const diffModes = {
mode_changed: 'mode_changed', mode_changed: 'mode_changed',
}; };
export const diffViewerModes = Object.freeze({
not_diffable: 'not_diffable',
no_preview: 'no_preview',
added: 'added',
deleted: 'deleted',
renamed: 'renamed',
mode_changed: 'mode_changed',
text: 'text',
image: 'image',
});
export const diffViewerErrors = Object.freeze({
too_large: 'too_large',
stored_externally: 'server_side_but_stored_externally',
});
export const rightSidebarViews = { export const rightSidebarViews = {
pipelines: { name: 'pipelines-list', keepAlive: true }, pipelines: { name: 'pipelines-list', keepAlive: true },
jobsDetail: { name: 'jobs-detail', keepAlive: false }, jobsDetail: { name: 'jobs-detail', keepAlive: false },
......
...@@ -5,6 +5,7 @@ import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue'; ...@@ -5,6 +5,7 @@ import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue'; import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import { GlSkeletonLoading } from '@gitlab/ui'; import { GlSkeletonLoading } from '@gitlab/ui';
import { getDiffMode } from '~/diffs/store/utils'; import { getDiffMode } from '~/diffs/store/utils';
import { diffViewerModes } from '~/ide/constants';
export default { export default {
components: { components: {
...@@ -31,6 +32,12 @@ export default { ...@@ -31,6 +32,12 @@ export default {
diffMode() { diffMode() {
return getDiffMode(this.discussion.diff_file); return getDiffMode(this.discussion.diff_file);
}, },
diffViewerMode() {
return this.discussion.diff_file.viewer.name;
},
isTextFile() {
return this.diffViewerMode === diffViewerModes.text;
},
hasTruncatedDiffLines() { hasTruncatedDiffLines() {
return ( return (
this.discussion.truncated_diff_lines && this.discussion.truncated_diff_lines.length !== 0 this.discussion.truncated_diff_lines && this.discussion.truncated_diff_lines.length !== 0
...@@ -58,18 +65,14 @@ export default { ...@@ -58,18 +65,14 @@ export default {
</script> </script>
<template> <template>
<div :class="{ 'text-file': discussion.diff_file.text }" class="diff-file file-holder"> <div :class="{ 'text-file': isTextFile }" class="diff-file file-holder">
<diff-file-header <diff-file-header
:discussion-path="discussion.discussion_path" :discussion-path="discussion.discussion_path"
:diff-file="discussion.diff_file" :diff-file="discussion.diff_file"
:can-current-user-fork="false" :can-current-user-fork="false"
:expanded="!discussion.diff_file.collapsed" :expanded="!discussion.diff_file.viewer.collapsed"
/> />
<div <div v-if="isTextFile" :class="$options.userColorSchemeClass" class="diff-content code">
v-if="discussion.diff_file.text"
:class="$options.userColorSchemeClass"
class="diff-content code"
>
<table> <table>
<template v-if="hasTruncatedDiffLines"> <template v-if="hasTruncatedDiffLines">
<tr <tr
...@@ -109,6 +112,7 @@ export default { ...@@ -109,6 +112,7 @@ export default {
<div v-else> <div v-else>
<diff-viewer <diff-viewer
:diff-mode="diffMode" :diff-mode="diffMode"
:diff-viewer-mode="diffViewerMode"
:new-path="discussion.diff_file.new_path" :new-path="discussion.diff_file.new_path"
:new-sha="discussion.diff_file.diff_refs.head_sha" :new-sha="discussion.diff_file.diff_refs.head_sha"
:old-path="discussion.diff_file.old_path" :old-path="discussion.diff_file.old_path"
......
<script> <script>
import { diffModes } from '~/ide/constants'; import { diffViewerModes, diffModes } from '~/ide/constants';
import { viewerInformationForPath } from '../content_viewer/lib/viewer_utils';
import ImageDiffViewer from './viewers/image_diff_viewer.vue'; import ImageDiffViewer from './viewers/image_diff_viewer.vue';
import DownloadDiffViewer from './viewers/download_diff_viewer.vue'; import DownloadDiffViewer from './viewers/download_diff_viewer.vue';
import RenamedFile from './viewers/renamed.vue'; import RenamedFile from './viewers/renamed.vue';
...@@ -12,6 +11,10 @@ export default { ...@@ -12,6 +11,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
diffViewerMode: {
type: String,
required: true,
},
newPath: { newPath: {
type: String, type: String,
required: true, required: true,
...@@ -46,7 +49,7 @@ export default { ...@@ -46,7 +49,7 @@ export default {
}, },
computed: { computed: {
viewer() { viewer() {
if (this.diffMode === diffModes.renamed) { if (this.diffViewerMode === diffViewerModes.renamed) {
return RenamedFile; return RenamedFile;
} else if (this.diffMode === diffModes.mode_changed) { } else if (this.diffMode === diffModes.mode_changed) {
return ModeChanged; return ModeChanged;
...@@ -54,11 +57,8 @@ export default { ...@@ -54,11 +57,8 @@ export default {
if (!this.newPath) return null; if (!this.newPath) return null;
const previewInfo = viewerInformationForPath(this.newPath); switch (this.diffViewerMode) {
if (!previewInfo) return DownloadDiffViewer; case diffViewerModes.image:
switch (previewInfo.id) {
case 'image':
return ImageDiffViewer; return ImageDiffViewer;
default: default:
return DownloadDiffViewer; return DownloadDiffViewer;
......
<template>
<div class="nothing-here-block">
{{ __('No preview for this file type') }}
</div>
</template>
<template>
<div class="nothing-here-block">
{{ __('This diff was suppressed by a .gitattributes entry.') }}
</div>
</template>
...@@ -72,17 +72,20 @@ class DiffFileBaseEntity < Grape::Entity ...@@ -72,17 +72,20 @@ class DiffFileBaseEntity < Grape::Entity
expose :old_path expose :old_path
expose :new_path expose :new_path
expose :new_file?, as: :new_file expose :new_file?, as: :new_file
expose :collapsed?, as: :collapsed expose :renamed_file?, as: :renamed_file
expose :text?, as: :text expose :deleted_file?, as: :deleted_file
expose :diff_refs expose :diff_refs
expose :stored_externally?, as: :stored_externally expose :stored_externally?, as: :stored_externally
expose :external_storage expose :external_storage
expose :renamed_file?, as: :renamed_file
expose :deleted_file?, as: :deleted_file
expose :mode_changed?, as: :mode_changed expose :mode_changed?, as: :mode_changed
expose :a_mode expose :a_mode
expose :b_mode expose :b_mode
expose :viewer, using: DiffViewerEntity
private private
def memoized_submodule_links(diff_file) def memoized_submodule_links(diff_file)
......
...@@ -4,12 +4,10 @@ class DiffFileEntity < DiffFileBaseEntity ...@@ -4,12 +4,10 @@ class DiffFileEntity < DiffFileBaseEntity
include CommitsHelper include CommitsHelper
include IconsHelper include IconsHelper
expose :too_large?, as: :too_large
expose :empty?, as: :empty
expose :added_lines expose :added_lines
expose :removed_lines expose :removed_lines
expose :load_collapsed_diff_url, if: -> (diff_file, options) { diff_file.text? && options[:merge_request] } do |diff_file| expose :load_collapsed_diff_url, if: -> (diff_file, options) { diff_file.viewer.collapsed? && options[:merge_request] } do |diff_file|
merge_request = options[:merge_request] merge_request = options[:merge_request]
project = merge_request.target_project project = merge_request.target_project
...@@ -36,10 +34,6 @@ class DiffFileEntity < DiffFileBaseEntity ...@@ -36,10 +34,6 @@ class DiffFileEntity < DiffFileBaseEntity
project_blob_path(project, tree_join(diff_file.content_sha, diff_file.new_path)) project_blob_path(project, tree_join(diff_file.content_sha, diff_file.new_path))
end end
expose :viewer, using: DiffViewerEntity do |diff_file|
diff_file.rich_viewer || diff_file.simple_viewer
end
expose :replaced_view_path, if: -> (_, options) { options[:merge_request] } do |diff_file| expose :replaced_view_path, if: -> (_, options) { options[:merge_request] } do |diff_file|
image_diff = diff_file.rich_viewer && diff_file.rich_viewer.partial_name == 'image' image_diff = diff_file.rich_viewer && diff_file.rich_viewer.partial_name == 'image'
image_replaced = diff_file.old_content_sha && diff_file.old_content_sha != diff_file.content_sha image_replaced = diff_file.old_content_sha && diff_file.old_content_sha != diff_file.content_sha
......
# frozen_string_literal: true # frozen_string_literal: true
class DiffViewerEntity < Grape::Entity class DiffViewerEntity < Grape::Entity
# Partial name refers directly to a Rails feature, let's avoid
# using this on the frontend.
expose :partial_name, as: :name expose :partial_name, as: :name
expose :error do |diff_viewer| expose :render_error, as: :error
diff_viewer.render_error_message expose :render_error_message, as: :error_message
end expose :collapsed?, as: :collapsed
end end
...@@ -293,6 +293,10 @@ module Gitlab ...@@ -293,6 +293,10 @@ module Gitlab
end end
end end
def viewer
rich_viewer || simple_viewer
end
def simple_viewer def simple_viewer
@simple_viewer ||= simple_viewer_class.new(self) @simple_viewer ||= simple_viewer_class.new(self)
end end
......
...@@ -222,6 +222,11 @@ describe 'Merge request > User creates image diff notes', :js do ...@@ -222,6 +222,11 @@ describe 'Merge request > User creates image diff notes', :js do
end end
def create_image_diff_note def create_image_diff_note
expand_text = 'Click to expand it.'
page.all('a', text: expand_text).each do |element|
element.click
end
find('.js-add-image-diff-note-button', match: :first).click find('.js-add-image-diff-note-button', match: :first).click
find('.diff-content .note-textarea').native.send_keys('image diff test comment') find('.diff-content .note-textarea').native.send_keys('image diff test comment')
click_button 'Comment' click_button 'Comment'
......
...@@ -14,6 +14,17 @@ ...@@ -14,6 +14,17 @@
"string", "string",
"null" "null"
] ]
},
"error_message": {
"type": [
"string",
"null"
]
},
"collapsed": {
"type": [
"boolean"
]
} }
}, },
"additionalProperties": false "additionalProperties": false
......
...@@ -6,6 +6,7 @@ import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants'; ...@@ -6,6 +6,7 @@ import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
import '~/behaviors/markdown/render_gfm'; import '~/behaviors/markdown/render_gfm';
import diffFileMockData from '../mock_data/diff_file'; import diffFileMockData from '../mock_data/diff_file';
import discussionsMockData from '../mock_data/diff_discussions'; import discussionsMockData from '../mock_data/diff_discussions';
import { diffViewerModes } from '~/ide/constants';
describe('DiffContent', () => { describe('DiffContent', () => {
const Component = Vue.extend(DiffContentComponent); const Component = Vue.extend(DiffContentComponent);
...@@ -52,26 +53,39 @@ describe('DiffContent', () => { ...@@ -52,26 +53,39 @@ describe('DiffContent', () => {
describe('empty files', () => { describe('empty files', () => {
beforeEach(() => { beforeEach(() => {
vm.diffFile.empty = true;
vm.diffFile.highlighted_diff_lines = []; vm.diffFile.highlighted_diff_lines = [];
vm.diffFile.parallel_diff_lines = []; vm.diffFile.parallel_diff_lines = [];
}); });
it('should render a message', done => { it('should render a no preview message if viewer returns no preview', done => {
vm.diffFile.viewer.name = diffViewerModes.no_preview;
vm.$nextTick(() => { vm.$nextTick(() => {
const block = vm.$el.querySelector('.diff-viewer .nothing-here-block'); const block = vm.$el.querySelector('.diff-viewer .nothing-here-block');
expect(block).not.toBe(null); expect(block).not.toBe(null);
expect(block.textContent.trim()).toContain('Empty file'); expect(block.textContent.trim()).toContain('No preview for this file type');
done();
});
});
it('should render a not diffable message if viewer returns not diffable', done => {
vm.diffFile.viewer.name = diffViewerModes.not_diffable;
vm.$nextTick(() => {
const block = vm.$el.querySelector('.diff-viewer .nothing-here-block');
expect(block).not.toBe(null);
expect(block.textContent.trim()).toContain(
'This diff was suppressed by a .gitattributes entry',
);
done(); done();
}); });
}); });
it('should not render multiple messages', done => { it('should not render multiple messages', done => {
vm.diffFile.mode_changed = true;
vm.diffFile.b_mode = '100755'; vm.diffFile.b_mode = '100755';
vm.diffFile.viewer.name = 'mode_changed'; vm.diffFile.viewer.name = diffViewerModes.mode_changed;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.querySelectorAll('.nothing-here-block').length).toBe(1); expect(vm.$el.querySelectorAll('.nothing-here-block').length).toBe(1);
...@@ -81,6 +95,7 @@ describe('DiffContent', () => { ...@@ -81,6 +95,7 @@ describe('DiffContent', () => {
}); });
it('should not render diff table', done => { it('should not render diff table', done => {
vm.diffFile.viewer.name = diffViewerModes.no_preview;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.querySelector('table')).toBe(null); expect(vm.$el.querySelector('table')).toBe(null);
...@@ -157,6 +172,7 @@ describe('DiffContent', () => { ...@@ -157,6 +172,7 @@ describe('DiffContent', () => {
vm.diffFile.new_sha = 'DEF'; vm.diffFile.new_sha = 'DEF';
vm.diffFile.old_path = 'test.abc'; vm.diffFile.old_path = 'test.abc';
vm.diffFile.old_sha = 'ABC'; vm.diffFile.old_sha = 'ABC';
vm.diffFile.viewer.name = diffViewerModes.added;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(el.querySelectorAll('.js-diff-inline-view').length).toEqual(0); expect(el.querySelectorAll('.js-diff-inline-view').length).toEqual(0);
......
...@@ -4,15 +4,15 @@ import diffsModule from '~/diffs/store/modules'; ...@@ -4,15 +4,15 @@ import diffsModule from '~/diffs/store/modules';
import notesModule from '~/notes/stores/modules'; import notesModule from '~/notes/stores/modules';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue'; import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffDiscussionsMockData from '../mock_data/diff_discussions';
import { diffViewerModes } from '~/ide/constants';
Vue.use(Vuex); Vue.use(Vuex);
const discussionFixture = 'merge_requests/diff_discussion.json';
describe('diff_file_header', () => { describe('diff_file_header', () => {
let vm; let vm;
let props; let props;
const diffDiscussionMock = getJSONFixture(discussionFixture)[0]; const diffDiscussionMock = diffDiscussionsMockData;
const Component = Vue.extend(DiffFileHeader); const Component = Vue.extend(DiffFileHeader);
const store = new Vuex.Store({ const store = new Vuex.Store({
...@@ -303,13 +303,13 @@ describe('diff_file_header', () => { ...@@ -303,13 +303,13 @@ describe('diff_file_header', () => {
}); });
it('displays old and new path if the file was renamed', () => { it('displays old and new path if the file was renamed', () => {
props.diffFile.renamed_file = true; props.diffFile.viewer.name = diffViewerModes.renamed;
vm = mountComponentWithStore(Component, { props, store }); vm = mountComponentWithStore(Component, { props, store });
expect(filePaths()).toHaveLength(2); expect(filePaths()).toHaveLength(2);
expect(filePaths()[0]).toHaveText(props.diffFile.old_path); expect(filePaths()[0]).toHaveText(props.diffFile.old_path_html);
expect(filePaths()[1]).toHaveText(props.diffFile.new_path); expect(filePaths()[1]).toHaveText(props.diffFile.new_path_html);
}); });
}); });
...@@ -319,14 +319,12 @@ describe('diff_file_header', () => { ...@@ -319,14 +319,12 @@ describe('diff_file_header', () => {
const button = vm.$el.querySelector('.btn-clipboard'); const button = vm.$el.querySelector('.btn-clipboard');
expect(button).not.toBe(null); expect(button).not.toBe(null);
expect(button.dataset.clipboardText).toBe( expect(button.dataset.clipboardText).toBe('{"text":"CHANGELOG.rb","gfm":"`CHANGELOG.rb`"}');
'{"text":"files/ruby/popen.rb","gfm":"`files/ruby/popen.rb`"}',
);
}); });
describe('file mode', () => { describe('file mode', () => {
it('it displays old and new file mode if it changed', () => { it('it displays old and new file mode if it changed', () => {
props.diffFile.mode_changed = true; props.diffFile.viewer.name = diffViewerModes.mode_changed;
vm = mountComponentWithStore(Component, { props, store }); vm = mountComponentWithStore(Component, { props, store });
...@@ -338,7 +336,7 @@ describe('diff_file_header', () => { ...@@ -338,7 +336,7 @@ describe('diff_file_header', () => {
}); });
it('does not display the file mode if it has not changed', () => { it('does not display the file mode if it has not changed', () => {
props.diffFile.mode_changed = false; props.diffFile.viewer.name = diffViewerModes.text;
vm = mountComponentWithStore(Component, { props, store }); vm = mountComponentWithStore(Component, { props, store });
......
import Vue from 'vue'; import Vue from 'vue';
import DiffFileComponent from '~/diffs/components/diff_file.vue'; import DiffFileComponent from '~/diffs/components/diff_file.vue';
import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
import store from '~/mr_notes/stores'; import store from '~/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file'; import diffFileMockData from '../mock_data/diff_file';
...@@ -27,8 +28,8 @@ describe('DiffFile', () => { ...@@ -27,8 +28,8 @@ describe('DiffFile', () => {
expect(el.querySelector('.file-title-name').innerText.indexOf(file_path)).toBeGreaterThan(-1); expect(el.querySelector('.file-title-name').innerText.indexOf(file_path)).toBeGreaterThan(-1);
expect(el.querySelector('.js-syntax-highlight')).toBeDefined(); expect(el.querySelector('.js-syntax-highlight')).toBeDefined();
expect(vm.file.renderIt).toEqual(false); expect(vm.renderIt).toEqual(false);
vm.file.renderIt = true; vm.renderIt = true;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(el.querySelectorAll('.line_content').length).toBeGreaterThan(5); expect(el.querySelectorAll('.line_content').length).toBeGreaterThan(5);
...@@ -38,9 +39,9 @@ describe('DiffFile', () => { ...@@ -38,9 +39,9 @@ describe('DiffFile', () => {
describe('collapsed', () => { describe('collapsed', () => {
it('should not have file content', done => { it('should not have file content', done => {
expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(1); expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(1);
expect(vm.file.collapsed).toEqual(false); expect(vm.isCollapsed).toEqual(false);
vm.file.collapsed = true; vm.isCollapsed = true;
vm.file.renderIt = true; vm.renderIt = true;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(0); expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(0);
...@@ -50,9 +51,8 @@ describe('DiffFile', () => { ...@@ -50,9 +51,8 @@ describe('DiffFile', () => {
}); });
it('should have collapsed text and link', done => { it('should have collapsed text and link', done => {
vm.file.renderIt = true; vm.renderIt = true;
vm.file.collapsed = false; vm.isCollapsed = true;
vm.file.highlighted_diff_lines = null;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.innerText).toContain('This diff is collapsed'); expect(vm.$el.innerText).toContain('This diff is collapsed');
...@@ -63,8 +63,8 @@ describe('DiffFile', () => { ...@@ -63,8 +63,8 @@ describe('DiffFile', () => {
}); });
it('should have collapsed text and link even before rendered', done => { it('should have collapsed text and link even before rendered', done => {
vm.file.renderIt = false; vm.renderIt = false;
vm.file.collapsed = true; vm.isCollapsed = true;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.innerText).toContain('This diff is collapsed'); expect(vm.$el.innerText).toContain('This diff is collapsed');
...@@ -75,10 +75,10 @@ describe('DiffFile', () => { ...@@ -75,10 +75,10 @@ describe('DiffFile', () => {
}); });
it('should be collapsed for renamed files', done => { it('should be collapsed for renamed files', done => {
vm.file.renderIt = true; vm.renderIt = true;
vm.file.collapsed = false; vm.isCollapsed = false;
vm.file.highlighted_diff_lines = null; vm.file.highlighted_diff_lines = null;
vm.file.renamed_file = true; vm.file.viewer.name = diffViewerModes.renamed;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.innerText).not.toContain('This diff is collapsed'); expect(vm.$el.innerText).not.toContain('This diff is collapsed');
...@@ -88,10 +88,10 @@ describe('DiffFile', () => { ...@@ -88,10 +88,10 @@ describe('DiffFile', () => {
}); });
it('should be collapsed for mode changed files', done => { it('should be collapsed for mode changed files', done => {
vm.file.renderIt = true; vm.renderIt = true;
vm.file.collapsed = false; vm.isCollapsed = false;
vm.file.highlighted_diff_lines = null; vm.file.highlighted_diff_lines = null;
vm.file.mode_changed = true; vm.file.viewer.name = diffViewerModes.mode_changed;
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.innerText).not.toContain('This diff is collapsed'); expect(vm.$el.innerText).not.toContain('This diff is collapsed');
...@@ -101,7 +101,7 @@ describe('DiffFile', () => { ...@@ -101,7 +101,7 @@ describe('DiffFile', () => {
}); });
it('should have loading icon while loading a collapsed diffs', done => { it('should have loading icon while loading a collapsed diffs', done => {
vm.file.collapsed = true; vm.isCollapsed = true;
vm.isLoadingCollapsedDiff = true; vm.isLoadingCollapsedDiff = true;
vm.$nextTick(() => { vm.$nextTick(() => {
...@@ -116,7 +116,7 @@ describe('DiffFile', () => { ...@@ -116,7 +116,7 @@ describe('DiffFile', () => {
describe('too large diff', () => { describe('too large diff', () => {
it('should have too large warning and blob link', done => { it('should have too large warning and blob link', done => {
const BLOB_LINK = '/file/view/path'; const BLOB_LINK = '/file/view/path';
vm.file.too_large = true; vm.file.viewer.error = diffViewerErrors.too_large;
vm.file.view_path = BLOB_LINK; vm.file.view_path = BLOB_LINK;
vm.$nextTick(() => { vm.$nextTick(() => {
...@@ -140,11 +140,11 @@ describe('DiffFile', () => { ...@@ -140,11 +140,11 @@ describe('DiffFile', () => {
vm.file.highlighted_diff_lines = undefined; vm.file.highlighted_diff_lines = undefined;
vm.file.parallel_diff_lines = []; vm.file.parallel_diff_lines = [];
vm.file.collapsed = true; vm.isCollapsed = true;
vm.$nextTick() vm.$nextTick()
.then(() => { .then(() => {
vm.file.collapsed = false; vm.isCollapsed = false;
return vm.$nextTick(); return vm.$nextTick();
}) })
......
...@@ -266,7 +266,7 @@ export default { ...@@ -266,7 +266,7 @@ export default {
blob_name: 'CHANGELOG', blob_name: 'CHANGELOG',
blob_icon: '<i aria-hidden="true" data-hidden="true" class="fa fa-file-text-o fa-fw"></i>', blob_icon: '<i aria-hidden="true" data-hidden="true" class="fa fa-file-text-o fa-fw"></i>',
file_hash: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a', file_hash: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a',
file_path: 'CHANGELOG', file_path: 'CHANGELOG.rb',
new_file: false, new_file: false,
deleted_file: false, deleted_file: false,
renamed_file: false, renamed_file: false,
...@@ -286,7 +286,7 @@ export default { ...@@ -286,7 +286,7 @@ export default {
content_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13', content_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
stored_externally: null, stored_externally: null,
external_storage: null, external_storage: null,
old_path_html: ['CHANGELOG', 'CHANGELOG'], old_path_html: 'CHANGELOG_OLD',
new_path_html: 'CHANGELOG', new_path_html: 'CHANGELOG',
context_lines_path: context_lines_path:
'/gitlab-org/gitlab-test/blob/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG/diff', '/gitlab-org/gitlab-test/blob/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG/diff',
...@@ -485,6 +485,10 @@ export default { ...@@ -485,6 +485,10 @@ export default {
}, },
}, },
], ],
viewer: {
name: 'text',
error: null,
},
}, },
diff_discussion: true, diff_discussion: true,
truncated_diff_lines: [ truncated_diff_lines: [
......
...@@ -25,6 +25,8 @@ export default { ...@@ -25,6 +25,8 @@ export default {
text: true, text: true,
viewer: { viewer: {
name: 'text', name: 'text',
error: null,
collapsed: false,
}, },
added_lines: 2, added_lines: 2,
removed_lines: 0, removed_lines: 0,
......
...@@ -262,12 +262,16 @@ describe('DiffsStoreActions', () => { ...@@ -262,12 +262,16 @@ describe('DiffsStoreActions', () => {
{ {
id: 1, id: 1,
renderIt: false, renderIt: false,
collapsed: false, viewer: {
collapsed: false,
},
}, },
{ {
id: 2, id: 2,
renderIt: false, renderIt: false,
collapsed: false, viewer: {
collapsed: false,
},
}, },
], ],
}; };
...@@ -766,7 +770,9 @@ describe('DiffsStoreActions', () => { ...@@ -766,7 +770,9 @@ describe('DiffsStoreActions', () => {
diffFiles: [ diffFiles: [
{ {
file_hash: 'HASH', file_hash: 'HASH',
collapsed, viewer: {
collapsed,
},
renderIt, renderIt,
}, },
], ],
......
...@@ -51,13 +51,13 @@ describe('Diffs Module Getters', () => { ...@@ -51,13 +51,13 @@ describe('Diffs Module Getters', () => {
describe('hasCollapsedFile', () => { describe('hasCollapsedFile', () => {
it('returns true when all files are collapsed', () => { it('returns true when all files are collapsed', () => {
localState.diffFiles = [{ collapsed: true }, { collapsed: true }]; localState.diffFiles = [{ viewer: { collapsed: true } }, { viewer: { collapsed: true } }];
expect(getters.hasCollapsedFile(localState)).toEqual(true); expect(getters.hasCollapsedFile(localState)).toEqual(true);
}); });
it('returns true when at least one file is collapsed', () => { it('returns true when at least one file is collapsed', () => {
localState.diffFiles = [{ collapsed: false }, { collapsed: true }]; localState.diffFiles = [{ viewer: { collapsed: false } }, { viewer: { collapsed: true } }];
expect(getters.hasCollapsedFile(localState)).toEqual(true); expect(getters.hasCollapsedFile(localState)).toEqual(true);
}); });
......
...@@ -121,8 +121,14 @@ describe('DiffsStoreMutations', () => { ...@@ -121,8 +121,14 @@ describe('DiffsStoreMutations', () => {
describe('ADD_COLLAPSED_DIFFS', () => { describe('ADD_COLLAPSED_DIFFS', () => {
it('should update the state with the given data for the given file hash', () => { it('should update the state with the given data for the given file hash', () => {
const fileHash = 123; const fileHash = 123;
const state = { diffFiles: [{}, { file_hash: fileHash, existing_field: 0 }] }; const state = {
const data = { diff_files: [{ file_hash: fileHash, extra_field: 1, existing_field: 1 }] }; diffFiles: [{}, { file_hash: fileHash, existing_field: 0 }],
};
const data = {
diff_files: [
{ file_hash: fileHash, extra_field: 1, existing_field: 1, viewer: { name: 'text' } },
],
};
mutations[types.ADD_COLLAPSED_DIFFS](state, { file: state.diffFiles[1], data }); mutations[types.ADD_COLLAPSED_DIFFS](state, { file: state.diffFiles[1], data });
......
...@@ -601,7 +601,7 @@ describe('DiffsStoreUtils', () => { ...@@ -601,7 +601,7 @@ describe('DiffsStoreUtils', () => {
it('returns mode_changed if key has no match', () => { it('returns mode_changed if key has no match', () => {
expect( expect(
utils.getDiffMode({ utils.getDiffMode({
mode_changed: true, viewer: { name: 'mode_changed' },
}), }),
).toBe('mode_changed'); ).toBe('mode_changed');
}); });
......
...@@ -22,6 +22,7 @@ describe('DiffViewer', () => { ...@@ -22,6 +22,7 @@ describe('DiffViewer', () => {
createComponent({ createComponent({
diffMode: 'replaced', diffMode: 'replaced',
diffViewerMode: 'image',
newPath: GREEN_BOX_IMAGE_URL, newPath: GREEN_BOX_IMAGE_URL,
newSha: 'ABC', newSha: 'ABC',
oldPath: RED_BOX_IMAGE_URL, oldPath: RED_BOX_IMAGE_URL,
...@@ -45,6 +46,7 @@ describe('DiffViewer', () => { ...@@ -45,6 +46,7 @@ describe('DiffViewer', () => {
it('renders fallback download diff display', done => { it('renders fallback download diff display', done => {
createComponent({ createComponent({
diffMode: 'replaced', diffMode: 'replaced',
diffViewerMode: 'added',
newPath: 'test.abc', newPath: 'test.abc',
newSha: 'ABC', newSha: 'ABC',
oldPath: 'testold.abc', oldPath: 'testold.abc',
...@@ -72,6 +74,7 @@ describe('DiffViewer', () => { ...@@ -72,6 +74,7 @@ describe('DiffViewer', () => {
it('renders renamed component', () => { it('renders renamed component', () => {
createComponent({ createComponent({
diffMode: 'renamed', diffMode: 'renamed',
diffViewerMode: 'renamed',
newPath: 'test.abc', newPath: 'test.abc',
newSha: 'ABC', newSha: 'ABC',
oldPath: 'testold.abc', oldPath: 'testold.abc',
...@@ -84,6 +87,7 @@ describe('DiffViewer', () => { ...@@ -84,6 +87,7 @@ describe('DiffViewer', () => {
it('renders mode changed component', () => { it('renders mode changed component', () => {
createComponent({ createComponent({
diffMode: 'mode_changed', diffMode: 'mode_changed',
diffViewerMode: 'image',
newPath: 'test.abc', newPath: 'test.abc',
newSha: 'ABC', newSha: 'ABC',
oldPath: 'testold.abc', oldPath: 'testold.abc',
......
...@@ -22,7 +22,7 @@ describe DiffFileEntity do ...@@ -22,7 +22,7 @@ describe DiffFileEntity do
let(:request) { EntityRequest.new(project: project, current_user: user) } let(:request) { EntityRequest.new(project: project, current_user: user) }
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let(:entity) { described_class.new(diff_file, request: request, merge_request: merge_request) } let(:entity) { described_class.new(diff_file, request: request, merge_request: merge_request) }
let(:exposed_urls) { %i(load_collapsed_diff_url edit_path view_path context_lines_path) } let(:exposed_urls) { %i(edit_path view_path context_lines_path) }
it_behaves_like 'diff file entity' it_behaves_like 'diff file entity'
...@@ -38,6 +38,12 @@ describe DiffFileEntity do ...@@ -38,6 +38,12 @@ describe DiffFileEntity do
expect(response[attribute]).to include(merge_request.target_project.to_param) expect(response[attribute]).to include(merge_request.target_project.to_param)
end end
end end
it 'exposes load_collapsed_diff_url if the file viewer is collapsed' do
allow(diff_file.viewer).to receive(:collapsed?) { true }
expect(subject).to include(:load_collapsed_diff_url)
end
end end
context '#parallel_diff_lines' do context '#parallel_diff_lines' do
......
...@@ -6,9 +6,9 @@ shared_examples 'diff file base entity' do ...@@ -6,9 +6,9 @@ shared_examples 'diff file base entity' do
:submodule_tree_url, :old_path_html, :submodule_tree_url, :old_path_html,
:new_path_html, :blob, :can_modify_blob, :new_path_html, :blob, :can_modify_blob,
:file_hash, :file_path, :old_path, :new_path, :file_hash, :file_path, :old_path, :new_path,
:collapsed, :text, :diff_refs, :stored_externally, :viewer, :diff_refs, :stored_externally,
:external_storage, :renamed_file, :deleted_file, :external_storage, :renamed_file, :deleted_file,
:mode_changed, :a_mode, :b_mode, :new_file) :a_mode, :b_mode, :new_file)
end end
# Converted diff files from GitHub import does not contain blob file # Converted diff files from GitHub import does not contain blob file
...@@ -30,9 +30,9 @@ shared_examples 'diff file entity' do ...@@ -30,9 +30,9 @@ shared_examples 'diff file entity' do
it_behaves_like 'diff file base entity' it_behaves_like 'diff file base entity'
it 'exposes correct attributes' do it 'exposes correct attributes' do
expect(subject).to include(:too_large, :added_lines, :removed_lines, expect(subject).to include(:added_lines, :removed_lines,
:context_lines_path, :highlighted_diff_lines, :context_lines_path, :highlighted_diff_lines,
:parallel_diff_lines, :empty) :parallel_diff_lines)
end end
it 'includes viewer' do it 'includes viewer' do
......
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