Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
defeeba1a8
commit
d0db908485
|
|
@ -108,7 +108,6 @@ Layout/ArgumentAlignment:
|
|||
- 'app/graphql/mutations/jira_import/import_users.rb'
|
||||
- 'app/graphql/mutations/jira_import/start.rb'
|
||||
- 'app/graphql/mutations/labels/create.rb'
|
||||
- 'app/graphql/mutations/members/groups/bulk_update.rb'
|
||||
- 'app/graphql/mutations/merge_requests/accept.rb'
|
||||
- 'app/graphql/mutations/merge_requests/base.rb'
|
||||
- 'app/graphql/mutations/merge_requests/create.rb'
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ Lint/UnusedMethodArgument:
|
|||
- 'app/graphql/mutations/base_mutation.rb'
|
||||
- 'app/graphql/mutations/ci/runner/delete.rb'
|
||||
- 'app/graphql/mutations/concerns/mutations/assignable.rb'
|
||||
- 'app/graphql/mutations/members/groups/bulk_update.rb'
|
||||
- 'app/graphql/mutations/notes/create/base.rb'
|
||||
- 'app/graphql/mutations/notes/create/diff_note.rb'
|
||||
- 'app/graphql/mutations/notes/create/image_diff_note.rb'
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ Style/MutableConstant:
|
|||
Exclude:
|
||||
- 'app/finders/group_members_finder.rb'
|
||||
- 'app/graphql/mutations/container_repositories/destroy_tags.rb'
|
||||
- 'app/graphql/mutations/members/groups/bulk_update.rb'
|
||||
- 'app/graphql/mutations/packages/bulk_destroy.rb'
|
||||
- 'app/helpers/blame_helper.rb'
|
||||
- 'app/models/ci/build_trace_chunks/redis_base.rb'
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ export default function syntaxHighlight($els = null) {
|
|||
|
||||
const els = $els.get ? $els.get() : $els;
|
||||
const handler = (el) => {
|
||||
if (el.classList === undefined) {
|
||||
return el;
|
||||
}
|
||||
|
||||
if (el.classList.contains('js-syntax-highlight')) {
|
||||
// Given the element itself, apply highlighting
|
||||
return el.classList.add(gon.user_color_scheme);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module Members
|
||||
class BulkUpdateBase < BaseMutation
|
||||
include ::API::Helpers::MembersHelpers
|
||||
|
||||
argument :user_ids,
|
||||
[::Types::GlobalIDType[::User]],
|
||||
required: true,
|
||||
description: 'Global IDs of the members.'
|
||||
|
||||
argument :access_level,
|
||||
::Types::MemberAccessLevelEnum,
|
||||
required: true,
|
||||
description: 'Access level to update the members to.'
|
||||
|
||||
argument :expires_at,
|
||||
Types::TimeType,
|
||||
required: false,
|
||||
description: 'Date and time the membership expires.'
|
||||
|
||||
MAX_MEMBERS_UPDATE_LIMIT = 50
|
||||
MAX_MEMBERS_UPDATE_ERROR = "Count of members to be updated should be less than #{MAX_MEMBERS_UPDATE_LIMIT}."
|
||||
.freeze
|
||||
INVALID_MEMBERS_ERROR = 'Only access level of direct members can be updated.'
|
||||
|
||||
def resolve(**args)
|
||||
result = ::Members::UpdateService
|
||||
.new(current_user, args.except(:user_ids, source_id_param_name))
|
||||
.execute(@updatable_members)
|
||||
|
||||
{
|
||||
source_members_key => result[:members],
|
||||
errors: Array.wrap(result[:message])
|
||||
}
|
||||
rescue Gitlab::Access::AccessDeniedError
|
||||
{
|
||||
errors: ["Unable to update members, please check user permissions."]
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ready?(**args)
|
||||
source = authorized_find!(source_id: args[source_id_param_name])
|
||||
user_ids = args.fetch(:user_ids, {}).map(&:model_id)
|
||||
@updatable_members = only_direct_members(source, user_ids)
|
||||
|
||||
if @updatable_members.size > MAX_MEMBERS_UPDATE_LIMIT
|
||||
raise Gitlab::Graphql::Errors::InvalidMemberCountError, MAX_MEMBERS_UPDATE_ERROR
|
||||
end
|
||||
|
||||
if @updatable_members.size != user_ids.size
|
||||
raise Gitlab::Graphql::Errors::InvalidMembersError, INVALID_MEMBERS_ERROR
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def find_object(source_id:)
|
||||
GitlabSchema.object_from_id(source_id, expected_type: source_type)
|
||||
end
|
||||
|
||||
def only_direct_members(source, user_ids)
|
||||
source_members(source)
|
||||
.with_user(user_ids)
|
||||
.to_a
|
||||
end
|
||||
|
||||
def source_id_param_name
|
||||
"#{source_name}_id".to_sym
|
||||
end
|
||||
|
||||
def source_members_key
|
||||
"#{source_name}_members".to_sym
|
||||
end
|
||||
|
||||
def source_name
|
||||
source_type.name.downcase
|
||||
end
|
||||
|
||||
def source_type
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,81 +3,22 @@
|
|||
module Mutations
|
||||
module Members
|
||||
module Groups
|
||||
class BulkUpdate < ::Mutations::BaseMutation
|
||||
class BulkUpdate < BulkUpdateBase
|
||||
graphql_name 'GroupMemberBulkUpdate'
|
||||
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
authorize :admin_group_member
|
||||
|
||||
field :group_members,
|
||||
[Types::GroupMemberType],
|
||||
null: true,
|
||||
description: 'Group members after mutation.'
|
||||
[Types::GroupMemberType],
|
||||
null: true,
|
||||
description: 'Group members after mutation.'
|
||||
|
||||
argument :group_id,
|
||||
::Types::GlobalIDType[::Group],
|
||||
required: true,
|
||||
description: 'Global ID of the group.'
|
||||
::Types::GlobalIDType[::Group],
|
||||
required: true,
|
||||
description: 'Global ID of the group.'
|
||||
|
||||
argument :user_ids,
|
||||
[::Types::GlobalIDType[::User]],
|
||||
required: true,
|
||||
description: 'Global IDs of the group members.'
|
||||
|
||||
argument :access_level,
|
||||
::Types::MemberAccessLevelEnum,
|
||||
required: true,
|
||||
description: 'Access level to update the members to.'
|
||||
|
||||
argument :expires_at,
|
||||
Types::TimeType,
|
||||
required: false,
|
||||
description: 'Date and time the membership expires.'
|
||||
|
||||
MAX_MEMBERS_UPDATE_LIMIT = 50
|
||||
MAX_MEMBERS_UPDATE_ERROR = "Count of members to be updated should be less than #{MAX_MEMBERS_UPDATE_LIMIT}."
|
||||
INVALID_MEMBERS_ERROR = 'Only access level of direct members can be updated.'
|
||||
|
||||
def resolve(group_id:, **args)
|
||||
result = ::Members::UpdateService.new(current_user, args.except(:user_ids)).execute(@updatable_group_members)
|
||||
|
||||
{
|
||||
group_members: result[:members],
|
||||
errors: Array.wrap(result[:message])
|
||||
}
|
||||
rescue Gitlab::Access::AccessDeniedError
|
||||
{
|
||||
errors: ["Unable to update members, please check user permissions."]
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ready?(**args)
|
||||
group = authorized_find!(group_id: args[:group_id])
|
||||
user_ids = args.fetch(:user_ids, {}).map(&:model_id)
|
||||
@updatable_group_members = only_direct_group_members(group, user_ids)
|
||||
|
||||
if @updatable_group_members.size > MAX_MEMBERS_UPDATE_LIMIT
|
||||
raise Gitlab::Graphql::Errors::InvalidMemberCountError, MAX_MEMBERS_UPDATE_ERROR
|
||||
end
|
||||
|
||||
if @updatable_group_members.size != user_ids.size
|
||||
raise Gitlab::Graphql::Errors::InvalidMembersError, INVALID_MEMBERS_ERROR
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def find_object(group_id:)
|
||||
GitlabSchema.object_from_id(group_id, expected_type: ::Group)
|
||||
end
|
||||
|
||||
def only_direct_group_members(group, user_ids)
|
||||
group
|
||||
.members
|
||||
.with_user(user_ids).to_a
|
||||
def source_type
|
||||
::Group
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module Members
|
||||
module Projects
|
||||
class BulkUpdate < BulkUpdateBase
|
||||
graphql_name 'ProjectMemberBulkUpdate'
|
||||
authorize :admin_project_member
|
||||
|
||||
field :project_members,
|
||||
[Types::ProjectMemberType],
|
||||
null: true,
|
||||
description: 'Project members after mutation.'
|
||||
|
||||
argument :project_id,
|
||||
::Types::GlobalIDType[::Project],
|
||||
required: true,
|
||||
description: 'Global ID of the project.'
|
||||
|
||||
def source_type
|
||||
::Project
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -70,6 +70,7 @@ module Types
|
|||
mount_mutation Mutations::Issues::BulkUpdate, alpha: { milestone: '15.9' }
|
||||
mount_mutation Mutations::Labels::Create
|
||||
mount_mutation Mutations::Members::Groups::BulkUpdate
|
||||
mount_mutation Mutations::Members::Projects::BulkUpdate
|
||||
mount_mutation Mutations::MergeRequests::Accept
|
||||
mount_mutation Mutations::MergeRequests::Create
|
||||
mount_mutation Mutations::MergeRequests::Update
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@ module DiffHelper
|
|||
options[:expanded] = true
|
||||
options[:paths] = params.values_at(:old_path, :new_path)
|
||||
options[:use_extra_viewer_as_main] = false
|
||||
|
||||
if Feature.enabled?(:large_ipynb_diffs, @project) && params[:file_identifier]&.include?('.ipynb')
|
||||
options[:max_patch_bytes_for_file_extension] = {
|
||||
'.ipynb' => 1.megabyte
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
options
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- breadcrumb_title _("Compare Revisions")
|
||||
- page_title _("Compare")
|
||||
- breadcrumb_title _("Compare revisions")
|
||||
- page_title _("Compare revisions")
|
||||
|
||||
%h1.page-title.gl-font-size-h-display
|
||||
= _("Compare Git revisions")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
- add_to_breadcrumbs _("Compare Revisions"), project_compare_index_path(@project)
|
||||
- add_to_breadcrumbs _("Compare revisions"), project_compare_index_path(@project)
|
||||
- page_title "#{params[:from]}...#{params[:to]}"
|
||||
|
||||
.sub-header-block.gl-border-b-0.gl-mb-0
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
- page_title _('Contributors')
|
||||
- page_title _('Contributor statistics')
|
||||
- graph_path = project_graph_path(@project, current_ref, ref_type: @ref_type, format: :json)
|
||||
- commits_path = project_commits_path(@project, current_ref, ref_type: @ref_type)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: large_ipynb_diffs
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113370
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/393886
|
||||
milestone: '15.10'
|
||||
type: development
|
||||
group: group::incubation
|
||||
default_enabled: false
|
||||
|
|
@ -3185,7 +3185,7 @@ Input type: `GroupMemberBulkUpdateInput`
|
|||
| <a id="mutationgroupmemberbulkupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationgroupmemberbulkupdateexpiresat"></a>`expiresAt` | [`Time`](#time) | Date and time the membership expires. |
|
||||
| <a id="mutationgroupmemberbulkupdategroupid"></a>`groupId` | [`GroupID!`](#groupid) | Global ID of the group. |
|
||||
| <a id="mutationgroupmemberbulkupdateuserids"></a>`userIds` | [`[UserID!]!`](#userid) | Global IDs of the group members. |
|
||||
| <a id="mutationgroupmemberbulkupdateuserids"></a>`userIds` | [`[UserID!]!`](#userid) | Global IDs of the members. |
|
||||
|
||||
#### Fields
|
||||
|
||||
|
|
@ -4715,6 +4715,28 @@ Input type: `ProjectInitializeProductAnalyticsInput`
|
|||
| <a id="mutationprojectinitializeproductanalyticserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationprojectinitializeproductanalyticsproject"></a>`project` | [`Project`](#project) | Project on which the initialization took place. |
|
||||
|
||||
### `Mutation.projectMemberBulkUpdate`
|
||||
|
||||
Input type: `ProjectMemberBulkUpdateInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationprojectmemberbulkupdateaccesslevel"></a>`accessLevel` | [`MemberAccessLevel!`](#memberaccesslevel) | Access level to update the members to. |
|
||||
| <a id="mutationprojectmemberbulkupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationprojectmemberbulkupdateexpiresat"></a>`expiresAt` | [`Time`](#time) | Date and time the membership expires. |
|
||||
| <a id="mutationprojectmemberbulkupdateprojectid"></a>`projectId` | [`ProjectID!`](#projectid) | Global ID of the project. |
|
||||
| <a id="mutationprojectmemberbulkupdateuserids"></a>`userIds` | [`[UserID!]!`](#userid) | Global IDs of the members. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationprojectmemberbulkupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationprojectmemberbulkupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationprojectmemberbulkupdateprojectmembers"></a>`projectMembers` | [`[ProjectMember!]`](#projectmember) | Project members after mutation. |
|
||||
|
||||
### `Mutation.projectSetComplianceFramework`
|
||||
|
||||
Assign (or unset) a compliance framework to a project.
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ To view the user who locked the file (if it was not you), hover over the button.
|
|||
To view and remove file locks:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Repository > Locked Files**.
|
||||
1. On the left sidebar, select **Repository > Locked files**.
|
||||
|
||||
This list shows all the files locked either through LFS or GitLab UI.
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ issue number. GitLab uses the issue number to import data into the merge request
|
|||
To compare branches in a repository:
|
||||
|
||||
1. On the top bar, select **Main menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Repository > Compare**.
|
||||
1. On the left sidebar, select **Repository > Compare revisions**.
|
||||
1. Select the **Source** branch to search for your desired branch. Exact matches are
|
||||
shown first. You can refine your search with operators:
|
||||
- `^` matches the beginning of the branch name: `^feat` matches `feat/user-authentication`.
|
||||
|
|
|
|||
|
|
@ -235,9 +235,9 @@ The size can differ slightly from one instance to another due to compression, ho
|
|||
Administrators can set a [repository size limit](../../admin_area/settings/account_and_limit_settings.md).
|
||||
[GitLab sets the size limits for GitLab.com](../../gitlab_com/index.md#account-and-limit-settings).
|
||||
|
||||
## Repository contributor graph
|
||||
## Repository contributor statistics
|
||||
|
||||
All code contributors are displayed under your project's **Repository > Contributors**.
|
||||
All code contributors are displayed under your project's **Repository > Contributor statistics**.
|
||||
|
||||
The graph shows the contributor with the most commits to the fewest.
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ module Gitlab
|
|||
limits[:safe_max_lines] = [limits[:max_lines], defaults[:max_lines]].min
|
||||
limits[:safe_max_bytes] = limits[:safe_max_files] * 5.kilobytes # Average 5 KB per file
|
||||
limits[:max_patch_bytes] = Gitlab::Git::Diff.patch_hard_limit_bytes
|
||||
limits[:max_patch_bytes_for_file_extension] = options.fetch(:max_patch_bytes_for_file_extension, {})
|
||||
|
||||
limits
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ module Sidebars
|
|||
link = project_graph_path(context.project, context.current_ref, ref_type: ref_type_from_context(context))
|
||||
|
||||
::Sidebars::MenuItem.new(
|
||||
title: _('Contributors'),
|
||||
title: _('Contributor statistics'),
|
||||
link: link,
|
||||
active_routes: { path: 'graphs#show' },
|
||||
item_id: :contributors
|
||||
|
|
@ -112,7 +112,7 @@ module Sidebars
|
|||
|
||||
def compare_menu_item
|
||||
::Sidebars::MenuItem.new(
|
||||
title: _('Compare'),
|
||||
title: _('Compare revisions'),
|
||||
link: project_compare_index_path(context.project, from: context.project.repository.root_ref, to: context.current_ref),
|
||||
active_routes: { controller: :compare },
|
||||
item_id: :compare
|
||||
|
|
|
|||
|
|
@ -10390,9 +10390,6 @@ msgstr ""
|
|||
msgid "Compare GitLab plans"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compare Revisions"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compare branches and continue"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -10405,6 +10402,9 @@ msgstr ""
|
|||
msgid "Compare changes with the merge request target branch"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compare revisions"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compare submodule commit revisions"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -11401,7 +11401,7 @@ msgstr ""
|
|||
msgid "Contributor"
|
||||
msgstr ""
|
||||
|
||||
msgid "Contributors"
|
||||
msgid "Contributor statistics"
|
||||
msgstr ""
|
||||
|
||||
msgid "Control emails linked to your account"
|
||||
|
|
@ -25756,9 +25756,6 @@ msgstr ""
|
|||
msgid "Locked"
|
||||
msgstr ""
|
||||
|
||||
msgid "Locked Files"
|
||||
msgstr ""
|
||||
|
||||
msgid "Locked by %{fileLockUserName}"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ module QA
|
|||
def go_to_repository_contributors
|
||||
hover_repository do
|
||||
within_submenu do
|
||||
click_element(:sidebar_menu_item_link, menu_item: 'Contributors')
|
||||
click_element(:sidebar_menu_item_link, menu_item: 'Contributor statistics')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# TODO: remove this test when 'vscode_web_ide' feature flag is default enabled
|
||||
module QA
|
||||
RSpec.describe 'Create', :skip_live_env, except: { job: 'review-qa-*' },
|
||||
feature_flag: { name: 'vscode_web_ide', scope: :global },
|
||||
product_group: :editor,
|
||||
quarantine: {
|
||||
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/387928',
|
||||
type: :stale
|
||||
} do
|
||||
RSpec.describe 'Create', :skip_live_env, except: { job: 'review-qa-*' }, product_group: :editor do
|
||||
describe 'Git Server Hooks' do
|
||||
let(:file_path) { File.join(Runtime::Path.fixtures_path, 'web_ide', 'README.md') }
|
||||
|
||||
|
|
@ -20,15 +15,10 @@ module QA
|
|||
end
|
||||
|
||||
before do
|
||||
Runtime::Feature.disable(:vscode_web_ide)
|
||||
Flow::Login.sign_in
|
||||
project.visit!
|
||||
end
|
||||
|
||||
after do
|
||||
Runtime::Feature.enable(:vscode_web_ide)
|
||||
end
|
||||
|
||||
context 'with custom error messages' do
|
||||
it 'renders preconfigured error message when user hook failed on commit in WebIDE',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/364751' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Merge request > Real-time reviewers', feature_category: :code_review_workflow do
|
||||
let_it_be(:project) { create(:project, :public, :repository) }
|
||||
let(:user) { project.creator }
|
||||
let(:merge_request) { create(:merge_request, :simple, source_project: project, author: user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
visit project_merge_request_path(project, merge_request)
|
||||
end
|
||||
|
||||
it 'updates in real-time', :js do
|
||||
wait_for_requests
|
||||
|
||||
# Simulate a real-time update of reviewers
|
||||
merge_request.update!(reviewer_ids: [user.id])
|
||||
GraphqlTriggers.merge_request_reviewers_updated(merge_request)
|
||||
|
||||
expect(find('.reviewer')).to have_content(user.name)
|
||||
end
|
||||
end
|
||||
|
|
@ -4,12 +4,12 @@ import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
|||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import NewAccessTokenApp from '~/access_tokens/components/new_access_token_app.vue';
|
||||
import { EVENT_ERROR, EVENT_SUCCESS, FORM_SELECTOR } from '~/access_tokens/components/constants';
|
||||
import { createAlert, VARIANT_INFO } from '~/flash';
|
||||
import { createAlert, VARIANT_INFO } from '~/alert';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import DomElementListener from '~/vue_shared/components/dom_element_listener.vue';
|
||||
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('~/access_tokens/components/new_access_token_app', () => {
|
||||
let wrapper;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import testAction from 'helpers/vuex_action_helper';
|
||||
import * as actions from '~/contributors/stores/actions';
|
||||
import * as types from '~/contributors/stores/mutation_types';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('Contributors store actions', () => {
|
||||
describe('fetchChartData', () => {
|
||||
|
|
@ -38,7 +38,7 @@ describe('Contributors store actions', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should show flash on API error', async () => {
|
||||
it('should show alert on API error', async () => {
|
||||
mock.onGet().reply(HTTP_STATUS_BAD_REQUEST, 'Not Found');
|
||||
|
||||
await testAction(
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ import Api from '~/api';
|
|||
import * as actions from '~/deploy_freeze/store/actions';
|
||||
import * as types from '~/deploy_freeze/store/mutation_types';
|
||||
import getInitialState from '~/deploy_freeze/store/state';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import * as logger from '~/lib/logger';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { freezePeriodsFixture } from '../helpers';
|
||||
import { timezoneDataFixture } from '../../vue_shared/components/timezone_dropdown/helpers';
|
||||
|
||||
jest.mock('~/api.js');
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('deploy freeze store actions', () => {
|
||||
const freezePeriodFixture = freezePeriodsFixture[0];
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
|
|||
import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
|
||||
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
|
||||
import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from '~/lib/utils/keycodes';
|
||||
import { visitUrl, getParameterByName } from '~/lib/utils/url_utility';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
jest.mock('~/lib/utils/url_utility', () => ({
|
||||
...jest.requireActual('~/lib/utils/url_utility'),
|
||||
getParameterByName: jest.fn(),
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
|
|||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import DropdownUtils from '~/filtered_search/dropdown_utils';
|
||||
import VisualTokenValue from '~/filtered_search/visual_token_value';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import AjaxCache from '~/lib/utils/ajax_cache';
|
||||
import UsersCache from '~/lib/utils/users_cache';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('Filtered Search Visual Tokens', () => {
|
||||
const findElements = (tokenElement) => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import AxiosMockAdapter from 'axios-mock-adapter';
|
|||
import Vue, { nextTick } from 'vue';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import appComponent from '~/groups/components/app.vue';
|
||||
import groupFolderComponent from '~/groups/components/group_folder.vue';
|
||||
import groupItemComponent from '~/groups/components/group_item.vue';
|
||||
|
|
@ -34,7 +34,7 @@ import {
|
|||
const $toast = {
|
||||
show: jest.fn(),
|
||||
};
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('AppComponent', () => {
|
||||
let wrapper;
|
||||
|
|
@ -117,7 +117,7 @@ describe('AppComponent', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should show flash error when request fails', () => {
|
||||
it('should show alert error when request fails', () => {
|
||||
mock.onGet('/dashboard/groups.json').reply(HTTP_STATUS_BAD_REQUEST);
|
||||
|
||||
jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
||||
|
|
@ -325,7 +325,7 @@ describe('AppComponent', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should show error flash message if request failed to leave group', () => {
|
||||
it('should show error alert message if request failed to leave group', () => {
|
||||
const message = 'An error occurred. Please try again.';
|
||||
jest
|
||||
.spyOn(vm.service, 'leaveGroup')
|
||||
|
|
@ -342,7 +342,7 @@ describe('AppComponent', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should show appropriate error flash message if request forbids to leave group', () => {
|
||||
it('should show appropriate error alert message if request forbids to leave group', () => {
|
||||
const message = 'Failed to leave the group. Please make sure you are not the only owner.';
|
||||
jest.spyOn(vm.service, 'leaveGroup').mockRejectedValue({ status: HTTP_STATUS_FORBIDDEN });
|
||||
jest.spyOn(vm.store, 'removeGroup');
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ import waitForPromises from 'helpers/wait_for_promises';
|
|||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import GroupNameAndPath from '~/groups/components/group_name_and_path.vue';
|
||||
import { getGroupPathAvailability } from '~/rest_api';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import searchGroupsWhereUserCanCreateSubgroups from '~/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
jest.mock('~/rest_api', () => ({
|
||||
getGroupPathAvailability: jest.fn(),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
MOCK_ISSUE_PATH,
|
||||
} from '../mock_data';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('Header Search Store Actions', () => {
|
||||
let state;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
issuable1,
|
||||
issuable2,
|
||||
} from 'jest/issuable/components/related_issuable_mock_data';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import {
|
||||
HTTP_STATUS_CONFLICT,
|
||||
|
|
@ -19,7 +19,7 @@ import RelatedIssuesBlock from '~/related_issues/components/related_issues_block
|
|||
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
|
||||
import relatedIssuesService from '~/related_issues/services/related_issues_service';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('RelatedIssuesRoot', () => {
|
||||
let wrapper;
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import $ from 'jquery';
|
|||
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||
import { TEST_HOST } from 'spec/test_constants';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_CONFLICT, HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
import MergeRequest from '~/merge_request';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('MergeRequest', () => {
|
||||
const test = {};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Vue from 'vue';
|
|||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import FailedJobsApp from '~/pipelines/components/jobs/failed_jobs_app.vue';
|
||||
import FailedJobsTable from '~/pipelines/components/jobs/failed_jobs_table.vue';
|
||||
import GetFailedJobsQuery from '~/pipelines/graphql/queries/get_failed_jobs.query.graphql';
|
||||
|
|
@ -12,7 +12,7 @@ import { mockFailedJobsQueryResponse, mockFailedJobsSummaryData } from '../../mo
|
|||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('Failed Jobs App', () => {
|
||||
let wrapper;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
|
|||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import { redirectTo } from '~/lib/utils/url_utility';
|
||||
import FailedJobsTable from '~/pipelines/components/jobs/failed_jobs_table.vue';
|
||||
import RetryFailedJobMutation from '~/pipelines/graphql/mutations/retry_failed_job.mutation.graphql';
|
||||
|
|
@ -15,7 +15,7 @@ import {
|
|||
mockPreparedFailedJobsDataNoPermission,
|
||||
} from '../../mock_data';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
jest.mock('~/lib/utils/url_utility');
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Vue from 'vue';
|
|||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import JobsApp from '~/pipelines/components/jobs/jobs_app.vue';
|
||||
import JobsTable from '~/jobs/components/table/jobs_table.vue';
|
||||
import getPipelineJobsQuery from '~/pipelines/graphql/queries/get_pipeline_jobs.query.graphql';
|
||||
|
|
@ -12,7 +12,7 @@ import { mockPipelineJobsQueryResponse } from '../../mock_data';
|
|||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('Jobs app', () => {
|
||||
let wrapper;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { nextTick } from 'vue';
|
|||
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { TEST_HOST } from 'spec/test_constants';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
|
||||
|
|
@ -13,7 +13,7 @@ import PipelinesManualActions from '~/pipelines/components/pipelines_list/pipeli
|
|||
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
|
||||
import { TRACKING_CATEGORIES } from '~/pipelines/constants';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal');
|
||||
|
||||
describe('Pipelines Actions dropdown', () => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { mockTracking } from 'helpers/tracking_helper';
|
|||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import Api from '~/api';
|
||||
import { createAlert, VARIANT_WARNING } from '~/flash';
|
||||
import { createAlert, VARIANT_WARNING } from '~/alert';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue';
|
||||
|
|
@ -25,7 +25,7 @@ import TablePagination from '~/vue_shared/components/pagination/table_pagination
|
|||
|
||||
import { stageReply, users, mockSearch, branches } from './mock_data';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
const mockProjectPath = 'twitter/flight';
|
||||
const mockProjectId = '21';
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import testReports from 'test_fixtures/pipelines/test_report.json';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import testAction from 'helpers/vuex_action_helper';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
import * as actions from '~/pipelines/stores/test_reports/actions';
|
||||
import * as types from '~/pipelines/stores/test_reports/mutation_types';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('Actions TestReports Store', () => {
|
||||
let mock;
|
||||
|
|
@ -49,7 +49,7 @@ describe('Actions TestReports Store', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should create flash on API error', async () => {
|
||||
it('should create alert on API error', async () => {
|
||||
await testAction(
|
||||
actions.fetchSummary,
|
||||
null,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import testReports from 'test_fixtures/pipelines/test_report.json';
|
||||
import * as types from '~/pipelines/stores/test_reports/mutation_types';
|
||||
import mutations from '~/pipelines/stores/test_reports/mutations';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
|
||||
describe('Mutations TestReports Store', () => {
|
||||
let mockState;
|
||||
|
|
@ -58,7 +58,7 @@ describe('Mutations TestReports Store', () => {
|
|||
expect(mockState.errorMessage).toBe(message);
|
||||
});
|
||||
|
||||
it('should show a flash message otherwise', () => {
|
||||
it('should show an alert message otherwise', () => {
|
||||
mutations[types.SET_SUITE_ERROR](mockState, {});
|
||||
|
||||
expect(createAlert).toHaveBeenCalled();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import testAction from 'helpers/vuex_action_helper';
|
||||
import Api from '~/api';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import * as logger from '~/lib/logger';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
|
|
@ -33,7 +33,7 @@ import {
|
|||
MOCK_AGGREGATIONS,
|
||||
} from '../mock_data';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
jest.mock('~/lib/utils/url_utility', () => ({
|
||||
setUrlParams: jest.fn(),
|
||||
joinPaths: jest.fn().mockReturnValue(''),
|
||||
|
|
@ -47,7 +47,7 @@ describe('Global Search Store Actions', () => {
|
|||
let mock;
|
||||
let state;
|
||||
|
||||
const flashCallback = (callCount) => {
|
||||
const alertCallback = (callCount) => {
|
||||
expect(createAlert).toHaveBeenCalledTimes(callCount);
|
||||
createAlert.mockClear();
|
||||
};
|
||||
|
|
@ -63,12 +63,12 @@ describe('Global Search Store Actions', () => {
|
|||
});
|
||||
|
||||
describe.each`
|
||||
action | axiosMock | type | expectedMutations | flashCallCount
|
||||
action | axiosMock | type | expectedMutations | alertCallCount
|
||||
${actions.fetchGroups} | ${{ method: 'onGet', code: HTTP_STATUS_OK, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${0}
|
||||
${actions.fetchGroups} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${1}
|
||||
${actions.fetchProjects} | ${{ method: 'onGet', code: HTTP_STATUS_OK, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${0}
|
||||
${actions.fetchProjects} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${1}
|
||||
`(`axios calls`, ({ action, axiosMock, type, expectedMutations, flashCallCount }) => {
|
||||
`(`axios calls`, ({ action, axiosMock, type, expectedMutations, alertCallCount }) => {
|
||||
describe(action.name, () => {
|
||||
describe(`on ${type}`, () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -76,7 +76,7 @@ describe('Global Search Store Actions', () => {
|
|||
});
|
||||
it(`should dispatch the correct mutations`, () => {
|
||||
return testAction({ action, state, expectedMutations }).then(() =>
|
||||
flashCallback(flashCallCount),
|
||||
alertCallback(alertCallCount),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -84,12 +84,12 @@ describe('Global Search Store Actions', () => {
|
|||
});
|
||||
|
||||
describe.each`
|
||||
action | axiosMock | type | expectedMutations | flashCallCount
|
||||
action | axiosMock | type | expectedMutations | alertCallCount
|
||||
${actions.loadFrequentGroups} | ${{ method: 'onGet', code: HTTP_STATUS_OK }} | ${'success'} | ${[PROMISE_ALL_EXPECTED_MUTATIONS.resGroups]} | ${0}
|
||||
${actions.loadFrequentGroups} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR }} | ${'error'} | ${[]} | ${1}
|
||||
${actions.loadFrequentProjects} | ${{ method: 'onGet', code: HTTP_STATUS_OK }} | ${'success'} | ${[PROMISE_ALL_EXPECTED_MUTATIONS.resProjects]} | ${0}
|
||||
${actions.loadFrequentProjects} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR }} | ${'error'} | ${[]} | ${1}
|
||||
`('Promise.all calls', ({ action, axiosMock, type, expectedMutations, flashCallCount }) => {
|
||||
`('Promise.all calls', ({ action, axiosMock, type, expectedMutations, alertCallCount }) => {
|
||||
describe(action.name, () => {
|
||||
describe(`on ${type}`, () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -103,7 +103,7 @@ describe('Global Search Store Actions', () => {
|
|||
|
||||
it(`should dispatch the correct mutations`, () => {
|
||||
return testAction({ action, state, expectedMutations }).then(() => {
|
||||
flashCallback(flashCallCount);
|
||||
alertCallback(alertCallCount);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import approvedByCurrentUser from 'test_fixtures/graphql/merge_requests/approval
|
|||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import Approvals from '~/vue_merge_request_widget/components/approvals/approvals.vue';
|
||||
import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
|
||||
import ApprovalsSummaryOptional from '~/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue';
|
||||
|
|
@ -21,7 +21,7 @@ import { createCanApproveResponse } from 'jest/approvals/mock_data';
|
|||
Vue.use(VueApollo);
|
||||
|
||||
const mockAlertDismiss = jest.fn();
|
||||
jest.mock('~/flash', () => ({
|
||||
jest.mock('~/alert', () => ({
|
||||
createAlert: jest.fn().mockImplementation(() => ({
|
||||
dismiss: mockAlertDismiss,
|
||||
})),
|
||||
|
|
@ -295,7 +295,7 @@ describe('MRWidget approvals', () => {
|
|||
return nextTick();
|
||||
});
|
||||
|
||||
it('flashes error message', () => {
|
||||
it('alerts error message', () => {
|
||||
expect(createAlert).toHaveBeenCalledWith({ message: UNAPPROVE_ERROR });
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import getStateQueryResponse from 'test_fixtures/graphql/merge_requests/get_state.query.graphql.json';
|
||||
import { createAlert } from '~/flash';
|
||||
import { createAlert } from '~/alert';
|
||||
import WorkInProgress, {
|
||||
MSG_SOMETHING_WENT_WRONG,
|
||||
MSG_MARK_READY,
|
||||
|
|
@ -22,7 +22,7 @@ const TEST_MR_IID = '23';
|
|||
const TEST_MR_TITLE = 'Test MR Title';
|
||||
const TEST_PROJECT_PATH = 'lorem/ipsum';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/alert');
|
||||
jest.mock('~/merge_request');
|
||||
|
||||
describe('~/vue_merge_request_widget/components/states/work_in_progress.vue', () => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Mutations::Members::BulkUpdateBase, feature_category: :subgroups do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group).tap { |group| group.add_owner(user) } }
|
||||
|
||||
it 'raises a NotImplementedError error if the source_type method is called on the base class' do
|
||||
mutation = described_class.new(context: { current_user: user }, object: nil, field: nil)
|
||||
|
||||
expect { mutation.resolve(group_id: group.to_gid.to_s) }.to raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
||||
|
|
@ -47,6 +47,12 @@ RSpec.describe DiffHelper do
|
|||
end
|
||||
|
||||
describe 'diff_options' do
|
||||
let(:large_notebooks_enabled) { false }
|
||||
|
||||
before do
|
||||
stub_feature_flags(large_ipynb_diffs: large_notebooks_enabled)
|
||||
end
|
||||
|
||||
it 'returns no collapse false' do
|
||||
expect(diff_options).to include(expanded: false)
|
||||
end
|
||||
|
|
@ -56,21 +62,48 @@ RSpec.describe DiffHelper do
|
|||
expect(diff_options).to include(expanded: true)
|
||||
end
|
||||
|
||||
it 'returns no collapse true if action name diff_for_path' do
|
||||
allow(controller).to receive(:action_name) { 'diff_for_path' }
|
||||
expect(diff_options).to include(expanded: true)
|
||||
end
|
||||
context 'when action name is diff_for_path' do
|
||||
before do
|
||||
allow(controller).to receive(:action_name) { 'diff_for_path' }
|
||||
end
|
||||
|
||||
it 'returns paths if action name diff_for_path and param old path' do
|
||||
allow(controller).to receive(:params) { { old_path: 'lib/wadus.rb' } }
|
||||
allow(controller).to receive(:action_name) { 'diff_for_path' }
|
||||
expect(diff_options[:paths]).to include('lib/wadus.rb')
|
||||
end
|
||||
it 'returns expanded true' do
|
||||
expect(diff_options).to include(expanded: true)
|
||||
end
|
||||
|
||||
it 'returns paths if action name diff_for_path and param new path' do
|
||||
allow(controller).to receive(:params) { { new_path: 'lib/wadus.rb' } }
|
||||
allow(controller).to receive(:action_name) { 'diff_for_path' }
|
||||
expect(diff_options[:paths]).to include('lib/wadus.rb')
|
||||
it 'returns paths if param old path' do
|
||||
allow(controller).to receive(:params) { { old_path: 'lib/wadus.rb' } }
|
||||
expect(diff_options[:paths]).to include('lib/wadus.rb')
|
||||
end
|
||||
|
||||
it 'returns paths if param new path' do
|
||||
allow(controller).to receive(:params) { { new_path: 'lib/wadus.rb' } }
|
||||
expect(diff_options[:paths]).to include('lib/wadus.rb')
|
||||
end
|
||||
|
||||
it 'does not set max_patch_bytes_for_file_extension' do
|
||||
expect(diff_options[:max_patch_bytes_for_file_extension]).to be_nil
|
||||
end
|
||||
|
||||
context 'when file_identifier include .ipynb' do
|
||||
before do
|
||||
allow(controller).to receive(:params) { { file_identifier: 'something.ipynb' } }
|
||||
end
|
||||
|
||||
context 'when large_ipynb_diffs is disabled' do
|
||||
it 'does not set max_patch_bytes_for_file_extension' do
|
||||
expect(diff_options[:max_patch_bytes_for_file_extension]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when large_ipynb_diffs is enabled' do
|
||||
let(:large_notebooks_enabled) { true }
|
||||
|
||||
it 'sets max_patch_bytes_for_file_extension' do
|
||||
expect(diff_options[:max_patch_bytes_for_file_extension]).to eq({ '.ipynb' => 1.megabyte })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -777,6 +777,26 @@ RSpec.describe Gitlab::Git::DiffCollection do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.limits' do
|
||||
let(:options) { {} }
|
||||
|
||||
subject { described_class.limits(options) }
|
||||
|
||||
context 'when options do not include max_patch_bytes_for_file_extension' do
|
||||
it 'sets max_patch_bytes_for_file_extension as empty' do
|
||||
expect(subject[:max_patch_bytes_for_file_extension]).to eq({})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when options include max_patch_bytes_for_file_extension' do
|
||||
let(:options) { { max_patch_bytes_for_file_extension: { '.file' => 1 } } }
|
||||
|
||||
it 'sets value for max_patch_bytes_for_file_extension' do
|
||||
expect(subject[:max_patch_bytes_for_file_extension]).to eq({ '.file' => 1 })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def fake_diff(line_length, line_count)
|
||||
{ 'diff' => "#{'a' * line_length}\n" * line_count }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu, feature_category: :sou
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Contributors' do
|
||||
describe 'Contributor statistics' do
|
||||
let_it_be(:item_id) { :contributors }
|
||||
|
||||
context 'when analytics is disabled' do
|
||||
|
|
|
|||
|
|
@ -5,126 +5,14 @@ require 'spec_helper'
|
|||
RSpec.describe 'GroupMemberBulkUpdate', feature_category: :subgroups do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:user1) { create(:user) }
|
||||
let_it_be(:user2) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:group_member1) { create(:group_member, group: group, user: user1) }
|
||||
let_it_be(:group_member2) { create(:group_member, group: group, user: user2) }
|
||||
let_it_be(:parent_group) { create(:group) }
|
||||
let_it_be(:parent_group_member) { create(:group_member, group: parent_group) }
|
||||
let_it_be(:group) { create(:group, parent: parent_group) }
|
||||
let_it_be(:source) { group }
|
||||
let_it_be(:member_type) { :group_member }
|
||||
let_it_be(:mutation_name) { :group_member_bulk_update }
|
||||
let_it_be(:source_id_key) { 'group_id' }
|
||||
let_it_be(:response_member_field) { 'groupMembers' }
|
||||
|
||||
let(:input) do
|
||||
{
|
||||
'group_id' => group.to_global_id.to_s,
|
||||
'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s],
|
||||
'access_level' => 'GUEST'
|
||||
}
|
||||
end
|
||||
|
||||
let(:extra_params) { { expires_at: 10.days.from_now } }
|
||||
let(:input_params) { input.merge(extra_params) }
|
||||
let(:mutation) { graphql_mutation(mutation_name, input_params) }
|
||||
let(:mutation_response) { graphql_mutation_response(mutation_name) }
|
||||
|
||||
context 'when user is not logged-in' do
|
||||
it_behaves_like 'a mutation that returns a top-level access error'
|
||||
end
|
||||
|
||||
context 'when user is not an owner' do
|
||||
before do
|
||||
group.add_maintainer(current_user)
|
||||
end
|
||||
|
||||
it_behaves_like 'a mutation that returns a top-level access error'
|
||||
end
|
||||
|
||||
context 'when user is an owner' do
|
||||
before do
|
||||
group.add_owner(current_user)
|
||||
end
|
||||
|
||||
shared_examples 'updates the user access role' do
|
||||
specify do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
new_access_levels = mutation_response['groupMembers'].map { |member| member['accessLevel']['integerValue'] }
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(mutation_response['errors']).to be_empty
|
||||
expect(new_access_levels).to all(be Gitlab::Access::GUEST)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'updates the user access role'
|
||||
|
||||
context 'when inherited members are passed' do
|
||||
let_it_be(:subgroup) { create(:group, parent: group) }
|
||||
let_it_be(:subgroup_member) { create(:group_member, group: subgroup) }
|
||||
|
||||
let(:input) do
|
||||
{
|
||||
'group_id' => group.to_global_id.to_s,
|
||||
'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s, subgroup_member.user.to_global_id.to_s],
|
||||
'access_level' => 'GUEST'
|
||||
}
|
||||
end
|
||||
|
||||
it 'does not update the members' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
error = Mutations::Members::Groups::BulkUpdate::INVALID_MEMBERS_ERROR
|
||||
expect(json_response['errors'].first['message']).to include(error)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when members count is more than the allowed limit' do
|
||||
let(:max_members_update_limit) { 1 }
|
||||
|
||||
before do
|
||||
stub_const('Mutations::Members::Groups::BulkUpdate::MAX_MEMBERS_UPDATE_LIMIT', max_members_update_limit)
|
||||
end
|
||||
|
||||
it 'does not update the members' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
error = Mutations::Members::Groups::BulkUpdate::MAX_MEMBERS_UPDATE_ERROR
|
||||
expect(json_response['errors'].first['message']).to include(error)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the update service raises access denied error' do
|
||||
before do
|
||||
allow_next_instance_of(Members::UpdateService) do |instance|
|
||||
allow(instance).to receive(:execute).and_raise(Gitlab::Access::AccessDeniedError)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not update the members' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
expect(mutation_response['groupMembers']).to be_nil
|
||||
expect(mutation_response['errors'])
|
||||
.to contain_exactly("Unable to update members, please check user permissions.")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the update service returns an error message' do
|
||||
before do
|
||||
allow_next_instance_of(Members::UpdateService) do |instance|
|
||||
error_result = {
|
||||
message: 'Expires at cannot be a date in the past',
|
||||
status: :error,
|
||||
members: [group_member1]
|
||||
}
|
||||
allow(instance).to receive(:execute).and_return(error_result)
|
||||
end
|
||||
end
|
||||
|
||||
it 'will pass through the error' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
expect(mutation_response['groupMembers'].first['id']).to eq(group_member1.to_global_id.to_s)
|
||||
expect(mutation_response['errors']).to contain_exactly('Expires at cannot be a date in the past')
|
||||
end
|
||||
end
|
||||
end
|
||||
it_behaves_like 'members bulk update mutation'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'ProjectMemberBulkUpdate', feature_category: :projects do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:parent_group) { create(:group) }
|
||||
let_it_be(:parent_group_member) { create(:group_member, group: parent_group) }
|
||||
let_it_be(:project) { create(:project, group: parent_group) }
|
||||
let_it_be(:source) { project }
|
||||
let_it_be(:member_type) { :project_member }
|
||||
let_it_be(:mutation_name) { :project_member_bulk_update }
|
||||
let_it_be(:source_id_key) { 'project_id' }
|
||||
let_it_be(:response_member_field) { 'projectMembers' }
|
||||
|
||||
it_behaves_like 'members bulk update mutation'
|
||||
end
|
||||
|
|
@ -34,10 +34,10 @@ RSpec.shared_context 'project navbar structure' do
|
|||
_('Commits'),
|
||||
_('Branches'),
|
||||
_('Tags'),
|
||||
_('Contributors'),
|
||||
_('Contributor statistics'),
|
||||
_('Graph'),
|
||||
_('Compare'),
|
||||
(_('Locked Files') if Gitlab.ee?)
|
||||
_('Compare revisions'),
|
||||
(_('Locked files') if Gitlab.ee?)
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'members bulk update mutation' do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:user1) { create(:user) }
|
||||
let_it_be(:user2) { create(:user) }
|
||||
let_it_be(:member1) { create(member_type, source: source, user: user1) }
|
||||
let_it_be(:member2) { create(member_type, source: source, user: user2) }
|
||||
|
||||
let(:extra_params) { { expires_at: 10.days.from_now } }
|
||||
let(:input_params) { input.merge(extra_params) }
|
||||
let(:mutation) { graphql_mutation(mutation_name, input_params) }
|
||||
let(:mutation_response) { graphql_mutation_response(mutation_name) }
|
||||
|
||||
let(:input) do
|
||||
{
|
||||
source_id_key => source.to_global_id.to_s,
|
||||
'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s],
|
||||
'access_level' => 'GUEST'
|
||||
}
|
||||
end
|
||||
|
||||
context 'when user is not logged-in' do
|
||||
it_behaves_like 'a mutation that returns a top-level access error'
|
||||
end
|
||||
|
||||
context 'when user is not an owner' do
|
||||
before do
|
||||
source.add_developer(current_user)
|
||||
end
|
||||
|
||||
it_behaves_like 'a mutation that returns a top-level access error'
|
||||
end
|
||||
|
||||
context 'when user is an owner' do
|
||||
before do
|
||||
source.add_owner(current_user)
|
||||
end
|
||||
|
||||
shared_examples 'updates the user access role' do
|
||||
specify do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
new_access_levels = mutation_response[response_member_field].map do |member|
|
||||
member['accessLevel']['integerValue']
|
||||
end
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(mutation_response['errors']).to be_empty
|
||||
expect(new_access_levels).to all(be Gitlab::Access::GUEST)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'updates the user access role'
|
||||
|
||||
context 'when inherited members are passed' do
|
||||
let(:input) do
|
||||
{
|
||||
source_id_key => source.to_global_id.to_s,
|
||||
'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s, parent_group_member.user.to_global_id.to_s],
|
||||
'access_level' => 'GUEST'
|
||||
}
|
||||
end
|
||||
|
||||
it 'does not update the members' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
error = Mutations::Members::BulkUpdateBase::INVALID_MEMBERS_ERROR
|
||||
expect(json_response['errors'].first['message']).to include(error)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when members count is more than the allowed limit' do
|
||||
let(:max_members_update_limit) { 1 }
|
||||
|
||||
before do
|
||||
stub_const('Mutations::Members::BulkUpdateBase::MAX_MEMBERS_UPDATE_LIMIT', max_members_update_limit)
|
||||
end
|
||||
|
||||
it 'does not update the members' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
error = Mutations::Members::BulkUpdateBase::MAX_MEMBERS_UPDATE_ERROR
|
||||
expect(json_response['errors'].first['message']).to include(error)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the update service raises access denied error' do
|
||||
before do
|
||||
allow_next_instance_of(Members::UpdateService) do |instance|
|
||||
allow(instance).to receive(:execute).and_raise(Gitlab::Access::AccessDeniedError)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not update the members' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
expect(mutation_response[response_member_field]).to be_nil
|
||||
expect(mutation_response['errors'])
|
||||
.to contain_exactly("Unable to update members, please check user permissions.")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the update service returns an error message' do
|
||||
before do
|
||||
allow_next_instance_of(Members::UpdateService) do |instance|
|
||||
error_result = {
|
||||
message: 'Expires at cannot be a date in the past',
|
||||
status: :error,
|
||||
members: [member1]
|
||||
}
|
||||
allow(instance).to receive(:execute).and_return(error_result)
|
||||
end
|
||||
end
|
||||
|
||||
it 'will pass through the error' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
||||
expect(mutation_response[response_member_field].first['id']).to eq(member1.to_global_id.to_s)
|
||||
expect(mutation_response['errors']).to contain_exactly('Expires at cannot be a date in the past')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -106,11 +106,11 @@ RSpec.describe 'layouts/nav/sidebar/_project', feature_category: :navigation do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Contributors' do
|
||||
describe 'Contributor statistics' do
|
||||
it 'has a link to the project contributors path' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_link('Contributors', href: project_graph_path(project, current_ref, ref_type: 'heads'))
|
||||
expect(rendered).to have_link('Contributor statistics', href: project_graph_path(project, current_ref, ref_type: 'heads'))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -122,11 +122,11 @@ RSpec.describe 'layouts/nav/sidebar/_project', feature_category: :navigation do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Compare' do
|
||||
describe 'Compare revisions' do
|
||||
it 'has a link to the project compare path' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_link('Compare', href: project_compare_index_path(project, from: project.repository.root_ref, to: current_ref))
|
||||
expect(rendered).to have_link('Compare revisions', href: project_compare_index_path(project, from: project.repository.root_ref, to: current_ref))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue