Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-11-20 16:17:59 +0300
committerPhil Hughes <me@iamphill.com>2017-11-21 14:27:58 +0300
commitc0b26796272f09e512cd20674707b033442c956c (patch)
tree3f878fc10e089566456b09685a89e54850b7b6cc
parentee22172edd987e902903e3b12dbbfb855ce4145e (diff)
fixed up some JS based on comments
added feature spec
-rw-r--r--app/assets/javascripts/repo/components/blob_viewer_switch.vue13
-rw-r--r--app/assets/javascripts/repo/components/repo_editor.vue2
-rw-r--r--app/assets/javascripts/repo/components/repo_file_buttons.vue14
-rw-r--r--app/assets/javascripts/repo/components/source_copy_button.vue2
-rw-r--r--app/assets/javascripts/repo/components/viewers/error.vue7
-rw-r--r--app/assets/javascripts/repo/components/viewers/html.vue6
-rw-r--r--app/assets/javascripts/repo/services/index.js4
-rw-r--r--app/assets/javascripts/repo/stores/actions.js4
-rw-r--r--app/assets/javascripts/repo/stores/actions/file.js6
-rw-r--r--app/assets/javascripts/repo/stores/getters.js13
-rw-r--r--app/assets/javascripts/repo/stores/mutations/file.js1
-rw-r--r--app/assets/javascripts/repo/stores/utils.js1
-rw-r--r--app/assets/stylesheets/pages/repo.scss2
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/models/blob_viewer/server_side.rb2
-rw-r--r--spec/features/projects/tree/multi_file_blob_show_spec.rb357
-rw-r--r--spec/javascripts/repo/components/viewers/error_spec.js4
-rw-r--r--spec/javascripts/repo/stores/actions/file_spec.js8
18 files changed, 415 insertions, 33 deletions
diff --git a/app/assets/javascripts/repo/components/blob_viewer_switch.vue b/app/assets/javascripts/repo/components/blob_viewer_switch.vue
index cd1fd00bdf7..0b4379773a6 100644
--- a/app/assets/javascripts/repo/components/blob_viewer_switch.vue
+++ b/app/assets/javascripts/repo/components/blob_viewer_switch.vue
@@ -13,6 +13,9 @@
displayTooltip() {
return `Display ${this.activeFile.simple.switcherTitle}`;
},
+ richTooltip() {
+ return `Display ${this.activeFile.rich.switcherTitle}`;
+ },
},
methods: {
...mapActions([
@@ -24,18 +27,19 @@
<template>
<div
- class="btn-group"
+ class="btn-group js-blob-viewer-switcher"
role="group"
>
<button
v-tooltip
type="button"
- class="btn btn-default btn-sm"
+ class="btn btn-default btn-sm js-blob-viewer-switch-btn"
:class="{
active: activeFile.currentViewer === 'simple',
}"
:title="displayTooltip"
data-container="body"
+ data-viewer="simple"
@click="changeFileViewer({ file: activeFile, type: 'simple' })"
>
<i
@@ -48,12 +52,13 @@
<button
v-tooltip
type="button"
- class="btn btn-default btn-sm"
+ class="btn btn-default btn-sm js-blob-viewer-switch-btn"
:class="{
active: activeFile.currentViewer === 'rich',
}"
- title="Display rendered file"
+ :title="richTooltip"
data-container="body"
+ data-viewer="rich"
@click="changeFileViewer({ file: activeFile, type: 'rich' })"
>
<i
diff --git a/app/assets/javascripts/repo/components/repo_editor.vue b/app/assets/javascripts/repo/components/repo_editor.vue
index 6dd7c30cc23..aba91dc1d63 100644
--- a/app/assets/javascripts/repo/components/repo_editor.vue
+++ b/app/assets/javascripts/repo/components/repo_editor.vue
@@ -92,7 +92,7 @@ export default {
'activeFile',
]),
shouldHideEditor() {
- return this.activeFile.binary && !this.activeFile.raw;
+ return (this.activeFile.binary || this.activeFile.storedExternally) && !this.activeFile.raw;
},
},
};
diff --git a/app/assets/javascripts/repo/components/repo_file_buttons.vue b/app/assets/javascripts/repo/components/repo_file_buttons.vue
index 3560206909b..dfbd282ba20 100644
--- a/app/assets/javascripts/repo/components/repo_file_buttons.vue
+++ b/app/assets/javascripts/repo/components/repo_file_buttons.vue
@@ -1,9 +1,13 @@
<script>
import { mapGetters } from 'vuex';
+import tooltip from '../../vue_shared/directives/tooltip';
import viewerSwitch from './blob_viewer_switch.vue';
import sourceCopyButton from './source_copy_button.vue';
export default {
+ directives: {
+ tooltip,
+ },
components: {
viewerSwitch,
sourceCopyButton,
@@ -12,6 +16,7 @@ export default {
...mapGetters([
'activeFile',
'canActiveFileSwitchViewer',
+ 'canCopySource',
]),
showButtons() {
return this.activeFile.rawPath ||
@@ -20,10 +25,10 @@ export default {
this.activeFile.permalink;
},
rawDownloadButtonLabel() {
- return this.activeFile.binary ? 'Download' : 'Raw';
+ return this.activeFile.binary || this.activeFile.storedExternally ? 'Download' : 'Open raw';
},
rawDownloadButtonIcon() {
- return this.activeFile.binary ? 'fa-download' : 'fa-file-code-o';
+ return this.activeFile.binary || this.activeFile.storedExternally ? 'fa-download' : 'fa-file-code-o';
},
},
};
@@ -42,14 +47,17 @@ export default {
role="group"
>
<source-copy-button
- v-if="canActiveFileSwitchViewer"
+ v-if="canCopySource"
/>
<a
+ v-tooltip
:href="activeFile.rawPath"
target="_blank"
class="btn btn-default btn-sm raw"
rel="noopener noreferrer"
:aria-label="rawDownloadButtonLabel"
+ :title="rawDownloadButtonLabel"
+ data-container="body"
>
<i
class="fa"
diff --git a/app/assets/javascripts/repo/components/source_copy_button.vue b/app/assets/javascripts/repo/components/source_copy_button.vue
index 889a05dec03..3a21c214fa1 100644
--- a/app/assets/javascripts/repo/components/source_copy_button.vue
+++ b/app/assets/javascripts/repo/components/source_copy_button.vue
@@ -54,7 +54,7 @@
<button
v-tooltip
type="button"
- class="btn btn-default btn-sm"
+ class="btn btn-default btn-sm js-copy-blob-source-btn"
:class="{
disabled: copySourceButtonDisabled,
}"
diff --git a/app/assets/javascripts/repo/components/viewers/error.vue b/app/assets/javascripts/repo/components/viewers/error.vue
index 607ab96cc67..44f53fce875 100644
--- a/app/assets/javascripts/repo/components/viewers/error.vue
+++ b/app/assets/javascripts/repo/components/viewers/error.vue
@@ -17,14 +17,15 @@
text: 'load it anyway',
callback: () => this.getFileHTML({
file: this.activeFile,
- expanded: true,
+ override: true,
}),
});
}
if (
this.activeFile.simple.name === 'text' &&
- (this.activeFileCurrentViewer.renderError === 'server_side_but_stored_externally' || this.activeFileCurrentViewer.renderError === 'too_large')
+ this.activeFile.currentViewer === 'rich' &&
+ (this.activeFileCurrentViewer.renderError !== 'server_side_but_stored_externally')
) {
links.push({
href: '#',
@@ -64,7 +65,7 @@
<div
class="nothing-here-block"
>
- The {{ activeFileCurrentViewer.name }} could not be displayed because {{ activeFileCurrentViewer.renderErrorReason }}.
+ The {{ activeFileCurrentViewer.switcherTitle }} could not be displayed because {{ activeFileCurrentViewer.renderErrorReason }}.
You can
<template
v-for="(link, index) in optionLinks"
diff --git a/app/assets/javascripts/repo/components/viewers/html.vue b/app/assets/javascripts/repo/components/viewers/html.vue
index 44d4a26577f..d933e3cb9b2 100644
--- a/app/assets/javascripts/repo/components/viewers/html.vue
+++ b/app/assets/javascripts/repo/components/viewers/html.vue
@@ -15,10 +15,7 @@
},
methods: {
highlightFile() {
- const $el = $(this.$el).find('.file-content');
-
- $el.syntaxHighlight();
- $el.renderGFM();
+ $(this.$el).find('.blob-viewer').renderGFM();
},
},
mounted() {
@@ -32,6 +29,7 @@
this.$nextTick(() => {
this.highlightFile();
this.lineHighlighter.highlightHash();
+ gl.utils.handleLocationHash();
});
},
};
diff --git a/app/assets/javascripts/repo/services/index.js b/app/assets/javascripts/repo/services/index.js
index 483b5803cf2..b1908cfaafb 100644
--- a/app/assets/javascripts/repo/services/index.js
+++ b/app/assets/javascripts/repo/services/index.js
@@ -11,8 +11,8 @@ export default {
getFileData(endpoint) {
return Vue.http.get(endpoint, { params: { format: 'json' } });
},
- getFileHTML(endpoint, expanded) {
- return Vue.http.get(endpoint, { params: { expanded } });
+ getFileHTML(endpoint) {
+ return Vue.http.get(endpoint);
},
getRawFileData(file) {
if (file.tempFile) {
diff --git a/app/assets/javascripts/repo/stores/actions.js b/app/assets/javascripts/repo/stores/actions.js
index e3fab085ab3..7fa53f5e26a 100644
--- a/app/assets/javascripts/repo/stores/actions.js
+++ b/app/assets/javascripts/repo/stores/actions.js
@@ -117,7 +117,9 @@ export const createTempEntry = ({ state, dispatch }, { name, type, content = '',
}
};
-export const popHistoryState = ({ state, dispatch, getters }) => {
+export const popHistoryState = ({ state, dispatch, getters }, e) => {
+ if (!e.state) return;
+
const treeList = getters.treeList;
const tree = treeList.find(file => file.url === state.previousUrl);
diff --git a/app/assets/javascripts/repo/stores/actions/file.js b/app/assets/javascripts/repo/stores/actions/file.js
index b7b81f4ff30..11560bfb7a8 100644
--- a/app/assets/javascripts/repo/stores/actions/file.js
+++ b/app/assets/javascripts/repo/stores/actions/file.js
@@ -111,10 +111,10 @@ export const createTempFile = ({ state, commit, dispatch }, { tree, name, conten
return Promise.resolve(file);
};
-export const getFileHTML = ({ commit, getters }, { file, expanded = false }) => {
+export const getFileHTML = ({ commit, getters }, { file, override = false }) => {
const currentViewer = getters.activeFileCurrentViewer;
- if (expanded) {
+ if (override) {
commit(types.RESET_VIEWER_RENDER_ERROR, currentViewer);
}
@@ -122,7 +122,7 @@ export const getFileHTML = ({ commit, getters }, { file, expanded = false }) =>
commit(types.TOGGLE_FILE_VIEWER_LOADING, currentViewer);
- service.getFileHTML(currentViewer.path, expanded)
+ service.getFileHTML(currentViewer.path)
.then(res => res.json())
.then((data) => {
commit(types.TOGGLE_FILE_VIEWER_LOADING, currentViewer);
diff --git a/app/assets/javascripts/repo/stores/getters.js b/app/assets/javascripts/repo/stores/getters.js
index abbc5869d4b..55c187159cf 100644
--- a/app/assets/javascripts/repo/stores/getters.js
+++ b/app/assets/javascripts/repo/stores/getters.js
@@ -31,10 +31,19 @@ export const activeFileCurrentViewer = (state) => {
export const canActiveFileSwitchViewer = (state) => {
const file = activeFile(state);
- if (!file) return false;
+ if (!file || state.editMode) return false;
if (file.binary) return false;
- return file.rich.path !== '' && file.simple.path !== '' && file.simple.name === 'text' && !file.simple.renderError;
+ return file.rich.path !== '' && file.simple.path !== '' && file.simple.name === 'text' && !file.binary;
+};
+
+export const canCopySource = (state) => {
+ const file = activeFile(state);
+
+ if (!file || state.editMode) return false;
+ if (file.binary) return false;
+
+ return file.simple.name === 'text' && !file.simple.renderError;
};
export const isCollapsed = state => !!state.openFiles.length;
diff --git a/app/assets/javascripts/repo/stores/mutations/file.js b/app/assets/javascripts/repo/stores/mutations/file.js
index 710780e677b..e96d73282f4 100644
--- a/app/assets/javascripts/repo/stores/mutations/file.js
+++ b/app/assets/javascripts/repo/stores/mutations/file.js
@@ -31,6 +31,7 @@ export default {
renderError: data.render_error,
currentViewer: data.rich_viewer ? 'rich' : 'simple',
extension: data.extension,
+ storedExternally: data.stored_externally,
});
createViewerStructure(file, 'rich', data);
diff --git a/app/assets/javascripts/repo/stores/utils.js b/app/assets/javascripts/repo/stores/utils.js
index 803377afaa1..5d4864074fb 100644
--- a/app/assets/javascripts/repo/stores/utils.js
+++ b/app/assets/javascripts/repo/stores/utils.js
@@ -44,6 +44,7 @@ export const dataStructure = () => ({
currentViewer: 'rich',
rich: viewerDataStructure(),
simple: viewerDataStructure(),
+ storedExternally: false,
});
export const decorateData = (entity) => {
diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss
index 0dca17c2b50..b7876775dc9 100644
--- a/app/assets/stylesheets/pages/repo.scss
+++ b/app/assets/stylesheets/pages/repo.scss
@@ -94,7 +94,7 @@
overflow: auto;
.blob-full-height,
- .file-content:not(.wiki) {
+ .file-content:not(.wiki):not(.image_file) {
display: flex;
}
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 2e49e2ab0fa..00b3d4c8e18 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -49,7 +49,7 @@ class Projects::BlobController < Projects::ApplicationController
end
def viewer
- conditionally_expand_blob(@blob)
+ @blob.expand!
respond_to do |format|
format.json do
diff --git a/app/models/blob_viewer/server_side.rb b/app/models/blob_viewer/server_side.rb
index 46cb63fda0a..86afcc86aa0 100644
--- a/app/models/blob_viewer/server_side.rb
+++ b/app/models/blob_viewer/server_side.rb
@@ -5,7 +5,7 @@ module BlobViewer
included do
self.load_async = true
self.collapse_limit = 2.megabytes
- self.size_limit = 5.megabyte
+ self.size_limit = 5.megabytes
end
def prepare!
diff --git a/spec/features/projects/tree/multi_file_blob_show_spec.rb b/spec/features/projects/tree/multi_file_blob_show_spec.rb
new file mode 100644
index 00000000000..3d1e8d6d4a8
--- /dev/null
+++ b/spec/features/projects/tree/multi_file_blob_show_spec.rb
@@ -0,0 +1,357 @@
+require 'spec_helper'
+
+feature 'File blob', :js do
+ let(:project) { create(:project, :public, :repository) }
+
+ def visit_blob(path, file: '', anchor: nil, ref: 'master')
+ visit project_tree_path(project, File.join(ref, path), anchor: anchor)
+
+ wait_for_requests
+
+ click_link file
+
+ wait_for_requests
+ end
+
+ before do
+ set_cookie('new_repo', 'true')
+ end
+
+ context 'Ruby file' do
+ before do
+ visit_blob('files/ruby', file: 'popen.rb')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows highlighted Ruby code
+ expect(page).to have_css(".js-syntax-highlight")
+ expect(page).to have_content("require 'fileutils'")
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_selector('a[data-original-title="Open raw"]')
+ end
+ end
+ end
+
+ context 'Markdown file' do
+ context 'visiting directly' do
+ before do
+ visit_blob('files/markdown', file: 'ruby-style-guide.md')
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows rendered Markdown
+ expect(page).to have_link("PEP-8")
+
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # shows a disabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
+
+ # shows a raw button
+ expect(page).to have_selector('a[data-original-title="Open raw"]')
+ end
+ end
+
+ context 'switching to the simple viewer' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
+
+ wait_for_requests
+ end
+
+ it 'displays the blob using the simple viewer' do
+ aggregate_failures do
+ # hides the rich viewer
+ expect(page).to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows highlighted Markdown code
+ expect(page).to have_css(".js-syntax-highlight")
+ expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+
+ context 'switching to the rich viewer again' do
+ before do
+ find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
+
+ wait_for_requests
+ end
+
+ it 'displays the blob using the rich viewer' do
+ aggregate_failures do
+ # hides the simple viewer
+ expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
+ expect(page).to have_selector('.blob-viewer[data-type="rich"]')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+ end
+ end
+ end
+ end
+ end
+ end
+
+ context 'Markdown file (stored in LFS)' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add Markdown in LFS",
+ file_path: 'files/lfs/file.md',
+ file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data
+ ).execute
+ end
+
+ context 'when LFS is enabled on the project' do
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+
+ visit_blob('files/lfs', file: 'file.md')
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # shows an error message
+ expect(page).to have_content('The rendered file could not be displayed because it is stored in LFS. You can download it instead.')
+
+ # shows a viewer switcher
+ expect(page).to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_selector('a[data-original-title="Download"]')
+ end
+ end
+
+ context 'switching to the simple viewer' do
+ before do
+ find('.js-blob-viewer-switcher .js-blob-viewer-switch-btn[data-viewer=simple]').click
+
+ wait_for_requests
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # shows an error message
+ expect(page).to have_content('The source could not be displayed because it is stored in LFS. You can download it instead.')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+ end
+ end
+ end
+ end
+
+ context 'when LFS is disabled on the project' do
+ before do
+ visit_blob('files/lfs', file: 'file.md')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_selector('a[data-original-title="Open raw"]')
+ end
+ end
+ end
+ end
+
+ xcontext 'PDF file' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add PDF",
+ file_path: 'files/test.pdf',
+ file_content: project.repository.blob_at('add-pdf-file', 'files/pdf/test.pdf').data
+ ).execute
+
+ visit_blob('files', file: 'test.pdf')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows rendered PDF
+ expect(page).to have_selector('.js-pdf-viewer')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_selector('a[data-original-title="Download"]')
+ end
+ end
+ end
+
+ context 'ISO file (stored in LFS)' do
+ context 'when LFS is enabled on the project' do
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+
+ visit_blob('files/lfs', file: 'lfs_object.iso')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows a download link
+ expect(page).to have_link('Download (1.5 MB)')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_selector('a[data-original-title="Download"]')
+ end
+ end
+ end
+
+ context 'when LFS is disabled on the project' do
+ before do
+ visit_blob('files/lfs', file: 'lfs_object.iso')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # shows an enabled copy button
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button
+ expect(page).to have_selector('a[data-original-title="Open raw"]')
+ end
+ end
+ end
+ end
+
+ context 'ZIP file' do
+ before do
+ visit_blob('', file: 'Gemfile.zip')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows a download link
+ expect(page).to have_link('Download (2.11 KB)')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # shows a download button
+ expect(page).to have_selector('a[data-original-title="Download"]')
+ end
+ end
+ end
+
+ context 'empty file' do
+ before do
+ project.add_master(project.creator)
+
+ Files::CreateService.new(
+ project,
+ project.creator,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: "Add empty file",
+ file_path: 'files/empty.md',
+ file_content: ''
+ ).execute
+
+ visit_blob('files', file: 'empty.md')
+ end
+
+ it 'displays an error' do
+ aggregate_failures do
+ # shows an error message
+ expect(page).to have_content('Empty file')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # does not show a copy button
+ expect(page).not_to have_selector('.js-copy-blob-source-btn')
+
+ # does not show a download or raw button
+ expect(page).not_to have_selector('a[data-original-title="Download"]')
+ end
+ end
+ end
+
+ context 'binary file that appears to be text in the first 1024 bytes' do
+ before do
+ visit_blob('encoding', file: 'binary-1.bin', ref: 'binary-encoding')
+ end
+
+ it 'displays the blob' do
+ aggregate_failures do
+ # shows a download link
+ expect(page).to have_link('Download (23.8 KB)')
+
+ # does not show a viewer switcher
+ expect(page).not_to have_selector('.js-blob-viewer-switcher')
+
+ # The specs below verify an arguably incorrect result, but since we only
+ # learn that the file is not actually text once the text viewer content
+ # is loaded asynchronously, there is no straightforward way to get these
+ # synchronously loaded elements to display correctly.
+ #
+ # Clicking the copy button will result in nothing being copied.
+ # Clicking the raw button will result in the binary file being downloaded,
+ # as expected.
+
+ # shows an enabled copy button, incorrectly
+ expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
+
+ # shows a raw button, incorrectly
+ expect(page).to have_selector('a[data-original-title="Open raw"]')
+ end
+ end
+ end
+end
diff --git a/spec/javascripts/repo/components/viewers/error_spec.js b/spec/javascripts/repo/components/viewers/error_spec.js
index 0d5dbd28509..073d153c63f 100644
--- a/spec/javascripts/repo/components/viewers/error_spec.js
+++ b/spec/javascripts/repo/components/viewers/error_spec.js
@@ -53,12 +53,12 @@ describe('Multi-file editor error viewer', () => {
spyOn(vm, 'getFileHTML');
});
- it('calls getFileHTML with expanded when clicking load anyway link', () => {
+ it('calls getFileHTML with override when clicking load anyway link', () => {
vm.$el.querySelector('a').click();
expect(vm.getFileHTML).toHaveBeenCalledWith({
file: f,
- expanded: true,
+ override: true,
});
});
});
diff --git a/spec/javascripts/repo/stores/actions/file_spec.js b/spec/javascripts/repo/stores/actions/file_spec.js
index 6473069f8d0..def29c0554f 100644
--- a/spec/javascripts/repo/stores/actions/file_spec.js
+++ b/spec/javascripts/repo/stores/actions/file_spec.js
@@ -509,10 +509,10 @@ describe('Multi-file store file actions', () => {
}).catch(done.fail);
});
- it('calls service if file has renderError and expanded is true', (done) => {
+ it('calls service if file has renderError and override is true', (done) => {
localFile.rich.renderError = 'error';
- store.dispatch('getFileHTML', { file: localFile, expanded: true })
+ store.dispatch('getFileHTML', { file: localFile, override: true })
.then(() => {
expect(service.getFileHTML).toHaveBeenCalled();
@@ -520,10 +520,10 @@ describe('Multi-file store file actions', () => {
}).catch(done.fail);
});
- it('resets renderError if expanded is true', (done) => {
+ it('resets renderError if override is true', (done) => {
localFile.rich.renderError = 'error';
- store.dispatch('getFileHTML', { file: localFile, expanded: true })
+ store.dispatch('getFileHTML', { file: localFile, override: true })
.then(Vue.nextTick)
.then(() => {
expect(localFile.rich.renderError).not.toBe('error');