Commit ee294618 authored by Matthias Käppler's avatar Matthias Käppler

Merge branch 'blob-show-spec' into 'master'

Blob refactor: Fix/update blob show specs

See merge request gitlab-org/gitlab!78541
parents 84ff263c 9e1369c1
......@@ -42,6 +42,11 @@ export default {
required: false,
default: false,
},
showPath: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {
......@@ -55,6 +60,9 @@ export default {
showDefaultActions() {
return !this.hideDefaultActions;
},
isEmpty() {
return this.blob.rawSize === 0;
},
},
watch: {
viewer(newVal, oldVal) {
......@@ -74,7 +82,7 @@ export default {
<div class="js-file-title file-title-flex-parent">
<div class="gl-display-flex">
<table-of-contents class="gl-pr-2" />
<blob-filepath :blob="blob">
<blob-filepath :blob="blob" :show-path="showPath">
<template #filepath-prepend>
<slot name="prepend"></slot>
</template>
......@@ -88,12 +96,13 @@ export default {
<default-actions
v-if="showDefaultActions"
:raw-path="blob.rawPath"
:raw-path="blob.externalStorageUrl || blob.rawPath"
:active-viewer="viewer"
:has-render-error="hasRenderError"
:is-binary="isBinary"
:environment-name="blob.environmentFormattedExternalUrl"
:environment-path="blob.environmentExternalUrlForRouteMap"
:is-empty="isEmpty"
@copy="proxyCopyRequest"
/>
</div>
......
......@@ -48,6 +48,11 @@ export default {
required: false,
default: null,
},
isEmpty: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
downloadUrl() {
......@@ -87,6 +92,7 @@ export default {
icon="copy-to-clipboard"
category="primary"
variant="default"
class="js-copy-blob-source-btn"
/>
<gl-button
v-if="!isBinary"
......@@ -100,6 +106,7 @@ export default {
variant="default"
/>
<gl-button
v-if="!isEmpty"
v-gl-tooltip.hover
:aria-label="$options.BTN_DOWNLOAD_TITLE"
:title="$options.BTN_DOWNLOAD_TITLE"
......
......@@ -15,6 +15,11 @@ export default {
type: Object,
required: true,
},
showPath: {
type: Boolean,
required: false,
default: true,
},
},
computed: {
blobSize() {
......@@ -26,6 +31,13 @@ export default {
showLfsBadge() {
return this.blob.storedExternally && this.blob.externalStorage === 'lfs';
},
fileName() {
if (this.showPath) {
return this.blob.path;
}
return this.blob.name;
},
},
};
</script>
......@@ -33,12 +45,12 @@ export default {
<div class="file-header-content d-flex align-items-center lh-100">
<slot name="filepath-prepend"></slot>
<template v-if="blob.path">
<file-icon :file-name="blob.path" :size="16" aria-hidden="true" css-classes="mr-2" />
<template v-if="fileName">
<file-icon :file-name="fileName" :size="16" aria-hidden="true" css-classes="mr-2" />
<strong
class="file-title-name mr-1 js-blob-header-filepath"
data-qa-selector="file_title_content"
>{{ blob.path }}</strong
>{{ fileName }}</strong
>
</template>
......
......@@ -153,7 +153,7 @@ export default {
},
blobViewer() {
const { fileType } = this.viewer;
return loadViewer(fileType);
return loadViewer(fileType, this.isUsingLfs);
},
viewerProps() {
const { fileType } = this.viewer;
......@@ -185,6 +185,9 @@ export default {
? this.blobInfo.ideForkAndEditPath
: this.blobInfo.forkAndEditPath;
},
isUsingLfs() {
return this.blobInfo.storedExternally && this.blobInfo.externalStorage === 'lfs';
},
},
methods: {
loadLegacyViewer(type) {
......@@ -245,10 +248,11 @@ export default {
<div v-if="blobInfo && !isLoading" class="file-holder">
<blob-header
:blob="blobInfo"
:hide-viewer-switcher="!hasRichViewer || isBinaryFileType"
:hide-viewer-switcher="!hasRichViewer || isBinaryFileType || isUsingLfs"
:is-binary="isBinaryFileType"
:active-viewer-type="viewer.type"
:has-render-error="hasRenderError"
:show-path="false"
@viewer-changed="switchViewer"
>
<template #actions>
......
export const loadViewer = (type) => {
switch (type) {
case 'empty':
return () => import(/* webpackChunkName: 'blob_empty_viewer' */ './empty_viewer.vue');
case 'text':
return gon.features.highlightJs
? () =>
import(
/* webpackChunkName: 'blob_text_viewer' */ '~/vue_shared/components/source_viewer.vue'
)
: null;
case 'download':
return () => import(/* webpackChunkName: 'blob_download_viewer' */ './download_viewer.vue');
case 'image':
return () => import(/* webpackChunkName: 'blob_image_viewer' */ './image_viewer.vue');
case 'video':
return () => import(/* webpackChunkName: 'blob_video_viewer' */ './video_viewer.vue');
case 'pdf':
return () => import(/* webpackChunkName: 'blob_pdf_viewer' */ './pdf_viewer.vue');
default:
return null;
const viewers = {
download: () => import('./download_viewer.vue'),
image: () => import('./image_viewer.vue'),
video: () => import('./video_viewer.vue'),
empty: () => import('./empty_viewer.vue'),
text: () => import('~/vue_shared/components/source_viewer.vue'),
pdf: () => import('./pdf_viewer.vue'),
lfs: () => import('./lfs_viewer.vue'),
};
export const loadViewer = (type, isUsingLfs) => {
let viewer = viewers[type];
if (!viewer && isUsingLfs) {
viewer = viewers.lfs;
}
return viewer;
};
export const viewerProps = (type, blob) => {
return {
const props = {
text: {
content: blob.rawTextBlob,
autoDetect: true, // We'll eventually disable autoDetect and pass the language explicitly to reduce the footprint (https://gitlab.com/gitlab-org/gitlab/-/issues/348145)
......@@ -44,5 +40,11 @@ export const viewerProps = (type, blob) => {
url: blob.rawPath,
fileSize: blob.rawSize,
},
}[type];
lfs: {
fileName: blob.name,
filePath: blob.rawPath,
},
};
return props[type] || props[blob.externalStorage];
};
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
i18n: {
lfsText: __(
'This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead.',
),
},
components: {
GlLink,
GlSprintf,
},
props: {
fileName: {
type: String,
required: true,
},
filePath: {
type: String,
required: true,
},
},
};
</script>
<template>
<div class="gl-text-center gl-py-13 gl-bg-gray-50" data-type="lfs">
<gl-sprintf :message="$options.i18n.lfsText">
<template #link="{ content }">
<gl-link :href="filePath" :download="fileName" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</div>
</template>
......@@ -32,6 +32,7 @@ query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
archived
storedExternally
externalStorage
externalStorageUrl
rawPath
replacePath
pipelineEditorPath
......
......@@ -115,7 +115,12 @@ export default {
};
</script>
<template>
<div class="file-content code js-syntax-highlight" :class="$options.userColorScheme">
<div
class="file-content code js-syntax-highlight blob-content"
:class="$options.userColorScheme"
data-type="simple"
data-qa-selector="blob_viewer_file_content"
>
<line-numbers :lines="lineNumbers" />
<pre class="code"><code v-safe-html="highlightedContent"></code>
</pre>
......
......@@ -125,7 +125,7 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
def external_storage_url
return unless static_objects_external_storage_enabled?
external_storage_url_or_path(url_helpers.project_raw_url(project, ref_qualified_path))
external_storage_url_or_path(url_helpers.project_raw_url(project, ref_qualified_path), project)
end
private
......
......@@ -36578,6 +36578,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
msgstr ""
msgid "This credential has expired"
msgstr ""
......
......@@ -22,6 +22,10 @@ module QA
element :copy_contents_button
end
base.view 'app/assets/javascripts/vue_shared/components/source_viewer.vue' do
element :blob_viewer_file_content
end
base.view 'app/views/projects/blob/_header_content.html.haml' do
element :file_name_content
end
......
......@@ -29,10 +29,7 @@ RSpec.describe 'File blob', :js do
).execute
end
before do
stub_feature_flags(refactor_blob_viewer: false) # This stub will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/350455
end
context 'with refactor_blob_viewer feature flag enabled' do
context 'Ruby file' do
before do
visit_blob('files/ruby/popen.rb')
......@@ -79,7 +76,7 @@ RSpec.describe 'File blob', :js do
it 'displays the blob using the rich viewer' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
expect(page).to have_selector('.blob-viewer[data-type="rich"]')
# shows rendered Markdown
......@@ -107,7 +104,7 @@ RSpec.describe 'File blob', :js do
aggregate_failures do
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
# shows highlighted Markdown code
expect(page).to have_css(".js-syntax-highlight")
......@@ -128,11 +125,11 @@ RSpec.describe 'File blob', :js do
it 'displays the blob using the rich viewer' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
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)')
# shows a disabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
end
end
end
......@@ -149,28 +146,6 @@ RSpec.describe 'File blob', :js do
end
end
it 'displays single highlighted line number of different ref' do
visit_blob('files/js/application.js', anchor: 'L1')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
end
end
it 'displays multiple highlighted line numbers of different ref' do
visit_blob('files/js/application.js', anchor: 'L1-3')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
expect(find_by_id('LC2')[:class]).to include("hll")
expect(find_by_id('LC3')[:class]).to include("hll")
end
end
it 'displays no highlighted number of different ref' do
Files::UpdateService.new(
project,
......@@ -231,30 +206,6 @@ RSpec.describe 'File blob', :js do
end
end
end
context 'visiting with a line number anchor' do
before do
visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1')
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).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
# highlights the line in question
expect(page).to have_selector('#LC1.hll')
# 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
end
end
context 'Markdown rendering' do
......@@ -316,14 +267,14 @@ RSpec.describe 'File blob', :js do
it 'displays an error' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
expect(page).to have_selector('.blob-viewer[data-type="rich"]')
expect(page).not_to have_selector('.blob-viewer[data-type="simple"]')
expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
# 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.')
expect(page).to have_content('This content 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 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')
......@@ -332,28 +283,6 @@ RSpec.describe 'File blob', :js do
expect(page).to have_link('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
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
# 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
......@@ -473,7 +402,7 @@ RSpec.describe 'File blob', :js do
it 'displays the blob' do
aggregate_failures do
# shows a download link
expect(page).to have_link('Download (1.5 MB)')
expect(page).to have_link('Download (1.50 MiB)')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
......@@ -522,7 +451,7 @@ RSpec.describe 'File blob', :js do
it 'displays the blob' do
aggregate_failures do
# shows a download link
expect(page).to have_link('Download (2.11 KB)')
expect(page).to have_link('Download (2.11 KiB)')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
......@@ -573,42 +502,7 @@ RSpec.describe 'File blob', :js do
end
end
context 'binary file that appears to be text in the first 1024 bytes' do
before do
visit_blob('encoding/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_link('Open raw')
end
end
end
context 'files with auxiliary viewers' do
before do
stub_feature_flags(refactor_blob_viewer: true)
end
describe '.gitlab-ci.yml' do
before do
project.add_maintainer(project.creator)
......@@ -1054,12 +948,221 @@ RSpec.describe 'File blob', :js do
end
end
end
end
context 'realtime pipelines' do
before do
Files::CreateService.new(
project,
project.creator,
start_branch: 'feature',
branch_name: 'feature',
commit_message: "Add ruby file",
file_path: 'files/ruby/test.rb',
file_content: "# Awesome content"
).execute
create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
visit_blob('files/ruby/test.rb', ref: 'feature')
end
it 'shows the realtime pipeline status' do
page.within('.commit-actions') do
expect(page).to have_css('.ci-status-icon')
expect(page).to have_css('.ci-status-icon-running')
expect(page).to have_css('.js-ci-status-icon-running')
end
end
end
context 'for subgroups' do
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
let(:project) { create(:project, :public, :repository, group: subgroup) }
it 'renders tree table without errors' do
visit_blob('README.md')
expect(page).to have_selector('.file-content')
expect(page).not_to have_selector('.flash-alert')
end
it 'displays a GPG badge' do
visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
expect(page).to have_selector '.gpg-status-box.invalid'
end
end
context 'on signed merge commit' do
it 'displays a GPG badge' do
visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
expect(page).to have_selector '.gpg-status-box.invalid'
end
end
context 'when static objects external storage is enabled' do
before do
stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
end
context 'when refactor_blob_viewer is disabled' do
context 'public project' do
before do
visit_blob('README.md')
end
it 'shows open raw and download buttons with external storage URL prepended to their href' do
path = project_raw_path(project, 'master/README.md')
raw_uri = "https://cdn.gitlab.com#{path}"
download_uri = "https://cdn.gitlab.com#{path}?inline=false"
aggregate_failures do
expect(page).to have_link 'Open raw', href: raw_uri
expect(page).to have_link 'Download', href: download_uri
end
end
end
end
end
context 'with refactor_blob_viewer feature flag disabled' do
before do
stub_feature_flags(refactor_blob_viewer: false)
end
context 'when ref switch' do
# We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
# This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558
def switch_ref_to(ref_name)
first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
page.within '.project-refs-form' do
click_link ref_name
wait_for_requests
end
end
context 'when highlighting lines' do
it 'displays single highlighted line number of different ref' do
visit_blob('files/js/application.js', anchor: 'L1')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
end
end
it 'displays multiple highlighted line numbers of different ref' do
visit_blob('files/js/application.js', anchor: 'L1-3')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
expect(find_by_id('LC2')[:class]).to include("hll")
expect(find_by_id('LC3')[:class]).to include("hll")
end
end
end
end
context 'visiting with a line number anchor' do
# We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
# This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558
before do
visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1')
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"]')
# highlights the line in question
expect(page).to have_selector('#LC1.hll')
# 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
end
context 'binary file that appears to be text in the first 1024 bytes' do
# We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
# This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351559
before do
visit_blob('encoding/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_link('Open raw')
end
end
end
context 'when static objects external storage is enabled' do
# We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
# This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351555
before do
stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
end
context 'private project' do
let_it_be(:project) { create(:project, :repository, :private) }
let_it_be(:user) { create(:user) }
before do
project.add_developer(user)
sign_in(user)
visit_blob('README.md')
end
it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
path = project_raw_path(project, 'master/README.md')
raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}"
aggregate_failures do
expect(page).to have_link 'Open raw', href: raw_uri
expect(page).to have_link 'Download', href: download_uri
end
end
end
end
context 'files with auxiliary viewers' do
# This context is the same as the other 'files with auxiliary viewers' in this file, we just ensure that the auxiliary viewers still work this the refactor_blob_viewer disabled
# It should be safe to remove once we rollout the refactored blob viewer
describe '.gitlab-ci.yml' do
before do
project.add_maintainer(project.creator)
......@@ -1554,104 +1657,4 @@ RSpec.describe 'File blob', :js do
end
end
end
context 'realtime pipelines' do
before do
Files::CreateService.new(
project,
project.creator,
start_branch: 'feature',
branch_name: 'feature',
commit_message: "Add ruby file",
file_path: 'files/ruby/test.rb',
file_content: "# Awesome content"
).execute
create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
visit_blob('files/ruby/test.rb', ref: 'feature')
end
it 'shows the realtime pipeline status' do
page.within('.commit-actions') do
expect(page).to have_css('.ci-status-icon')
expect(page).to have_css('.ci-status-icon-running')
expect(page).to have_css('.js-ci-status-icon-running')
end
end
end
context 'for subgroups' do
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
let(:project) { create(:project, :public, :repository, group: subgroup) }
it 'renders tree table without errors' do
visit_blob('README.md')
expect(page).to have_selector('.file-content')
expect(page).not_to have_selector('.flash-alert')
end
it 'displays a GPG badge' do
visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
expect(page).to have_selector '.gpg-status-box.invalid'
end
end
context 'on signed merge commit' do
it 'displays a GPG badge' do
visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
expect(page).to have_selector '.gpg-status-box.invalid'
end
end
context 'when static objects external storage is enabled' do
before do
stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
end
context 'private project' do
let_it_be(:project) { create(:project, :repository, :private) }
let_it_be(:user) { create(:user) }
before do
project.add_developer(user)
sign_in(user)
visit_blob('README.md')
end
it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
path = project_raw_path(project, 'master/README.md')
raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}"
aggregate_failures do
expect(page).to have_link 'Open raw', href: raw_uri
expect(page).to have_link 'Download', href: download_uri
end
end
end
context 'public project' do
before do
visit_blob('README.md')
end
it 'shows open raw and download buttons with external storage URL prepended to their href' do
path = project_raw_path(project, 'master/README.md')
raw_uri = "https://cdn.gitlab.com#{path}"
download_uri = "https://cdn.gitlab.com#{path}?inline=false"
aggregate_failures do
expect(page).to have_link 'Open raw', href: raw_uri
expect(page).to have_link 'Download', href: download_uri
end
end
end
end
end
......@@ -13,6 +13,7 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
<blob-filepath-stub
blob="[object Object]"
showpath="true"
/>
</div>
......
......@@ -236,7 +236,7 @@ describe('Blob content viewer component', () => {
await waitForPromises();
expect(loadViewer).toHaveBeenCalledWith(viewer);
expect(loadViewer).toHaveBeenCalledWith(viewer, false);
expect(wrapper.findComponent(loadViewerReturnValue).exists()).toBe(true);
},
);
......
import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import LfsViewer from '~/repository/components/blob_viewers/lfs_viewer.vue';
describe('LFS Viewer', () => {
let wrapper;
const DEFAULT_PROPS = {
fileName: 'file_name.js',
filePath: '/some/file/path',
};
const createComponent = () => {
wrapper = shallowMount(LfsViewer, {
propsData: { ...DEFAULT_PROPS },
stubs: { GlSprintf },
});
};
const findLink = () => wrapper.findComponent(GlLink);
beforeEach(() => createComponent());
afterEach(() => wrapper.destroy());
it('renders the correct text', () => {
expect(wrapper.text()).toBe(
'This content could not be displayed because it is stored in LFS. You can download it instead.',
);
});
it('renders download link', () => {
const { filePath, fileName } = DEFAULT_PROPS;
expect(findLink().attributes()).toMatchObject({
target: '_blank',
href: filePath,
download: fileName,
});
});
});
......@@ -17,6 +17,7 @@ export const simpleViewerMock = {
canCurrentUserPushToBranch: true,
archived: false,
storedExternally: false,
externalStorageUrl: '',
externalStorage: 'lfs',
rawPath: 'some_file.js',
replacePath: 'some_file.js/replace',
......
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