Commit 9302be37 authored by Paul Slaughter's avatar Paul Slaughter

Remove snippets_vue feature flag

- Also wrapped snippet_show in DOMContentLoaded
- Also fixes full screen comment button on snippets
parent b33510a2
import { __ } from '~/locale';
import { parseUrlPathname, parseUrl } from '../lib/utils/common_utils';
function swapActiveState(activateBtn, deactivateBtn) {
activateBtn.classList.add('is-active');
deactivateBtn.classList.remove('is-active');
}
export default () => {
const shareBtn = document.querySelector('.js-share-btn');
if (shareBtn) {
const embedBtn = document.querySelector('.js-embed-btn');
const snippetUrlArea = document.querySelector('.js-snippet-url-area');
const embedAction = document.querySelector('.js-embed-action');
const dataUrl = snippetUrlArea.getAttribute('data-url');
snippetUrlArea.addEventListener('click', () => snippetUrlArea.select());
shareBtn.addEventListener('click', () => {
swapActiveState(shareBtn, embedBtn);
snippetUrlArea.value = dataUrl;
embedAction.innerText = __('Share');
});
embedBtn.addEventListener('click', () => {
const parser = parseUrl(dataUrl);
const url = `${parser.origin + parseUrlPathname(dataUrl)}`;
const params = parser.search;
const scriptTag = `<script src="${url}.js${params}"></script>`;
swapActiveState(embedBtn, shareBtn);
snippetUrlArea.value = scriptTag;
embedAction.innerText = __('Embed');
});
}
};
if (!gon.features.snippetsVue) {
const LineHighlighterModule = import('~/line_highlighter');
const BlobViewerModule = import('~/blob/viewer');
const ZenModeModule = import('~/zen_mode');
const SnippetEmbedModule = import('~/snippet/snippet_embed');
const initNotesModule = import('~/init_notes');
const loadAwardsHandlerModule = import('~/awards_handler');
import initNotes from '~/init_notes';
import loadAwardsHandler from '~/awards_handler';
import { SnippetShowInit } from '~/snippets';
import ZenMode from '~/zen_mode';
Promise.all([
LineHighlighterModule,
BlobViewerModule,
ZenModeModule,
SnippetEmbedModule,
initNotesModule,
loadAwardsHandlerModule,
])
.then(
([
{ default: LineHighlighter },
{ default: BlobViewer },
{ default: ZenMode },
{ default: SnippetEmbed },
{ default: initNotes },
{ default: loadAwardsHandler },
]) => {
new LineHighlighter(); // eslint-disable-line no-new
new BlobViewer(); // eslint-disable-line no-new
new ZenMode(); // eslint-disable-line no-new
SnippetEmbed();
initNotes();
loadAwardsHandler();
},
)
.catch(() => {});
} else {
import('~/snippets')
.then(({ SnippetShowInit }) => {
SnippetShowInit();
})
.then(() => {
return Promise.all([import('~/init_notes'), import('~/awards_handler')]);
})
.then(([{ default: initNotes }, { default: loadAwardsHandler }]) => {
initNotes();
loadAwardsHandler();
})
.catch(() => {});
}
document.addEventListener('DOMContentLoaded', () => {
SnippetShowInit();
initNotes();
loadAwardsHandler();
// eslint-disable-next-line no-new
new ZenMode();
});
......@@ -60,7 +60,7 @@ export default {
class="gl-dropdown-text-py-0 gl-dropdown-text-block"
data-testid="input"
>
<gl-form-input-group :value="value" readonly select-on-click>
<gl-form-input-group :value="value" readonly select-on-click :aria-label="name">
<template #append>
<gl-button
v-gl-tooltip.hover
......
......@@ -18,14 +18,6 @@
}
}
.markdown-snippet-copy {
position: fixed;
top: -10px;
left: -10px;
max-height: 0;
max-width: 0;
}
.snippet-file-content {
border-radius: 3px;
......@@ -45,21 +37,6 @@
min-height: $header-height;
}
.snippet-actions {
@include media-breakpoint-up(sm) {
float: right;
}
}
.snippet-scope-menu .btn-success {
margin-top: 15px;
}
.embed-snippet {
padding-right: 0;
padding-top: $gl-padding;
.embed-toggle-list li button {
padding: 8px 40px;
}
}
......@@ -32,31 +32,6 @@ module SnippetsHelper
end
end
# Get an array of line numbers surrounding a matching
# line, bounded by min/max.
#
# @returns Array of line numbers
def bounded_line_numbers(line, min, max, surrounding_lines)
lower = line - surrounding_lines > min ? line - surrounding_lines : min
upper = line + surrounding_lines < max ? line + surrounding_lines : max
(lower..upper).to_a
end
def snippet_embed_tag(snippet)
content_tag(:script, nil, src: gitlab_snippet_url(snippet, format: :js))
end
def snippet_embed_input(snippet)
content_tag(:input,
nil,
type: :text,
readonly: true,
class: 'js-snippet-url-area snippet-embed-input form-control',
data: { url: gitlab_snippet_url(snippet) },
value: snippet_embed_tag(snippet),
autocomplete: 'off')
end
def snippet_badge(snippet)
return unless attrs = snippet_badge_attributes(snippet)
......
......@@ -23,8 +23,6 @@ module VisibilityLevelHelper
project_visibility_level_description(level)
when Group
group_visibility_level_description(level)
when Snippet
snippet_visibility_level_description(level, form_model)
end
end
......@@ -50,21 +48,6 @@ module VisibilityLevelHelper
end
end
def snippet_visibility_level_description(level, snippet = nil)
case level
when Gitlab::VisibilityLevel::PRIVATE
if snippet.is_a? ProjectSnippet
_("The snippet is visible only to project members.")
else
_("The snippet is visible only to me.")
end
when Gitlab::VisibilityLevel::INTERNAL
_("The snippet is visible to any logged in user.")
when Gitlab::VisibilityLevel::PUBLIC
_("The snippet can be accessed without any authentication.")
end
end
# Note: these messages closely mirror the form validation strings found in the project
# model and any changes or additons to these may also need to be made there.
def disallowed_project_visibility_level_description(level, project)
......
- return unless current_user
.d-none.d-sm-block
- if can?(current_user, :update_snippet, @snippet)
= link_to edit_project_snippet_path(@project, @snippet), class: "btn btn-grouped" do
= _('Edit')
- if can?(current_user, :admin_snippet, @snippet)
= link_to project_snippet_path(@project, @snippet), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Snippet') do
= _('Delete')
- if can?(current_user, :create_snippet, @project)
= link_to new_project_snippet_path(@project), class: 'btn btn-grouped btn-inverted btn-success', title: _("New snippet") do
= _('New snippet')
- if @snippet.submittable_as_spam_by?(current_user)
= link_to _('Submit as spam'), mark_as_spam_project_snippet_path(@project, @snippet), method: :post, class: 'btn btn-grouped btn-spam', title: _('Submit as spam')
- if can?(current_user, :create_snippet, @project) || can?(current_user, :update_snippet, @snippet)
.d-block.d-sm-none.dropdown
%button.btn.btn-default.btn-block.gl-mb-0.gl-mt-2{ data: { toggle: "dropdown" } }
= _('Options')
= icon('caret-down')
.dropdown-menu.dropdown-menu-full-width
%ul
- if can?(current_user, :create_snippet, @project)
%li
= link_to new_project_snippet_path(@project), title: _("New snippet") do
= _('New snippet')
- if can?(current_user, :admin_snippet, @snippet)
%li
= link_to project_snippet_path(@project, @snippet), method: :delete, data: { confirm: _("Are you sure?") }, title: _('Delete Snippet') do
= _('Delete')
- if can?(current_user, :update_snippet, @snippet)
%li
= link_to edit_project_snippet_path(@project, @snippet) do
= _('Edit')
- if @snippet.submittable_as_spam_by?(current_user)
%li
= link_to _('Submit as spam'), mark_as_spam_project_snippet_path(@project, @snippet), method: :post
......@@ -3,13 +3,7 @@
- breadcrumb_title @snippet.to_reference
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
- if Feature.enabled?(:snippets_vue, default_enabled: true)
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id} }
- else
= render 'shared/snippets/header'
.project-snippets
= render 'shared/snippets/blob', blob: @blob
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id} }
.row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
......
%article.file-holder.snippet-file-content
.js-file-title.file-title-flex-parent
= render 'projects/blob/header_content', blob: blob
.file-actions.d-none.d-sm-block
= render 'projects/blob/viewer_switcher', blob: blob
.btn-group{ role: "group" }<
= copy_blob_source_button(blob)
= open_raw_blob_button(blob)
= download_raw_snippet_button(@snippet)
= render 'projects/blob/content', blob: blob
.detail-page-header
.detail-page-header-body
.snippet-box.has-tooltip.inline.gl-mr-2{ title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: "body" } }
%span.sr-only
= visibility_level_label(@snippet.visibility_level)
= visibility_level_icon(@snippet.visibility_level)
%span.creator
= s_('Snippets|Authored %{time_ago} by %{author}').html_safe % { time_ago: time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago'), author: link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title", avatar_class: "d-none d-sm-inline") + user_status(@snippet.author) }
.detail-page-header-actions
- if @snippet.project_id?
= render "projects/snippets/actions"
- else
= render "snippets/actions"
.snippet-header.limited-header-width
%h2.snippet-title.gl-mt-0.mb-3
= markdown_field(@snippet, :title)
- if @snippet.description.present?
.description
.md
= markdown_field(@snippet, :description)
- if @snippet.updated_at != @snippet.created_at
= edited_time_ago_with_tooltip(@snippet, placement: 'bottom', exclude_author: true)
- if @snippet.embeddable?
.embed-snippet
.input-group
.input-group-prepend
%button.btn.gl-button.btn-svg.embed-toggle.input-group-text{ 'data-toggle': 'dropdown', type: 'button' }
%span.js-embed-action= _("Embed")
= sprite_icon('angle-down', size: 12, css_class: 'caret-down')
%ul.dropdown-menu.dropdown-menu-selectable.embed-toggle-list
%li
%button.js-embed-btn.btn.gl-button.btn-default-tertiary.is-active{ type: 'button' }
%strong.embed-toggle-list-item= _("Embed")
%li
%button.js-share-btn.btn.gl-button.btn-default-tertiary{ type: 'button' }
%strong.embed-toggle-list-item= _("Share")
= snippet_embed_input(@snippet)
.input-group-append
= clipboard_button(title: _('Copy'), class: 'js-clipboard-btn snippet-clipboard-btn btn btn-default', target: '.js-snippet-url-area')
.clearfix
- return unless current_user
.d-none.d-sm-block
- if can?(current_user, :update_snippet, @snippet)
= link_to edit_snippet_path(@snippet), class: "btn btn-grouped" do
= _("Edit")
- if can?(current_user, :admin_snippet, @snippet)
= link_to gitlab_snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Snippet') do
= _("Delete")
- if can?(current_user, :create_snippet)
= link_to new_snippet_path, class: "btn btn-grouped btn-success btn-inverted", title: _("New snippet") do
= _("New snippet")
- if @snippet.submittable_as_spam_by?(current_user)
= link_to _('Submit as spam'), mark_as_spam_snippet_path(@snippet), method: :post, class: 'btn btn-grouped btn-spam', title: _('Submit as spam')
.d-block.d-sm-none.dropdown
%button.btn.btn-default.btn-block.gl-mb-0.gl-mt-2{ data: { toggle: "dropdown" } }
= _("Options")
= icon('caret-down')
.dropdown-menu.dropdown-menu-full-width
%ul
- if can?(current_user, :create_snippet)
%li
= link_to new_snippet_path, title: _("New snippet") do
= _("New snippet")
- if can?(current_user, :admin_snippet, @snippet)
%li
= link_to gitlab_snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, title: _('Delete Snippet') do
= _("Delete")
- if can?(current_user, :update_snippet, @snippet)
%li
= link_to edit_snippet_path(@snippet) do
= _("Edit")
- if @snippet.submittable_as_spam_by?(current_user)
%li
= link_to _('Submit as spam'), mark_as_spam_snippet_path(@snippet), method: :post
......@@ -4,13 +4,7 @@
- breadcrumb_title @snippet.to_reference
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
- if Feature.enabled?(:snippets_vue, default_enabled: true)
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id} }
- else
= render 'shared/snippets/header'
.personal-snippets
= render 'shared/snippets/blob', blob: @blob
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id} }
.row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
......
---
title: Fix full screen comment button on snippets
merge_request: 44083
author:
type: fixed
---
name: snippets_vue
introduced_by_url:
rollout_issue_url:
group: group::editor
type: development
default_enabled: true
......@@ -43,7 +43,6 @@ module Gitlab
# Initialize gon.features with any flags that should be
# made globally available to the frontend
push_frontend_feature_flag(:snippets_vue, default_enabled: true)
push_frontend_feature_flag(:monaco_blobs, default_enabled: true)
push_frontend_feature_flag(:monaco_ci, default_enabled: true)
push_frontend_feature_flag(:webperf_experiment, default_enabled: false)
......
......@@ -8352,9 +8352,6 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
msgid "Delete Snippet"
msgstr ""
msgid "Delete Value Stream"
msgstr ""
......@@ -23967,9 +23964,6 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
msgid "Snippets|Authored %{time_ago} by %{author}"
msgstr ""
msgid "Snippets|Delete file"
msgstr ""
......@@ -24786,9 +24780,6 @@ msgstr ""
msgid "Submit a review"
msgstr ""
msgid "Submit as spam"
msgstr ""
msgid "Submit changes"
msgstr ""
......
......@@ -8,7 +8,6 @@ RSpec.describe 'Thread Comments Snippet', :js do
let_it_be(:snippet) { create(:project_snippet, :private, :repository, project: project, author: user) }
before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
......
......@@ -13,8 +13,6 @@ RSpec.describe 'Projects > Snippets > Project snippet', :js do
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
before do
stub_feature_flags(snippets_vue: false)
sign_in(user)
end
......@@ -28,12 +26,8 @@ RSpec.describe 'Projects > Snippets > Project snippet', :js do
end
end
it_behaves_like 'showing user status' do
let(:file_path) { 'files/ruby/popen.rb' }
let(:user_with_status) { snippet.author }
subject { visit project_snippet_path(project, snippet) }
end
# it_behaves_like 'showing user status' do
# This will be handled in https://gitlab.com/gitlab-org/gitlab/-/issues/262394
it_behaves_like 'does not show New Snippet button' do
let(:file_path) { 'files/ruby/popen.rb' }
......
......@@ -8,7 +8,6 @@ RSpec.describe 'Projects > Snippets > User comments on a snippet', :js do
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
......
......@@ -2,13 +2,12 @@
require 'spec_helper'
RSpec.describe 'Projects > Snippets > User deletes a snippet' do
RSpec.describe 'Projects > Snippets > User deletes a snippet', :js do
let(:project) { create(:project) }
let!(:snippet) { create(:project_snippet, project: project, author: user) }
let!(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
let(:user) { create(:user) }
before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
......@@ -16,7 +15,11 @@ RSpec.describe 'Projects > Snippets > User deletes a snippet' do
end
it 'deletes a snippet' do
first(:link, 'Delete').click
expect(page).to have_content(snippet.title)
click_button('Delete')
click_button('Delete snippet')
wait_for_requests
expect(page).not_to have_content(snippet.title)
end
......
......@@ -7,7 +7,6 @@ RSpec.describe 'Reportable note on snippets', :js do
let_it_be(:project) { create(:project) }
before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
end
......
......@@ -3,11 +3,8 @@
require 'spec_helper'
RSpec.describe 'Internal Snippets', :js do
let(:internal_snippet) { create(:personal_snippet, :internal) }
before do
stub_feature_flags(snippets_vue: false)
end
let(:internal_snippet) { create(:personal_snippet, :internal, :repository) }
let(:content) { internal_snippet.blobs.first.data.strip! }
describe 'normal user' do
before do
......@@ -17,13 +14,13 @@ RSpec.describe 'Internal Snippets', :js do
it 'sees internal snippets' do
visit snippet_path(internal_snippet)
expect(page).to have_content(internal_snippet.content)
expect(page).to have_content(content)
end
it 'sees raw internal snippets' do
visit raw_snippet_path(internal_snippet)
expect(page).to have_content(internal_snippet.content)
expect(page).to have_content(content)
end
end
end
......@@ -18,7 +18,6 @@ RSpec.describe 'Comments on personal snippets', :js do
end
before do
stub_feature_flags(snippets_vue: false)
sign_in user
visit snippet_path(snippet)
......
......@@ -4,19 +4,18 @@ require 'spec_helper'
RSpec.describe 'Private Snippets', :js do
let(:user) { create(:user) }
let(:private_snippet) { create(:personal_snippet, :repository, :private, author: user) }
let(:content) { private_snippet.blobs.first.data.strip! }
before do
stub_feature_flags(snippets_vue: false)
sign_in(user)
end
it 'Private Snippet renders for creator' do
private_snippet = create(:personal_snippet, :private, author: user)
visit snippet_path(private_snippet)
wait_for_requests
expect(page).to have_content(private_snippet.content)
expect(page).to have_content(content)
expect(page).not_to have_css('.js-embed-btn')
expect(page).not_to have_css('.js-share-btn')
end
......
......@@ -3,27 +3,24 @@
require 'spec_helper'
RSpec.describe 'Public Snippets', :js do
before do
stub_feature_flags(snippets_vue: false)
end
let(:public_snippet) { create(:personal_snippet, :public, :repository) }
let(:content) { public_snippet.blobs.first.data.strip! }
it 'Unauthenticated user should see public snippets' do
public_snippet = create(:personal_snippet, :public)
url = Gitlab::UrlBuilder.build(public_snippet)
visit snippet_path(public_snippet)
wait_for_requests
expect(page).to have_content(public_snippet.content)
expect(page).to have_css('.js-embed-btn', visible: false)
expect(page).to have_css('.js-share-btn', visible: false)
expect(page.find('.js-snippet-url-area')).to be_readonly
expect(page).to have_content(content)
click_button('Embed')
expect(page).to have_field('Embed', readonly: true, with: "<script src=\"#{url}.js\"></script>")
expect(page).to have_field('Share', readonly: true, with: url)
end
it 'Unauthenticated user should see raw public snippets' do
public_snippet = create(:personal_snippet, :public)
visit raw_snippet_path(public_snippet)
expect(page).to have_content(public_snippet.content)
expect(page).to have_content(content)
end
end
......@@ -6,10 +6,6 @@ RSpec.describe 'Snippet', :js do
let_it_be(:user) { create(:user) }
let_it_be(:snippet) { create(:personal_snippet, :public, :repository, author: user) }
before do
stub_feature_flags(snippets_vue: false)
end
it_behaves_like 'show and render proper snippet blob' do
let(:anchor) { nil }
......@@ -20,12 +16,8 @@ RSpec.describe 'Snippet', :js do
end
end
it_behaves_like 'showing user status' do
let(:file_path) { 'files/ruby/popen.rb' }
let(:user_with_status) { snippet.author }
subject { visit snippet_path(snippet) }
end
# it_behaves_like 'showing user status' do
# This will be handled in https://gitlab.com/gitlab-org/gitlab/-/issues/262394
it_behaves_like 'does not show New Snippet button' do
let(:file_path) { 'files/ruby/popen.rb' }
......
......@@ -2,21 +2,23 @@
require 'spec_helper'
RSpec.describe 'User deletes snippet' do
RSpec.describe 'User deletes snippet', :js do
let(:user) { create(:user) }
let(:content) { 'puts "test"' }
let(:snippet) { create(:personal_snippet, :public, content: content, author: user) }
let(:snippet) { create(:personal_snippet, :repository, :public, content: content, author: user) }
before do
sign_in(user)
stub_feature_flags(snippets_vue: false)
visit snippet_path(snippet)
end
it 'deletes the snippet' do
first(:link, 'Delete').click
expect(page).to have_content(snippet.title)
click_button('Delete')
click_button('Delete snippet')
wait_for_requests
expect(page).not_to have_content(snippet.title)
end
......
......@@ -18,11 +18,8 @@ RSpec.describe 'Snippets' do
describe 'rendering engine' do
let_it_be(:snippet) { create(:personal_snippet, :public) }
let(:snippets_vue_feature_flag_enabled) { true }
before do
stub_feature_flags(snippets_vue: snippets_vue_feature_flag_enabled)
visit snippet_path(snippet)
end
......@@ -30,14 +27,5 @@ RSpec.describe 'Snippets' do
expect(page).to have_selector('#js-snippet-view')
expect(page).not_to have_selector('.personal-snippets')
end
context 'when feature flag is disabled' do
let(:snippets_vue_feature_flag_enabled) { false }
it 'renders HAML application and not Vue' do
expect(page).not_to have_selector('#js-snippet-view')
expect(page).to have_selector('.personal-snippets')
end
end
end
end
......@@ -2,6 +2,7 @@
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
import { setTestTimeout } from 'helpers/timeout';
import BlobViewer from '~/blob/viewer/index';
import axios from '~/lib/utils/axios_utils';
......@@ -13,26 +14,22 @@ describe('Blob viewer', () => {
tooltip: jest.fn(),
};
preloadFixtures('snippets/show.html');
setTestTimeout(2000);
preloadFixtures('blob/show_readme.html');
beforeEach(() => {
$.fn.extend(jQueryMock);
mock = new MockAdapter(axios);
loadFixtures('snippets/show.html');
loadFixtures('blob/show_readme.html');
$('#modal-upload-blob').remove();
blob = new BlobViewer();
mock.onGet('http://test.host/-/snippets/1.json?viewer=rich').reply(200, {
html: '<div>testing</div>',
});
mock.onGet('http://test.host/-/snippets/1.json?viewer=simple').reply(200, {
mock.onGet(/blob\/master\/README\.md/).reply(200, {
html: '<div>testing</div>',
});
jest.spyOn(axios, 'get');
blob = new BlobViewer();
});
afterEach(() => {
......@@ -71,12 +68,11 @@ describe('Blob viewer', () => {
});
it('doesnt reload file if already loaded', () => {
const asyncClick = () =>
new Promise(resolve => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
const asyncClick = async () => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setImmediate(resolve);
});
await axios.waitForAll();
};
return asyncClick()
.then(() => asyncClick())
......@@ -163,17 +159,30 @@ describe('Blob viewer', () => {
expect(simpleBtn.blur).toHaveBeenCalled();
});
it('sends AJAX request when switching to simple view', () => {
blob.switchToViewer('simple');
expect(axios.get).toHaveBeenCalled();
it('makes request for initial view', () => {
expect(mock.history).toMatchObject({
get: [{ url: expect.stringMatching(/README\.md\?.*viewer=rich/) }],
});
});
it('does not send AJAX request when switching to rich view', () => {
blob.switchToViewer('simple');
blob.switchToViewer('rich');
describe.each`
views
${['simple']}
${['simple', 'rich']}
`('when view switches to $views', ({ views }) => {
beforeEach(async () => {
views.forEach(view => blob.switchToViewer(view));
await axios.waitForAll();
});
expect(axios.get.mock.calls.length).toBe(1);
it('sends 1 AJAX request for new view', async () => {
expect(mock.history).toMatchObject({
get: [
{ url: expect.stringMatching(/README\.md\?.*viewer=rich/) },
{ url: expect.stringMatching(/README\.md\?.*viewer=simple/) },
],
});
});
});
});
});
......@@ -33,4 +33,14 @@ RSpec.describe Projects::BlobController, '(JavaScript fixtures)', type: :control
expect(response).to be_successful
end
it 'blob/show_readme.html' do
get(:show, params: {
namespace_id: project.namespace,
project_id: project,
id: 'master/README.md'
})
expect(response).to be_successful
end
end
......@@ -17,7 +17,6 @@ RSpec.describe SnippetsController, '(JavaScript fixtures)', type: :controller do
end
before do
stub_feature_flags(snippets_vue: false)
sign_in(admin)
allow(Discussion).to receive(:build_discussion_id).and_return(['discussionid:ceterumcenseo'])
end
......
import snippetEmbed from '~/snippet/snippet_embed';
import { loadHTMLFixture } from './helpers/fixtures';
describe('Snippets', () => {
let embedBtn;
let snippetUrlArea;
let shareBtn;
let scriptTag;
const snippetUrl = 'http://test.host/-/snippets/1';
beforeEach(() => {
loadHTMLFixture('snippets/show.html');
embedBtn = document.querySelector('.js-embed-btn');
snippetUrlArea = document.querySelector('.js-snippet-url-area');
shareBtn = document.querySelector('.js-share-btn');
});
it('selects the fields content when it is clicked', () => {
jest.spyOn(snippetUrlArea, 'select');
snippetEmbed();
expect(snippetUrlArea.select).not.toHaveBeenCalled();
snippetUrlArea.dispatchEvent(new Event('click'));
expect(snippetUrlArea.select).toHaveBeenCalled();
});
describe('when the snippet url does not include params', () => {
beforeEach(() => {
snippetEmbed();
scriptTag = `<script src="${snippetUrl}.js"></script>`;
});
it('shows the script tag as default', () => {
expect(snippetUrlArea.value).toEqual(scriptTag);
});
it('sets the proper url depending on the button clicked', () => {
shareBtn.dispatchEvent(new Event('click'));
expect(snippetUrlArea.value).toEqual(snippetUrl);
embedBtn.dispatchEvent(new Event('click'));
expect(snippetUrlArea.value).toEqual(scriptTag);
});
});
describe('when the snippet url includes params', () => {
beforeEach(() => {
scriptTag = `<script src="${snippetUrl}.js?foo=bar"></script>`;
snippetUrlArea.value = scriptTag;
snippetUrlArea.dataset.url = `${snippetUrl}?foo=bar`;
snippetEmbed();
});
it('shows the script tag as default', () => {
expect(snippetUrlArea.value).toEqual(scriptTag);
});
it('sets the proper url depending on the button clicked', () => {
shareBtn.dispatchEvent(new Event('click'));
expect(snippetUrlArea.value).toEqual(`${snippetUrl}?foo=bar`);
embedBtn.dispatchEvent(new Event('click'));
expect(snippetUrlArea.value).toEqual(scriptTag);
});
});
});
......@@ -63,32 +63,6 @@ RSpec.describe SnippetsHelper do
end
end
describe '#snippet_embed_tag' do
subject { snippet_embed_tag(snippet) }
context 'personal snippets' do
let(:snippet) { public_personal_snippet }
context 'public' do
it 'returns a script tag with the snippet full url' do
expect(subject).to eq(script_embed("http://test.host/-/snippets/#{snippet.id}"))
end
end
end
context 'project snippets' do
let(:snippet) { public_project_snippet }
it 'returns a script tag with the snippet full url' do
expect(subject).to eq(script_embed("http://test.host/#{snippet.project.path_with_namespace}/-/snippets/#{snippet.id}"))
end
end
def script_embed(url)
"<script src=\"#{url}.js\"></script>"
end
end
describe '#download_raw_snippet_button' do
subject { download_raw_snippet_button(snippet) }
......@@ -142,28 +116,4 @@ RSpec.describe SnippetsHelper do
end
end
end
describe '#snippet_embed_input' do
subject { snippet_embed_input(snippet) }
context 'with PersonalSnippet' do
let(:snippet) { public_personal_snippet }
it 'returns the input component' do
expect(subject).to eq embed_input(snippet_url(snippet))
end
end
context 'with ProjectSnippet' do
let(:snippet) { public_project_snippet }
it 'returns the input component' do
expect(subject).to eq embed_input(project_snippet_url(snippet.project, snippet))
end
end
def embed_input(url)
"<input type=\"text\" readonly=\"readonly\" class=\"js-snippet-url-area snippet-embed-input form-control\" data-url=\"#{url}\" value=\"<script src=&quot;#{url}.js&quot;></script>\" autocomplete=\"off\"></input>"
end
end
end
......@@ -47,13 +47,6 @@ RSpec.describe VisibilityLevelHelper do
.to match /group/i
end
end
context 'called with a Snippet' do
it 'delegates snippets to #snippet_visibility_level_description' do
expect(visibility_level_description(Gitlab::VisibilityLevel::INTERNAL, project_snippet))
.to match /snippet/i
end
end
end
describe "#project_visibility_level_description" do
......@@ -68,23 +61,6 @@ RSpec.describe VisibilityLevelHelper do
end
end
describe "#snippet_visibility_level_description" do
it 'describes visibility only for me' do
expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, personal_snippet))
.to eq _('The snippet is visible only to me.')
end
it 'describes visibility for project members' do
expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE, project_snippet))
.to eq _('The snippet is visible only to project members.')
end
it 'defaults to personal snippet' do
expect(snippet_visibility_level_description(Gitlab::VisibilityLevel::PRIVATE))
.to eq _('The snippet is visible only to me.')
end
end
describe "disallowed_visibility_level?" do
describe "forks" do
let(:project) { create(:project, :internal) }
......
......@@ -84,7 +84,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do
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)')
expect(page).to have_button('Copy file contents', disabled: false)
# shows a raw button
expect(page).to have_link('Open raw')
......@@ -106,7 +106,6 @@ RSpec.shared_examples 'show and render proper snippet blob' 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).to have_selector('.blob-viewer[data-type="rich"]')
# shows rendered Markdown
......@@ -116,7 +115,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do
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')
expect(page).to have_button('Copy file contents', disabled: true)
# shows a raw button
expect(page).to have_link('Open raw')
......@@ -128,7 +127,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do
context 'switching to the simple viewer' do
before do
find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
find_button('Display source').click
wait_for_requests
end
......@@ -137,19 +136,18 @@ RSpec.shared_examples 'show and render proper snippet blob' 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 highlighted Markdown code
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)')
expect(page).to have_button('Copy file contents', disabled: false)
end
end
context 'switching to the rich viewer again' do
before do
find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
find_button('Display rendered file').click
wait_for_requests
end
......@@ -157,11 +155,11 @@ RSpec.shared_examples 'show and render proper snippet blob' 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).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)')
# Used to show an enabled copy button since the code has already been fetched
# Will be resolved in https://gitlab.com/gitlab-org/gitlab/-/issues/262389
expect(page).to have_button('Copy file contents', disabled: true)
end
end
end
......@@ -169,7 +167,8 @@ RSpec.shared_examples 'show and render proper snippet blob' do
end
context 'visiting with a line number anchor' do
let(:anchor) { 'L1' }
# L1 used to work and will be revisited in https://gitlab.com/gitlab-org/gitlab/-/issues/262391
let(:anchor) { 'LC1' }
it 'displays the blob using the simple viewer' do
subject
......@@ -177,7 +176,6 @@ RSpec.shared_examples 'show and render proper snippet blob' 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')
......@@ -186,7 +184,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do
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)')
expect(page).to have_button('Copy file contents', disabled: false)
end
end
end
......
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