Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a807e50ade
commit
53a3791717
|
@ -5,26 +5,6 @@ Layout/FirstArrayElementIndentation:
|
|||
Exclude:
|
||||
- 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/search/found_blob_spec.rb'
|
||||
- 'spec/lib/gitlab/serializer/ci/variables_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_config_spec.rb'
|
||||
- 'spec/lib/gitlab/ssh_public_key_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data/topology_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_spec.rb'
|
||||
- 'spec/lib/gitlab/utils_spec.rb'
|
||||
- 'spec/lib/gitlab/webpack/manifest_spec.rb'
|
||||
- 'spec/lib/google_api/cloud_platform/client_spec.rb'
|
||||
- 'spec/lib/peek/views/bullet_detailed_spec.rb'
|
||||
- 'spec/lib/system_check/incoming_email_check_spec.rb'
|
||||
- 'spec/lib/unnested_in_filters/rewriter_spec.rb'
|
||||
- 'spec/migrations/add_premium_and_ultimate_plan_limits_spec.rb'
|
||||
- 'spec/migrations/backfill_escalation_policies_for_oncall_schedules_spec.rb'
|
||||
- 'spec/migrations/slice_merge_request_diff_commit_migrations_spec.rb'
|
||||
- 'spec/models/analytics/cycle_analytics/project_stage_spec.rb'
|
||||
- 'spec/models/application_setting_spec.rb'
|
||||
- 'spec/models/ci/build_spec.rb'
|
||||
- 'spec/models/ci/build_trace_spec.rb'
|
||||
- 'spec/models/ci/daily_build_group_report_result_spec.rb'
|
||||
- 'spec/models/ci/pipeline_spec.rb'
|
||||
- 'spec/models/ci/runner_version_spec.rb'
|
||||
- 'spec/models/repository_spec.rb'
|
||||
- 'spec/models/user_preference_spec.rb'
|
||||
|
|
|
@ -30,6 +30,9 @@ module Mutations
|
|||
argument :start_and_due_date_widget, ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType,
|
||||
required: false,
|
||||
description: 'Input for start and due date widget.'
|
||||
argument :labels_widget, ::Types::WorkItems::Widgets::LabelsUpdateInputType,
|
||||
required: false,
|
||||
description: 'Input for labels widget.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module WorkItems
|
||||
module Widgets
|
||||
class LabelsUpdateInputType < BaseInputObject
|
||||
graphql_name 'WorkItemWidgetLabelsUpdateInput'
|
||||
|
||||
argument :add_label_ids, [Types::GlobalIDType[::Label]],
|
||||
required: false,
|
||||
description: 'Global IDs of labels to be added to the work item.',
|
||||
prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) }
|
||||
argument :remove_label_ids, [Types::GlobalIDType[::Label]],
|
||||
required: false,
|
||||
description: 'Global IDs of labels to be removed from the work item.',
|
||||
prepare: ->(label_ids, _ctx) { label_ids.map(&:model_id) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,7 +14,13 @@ module AppearancesHelper
|
|||
end
|
||||
|
||||
def brand_image
|
||||
image_tag(current_appearance.logo_path) if current_appearance&.logo?
|
||||
image_tag(brand_image_path, alt: brand_title, class: 'gl-w-10')
|
||||
end
|
||||
|
||||
def brand_image_path
|
||||
return current_appearance.logo_path if current_appearance&.logo?
|
||||
|
||||
image_path('logo.svg')
|
||||
end
|
||||
|
||||
def brand_text
|
||||
|
|
|
@ -65,7 +65,10 @@ module WikiHelper
|
|||
reversed_direction = direction == 'desc' ? 'asc' : 'desc'
|
||||
icon_class = direction == 'desc' ? 'highest' : 'lowest'
|
||||
|
||||
link_to(wiki_path(wiki, action: :pages, sort: sort, direction: reversed_direction),
|
||||
link_options = { action: :pages, direction: reversed_direction }
|
||||
link_options[:sort] = sort unless wiki.disable_sorting?
|
||||
|
||||
link_to(wiki_path(wiki, **link_options),
|
||||
type: 'button', class: link_class, title: _('Sort direction')) do
|
||||
sprite_icon("sort-#{icon_class}")
|
||||
end
|
||||
|
|
|
@ -173,7 +173,7 @@ class Wiki
|
|||
end
|
||||
|
||||
def empty?
|
||||
!repository_exists? || list_pages(limit: 1).empty?
|
||||
!repository_exists? || list_page_paths.empty?
|
||||
end
|
||||
|
||||
def exists?
|
||||
|
@ -191,13 +191,11 @@ class Wiki
|
|||
# Returns an Array of GitLab WikiPage instances or an
|
||||
# empty Array if this Wiki has no pages.
|
||||
def list_pages(limit: 0, sort: nil, direction: DIRECTION_ASC, load_content: false)
|
||||
wiki.list_pages(
|
||||
limit: limit,
|
||||
sort: sort,
|
||||
direction_desc: direction == DIRECTION_DESC,
|
||||
load_content: load_content
|
||||
).map do |page|
|
||||
WikiPage.new(self, page)
|
||||
if list_pages_with_repository_rpcs?
|
||||
create_wiki_repository unless repository_exists?
|
||||
list_pages_with_repository_rpcs(limit: limit, sort: sort, direction: direction, load_content: load_content)
|
||||
else
|
||||
list_pages_with_legacy_wiki_service(limit: limit, sort: sort, direction: direction, load_content: load_content)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -383,6 +381,10 @@ class Wiki
|
|||
false
|
||||
end
|
||||
|
||||
def disable_sorting?
|
||||
list_pages_with_repository_rpcs?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def multi_commit_options(action, message = nil, title = nil)
|
||||
|
@ -452,14 +454,7 @@ class Wiki
|
|||
|
||||
def find_matched_file(title, version)
|
||||
escaped_path = RE2::Regexp.escape(sluggified_title(title))
|
||||
# We could not use ALLOWED_EXTENSIONS_REGEX constant or similar regexp with
|
||||
# Regexp.union. The result combination complicated modifiers:
|
||||
# /(?i-mx:md|mkdn?|mdown|markdown)|(?i-mx:rdoc).../
|
||||
# Regexp used by Gitaly is Go's Regexp package. It does not support those
|
||||
# features. So, we have to compose another more-friendly regexp to pass to
|
||||
# Gitaly side.
|
||||
extension_regexp = Wiki::MARKUPS.map { |_, format| format[:extension_regex].source }.join("|")
|
||||
path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)^#{escaped_path}\\.(#{extension_regexp})$")
|
||||
path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)^#{escaped_path}\\.(#{file_extension_regexp})$")
|
||||
|
||||
matched_files = repository.search_files_by_regexp(path_regexp, version)
|
||||
return if matched_files.blank?
|
||||
|
@ -487,7 +482,7 @@ class Wiki
|
|||
format = find_page_format(path)
|
||||
|
||||
page = Gitlab::Git::WikiPage.new(
|
||||
url_path: sluggified_title(path.sub(/\.[^.]+\z/, "")),
|
||||
url_path: sluggified_title(strip_extension(path)),
|
||||
title: canonicalize_filename(path),
|
||||
format: format,
|
||||
path: sluggified_title(path),
|
||||
|
@ -509,6 +504,93 @@ class Wiki
|
|||
|
||||
Feature.enabled?(:wiki_find_page_with_normal_repository_rpcs, group, type: :development)
|
||||
end
|
||||
|
||||
def file_extension_regexp
|
||||
# We could not use ALLOWED_EXTENSIONS_REGEX constant or similar regexp with
|
||||
# Regexp.union. The result combination complicated modifiers:
|
||||
# /(?i-mx:md|mkdn?|mdown|markdown)|(?i-mx:rdoc).../
|
||||
# Regexp used by Gitaly is Go's Regexp package. It does not support those
|
||||
# features. So, we have to compose another more-friendly regexp to pass to
|
||||
# Gitaly side.
|
||||
Wiki::MARKUPS.map { |_, format| format[:extension_regex].source }.join("|")
|
||||
end
|
||||
|
||||
def strip_extension(path)
|
||||
path.sub(/\.[^.]+\z/, "")
|
||||
end
|
||||
|
||||
def list_pages_with_repository_rpcs?
|
||||
group =
|
||||
if container.is_a?(::Group)
|
||||
container
|
||||
else
|
||||
container.group
|
||||
end
|
||||
|
||||
Feature.enabled?(:wiki_list_pages_with_normal_repository_rpcs, group, type: :development)
|
||||
end
|
||||
|
||||
def list_page_paths
|
||||
return [] if repository.empty?
|
||||
|
||||
path_regexp = Gitlab::EncodingHelper.encode_utf8_no_detect("(?i)\\.(#{file_extension_regexp})$")
|
||||
repository.search_files_by_regexp(path_regexp, default_branch)
|
||||
end
|
||||
|
||||
def list_pages_with_repository_rpcs(limit:, sort:, direction:, load_content:)
|
||||
paths = list_page_paths
|
||||
return [] if paths.empty?
|
||||
|
||||
pages = paths.map do |path|
|
||||
page = Gitlab::Git::WikiPage.new(
|
||||
url_path: sluggified_title(strip_extension(path)),
|
||||
title: canonicalize_filename(path),
|
||||
format: find_page_format(path),
|
||||
path: sluggified_title(path),
|
||||
raw_data: '',
|
||||
name: canonicalize_filename(path),
|
||||
historical: false
|
||||
)
|
||||
WikiPage.new(self, page)
|
||||
end
|
||||
sort_pages!(pages, sort, direction)
|
||||
pages = pages.take(limit) if limit > 0
|
||||
fetch_pages_content!(pages) if load_content
|
||||
|
||||
pages
|
||||
end
|
||||
|
||||
def list_pages_with_legacy_wiki_service(limit:, sort:, direction:, load_content:)
|
||||
wiki.list_pages(
|
||||
limit: limit,
|
||||
sort: sort,
|
||||
direction_desc: direction == DIRECTION_DESC,
|
||||
load_content: load_content
|
||||
).map do |page|
|
||||
WikiPage.new(self, page)
|
||||
end
|
||||
end
|
||||
|
||||
# After migrating to normal repository RPCs, it's very expensive to sort the
|
||||
# pages by created_at. We have to either ListLastCommitsForTree RPC call or
|
||||
# N+1 LastCommitForPath. Either are efficient for a large repository.
|
||||
# Therefore, we decide to sort the title only.
|
||||
def sort_pages!(pages, _sort, direction)
|
||||
# Sort by path to ensure the files inside a sub-folder are grouped and sorted together
|
||||
pages.sort_by!(&:path)
|
||||
pages.reverse! if direction == DIRECTION_DESC
|
||||
end
|
||||
|
||||
def fetch_pages_content!(pages)
|
||||
blobs =
|
||||
repository
|
||||
.blobs_at(pages.map { |page| [default_branch, page.path] } )
|
||||
.to_h { |blob| [blob.path, blob.data] }
|
||||
|
||||
pages.each do |page|
|
||||
page.raw_content = blobs[page.path]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Wiki.prepend_mod_with('Wiki')
|
||||
|
|
|
@ -99,6 +99,13 @@ class WikiPage
|
|||
attributes[:content] ||= page&.text_data
|
||||
end
|
||||
|
||||
def raw_content=(content)
|
||||
return if page.nil?
|
||||
|
||||
page.raw_data = content
|
||||
attributes[:content] = page.text_data
|
||||
end
|
||||
|
||||
# The hierarchy of the directory this page is contained in.
|
||||
def directory
|
||||
wiki.page_title_and_dir(slug)&.last.to_s
|
||||
|
@ -118,7 +125,7 @@ class WikiPage
|
|||
def version
|
||||
return unless persisted?
|
||||
|
||||
@version ||= @page.version
|
||||
@version ||= @page.version || last_version
|
||||
end
|
||||
|
||||
def path
|
||||
|
@ -151,7 +158,7 @@ class WikiPage
|
|||
end
|
||||
|
||||
def last_version
|
||||
@last_version ||= versions(limit: 1).first
|
||||
@last_version ||= wiki.repository.last_commit_for_path(wiki.default_branch, page.path) if page
|
||||
end
|
||||
|
||||
def last_commit_sha
|
||||
|
|
|
@ -2,18 +2,22 @@
|
|||
|
||||
module WorkItems
|
||||
module WidgetableService
|
||||
def execute_widgets(work_item:, callback:, widget_params: {})
|
||||
def execute_widgets(work_item:, callback:, widget_params: {}, service_params: {})
|
||||
work_item.widgets.each do |widget|
|
||||
widget_service(widget).try(callback, params: widget_params[widget.class.api_symbol])
|
||||
widget_service(widget, service_params).try(callback, params: widget_params[widget.class.api_symbol])
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
def widget_service(widget)
|
||||
def widget_service(widget, service_params)
|
||||
@widget_services ||= {}
|
||||
return @widget_services[widget] if @widget_services.has_key?(widget)
|
||||
|
||||
@widget_services[widget] = widget_service_class(widget)&.new(widget: widget, current_user: current_user)
|
||||
@widget_services[widget] = widget_service_class(widget)&.new(
|
||||
widget: widget,
|
||||
current_user: current_user,
|
||||
service_params: service_params
|
||||
)
|
||||
end
|
||||
# rubocop:enable Gitlab/ModuleWithInstanceVariables
|
||||
|
||||
|
|
|
@ -266,6 +266,10 @@ class IssuableBaseService < ::BaseProjectService
|
|||
# To be overridden by subclasses
|
||||
end
|
||||
|
||||
def prepare_update_params(issuable)
|
||||
# To be overridden by subclasses
|
||||
end
|
||||
|
||||
def after_update(issuable)
|
||||
handle_description_updated(issuable)
|
||||
end
|
||||
|
@ -277,6 +281,7 @@ class IssuableBaseService < ::BaseProjectService
|
|||
end
|
||||
|
||||
def update(issuable)
|
||||
prepare_update_params(issuable)
|
||||
handle_quick_actions(issuable)
|
||||
filter_params(issuable)
|
||||
|
||||
|
|
|
@ -26,6 +26,17 @@ module WorkItems
|
|||
|
||||
private
|
||||
|
||||
def prepare_update_params(work_item)
|
||||
execute_widgets(
|
||||
work_item: work_item,
|
||||
callback: :prepare_update_params,
|
||||
widget_params: @widget_params,
|
||||
service_params: params
|
||||
)
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def before_update(work_item, skip_spam_check: false)
|
||||
execute_widgets(work_item: work_item, callback: :before_update_callback, widget_params: @widget_params)
|
||||
|
||||
|
|
|
@ -5,12 +5,13 @@ module WorkItems
|
|||
class BaseService < ::BaseService
|
||||
WidgetError = Class.new(StandardError)
|
||||
|
||||
attr_reader :widget, :work_item, :current_user
|
||||
attr_reader :widget, :work_item, :current_user, :service_params
|
||||
|
||||
def initialize(widget:, current_user:)
|
||||
def initialize(widget:, current_user:, service_params: {})
|
||||
@widget = widget
|
||||
@work_item = widget.work_item
|
||||
@current_user = current_user
|
||||
@service_params = service_params
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module WorkItems
|
||||
module Widgets
|
||||
module LabelsService
|
||||
class UpdateService < WorkItems::Widgets::BaseService
|
||||
def prepare_update_params(params: {})
|
||||
return if params.blank?
|
||||
|
||||
service_params.merge!(params.slice(:add_label_ids, :remove_label_ids))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,9 +13,9 @@
|
|||
= render "layouts/flash"
|
||||
.mt-3
|
||||
.col-sm-12.gl-text-center
|
||||
%img.gl-w-10{ :alt => _("GitLab Logo"), :src => image_path('logo.svg') }
|
||||
= brand_image
|
||||
%h1.mb-3.gl-font-size-h2
|
||||
= current_appearance&.title.presence || _('GitLab')
|
||||
= brand_title
|
||||
- if current_appearance&.description?
|
||||
= brand_text
|
||||
= render_if_exists 'layouts/devise_help_text'
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
.dropdown.inline.wiki-sort-dropdown
|
||||
.btn-group{ role: 'group' }
|
||||
- unless @wiki.disable_sorting?
|
||||
= gl_redirect_listbox_tag wiki_sort_options, params[:sort], data: { right: true }
|
||||
= wiki_sort_controls(@wiki, params[:sort], params[:direction])
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: wiki_list_pages_with_normal_repository_rpcs
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96461
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372259
|
||||
milestone: '15.4'
|
||||
type: development
|
||||
group: group::gitaly
|
||||
default_enabled: false
|
|
@ -5839,6 +5839,7 @@ Input type: `WorkItemUpdateInput`
|
|||
| <a id="mutationworkitemupdatehierarchywidget"></a>`hierarchyWidget` | [`WorkItemWidgetHierarchyUpdateInput`](#workitemwidgethierarchyupdateinput) | Input for hierarchy widget. |
|
||||
| <a id="mutationworkitemupdateid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
|
||||
| <a id="mutationworkitemupdateiterationwidget"></a>`iterationWidget` | [`WorkItemWidgetIterationInput`](#workitemwidgetiterationinput) | Input for iteration widget. |
|
||||
| <a id="mutationworkitemupdatelabelswidget"></a>`labelsWidget` | [`WorkItemWidgetLabelsUpdateInput`](#workitemwidgetlabelsupdateinput) | Input for labels widget. |
|
||||
| <a id="mutationworkitemupdatestartandduedatewidget"></a>`startAndDueDateWidget` | [`WorkItemWidgetStartAndDueDateUpdateInput`](#workitemwidgetstartandduedateupdateinput) | Input for start and due date widget. |
|
||||
| <a id="mutationworkitemupdatestateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
|
||||
| <a id="mutationworkitemupdatetitle"></a>`title` | [`String`](#string) | Title of the work item. |
|
||||
|
@ -23494,6 +23495,7 @@ A time-frame defined as a closed inclusive range of two dates.
|
|||
| <a id="workitemupdatedtaskinputdescriptionwidget"></a>`descriptionWidget` | [`WorkItemWidgetDescriptionInput`](#workitemwidgetdescriptioninput) | Input for description widget. |
|
||||
| <a id="workitemupdatedtaskinputhierarchywidget"></a>`hierarchyWidget` | [`WorkItemWidgetHierarchyUpdateInput`](#workitemwidgethierarchyupdateinput) | Input for hierarchy widget. |
|
||||
| <a id="workitemupdatedtaskinputid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
|
||||
| <a id="workitemupdatedtaskinputlabelswidget"></a>`labelsWidget` | [`WorkItemWidgetLabelsUpdateInput`](#workitemwidgetlabelsupdateinput) | Input for labels widget. |
|
||||
| <a id="workitemupdatedtaskinputstartandduedatewidget"></a>`startAndDueDateWidget` | [`WorkItemWidgetStartAndDueDateUpdateInput`](#workitemwidgetstartandduedateupdateinput) | Input for start and due date widget. |
|
||||
| <a id="workitemupdatedtaskinputstateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
|
||||
| <a id="workitemupdatedtaskinputtitle"></a>`title` | [`String`](#string) | Title of the work item. |
|
||||
|
@ -23539,6 +23541,15 @@ A time-frame defined as a closed inclusive range of two dates.
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="workitemwidgetiterationinputiterationid"></a>`iterationId` | [`IterationID`](#iterationid) | Iteration to assign to the work item. |
|
||||
|
||||
### `WorkItemWidgetLabelsUpdateInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="workitemwidgetlabelsupdateinputaddlabelids"></a>`addLabelIds` | [`[LabelID!]`](#labelid) | Global IDs of labels to be added to the work item. |
|
||||
| <a id="workitemwidgetlabelsupdateinputremovelabelids"></a>`removeLabelIds` | [`[LabelID!]`](#labelid) | Global IDs of labels to be removed from the work item. |
|
||||
|
||||
### `WorkItemWidgetStartAndDueDateUpdateInput`
|
||||
|
||||
#### Arguments
|
||||
|
|
|
@ -41,6 +41,11 @@ module Gitlab
|
|||
|
||||
@text_data = @raw_data && Gitlab::EncodingHelper.encode!(@raw_data.dup)
|
||||
end
|
||||
|
||||
def raw_data=(data)
|
||||
@raw_data = data
|
||||
@text_data = @raw_data && Gitlab::EncodingHelper.encode!(@raw_data.dup)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17964,9 +17964,6 @@ msgstr ""
|
|||
msgid "GitLab KAS"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLab Logo"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLab Pages"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ RSpec.describe 'Project wikis', :js do
|
|||
let(:wiki) { create(:project_wiki, user: user, project: project) }
|
||||
let(:project) { create(:project, namespace: user.namespace, creator: user) }
|
||||
|
||||
context 'with legacy wiki rpcs' do
|
||||
before do
|
||||
stub_feature_flags(wiki_list_pages_with_normal_repository_rpcs: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'User creates wiki page'
|
||||
it_behaves_like 'User deletes wiki page'
|
||||
it_behaves_like 'User previews wiki changes'
|
||||
|
@ -23,3 +28,21 @@ RSpec.describe 'Project wikis', :js do
|
|||
it_behaves_like 'User views wiki sidebar'
|
||||
it_behaves_like 'User views Git access wiki page'
|
||||
end
|
||||
|
||||
context 'with normal repository rpcs' do
|
||||
before do
|
||||
stub_feature_flags(wiki_list_pages_with_normal_repository_rpcs: true)
|
||||
end
|
||||
|
||||
it_behaves_like 'User creates wiki page'
|
||||
it_behaves_like 'User deletes wiki page'
|
||||
it_behaves_like 'User previews wiki changes'
|
||||
it_behaves_like 'User updates wiki page'
|
||||
it_behaves_like 'User uses wiki shortcuts'
|
||||
it_behaves_like 'User views AsciiDoc page with includes'
|
||||
it_behaves_like 'User views a wiki page'
|
||||
it_behaves_like 'User views wiki pages', false
|
||||
it_behaves_like 'User views wiki sidebar'
|
||||
it_behaves_like 'User views Git access wiki page'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ::Types::WorkItems::Widgets::LabelsUpdateInputType do
|
||||
it { expect(described_class.graphql_name).to eq('WorkItemWidgetLabelsUpdateInput') }
|
||||
|
||||
it { expect(described_class.arguments.keys).to contain_exactly('addLabelIds', 'removeLabelIds') }
|
||||
end
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AppearancesHelper do
|
||||
let_it_be(:gitlab_logo) { ActionController::Base.helpers.image_path('logo.svg') }
|
||||
|
||||
before do
|
||||
user = create(:user)
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
|
@ -59,15 +61,14 @@ RSpec.describe AppearancesHelper do
|
|||
end
|
||||
|
||||
describe '#brand_image' do
|
||||
context 'when there is a logo' do
|
||||
let!(:appearance) { create(:appearance, :with_logo) }
|
||||
|
||||
context 'when there is a logo' do
|
||||
it 'returns a path' do
|
||||
expect(helper.brand_image).to match(%r(img data-src="/uploads/-/system/appearance/.*png))
|
||||
end
|
||||
expect(helper.brand_image).to match(%r(img .* data-src="/uploads/-/system/appearance/.*png))
|
||||
end
|
||||
|
||||
context 'when there is a logo but no associated upload' do
|
||||
context 'when there is no associated upload' do
|
||||
before do
|
||||
# Legacy attachments were not tracked in the uploads table
|
||||
appearance.logo.upload.destroy!
|
||||
|
@ -75,7 +76,44 @@ RSpec.describe AppearancesHelper do
|
|||
end
|
||||
|
||||
it 'falls back to using the original path' do
|
||||
expect(helper.brand_image).to match(%r(img data-src="/uploads/-/system/appearance/.*png))
|
||||
expect(helper.brand_image).to match(%r(img .* data-src="/uploads/-/system/appearance/.*png))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is no logo' do
|
||||
it 'returns path of GitLab logo' do
|
||||
expect(helper.brand_image).to match(%r(img .* data-src="#{gitlab_logo}))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is a title' do
|
||||
let!(:appearance) { create(:appearance, title: 'My title') }
|
||||
|
||||
it 'returns the title' do
|
||||
expect(helper.brand_image).to match(%r(img alt="My title"))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is no title' do
|
||||
it 'returns the default title' do
|
||||
expect(helper.brand_image).to match(%r(img alt="GitLab))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#brand_image_path' do
|
||||
context 'with a custom logo' do
|
||||
let!(:appearance) { create(:appearance, :with_logo) }
|
||||
|
||||
it 'returns path of custom logo' do
|
||||
expect(helper.brand_image_path).to match(%r(/uploads/-/system/appearance/.*/dk.png))
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no custom logo' do
|
||||
it 'returns path of GitLab logo' do
|
||||
expect(helper.brand_image_path).to eq(gitlab_logo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -79,13 +79,23 @@ RSpec.describe WikiHelper do
|
|||
let(:classes) { "gl-button btn btn-default btn-icon has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort" }
|
||||
|
||||
def expected_link(sort, direction, icon_class)
|
||||
path = "/#{wiki.project.full_path}/-/wikis/pages?direction=#{direction}&sort=#{sort}"
|
||||
path =
|
||||
if sort
|
||||
"/#{wiki.project.full_path}/-/wikis/pages?direction=#{direction}&sort=#{sort}"
|
||||
else
|
||||
"/#{wiki.project.full_path}/-/wikis/pages?direction=#{direction}"
|
||||
end
|
||||
|
||||
helper.link_to(path, type: 'button', class: classes, title: 'Sort direction') do
|
||||
helper.sprite_icon("sort-#{icon_class}")
|
||||
end
|
||||
end
|
||||
|
||||
context 'wiki sorting enabled' do
|
||||
before do
|
||||
allow(wiki).to receive(:disable_sorting?).and_return(false)
|
||||
end
|
||||
|
||||
context 'initial call' do
|
||||
let(:sort) { nil }
|
||||
let(:direction) { nil }
|
||||
|
@ -114,6 +124,31 @@ RSpec.describe WikiHelper do
|
|||
end
|
||||
end
|
||||
|
||||
context 'wiki sorting disabled' do
|
||||
before do
|
||||
allow(wiki).to receive(:disable_sorting?).and_return(true)
|
||||
end
|
||||
|
||||
context 'sort by created_at' do
|
||||
let(:sort) { 'created_at' }
|
||||
let(:direction) { 'asc' }
|
||||
|
||||
it 'ignores created_at and renders a link with opposite direction' do
|
||||
expect(wiki_link).to eq(expected_link(nil, 'desc', 'lowest'))
|
||||
end
|
||||
end
|
||||
|
||||
context 'initial call' do
|
||||
let(:sort) { nil }
|
||||
let(:direction) { nil }
|
||||
|
||||
it 'renders with default values' do
|
||||
expect(wiki_link).to eq(expected_link(nil, 'desc', 'lowest'))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wiki_sort_title' do
|
||||
it 'returns a title corresponding to a key' do
|
||||
expect(helper.wiki_sort_title('created_at')).to eq('Created date')
|
||||
|
|
|
@ -118,7 +118,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
|
|||
shared_examples 'blob search repository ref' do |entity_type, blob_type|
|
||||
let(:query) { 'files' }
|
||||
let(:file_finder) { double }
|
||||
let(:project_branch) { 'project_branch' }
|
||||
let(:project_branch) { blob_type == 'wiki_blobs' ? entity.default_branch : 'project_branch' }
|
||||
|
||||
subject(:objects) { results.objects(blob_type) }
|
||||
|
||||
|
@ -209,8 +209,11 @@ RSpec.describe Gitlab::ProjectSearchResults do
|
|||
|
||||
describe 'wiki search' do
|
||||
let(:project) { create(:project, :public, :wiki_repo) }
|
||||
let(:project_branch) { 'project_branch' }
|
||||
|
||||
before do
|
||||
allow(project.wiki).to receive(:root_ref).and_return(project_branch)
|
||||
|
||||
project.wiki.create_page('Files/Title', 'Content')
|
||||
project.wiki.create_page('CHANGELOG', 'Files example')
|
||||
end
|
||||
|
|
|
@ -13,7 +13,8 @@ RSpec.describe Gitlab::Serializer::Ci::Variables do
|
|||
end
|
||||
|
||||
it 'converts keys into strings and symbolizes hash' do
|
||||
is_expected.to eq([
|
||||
is_expected.to eq(
|
||||
[
|
||||
{ key: 'key', value: 'value', public: true },
|
||||
{ key: 'wee', value: 1, public: false }
|
||||
])
|
||||
|
|
|
@ -193,9 +193,7 @@ RSpec.describe Gitlab::SidekiqConfig do
|
|||
it 'returns worker queue mappings that have queues in the current Sidekiq options' do
|
||||
queues = described_class.routing_queues
|
||||
|
||||
expect(queues).to match_array(%w[
|
||||
default mailers high_urgency gitaly
|
||||
])
|
||||
expect(queues).to match_array(%w[default mailers high_urgency gitaly])
|
||||
expect(queues).not_to include('not_exist')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1050,11 +1050,12 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
|
|||
|
||||
before do
|
||||
allow(described_class).to receive(:operating_system).and_return('ubuntu-20.04')
|
||||
expect(prometheus_client).to receive(:query).with(/gitlab_usage_ping:gitaly_apdex:ratio_avg_over_time_5m/).and_return([
|
||||
{
|
||||
'metric' => {},
|
||||
'value' => [1616016381.473, '0.95']
|
||||
}
|
||||
expect(prometheus_client).to receive(:query)
|
||||
.with(/gitlab_usage_ping:gitaly_apdex:ratio_avg_over_time_5m/)
|
||||
.and_return(
|
||||
[
|
||||
{ 'metric' => {},
|
||||
'value' => [1616016381.473, '0.95'] }
|
||||
])
|
||||
expect(described_class).to receive(:with_prometheus_client).and_yield(prometheus_client)
|
||||
end
|
||||
|
|
|
@ -582,7 +582,8 @@ RSpec.describe Gitlab::Utils do
|
|||
end
|
||||
|
||||
it 'sorts items like the regular sort_by' do
|
||||
expect(sorted_list).to eq([
|
||||
expect(sorted_list).to eq(
|
||||
[
|
||||
{ name: 'obj 2', priority: 1 },
|
||||
{ name: 'obj 1', priority: 2 },
|
||||
{ name: 'obj 3', priority: 3 }
|
||||
|
|
|
@ -66,7 +66,8 @@ RSpec.describe Gitlab::Webpack::Manifest do
|
|||
describe "webpack errors" do
|
||||
context "when webpack has 'Module build failed' errors in its manifest" do
|
||||
it "errors" do
|
||||
error_manifest = Gitlab::Json.parse(manifest).merge("errors" => [
|
||||
error_manifest = Gitlab::Json.parse(manifest).merge("errors" =>
|
||||
[
|
||||
"somethingModule build failed something",
|
||||
"I am an error"
|
||||
]).to_json
|
||||
|
|
|
@ -17,14 +17,16 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
|
|||
let(:tier) { 'mock-tier' }
|
||||
|
||||
let(:database_list) do
|
||||
Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(items: [
|
||||
Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(
|
||||
items: [
|
||||
Google::Apis::SqladminV1beta4::Database.new(name: 'db_01', instance: database_instance),
|
||||
Google::Apis::SqladminV1beta4::Database.new(name: 'db_02', instance: database_instance)
|
||||
])
|
||||
end
|
||||
|
||||
let(:user_list) do
|
||||
Google::Apis::SqladminV1beta4::ListUsersResponse.new(items: [
|
||||
Google::Apis::SqladminV1beta4::ListUsersResponse.new(
|
||||
items: [
|
||||
Google::Apis::SqladminV1beta4::User.new(name: 'user_01', instance: database_instance),
|
||||
Google::Apis::SqladminV1beta4::User.new(name: 'user_02', instance: database_instance)
|
||||
])
|
||||
|
|
|
@ -44,7 +44,8 @@ RSpec.describe Peek::Views::BulletDetailed do
|
|||
expect(subject.key).to eq('bullet')
|
||||
expect(subject.results[:calls]).to eq(2)
|
||||
expect(subject.results[:warnings]).to eq([Peek::Views::BulletDetailed::WARNING_MESSAGE])
|
||||
expect(subject.results[:details]).to eq([
|
||||
expect(subject.results[:details]).to eq(
|
||||
[
|
||||
{ notification: 'Title 1: Body 1', backtrace: "first\nsecond\n" },
|
||||
{ notification: 'Title 2: Body 2', backtrace: "first\nsecond\n" }
|
||||
])
|
||||
|
|
|
@ -26,7 +26,8 @@ RSpec.describe SystemCheck::IncomingEmailCheck do
|
|||
end
|
||||
|
||||
it 'runs IMAP and mailroom checks' do
|
||||
expect(SystemCheck).to receive(:run).with('Reply by email', [
|
||||
expect(SystemCheck).to receive(:run).with('Reply by email',
|
||||
[
|
||||
SystemCheck::IncomingEmail::ImapAuthenticationCheck,
|
||||
SystemCheck::IncomingEmail::MailRoomEnabledCheck,
|
||||
SystemCheck::IncomingEmail::MailRoomRunningCheck
|
||||
|
@ -42,7 +43,8 @@ RSpec.describe SystemCheck::IncomingEmailCheck do
|
|||
end
|
||||
|
||||
it 'runs mailroom checks' do
|
||||
expect(SystemCheck).to receive(:run).with('Reply by email', [
|
||||
expect(SystemCheck).to receive(:run).with('Reply by email',
|
||||
[
|
||||
SystemCheck::IncomingEmail::MailRoomEnabledCheck,
|
||||
SystemCheck::IncomingEmail::MailRoomRunningCheck
|
||||
])
|
||||
|
|
|
@ -41,7 +41,8 @@ RSpec.describe UnnestedInFilters::Rewriter do
|
|||
|
||||
context 'when the order is a Keyset order' do
|
||||
let(:order) do
|
||||
Gitlab::Pagination::Keyset::Order.build([
|
||||
Gitlab::Pagination::Keyset::Order.build(
|
||||
[
|
||||
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
|
||||
attribute_name: 'user_type',
|
||||
order_expression: User.arel_table['user_type'].desc,
|
||||
|
@ -152,7 +153,8 @@ RSpec.describe UnnestedInFilters::Rewriter do
|
|||
|
||||
context 'when the order is a Keyset order' do
|
||||
let(:order) do
|
||||
Gitlab::Pagination::Keyset::Order.build([
|
||||
Gitlab::Pagination::Keyset::Order.build(
|
||||
[
|
||||
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
|
||||
attribute_name: 'user_type',
|
||||
order_expression: User.arel_table['user_type'].desc,
|
||||
|
|
|
@ -72,7 +72,9 @@ RSpec.describe AddPremiumAndUltimatePlanLimits, :migration do
|
|||
it 'creates plan limits from the source plan' do
|
||||
migrate!
|
||||
|
||||
expect(AddPremiumAndUltimatePlanLimits::PlanLimits.pluck(:plan_id, :storage_size_limit)).to match_array([
|
||||
expect(AddPremiumAndUltimatePlanLimits::PlanLimits.pluck(:plan_id, :storage_size_limit))
|
||||
.to match_array(
|
||||
[
|
||||
[silver.id, silver_limits.storage_size_limit],
|
||||
[gold.id, gold_limits.storage_size_limit],
|
||||
[premium.id, silver_limits.storage_size_limit],
|
||||
|
|
|
@ -57,7 +57,8 @@ RSpec.describe BackfillEscalationPoliciesForOncallSchedules do
|
|||
expect(new_polices).to all have_attributes(name: 'On-call Escalation Policy')
|
||||
expect(new_policy_b1.description).to eq('Immediately notify Schedule B1')
|
||||
expect(new_policy_c1.description).to eq('Immediately notify Schedule C1')
|
||||
expect(policies.pluck(:project_id)).to eq([
|
||||
expect(policies.pluck(:project_id)).to eq(
|
||||
[
|
||||
project_d.id,
|
||||
project_e.id,
|
||||
project_f.id,
|
||||
|
@ -67,7 +68,8 @@ RSpec.describe BackfillEscalationPoliciesForOncallSchedules do
|
|||
])
|
||||
|
||||
expect(new_rules).to all have_attributes(status: 1, elapsed_time_seconds: 0)
|
||||
expect(rules.pluck(:policy_id)).to eq([
|
||||
expect(rules.pluck(:policy_id)).to eq(
|
||||
[
|
||||
rule_d1.policy_id,
|
||||
rule_e1.policy_id,
|
||||
rule_f1.policy_id,
|
||||
|
@ -77,7 +79,8 @@ RSpec.describe BackfillEscalationPoliciesForOncallSchedules do
|
|||
new_policy_c1.id,
|
||||
new_policy_c1.id
|
||||
])
|
||||
expect(rules.pluck(:oncall_schedule_id)).to eq([
|
||||
expect(rules.pluck(:oncall_schedule_id)).to eq(
|
||||
[
|
||||
rule_d1.oncall_schedule_id,
|
||||
rule_e1.oncall_schedule_id,
|
||||
rule_f1.oncall_schedule_id,
|
||||
|
|
|
@ -49,7 +49,8 @@ RSpec.describe SliceMergeRequestDiffCommitMigrations, :migration do
|
|||
.pending
|
||||
.to_a
|
||||
|
||||
expect(new_jobs.map(&:arguments)).to eq([
|
||||
expect(new_jobs.map(&:arguments)).to eq(
|
||||
[
|
||||
[1, 5_001],
|
||||
[5_001, 10_001],
|
||||
[10_001, 15_001],
|
||||
|
|
|
@ -48,7 +48,8 @@ RSpec.describe Analytics::CycleAnalytics::ProjectStage do
|
|||
subject(:distinct_start_and_end_event_identifiers) { described_class.distinct_stages_within_hierarchy(top_level_group).to_a.pluck(:start_event_identifier, :end_event_identifier) }
|
||||
|
||||
it 'returns distinct stages by start and end events (using stage_event_hash_id)' do
|
||||
expect(distinct_start_and_end_event_identifiers).to match_array([
|
||||
expect(distinct_start_and_end_event_identifiers).to match_array(
|
||||
[
|
||||
%w[issue_created issue_deployed_to_production],
|
||||
%w[merge_request_created merge_request_merged]
|
||||
])
|
||||
|
|
|
@ -257,7 +257,8 @@ RSpec.describe ApplicationSetting do
|
|||
subject.grafana_url = ' ' + http
|
||||
expect(subject.save).to be false
|
||||
|
||||
expect(subject.errors[:grafana_url]).to eq([
|
||||
expect(subject.errors[:grafana_url]).to eq(
|
||||
[
|
||||
'must be a valid relative or absolute URL. ' \
|
||||
'Please check your Grafana URL setting in ' \
|
||||
'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
|
||||
|
@ -270,7 +271,8 @@ RSpec.describe ApplicationSetting do
|
|||
subject.grafana_url = javascript
|
||||
expect(subject.save).to be false
|
||||
|
||||
expect(subject.errors[:grafana_url]).to eq([
|
||||
expect(subject.errors[:grafana_url]).to eq(
|
||||
[
|
||||
'is blocked: Only allowed schemes are http, https. Please check your ' \
|
||||
'Grafana URL setting in ' \
|
||||
'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
|
||||
|
|
|
@ -5275,7 +5275,8 @@ RSpec.describe Ci::Build do
|
|||
it { expect(matchers.size).to eq(2) }
|
||||
|
||||
it 'groups build ids' do
|
||||
expect(matchers.map(&:build_ids)).to match_array([
|
||||
expect(matchers.map(&:build_ids)).to match_array(
|
||||
[
|
||||
[build_without_tags.id],
|
||||
match_array([build_with_tags.id, other_build_with_tags.id])
|
||||
])
|
||||
|
@ -5475,7 +5476,8 @@ RSpec.describe Ci::Build do
|
|||
create(:ci_job_variable, job: build, key: 'TEST_KEY', value: 'old value')
|
||||
create(:ci_job_variable, job: build, key: 'OLD_KEY', value: 'i will not live for long')
|
||||
|
||||
new_build = build.clone(current_user: user, new_job_variables_attributes: [
|
||||
new_build = build.clone(current_user: user, new_job_variables_attributes:
|
||||
[
|
||||
{ key: 'TEST_KEY', value: 'new value' },
|
||||
{ key: 'NEW_KEY', value: 'exciting new value' }
|
||||
])
|
||||
|
@ -5492,9 +5494,10 @@ RSpec.describe Ci::Build do
|
|||
build = create(:ci_build)
|
||||
create(:ci_job_variable, job: build, key: 'TEST_KEY', value: 'old value')
|
||||
|
||||
new_build = build.clone(current_user: user, new_job_variables_attributes: [
|
||||
{ key: 'TEST_KEY', value: 'new value' }
|
||||
])
|
||||
new_build = build.clone(
|
||||
current_user: user,
|
||||
new_job_variables_attributes: [{ key: 'TEST_KEY', value: 'new value' }]
|
||||
)
|
||||
new_build.save!
|
||||
|
||||
expect(new_build.job_variables.count).to be(1)
|
||||
|
|
|
@ -28,7 +28,8 @@ RSpec.describe Ci::BuildTrace do
|
|||
it_behaves_like 'delegates methods'
|
||||
|
||||
it 'returns formatted trace' do
|
||||
expect(subject.lines).to eq([
|
||||
expect(subject.lines).to eq(
|
||||
[
|
||||
{ offset: 0, content: [{ text: 'the-stream' }] }
|
||||
])
|
||||
end
|
||||
|
|
|
@ -41,7 +41,8 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
|
|||
let!(:new_pipeline) { create(:ci_pipeline) }
|
||||
|
||||
it 'creates or updates matching report results' do
|
||||
described_class.upsert_reports([
|
||||
described_class.upsert_reports(
|
||||
[
|
||||
{
|
||||
project_id: rspec_coverage.project_id,
|
||||
ref_path: rspec_coverage.ref_path,
|
||||
|
|
|
@ -4531,7 +4531,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
|||
end
|
||||
|
||||
it 'returns accessibility report with collected data' do
|
||||
expect(subject.urls.keys).to match_array([
|
||||
expect(subject.urls.keys).to match_array(
|
||||
[
|
||||
"https://pa11y.org/",
|
||||
"https://about.gitlab.com/"
|
||||
])
|
||||
|
|
|
@ -144,6 +144,78 @@ RSpec.describe 'Update a work item' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with labels widget input' do
|
||||
shared_examples 'mutation updating work item labels' do
|
||||
it 'updates labels' do
|
||||
expect do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
work_item.reload
|
||||
end.to change { work_item.labels.count }.to(expected_labels.count)
|
||||
|
||||
expect(work_item.labels).to match_array(expected_labels)
|
||||
expect(mutation_response['workItem']['widgets']).to include(
|
||||
'labels' => {
|
||||
'nodes' => match_array(expected_labels.map { |l| { 'id' => l.to_gid.to_s } })
|
||||
},
|
||||
'type' => 'LABELS'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
let_it_be(:existing_label) { create(:label, project: project) }
|
||||
let_it_be(:label1) { create(:label, project: project) }
|
||||
let_it_be(:label2) { create(:label, project: project) }
|
||||
|
||||
let(:fields) do
|
||||
<<~FIELDS
|
||||
workItem {
|
||||
widgets {
|
||||
type
|
||||
... on WorkItemWidgetLabels {
|
||||
labels {
|
||||
nodes { id }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
errors
|
||||
FIELDS
|
||||
end
|
||||
|
||||
let(:input) do
|
||||
{ 'labelsWidget' => { 'addLabelIds' => add_label_ids, 'removeLabelIds' => remove_label_ids } }
|
||||
end
|
||||
|
||||
let(:add_label_ids) { [] }
|
||||
let(:remove_label_ids) { [] }
|
||||
|
||||
before_all do
|
||||
work_item.update!(labels: [existing_label])
|
||||
end
|
||||
|
||||
context 'when only removing labels' do
|
||||
let(:remove_label_ids) { [existing_label.to_gid.to_s] }
|
||||
let(:expected_labels) { [] }
|
||||
|
||||
it_behaves_like 'mutation updating work item labels'
|
||||
end
|
||||
|
||||
context 'when only adding labels' do
|
||||
let(:add_label_ids) { [label1.to_gid.to_s, label2.to_gid.to_s] }
|
||||
let(:expected_labels) { [label1, label2, existing_label] }
|
||||
|
||||
it_behaves_like 'mutation updating work item labels'
|
||||
end
|
||||
|
||||
context 'when adding and removing labels' do
|
||||
let(:remove_label_ids) { [existing_label.to_gid.to_s] }
|
||||
let(:add_label_ids) { [label1.to_gid.to_s, label2.to_gid.to_s] }
|
||||
let(:expected_labels) { [label1, label2] }
|
||||
|
||||
it_behaves_like 'mutation updating work item labels'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with due and start date widget input' do
|
||||
let(:start_date) { Date.today }
|
||||
let(:due_date) { 1.week.from_now.to_date }
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# wiki
|
||||
# user
|
||||
|
||||
RSpec.shared_examples 'User views wiki pages' do
|
||||
RSpec.shared_examples 'User views wiki pages' do |support_sorting_by_created_at = true|
|
||||
include WikiHelpers
|
||||
|
||||
let!(:wiki_page1) do
|
||||
|
@ -54,10 +54,12 @@ RSpec.shared_examples 'User views wiki pages' do
|
|||
end
|
||||
end
|
||||
|
||||
if support_sorting_by_created_at
|
||||
context 'ordered by created_at' do
|
||||
let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3] }
|
||||
|
||||
before do
|
||||
stub_feature_flags(wiki_list_pages_with_normal_repository_rpcs: false)
|
||||
page.within('.wiki-sort-dropdown') do
|
||||
click_button('Title')
|
||||
click_button('Created date')
|
||||
|
@ -87,3 +89,4 @@ RSpec.shared_examples 'User views wiki pages' do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -180,17 +180,12 @@ RSpec.shared_examples 'wiki model' do
|
|||
it 'returns false' do
|
||||
expect(subject.empty?).to be(false)
|
||||
end
|
||||
|
||||
it 'only instantiates a Wiki page once' do
|
||||
expect(WikiPage).to receive(:new).once.and_call_original
|
||||
|
||||
subject.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#list_pages' do
|
||||
shared_examples 'wiki model #list_pages' do
|
||||
let(:wiki_pages) { subject.list_pages }
|
||||
|
||||
before do
|
||||
|
@ -227,13 +222,6 @@ RSpec.shared_examples 'wiki model' do
|
|||
expect(subject.list_pages.map(&:title)).to eq(pages)
|
||||
expect(subject.list_pages(direction: 'desc').map(&:title)).to eq(pages.reverse)
|
||||
end
|
||||
|
||||
it 'returns pages sorted by created_at' do
|
||||
pages = ['index', 'index2', 'an index3']
|
||||
|
||||
expect(subject.list_pages(sort: 'created_at').map(&:title)).to eq(pages)
|
||||
expect(subject.list_pages(sort: 'created_at', direction: 'desc').map(&:title)).to eq(pages.reverse)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with load_content option' do
|
||||
|
@ -247,6 +235,19 @@ RSpec.shared_examples 'wiki model' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'list pages with legacy wiki rpcs' do
|
||||
before do
|
||||
stub_feature_flags(wiki_list_page_with_normal_repository_rpcs: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'wiki model #list_pages'
|
||||
end
|
||||
|
||||
context 'list pages with normal repository rpcs' do
|
||||
it_behaves_like 'wiki model #list_pages'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#sidebar_entries' do
|
||||
before do
|
||||
(1..5).each { |i| create(:wiki_page, wiki: wiki, title: "my page #{i}") }
|
||||
|
@ -531,7 +532,7 @@ RSpec.shared_examples 'wiki model' do
|
|||
it 'sets the correct commit message' do
|
||||
subject.create_page('test page', 'some content', :markdown, 'commit message')
|
||||
|
||||
expect(subject.list_pages.first.page.version.message).to eq('commit message')
|
||||
expect(subject.list_pages.first.version.message).to eq('commit message')
|
||||
end
|
||||
|
||||
it 'sets the correct commit email' do
|
||||
|
|
|
@ -4,4 +4,22 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe 'layouts/devise' do
|
||||
it_behaves_like 'a layout which reflects the application theme setting'
|
||||
|
||||
describe 'logo' do
|
||||
it 'renders GitLab logo' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_selector('img[alt^="GitLab"]')
|
||||
end
|
||||
|
||||
context 'with custom logo' do
|
||||
let_it_be(:appearance) { create(:appearance, logo: fixture_file_upload('spec/fixtures/dk.png')) }
|
||||
|
||||
it 'renders custom logo' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_selector('img[data-src$="dk.png"]')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue