Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-05-02 15:10:10 +00:00
parent 610d783b61
commit f62efc3864
88 changed files with 499 additions and 600 deletions

View File

@ -108,7 +108,7 @@ export default {
by
<user-avatar-image
css-classes="ide-status-avatar"
:size="18"
:size="16"
:img-src="latestPipeline && latestPipeline.commit.author_gravatar_url"
:img-alt="lastCommit.author_name"
:tooltip-text="lastCommit.author_name"

View File

@ -132,6 +132,8 @@ export const TOKEN_TYPE_CONFIDENTIAL = 'confidential';
export const TOKEN_TYPE_ITERATION = 'iteration';
export const TOKEN_TYPE_EPIC = 'epic_id';
export const TOKEN_TYPE_WEIGHT = 'weight';
export const TOKEN_TYPE_CONTACT = 'crm_contact';
export const TOKEN_TYPE_ORGANIZATION = 'crm_organization';
export const filters = {
[TOKEN_TYPE_AUTHOR]: {
@ -294,4 +296,24 @@ export const filters = {
},
},
},
[TOKEN_TYPE_CONTACT]: {
[API_PARAM]: {
[NORMAL_FILTER]: 'crmContactId',
},
[URL_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'crm_contact_id',
},
},
},
[TOKEN_TYPE_ORGANIZATION]: {
[API_PARAM]: {
[NORMAL_FILTER]: 'crmOrganizationId',
},
[URL_PARAM]: {
[OPERATOR_IS]: {
[NORMAL_FILTER]: 'crm_organization_id',
},
},
},
};

View File

@ -20,6 +20,8 @@ query getIssues(
$releaseTag: [String!]
$releaseTagWildcardId: ReleaseTagWildcardId
$types: [IssueType!]
$crmContactId: String
$crmOrganizationId: String
$not: NegatedIssueFilterInput
$beforeCursor: String
$afterCursor: String
@ -43,6 +45,8 @@ query getIssues(
milestoneWildcardId: $milestoneWildcardId
myReactionEmoji: $myReactionEmoji
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
before: $beforeCursor
after: $afterCursor
@ -76,6 +80,8 @@ query getIssues(
releaseTag: $releaseTag
releaseTagWildcardId: $releaseTagWildcardId
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
before: $beforeCursor
after: $afterCursor

View File

@ -14,6 +14,8 @@ query getIssuesCount(
$releaseTag: [String!]
$releaseTagWildcardId: ReleaseTagWildcardId
$types: [IssueType!]
$crmContactId: String
$crmOrganizationId: String
$not: NegatedIssueFilterInput
) {
group(fullPath: $fullPath) @skip(if: $isProject) {
@ -32,6 +34,8 @@ query getIssuesCount(
milestoneWildcardId: $milestoneWildcardId
myReactionEmoji: $myReactionEmoji
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
) {
count
@ -50,6 +54,8 @@ query getIssuesCount(
milestoneWildcardId: $milestoneWildcardId
myReactionEmoji: $myReactionEmoji
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
) {
count
@ -68,6 +74,8 @@ query getIssuesCount(
milestoneWildcardId: $milestoneWildcardId
myReactionEmoji: $myReactionEmoji
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
) {
count
@ -90,6 +98,8 @@ query getIssuesCount(
releaseTag: $releaseTag
releaseTagWildcardId: $releaseTagWildcardId
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
) {
count
@ -109,6 +119,8 @@ query getIssuesCount(
releaseTag: $releaseTag
releaseTagWildcardId: $releaseTagWildcardId
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
) {
count
@ -128,6 +140,8 @@ query getIssuesCount(
releaseTag: $releaseTag
releaseTagWildcardId: $releaseTagWildcardId
types: $types
crmContactId: $crmContactId
crmOrganizationId: $crmOrganizationId
not: $not
) {
count

View File

@ -16,19 +16,11 @@ module Groups
private
def releases
if Feature.enabled?(:group_releases_finder_inoperator)
Releases::GroupReleasesFinder
.new(@group, current_user)
.execute(preload: false)
.page(params[:page])
.per(30)
else
ReleasesFinder
.new(@group, current_user, { include_subgroups: true })
.execute(preload: false)
.page(params[:page])
.per(30)
end
Releases::GroupReleasesFinder
.new(@group, current_user)
.execute(preload: false)
.page(params[:page])
.per(30)
end
end
end

View File

@ -29,28 +29,14 @@ class ReleasesFinder
Release.where(project_id: projects).where.not(tag: nil) # rubocop: disable CodeReuse/ActiveRecord
end
def include_subgroups?
params.fetch(:include_subgroups, false)
end
def projects
strong_memoize(:projects) do
if parent.is_a?(Project)
Ability.allowed?(current_user, :read_release, parent) ? [parent] : []
elsif parent.is_a?(Group)
Ability.allowed?(current_user, :read_release, parent) ? accessible_projects : []
end
end
end
def accessible_projects
if include_subgroups?
Project.for_group_and_its_subgroups(parent)
else
parent.projects
end
end
# rubocop: disable CodeReuse/ActiveRecord
def by_tag(releases)
return releases unless params[:tag].present?

View File

@ -68,6 +68,12 @@ module IssueResolverArguments
description: 'Negated arguments.',
prepare: ->(negated_args, ctx) { negated_args.to_h },
required: false
argument :crm_contact_id, GraphQL::Types::String,
required: false,
description: 'ID of a contact assigned to the issues.'
argument :crm_organization_id, GraphQL::Types::String,
required: false,
description: 'ID of an organization assigned to the issues.'
end
def resolve_with_lookahead(**args)

View File

@ -27,18 +27,11 @@ module Types
field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :version, GraphQL::Types::String, null: true, description: 'Version string.'
field :versions, ::Types::Packages::PackageType.connection_type, null: true,
description: 'Other versions of the package.',
deprecated: { reason: 'This field is now only returned in the PackageDetailsType', milestone: '13.11' }
def project
Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
end
def versions
[]
end
def can_destroy
Ability.allowed?(current_user, :destroy_package, object)
end

View File

@ -99,17 +99,6 @@ module Types
argument :id, ::Types::GlobalIDType[::MergeRequest], required: true, description: 'Global ID of the merge request.'
end
field :instance_statistics_measurements,
type: Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type,
null: true,
description: 'Get statistics on the instance.',
resolver: Resolvers::Admin::Analytics::UsageTrends::MeasurementsResolver,
deprecated: {
reason: :renamed,
replacement: 'Query.usageTrendsMeasurements',
milestone: '13.10'
}
field :usage_trends_measurements, Types::Admin::Analytics::UsageTrends::MeasurementType.connection_type,
null: true,
description: 'Get statistics on the instance.',

View File

@ -520,7 +520,7 @@ module Issuable
changes.merge!(hook_association_changes(old_associations))
end
Gitlab::HookData::IssuableBuilder.new(self).build(user: user, changes: changes)
Gitlab::DataBuilder::Issuable.new(self).build(user: user, changes: changes)
end
def labels_array

View File

@ -1,8 +0,0 @@
---
name: group_releases_finder_inoperator
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80093
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355463
milestone: '14.9'
type: development
group: group::release
default_enabled: false

View File

@ -0,0 +1,16 @@
- name: "Removed feature flag PUSH_RULES_SUPERSEDE_CODE_OWNERS" # The name of the feature to be deprecated
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true
reporter: tlinz # GitLab username of the person reporting the deprecation
body: | # Do not modify this line, instead modify the lines below.
The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` has been removed in GitLab 15.0. From now on, push rules will supersede CODEOWNERS. The CODEOWNERS feature is no longer available for access control.
# The following items are not published on the docs page, but may be used in the future.
stage: create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -3,7 +3,7 @@ table_name: user_interacted_projects
classes:
- UserInteractedProject
feature_categories:
- product_analytics
description: TODO
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/43b74afd8656df8228c19d5e5e6aee9f87abc244
- projects
description: Tracks which projects a given user has actively interacted with
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17327
milestone: '10.6'

View File

@ -181,29 +181,6 @@ Fields related to Instance Security Dashboard.
Returns [`InstanceSecurityDashboard`](#instancesecuritydashboard).
### `Query.instanceStatisticsMeasurements`
Get statistics on the instance.
WARNING:
**Deprecated** in 13.10.
This was renamed.
Use: [`Query.usageTrendsMeasurements`](#queryusagetrendsmeasurements).
Returns [`UsageTrendsMeasurementConnection`](#usagetrendsmeasurementconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="queryinstancestatisticsmeasurementsidentifier"></a>`identifier` | [`MeasurementIdentifier!`](#measurementidentifier) | Type of measurement or statistics to retrieve. |
| <a id="queryinstancestatisticsmeasurementsrecordedafter"></a>`recordedAfter` | [`Time`](#time) | Measurement recorded after this date. |
| <a id="queryinstancestatisticsmeasurementsrecordedbefore"></a>`recordedBefore` | [`Time`](#time) | Measurement recorded before this date. |
### `Query.issue`
Find an issue.
@ -11578,6 +11555,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupissuesconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter for confidential issues. If "false", excludes confidential issues. If "true", returns only confidential issues. |
| <a id="groupissuescreatedafter"></a>`createdAfter` | [`Time`](#time) | Issues created after this date. |
| <a id="groupissuescreatedbefore"></a>`createdBefore` | [`Time`](#time) | Issues created before this date. |
| <a id="groupissuescrmcontactid"></a>`crmContactId` | [`String`](#string) | ID of a contact assigned to the issues. |
| <a id="groupissuescrmorganizationid"></a>`crmOrganizationId` | [`String`](#string) | ID of an organization assigned to the issues. |
| <a id="groupissuesepicid"></a>`epicId` | [`String`](#string) | ID of an epic associated with the issues, "none" and "any" values are supported. |
| <a id="groupissuesiid"></a>`iid` | [`String`](#string) | IID of the issue. For example, "1". |
| <a id="groupissuesiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example, `["1", "2"]`. |
@ -13933,7 +13912,6 @@ Represents a package in the Package Registry. Note that this type is in beta and
| <a id="packagetags"></a>`tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. (see [Connections](#connections)) |
| <a id="packageupdatedat"></a>`updatedAt` | [`Time!`](#time) | Date of most recent update. |
| <a id="packageversion"></a>`version` | [`String`](#string) | Version string. |
| <a id="packageversions"></a>`versions` **{warning-solid}** | [`PackageConnection`](#packageconnection) | **Deprecated** in 13.11. This field is now only returned in the PackageDetailsType. |
### `PackageComposerJsonType`
@ -14814,6 +14792,8 @@ Returns [`Issue`](#issue).
| <a id="projectissueconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter for confidential issues. If "false", excludes confidential issues. If "true", returns only confidential issues. |
| <a id="projectissuecreatedafter"></a>`createdAfter` | [`Time`](#time) | Issues created after this date. |
| <a id="projectissuecreatedbefore"></a>`createdBefore` | [`Time`](#time) | Issues created before this date. |
| <a id="projectissuecrmcontactid"></a>`crmContactId` | [`String`](#string) | ID of a contact assigned to the issues. |
| <a id="projectissuecrmorganizationid"></a>`crmOrganizationId` | [`String`](#string) | ID of an organization assigned to the issues. |
| <a id="projectissueepicid"></a>`epicId` | [`String`](#string) | ID of an epic associated with the issues, "none" and "any" values are supported. |
| <a id="projectissueiid"></a>`iid` | [`String`](#string) | IID of the issue. For example, "1". |
| <a id="projectissueiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example, `["1", "2"]`. |
@ -14854,6 +14834,8 @@ Returns [`IssueStatusCountsType`](#issuestatuscountstype).
| <a id="projectissuestatuscountsconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter for confidential issues. If "false", excludes confidential issues. If "true", returns only confidential issues. |
| <a id="projectissuestatuscountscreatedafter"></a>`createdAfter` | [`Time`](#time) | Issues created after this date. |
| <a id="projectissuestatuscountscreatedbefore"></a>`createdBefore` | [`Time`](#time) | Issues created before this date. |
| <a id="projectissuestatuscountscrmcontactid"></a>`crmContactId` | [`String`](#string) | ID of a contact assigned to the issues. |
| <a id="projectissuestatuscountscrmorganizationid"></a>`crmOrganizationId` | [`String`](#string) | ID of an organization assigned to the issues. |
| <a id="projectissuestatuscountsiid"></a>`iid` | [`String`](#string) | IID of the issue. For example, "1". |
| <a id="projectissuestatuscountsiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example, `["1", "2"]`. |
| <a id="projectissuestatuscountslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to this issue. |
@ -14891,6 +14873,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectissuesconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter for confidential issues. If "false", excludes confidential issues. If "true", returns only confidential issues. |
| <a id="projectissuescreatedafter"></a>`createdAfter` | [`Time`](#time) | Issues created after this date. |
| <a id="projectissuescreatedbefore"></a>`createdBefore` | [`Time`](#time) | Issues created before this date. |
| <a id="projectissuescrmcontactid"></a>`crmContactId` | [`String`](#string) | ID of a contact assigned to the issues. |
| <a id="projectissuescrmorganizationid"></a>`crmOrganizationId` | [`String`](#string) | ID of an organization assigned to the issues. |
| <a id="projectissuesepicid"></a>`epicId` | [`String`](#string) | ID of an epic associated with the issues, "none" and "any" values are supported. |
| <a id="projectissuesiid"></a>`iid` | [`String`](#string) | IID of the issue. For example, "1". |
| <a id="projectissuesiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example, `["1", "2"]`. |

View File

@ -297,7 +297,7 @@ it('tests a promise rejection', async () => {
You can also simply return a promise from the test function.
Using the `done` and `done.fail` callbacks is discouraged when working with
promises. They should only be used when testing callback-based code.
promises. They should not be used.
**Bad**:
@ -487,15 +487,17 @@ If the application triggers an event that you need to wait for in your test, reg
the assertions:
```javascript
it('waits for an event', done => {
it('waits for an event', () => {
eventHub.$once('someEvent', eventHandler);
someFunction();
function eventHandler() {
expect(something).toBe('done');
done();
}
return new Promise((resolve) => {
function expectEventHandler() {
expect(something).toBe('done');
resolve();
}
});
});
```

View File

@ -1049,13 +1049,6 @@ follow the normal directions and generate a self-signed SSL certificate:
sudo chmod o-r gitlab.key
```
WARNING:
The `self_signed_cert` variable is
[deprecated and redundant](https://gitlab.com/gitlab-org/gitlab-shell/-/issues/120).
It is set to `false` by default, but still accepts self-signed certificates. Setting
this value to `true` allows any certificate to be accepted, and can make
machine-in-the-middle attacks possible.
### Enable Reply by email
See the ["Reply by email" documentation](../administration/reply_by_email.md) for more information on how to set this up.

View File

@ -119,6 +119,16 @@ In GraphQL, there are two `pipelines` fields that you can use in a [`PackageDeta
To mitigate possible performance problems, we will remove the `versions` field's `pipelines` field in GitLab 15.0. Although you will no longer be able to get all pipelines for all versions of a package, you can still get the pipelines of a single version through the remaining `pipelines` field for that version.
### Removed feature flag PUSH_RULES_SUPERSEDE_CODE_OWNERS
WARNING:
This feature was changed or removed in 15.0
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` has been removed in GitLab 15.0. From now on, push rules will supersede CODEOWNERS. The CODEOWNERS feature is no longer available for access control.
### Test coverage project CI/CD setting
WARNING:

View File

@ -228,10 +228,19 @@ This error can occur when a firewall performs a `Deep SSH Inspection` on outgoin
If you receive this error after creating a new project using
[GitLab CI/CD for external repositories](../../../../ci/ci_cd_for_external_repos/):
```plaintext
"2:fetch remote: "fatal: could not read Username for 'https://bitbucket.org':
terminal prompts disabled\n": exit status 128."
```
- In Bitbucket Cloud:
```plaintext
"2:fetch remote: "fatal: could not read Username for 'https://bitbucket.org':
terminal prompts disabled\n": exit status 128."
```
- In Bitbucket Server (self-managed):
```plaintext
"2:fetch remote: "fatal: could not read Username for 'https://lab.example.com':
terminal prompts disabled\n": exit status 128.
```
Check if the repository owner is specified in the URL of your mirrored repository:
@ -239,13 +248,21 @@ Check if the repository owner is specified in the URL of your mirrored repositor
1. On the left sidebar, select **Settings > Repository**.
1. Expand **Mirroring repositories**.
1. If no repository owner is specified, delete and add the URL again in this format,
replacing `OWNER`, `ACCOUNTNAME`, and `REPONAME` with your values:
replacing `OWNER`, `ACCOUNTNAME`, `PATH_TO_REPO`, and `REPONAME` with your values:
```plaintext
https://OWNER@bitbucket.org/ACCOUNTNAME/REPONAME.git
```
- In Bitbucket Cloud:
When connecting to the repository for mirroring, Bitbucket requires the repository owner in the string.
```plaintext
https://OWNER@bitbucket.org/ACCOUNTNAME/REPONAME.git
```
- In Bitbucket Server (self-managed):
```plaintext
https://OWNER@lab.example.com/PATH_TO_REPO/REPONAME.git
```
When connecting to the Cloud or self-managed Bitbucket repository for mirroring, the repository owner is required in the string.
### Pull mirror is missing LFS files

View File

@ -30,8 +30,6 @@ module API
use :pagination
end
get ":id/releases" do
not_found! unless Feature.enabled?(:group_releases_finder_inoperator)
finder_options = {
sort: params[:sort]
}

View File

@ -1,11 +1,15 @@
# frozen_string_literal: true
module Gitlab
module HookData
class IssuableBuilder < BaseBuilder
module DataBuilder
class Issuable
CHANGES_KEYS = %i[previous current].freeze
alias_method :issuable, :object
attr_reader :issuable
def initialize(issuable)
@issuable = issuable
end
def build(user: nil, changes: {})
hook_data = {

View File

@ -43,7 +43,7 @@ module Gitlab
TRANSLATION_LEVELS = {
'bg' => 0,
'cs_CZ' => 0,
'da_DK' => 44,
'da_DK' => 43,
'de' => 14,
'en' => 100,
'eo' => 0,
@ -53,17 +53,17 @@ module Gitlab
'gl_ES' => 0,
'id_ID' => 0,
'it' => 1,
'ja' => 34,
'ja' => 33,
'ko' => 12,
'nb_NO' => 29,
'nl_NL' => 0,
'pl_PL' => 4,
'pt_BR' => 50,
'ro_RO' => 36,
'ru' => 31,
'ro_RO' => 58,
'ru' => 30,
'tr_TR' => 13,
'uk' => 46,
'zh_CN' => 97,
'uk' => 47,
'zh_CN' => 96,
'zh_HK' => 2,
'zh_TW' => 2
}.freeze

View File

@ -21,7 +21,6 @@ namespace :gitlab do
config = {
user: Gitlab.config.gitlab.user,
gitlab_url: gitlab_url,
http_settings: { self_signed_cert: false }.stringify_keys,
auth_file: File.join(user_home, ".ssh", "authorized_keys"),
log_level: "INFO",
audit_usernames: false

View File

@ -60,32 +60,6 @@ RSpec.describe Groups::ReleasesController do
end
end
context 'group_releases_finder_inoperator feature flag' do
before do
sign_in(guest)
end
it 'calls old code when disabled' do
stub_feature_flags(group_releases_finder_inoperator: false)
allow(ReleasesFinder).to receive(:new).and_call_original
index
expect(ReleasesFinder).to have_received(:new)
end
it 'calls new code when enabled' do
stub_feature_flags(group_releases_finder_inoperator: true)
allow(Releases::GroupReleasesFinder).to receive(:new).and_call_original
index
expect(Releases::GroupReleasesFinder).to have_received(:new)
end
end
context 'N+1 queries' do
it 'avoids N+1 database queries' do
control_count = ActiveRecord::QueryRecorder.new { subject }.count

View File

@ -33,7 +33,7 @@ RSpec.describe ProjectCommitCount do
allow(Gitlab::GitalyClient).to receive(:call).and_call_original
allow(Gitlab::GitalyClient).to receive(:call).with(anything, :commit_service, :count_commits, anything, anything).and_raise(e = StandardError.new('_message_'))
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(e, caller_info: :identifiable)
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(e, { caller_info: :identifiable })
expect(subject).to eq(42)
end

View File

@ -107,130 +107,4 @@ RSpec.describe ReleasesFinder do
it_behaves_like 'when a tag parameter is passed'
end
end
describe 'when parent is a group' do
context 'without subgroups' do
let(:project2) { create(:project, :repository, namespace: group) }
let!(:v6) { create(:release, project: project2, tag: 'v6') }
subject { described_class.new(group, user, params).execute(**args) }
it_behaves_like 'when the user is not part of the group'
context 'when the user is a project guest on one sibling project' do
before do
project.add_guest(user)
v1_0_0.update_attribute(:released_at, 3.days.ago)
v1_1_0.update_attribute(:released_at, 1.day.ago)
end
it 'does not return any releases' do
expect(subject.size).to eq(0)
expect(subject).to eq([])
end
end
context 'when the user is a guest on the group' do
before do
group.add_guest(user)
v1_0_0.update_attribute(:released_at, 3.days.ago)
v6.update_attribute(:released_at, 2.days.ago)
v1_1_0.update_attribute(:released_at, 1.day.ago)
end
it 'sorts by release date' do
expect(subject.size).to eq(3)
expect(subject).to eq([v1_1_0, v6, v1_0_0])
end
it_behaves_like 'when a tag parameter is passed'
end
end
describe 'with subgroups' do
let(:params) { { include_subgroups: true } }
subject { described_class.new(group, user, params).execute(**args) }
context 'with a single-level subgroup' do
let(:subgroup) { create :group, parent: group }
let(:project2) { create(:project, :repository, namespace: subgroup) }
let!(:v6) { create(:release, project: project2, tag: 'v6') }
it_behaves_like 'when the user is not part of the group'
context 'when the user a project guest in the subgroup project' do
before do
project2.add_guest(user)
end
it 'does not return any releases' do
expect(subject).to match_array([])
end
end
context 'when the user is a guest on the group' do
before do
group.add_guest(user)
v6.update_attribute(:released_at, 2.days.ago)
end
it 'returns all releases' do
expect(subject).to match_array([v1_1_0, v1_0_0, v6])
end
it_behaves_like 'when a tag parameter is passed'
end
end
context 'with a multi-level subgroup' do
let(:subgroup) { create :group, parent: group }
let(:subsubgroup) { create :group, parent: subgroup }
let(:project2) { create(:project, :repository, namespace: subgroup) }
let(:project3) { create(:project, :repository, namespace: subsubgroup) }
let!(:v6) { create(:release, project: project2, tag: 'v6') }
let!(:p3) { create(:release, project: project3, tag: 'p3') }
before do
v6.update_attribute(:released_at, 2.days.ago)
p3.update_attribute(:released_at, 3.days.ago)
end
it_behaves_like 'when the user is not part of the group'
context 'when the user a project guest in the subgroup and subsubgroup project' do
before do
project2.add_guest(user)
project3.add_guest(user)
end
it 'does not return any releases' do
expect(subject).to match_array([])
end
end
context 'when the user a project guest in the subsubgroup project' do
before do
project3.add_guest(user)
end
it 'does not return any releases' do
expect(subject).to match_array([])
end
end
context 'when the user a guest on the group' do
before do
group.add_guest(user)
end
it 'returns all releases' do
expect(subject).to match_array([v1_1_0, v6, v1_0_0, p3])
end
it_behaves_like 'when a tag parameter is passed'
end
end
end
end
end

View File

@ -1,5 +1,3 @@
const noop = () => {};
/**
* Helper for testing action with expected mutations inspired in
* https://vuex.vuejs.org/en/testing.html
@ -9,7 +7,6 @@ const noop = () => {};
* @param {Object} state will be provided to the action
* @param {Array} [expectedMutations=[]] mutations expected to be committed
* @param {Array} [expectedActions=[]] actions expected to be dispatched
* @param {Function} [done=noop] to be executed after the tests
* @return {Promise}
*
* @example
@ -27,20 +24,9 @@ const noop = () => {};
* { type: 'actionName', payload: {param: 'foobar'}},
* { type: 'actionName1'}
* ]
* done,
* );
*
* @example
* testAction(
* actions.actionName, // action
* { }, // mocked payload
* state, //state
* [ { type: types.MUTATION} ], // expected mutations
* [], // expected actions
* ).then(done)
* .catch(done.fail);
*
* @example
* await testAction({
* action: actions.actionName,
* payload: { deleteListId: 1 },
@ -56,24 +42,15 @@ export default (
stateArg,
expectedMutationsArg = [],
expectedActionsArg = [],
doneArg = noop,
) => {
let action = actionArg;
let payload = payloadArg;
let state = stateArg;
let expectedMutations = expectedMutationsArg;
let expectedActions = expectedActionsArg;
let done = doneArg;
if (typeof actionArg !== 'function') {
({
action,
payload,
state,
expectedMutations = [],
expectedActions = [],
done = noop,
} = actionArg);
({ action, payload, state, expectedMutations = [], expectedActions = [] } = actionArg);
}
const mutations = [];
@ -109,7 +86,6 @@ export default (
mutations: expectedMutations,
actions: expectedActions,
});
done();
};
const result = action(

View File

@ -4,8 +4,8 @@ import axios from '~/lib/utils/axios_utils';
import testActionFn from './vuex_action_helper';
const testActionFnWithOptionsArg = (...args) => {
const [action, payload, state, expectedMutations, expectedActions, done] = args;
return testActionFn({ action, payload, state, expectedMutations, expectedActions, done });
const [action, payload, state, expectedMutations, expectedActions] = args;
return testActionFn({ action, payload, state, expectedMutations, expectedActions });
};
describe.each([testActionFn, testActionFnWithOptionsArg])(
@ -14,7 +14,6 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
let originalExpect;
let assertion;
let mock;
const noop = () => {};
beforeEach(() => {
mock = new MockAdapter(axios);
@ -48,7 +47,7 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
assertion = { mutations: [], actions: [] };
testAction(action, examplePayload, exampleState);
return testAction(action, examplePayload, exampleState);
});
describe('given a sync action', () => {
@ -59,7 +58,7 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
assertion = { mutations: [{ type: 'MUTATION' }], actions: [] };
testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
return testAction(action, null, {}, assertion.mutations, assertion.actions);
});
it('mocks dispatching actions', () => {
@ -69,26 +68,21 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
assertion = { actions: [{ type: 'ACTION' }], mutations: [] };
testAction(action, null, {}, assertion.mutations, assertion.actions, noop);
return testAction(action, null, {}, assertion.mutations, assertion.actions);
});
it('works with done callback once finished', (done) => {
it('returns a promise', () => {
assertion = { mutations: [], actions: [] };
testAction(noop, null, {}, assertion.mutations, assertion.actions, done);
});
const promise = testAction(() => {}, null, {}, assertion.mutations, assertion.actions);
it('returns a promise', (done) => {
assertion = { mutations: [], actions: [] };
originalExpect(promise instanceof Promise).toBeTruthy();
testAction(noop, null, {}, assertion.mutations, assertion.actions)
.then(done)
.catch(done.fail);
return promise;
});
});
describe('given an async action (returning a promise)', () => {
let lastError;
const data = { FOO: 'BAR' };
const asyncAction = ({ commit, dispatch }) => {
@ -98,7 +92,6 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
.get(TEST_HOST)
.catch((error) => {
commit('ERROR');
lastError = error;
throw error;
})
.then(() => {
@ -107,46 +100,26 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
});
};
beforeEach(() => {
lastError = null;
});
it('works with done callback once finished', (done) => {
it('returns original data of successful promise while checking actions/mutations', async () => {
mock.onGet(TEST_HOST).replyOnce(200, 42);
assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
const res = await testAction(asyncAction, null, {}, assertion.mutations, assertion.actions);
originalExpect(res).toEqual(data);
});
it('returns original data of successful promise while checking actions/mutations', (done) => {
mock.onGet(TEST_HOST).replyOnce(200, 42);
assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
.then((res) => {
originalExpect(res).toEqual(data);
done();
})
.catch(done.fail);
});
it('returns original error of rejected promise while checking actions/mutations', (done) => {
it('returns original error of rejected promise while checking actions/mutations', async () => {
mock.onGet(TEST_HOST).replyOnce(500, '');
assertion = { mutations: [{ type: 'ERROR' }], actions: [{ type: 'ACTION' }] };
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions)
.then(done.fail)
.catch((error) => {
originalExpect(error).toBe(lastError);
done();
});
const err = testAction(asyncAction, null, {}, assertion.mutations, assertion.actions);
await originalExpect(err).rejects.toEqual(new Error('Request failed with status code 500'));
});
});
it('works with async actions not returning promises', (done) => {
it('works with actions not returning promises', () => {
const data = { FOO: 'BAR' };
const asyncAction = ({ commit, dispatch }) => {
@ -168,7 +141,7 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
testAction(asyncAction, null, {}, assertion.mutations, assertion.actions, done);
return testAction(asyncAction, null, {}, assertion.mutations, assertion.actions);
});
},
);

View File

@ -146,6 +146,8 @@ export const locationSearch = [
'not[epic_id]=34',
'weight=1',
'not[weight]=3',
'crm_contact_id=123',
'crm_organization_id=456',
].join('&');
export const locationSearchWithSpecialValues = [
@ -194,6 +196,8 @@ export const filteredTokens = [
{ type: 'epic_id', value: { data: '34', operator: OPERATOR_IS_NOT } },
{ type: 'weight', value: { data: '1', operator: OPERATOR_IS } },
{ type: 'weight', value: { data: '3', operator: OPERATOR_IS_NOT } },
{ type: 'crm_contact', value: { data: '123', operator: OPERATOR_IS } },
{ type: 'crm_organization', value: { data: '456', operator: OPERATOR_IS } },
{ type: 'filtered-search-term', value: { data: 'find' } },
{ type: 'filtered-search-term', value: { data: 'issues' } },
];
@ -222,6 +226,8 @@ export const apiParams = {
iterationId: ['4', '12'],
epicId: '12',
weight: '1',
crmContactId: '123',
crmOrganizationId: '456',
not: {
authorUsername: 'marge',
assigneeUsernames: ['patty', 'selma'],
@ -270,6 +276,8 @@ export const urlParams = {
'not[epic_id]': '34',
weight: '1',
'not[weight]': '3',
crm_contact_id: '123',
crm_organization_id: '456',
};
export const urlParamsWithSpecialValues = {

View File

@ -389,6 +389,34 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
describe 'filtering by crm' do
let_it_be(:organization) { create(:organization, group: group) }
let_it_be(:contact1) { create(:contact, group: group, organization: organization) }
let_it_be(:contact2) { create(:contact, group: group, organization: organization) }
let_it_be(:contact3) { create(:contact, group: group) }
let_it_be(:crm_issue1) { create(:issue, project: project) }
let_it_be(:crm_issue2) { create(:issue, project: project) }
let_it_be(:crm_issue3) { create(:issue, project: project) }
before_all do
create(:issue_customer_relations_contact, issue: crm_issue1, contact: contact1)
create(:issue_customer_relations_contact, issue: crm_issue2, contact: contact2)
create(:issue_customer_relations_contact, issue: crm_issue3, contact: contact3)
end
context 'contact' do
it 'returns only the issues for the contact' do
expect(resolve_issues({ crm_contact_id: contact1.id })).to contain_exactly(crm_issue1)
end
end
context 'organization' do
it 'returns only the issues for the contact' do
expect(resolve_issues({ crm_organization_id: organization.id })).to contain_exactly(crm_issue1, crm_issue2)
end
end
end
describe 'sorting' do
context 'when sorting by created' do
it 'sorts issues ascending' do

View File

@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['Package'] do
id name version package_type
created_at updated_at
project
tags pipelines metadata versions
tags pipelines metadata
status can_destroy
]

View File

@ -11,7 +11,7 @@ RSpec.describe CookiesHelper do
value = 'secure value'
expect_next_instance_of(ActionDispatch::Cookies::EncryptedKeyRotatingCookieJar) do |instance|
expect(instance).to receive(:[]=).with(key, httponly: true, secure: true, expires: expiration, value: value)
expect(instance).to receive(:[]=).with(key, { httponly: true, secure: true, expires: expiration, value: value })
end
helper.set_secure_cookie(key, value, httponly: true, expires: expiration, type: CookiesHelper::COOKIE_TYPE_ENCRYPTED)
@ -22,7 +22,7 @@ RSpec.describe CookiesHelper do
value = 'permanent value'
expect_next_instance_of(ActionDispatch::Cookies::PermanentCookieJar) do |instance|
expect(instance).to receive(:[]=).with(key, httponly: false, secure: false, expires: nil, value: value)
expect(instance).to receive(:[]=).with(key, { httponly: false, secure: false, expires: nil, value: value })
end
helper.set_secure_cookie(key, value, type: CookiesHelper::COOKIE_TYPE_PERMANENT)
@ -33,7 +33,7 @@ RSpec.describe CookiesHelper do
value = 'regular value'
expect_next_instance_of(ActionDispatch::Cookies::CookieJar) do |instance|
expect(instance).to receive(:[]=).with(key, httponly: false, secure: false, expires: nil, value: value)
expect(instance).to receive(:[]=).with(key, { httponly: false, secure: false, expires: nil, value: value })
end
helper.set_secure_cookie(key, value)

View File

@ -378,7 +378,7 @@ RSpec.describe UsersHelper do
it 'users matches the serialized json' do
entity = double
expect_next_instance_of(Admin::UserSerializer) do |instance|
expect(instance).to receive(:represent).with([user], current_user: user).and_return(entity)
expect(instance).to receive(:represent).with([user], { current_user: user }).and_return(entity)
end
expect(entity).to receive(:to_json).and_return("{\"username\":\"admin\"}")
expect(data[:users]).to eq "{\"username\":\"admin\"}"

View File

@ -65,7 +65,8 @@ RSpec.describe Atlassian::JiraConnect::Jwt::Asymmetric do
before do
allow(JWT).to receive(:decode).and_call_original
allow(JWT).to receive(:decode).with(
jwt, anything, true, aud: anything, verify_aud: true, iss: client_key, verify_iss: true, algorithm: 'RS256'
jwt, anything, true,
{ aud: anything, verify_aud: true, iss: client_key, verify_iss: true, algorithm: 'RS256' }
).and_raise(JWT::DecodeError)
end

View File

@ -8,9 +8,9 @@ RSpec.describe Constraints::FeatureConstrainer do
gate = stub_feature_flag_gate("an object")
expect(Feature).to receive(:enabled?)
.with(:feature_name, gate, default_enabled: true)
.with(:feature_name, gate, { default_enabled: true })
described_class.new(:feature_name, gate, default_enabled: true).matches?(double('request'))
described_class.new(:feature_name, gate, { default_enabled: true }).matches?(double('request'))
end
end
end

View File

@ -67,7 +67,7 @@ RSpec.describe Feature, stub_feature_flags: false do
expect(Gitlab::ProcessMemoryCache.cache_backend)
.to receive(:fetch)
.once
.with('flipper/v1/features', expires_in: 1.minute)
.with('flipper/v1/features', { expires_in: 1.minute })
.and_call_original
2.times do
@ -190,13 +190,13 @@ RSpec.describe Feature, stub_feature_flags: false do
expect(described_class.send(:l2_cache_backend))
.to receive(:fetch)
.once
.with(flipper_key, expires_in: 1.hour)
.with(flipper_key, { expires_in: 1.hour })
.and_call_original
expect(described_class.send(:l1_cache_backend))
.to receive(:fetch)
.once
.with(flipper_key, expires_in: 1.minute)
.with(flipper_key, { expires_in: 1.minute })
.and_call_original
2.times do

View File

@ -26,10 +26,12 @@ RSpec.describe Gitlab::Auth::Ldap::Adapter do
it 'searches with the proper options when searching by dn' do
expect(adapter).to receive(:ldap_search).with(
base: 'uid=johndoe,ou=users,dc=example,dc=com',
scope: Net::LDAP::SearchScope_BaseObject,
attributes: ldap_attributes,
filter: nil
{
base: 'uid=johndoe,ou=users,dc=example,dc=com',
scope: Net::LDAP::SearchScope_BaseObject,
attributes: ldap_attributes,
filter: nil
}
).and_return({})
adapter.users('dn', 'uid=johndoe,ou=users,dc=example,dc=com')

View File

@ -87,7 +87,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::Deployments do
it 'logs the error' do
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
instance_of(Gitlab::Ci::Limit::LimitExceededError),
project_id: project.id, plan: namespace.actual_plan_name
{ project_id: project.id, plan: namespace.actual_plan_name }
)
perform

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::HookData::IssuableBuilder do
RSpec.describe Gitlab::DataBuilder::Issuable do
let_it_be(:user) { create(:user) }
# This shared example requires a `builder` and `user` variable

View File

@ -1537,10 +1537,12 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:add_concurrent_index)
.with(:issues,
%w(gl_project_id),
{
unique: false,
name: 'index_on_issues_gl_project_id',
length: [],
order: [])
order: []
})
model.copy_indexes(:issues, :project_id, :gl_project_id)
end
@ -1564,10 +1566,12 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:add_concurrent_index)
.with(:issues,
%w(gl_project_id foobar),
{
unique: false,
name: 'index_on_issues_gl_project_id_foobar',
length: [],
order: [])
order: []
})
model.copy_indexes(:issues, :project_id, :gl_project_id)
end
@ -1591,11 +1595,13 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:add_concurrent_index)
.with(:issues,
%w(gl_project_id),
{
unique: false,
name: 'index_on_issues_gl_project_id',
length: [],
order: [],
where: 'foo')
where: 'foo'
})
model.copy_indexes(:issues, :project_id, :gl_project_id)
end
@ -1619,11 +1625,13 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:add_concurrent_index)
.with(:issues,
%w(gl_project_id),
{
unique: false,
name: 'index_on_issues_gl_project_id',
length: [],
order: [],
using: 'foo')
using: 'foo'
})
model.copy_indexes(:issues, :project_id, :gl_project_id)
end
@ -1647,11 +1655,13 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:add_concurrent_index)
.with(:issues,
%w(gl_project_id),
{
unique: false,
name: 'index_on_issues_gl_project_id',
length: [],
order: [],
opclass: { 'gl_project_id' => 'bar' })
opclass: { 'gl_project_id' => 'bar' }
})
model.copy_indexes(:issues, :project_id, :gl_project_id)
end
@ -1660,14 +1670,16 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
context 'using an index with multiple columns and custom operator classes' do
it 'copies the index' do
index = double(:index,
columns: %w(project_id foobar),
name: 'index_on_issues_project_id_foobar',
using: :gin,
where: nil,
opclasses: { 'project_id' => 'bar', 'foobar' => :gin_trgm_ops },
unique: false,
lengths: [],
orders: [])
{
columns: %w(project_id foobar),
name: 'index_on_issues_project_id_foobar',
using: :gin,
where: nil,
opclasses: { 'project_id' => 'bar', 'foobar' => :gin_trgm_ops },
unique: false,
lengths: [],
orders: []
})
allow(model).to receive(:indexes_for).with(:issues, 'project_id')
.and_return([index])
@ -1675,12 +1687,14 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:add_concurrent_index)
.with(:issues,
%w(gl_project_id foobar),
{
unique: false,
name: 'index_on_issues_gl_project_id_foobar',
length: [],
order: [],
opclass: { 'gl_project_id' => 'bar', 'foobar' => :gin_trgm_ops },
using: :gin)
using: :gin
})
model.copy_indexes(:issues, :project_id, :gl_project_id)
end
@ -1689,14 +1703,16 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
context 'using an index with multiple columns and a custom operator class on the non affected column' do
it 'copies the index' do
index = double(:index,
columns: %w(project_id foobar),
name: 'index_on_issues_project_id_foobar',
using: :gin,
where: nil,
opclasses: { 'foobar' => :gin_trgm_ops },
unique: false,
lengths: [],
orders: [])
{
columns: %w(project_id foobar),
name: 'index_on_issues_project_id_foobar',
using: :gin,
where: nil,
opclasses: { 'foobar' => :gin_trgm_ops },
unique: false,
lengths: [],
orders: []
})
allow(model).to receive(:indexes_for).with(:issues, 'project_id')
.and_return([index])
@ -1704,12 +1720,14 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(model).to receive(:add_concurrent_index)
.with(:issues,
%w(gl_project_id foobar),
{
unique: false,
name: 'index_on_issues_gl_project_id_foobar',
length: [],
order: [],
opclass: { 'foobar' => :gin_trgm_ops },
using: :gin)
using: :gin
})
model.copy_indexes(:issues, :project_id, :gl_project_id)
end

View File

@ -54,7 +54,7 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::IndexHelpers do
expect_add_concurrent_index_and_call_original(partition2_identifier, column_name, partition2_index)
expect(migration).to receive(:with_lock_retries).ordered.and_yield
expect(migration).to receive(:add_index).with(table_name, column_name, name: index_name).ordered.and_call_original
expect(migration).to receive(:add_index).with(table_name, column_name, { name: index_name }).ordered.and_call_original
migration.add_concurrent_partitioned_index(table_name, column_name, name: index_name)
@ -64,7 +64,7 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::IndexHelpers do
end
def expect_add_concurrent_index_and_call_original(table, column, index)
expect(migration).to receive(:add_concurrent_index).ordered.with(table, column, name: index)
expect(migration).to receive(:add_concurrent_index).ordered.with(table, column, { name: index })
.and_wrap_original { |_, table, column, options| connection.add_index(table, column, **options) }
end
end
@ -90,13 +90,13 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::IndexHelpers do
it 'forwards them to the index helper methods', :aggregate_failures do
expect(migration).to receive(:add_concurrent_index)
.with(partition1_identifier, column_name, name: partition1_index, where: 'x > 0', unique: true)
.with(partition1_identifier, column_name, { name: partition1_index, where: 'x > 0', unique: true })
expect(migration).to receive(:add_index)
.with(table_name, column_name, name: index_name, where: 'x > 0', unique: true)
.with(table_name, column_name, { name: index_name, where: 'x > 0', unique: true })
migration.add_concurrent_partitioned_index(table_name, column_name,
name: index_name, where: 'x > 0', unique: true)
{ name: index_name, where: 'x > 0', unique: true })
end
end

View File

@ -181,8 +181,10 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
expect(Gitlab::GithubImport::Logger)
.to receive(:warn)
.with(
message: "Validation failed: Line code can't be blank, Line code must be a valid line code, Position is incomplete",
'error.class': 'Gitlab::GithubImport::Importer::DiffNoteImporter::DiffNoteCreationError'
{
message: "Validation failed: Line code can't be blank, Line code must be a valid line code, Position is incomplete",
'error.class': 'Gitlab::GithubImport::Importer::DiffNoteImporter::DiffNoteCreationError'
}
)
expect { subject.execute }
@ -204,8 +206,10 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
expect(Gitlab::GithubImport::Logger)
.to receive(:warn)
.with(
message: 'Failed to create diff note file',
'error.class': 'DiffNote::NoteDiffFileCreationError'
{
message: 'Failed to create diff note file',
'error.class': 'DiffNote::NoteDiffFileCreationError'
}
)
expect { subject.execute }

View File

@ -48,7 +48,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsReviewsImporter do
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:pull_request_reviews, 'github/repo', merge_request.iid, page: 1)
.with(:pull_request_reviews, 'github/repo', merge_request.iid, { page: 1 })
.and_yield(page)
expect { |b| subject.each_object_to_import(&b) }
@ -67,7 +67,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsReviewsImporter do
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:pull_request_reviews, 'github/repo', merge_request.iid, page: 2)
.with(:pull_request_reviews, 'github/repo', merge_request.iid, { page: 2 })
subject.each_object_to_import {}
end

View File

@ -33,7 +33,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointDiffNotesImporter d
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:pull_request_comments, 'github/repo', merge_request.iid, page: 1)
.with(:pull_request_comments, 'github/repo', merge_request.iid, { page: 1 })
.and_yield(page)
expect { |b| subject.each_object_to_import(&b) }.to yield_with_args(note)
@ -56,7 +56,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointDiffNotesImporter d
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:pull_request_comments, 'github/repo', merge_request.iid, page: 2)
.with(:pull_request_comments, 'github/repo', merge_request.iid, { page: 2 })
subject.each_object_to_import {}
end

View File

@ -32,7 +32,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueNotesImporter
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:issue_comments, 'github/repo', issue.iid, page: 1)
.with(:issue_comments, 'github/repo', issue.iid, { page: 1 })
.and_yield(page)
expect { |b| subject.each_object_to_import(&b) }.to yield_with_args(note)
@ -55,7 +55,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueNotesImporter
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:issue_comments, 'github/repo', issue.iid, page: 2)
.with(:issue_comments, 'github/repo', issue.iid, { page: 2 })
subject.each_object_to_import {}
end

View File

@ -33,7 +33,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointMergeRequestNotesIm
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:issue_comments, 'github/repo', merge_request.iid, page: 1)
.with(:issue_comments, 'github/repo', merge_request.iid, { page: 1 })
.and_yield(page)
expect { |b| subject.each_object_to_import(&b) }.to yield_with_args(note)
@ -56,7 +56,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointMergeRequestNotesIm
expect(client)
.to receive(:each_page)
.exactly(:once) # ensure to be cached on the second call
.with(:issue_comments, 'github/repo', merge_request.iid, page: 2)
.with(:issue_comments, 'github/repo', merge_request.iid, { page: 2 })
subject.each_object_to_import {}
end

View File

@ -44,7 +44,7 @@ RSpec.describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_cache
it 'builds the cache of all project milestones' do
expect(Gitlab::Cache::Import::Caching)
.to receive(:write_multiple)
.with("github-import/milestone-finder/#{project.id}/1" => milestone.id)
.with({ "github-import/milestone-finder/#{project.id}/1" => milestone.id })
.and_call_original
finder.build_cache

View File

@ -87,19 +87,23 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'starting importer',
parallel: false,
project_id: project.id,
importer: 'Class'
{
message: 'starting importer',
parallel: false,
project_id: project.id,
importer: 'Class'
}
)
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'importer finished',
parallel: false,
project_id: project.id,
importer: 'Class'
{
message: 'importer finished',
parallel: false,
project_id: project.id,
importer: 'Class'
}
)
importer.execute
@ -118,20 +122,24 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'starting importer',
parallel: false,
project_id: project.id,
importer: 'Class'
{
message: 'starting importer',
parallel: false,
project_id: project.id,
importer: 'Class'
}
)
expect(Gitlab::Import::ImportFailureService)
.to receive(:track)
.with(
project_id: project.id,
exception: exception,
error_source: 'MyImporter',
fail_import: false,
metrics: true
{
project_id: project.id,
exception: exception,
error_source: 'MyImporter',
fail_import: false,
metrics: true
}
).and_call_original
expect { importer.execute }
@ -184,10 +192,12 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'starting importer',
parallel: false,
project_id: project.id,
importer: 'Class'
{
message: 'starting importer',
parallel: false,
project_id: project.id,
importer: 'Class'
}
)
expect(Gitlab::Import::ImportFailureService)

View File

@ -246,10 +246,10 @@ RSpec.describe Gitlab::HTTP do
context 'when :timeout is set' do
it 'does not set any default timeouts' do
expect(described_class).to receive(:httparty_perform_request).with(
Net::HTTP::Get, 'http://example.org', timeout: 1
Net::HTTP::Get, 'http://example.org', { timeout: 1 }
).and_call_original
described_class.get('http://example.org', timeout: 1)
described_class.get('http://example.org', { timeout: 1 })
end
end

View File

@ -64,19 +64,23 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
.to receive(:track_exception)
.with(
exception,
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
{
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
}
)
expect(Gitlab::Import::Logger)
.to receive(:error)
.with(
message: 'importer failed',
'error.message': 'some error',
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
{
message: 'importer failed',
'error.message': 'some error',
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
}
)
service.execute
@ -96,19 +100,23 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
.to receive(:track_exception)
.with(
exception,
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
{
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
}
)
expect(Gitlab::Import::Logger)
.to receive(:error)
.with(
message: 'importer failed',
'error.message': 'some error',
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
{
message: 'importer failed',
'error.message': 'some error',
project_id: project.id,
import_type: import_type,
source: 'SomeImporter'
}
)
service.execute

View File

@ -23,8 +23,8 @@ RSpec.describe Gitlab::Jira::Middleware do
describe '#call' do
it 'adjusts HTTP_AUTHORIZATION env when request from Jira DVCS user agent' do
expect(app).to receive(:call).with('HTTP_USER_AGENT' => jira_user_agent,
'HTTP_AUTHORIZATION' => 'Bearer hash-123')
expect(app).to receive(:call).with({ 'HTTP_USER_AGENT' => jira_user_agent,
'HTTP_AUTHORIZATION' => 'Bearer hash-123' })
middleware.call('HTTP_USER_AGENT' => jira_user_agent, 'HTTP_AUTHORIZATION' => 'token hash-123')
end

View File

@ -313,9 +313,9 @@ RSpec.describe Gitlab::JsonCache do
it 'passes options the underlying cache implementation' do
expect(backend).to receive(:write)
.with(expanded_key, "true", expires_in: 15.seconds)
.with(expanded_key, "true", { expires_in: 15.seconds })
cache.fetch(key, expires_in: 15.seconds) { true }
cache.fetch(key, { expires_in: 15.seconds }) { true }
end
context 'when the given key does not exist in the cache' do

View File

@ -171,9 +171,9 @@ RSpec.describe Gitlab::MarkdownCache::ActiveRecord::Extension do
expect(thing).to receive(:persisted?).and_return(true)
expect(thing).to receive(:update_columns)
.with("title_html" => updated_html,
.with({ "title_html" => updated_html,
"description_html" => "",
"cached_markdown_version" => cache_version)
"cached_markdown_version" => cache_version })
thing.refresh_markdown_cache!
end

View File

@ -35,7 +35,7 @@ RSpec.describe Gitlab::Metrics::Methods do
context 'metric is not cached' do
it 'calls fetch_metric' do
expect(subject).to receive(:init_metric).with(metric_type, metric_name, docstring: docstring)
expect(subject).to receive(:init_metric).with(metric_type, metric_name, { docstring: docstring })
subject.public_send(metric_name)
end

View File

@ -155,7 +155,7 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do
end
it 'captures the metrics for web only' do
expect(web_transaction).to receive(:observe).with(:gitlab_database_transaction_seconds, 0.23, db_config_name: db_config_name)
expect(web_transaction).to receive(:observe).with(:gitlab_database_transaction_seconds, 0.23, { db_config_name: db_config_name })
expect(background_transaction).not_to receive(:observe)
expect(background_transaction).not_to receive(:increment)
@ -195,7 +195,7 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do
end
it 'captures the metrics for web only' do
expect(background_transaction).to receive(:observe).with(:gitlab_database_transaction_seconds, 0.23, db_config_name: db_config_name)
expect(background_transaction).to receive(:observe).with(:gitlab_database_transaction_seconds, 0.23, { db_config_name: db_config_name })
expect(web_transaction).not_to receive(:observe)
expect(web_transaction).not_to receive(:increment)

View File

@ -23,9 +23,9 @@ RSpec.describe Gitlab::SidekiqDeathHandler, :clean_gitlab_redis_queues do
it 'uses the attributes from the worker' do
expect(described_class.counter)
.to receive(:increment)
.with(queue: 'test_queue', worker: 'TestWorker',
.with({ queue: 'test_queue', worker: 'TestWorker',
urgency: 'low', external_dependencies: 'yes',
feature_category: 'users', boundary: 'cpu')
feature_category: 'users', boundary: 'cpu' })
described_class.handler({ 'class' => 'TestWorker', 'queue' => 'test_queue' }, nil)
end
@ -39,9 +39,9 @@ RSpec.describe Gitlab::SidekiqDeathHandler, :clean_gitlab_redis_queues do
it 'uses blank attributes' do
expect(described_class.counter)
.to receive(:increment)
.with(queue: 'test_queue', worker: 'TestWorker',
.with({ queue: 'test_queue', worker: 'TestWorker',
urgency: '', external_dependencies: 'no',
feature_category: '', boundary: '')
feature_category: '', boundary: '' })
described_class.handler({ 'class' => 'TestWorker', 'queue' => 'test_queue' }, nil)
end

View File

@ -21,40 +21,40 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
.and_return('MergeWorker' => 'merge', 'Ci::BuildFinishedWorker' => 'default')
expect(completion_seconds_metric)
.to receive(:get).with(queue: 'merge',
.to receive(:get).with({ queue: 'merge',
worker: 'MergeWorker',
urgency: 'high',
external_dependencies: 'no',
feature_category: 'source_code_management',
boundary: '',
job_status: 'done')
job_status: 'done' })
expect(completion_seconds_metric)
.to receive(:get).with(queue: 'merge',
.to receive(:get).with({ queue: 'merge',
worker: 'MergeWorker',
urgency: 'high',
external_dependencies: 'no',
feature_category: 'source_code_management',
boundary: '',
job_status: 'fail')
job_status: 'fail' })
expect(completion_seconds_metric)
.to receive(:get).with(queue: 'default',
.to receive(:get).with({ queue: 'default',
worker: 'Ci::BuildFinishedWorker',
urgency: 'high',
external_dependencies: 'no',
feature_category: 'continuous_integration',
boundary: 'cpu',
job_status: 'done')
job_status: 'done' })
expect(completion_seconds_metric)
.to receive(:get).with(queue: 'default',
.to receive(:get).with({ queue: 'default',
worker: 'Ci::BuildFinishedWorker',
urgency: 'high',
external_dependencies: 'no',
feature_category: 'continuous_integration',
boundary: 'cpu',
job_status: 'fail')
job_status: 'fail' })
described_class.initialize_process_metrics
end

View File

@ -32,7 +32,7 @@ RSpec.describe AbuseReport do
end
it 'lets a worker delete the user' do
expect(DeleteUserWorker).to receive(:perform_async).with(user.id, subject.user.id, hard_delete: true)
expect(DeleteUserWorker).to receive(:perform_async).with(user.id, subject.user.id, { hard_delete: true })
subject.remove_user(deleted_by: user)
end

View File

@ -149,7 +149,7 @@ RSpec.describe CacheMarkdownField, :clean_gitlab_redis_cache do
it 'saves the changes' do
expect(thing)
.to receive(:save_markdown)
.with("description_html" => updated_html, "title_html" => "", "cached_markdown_version" => cache_version)
.with({ "description_html" => updated_html, "title_html" => "", "cached_markdown_version" => cache_version })
thing.refresh_markdown_cache!
end

View File

@ -474,11 +474,11 @@ RSpec.describe Issuable do
issue.update!(labels: [label])
issue.assignees << user
issue.spend_time(duration: 2, user_id: user.id, spent_at: Time.current)
expect(Gitlab::HookData::IssuableBuilder)
expect(Gitlab::DataBuilder::Issuable)
.to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build and does not set labels, assignees, nor total_time_spent' do
it 'delegates to Gitlab::DataBuilder::Issuable#build and does not set labels, assignees, nor total_time_spent' do
expect(builder).to receive(:build).with(
user: user,
changes: {})
@ -493,11 +493,11 @@ RSpec.describe Issuable do
before do
issue.update!(labels: [labels[1]])
expect(Gitlab::HookData::IssuableBuilder)
expect(Gitlab::DataBuilder::Issuable)
.to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
it 'delegates to Gitlab::DataBuilder::Issuable#build' do
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
@ -512,11 +512,11 @@ RSpec.describe Issuable do
before do
issue.spend_time(duration: 2, user_id: user.id, spent_at: Time.current)
issue.save!
expect(Gitlab::HookData::IssuableBuilder)
expect(Gitlab::DataBuilder::Issuable)
.to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
it 'delegates to Gitlab::DataBuilder::Issuable#build' do
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
@ -532,11 +532,11 @@ RSpec.describe Issuable do
before do
issue.assignees << user << user2
expect(Gitlab::HookData::IssuableBuilder)
expect(Gitlab::DataBuilder::Issuable)
.to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
it 'delegates to Gitlab::DataBuilder::Issuable#build' do
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
@ -554,11 +554,11 @@ RSpec.describe Issuable do
before do
merge_request.update!(assignees: [user])
merge_request.update!(assignees: [user, user2])
expect(Gitlab::HookData::IssuableBuilder)
expect(Gitlab::DataBuilder::Issuable)
.to receive(:new).with(merge_request).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
it 'delegates to Gitlab::DataBuilder::Issuable#build' do
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
@ -574,11 +574,11 @@ RSpec.describe Issuable do
before do
issue.update!(issuable_severity_attributes: { severity: 'low' })
expect(Gitlab::HookData::IssuableBuilder)
expect(Gitlab::DataBuilder::Issuable)
.to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
it 'delegates to Gitlab::DataBuilder::Issuable#build' do
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(
@ -596,10 +596,10 @@ RSpec.describe Issuable do
before do
issue.escalation_status.update!(status: acknowledged)
expect(Gitlab::HookData::IssuableBuilder).to receive(:new).with(issue).and_return(builder)
expect(Gitlab::DataBuilder::Issuable).to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build' do
it 'delegates to Gitlab::DataBuilder::Issuable#build' do
expect(builder).to receive(:build).with(
user: user,
changes: hash_including(

View File

@ -1833,7 +1833,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
it 'fetches the rollout status from the deployment platform' do
expect(environment.deployment_platform).to receive(:rollout_status)
.with(environment, pods: pods, deployments: deployments)
.with(environment, { pods: pods, deployments: deployments })
.and_return(:mock_rollout_status)
is_expected.to eq(:mock_rollout_status)

View File

@ -227,7 +227,7 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching do
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(instance_of(http_error), project_id: project.id)
.with(instance_of(http_error), { project_id: project.id })
is_expected.to eq(:error)
end

View File

@ -129,7 +129,7 @@ RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(instance_of(http_error), project_id: project.id)
.with(instance_of(http_error), { project_id: project.id })
is_expected.to eq(:error)
end

View File

@ -163,7 +163,7 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(instance_of(http_error), project_id: project.id)
.with(instance_of(http_error), { project_id: project.id })
is_expected.to eq(:error)
end

View File

@ -931,10 +931,12 @@ RSpec.describe Integrations::Jira do
expect(jira_integration).to receive(:log_error).with(
'Error sending message',
client_url: 'http://jira.example.com',
'exception.class' => anything,
'exception.message' => error_message,
'exception.backtrace' => anything
{
client_url: 'http://jira.example.com',
'exception.class' => anything,
'exception.message' => error_message,
'exception.backtrace' => anything
}
)
expect(jira_integration.test(nil)).to eq(success: false, result: error_message)

View File

@ -210,7 +210,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
.with(instance_of(Errno::ECONNREFUSED), { project_id: project.id })
is_expected.to eq(teamcity_url)
end
@ -260,7 +260,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
.with(instance_of(Errno::ECONNREFUSED), { project_id: project.id })
is_expected.to eq(:error)
end

View File

@ -185,7 +185,7 @@ RSpec.describe PerformanceMonitoring::PrometheusDashboard do
context 'dashboard has been found' do
it 'uses dashboard finder to find and load dashboard data and returns dashboard instance', :aggregate_failures do
expect(Gitlab::Metrics::Dashboard::Finder).to receive(:find).with(project, user, environment: environment, dashboard_path: path).and_return(status: :success, dashboard: json_content)
expect(Gitlab::Metrics::Dashboard::Finder).to receive(:find).with(project, user, { environment: environment, dashboard_path: path }).and_return(status: :success, dashboard: json_content)
dashboard_instance = described_class.find_for(project: project, user: user, path: path, options: { environment: environment })

View File

@ -65,9 +65,11 @@ RSpec.describe ProjectImportState, type: :model do
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger).to receive(:error).with(
error: 'ActiveRecord::ActiveRecordError',
message: 'Error setting import status to failed',
original_error: error_message
{
error: 'ActiveRecord::ActiveRecordError',
message: 'Error setting import status to failed',
original_error: error_message
}
)
end

View File

@ -38,12 +38,12 @@ RSpec.describe Shard do
expect(described_class)
.to receive(:find_by)
.with(name: 'new_shard')
.with({ name: 'new_shard' })
.and_return(nil, shard_created_by_others)
expect(described_class)
.to receive(:create)
.with(name: 'new_shard')
.with({ name: 'new_shard' })
.and_raise(ActiveRecord::RecordNotUnique, 'fail')
.once

View File

@ -5335,7 +5335,7 @@ RSpec.describe User do
let(:deleted_by) { create(:user) }
it 'blocks the user then schedules them for deletion if a hard delete is specified' do
expect(DeleteUserWorker).to receive(:perform_async).with(deleted_by.id, user.id, hard_delete: true)
expect(DeleteUserWorker).to receive(:perform_async).with(deleted_by.id, user.id, { hard_delete: true })
user.delete_async(deleted_by: deleted_by, params: { hard_delete: true })

View File

@ -65,32 +65,6 @@ RSpec.describe 'package details' do
end
end
context 'there are other versions of this package' do
let(:depth) { 3 }
let(:excluded) { %w[metadata project tags pipelines] } # to limit the query complexity
let_it_be(:siblings) { create_list(:composer_package, 2, project: project, name: composer_package.name) }
it 'includes the sibling versions' do
subject
expect(graphql_data_at(:package, :versions, :nodes)).to match_array(
siblings.map { |p| a_hash_including('id' => global_id_of(p)) }
)
end
context 'going deeper' do
let(:depth) { 6 }
it 'does not create a cycle of versions' do
subject
expect(graphql_data_at(:package, :versions, :nodes, :version)).to be_present
expect(graphql_data_at(:package, :versions, :nodes, :versions, :nodes)).to match_array [nil, nil]
end
end
end
context 'with package files pending destruction' do
let_it_be(:package_file) { create(:package_file, package: composer_package) }
let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: composer_package) }

View File

@ -1399,14 +1399,6 @@ RSpec.describe API::Releases do
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns not found unless :group_releases_finder_inoperator feature flag enabled' do
stub_feature_flags(group_releases_finder_inoperator: false)
get api("/groups/#{group1.id}/releases", admin)
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'when authenticated as guest' do

View File

@ -76,11 +76,13 @@ RSpec.describe AuditEventService do
it 'creates an authentication event' do
expect(AuthenticationEvent).to receive(:new).with(
user: user,
user_name: user.name,
ip_address: user.current_sign_in_ip,
result: AuthenticationEvent.results[:success],
provider: 'standard'
{
user: user,
user_name: user.name,
ip_address: user.current_sign_in_ip,
result: AuthenticationEvent.results[:success],
provider: 'standard'
}
).and_call_original
audit_service.for_authentication.security_event

View File

@ -26,11 +26,13 @@ RSpec.describe JiraConnect::SyncService do
def expect_log(type, message)
expect(Gitlab::IntegrationsLogger)
.to receive(type).with(
message: 'response from jira dev_info api',
integration: 'JiraConnect',
project_id: project.id,
project_path: project.full_path,
jira_response: message&.to_json
{
message: 'response from jira dev_info api',
integration: 'JiraConnect',
project_id: project.id,
project_path: project.full_path,
jira_response: message&.to_json
}
)
end

View File

@ -70,11 +70,13 @@ RSpec.describe MergeRequests::RebaseService do
it 'logs the error' do
expect(service).to receive(:log_error).with(exception: exception, message: described_class::REBASE_ERROR, save_message_on_model: true).and_call_original
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception,
class: described_class.to_s,
merge_request: merge_request_ref,
merge_request_id: merge_request.id,
message: described_class::REBASE_ERROR,
save_message_on_model: true).and_call_original
{
class: described_class.to_s,
merge_request: merge_request_ref,
merge_request_id: merge_request.id,
message: described_class::REBASE_ERROR,
save_message_on_model: true
}).and_call_original
service.execute(merge_request)
end

View File

@ -222,11 +222,13 @@ RSpec.describe MergeRequests::SquashService do
it 'logs the error' do
expect(service).to receive(:log_error).with(exception: exception, message: 'Failed to squash merge request').and_call_original
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception,
class: described_class.to_s,
merge_request: merge_request_ref,
merge_request_id: merge_request.id,
message: 'Failed to squash merge request',
save_message_on_model: false).and_call_original
{
class: described_class.to_s,
merge_request: merge_request_ref,
merge_request_id: merge_request.id,
message: 'Failed to squash merge request',
save_message_on_model: false
}).and_call_original
service.execute
end

View File

@ -429,10 +429,10 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService, :clean_gitlab_
end
# We will ping the container registry for all tags *except* for C because it's cached
expect(ContainerRegistry::Blob).to receive(:new).with(repository, "digest" => "sha256:configA").and_call_original
expect(ContainerRegistry::Blob).to receive(:new).with(repository, "digest" => "sha256:configB").twice.and_call_original
expect(ContainerRegistry::Blob).not_to receive(:new).with(repository, "digest" => "sha256:configC")
expect(ContainerRegistry::Blob).to receive(:new).with(repository, "digest" => "sha256:configD").and_call_original
expect(ContainerRegistry::Blob).to receive(:new).with(repository, { "digest" => "sha256:configA" }).and_call_original
expect(ContainerRegistry::Blob).to receive(:new).with(repository, { "digest" => "sha256:configB" }).twice.and_call_original
expect(ContainerRegistry::Blob).not_to receive(:new).with(repository, { "digest" => "sha256:configC" })
expect(ContainerRegistry::Blob).to receive(:new).with(repository, { "digest" => "sha256:configD" }).and_call_original
expect(subject).to include(cached_tags_count: 1)
end

View File

@ -18,11 +18,13 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
shared_examples 'logging a success response' do
it 'logs an info message' do
expect(service).to receive(:log_info).with(
service_class: 'Projects::ContainerRepository::DeleteTagsService',
message: 'deleted tags',
container_repository_id: repository.id,
project_id: repository.project_id,
deleted_tags_count: tags.size
{
service_class: 'Projects::ContainerRepository::DeleteTagsService',
message: 'deleted tags',
container_repository_id: repository.id,
project_id: repository.project_id,
deleted_tags_count: tags.size
}
)
subject

View File

@ -73,10 +73,10 @@ RSpec.describe Users::DestroyService do
allow(user).to receive(:personal_projects).and_return([])
expect_next_instance_of(Snippets::BulkDestroyService) do |bulk_destroy_service|
expect(bulk_destroy_service).to receive(:execute).with(hard_delete: true).and_call_original
expect(bulk_destroy_service).to receive(:execute).with({ hard_delete: true }).and_call_original
end
service.execute(user, hard_delete: true)
service.execute(user, { hard_delete: true })
end
it 'does not delete project snippets that the user is the author of' do

View File

@ -44,8 +44,10 @@ RSpec.shared_examples 'a controller that can serve LFS files' do |options = {}|
expect(controller).to receive(:send_file)
.with(
File.join(lfs_uploader.root, lfs_uploader.store_dir, lfs_uploader.filename),
filename: filename,
disposition: 'attachment')
{
filename: filename,
disposition: 'attachment'
})
subject

View File

@ -17,7 +17,7 @@ end
RSpec.shared_examples 'a successful manifest pull' do
it 'sends a file' do
expect(controller).to receive(:send_file).with(manifest.file.path, type: manifest.content_type)
expect(controller).to receive(:send_file).with(manifest.file.path, { type: manifest.content_type })
subject
end

View File

@ -13,7 +13,7 @@ RSpec.describe BuildFinishedWorker do
before do
stub_feature_flags(ci_build_finished_worker_namespace_changed: build.project)
expect(Ci::Build).to receive(:find_by).with(id: build.id).and_return(build)
expect(Ci::Build).to receive(:find_by).with({ id: build.id }).and_return(build)
end
it 'calculates coverage and calls hooks', :aggregate_failures do

View File

@ -11,7 +11,7 @@ RSpec.describe Ci::BuildFinishedWorker do
before do
stub_feature_flags(ci_build_finished_worker_namespace_changed: build.project)
expect(Ci::Build).to receive(:find_by).with(id: build.id).and_return(build)
expect(Ci::Build).to receive(:find_by).with({ id: build.id }).and_return(build)
end
it 'calculates coverage and calls hooks', :aggregate_failures do

View File

@ -83,19 +83,23 @@ RSpec.describe Gitlab::GithubImport::ObjectImporter, :aggregate_failures do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
github_identifiers: github_identifiers,
message: 'starting importer',
project_id: project.id,
importer: 'klass_name'
{
github_identifiers: github_identifiers,
message: 'starting importer',
project_id: project.id,
importer: 'klass_name'
}
)
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
github_identifiers: github_identifiers,
message: 'importer finished',
project_id: project.id,
importer: 'klass_name'
{
github_identifiers: github_identifiers,
message: 'importer finished',
project_id: project.id,
importer: 'klass_name'
}
)
worker.import(project, client, { 'number' => 10, 'github_id' => 1 })
@ -120,10 +124,12 @@ RSpec.describe Gitlab::GithubImport::ObjectImporter, :aggregate_failures do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
github_identifiers: github_identifiers,
message: 'starting importer',
project_id: project.id,
importer: 'klass_name'
{
github_identifiers: github_identifiers,
message: 'starting importer',
project_id: project.id,
importer: 'klass_name'
}
)
expect(Gitlab::Import::ImportFailureService)

View File

@ -38,17 +38,21 @@ RSpec.describe Gitlab::GithubImport::StageMethods do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'starting stage',
project_id: project.id,
import_stage: 'DummyStage'
{
message: 'starting stage',
project_id: project.id,
import_stage: 'DummyStage'
}
)
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'stage finished',
project_id: project.id,
import_stage: 'DummyStage'
{
message: 'stage finished',
project_id: project.id,
import_stage: 'DummyStage'
}
)
worker.perform(project.id)
@ -70,18 +74,22 @@ RSpec.describe Gitlab::GithubImport::StageMethods do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'starting stage',
project_id: project.id,
import_stage: 'DummyStage'
{
message: 'starting stage',
project_id: project.id,
import_stage: 'DummyStage'
}
)
expect(Gitlab::Import::ImportFailureService)
.to receive(:track)
.with(
project_id: project.id,
exception: exception,
error_source: 'DummyStage',
fail_import: false
{
project_id: project.id,
exception: exception,
error_source: 'DummyStage',
fail_import: false
}
).and_call_original
expect { worker.perform(project.id) }
@ -125,9 +133,11 @@ RSpec.describe Gitlab::GithubImport::StageMethods do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'starting stage',
project_id: project.id,
import_stage: 'DummyStage'
{
message: 'starting stage',
project_id: project.id,
import_stage: 'DummyStage'
}
)
expect(Gitlab::Import::ImportFailureService)

View File

@ -10,8 +10,8 @@ RSpec.describe CreateCommitSignatureWorker do
let(:x509_commit) { instance_double(Gitlab::X509::Commit) }
before do
allow(Project).to receive(:find_by).with(id: project.id).and_return(project)
allow(project).to receive(:commits_by).with(oids: commit_shas).and_return(commits)
allow(Project).to receive(:find_by).with({ id: project.id }).and_return(project)
allow(project).to receive(:commits_by).with({ oids: commit_shas }).and_return(commits)
end
subject { described_class.new.perform(commit_shas, project.id) }

View File

@ -16,9 +16,9 @@ RSpec.describe DeleteUserWorker do
it "uses symbolized keys" do
expect_next_instance_of(Users::DestroyService) do |service|
expect(service).to receive(:execute).with(user, test: "test")
expect(service).to receive(:execute).with(user, { test: "test" })
end
described_class.new.perform(current_user.id, user.id, "test" => "test")
described_class.new.perform(current_user.id, user.id, { "test" => "test" })
end
end

View File

@ -17,14 +17,16 @@ RSpec.describe Gitlab::GithubImport::Stage::FinishImportWorker do
expect(Gitlab::GithubImport::Logger)
.to receive(:info)
.with(
message: 'GitHub project import finished',
import_stage: 'Gitlab::GithubImport::Stage::FinishImportWorker',
object_counts: {
'fetched' => {},
'imported' => {}
},
project_id: project.id,
duration_s: 3.01
{
message: 'GitHub project import finished',
import_stage: 'Gitlab::GithubImport::Stage::FinishImportWorker',
object_counts: {
'fetched' => {},
'imported' => {}
},
project_id: project.id,
duration_s: 3.01
}
)
worker.import(double(:client), project)

View File

@ -354,7 +354,7 @@ RSpec.describe PostReceive do
context 'webhook' do
it 'fetches the correct project' do
expect(Project).to receive(:find_by).with(id: project.id)
expect(Project).to receive(:find_by).with({ id: project.id })
perform
end