Commit 18084543 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent fd3a95f0
...@@ -42,7 +42,7 @@ export default class Playable extends Node { ...@@ -42,7 +42,7 @@ export default class Playable extends Node {
}, },
{ {
tag: `${this.mediaType}[src]`, tag: `${this.mediaType}[src]`,
getAttrs: el => ({ src: el.getAttribute('src'), alt: el.dataset.title }), getAttrs: el => ({ src: el.src, alt: el.dataset.title }),
}, },
]; ];
......
<script> <script>
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { n__ } from '~/locale'; import { n__ } from '~/locale';
import { isNumber } from 'underscore';
export default { export default {
components: { Icon }, components: { Icon },
...@@ -16,7 +17,7 @@ export default { ...@@ -16,7 +17,7 @@ export default {
diffFilesLength: { diffFilesLength: {
type: Number, type: Number,
required: false, required: false,
default: null, default: 0,
}, },
}, },
computed: { computed: {
...@@ -26,6 +27,9 @@ export default { ...@@ -26,6 +27,9 @@ export default {
isCompareVersionsHeader() { isCompareVersionsHeader() {
return Boolean(this.diffFilesLength); return Boolean(this.diffFilesLength);
}, },
hasDiffFiles() {
return isNumber(this.diffFilesLength) && this.diffFilesLength >= 0;
},
}, },
}; };
</script> </script>
...@@ -38,7 +42,7 @@ export default { ...@@ -38,7 +42,7 @@ export default {
'd-inline-flex': !isCompareVersionsHeader, 'd-inline-flex': !isCompareVersionsHeader,
}" }"
> >
<div v-if="diffFilesLength !== null" class="diff-stats-group"> <div v-if="hasDiffFiles" class="diff-stats-group">
<icon name="doc-code" class="diff-stats-icon text-secondary" /> <icon name="doc-code" class="diff-stats-icon text-secondary" />
<strong>{{ diffFilesLength }} {{ filesText }}</strong> <strong>{{ diffFilesLength }} {{ filesText }}</strong>
</div> </div>
......
import LengthValidator from '~/pages/sessions/new/length_validator';
import NoEmojiValidator from '~/emoji/no_emoji_validator';
document.addEventListener('DOMContentLoaded', () => {
new LengthValidator(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
});
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
} }
.prometheus-graphs-header { .prometheus-graphs-header {
.monitor-environment-dropdown-header header,
.monitor-dashboard-dropdown-header header { .monitor-dashboard-dropdown-header header {
font-size: $gl-font-size; font-size: $gl-font-size;
} }
......
...@@ -8,27 +8,26 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -8,27 +8,26 @@ class Projects::ProjectMembersController < Projects::ApplicationController
# Authorize # Authorize
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
# rubocop: disable CodeReuse/ActiveRecord
def index def index
@sort = params[:sort].presence || sort_value_name @sort = params[:sort].presence || sort_value_name
@skip_groups = @project.invited_group_ids
@skip_groups += @project.group.self_and_ancestors_ids if @project.group
@group_links = @project.project_group_links @group_links = @project.project_group_links
@group_links = @group_links.search(params[:search]) if params[:search].present?
@skip_groups = @group_links.pluck(:group_id) @project_members = MembersFinder.new(@project, current_user)
@skip_groups << @project.namespace_id unless @project.personal? .execute(include_relations: requested_relations, params: params.merge(sort: @sort))
@skip_groups += @project.group.ancestors.pluck(:id) if @project.group
@project_members = MembersFinder.new(@project, current_user).execute(include_relations: requested_relations) @project_members = present_members(@project_members.page(params[:page]))
if params[:search].present? @requesters = present_members(
@project_members = @project_members.joins(:user).merge(User.search(params[:search])) AccessRequestsFinder.new(@project).execute(current_user)
@group_links = @group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id)) )
end
@project_members = present_members(@project_members.sort_by_attribute(@sort).page(params[:page]))
@requesters = present_members(AccessRequestsFinder.new(@project).execute(current_user))
@project_member = @project.project_members.new @project_member = @project.project_members.new
end end
# rubocop: enable CodeReuse/ActiveRecord
def import def import
@projects = current_user.authorized_projects.order_id_desc @projects = current_user.authorized_projects.order_id_desc
......
...@@ -56,7 +56,6 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -56,7 +56,6 @@ class RegistrationsController < Devise::RegistrationsController
return redirect_to stored_location_or_dashboard_or_almost_there_path(current_user) if current_user.role.present? && !current_user.setup_for_company.nil? return redirect_to stored_location_or_dashboard_or_almost_there_path(current_user) if current_user.role.present? && !current_user.setup_for_company.nil?
current_user.name = nil if current_user.name == current_user.username current_user.name = nil if current_user.name == current_user.username
render layout: 'devise_experimental_separate_sign_up_flow'
end end
def update_registration def update_registration
...@@ -68,7 +67,7 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -68,7 +67,7 @@ class RegistrationsController < Devise::RegistrationsController
set_flash_message! :notice, :signed_up set_flash_message! :notice, :signed_up
redirect_to stored_location_or_dashboard_or_almost_there_path(current_user) redirect_to stored_location_or_dashboard_or_almost_there_path(current_user)
else else
render :welcome, layout: 'devise_experimental_separate_sign_up_flow' render :welcome
end end
end end
......
# frozen_string_literal: true # frozen_string_literal: true
class MembersFinder class MembersFinder
attr_reader :project, :current_user, :group # Params can be any of the following:
# sort: string
# search: string
def initialize(project, current_user) def initialize(project, current_user)
@project = project @project = project
...@@ -9,28 +11,39 @@ class MembersFinder ...@@ -9,28 +11,39 @@ class MembersFinder
@group = project.group @group = project.group
end end
def execute(include_relations: [:inherited, :direct]) def execute(include_relations: [:inherited, :direct], params: {})
members = find_members(include_relations, params)
filter_members(members, params)
end
def can?(*args)
Ability.allowed?(*args)
end
private
attr_reader :project, :current_user, :group
def find_members(include_relations, params)
project_members = project.project_members project_members = project.project_members
project_members = project_members.non_invite unless can?(current_user, :admin_project, project) project_members = project_members.non_invite unless can?(current_user, :admin_project, project)
return project_members if include_relations == [:direct] return project_members if include_relations == [:direct]
union_members = group_union_members(include_relations) union_members = group_union_members(include_relations)
union_members << project_members if include_relations.include?(:direct) union_members << project_members if include_relations.include?(:direct)
if union_members.any? return project_members unless union_members.any?
distinct_union_of_members(union_members)
else
project_members
end
end
def can?(*args) distinct_union_of_members(union_members)
Ability.allowed?(*args)
end end
private def filter_members(members, params)
members = members.search(params[:search]) if params[:search].present?
members = members.sort_by_attribute(params[:sort]) if params[:sort].present?
members
end
def group_union_members(include_relations) def group_union_members(include_relations)
[].tap do |members| [].tap do |members|
......
...@@ -18,7 +18,7 @@ module CommitsHelper ...@@ -18,7 +18,7 @@ module CommitsHelper
end end
def commit_to_html(commit, ref, project) def commit_to_html(commit, ref, project)
render 'projects/commits/commit', render 'projects/commits/commit.html',
commit: commit, commit: commit,
ref: ref, ref: ref,
project: project project: project
......
...@@ -40,7 +40,7 @@ module DiscussionOnDiff ...@@ -40,7 +40,7 @@ module DiscussionOnDiff
# Returns an array of at most 16 highlighted lines above a diff note # Returns an array of at most 16 highlighted lines above a diff note
def truncated_diff_lines(highlight: true, diff_limit: nil) def truncated_diff_lines(highlight: true, diff_limit: nil)
return [] unless on_text? return [] unless on_text?
return [] if diff_line.nil? && first_note.is_a?(LegacyDiffNote) return [] if diff_line.nil?
diff_limit = [diff_limit, NUMBER_OF_TRUNCATED_DIFF_LINES].compact.min diff_limit = [diff_limit, NUMBER_OF_TRUNCATED_DIFF_LINES].compact.min
lines = highlight ? highlighted_diff_lines : diff_lines lines = highlight ? highlighted_diff_lines : diff_lines
......
...@@ -31,6 +31,10 @@ class ProjectGroupLink < ApplicationRecord ...@@ -31,6 +31,10 @@ class ProjectGroupLink < ApplicationRecord
DEVELOPER DEVELOPER
end end
def self.search(query)
joins(:group).merge(Group.search(query))
end
def human_access def human_access
self.class.access_options.key(self.group_access) self.class.access_options.key(self.group_access)
end end
......
...@@ -12,7 +12,9 @@ module Projects ...@@ -12,7 +12,9 @@ module Projects
service = Projects::HousekeepingService.new(@project) service = Projects::HousekeepingService.new(@project)
service.execute do service.execute do
repository.delete_all_refs_except(RESERVED_REF_PREFIXES) import_failure_service.with_retry(action: 'delete_all_refs') do
repository.delete_all_refs_except(RESERVED_REF_PREFIXES)
end
end end
# Right now we don't actually have a way to know if a project # Right now we don't actually have a way to know if a project
...@@ -26,6 +28,10 @@ module Projects ...@@ -26,6 +28,10 @@ module Projects
private private
def import_failure_service
@import_failure_service ||= Gitlab::ImportExport::ImportFailureService.new(@project)
end
def repository def repository
@repository ||= @project.repository @repository ||= @project.repository
end end
......
...@@ -96,7 +96,7 @@ module Suggestions ...@@ -96,7 +96,7 @@ module Suggestions
end end
def suggestion_commit_message(project) def suggestion_commit_message(project)
project.suggestion_commit_message || DEFAULT_SUGGESTION_COMMIT_MESSAGE project.suggestion_commit_message.presence || DEFAULT_SUGGESTION_COMMIT_MESSAGE
end end
def processed_suggestion_commit_message(suggestion) def processed_suggestion_commit_message(suggestion)
......
---
title: Support require_password_to_approve in project merge request approvals API
merge_request: 24016
author:
type: added
---
title: Fix Merge Request comments when some notes are corrupt
merge_request: 23786
author:
type: fixed
---
title: Display operations feature flag internal ids
merge_request: 23914
author:
type: added
---
title: Fix showing 'NaN files' when a MR diff does not have any changes
merge_request: 24002
author:
type: fixed
---
title: Fix applying the suggestions with an empty custom message
merge_request: 24144
author:
type: fixed
...@@ -25,7 +25,10 @@ GET /projects/:id/approvals ...@@ -25,7 +25,10 @@ GET /projects/:id/approvals
{ {
"approvals_before_merge": 2, "approvals_before_merge": 2,
"reset_approvals_on_push": true, "reset_approvals_on_push": true,
"disable_overriding_approvers_per_merge_request": false "disable_overriding_approvers_per_merge_request": false,
"merge_requests_author_approval": true,
"merge_requests_disable_committers_approval": false,
"require_password_to_approve": true
} }
``` ```
...@@ -50,6 +53,7 @@ POST /projects/:id/approvals ...@@ -50,6 +53,7 @@ POST /projects/:id/approvals
| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR | | `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR |
| `merge_requests_author_approval` | boolean | no | Allow/Disallow authors from self approving merge requests; `true` means authors cannot self approve | | `merge_requests_author_approval` | boolean | no | Allow/Disallow authors from self approving merge requests; `true` means authors cannot self approve |
| `merge_requests_disable_committers_approval` | boolean | no | Allow/Disallow committers from self approving merge requests | | `merge_requests_disable_committers_approval` | boolean | no | Allow/Disallow committers from self approving merge requests |
| `require_password_to_approve` | boolean | no | Require approver to enter a password in order to authenticate before adding the approval |
```json ```json
{ {
...@@ -57,7 +61,8 @@ POST /projects/:id/approvals ...@@ -57,7 +61,8 @@ POST /projects/:id/approvals
"reset_approvals_on_push": true, "reset_approvals_on_push": true,
"disable_overriding_approvers_per_merge_request": false, "disable_overriding_approvers_per_merge_request": false,
"merge_requests_author_approval": false, "merge_requests_author_approval": false,
"merge_requests_disable_committers_approval": false "merge_requests_disable_committers_approval": false,
"require_password_to_approve": true
} }
``` ```
...@@ -441,7 +446,10 @@ PUT /projects/:id/approvers ...@@ -441,7 +446,10 @@ PUT /projects/:id/approvers
], ],
"approvals_before_merge": 2, "approvals_before_merge": 2,
"reset_approvals_on_push": true, "reset_approvals_on_push": true,
"disable_overriding_approvers_per_merge_request": false "disable_overriding_approvers_per_merge_request": false,
"merge_requests_author_approval": true,
"merge_requests_disable_committers_approval": false,
"require_password_to_approve": true
} }
``` ```
......
...@@ -16,7 +16,7 @@ module Gitlab ...@@ -16,7 +16,7 @@ module Gitlab
matches << :console if console? matches << :console if console?
matches << :sidekiq if sidekiq? matches << :sidekiq if sidekiq?
matches << :rake if rake? matches << :rake if rake?
matches << :rspec if rspec? matches << :test_suite if test_suite?
if matches.one? if matches.one?
matches.first matches.first
...@@ -48,8 +48,8 @@ module Gitlab ...@@ -48,8 +48,8 @@ module Gitlab
!!(defined?(::Rake) && Rake.application.top_level_tasks.any?) !!(defined?(::Rake) && Rake.application.top_level_tasks.any?)
end end
def rspec? def test_suite?
Rails.env.test? && process_name == 'rspec' Rails.env.test?
end end
def console? def console?
...@@ -64,10 +64,6 @@ module Gitlab ...@@ -64,10 +64,6 @@ module Gitlab
puma? || sidekiq? puma? || sidekiq?
end end
def process_name
File.basename($0)
end
def max_threads def max_threads
if puma? if puma?
Puma.cli_config.options[:max_threads] Puma.cli_config.options[:max_threads]
......
...@@ -10258,6 +10258,9 @@ msgstr "" ...@@ -10258,6 +10258,9 @@ msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index." msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr "" msgstr ""
msgid "In order to personalize your experience with GitLab<br>we would like to know a bit more about you."
msgstr ""
msgid "In order to tailor your experience with GitLab we<br>would like to know a bit more about you." msgid "In order to tailor your experience with GitLab we<br>would like to know a bit more about you."
msgstr "" msgstr ""
...@@ -10806,6 +10809,9 @@ msgstr "" ...@@ -10806,6 +10809,9 @@ msgstr ""
msgid "June" msgid "June"
msgstr "" msgstr ""
msgid "Just me"
msgstr ""
msgid "Key" msgid "Key"
msgstr "" msgstr ""
...@@ -12290,6 +12296,9 @@ msgstr "" ...@@ -12290,6 +12296,9 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}" msgid "Multiple uploaders found: %{uploader_types}"
msgstr "" msgstr ""
msgid "My company or team"
msgstr ""
msgid "My-Reaction" msgid "My-Reaction"
msgstr "" msgstr ""
...@@ -19484,6 +19493,9 @@ msgstr "" ...@@ -19484,6 +19493,9 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user." msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr "" msgstr ""
msgid "This will help us personalize your onboarding experience."
msgstr ""
msgid "This will redirect you to an external sign in page." msgid "This will redirect you to an external sign in page."
msgstr "" msgstr ""
...@@ -21278,6 +21290,9 @@ msgstr "" ...@@ -21278,6 +21290,9 @@ msgstr ""
msgid "Welcome to GitLab, %{first_name}!" msgid "Welcome to GitLab, %{first_name}!"
msgstr "" msgstr ""
msgid "Welcome to GitLab.com<br>@%{name}!"
msgstr ""
msgid "Welcome to the Guided GitLab Tour" msgid "Welcome to the Guided GitLab Tour"
msgstr "" msgstr ""
...@@ -21337,6 +21352,9 @@ msgstr "" ...@@ -21337,6 +21352,9 @@ msgstr ""
msgid "Who will be able to see this group?" msgid "Who will be able to see this group?"
msgstr "" msgstr ""
msgid "Who will be using this GitLab subscription?"
msgstr ""
msgid "Wiki" msgid "Wiki"
msgstr "" msgstr ""
...@@ -22051,6 +22069,9 @@ msgstr "" ...@@ -22051,6 +22069,9 @@ msgstr ""
msgid "Your password reset token has expired." msgid "Your password reset token has expired."
msgstr "" msgstr ""
msgid "Your profile"
msgstr ""
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it" msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr "" msgstr ""
......
...@@ -415,4 +415,36 @@ describe RegistrationsController do ...@@ -415,4 +415,36 @@ describe RegistrationsController do
patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } } patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
end end
end end
describe '#welcome' do
subject { get :welcome }
before do
sign_in(create(:user))
end
context 'signup_flow experiment enabled' do
before do
stub_experiment_for_user(signup_flow: true)
end
it 'renders the devise_experimental_separate_sign_up_flow layout' do
expected_layout = Gitlab.ee? ? :checkout : :devise_experimental_separate_sign_up_flow
expect(subject).to render_template(expected_layout)
end
end
context 'signup_flow experiment disabled' do
before do
stub_experiment_for_user(signup_flow: false)
end
it 'renders the devise layout' do
expected_layout = Gitlab.ee? ? :checkout : :devise
expect(subject).to render_template(expected_layout)
end
end
end
end end
...@@ -172,18 +172,36 @@ describe 'Copy as GFM', :js do ...@@ -172,18 +172,36 @@ describe 'Copy as GFM', :js do
'![Image](https://example.com/image.png)' '![Image](https://example.com/image.png)'
) )
verify_media_with_partial_path(
'![Image](/uploads/a123/image.png)',
project_media_uri(@project, '/uploads/a123/image.png')
)
verify( verify(
'VideoLinkFilter', 'VideoLinkFilter',
'![Video](https://example.com/video.mp4)' '![Video](https://example.com/video.mp4)'
) )
verify_media_with_partial_path(
'![Video](/uploads/a123/video.mp4)',
project_media_uri(@project, '/uploads/a123/video.mp4')
)
verify( verify(
'AudioLinkFilter', 'AudioLinkFilter',
'![Audio](https://example.com/audio.wav)' '![Audio](https://example.com/audio.wav)'
) )
verify_media_with_partial_path(
'![Audio](/uploads/a123/audio.wav)',
project_media_uri(@project, '/uploads/a123/audio.wav')
)
verify( verify(
'MathFilter: math as converted from GFM to HTML', 'MathFilter: math as converted from GFM to HTML',
...@@ -647,6 +665,16 @@ describe 'Copy as GFM', :js do ...@@ -647,6 +665,16 @@ describe 'Copy as GFM', :js do
end end
end end
def project_media_uri(project, media_path)
"#{project_path(project)}#{media_path}"
end
def verify_media_with_partial_path(gfm, media_uri)
html = gfm_to_html(gfm)
output_gfm = html_to_gfm(html)
expect(output_gfm).to include(media_uri)
end
# Fake a `current_user` helper # Fake a `current_user` helper
def current_user def current_user
@feat.user @feat.user
......
...@@ -445,8 +445,8 @@ end ...@@ -445,8 +445,8 @@ end
describe 'With experimental flow' do describe 'With experimental flow' do
before do before do
stub_experiment(signup_flow: true) stub_experiment(signup_flow: true, paid_signup_flow: false)
stub_experiment_for_user(signup_flow: true) stub_experiment_for_user(signup_flow: true, paid_signup_flow: false)
end end
it_behaves_like 'Signup' it_behaves_like 'Signup'
......
...@@ -75,6 +75,15 @@ describe MembersFinder, '#execute' do ...@@ -75,6 +75,15 @@ describe MembersFinder, '#execute' do
expect(result).to contain_exactly(member2, member3) expect(result).to contain_exactly(member2, member3)
end end
it 'returns only inherited members of a personal project' do
project = create(:project, namespace: user1.namespace)
member = project.members.first
result = described_class.new(project, user1).execute(include_relations: [:inherited])
expect(result).to contain_exactly(member)
end
it 'returns the members.access_level when the user is invited', :nested_groups do it 'returns the members.access_level when the user is invited', :nested_groups do
member_invite = create(:project_member, :invited, project: project, invite_email: create(:user).email) member_invite = create(:project_member, :invited, project: project, invite_email: create(:user).email)
member1 = group.add_maintainer(user2) member1 = group.add_maintainer(user2)
...@@ -96,6 +105,26 @@ describe MembersFinder, '#execute' do ...@@ -96,6 +105,26 @@ describe MembersFinder, '#execute' do
expect(result.first.access_level).to eq(Gitlab::Access::DEVELOPER) expect(result.first.access_level).to eq(Gitlab::Access::DEVELOPER)
end end
it 'returns searched members if requested' do
project.add_maintainer(user2)
project.add_maintainer(user3)
member3 = project.add_maintainer(user4)
result = described_class.new(project, user2).execute(params: { search: user4.name })
expect(result).to contain_exactly(member3)
end
it 'returns members sorted by id_desc' do
member1 = project.add_maintainer(user2)
member2 = project.add_maintainer(user3)
member3 = project.add_maintainer(user4)
result = described_class.new(project, user2).execute(params: { sort: 'id_desc' })
expect(result).to eq([member3, member2, member1])
end
context 'when include_invited_groups_members == true' do context 'when include_invited_groups_members == true' do
subject { described_class.new(project, user2).execute(include_relations: [:inherited, :direct, :invited_groups_members]) } subject { described_class.new(project, user2).execute(include_relations: [:inherited, :direct, :invited_groups_members]) }
......
...@@ -3,11 +3,12 @@ import Icon from '~/vue_shared/components/icon.vue'; ...@@ -3,11 +3,12 @@ import Icon from '~/vue_shared/components/icon.vue';
import DiffStats from '~/diffs/components/diff_stats.vue'; import DiffStats from '~/diffs/components/diff_stats.vue';
describe('diff_stats', () => { describe('diff_stats', () => {
it('does not render a group if diffFileLengths is not passed in', () => { it('does not render a group if diffFileLengths is not a number', () => {
const wrapper = shallowMount(DiffStats, { const wrapper = shallowMount(DiffStats, {
propsData: { propsData: {
addedLines: 1, addedLines: 1,
removedLines: 2, removedLines: 2,
diffFilesLength: Number.NaN,
}, },
}); });
const groups = wrapper.findAll('.diff-stats-group'); const groups = wrapper.findAll('.diff-stats-group');
......
...@@ -69,4 +69,17 @@ describe CommitsHelper do ...@@ -69,4 +69,17 @@ describe CommitsHelper do
expect(node[:href]).to eq('http://example.com/file.html') expect(node[:href]).to eq('http://example.com/file.html')
end end
end end
describe '#commit_to_html' do
let(:project) { create(:project, :repository) }
let(:ref) { 'master' }
let(:commit) { project.commit(ref) }
it 'renders HTML representation of a commit' do
assign(:project, project)
allow(helper).to receive(:current_user).and_return(project.owner)
expect(helper.commit_to_html(commit, ref, project)).to include('<div class="commit-content')
end
end
end end
...@@ -5,6 +5,7 @@ require 'spec_helper' ...@@ -5,6 +5,7 @@ require 'spec_helper'
describe Gitlab::Runtime do describe Gitlab::Runtime do
before do before do
allow(described_class).to receive(:process_name).and_return('ruby') allow(described_class).to receive(:process_name).and_return('ruby')
stub_rails_env('production')
end end
context "when unknown" do context "when unknown" do
...@@ -47,7 +48,7 @@ describe Gitlab::Runtime do ...@@ -47,7 +48,7 @@ describe Gitlab::Runtime do
expect(subject.sidekiq?).to be(false) expect(subject.sidekiq?).to be(false)
expect(subject.console?).to be(false) expect(subject.console?).to be(false)
expect(subject.rake?).to be(false) expect(subject.rake?).to be(false)
expect(subject.rspec?).to be(false) expect(subject.test_suite?).to be(false)
end end
it "reports its maximum concurrency" do it "reports its maximum concurrency" do
...@@ -74,7 +75,7 @@ describe Gitlab::Runtime do ...@@ -74,7 +75,7 @@ describe Gitlab::Runtime do
expect(subject.sidekiq?).to be(false) expect(subject.sidekiq?).to be(false)
expect(subject.console?).to be(false) expect(subject.console?).to be(false)
expect(subject.rake?).to be(false) expect(subject.rake?).to be(false)
expect(subject.rspec?).to be(false) expect(subject.test_suite?).to be(false)
end end
it "reports its maximum concurrency" do it "reports its maximum concurrency" do
...@@ -106,7 +107,7 @@ describe Gitlab::Runtime do ...@@ -106,7 +107,7 @@ describe Gitlab::Runtime do
expect(subject.puma?).to be(false) expect(subject.puma?).to be(false)
expect(subject.console?).to be(false) expect(subject.console?).to be(false)
expect(subject.rake?).to be(false) expect(subject.rake?).to be(false)
expect(subject.rspec?).to be(false) expect(subject.test_suite?).to be(false)
end end
it "reports its maximum concurrency" do it "reports its maximum concurrency" do
...@@ -131,7 +132,7 @@ describe Gitlab::Runtime do ...@@ -131,7 +132,7 @@ describe Gitlab::Runtime do
expect(subject.sidekiq?).to be(false) expect(subject.sidekiq?).to be(false)
expect(subject.puma?).to be(false) expect(subject.puma?).to be(false)
expect(subject.rake?).to be(false) expect(subject.rake?).to be(false)
expect(subject.rspec?).to be(false) expect(subject.test_suite?).to be(false)
end end
it "reports its maximum concurrency" do it "reports its maximum concurrency" do
...@@ -139,14 +140,14 @@ describe Gitlab::Runtime do ...@@ -139,14 +140,14 @@ describe Gitlab::Runtime do
end end
end end
context "rspec" do context "test suite" do
before do before do
allow(described_class).to receive(:process_name).and_return('rspec') stub_rails_env('test')
end end
it "identifies itself" do it "identifies itself" do
expect(subject.identify).to eq(:rspec) expect(subject.identify).to eq(:test_suite)
expect(subject.rspec?).to be(true) expect(subject.test_suite?).to be(true)
end end
it "does not identify as others" do it "does not identify as others" do
......
...@@ -59,6 +59,18 @@ describe DiscussionOnDiff do ...@@ -59,6 +59,18 @@ describe DiscussionOnDiff do
end end
end end
context "when the diff line does not exist on a corrupt diff note" do
subject { create(:diff_note_on_merge_request, line_number: 18).to_discussion }
before do
allow(subject).to receive(:diff_line) { nil }
end
it "returns an empty array" do
expect(truncated_lines).to eq([])
end
end
context 'when the discussion is on an image' do context 'when the discussion is on an image' do
subject { create(:image_diff_note_on_merge_request).to_discussion } subject { create(:image_diff_note_on_merge_request).to_discussion }
......
...@@ -47,4 +47,12 @@ describe ProjectGroupLink do ...@@ -47,4 +47,12 @@ describe ProjectGroupLink do
group_users.each { |user| expect(user.authorized_projects).not_to include(project) } group_users.each { |user| expect(user.authorized_projects).not_to include(project) }
end end
end end
describe 'search by group name' do
let_it_be(:project_group_link) { create(:project_group_link) }
let_it_be(:group) { project_group_link.group }
it { expect(described_class.search(group.name)).to eq([project_group_link]) }
it { expect(described_class.search('not-a-group-name')).to be_empty }
end
end end
...@@ -20,7 +20,7 @@ describe Projects::AfterImportService do ...@@ -20,7 +20,7 @@ describe Projects::AfterImportService do
allow(housekeeping_service) allow(housekeeping_service)
.to receive(:execute).and_yield .to receive(:execute).and_yield
expect(housekeeping_service).to receive(:increment!) allow(housekeeping_service).to receive(:increment!)
end end
it 'performs housekeeping' do it 'performs housekeeping' do
...@@ -58,6 +58,52 @@ describe Projects::AfterImportService do ...@@ -58,6 +58,52 @@ describe Projects::AfterImportService do
end end
end end
context 'when after import action throw non-retriable exception' do
let(:exception) { StandardError.new('after import error') }
before do
allow(repository)
.to receive(:delete_all_refs_except)
.and_raise(exception)
end
it 'throws after import error' do
expect { subject.execute }.to raise_exception('after import error')
end
end
context 'when after import action throw retriable exception one time' do
let(:exception) { GRPC::DeadlineExceeded.new }
before do
call_count = 0
allow(repository).to receive(:delete_all_refs_except).and_wrap_original do |original_method, *args|
call_count += 1
call_count > 1 ? original_method.call(*args) : raise(exception)
end
subject.execute
end
it 'removes refs/pull/**/*' do
expect(rugged.references.map(&:name))
.not_to include(%r{\Arefs/pull/})
end
it 'records the failures in the database', :aggregate_failures do
import_failure = ImportFailure.last
expect(import_failure.source).to eq('delete_all_refs')
expect(import_failure.project_id).to eq(project.id)
expect(import_failure.relation_key).to be_nil
expect(import_failure.relation_index).to be_nil
expect(import_failure.exception_class).to eq('GRPC::DeadlineExceeded')
expect(import_failure.exception_message).to be_present
expect(import_failure.correlation_id_value).not_to be_empty
end
end
def rugged def rugged
rugged_repo(repository) rugged_repo(repository)
end end
......
...@@ -57,10 +57,22 @@ describe Suggestions::ApplyService do ...@@ -57,10 +57,22 @@ describe Suggestions::ApplyService do
end end
context 'is not specified' do context 'is not specified' do
let(:message) { nil } let(:expected_value) { "Apply suggestion to files/ruby/popen.rb" }
it 'sets default commit message' do context 'is nil' do
expect(project.repository.commit.message).to eq("Apply suggestion to files/ruby/popen.rb") let(:message) { nil }
it 'sets default commit message' do
expect(project.repository.commit.message).to eq(expected_value)
end
end
context 'is an empty string' do
let(:message) { '' }
it 'sets default commit message' do
expect(project.repository.commit.message).to eq(expected_value)
end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment