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) { import initNotes from '~/init_notes';
const LineHighlighterModule = import('~/line_highlighter'); import loadAwardsHandler from '~/awards_handler';
const BlobViewerModule = import('~/blob/viewer'); import { SnippetShowInit } from '~/snippets';
const ZenModeModule = import('~/zen_mode'); import ZenMode from '~/zen_mode';
const SnippetEmbedModule = import('~/snippet/snippet_embed');
const initNotesModule = import('~/init_notes');
const loadAwardsHandlerModule = import('~/awards_handler');
Promise.all([ document.addEventListener('DOMContentLoaded', () => {
LineHighlighterModule, SnippetShowInit();
BlobViewerModule, initNotes();
ZenModeModule, loadAwardsHandler();
SnippetEmbedModule,
initNotesModule, // eslint-disable-next-line no-new
loadAwardsHandlerModule, new ZenMode();
]) });
.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(() => {});
}
...@@ -60,7 +60,7 @@ export default { ...@@ -60,7 +60,7 @@ export default {
class="gl-dropdown-text-py-0 gl-dropdown-text-block" class="gl-dropdown-text-py-0 gl-dropdown-text-block"
data-testid="input" 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> <template #append>
<gl-button <gl-button
v-gl-tooltip.hover v-gl-tooltip.hover
......
...@@ -18,14 +18,6 @@ ...@@ -18,14 +18,6 @@
} }
} }
.markdown-snippet-copy {
position: fixed;
top: -10px;
left: -10px;
max-height: 0;
max-width: 0;
}
.snippet-file-content { .snippet-file-content {
border-radius: 3px; border-radius: 3px;
...@@ -45,21 +37,6 @@ ...@@ -45,21 +37,6 @@
min-height: $header-height; min-height: $header-height;
} }
.snippet-actions {
@include media-breakpoint-up(sm) {
float: right;
}
}
.snippet-scope-menu .btn-success { .snippet-scope-menu .btn-success {
margin-top: 15px; 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 ...@@ -32,31 +32,6 @@ module SnippetsHelper
end end
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) def snippet_badge(snippet)
return unless attrs = snippet_badge_attributes(snippet) return unless attrs = snippet_badge_attributes(snippet)
......
...@@ -23,8 +23,6 @@ module VisibilityLevelHelper ...@@ -23,8 +23,6 @@ module VisibilityLevelHelper
project_visibility_level_description(level) project_visibility_level_description(level)
when Group when Group
group_visibility_level_description(level) group_visibility_level_description(level)
when Snippet
snippet_visibility_level_description(level, form_model)
end end
end end
...@@ -50,21 +48,6 @@ module VisibilityLevelHelper ...@@ -50,21 +48,6 @@ module VisibilityLevelHelper
end end
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 # 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. # model and any changes or additons to these may also need to be made there.
def disallowed_project_visibility_level_description(level, project) 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 @@ ...@@ -3,13 +3,7 @@
- breadcrumb_title @snippet.to_reference - breadcrumb_title @snippet.to_reference
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets") - 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} }
#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
.row-content-block.top-block.content-component-block .row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true = 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 @@ ...@@ -4,13 +4,7 @@
- breadcrumb_title @snippet.to_reference - breadcrumb_title @snippet.to_reference
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets") - 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} }
#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
.row-content-block.top-block.content-component-block .row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true = 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 ...@@ -43,7 +43,6 @@ module Gitlab
# Initialize gon.features with any flags that should be # Initialize gon.features with any flags that should be
# made globally available to the frontend # 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_blobs, default_enabled: true)
push_frontend_feature_flag(:monaco_ci, default_enabled: true) push_frontend_feature_flag(:monaco_ci, default_enabled: true)
push_frontend_feature_flag(:webperf_experiment, default_enabled: false) push_frontend_feature_flag(:webperf_experiment, default_enabled: false)
......
...@@ -8352,9 +8352,6 @@ msgstr "" ...@@ -8352,9 +8352,6 @@ msgstr ""
msgid "Delete Comment" msgid "Delete Comment"
msgstr "" msgstr ""
msgid "Delete Snippet"
msgstr ""
msgid "Delete Value Stream" msgid "Delete Value Stream"
msgstr "" msgstr ""
...@@ -23967,9 +23964,6 @@ msgstr "" ...@@ -23967,9 +23964,6 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}" msgid "Snippets|Add another file %{num}/%{total}"
msgstr "" msgstr ""
msgid "Snippets|Authored %{time_ago} by %{author}"
msgstr ""
msgid "Snippets|Delete file" msgid "Snippets|Delete file"
msgstr "" msgstr ""
...@@ -24786,9 +24780,6 @@ msgstr "" ...@@ -24786,9 +24780,6 @@ msgstr ""
msgid "Submit a review" msgid "Submit a review"
msgstr "" msgstr ""
msgid "Submit as spam"
msgstr ""
msgid "Submit changes" msgid "Submit changes"
msgstr "" msgstr ""
......
...@@ -8,7 +8,6 @@ RSpec.describe 'Thread Comments Snippet', :js do ...@@ -8,7 +8,6 @@ RSpec.describe 'Thread Comments Snippet', :js do
let_it_be(:snippet) { create(:project_snippet, :private, :repository, project: project, author: user) } let_it_be(:snippet) { create(:project_snippet, :private, :repository, project: project, author: user) }
before do before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
......
...@@ -13,8 +13,6 @@ RSpec.describe 'Projects > Snippets > Project snippet', :js do ...@@ -13,8 +13,6 @@ RSpec.describe 'Projects > Snippets > Project snippet', :js do
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) } let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
before do before do
stub_feature_flags(snippets_vue: false)
sign_in(user) sign_in(user)
end end
...@@ -28,12 +26,8 @@ RSpec.describe 'Projects > Snippets > Project snippet', :js do ...@@ -28,12 +26,8 @@ RSpec.describe 'Projects > Snippets > Project snippet', :js do
end end
end end
it_behaves_like 'showing user status' do # it_behaves_like 'showing user status' do
let(:file_path) { 'files/ruby/popen.rb' } # This will be handled in https://gitlab.com/gitlab-org/gitlab/-/issues/262394
let(:user_with_status) { snippet.author }
subject { visit project_snippet_path(project, snippet) }
end
it_behaves_like 'does not show New Snippet button' do it_behaves_like 'does not show New Snippet button' do
let(:file_path) { 'files/ruby/popen.rb' } let(:file_path) { 'files/ruby/popen.rb' }
......
...@@ -8,7 +8,6 @@ RSpec.describe 'Projects > Snippets > User comments on a snippet', :js do ...@@ -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) } let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
before do before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
......
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
require 'spec_helper' 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(: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) } let(:user) { create(:user) }
before do before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
...@@ -16,7 +15,11 @@ RSpec.describe 'Projects > Snippets > User deletes a snippet' do ...@@ -16,7 +15,11 @@ RSpec.describe 'Projects > Snippets > User deletes a snippet' do
end end
it 'deletes a snippet' do 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) expect(page).not_to have_content(snippet.title)
end end
......
...@@ -7,7 +7,6 @@ RSpec.describe 'Reportable note on snippets', :js do ...@@ -7,7 +7,6 @@ RSpec.describe 'Reportable note on snippets', :js do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
before do before do
stub_feature_flags(snippets_vue: false)
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
end end
......
...@@ -3,11 +3,8 @@ ...@@ -3,11 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Internal Snippets', :js do RSpec.describe 'Internal Snippets', :js do
let(:internal_snippet) { create(:personal_snippet, :internal) } let(:internal_snippet) { create(:personal_snippet, :internal, :repository) }
let(:content) { internal_snippet.blobs.first.data.strip! }
before do
stub_feature_flags(snippets_vue: false)
end
describe 'normal user' do describe 'normal user' do
before do before do
...@@ -17,13 +14,13 @@ RSpec.describe 'Internal Snippets', :js do ...@@ -17,13 +14,13 @@ RSpec.describe 'Internal Snippets', :js do
it 'sees internal snippets' do it 'sees internal snippets' do
visit snippet_path(internal_snippet) visit snippet_path(internal_snippet)
expect(page).to have_content(internal_snippet.content) expect(page).to have_content(content)
end end
it 'sees raw internal snippets' do it 'sees raw internal snippets' do
visit raw_snippet_path(internal_snippet) visit raw_snippet_path(internal_snippet)
expect(page).to have_content(internal_snippet.content) expect(page).to have_content(content)
end end
end end
end end
...@@ -18,7 +18,6 @@ RSpec.describe 'Comments on personal snippets', :js do ...@@ -18,7 +18,6 @@ RSpec.describe 'Comments on personal snippets', :js do
end end
before do before do
stub_feature_flags(snippets_vue: false)
sign_in user sign_in user
visit snippet_path(snippet) visit snippet_path(snippet)
......
...@@ -4,19 +4,18 @@ require 'spec_helper' ...@@ -4,19 +4,18 @@ require 'spec_helper'
RSpec.describe 'Private Snippets', :js do RSpec.describe 'Private Snippets', :js do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:private_snippet) { create(:personal_snippet, :repository, :private, author: user) }
let(:content) { private_snippet.blobs.first.data.strip! }
before do before do
stub_feature_flags(snippets_vue: false)
sign_in(user) sign_in(user)
end end
it 'Private Snippet renders for creator' do it 'Private Snippet renders for creator' do
private_snippet = create(:personal_snippet, :private, author: user)
visit snippet_path(private_snippet) visit snippet_path(private_snippet)
wait_for_requests 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-embed-btn')
expect(page).not_to have_css('.js-share-btn') expect(page).not_to have_css('.js-share-btn')
end end
......
...@@ -3,27 +3,24 @@ ...@@ -3,27 +3,24 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Public Snippets', :js do RSpec.describe 'Public Snippets', :js do
before do let(:public_snippet) { create(:personal_snippet, :public, :repository) }
stub_feature_flags(snippets_vue: false) let(:content) { public_snippet.blobs.first.data.strip! }
end
it 'Unauthenticated user should see public snippets' do 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) visit snippet_path(public_snippet)
wait_for_requests wait_for_requests
expect(page).to have_content(public_snippet.content) expect(page).to have_content(content)
expect(page).to have_css('.js-embed-btn', visible: false) click_button('Embed')
expect(page).to have_css('.js-share-btn', visible: false) expect(page).to have_field('Embed', readonly: true, with: "<script src=\"#{url}.js\"></script>")
expect(page.find('.js-snippet-url-area')).to be_readonly expect(page).to have_field('Share', readonly: true, with: url)
end end
it 'Unauthenticated user should see raw public snippets' do it 'Unauthenticated user should see raw public snippets' do
public_snippet = create(:personal_snippet, :public)
visit raw_snippet_path(public_snippet) visit raw_snippet_path(public_snippet)
expect(page).to have_content(public_snippet.content) expect(page).to have_content(content)
end end
end end
...@@ -6,10 +6,6 @@ RSpec.describe 'Snippet', :js do ...@@ -6,10 +6,6 @@ RSpec.describe 'Snippet', :js do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:snippet) { create(:personal_snippet, :public, :repository, author: 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 it_behaves_like 'show and render proper snippet blob' do
let(:anchor) { nil } let(:anchor) { nil }
...@@ -20,12 +16,8 @@ RSpec.describe 'Snippet', :js do ...@@ -20,12 +16,8 @@ RSpec.describe 'Snippet', :js do
end end
end end
it_behaves_like 'showing user status' do # it_behaves_like 'showing user status' do
let(:file_path) { 'files/ruby/popen.rb' } # This will be handled in https://gitlab.com/gitlab-org/gitlab/-/issues/262394
let(:user_with_status) { snippet.author }
subject { visit snippet_path(snippet) }
end
it_behaves_like 'does not show New Snippet button' do it_behaves_like 'does not show New Snippet button' do
let(:file_path) { 'files/ruby/popen.rb' } let(:file_path) { 'files/ruby/popen.rb' }
......
...@@ -2,21 +2,23 @@ ...@@ -2,21 +2,23 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'User deletes snippet' do RSpec.describe 'User deletes snippet', :js do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:content) { 'puts "test"' } 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 before do
sign_in(user) sign_in(user)
stub_feature_flags(snippets_vue: false)
visit snippet_path(snippet) visit snippet_path(snippet)
end end
it 'deletes the snippet' do 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) expect(page).not_to have_content(snippet.title)
end end
......
...@@ -18,11 +18,8 @@ RSpec.describe 'Snippets' do ...@@ -18,11 +18,8 @@ RSpec.describe 'Snippets' do
describe 'rendering engine' do describe 'rendering engine' do
let_it_be(:snippet) { create(:personal_snippet, :public) } let_it_be(:snippet) { create(:personal_snippet, :public) }
let(:snippets_vue_feature_flag_enabled) { true }
before do before do
stub_feature_flags(snippets_vue: snippets_vue_feature_flag_enabled)
visit snippet_path(snippet) visit snippet_path(snippet)
end end
...@@ -30,14 +27,5 @@ RSpec.describe 'Snippets' do ...@@ -30,14 +27,5 @@ RSpec.describe 'Snippets' do
expect(page).to have_selector('#js-snippet-view') expect(page).to have_selector('#js-snippet-view')
expect(page).not_to have_selector('.personal-snippets') expect(page).not_to have_selector('.personal-snippets')
end 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
end end
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import $ from 'jquery'; import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import { setTestTimeout } from 'helpers/timeout';
import BlobViewer from '~/blob/viewer/index'; import BlobViewer from '~/blob/viewer/index';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
...@@ -13,26 +14,22 @@ describe('Blob viewer', () => { ...@@ -13,26 +14,22 @@ describe('Blob viewer', () => {
tooltip: jest.fn(), tooltip: jest.fn(),
}; };
preloadFixtures('snippets/show.html'); setTestTimeout(2000);
preloadFixtures('blob/show_readme.html');
beforeEach(() => { beforeEach(() => {
$.fn.extend(jQueryMock); $.fn.extend(jQueryMock);
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
loadFixtures('snippets/show.html'); loadFixtures('blob/show_readme.html');
$('#modal-upload-blob').remove(); $('#modal-upload-blob').remove();
blob = new BlobViewer(); mock.onGet(/blob\/master\/README\.md/).reply(200, {
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, {
html: '<div>testing</div>', html: '<div>testing</div>',
}); });
jest.spyOn(axios, 'get'); blob = new BlobViewer();
}); });
afterEach(() => { afterEach(() => {
...@@ -71,12 +68,11 @@ describe('Blob viewer', () => { ...@@ -71,12 +68,11 @@ describe('Blob viewer', () => {
}); });
it('doesnt reload file if already loaded', () => { it('doesnt reload file if already loaded', () => {
const asyncClick = () => const asyncClick = async () => {
new Promise(resolve => { document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setImmediate(resolve); await axios.waitForAll();
}); };
return asyncClick() return asyncClick()
.then(() => asyncClick()) .then(() => asyncClick())
...@@ -163,17 +159,30 @@ describe('Blob viewer', () => { ...@@ -163,17 +159,30 @@ describe('Blob viewer', () => {
expect(simpleBtn.blur).toHaveBeenCalled(); expect(simpleBtn.blur).toHaveBeenCalled();
}); });
it('sends AJAX request when switching to simple view', () => { it('makes request for initial view', () => {
blob.switchToViewer('simple'); expect(mock.history).toMatchObject({
get: [{ url: expect.stringMatching(/README\.md\?.*viewer=rich/) }],
expect(axios.get).toHaveBeenCalled(); });
}); });
it('does not send AJAX request when switching to rich view', () => { describe.each`
blob.switchToViewer('simple'); views
blob.switchToViewer('rich'); ${['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 ...@@ -33,4 +33,14 @@ RSpec.describe Projects::BlobController, '(JavaScript fixtures)', type: :control
expect(response).to be_successful expect(response).to be_successful
end 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 end
...@@ -17,7 +17,6 @@ RSpec.describe SnippetsController, '(JavaScript fixtures)', type: :controller do ...@@ -17,7 +17,6 @@ RSpec.describe SnippetsController, '(JavaScript fixtures)', type: :controller do
end end
before do before do
stub_feature_flags(snippets_vue: false)
sign_in(admin) sign_in(admin)
allow(Discussion).to receive(:build_discussion_id).and_return(['discussionid:ceterumcenseo']) allow(Discussion).to receive(:build_discussion_id).and_return(['discussionid:ceterumcenseo'])
end 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 ...@@ -63,32 +63,6 @@ RSpec.describe SnippetsHelper do
end end
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 describe '#download_raw_snippet_button' do
subject { download_raw_snippet_button(snippet) } subject { download_raw_snippet_button(snippet) }
...@@ -142,28 +116,4 @@ RSpec.describe SnippetsHelper do ...@@ -142,28 +116,4 @@ RSpec.describe SnippetsHelper do
end end
end 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 end
...@@ -47,13 +47,6 @@ RSpec.describe VisibilityLevelHelper do ...@@ -47,13 +47,6 @@ RSpec.describe VisibilityLevelHelper do
.to match /group/i .to match /group/i
end end
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 end
describe "#project_visibility_level_description" do describe "#project_visibility_level_description" do
...@@ -68,23 +61,6 @@ RSpec.describe VisibilityLevelHelper do ...@@ -68,23 +61,6 @@ RSpec.describe VisibilityLevelHelper do
end end
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 "disallowed_visibility_level?" do
describe "forks" do describe "forks" do
let(:project) { create(:project, :internal) } let(:project) { create(:project, :internal) }
......
...@@ -84,7 +84,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -84,7 +84,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do
expect(page).not_to have_selector('.js-blob-viewer-switcher') expect(page).not_to have_selector('.js-blob-viewer-switcher')
# shows an enabled copy button # 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 # shows a raw button
expect(page).to have_link('Open raw') expect(page).to have_link('Open raw')
...@@ -106,7 +106,6 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -106,7 +106,6 @@ RSpec.shared_examples 'show and render proper snippet blob' do
it 'displays the blob using the rich viewer' do it 'displays the blob using the rich viewer' do
aggregate_failures do aggregate_failures do
# hides the simple viewer # 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).to have_selector('.blob-viewer[data-type="rich"]')
# shows rendered Markdown # shows rendered Markdown
...@@ -116,7 +115,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -116,7 +115,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do
expect(page).to have_selector('.js-blob-viewer-switcher') expect(page).to have_selector('.js-blob-viewer-switcher')
# shows a disabled copy button # 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 # shows a raw button
expect(page).to have_link('Open raw') expect(page).to have_link('Open raw')
...@@ -128,7 +127,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -128,7 +127,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do
context 'switching to the simple viewer' do context 'switching to the simple viewer' do
before do before do
find('.js-blob-viewer-switch-btn[data-viewer=simple]').click find_button('Display source').click
wait_for_requests wait_for_requests
end end
...@@ -137,19 +136,18 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -137,19 +136,18 @@ RSpec.shared_examples 'show and render proper snippet blob' do
aggregate_failures do aggregate_failures do
# hides the rich viewer # hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]') 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 # shows highlighted Markdown code
expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
# shows an enabled copy button # 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 end
context 'switching to the rich viewer again' do context 'switching to the rich viewer again' do
before do before do
find('.js-blob-viewer-switch-btn[data-viewer=rich]').click find_button('Display rendered file').click
wait_for_requests wait_for_requests
end end
...@@ -157,11 +155,11 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -157,11 +155,11 @@ RSpec.shared_examples 'show and render proper snippet blob' do
it 'displays the blob using the rich viewer' do it 'displays the blob using the rich viewer' do
aggregate_failures do aggregate_failures do
# hides the simple viewer # 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).to have_selector('.blob-viewer[data-type="rich"]')
# shows an enabled copy button # Used to show an enabled copy button since the code has already been fetched
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') # 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 end
end end
...@@ -169,7 +167,8 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -169,7 +167,8 @@ RSpec.shared_examples 'show and render proper snippet blob' do
end end
context 'visiting with a line number anchor' do 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 it 'displays the blob using the simple viewer' do
subject subject
...@@ -177,7 +176,6 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -177,7 +176,6 @@ RSpec.shared_examples 'show and render proper snippet blob' do
aggregate_failures do aggregate_failures do
# hides the rich viewer # hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]') 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 # highlights the line in question
expect(page).to have_selector('#LC1.hll') expect(page).to have_selector('#LC1.hll')
...@@ -186,7 +184,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do ...@@ -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/)") expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
# shows an enabled copy button # 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 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