summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/boards_controller_spec.rb10
-rw-r--r--spec/controllers/projects/clusters/gcp_controller_spec.rb18
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb58
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb47
-rw-r--r--spec/factories/ci/builds.rb25
-rw-r--r--spec/features/boards/keyboard_shortcut_spec.rb36
-rw-r--r--spec/features/copy_as_gfm_spec.rb96
-rw-r--r--spec/features/explore/groups_spec.rb87
-rw-r--r--spec/features/groups/show_spec.rb16
-rw-r--r--spec/features/invites_spec.rb97
-rw-r--r--spec/features/issues/keyboard_shortcut_spec.rb36
-rw-r--r--spec/features/markdown_spec.rb2
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb155
-rw-r--r--spec/features/projects/clusters_spec.rb14
-rw-r--r--spec/features/projects/import_export/test_project_export.tar.gzbin343232 -> 343092 bytes
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb28
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb34
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_basic.json1
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_widget.json6
-rw-r--r--spec/javascripts/fixtures/pipelines.html.haml4
-rw-r--r--spec/javascripts/jobs/header_spec.js3
-rw-r--r--spec/javascripts/monitoring/graph/deployment_spec.js144
-rw-r--r--spec/javascripts/monitoring/graph/flag_spec.js114
-rw-r--r--spec/javascripts/pipelines/nav_controls_spec.js27
-rw-r--r--spec/javascripts/repo/components/ide_repo_tree_spec.js6
-rw-r--r--spec/javascripts/repo/components/ide_spec.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js115
-rw-r--r--spec/javascripts/vue_shared/components/header_ci_component_spec.js81
-rw-r--r--spec/lib/banzai/filter/mermaid_filter_spec.rb4
-rw-r--r--spec/lib/gitlab/background_migration/prepare_untracked_uploads_spec.rb13
-rw-r--r--spec/lib/gitlab/cycle_analytics/events_spec.rb14
-rw-r--r--spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb14
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb4
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb1
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb82
-rw-r--r--spec/lib/gitlab/gitaly_client/remote_service_spec.rb13
-rw-r--r--spec/lib/gitlab/import_export/project.json770
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb26
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb12
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/lib/google_api/cloud_platform/client_spec.rb24
-rw-r--r--spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb32
-rw-r--r--spec/migrations/migrate_stage_id_reference_in_background_spec.rb6
-rw-r--r--spec/migrations/migrate_stages_statuses_spec.rb6
-rw-r--r--spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb12
-rw-r--r--spec/migrations/schedule_merge_request_diff_migrations_spec.rb6
-rw-r--r--spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb6
-rw-r--r--spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb6
-rw-r--r--spec/migrations/schedule_populate_merge_request_metrics_with_events_data_spec.rb4
-rw-r--r--spec/migrations/track_untracked_uploads_spec.rb12
-rw-r--r--spec/models/ci/build_spec.rb36
-rw-r--r--spec/models/commit_spec.rb1
-rw-r--r--spec/models/merge_request_spec.rb46
-rw-r--r--spec/models/namespace_spec.rb10
-rw-r--r--spec/models/project_spec.rb69
-rw-r--r--spec/models/repository_spec.rb55
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb63
-rw-r--r--spec/requests/api/issues_spec.rb12
-rw-r--r--spec/requests/api/jobs_spec.rb4
-rw-r--r--spec/requests/api/merge_requests_spec.rb6
-rw-r--r--spec/serializers/group_child_entity_spec.rb12
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb16
-rw-r--r--spec/services/check_gcp_project_billing_service_spec.rb31
-rw-r--r--spec/services/files/multi_service_spec.rb4
-rw-r--r--spec/services/merge_requests/rebase_service_spec.rb134
-rw-r--r--spec/services/projects/create_service_spec.rb2
-rw-r--r--spec/services/projects/hashed_storage/migrate_repository_service_spec.rb2
-rw-r--r--spec/services/projects/transfer_service_spec.rb4
-rw-r--r--spec/services/protected_branches/create_service_spec.rb16
-rw-r--r--spec/services/reset_project_cache_service_spec.rb28
-rw-r--r--spec/support/background_migrations_matchers.rb15
-rw-r--r--spec/support/google_api/cloud_platform_helpers.rb6
-rw-r--r--spec/support/shared_examples/requests/api/issuable_participants_examples.rb29
-rw-r--r--spec/views/projects/merge_requests/show.html.haml_spec.rb2
-rw-r--r--spec/workers/check_gcp_project_billing_worker_spec.rb61
-rw-r--r--spec/workers/rebase_worker_spec.rb27
-rw-r--r--spec/workers/repository_import_worker_spec.rb1
78 files changed, 2223 insertions, 803 deletions
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index 305af289531..4d765229bde 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -55,6 +55,16 @@ describe Projects::BoardsController do
end
end
+ context 'issues are disabled' do
+ let(:project) { create(:project, :issues_disabled) }
+
+ it 'returns a not found 404 response' do
+ list_boards
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
def list_boards(format: :html)
get :index, namespace_id: project.namespace,
project_id: project,
diff --git a/spec/controllers/projects/clusters/gcp_controller_spec.rb b/spec/controllers/projects/clusters/gcp_controller_spec.rb
index ee7928beb7e..be19fa93183 100644
--- a/spec/controllers/projects/clusters/gcp_controller_spec.rb
+++ b/spec/controllers/projects/clusters/gcp_controller_spec.rb
@@ -17,7 +17,6 @@ describe Projects::Clusters::GcpController do
context 'when omniauth has been configured' do
let(:key) { 'secret-key' }
-
let(:session_key_for_redirect_uri) do
GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key)
end
@@ -78,6 +77,8 @@ describe Projects::Clusters::GcpController do
end
it 'has new object' do
+ expect(controller).to receive(:authorize_google_project_billing)
+
go
expect(assigns(:cluster)).to be_an_instance_of(Clusters::Cluster)
@@ -138,7 +139,11 @@ describe Projects::Clusters::GcpController do
stub_google_api_validate_token
end
- context 'when creates a cluster on gke' do
+ context 'when google project billing is enabled' do
+ before do
+ stub_google_project_billing_status
+ end
+
it 'creates a new cluster' do
expect(ClusterProvisionWorker).to receive(:perform_async)
expect { go }.to change { Clusters::Cluster.count }
@@ -148,6 +153,15 @@ describe Projects::Clusters::GcpController do
expect(project.clusters.first).to be_kubernetes
end
end
+
+ context 'when google project billing is not enabled' do
+ it 'renders the cluster form with an error' do
+ go
+
+ expect(response).to set_flash[:error]
+ expect(response).to render_template('new')
+ end
+ end
end
context 'when access token is expired' do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 45c424af8c4..c8cc6b374f6 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -684,4 +684,62 @@ describe Projects::MergeRequestsController do
format: :json
end
end
+
+ describe 'POST #rebase' do
+ let(:viewer) { user }
+
+ def post_rebase
+ post :rebase, namespace_id: project.namespace, project_id: project, id: merge_request
+ end
+
+ def expect_rebase_worker_for(user)
+ expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id)
+ end
+
+ context 'successfully' do
+ it 'enqeues a RebaseWorker' do
+ expect_rebase_worker_for(viewer)
+
+ post_rebase
+
+ expect(response.status).to eq(200)
+ end
+ end
+
+ context 'with a forked project' do
+ let(:fork_project) { create(:project, :repository, forked_from_project: project) }
+ let(:fork_owner) { fork_project.owner }
+
+ before do
+ merge_request.update!(source_project: fork_project)
+ fork_project.add_reporter(user)
+ end
+
+ context 'user cannot push to source branch' do
+ it 'returns 404' do
+ expect_rebase_worker_for(viewer).never
+
+ post_rebase
+
+ expect(response.status).to eq(404)
+ end
+ end
+
+ context 'user can push to source branch' do
+ before do
+ project.add_reporter(fork_owner)
+
+ sign_in(fork_owner)
+ end
+
+ it 'returns 200' do
+ expect_rebase_worker_for(fork_owner)
+
+ post_rebase
+
+ expect(response.status).to eq(200)
+ end
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index 77a47f0ad13..0202149f335 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -17,4 +17,51 @@ describe Projects::Settings::CiCdController do
expect(response).to render_template(:show)
end
end
+
+ describe '#reset_cache' do
+ before do
+ sign_in(user)
+
+ project.add_master(user)
+
+ allow(ResetProjectCacheService).to receive_message_chain(:new, :execute).and_return(true)
+ end
+
+ subject { post :reset_cache, namespace_id: project.namespace, project_id: project }
+
+ it 'calls reset project cache service' do
+ expect(ResetProjectCacheService).to receive_message_chain(:new, :execute)
+
+ subject
+ end
+
+ it 'redirects to project pipelines path' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:redirect)
+ expect(response).to redirect_to(project_pipelines_path(project))
+ end
+
+ context 'when service returns successfully' do
+ it 'sets the flash notice variable' do
+ subject
+
+ expect(controller).to set_flash[:notice]
+ expect(controller).not_to set_flash[:error]
+ end
+ end
+
+ context 'when service does not return successfully' do
+ before do
+ allow(ResetProjectCacheService).to receive_message_chain(:new, :execute).and_return(false)
+ end
+
+ it 'sets the flash error variable' do
+ subject
+
+ expect(controller).not_to set_flash[:notice]
+ expect(controller).to set_flash[:error]
+ end
+ end
+ end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index dc1d88c92dc..6f66468570f 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -7,12 +7,10 @@ FactoryBot.define do
stage_idx 0
ref 'master'
tag false
- status 'pending'
- created_at 'Di 29. Okt 09:50:00 CET 2013'
- started_at 'Di 29. Okt 09:51:28 CET 2013'
- finished_at 'Di 29. Okt 09:53:28 CET 2013'
commands 'ls -a'
protected false
+ created_at 'Di 29. Okt 09:50:00 CET 2013'
+ pending
options do
{
@@ -29,23 +27,37 @@ FactoryBot.define do
pipeline factory: :ci_pipeline
+ trait :started do
+ started_at 'Di 29. Okt 09:51:28 CET 2013'
+ end
+
+ trait :finished do
+ started
+ finished_at 'Di 29. Okt 09:53:28 CET 2013'
+ end
+
trait :success do
+ finished
status 'success'
end
trait :failed do
+ finished
status 'failed'
end
trait :canceled do
+ finished
status 'canceled'
end
trait :skipped do
+ started
status 'skipped'
end
trait :running do
+ started
status 'running'
end
@@ -114,11 +126,6 @@ FactoryBot.define do
build.project ||= build.pipeline.project
end
- factory :ci_not_started_build do
- started_at nil
- finished_at nil
- end
-
trait :tag do
tag true
end
diff --git a/spec/features/boards/keyboard_shortcut_spec.rb b/spec/features/boards/keyboard_shortcut_spec.rb
index 435de3861cf..d820a59aa16 100644
--- a/spec/features/boards/keyboard_shortcut_spec.rb
+++ b/spec/features/boards/keyboard_shortcut_spec.rb
@@ -1,20 +1,38 @@
require 'rails_helper'
describe 'Issue Boards shortcut', :js do
- let(:project) { create(:project) }
+ context 'issues are enabled' do
+ let(:project) { create(:project) }
- before do
- create(:board, project: project)
+ before do
+ create(:board, project: project)
- sign_in(create(:admin))
+ sign_in(create(:admin))
- visit project_path(project)
+ visit project_path(project)
+ end
+
+ it 'takes user to issue board index' do
+ find('body').native.send_keys('gb')
+ expect(page).to have_selector('.boards-list')
+
+ wait_for_requests
+ end
end
- it 'takes user to issue board index' do
- find('body').native.send_keys('gb')
- expect(page).to have_selector('.boards-list')
+ context 'issues are not enabled' do
+ let(:project) { create(:project, :issues_disabled) }
+
+ before do
+ sign_in(create(:admin))
+
+ visit project_path(project)
+ end
+
+ it 'does not take user to the issue board index' do
+ find('body').native.send_keys('gb')
- wait_for_requests
+ expect(page).to have_selector("body[data-page='projects:show']")
+ end
end
end
diff --git a/spec/features/copy_as_gfm_spec.rb b/spec/features/copy_as_gfm_spec.rb
index 1fcb8d5bc67..d8f1a919522 100644
--- a/spec/features/copy_as_gfm_spec.rb
+++ b/spec/features/copy_as_gfm_spec.rb
@@ -285,6 +285,102 @@ describe 'Copy as GFM', :js do
end
verify(
+ 'MermaidFilter: mermaid as converted from GFM to HTML',
+
+ <<-GFM.strip_heredoc
+ ```mermaid
+ graph TD;
+ A-->B;
+ ```
+ GFM
+ )
+
+ aggregate_failures('MermaidFilter: mermaid as transformed from HTML to SVG') do
+ gfm = <<-GFM.strip_heredoc
+ ```mermaid
+ graph TD;
+ A-->B;
+ ```
+ GFM
+
+ html = <<-HTML.strip_heredoc
+ <svg id="mermaidChart1" xmlns="http://www.w3.org/2000/svg" height="100%" viewBox="0 0 87.234375 174" style="max-width:87.234375px;" class="mermaid">
+ <style>
+ .mermaid {
+ /* Flowchart variables */
+ /* Sequence Diagram variables */
+ /* Gantt chart variables */
+ /** Section styling */
+ /* Grid and axis */
+ /* Today line */
+ /* Task styling */
+ /* Default task */
+ /* Specific task settings for the sections*/
+ /* Active task */
+ /* Completed task */
+ /* Tasks on the critical line */
+ }
+ </style>
+ <g>
+ <g class="output">
+ <g class="clusters"></g>
+ <g class="edgePaths">
+ <g class="edgePath" style="opacity: 1;">
+ <path class="path" d="M33.6171875,52L33.6171875,77L33.6171875,102" marker-end="url(#arrowhead65)" style="fill:none"></path>
+ <defs>
+ <marker id="arrowhead65" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto">
+ <path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path>
+ </marker>
+ </defs>
+ </g>
+ </g>
+ <g class="edgeLabels">
+ <g class="edgeLabel" style="opacity: 1;" transform="">
+ <g transform="translate(0,0)" class="label">
+ <foreignObject width="0" height="0">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">
+ <span class="edgeLabel"></span>
+ </div>
+ </foreignObject>
+ </g>
+ </g>
+ </g>
+ <g class="nodes">
+ <g class="node" id="A" transform="translate(33.6171875,36)" style="opacity: 1;">
+ <rect rx="0" ry="0" x="-13.6171875" y="-16" width="27.234375" height="32"></rect>
+ <g class="label" transform="translate(0,0)">
+ <g transform="translate(-3.6171875,-6)">
+ <foreignObject width="7.234375" height="12">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">A</div>
+ </foreignObject>
+ </g>
+ </g>
+ </g>
+ <g class="node" id="B" transform="translate(33.6171875,118)" style="opacity: 1;">
+ <rect rx="0" ry="0" x="-13.6171875" y="-16" width="27.234375" height="32">
+ </rect>
+ <g class="label" transform="translate(0,0)">
+ <g transform="translate(-3.6171875,-6)">
+ <foreignObject width="7.234375" height="12">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">B</div>
+ </foreignObject>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <text class="source" display="none">graph TD;
+ A--&gt;B;
+ </text>
+ </svg>
+ HTML
+
+ output_gfm = html_to_gfm(html)
+ expect(output_gfm.strip).to eq(gfm.strip)
+ end
+
+ verify(
'SanitizationFilter',
<<-GFM.strip_heredoc
diff --git a/spec/features/explore/groups_spec.rb b/spec/features/explore/groups_spec.rb
new file mode 100644
index 00000000000..e4ef47d88dd
--- /dev/null
+++ b/spec/features/explore/groups_spec.rb
@@ -0,0 +1,87 @@
+require 'spec_helper'
+
+describe 'Explore Groups', :js do
+ let(:user) { create :user }
+ let(:group) { create :group }
+ let!(:private_project) do
+ create :project, :private, namespace: group do |project|
+ create(:issue, project: internal_project)
+ create(:merge_request, source_project: project, target_project: project)
+ end
+ end
+
+ let!(:internal_project) do
+ create :project, :internal, namespace: group do |project|
+ create(:issue, project: project)
+ create(:merge_request, source_project: project, target_project: project)
+ end
+ end
+
+ let!(:public_project) do
+ create(:project, :public, namespace: group) do |project|
+ create(:issue, project: project)
+ create(:merge_request, source_project: project, target_project: project)
+ end
+ end
+
+ shared_examples 'renders public and internal projects' do
+ it do
+ visit_page
+ expect(page).to have_content(public_project.name)
+ expect(page).to have_content(internal_project.name)
+ expect(page).not_to have_content(private_project.name)
+ end
+ end
+
+ shared_examples 'renders only public project' do
+ it do
+ visit_page
+ expect(page).to have_content(public_project.name)
+ expect(page).not_to have_content(internal_project.name)
+ expect(page).not_to have_content(private_project.name)
+ end
+ end
+
+ shared_examples 'renders group in public groups area' do
+ it do
+ visit explore_groups_path
+ expect(page).to have_content(group.name)
+ end
+ end
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'renders public and internal projects' do
+ subject(:visit_page) { visit group_path(group) }
+ end
+
+ it_behaves_like 'renders public and internal projects' do
+ subject(:visit_page) { visit issues_group_path(group) }
+ end
+
+ it_behaves_like 'renders public and internal projects' do
+ subject(:visit_page) { visit merge_requests_group_path(group) }
+ end
+
+ it_behaves_like 'renders group in public groups area'
+ end
+
+ context 'when signed out' do
+ it_behaves_like 'renders only public project' do
+ subject(:visit_page) { visit group_path(group) }
+ end
+
+ it_behaves_like 'renders only public project' do
+ subject(:visit_page) { visit issues_group_path(group) }
+ end
+
+ it_behaves_like 'renders only public project' do
+ subject(:visit_page) { visit merge_requests_group_path(group) }
+ end
+
+ it_behaves_like 'renders group in public groups area'
+ end
+end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index 7fc2b383749..ceccc471405 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -55,4 +55,20 @@ feature 'Group show page' do
end
end
end
+
+ context 'group has a project with emoji in description', :js do
+ let(:user) { create(:user) }
+ let!(:project) { create(:project, description: ':smile:', namespace: group) }
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ visit path
+ end
+
+ it 'shows the project info' do
+ expect(page).to have_content(project.title)
+ expect(page).to have_selector('gl-emoji[data-name="smile"]')
+ end
+ end
end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
new file mode 100644
index 00000000000..e4be6193b8b
--- /dev/null
+++ b/spec/features/invites_spec.rb
@@ -0,0 +1,97 @@
+require 'spec_helper'
+
+describe 'Invites' do
+ let(:user) { create(:user) }
+ let(:owner) { create(:user, name: 'John Doe') }
+ let(:group) { create(:group, name: 'Owned') }
+ let(:project) { create(:project, :repository, namespace: group) }
+ let(:invite) { group.group_members.invite.last }
+
+ before do
+ project.add_master(owner)
+ group.add_user(owner, Gitlab::Access::OWNER)
+ group.add_developer('user@example.com', owner)
+ invite.generate_invite_token!
+ end
+
+ context 'when signed out' do
+ before do
+ visit invite_path(invite.raw_invite_token)
+ end
+
+ it 'renders sign in page with sign in notice' do
+ expect(current_path).to eq(new_user_session_path)
+ expect(page).to have_content('To accept this invitation, sign in')
+ end
+
+ it 'sign in and redirects to invitation page' do
+ fill_in 'user_login', with: user.email
+ fill_in 'user_password', with: user.password
+ check 'user_remember_me'
+ click_button 'Sign in'
+
+ expect(current_path).to eq(invite_path(invite.raw_invite_token))
+ expect(page).to have_content(
+ 'You have been invited by John Doe to join group Owned as Developer.'
+ )
+ expect(page).to have_link('Accept invitation')
+ expect(page).to have_link('Decline')
+ end
+ end
+
+ context 'when signed in as an exists member' do
+ before do
+ sign_in(owner)
+ end
+
+ it 'shows message user already a member' do
+ visit invite_path(invite.raw_invite_token)
+ expect(page).to have_content('However, you are already a member of this group.')
+ end
+ end
+
+ describe 'accepting the invitation' do
+ before do
+ sign_in(user)
+ visit invite_path(invite.raw_invite_token)
+ end
+
+ it 'grants access and redirects to group page' do
+ page.click_link 'Accept invitation'
+ expect(current_path).to eq(group_path(group))
+ expect(page).to have_content(
+ 'You have been granted Developer access to group Owned.'
+ )
+ end
+ end
+
+ describe 'declining the application' do
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ visit invite_path(invite.raw_invite_token)
+ end
+
+ it 'declines application and redirects to dashboard' do
+ page.click_link 'Decline'
+ expect(current_path).to eq(dashboard_projects_path)
+ expect(page).to have_content(
+ 'You have declined the invitation to join group Owned.'
+ )
+ end
+ end
+
+ context 'when signed out' do
+ before do
+ visit decline_invite_path(invite.raw_invite_token)
+ end
+
+ it 'declines application and redirects to sign in page' do
+ expect(current_path).to eq(new_user_session_path)
+ expect(page).to have_content(
+ 'You have declined the invitation to join group Owned.'
+ )
+ end
+ end
+ end
+end
diff --git a/spec/features/issues/keyboard_shortcut_spec.rb b/spec/features/issues/keyboard_shortcut_spec.rb
new file mode 100644
index 00000000000..961de9d3d25
--- /dev/null
+++ b/spec/features/issues/keyboard_shortcut_spec.rb
@@ -0,0 +1,36 @@
+require 'rails_helper'
+
+describe 'Issues shortcut', :js do
+ context 'New Issue shortcut' do
+ context 'issues are enabled' do
+ let(:project) { create(:project) }
+
+ before do
+ sign_in(create(:admin))
+
+ visit project_path(project)
+ end
+
+ it 'takes user to the new issue page' do
+ find('body').native.send_keys('i')
+ expect(page).to have_selector('#new_issue')
+ end
+ end
+
+ context 'issues are not enabled' do
+ let(:project) { create(:project, :issues_disabled) }
+
+ before do
+ sign_in(create(:admin))
+
+ visit project_path(project)
+ end
+
+ it 'does not take user to the new issue page' do
+ find('body').native.send_keys('i')
+
+ expect(page).to have_selector("body[data-page='projects:show']")
+ end
+ end
+ end
+end
diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb
index e285befc66f..a2b78a5e021 100644
--- a/spec/features/markdown_spec.rb
+++ b/spec/features/markdown_spec.rb
@@ -71,7 +71,7 @@ describe 'GitLab Markdown' do
it 'parses mermaid code block' do
aggregate_failures do
- expect(doc).to have_selector('pre.code.js-render-mermaid')
+ expect(doc).to have_selector('pre[lang=mermaid] > code.js-render-mermaid')
end
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 882a2756b72..523cc08496b 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -20,105 +20,126 @@ feature 'Gcp Cluster', :js do
.to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
end
- context 'when user does not have a cluster and visits cluster index page' do
+ context 'when user has a GCP project with billing enabled' do
before do
- visit project_clusters_path(project)
-
- click_link 'Add cluster'
- click_link 'Create on GKE'
+ allow_any_instance_of(Projects::Clusters::GcpController).to receive(:authorize_google_project_billing)
+ stub_google_project_billing_status
end
- context 'when user filled form with valid parameters' do
+ context 'when user does not have a cluster and visits cluster index page' do
before do
- allow_any_instance_of(GoogleApi::CloudPlatform::Client)
- .to receive(:projects_zones_clusters_create) do
- OpenStruct.new(
- self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
- status: 'RUNNING'
- )
+ visit project_clusters_path(project)
+
+ click_link 'Add cluster'
+ click_link 'Create on GKE'
+ end
+
+ context 'when user filled form with valid parameters' do
+ before do
+ allow_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive(:projects_zones_clusters_create) do
+ OpenStruct.new(
+ self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
+ status: 'RUNNING'
+ )
+ end
+
+ allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil)
+
+ fill_in 'cluster_provider_gcp_attributes_gcp_project_id', with: 'gcp-project-123'
+ fill_in 'cluster_name', with: 'dev-cluster'
+ click_button 'Create cluster'
end
- allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil)
+ it 'user sees a cluster details page and creation status' do
+ expect(page).to have_content('Cluster is being created on Google Kubernetes Engine...')
- fill_in 'cluster_provider_gcp_attributes_gcp_project_id', with: 'gcp-project-123'
- fill_in 'cluster_name', with: 'dev-cluster'
- click_button 'Create cluster'
- end
+ Clusters::Cluster.last.provider.make_created!
- it 'user sees a cluster details page and creation status' do
- expect(page).to have_content('Cluster is being created on Google Kubernetes Engine...')
+ expect(page).to have_content('Cluster was successfully created on Google Kubernetes Engine')
+ end
- Clusters::Cluster.last.provider.make_created!
+ it 'user sees a error if something worng during creation' do
+ expect(page).to have_content('Cluster is being created on Google Kubernetes Engine...')
- expect(page).to have_content('Cluster was successfully created on Google Kubernetes Engine')
- end
+ Clusters::Cluster.last.provider.make_errored!('Something wrong!')
- it 'user sees a error if something worng during creation' do
- expect(page).to have_content('Cluster is being created on Google Kubernetes Engine...')
+ expect(page).to have_content('Something wrong!')
+ end
+ end
- Clusters::Cluster.last.provider.make_errored!('Something wrong!')
+ context 'when user filled form with invalid parameters' do
+ before do
+ click_button 'Create cluster'
+ end
- expect(page).to have_content('Something wrong!')
+ it 'user sees a validation error' do
+ expect(page).to have_css('#error_explanation')
+ end
end
end
- context 'when user filled form with invalid parameters' do
+ context 'when user does have a cluster and visits cluster page' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
+
before do
- click_button 'Create cluster'
+ visit project_cluster_path(project, cluster)
end
- it 'user sees a validation error' do
- expect(page).to have_css('#error_explanation')
+ it 'user sees a cluster details page' do
+ expect(page).to have_button('Save changes')
+ expect(page.find(:css, '.cluster-name').value).to eq(cluster.name)
end
- end
- end
- context 'when user does have a cluster and visits cluster page' do
- let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
+ context 'when user disables the cluster' do
+ before do
+ page.find(:css, '.js-toggle-cluster').click
+ page.within('#cluster-integration') { click_button 'Save changes' }
+ end
- before do
- visit project_cluster_path(project, cluster)
- end
+ it 'user sees the successful message' do
+ expect(page).to have_content('Cluster was successfully updated.')
+ end
+ end
- it 'user sees a cluster details page' do
- expect(page).to have_button('Save changes')
- expect(page.find(:css, '.cluster-name').value).to eq(cluster.name)
- end
+ context 'when user changes cluster parameters' do
+ before do
+ fill_in 'cluster_platform_kubernetes_attributes_namespace', with: 'my-namespace'
+ page.within('#js-cluster-details') { click_button 'Save changes' }
+ end
- context 'when user disables the cluster' do
- before do
- page.find(:css, '.js-toggle-cluster').click
- page.within('#cluster-integration') { click_button 'Save changes' }
+ it 'user sees the successful message' do
+ expect(page).to have_content('Cluster was successfully updated.')
+ expect(cluster.reload.platform_kubernetes.namespace).to eq('my-namespace')
+ end
end
- it 'user sees the successful message' do
- expect(page).to have_content('Cluster was successfully updated.')
+ context 'when user destroy the cluster' do
+ before do
+ page.accept_confirm do
+ click_link 'Remove integration'
+ end
+ end
+
+ it 'user sees creation form with the successful message' do
+ expect(page).to have_content('Cluster integration was successfully removed.')
+ expect(page).to have_link('Add cluster')
+ end
end
end
+ end
- context 'when user changes cluster parameters' do
- before do
- fill_in 'cluster_platform_kubernetes_attributes_namespace', with: 'my-namespace'
- page.within('#js-cluster-details') { click_button 'Save changes' }
- end
+ context 'when user does not have a GCP project with billing enabled' do
+ before do
+ visit project_clusters_path(project)
- it 'user sees the successful message' do
- expect(page).to have_content('Cluster was successfully updated.')
- expect(cluster.reload.platform_kubernetes.namespace).to eq('my-namespace')
- end
+ click_link 'Add cluster'
+ click_link 'Create on GKE'
end
- context 'when user destroy the cluster' do
- before do
- page.accept_confirm do
- click_link 'Remove integration'
- end
- end
-
- it 'user sees creation form with the successful message' do
- expect(page).to have_content('Cluster integration was successfully removed.')
- expect(page).to have_link('Add cluster')
- end
+ it 'user sees a check page' do
+ pending 'the frontend still has not been implemented'
+ expect(page).to have_link('Continue')
end
end
end
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index 93929bf6814..eae2910a8f6 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -77,4 +77,18 @@ feature 'Clusters', :js do
end
end
end
+
+ context 'when user has not signed in Google' do
+ before do
+ visit project_clusters_path(project)
+
+ click_link 'Add cluster'
+ click_link 'Create on GKE'
+ end
+
+ it 'user sees a login page' do
+ expect(page).to have_css('.signin-with-google')
+ expect(page).to have_link('Google account')
+ end
+ end
end
diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz
index 0c354298433..0cc68aff494 100644
--- a/spec/features/projects/import_export/test_project_export.tar.gz
+++ b/spec/features/projects/import_export/test_project_export.tar.gz
Binary files differ
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
index 5d9208ebadd..4c49cff30d4 100644
--- a/spec/features/projects/jobs/user_browses_job_spec.rb
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe 'User browses a job', :js do
- let!(:build) { create(:ci_build, :coverage, pipeline: pipeline) }
+ let!(:build) { create(:ci_build, :running, :coverage, pipeline: pipeline) }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.sha, ref: 'master') }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:user) { create(:user) }
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index f8ea1a52656..9a6b27c00f8 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -369,6 +369,34 @@ feature 'Jobs' do
end
end
end
+
+ context 'Playable manual action' do
+ let(:job) { create(:ci_build, :playable, pipeline: pipeline) }
+
+ before do
+ project.add_developer(user)
+ visit project_job_path(project, job)
+ end
+
+ it 'shows manual action empty state' do
+ expect(page).to have_content('This job requires a manual action')
+ expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments.')
+ expect(page).to have_link('Trigger this manual action')
+ end
+ end
+
+ context 'Non triggered job' do
+ let(:job) { create(:ci_build, :created, pipeline: pipeline) }
+
+ before do
+ visit project_job_path(project, job)
+ end
+
+ it 'shows manual action empty state' do
+ expect(page).to have_content('This job has not been triggered yet')
+ expect(page).to have_content('This job depends on upstream jobs that need to succeed in order for this job to be triggered.')
+ end
+ end
end
describe "POST /:project/jobs/:id/cancel", :js do
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index df261c246f7..592c99fc64a 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -545,6 +545,40 @@ describe 'Pipelines', :js do
end
end
end
+
+ describe 'Reset runner caches' do
+ let(:project) { create(:project, :repository) }
+
+ before do
+ create(:ci_empty_pipeline, status: 'success', project: project, sha: project.commit.id, ref: 'master')
+ project.add_master(user)
+ visit project_pipelines_path(project)
+ end
+
+ it 'has a clear caches button' do
+ expect(page).to have_link 'Clear runner caches'
+ end
+
+ describe 'user clicks the button' do
+ context 'when project already has jobs_cache_index' do
+ before do
+ project.update_attributes(jobs_cache_index: 1)
+ end
+
+ it 'increments jobs_cache_index' do
+ click_link 'Clear runner caches'
+ expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
+ end
+ end
+
+ context 'when project does not have jobs_cache_index' do
+ it 'sets jobs_cache_index to 1' do
+ click_link 'Clear runner caches'
+ expect(page.find('.flash-notice')).to have_content 'Project cache successfully reset.'
+ end
+ end
+ end
+ end
end
context 'when user is not logged in' do
diff --git a/spec/fixtures/api/schemas/entities/merge_request_basic.json b/spec/fixtures/api/schemas/entities/merge_request_basic.json
index 995f13381ad..f1199468d53 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_basic.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_basic.json
@@ -9,6 +9,7 @@
"human_time_estimate": { "type": ["string", "null"] },
"human_total_time_spent": { "type": ["string", "null"] },
"merge_error": { "type": ["string", "null"] },
+ "rebase_in_progress": { "type": "boolean" },
"assignee_id": { "type": ["integer", "null"] },
"subscribed": { "type": ["boolean", "null"] },
"participants": { "type": "array" }
diff --git a/spec/fixtures/api/schemas/entities/merge_request_widget.json b/spec/fixtures/api/schemas/entities/merge_request_widget.json
index 9de27bee751..7f662098216 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_widget.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_widget.json
@@ -103,7 +103,11 @@
"remove_source_branch": { "type": ["boolean", "null"] },
"merge_ongoing": { "type": "boolean" },
"ff_only_enabled": { "type": ["boolean", false] },
- "should_be_rebased": { "type": "boolean" }
+ "should_be_rebased": { "type": "boolean" },
+ "rebase_commit_sha": { "type": ["string", "null"] },
+ "rebase_in_progress": { "type": "boolean" },
+ "can_push_to_source_branch": { "type": "boolean" },
+ "rebase_path": { "type": ["string", "null"] }
},
"additionalProperties": false
}
diff --git a/spec/javascripts/fixtures/pipelines.html.haml b/spec/javascripts/fixtures/pipelines.html.haml
index 85ee61f0b54..0161c0550d1 100644
--- a/spec/javascripts/fixtures/pipelines.html.haml
+++ b/spec/javascripts/fixtures/pipelines.html.haml
@@ -7,4 +7,6 @@
"new-pipeline-path" => 'foo',
"can-create-pipeline" => 'true',
"has-ci" => 'foo',
- "ci-lint-path" => 'foo' } }
+ "ci-lint-path" => 'foo',
+ "reset-cache-path" => 'foo' } }
+
diff --git a/spec/javascripts/jobs/header_spec.js b/spec/javascripts/jobs/header_spec.js
index 4a210faa017..83395ea451e 100644
--- a/spec/javascripts/jobs/header_spec.js
+++ b/spec/javascripts/jobs/header_spec.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import headerComponent from '~/jobs/components/header.vue';
+import mountComponent from '../helpers/vue_mount_component_helper';
describe('Job details header', () => {
let HeaderComponent;
@@ -35,7 +36,7 @@ describe('Job details header', () => {
isLoading: false,
};
- vm = new HeaderComponent({ propsData: props }).$mount();
+ vm = mountComponent(HeaderComponent, props);
});
afterEach(() => {
diff --git a/spec/javascripts/monitoring/graph/deployment_spec.js b/spec/javascripts/monitoring/graph/deployment_spec.js
index bf6ada8185e..d07db871d69 100644
--- a/spec/javascripts/monitoring/graph/deployment_spec.js
+++ b/spec/javascripts/monitoring/graph/deployment_spec.js
@@ -11,168 +11,38 @@ const createComponent = (propsData) => {
};
describe('MonitoringDeployment', () => {
- const reducedDeploymentData = [deploymentData[0]];
- reducedDeploymentData[0].ref = reducedDeploymentData[0].ref.name;
- reducedDeploymentData[0].xPos = 10;
- reducedDeploymentData[0].time = new Date(reducedDeploymentData[0].created_at);
describe('Methods', () => {
- it('refText shows the ref when a tag is available', () => {
- reducedDeploymentData[0].tag = '1.0';
- const component = createComponent({
- showDeployInfo: false,
- deploymentData: reducedDeploymentData,
- graphWidth: 440,
- graphHeight: 300,
- graphHeightOffset: 120,
- });
-
- expect(
- component.refText(reducedDeploymentData[0]),
- ).toEqual(reducedDeploymentData[0].ref);
- });
-
- it('refText shows the sha when no tag is available', () => {
- reducedDeploymentData[0].tag = null;
- const component = createComponent({
- showDeployInfo: false,
- deploymentData: reducedDeploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(
- component.refText(reducedDeploymentData[0]),
- ).toContain('f5bcd1');
- });
-
- it('nameDeploymentClass creates a class with the prefix deploy-info-', () => {
+ it('should contain a hidden gradient', () => {
const component = createComponent({
- showDeployInfo: false,
- deploymentData: reducedDeploymentData,
+ showDeployInfo: true,
+ deploymentData,
graphHeight: 300,
graphWidth: 440,
graphHeightOffset: 120,
});
- expect(
- component.nameDeploymentClass(reducedDeploymentData[0]),
- ).toContain('deploy-info');
+ expect(component.$el.querySelector('#shadow-gradient')).not.toBeNull();
});
it('transformDeploymentGroup translates an available deployment', () => {
const component = createComponent({
showDeployInfo: false,
- deploymentData: reducedDeploymentData,
+ deploymentData,
graphHeight: 300,
graphWidth: 440,
graphHeightOffset: 120,
});
expect(
- component.transformDeploymentGroup(reducedDeploymentData[0]),
+ component.transformDeploymentGroup({ xPos: 16 }),
).toContain('translate(11, 20)');
});
- it('hides the deployment flag', () => {
- reducedDeploymentData[0].showDeploymentFlag = false;
- const component = createComponent({
- showDeployInfo: true,
- deploymentData: reducedDeploymentData,
- graphWidth: 440,
- graphHeight: 300,
- graphHeightOffset: 120,
- });
-
- expect(component.$el.querySelector('.js-deploy-info-box')).toBeNull();
- });
-
- it('positions the flag to the left when the xPos is too far right', () => {
- reducedDeploymentData[0].showDeploymentFlag = false;
- reducedDeploymentData[0].xPos = 250;
- const component = createComponent({
- showDeployInfo: true,
- deploymentData: reducedDeploymentData,
- graphWidth: 440,
- graphHeight: 300,
- graphHeightOffset: 120,
- });
-
- expect(
- component.positionFlag(reducedDeploymentData[0]),
- ).toBeLessThan(0);
- });
-
- it('shows the deployment flag', () => {
- reducedDeploymentData[0].showDeploymentFlag = true;
- const component = createComponent({
- showDeployInfo: true,
- deploymentData: reducedDeploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(
- component.$el.querySelector('.js-deploy-info-box').style.display,
- ).not.toEqual('display: none;');
- });
-
- it('contains date, refs and the "deployed" text', () => {
- reducedDeploymentData[0].showDeploymentFlag = true;
- const component = createComponent({
- showDeployInfo: true,
- deploymentData: reducedDeploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(
- component.$el.querySelectorAll('.deploy-info-text'),
- ).toContainText('Deployed');
-
- expect(
- component.$el.querySelectorAll('.deploy-info-text'),
- ).toContainText('Wed, May 31');
-
- expect(
- component.$el.querySelectorAll('.deploy-info-text'),
- ).toContainText(component.refText(reducedDeploymentData[0]));
- });
-
- it('contains a link to the commit contents', () => {
- reducedDeploymentData[0].showDeploymentFlag = true;
- const component = createComponent({
- showDeployInfo: true,
- deploymentData: reducedDeploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(
- component.$el.querySelectorAll('.deploy-info-text-link')[0].parentElement.getAttribute('xlink:href'),
- ).not.toEqual('');
- });
-
- it('should contain a hidden gradient', () => {
- const component = createComponent({
- showDeployInfo: true,
- deploymentData: reducedDeploymentData,
- graphHeight: 300,
- graphWidth: 440,
- graphHeightOffset: 120,
- });
-
- expect(component.$el.querySelector('#shadow-gradient')).not.toBeNull();
- });
-
describe('Computed props', () => {
it('calculatedHeight', () => {
const component = createComponent({
showDeployInfo: true,
- deploymentData: reducedDeploymentData,
+ deploymentData,
graphHeight: 300,
graphWidth: 440,
graphHeightOffset: 120,
diff --git a/spec/javascripts/monitoring/graph/flag_spec.js b/spec/javascripts/monitoring/graph/flag_spec.js
index 8ee1171419d..2d474e9092f 100644
--- a/spec/javascripts/monitoring/graph/flag_spec.js
+++ b/spec/javascripts/monitoring/graph/flag_spec.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import GraphFlag from '~/monitoring/components/graph/flag.vue';
+import { deploymentData } from '../mock_data';
const createComponent = (propsData) => {
const Component = Vue.extend(GraphFlag);
@@ -9,11 +10,6 @@ const createComponent = (propsData) => {
}).$mount();
};
-function getCoordinate(component, selector, coordinate) {
- const coordinateVal = component.$el.querySelector(selector).getAttribute(coordinate);
- return parseInt(coordinateVal, 10);
-}
-
const defaultValuesComponent = {
currentXCoordinate: 200,
currentYCoordinate: 100,
@@ -25,31 +21,111 @@ const defaultValuesComponent = {
graphHeight: 300,
graphHeightOffset: 120,
showFlagContent: true,
+ realPixelRatio: 1,
+ timeSeries: [{
+ values: [{
+ time: new Date('2017-06-04T18:17:33.501Z'),
+ value: '1.49609375',
+ }],
+ }],
+ unitOfDisplay: 'ms',
+ currentDataIndex: 0,
+ legendTitle: 'Average',
+};
+
+const deploymentFlagData = {
+ ...deploymentData[0],
+ ref: deploymentData[0].ref.name,
+ xPos: 10,
+ time: new Date(deploymentData[0].created_at),
};
describe('GraphFlag', () => {
- it('has a line and a circle located at the currentXCoordinate and currentYCoordinate', () => {
- const component = createComponent(defaultValuesComponent);
+ let component;
- expect(getCoordinate(component, '.selected-metric-line', 'x1'))
- .toEqual(component.currentXCoordinate);
- expect(getCoordinate(component, '.selected-metric-line', 'x2'))
- .toEqual(component.currentXCoordinate);
+ it('has a line at the currentXCoordinate', () => {
+ component = createComponent(defaultValuesComponent);
+
+ expect(component.$el.style.left)
+ .toEqual(`${70 + component.currentXCoordinate}px`);
});
- it('has a SVG with the class rect-text-metric at the currentFlagPosition', () => {
- const component = createComponent(defaultValuesComponent);
+ describe('Deployment flag', () => {
+ it('shows a deployment flag when deployment data provided', () => {
+ const deploymentFlagComponent = createComponent({
+ ...defaultValuesComponent,
+ deploymentFlagData,
+ });
+
+ expect(
+ deploymentFlagComponent.$el.querySelector('.popover-title'),
+ ).toContainText('Deployed');
+ });
+
+ it('contains the ref when a tag is available', () => {
+ const deploymentFlagComponent = createComponent({
+ ...defaultValuesComponent,
+ deploymentFlagData: {
+ ...deploymentFlagData,
+ sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
+ tag: true,
+ ref: '1.0',
+ },
+ });
+
+ expect(
+ deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
+ ).toContainText('f5bcd1d9');
+
+ expect(
+ deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
+ ).toContainText('1.0');
+ });
+
+ it('does not contain the ref when a tag is unavailable', () => {
+ const deploymentFlagComponent = createComponent({
+ ...defaultValuesComponent,
+ deploymentFlagData: {
+ ...deploymentFlagData,
+ sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
+ tag: false,
+ ref: '1.0',
+ },
+ });
+
+ expect(
+ deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
+ ).toContainText('f5bcd1d9');
- const svg = component.$el.querySelector('.rect-text-metric');
- expect(svg.tagName).toEqual('svg');
- expect(parseInt(svg.getAttribute('x'), 10)).toEqual(component.currentFlagPosition);
+ expect(
+ deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
+ ).not.toContainText('1.0');
+ });
});
describe('Computed props', () => {
- it('calculatedHeight', () => {
- const component = createComponent(defaultValuesComponent);
+ beforeEach(() => {
+ component = createComponent(defaultValuesComponent);
+ });
+
+ it('formatTime', () => {
+ expect(component.formatTime).toMatch(/\d:17PM/);
+ });
+
+ it('formatDate', () => {
+ expect(component.formatDate).toEqual('Sun, Jun 4');
+ });
+
+ it('cursorStyle', () => {
+ expect(component.cursorStyle).toEqual({
+ top: '20px',
+ left: '270px',
+ height: '180px',
+ });
+ });
- expect(component.calculatedHeight).toEqual(180);
+ it('flagOrientation', () => {
+ expect(component.flagOrientation).toEqual('left');
});
});
});
diff --git a/spec/javascripts/pipelines/nav_controls_spec.js b/spec/javascripts/pipelines/nav_controls_spec.js
index f1697840fcd..09a0c14d96c 100644
--- a/spec/javascripts/pipelines/nav_controls_spec.js
+++ b/spec/javascripts/pipelines/nav_controls_spec.js
@@ -14,6 +14,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
+ resetCachePath: 'foo',
canCreatePipeline: true,
};
@@ -31,6 +32,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
+ resetCachePath: 'foo',
canCreatePipeline: false,
};
@@ -41,12 +43,31 @@ describe('Pipelines Nav Controls', () => {
expect(component.$el.querySelector('.btn-create')).toEqual(null);
});
+ it('should render link for resetting runner caches', () => {
+ const mockData = {
+ newPipelinePath: 'foo',
+ hasCiEnabled: true,
+ helpPagePath: 'foo',
+ ciLintPath: 'foo',
+ resetCachePath: 'foo',
+ canCreatePipeline: false,
+ };
+
+ const component = new NavControlsComponent({
+ propsData: mockData,
+ }).$mount();
+
+ expect(component.$el.querySelectorAll('.btn-default')[0].textContent).toContain('Clear runner caches');
+ expect(component.$el.querySelectorAll('.btn-default')[0].getAttribute('href')).toEqual(mockData.resetCachePath);
+ });
+
it('should render link for CI lint', () => {
const mockData = {
newPipelinePath: 'foo',
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
+ resetCachePath: 'foo',
canCreatePipeline: true,
};
@@ -54,8 +75,8 @@ describe('Pipelines Nav Controls', () => {
propsData: mockData,
}).$mount();
- expect(component.$el.querySelector('.btn-default').textContent).toContain('CI Lint');
- expect(component.$el.querySelector('.btn-default').getAttribute('href')).toEqual(mockData.ciLintPath);
+ expect(component.$el.querySelectorAll('.btn-default')[1].textContent).toContain('CI Lint');
+ expect(component.$el.querySelectorAll('.btn-default')[1].getAttribute('href')).toEqual(mockData.ciLintPath);
});
it('should render link to help page when CI is not enabled', () => {
@@ -64,6 +85,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: false,
helpPagePath: 'foo',
ciLintPath: 'foo',
+ resetCachePath: 'foo',
canCreatePipeline: true,
};
@@ -81,6 +103,7 @@ describe('Pipelines Nav Controls', () => {
hasCiEnabled: true,
helpPagePath: 'foo',
ciLintPath: 'foo',
+ resetCachePath: 'foo',
canCreatePipeline: true,
};
diff --git a/spec/javascripts/repo/components/ide_repo_tree_spec.js b/spec/javascripts/repo/components/ide_repo_tree_spec.js
index b6f70f585cd..e3bbda514da 100644
--- a/spec/javascripts/repo/components/ide_repo_tree_spec.js
+++ b/spec/javascripts/repo/components/ide_repo_tree_spec.js
@@ -41,11 +41,11 @@ describe('IdeRepoTree', () => {
expect(tbody.querySelector('.file')).toBeTruthy();
});
- it('renders 5 loading files if tree is loading', (done) => {
- vm.$store.state.loading = true;
+ it('renders 3 loading files if tree is loading', (done) => {
+ vm.treeId = '123';
Vue.nextTick(() => {
- expect(vm.$el.querySelectorAll('tbody .loading-file').length).toEqual(5);
+ expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toEqual(3);
done();
});
diff --git a/spec/javascripts/repo/components/ide_spec.js b/spec/javascripts/repo/components/ide_spec.js
index 20b8dc25dcb..acfd63eb8de 100644
--- a/spec/javascripts/repo/components/ide_spec.js
+++ b/spec/javascripts/repo/components/ide_spec.js
@@ -10,7 +10,9 @@ describe('ide component', () => {
beforeEach(() => {
const Component = Vue.extend(ide);
- vm = createComponentWithStore(Component, store).$mount();
+ vm = createComponentWithStore(Component, store, {
+ emptyStateSvgPath: 'svg',
+ }).$mount();
});
afterEach(() => {
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js
new file mode 100644
index 00000000000..66ecaa316c8
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js
@@ -0,0 +1,115 @@
+import Vue from 'vue';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import component from '~/vue_merge_request_widget/components/states/mr_widget_rebase.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('Merge request widget rebase component', () => {
+ let Component;
+ let vm;
+ beforeEach(() => {
+ Component = Vue.extend(component);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('While rebasing', () => {
+ it('should show progress message', () => {
+ vm = mountComponent(Component, {
+ mr: { rebaseInProgress: true },
+ service: {},
+ });
+
+ expect(
+ vm.$el.querySelector('.rebase-state-find-class-convention span').textContent.trim(),
+ ).toContain('Rebase in progress');
+ });
+ });
+
+ describe('With permissions', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: true,
+ },
+ service: {},
+ });
+ });
+
+ it('it should render rebase button and warning message', () => {
+ const text = vm.$el.querySelector('.rebase-state-find-class-convention span').textContent.trim();
+ expect(text).toContain('Fast-forward merge is not possible.');
+ expect(text).toContain('Rebase the source branch onto the target branch or merge target');
+ expect(text).toContain('branch into source branch to allow this merge request to be merged.');
+ });
+
+ it('it should render error message when it fails', (done) => {
+ vm.rebasingError = 'Something went wrong!';
+
+ Vue.nextTick(() => {
+ expect(
+ vm.$el.querySelector('.rebase-state-find-class-convention span').textContent.trim(),
+ ).toContain('Something went wrong!');
+ done();
+ });
+ });
+ });
+
+ describe('Without permissions', () => {
+ it('should render a message explaining user does not have permissions', () => {
+ vm = mountComponent(Component, {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: false,
+ targetBranch: 'foo',
+ },
+ service: {},
+ });
+
+ const text = vm.$el.querySelector('.rebase-state-find-class-convention span').textContent.trim();
+
+ expect(text).toContain('Fast-forward merge is not possible.');
+ expect(text).toContain('Rebase the source branch onto');
+ expect(text).toContain('foo');
+ expect(text).toContain('to allow this merge request to be merged.');
+ });
+ });
+
+ describe('methods', () => {
+ it('checkRebaseStatus', (done) => {
+ spyOn(eventHub, '$emit');
+ vm = mountComponent(Component, {
+ mr: {},
+ service: {
+ rebase() {
+ return Promise.resolve();
+ },
+ poll() {
+ return Promise.resolve({
+ data: {
+ rebase_in_progress: false,
+ merge_error: null,
+ },
+ });
+ },
+ },
+ });
+
+ vm.rebase();
+
+ // Wait for the rebase request
+ vm.$nextTick()
+ // Wait for the polling request
+ .then(vm.$nextTick())
+ // Wait for the eventHub to be called
+ .then(vm.$nextTick())
+ .then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/header_ci_component_spec.js b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
index b4553acb341..b378a0bd896 100644
--- a/spec/javascripts/vue_shared/components/header_ci_component_spec.js
+++ b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import headerCi from '~/vue_shared/components/header_ci_component.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Header CI Component', () => {
let HeaderCi;
@@ -8,7 +9,6 @@ describe('Header CI Component', () => {
beforeEach(() => {
HeaderCi = Vue.extend(headerCi);
-
props = {
status: {
group: 'failed',
@@ -45,54 +45,65 @@ describe('Header CI Component', () => {
],
hasSidebarButton: true,
};
-
- vm = new HeaderCi({
- propsData: props,
- }).$mount();
});
afterEach(() => {
vm.$destroy();
});
- it('should render status badge', () => {
- expect(vm.$el.querySelector('.ci-failed')).toBeDefined();
- expect(vm.$el.querySelector('.ci-status-icon-failed svg')).toBeDefined();
- expect(
- vm.$el.querySelector('.ci-failed').getAttribute('href'),
- ).toEqual(props.status.details_path);
- });
+ describe('render', () => {
+ beforeEach(() => {
+ vm = mountComponent(HeaderCi, props);
+ });
- it('should render item name and id', () => {
- expect(vm.$el.querySelector('strong').textContent.trim()).toEqual('job #123');
- });
+ it('should render status badge', () => {
+ expect(vm.$el.querySelector('.ci-failed')).toBeDefined();
+ expect(vm.$el.querySelector('.ci-status-icon-failed svg')).toBeDefined();
+ expect(
+ vm.$el.querySelector('.ci-failed').getAttribute('href'),
+ ).toEqual(props.status.details_path);
+ });
- it('should render timeago date', () => {
- expect(vm.$el.querySelector('time')).toBeDefined();
- });
+ it('should render item name and id', () => {
+ expect(vm.$el.querySelector('strong').textContent.trim()).toEqual('job #123');
+ });
- it('should render user icon and name', () => {
- expect(vm.$el.querySelector('.js-user-link').textContent.trim()).toEqual(props.user.name);
- });
+ it('should render timeago date', () => {
+ expect(vm.$el.querySelector('time')).toBeDefined();
+ });
- it('should render provided actions', () => {
- expect(vm.$el.querySelector('.btn').tagName).toEqual('BUTTON');
- expect(vm.$el.querySelector('.btn').textContent.trim()).toEqual(props.actions[0].label);
- expect(vm.$el.querySelector('.link').tagName).toEqual('A');
- expect(vm.$el.querySelector('.link').textContent.trim()).toEqual(props.actions[1].label);
- expect(vm.$el.querySelector('.link').getAttribute('href')).toEqual(props.actions[0].path);
- });
+ it('should render user icon and name', () => {
+ expect(vm.$el.querySelector('.js-user-link').textContent.trim()).toEqual(props.user.name);
+ });
+
+ it('should render provided actions', () => {
+ expect(vm.$el.querySelector('.btn').tagName).toEqual('BUTTON');
+ expect(vm.$el.querySelector('.btn').textContent.trim()).toEqual(props.actions[0].label);
+ expect(vm.$el.querySelector('.link').tagName).toEqual('A');
+ expect(vm.$el.querySelector('.link').textContent.trim()).toEqual(props.actions[1].label);
+ expect(vm.$el.querySelector('.link').getAttribute('href')).toEqual(props.actions[0].path);
+ });
- it('should show loading icon', (done) => {
- vm.actions[0].isLoading = true;
+ it('should show loading icon', (done) => {
+ vm.actions[0].isLoading = true;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn .fa-spinner').getAttribute('style')).toBeFalsy();
- done();
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.btn .fa-spinner').getAttribute('style')).toBeFalsy();
+ done();
+ });
+ });
+
+ it('should render sidebar toggle button', () => {
+ expect(vm.$el.querySelector('.js-sidebar-build-toggle')).toBeDefined();
});
});
- it('should render sidebar toggle button', () => {
- expect(vm.$el.querySelector('.js-sidebar-build-toggle')).toBeDefined();
+ describe('shouldRenderTriggeredLabel', () => {
+ it('should rendered created keyword when the shouldRenderTriggeredLabel is false', () => {
+ vm = mountComponent(HeaderCi, { ...props, shouldRenderTriggeredLabel: false });
+
+ expect(vm.$el.textContent).toContain('created');
+ expect(vm.$el.textContent).not.toContain('triggered');
+ });
});
});
diff --git a/spec/lib/banzai/filter/mermaid_filter_spec.rb b/spec/lib/banzai/filter/mermaid_filter_spec.rb
index 532d25e121d..f6474c8936d 100644
--- a/spec/lib/banzai/filter/mermaid_filter_spec.rb
+++ b/spec/lib/banzai/filter/mermaid_filter_spec.rb
@@ -3,9 +3,9 @@ require 'spec_helper'
describe Banzai::Filter::MermaidFilter do
include FilterSpecHelper
- it 'adds `js-render-mermaid` class to the `pre` tag' do
+ it 'adds `js-render-mermaid` class to the `code` tag' do
doc = filter("<pre class='code highlight js-syntax-highlight mermaid' lang='mermaid' v-pre='true'><code>graph TD;\n A--&gt;B;\n</code></pre>")
- result = doc.xpath('descendant-or-self::pre').first
+ result = doc.css('code').first
expect(result[:class]).to include('js-render-mermaid')
end
diff --git a/spec/lib/gitlab/background_migration/prepare_untracked_uploads_spec.rb b/spec/lib/gitlab/background_migration/prepare_untracked_uploads_spec.rb
index cd3f1a45270..8bb9ebe0419 100644
--- a/spec/lib/gitlab/background_migration/prepare_untracked_uploads_spec.rb
+++ b/spec/lib/gitlab/background_migration/prepare_untracked_uploads_spec.rb
@@ -2,21 +2,10 @@ require 'spec_helper'
describe Gitlab::BackgroundMigration::PrepareUntrackedUploads, :sidekiq do
include TrackUntrackedUploadsHelpers
+ include MigrationsHelpers
let!(:untracked_files_for_uploads) { described_class::UntrackedFile }
- matcher :be_scheduled_migration do |*expected|
- match do |migration|
- BackgroundMigrationWorker.jobs.any? do |job|
- job['args'] == [migration, expected]
- end
- end
-
- failure_message do |migration|
- "Migration `#{migration}` with args `#{expected.inspect}` not scheduled!"
- end
- end
-
before do
DatabaseCleaner.clean
diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb
index 28ea7d4c303..38a47a159e1 100644
--- a/spec/lib/gitlab/cycle_analytics/events_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb
@@ -122,17 +122,18 @@ describe 'cycle analytics events' do
let(:stage) { :test }
let(:merge_request) { MergeRequest.first }
+
let!(:pipeline) do
create(:ci_pipeline,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha,
- project: context.project,
+ project: project,
head_pipeline_of: merge_request)
end
before do
- create(:ci_build, pipeline: pipeline, status: :success, author: user)
- create(:ci_build, pipeline: pipeline, status: :success, author: user)
+ create(:ci_build, :success, pipeline: pipeline, author: user)
+ create(:ci_build, :success, pipeline: pipeline, author: user)
pipeline.run!
pipeline.succeed!
@@ -219,17 +220,18 @@ describe 'cycle analytics events' do
describe '#staging_events' do
let(:stage) { :staging }
let(:merge_request) { MergeRequest.first }
+
let!(:pipeline) do
create(:ci_pipeline,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha,
- project: context.project,
+ project: project,
head_pipeline_of: merge_request)
end
before do
- create(:ci_build, pipeline: pipeline, status: :success, author: user)
- create(:ci_build, pipeline: pipeline, status: :success, author: user)
+ create(:ci_build, :success, pipeline: pipeline, author: user)
+ create(:ci_build, :success, pipeline: pipeline, author: user)
pipeline.run!
pipeline.succeed!
diff --git a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
index d81774c8b8f..a067c42b75b 100644
--- a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
+++ b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
@@ -19,4 +19,18 @@ describe Gitlab::Diff::FileCollection::MergeRequestDiff do
diff_files
end
+
+ shared_examples 'initializes a DiffCollection' do
+ it 'returns a valid instance of a DiffCollection' do
+ expect(diff_files).to be_a(Gitlab::Git::DiffCollection)
+ end
+ end
+
+ context 'with Gitaly disabled', :disable_gitaly do
+ it_behaves_like 'initializes a DiffCollection'
+ end
+
+ context 'with Gitaly enabled' do
+ it_behaves_like 'initializes a DiffCollection'
+ end
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index 7f5946b1658..07eb5b82d5f 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -146,7 +146,7 @@ describe Gitlab::Git::Blob, seed_helper: true do
context 'when sha references a tree' do
it 'returns nil' do
- tree = Gitlab::Git::Commit.find(repository, 'master').tree
+ tree = repository.rugged.rev_parse('master^{tree}')
blob = Gitlab::Git::Blob.raw(repository, tree.oid)
@@ -230,7 +230,7 @@ describe Gitlab::Git::Blob, seed_helper: true do
end
describe '.batch_lfs_pointers' do
- let(:tree_object) { Gitlab::Git::Commit.find(repository, 'master').tree }
+ let(:tree_object) { repository.rugged.rev_parse('master^{tree}') }
let(:non_lfs_blob) do
Gitlab::Git::Blob.find(
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 6d35734d306..6a07a3ca8b8 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -55,7 +55,6 @@ describe Gitlab::Git::Commit, seed_helper: true do
it { expect(@commit.parents).to eq(@gitlab_parents) }
it { expect(@commit.parent_id).to eq(@parents.first.oid) }
it { expect(@commit.no_commit_message).to eq("--no commit message") }
- it { expect(@commit.tree).to eq(@tree) }
after do
# Erase the new commit so other tests get the original repo
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index faccc2c8e00..f346a345f00 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -649,29 +649,39 @@ describe Gitlab::Git::Repository, seed_helper: true do
Gitlab::Shell.new.remove_repository(storage_path, 'my_project')
end
- it 'fetches a repository as a mirror remote' do
- subject
+ shared_examples 'repository mirror fecthing' do
+ it 'fetches a repository as a mirror remote' do
+ subject
- expect(refs(new_repository.path)).to eq(refs(repository.path))
- end
+ expect(refs(new_repository.path)).to eq(refs(repository.path))
+ end
- context 'with keep-around refs' do
- let(:sha) { SeedRepo::Commit::ID }
- let(:keep_around_ref) { "refs/keep-around/#{sha}" }
- let(:tmp_ref) { "refs/tmp/#{SecureRandom.hex}" }
+ context 'with keep-around refs' do
+ let(:sha) { SeedRepo::Commit::ID }
+ let(:keep_around_ref) { "refs/keep-around/#{sha}" }
+ let(:tmp_ref) { "refs/tmp/#{SecureRandom.hex}" }
- before do
- repository.rugged.references.create(keep_around_ref, sha, force: true)
- repository.rugged.references.create(tmp_ref, sha, force: true)
- end
+ before do
+ repository.rugged.references.create(keep_around_ref, sha, force: true)
+ repository.rugged.references.create(tmp_ref, sha, force: true)
+ end
- it 'includes the temporary and keep-around refs' do
- subject
+ it 'includes the temporary and keep-around refs' do
+ subject
- expect(refs(new_repository.path)).to include(keep_around_ref)
- expect(refs(new_repository.path)).to include(tmp_ref)
+ expect(refs(new_repository.path)).to include(keep_around_ref)
+ expect(refs(new_repository.path)).to include(tmp_ref)
+ end
end
end
+
+ context 'with gitaly enabled' do
+ it_behaves_like 'repository mirror fecthing'
+ end
+
+ context 'with gitaly enabled', :skip_gitaly_mock do
+ it_behaves_like 'repository mirror fecthing'
+ end
end
describe '#remote_tags' do
@@ -1030,14 +1040,52 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
+ context 'with max_count' do
+ it 'returns the number of commits with path ' do
+ options = { ref: 'master', max_count: 5 }
+
+ expect(repository.count_commits(options)).to eq(5)
+ end
+ end
+
context 'with path' do
it 'returns the number of commits with path ' do
- options = { ref: 'master', path: "encoding" }
+ options = { ref: 'master', path: 'encoding' }
expect(repository.count_commits(options)).to eq(2)
end
end
+ context 'with option :from and option :to' do
+ it 'returns the number of commits ahead for fix-mode..fix-blob-path' do
+ options = { from: 'fix-mode', to: 'fix-blob-path' }
+
+ expect(repository.count_commits(options)).to eq(2)
+ end
+
+ it 'returns the number of commits ahead for fix-blob-path..fix-mode' do
+ options = { from: 'fix-blob-path', to: 'fix-mode' }
+
+ expect(repository.count_commits(options)).to eq(1)
+ end
+
+ context 'with option :left_right' do
+ it 'returns the number of commits for fix-mode...fix-blob-path' do
+ options = { from: 'fix-mode', to: 'fix-blob-path', left_right: true }
+
+ expect(repository.count_commits(options)).to eq([1, 2])
+ end
+
+ context 'with max_count' do
+ it 'returns the number of commits with path ' do
+ options = { from: 'fix-mode', to: 'fix-blob-path', left_right: true, max_count: 1 }
+
+ expect(repository.count_commits(options)).to eq([1, 1])
+ end
+ end
+ end
+ end
+
context 'with max_count' do
it 'returns the number of commits up to the passed limit' do
options = { ref: 'master', max_count: 10, after: Time.iso8601('2013-03-03T20:15:01+00:00') }
diff --git a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
index 69c6f054016..9d540446532 100644
--- a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
@@ -31,4 +31,17 @@ describe Gitlab::GitalyClient::RemoteService do
expect(client.remove_remote(remote_name)).to be(true)
end
end
+
+ describe '#fetch_internal_remote' do
+ let(:remote_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
+
+ it 'sends an fetch_internal_remote message and returns the result value' do
+ expect_any_instance_of(Gitaly::RemoteService::Stub)
+ .to receive(:fetch_internal_remote)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(result: true))
+
+ expect(client.fetch_internal_remote(remote_repository)).to be(true)
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index f0752649121..7580b62cfc0 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -6465,78 +6465,100 @@
}
}
],
- "statuses": [
- {
- "id": 71,
- "project_id": 5,
- "status": "failed",
- "finished_at": "2016-03-29T06:28:12.630Z",
- "trace": null,
- "created_at": "2016-03-22T15:20:35.772Z",
- "updated_at": "2016-03-29T06:28:12.634Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 36,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 1",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": null
- },
- "artifacts_metadata": {
- "url": null
- },
- "erased_by_id": null,
- "erased_at": null,
- "type": "Ci::Build",
- "token": "abcd"
- },
- {
- "id": 72,
- "project_id": 5,
- "status": "success",
- "finished_at": null,
- "trace": "Porro ea qui ut dolores. Labore ab nemo explicabo aspernatur quis voluptates corporis. Et quasi delectus est sit aperiam perspiciatis asperiores. Repudiandae cum aut consectetur accusantium officia sunt.\n\nQuidem dolore iusto quaerat ut aut inventore et molestiae. Libero voluptates atque nemo qui. Nulla temporibus ipsa similique facere.\n\nAliquam ipsam perferendis qui fugit accusantium omnis id voluptatum. Dignissimos aliquid dicta eos voluptatem assumenda quia. Sed autem natus unde dolor et non nisi et. Consequuntur nihil consequatur rerum est.\n\nSimilique neque est iste ducimus qui fuga cupiditate. Libero autem est aut fuga. Consectetur natus quis non ducimus ut dolore. Magni voluptatibus eius et maxime aut.\n\nAd officiis tempore voluptate vitae corrupti explicabo labore est. Consequatur expedita et sunt nihil aut. Deleniti porro iusto molestiae et beatae.\n\nDeleniti modi nulla qui et labore sequi corrupti. Qui voluptatem assumenda eum cupiditate et. Nesciunt ipsam ut ea possimus eum. Consectetur quidem suscipit atque dolore itaque voluptatibus et cupiditate.",
- "created_at": "2016-03-22T15:20:35.777Z",
- "updated_at": "2016-03-22T15:20:35.777Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 36,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 2",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/72/p5_build_artifacts.zip"
- },
- "artifacts_metadata": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/72/p5_build_artifacts_metadata.gz"
- },
- "erased_by_id": null,
- "erased_at": null
+ "stages": [
+ {
+ "id": 11,
+ "project_id": 5,
+ "pipeline_id": 36,
+ "name": "test",
+ "status": 1,
+ "created_at": "2016-03-22T15:44:44.772Z",
+ "updated_at": "2016-03-29T06:44:44.634Z",
+ "statuses": [
+ {
+ "id": 71,
+ "project_id": 5,
+ "status": "failed",
+ "finished_at": "2016-03-29T06:28:12.630Z",
+ "trace": null,
+ "created_at": "2016-03-22T15:20:35.772Z",
+ "updated_at": "2016-03-29T06:28:12.634Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 36,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 1",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "stage_id": 11,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": null
+ },
+ "artifacts_metadata": {
+ "url": null
+ },
+ "erased_by_id": null,
+ "erased_at": null,
+ "type": "Ci::Build",
+ "token": "abcd"
+ },
+ {
+ "id": 72,
+ "project_id": 5,
+ "status": "success",
+ "finished_at": null,
+ "trace": "Porro ea qui ut dolores. Labore ab nemo explicabo aspernatur quis voluptates corporis. Et quasi delectus est sit aperiam perspiciatis asperiores. Repudiandae cum aut consectetur accusantium officia sunt.\n\nQuidem dolore iusto quaerat ut aut inventore et molestiae. Libero voluptates atque nemo qui. Nulla temporibus ipsa similique facere.\n\nAliquam ipsam perferendis qui fugit accusantium omnis id voluptatum. Dignissimos aliquid dicta eos voluptatem assumenda quia. Sed autem natus unde dolor et non nisi et. Consequuntur nihil consequatur rerum est.\n\nSimilique neque est iste ducimus qui fuga cupiditate. Libero autem est aut fuga. Consectetur natus quis non ducimus ut dolore. Magni voluptatibus eius et maxime aut.\n\nAd officiis tempore voluptate vitae corrupti explicabo labore est. Consequatur expedita et sunt nihil aut. Deleniti porro iusto molestiae et beatae.\n\nDeleniti modi nulla qui et labore sequi corrupti. Qui voluptatem assumenda eum cupiditate et. Nesciunt ipsam ut ea possimus eum. Consectetur quidem suscipit atque dolore itaque voluptatibus et cupiditate.",
+ "created_at": "2016-03-22T15:20:35.777Z",
+ "updated_at": "2016-03-22T15:20:35.777Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 36,
+ "commands": "$ deploy command",
+ "job_id": null,
+ "name": "test build 2",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "deploy",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "stage_id": 12,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/72/p5_build_artifacts.zip"
+ },
+ "artifacts_metadata": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/72/p5_build_artifacts_metadata.gz"
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ }
+ ]
+ },
+ {
+ "id": 12,
+ "project_id": 5,
+ "pipeline_id": 36,
+ "name": "deploy",
+ "status": 2,
+ "created_at": "2016-03-22T15:45:45.772Z",
+ "updated_at": "2016-03-29T06:45:45.634Z"
}
]
},
@@ -6556,76 +6578,87 @@
"started_at": null,
"finished_at": null,
"duration": null,
- "statuses": [
- {
- "id": 74,
- "project_id": 5,
- "status": "success",
- "finished_at": null,
- "trace": "Ad ut quod repudiandae iste dolor doloribus. Adipisci consequuntur deserunt omnis quasi eveniet et sed fugit. Aut nemo omnis molestiae impedit ex consequatur ducimus. Voluptatum exercitationem quia aut est et hic dolorem.\n\nQuasi repellendus et eaque magni eum facilis. Dolorem aperiam nam nihil pariatur praesentium ad aliquam. Commodi enim et eos tenetur. Odio voluptatibus laboriosam mollitia rerum exercitationem magnam consequuntur. Tenetur ea vel eum corporis.\n\nVoluptatibus optio in aliquid est voluptates. Ad a ut ab placeat vero blanditiis. Earum aspernatur quia beatae expedita voluptatem dignissimos provident. Quis minima id nemo ut aut est veritatis provident.\n\nRerum voluptatem quidem eius maiores magnam veniam. Voluptatem aperiam aut voluptate et nulla deserunt voluptas. Quaerat aut accusantium laborum est dolorem architecto reiciendis. Aliquam asperiores doloribus omnis maxime enim nesciunt. Eum aut rerum repellendus debitis et ut eius.\n\nQuaerat assumenda ea sit consequatur autem in. Cum eligendi voluptatem quo sed. Ut fuga iusto cupiditate autem sint.\n\nOfficia totam officiis architecto corporis molestiae amet ut. Tempora sed dolorum rerum omnis voluptatem accusantium sit eum. Quia debitis ipsum quidem aliquam inventore sunt consequatur qui.",
- "created_at": "2016-03-22T15:20:35.846Z",
- "updated_at": "2016-03-22T15:20:35.846Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 37,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 2",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/74/p5_build_artifacts.zip"
- },
- "artifacts_metadata": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/74/p5_build_artifacts_metadata.gz"
- },
- "erased_by_id": null,
- "erased_at": null
- },
- {
- "id": 73,
- "project_id": 5,
- "status": "canceled",
- "finished_at": null,
- "trace": null,
- "created_at": "2016-03-22T15:20:35.842Z",
- "updated_at": "2016-03-22T15:20:35.842Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 37,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 1",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": null
- },
- "artifacts_metadata": {
- "url": null
- },
- "erased_by_id": null,
- "erased_at": null
+ "stages": [
+ {
+ "id": 21,
+ "project_id": 5,
+ "pipeline_id": 37,
+ "name": "test",
+ "status": 1,
+ "created_at": "2016-03-22T15:44:44.772Z",
+ "updated_at": "2016-03-29T06:44:44.634Z",
+ "statuses": [
+ {
+ "id": 74,
+ "project_id": 5,
+ "status": "success",
+ "finished_at": null,
+ "trace": "Ad ut quod repudiandae iste dolor doloribus. Adipisci consequuntur deserunt omnis quasi eveniet et sed fugit. Aut nemo omnis molestiae impedit ex consequatur ducimus. Voluptatum exercitationem quia aut est et hic dolorem.\n\nQuasi repellendus et eaque magni eum facilis. Dolorem aperiam nam nihil pariatur praesentium ad aliquam. Commodi enim et eos tenetur. Odio voluptatibus laboriosam mollitia rerum exercitationem magnam consequuntur. Tenetur ea vel eum corporis.\n\nVoluptatibus optio in aliquid est voluptates. Ad a ut ab placeat vero blanditiis. Earum aspernatur quia beatae expedita voluptatem dignissimos provident. Quis minima id nemo ut aut est veritatis provident.\n\nRerum voluptatem quidem eius maiores magnam veniam. Voluptatem aperiam aut voluptate et nulla deserunt voluptas. Quaerat aut accusantium laborum est dolorem architecto reiciendis. Aliquam asperiores doloribus omnis maxime enim nesciunt. Eum aut rerum repellendus debitis et ut eius.\n\nQuaerat assumenda ea sit consequatur autem in. Cum eligendi voluptatem quo sed. Ut fuga iusto cupiditate autem sint.\n\nOfficia totam officiis architecto corporis molestiae amet ut. Tempora sed dolorum rerum omnis voluptatem accusantium sit eum. Quia debitis ipsum quidem aliquam inventore sunt consequatur qui.",
+ "created_at": "2016-03-22T15:20:35.846Z",
+ "updated_at": "2016-03-22T15:20:35.846Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 37,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 2",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/74/p5_build_artifacts.zip"
+ },
+ "artifacts_metadata": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/74/p5_build_artifacts_metadata.gz"
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ },
+ {
+ "id": 73,
+ "project_id": 5,
+ "status": "canceled",
+ "finished_at": null,
+ "trace": null,
+ "created_at": "2016-03-22T15:20:35.842Z",
+ "updated_at": "2016-03-22T15:20:35.842Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 37,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 1",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": null
+ },
+ "artifacts_metadata": {
+ "url": null
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ }
+ ]
}
]
},
@@ -6645,76 +6678,87 @@
"started_at": null,
"finished_at": null,
"duration": null,
- "statuses": [
- {
- "id": 76,
- "project_id": 5,
- "status": "success",
- "finished_at": null,
- "trace": "Et rerum quia ea cumque ut modi non. Libero eaque ipsam architecto maiores expedita deleniti. Ratione quia qui est id.\n\nQuod sit officiis sed unde inventore veniam quisquam velit. Ea harum cum quibusdam quisquam minima quo possimus non. Temporibus itaque aliquam aut rerum veritatis at.\n\nMagnam ipsum eius recusandae qui quis sit maiores eum. Et animi iusto aut itaque. Doloribus harum deleniti nobis accusantium et libero.\n\nRerum fuga perferendis magni commodi officiis id repudiandae. Consequatur ratione consequatur suscipit facilis sunt iure est dicta. Qui unde quasi facilis et quae nesciunt. Magnam iste et nobis officiis tenetur. Aspernatur quo et temporibus non in.\n\nNisi rerum velit est ad enim sint molestiae consequuntur. Quaerat nisi nesciunt quasi officiis. Possimus non blanditiis laborum quos.\n\nRerum laudantium facere animi qui. Ipsa est iusto magnam nihil. Enim omnis occaecati non dignissimos ut recusandae eum quasi. Qui maxime dolor et nemo voluptates incidunt quia.",
- "created_at": "2016-03-22T15:20:35.882Z",
- "updated_at": "2016-03-22T15:20:35.882Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 38,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 2",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/76/p5_build_artifacts.zip"
- },
- "artifacts_metadata": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/76/p5_build_artifacts_metadata.gz"
- },
- "erased_by_id": null,
- "erased_at": null
- },
- {
- "id": 75,
- "project_id": 5,
- "status": "failed",
- "finished_at": null,
- "trace": "Sed et iste recusandae dicta corporis. Sunt alias porro fugit sunt. Fugiat omnis nihil dignissimos aperiam explicabo doloremque sit aut. Harum fugit expedita quia rerum ut consequatur laboriosam aliquam.\n\nNatus libero ut ut tenetur earum. Tempora omnis autem omnis et libero dolores illum autem. Deleniti eos sunt mollitia ipsam. Cum dolor repellendus dolorum sequi officia. Ullam sunt in aut pariatur excepturi.\n\nDolor nihil debitis et est eos. Cumque eos eum saepe ducimus autem. Alias architecto consequatur aut pariatur possimus. Aut quos aut incidunt quam velit et. Quas voluptatum ad dolorum dignissimos.\n\nUt voluptates consectetur illo et. Est commodi accusantium vel quo. Eos qui fugiat soluta porro.\n\nRatione possimus alias vel maxime sint totam est repellat. Ipsum corporis eos sint voluptatem eos odit. Temporibus libero nulla harum eligendi labore similique ratione magnam. Suscipit sequi in omnis neque.\n\nLaudantium dolor amet omnis placeat mollitia aut molestiae. Aut rerum similique ipsum quod illo quas unde. Sunt aut veritatis eos omnis porro. Rem veritatis mollitia praesentium dolorem. Consequatur sequi ad cumque earum omnis quia necessitatibus.",
- "created_at": "2016-03-22T15:20:35.864Z",
- "updated_at": "2016-03-22T15:20:35.864Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 38,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 1",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/75/p5_build_artifacts.zip"
- },
- "artifacts_metadata": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/75/p5_build_artifacts_metadata.gz"
- },
- "erased_by_id": null,
- "erased_at": null
+ "stages": [
+ {
+ "id": 22,
+ "project_id": 5,
+ "pipeline_id": 38,
+ "name": "test",
+ "status": 1,
+ "created_at": "2016-03-22T15:44:44.772Z",
+ "updated_at": "2016-03-29T06:44:44.634Z",
+ "statuses": [
+ {
+ "id": 76,
+ "project_id": 5,
+ "status": "success",
+ "finished_at": null,
+ "trace": "Et rerum quia ea cumque ut modi non. Libero eaque ipsam architecto maiores expedita deleniti. Ratione quia qui est id.\n\nQuod sit officiis sed unde inventore veniam quisquam velit. Ea harum cum quibusdam quisquam minima quo possimus non. Temporibus itaque aliquam aut rerum veritatis at.\n\nMagnam ipsum eius recusandae qui quis sit maiores eum. Et animi iusto aut itaque. Doloribus harum deleniti nobis accusantium et libero.\n\nRerum fuga perferendis magni commodi officiis id repudiandae. Consequatur ratione consequatur suscipit facilis sunt iure est dicta. Qui unde quasi facilis et quae nesciunt. Magnam iste et nobis officiis tenetur. Aspernatur quo et temporibus non in.\n\nNisi rerum velit est ad enim sint molestiae consequuntur. Quaerat nisi nesciunt quasi officiis. Possimus non blanditiis laborum quos.\n\nRerum laudantium facere animi qui. Ipsa est iusto magnam nihil. Enim omnis occaecati non dignissimos ut recusandae eum quasi. Qui maxime dolor et nemo voluptates incidunt quia.",
+ "created_at": "2016-03-22T15:20:35.882Z",
+ "updated_at": "2016-03-22T15:20:35.882Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 38,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 2",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/76/p5_build_artifacts.zip"
+ },
+ "artifacts_metadata": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/76/p5_build_artifacts_metadata.gz"
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ },
+ {
+ "id": 75,
+ "project_id": 5,
+ "status": "failed",
+ "finished_at": null,
+ "trace": "Sed et iste recusandae dicta corporis. Sunt alias porro fugit sunt. Fugiat omnis nihil dignissimos aperiam explicabo doloremque sit aut. Harum fugit expedita quia rerum ut consequatur laboriosam aliquam.\n\nNatus libero ut ut tenetur earum. Tempora omnis autem omnis et libero dolores illum autem. Deleniti eos sunt mollitia ipsam. Cum dolor repellendus dolorum sequi officia. Ullam sunt in aut pariatur excepturi.\n\nDolor nihil debitis et est eos. Cumque eos eum saepe ducimus autem. Alias architecto consequatur aut pariatur possimus. Aut quos aut incidunt quam velit et. Quas voluptatum ad dolorum dignissimos.\n\nUt voluptates consectetur illo et. Est commodi accusantium vel quo. Eos qui fugiat soluta porro.\n\nRatione possimus alias vel maxime sint totam est repellat. Ipsum corporis eos sint voluptatem eos odit. Temporibus libero nulla harum eligendi labore similique ratione magnam. Suscipit sequi in omnis neque.\n\nLaudantium dolor amet omnis placeat mollitia aut molestiae. Aut rerum similique ipsum quod illo quas unde. Sunt aut veritatis eos omnis porro. Rem veritatis mollitia praesentium dolorem. Consequatur sequi ad cumque earum omnis quia necessitatibus.",
+ "created_at": "2016-03-22T15:20:35.864Z",
+ "updated_at": "2016-03-22T15:20:35.864Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 38,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 1",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/75/p5_build_artifacts.zip"
+ },
+ "artifacts_metadata": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/75/p5_build_artifacts_metadata.gz"
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ }
+ ]
}
]
},
@@ -6734,76 +6778,87 @@
"started_at": null,
"finished_at": null,
"duration": null,
- "statuses": [
- {
- "id": 78,
- "project_id": 5,
- "status": "success",
- "finished_at": null,
- "trace": "Dolorem deserunt quas quia error hic quo cum vel. Natus voluptatem cumque expedita numquam odit. Eos expedita nostrum corporis consequatur est recusandae.\n\nCulpa blanditiis rerum repudiandae alias voluptatem. Velit iusto est ullam consequatur doloribus porro. Corporis voluptas consectetur est veniam et quia quae.\n\nEt aut magni fuga nesciunt officiis molestias. Quaerat et nam necessitatibus qui rerum. Architecto quia officiis voluptatem laborum est recusandae. Quasi ducimus soluta odit necessitatibus labore numquam dignissimos. Quia facere sint temporibus inventore sunt nihil saepe dolorum.\n\nFacere dolores quis dolores a. Est minus nostrum nihil harum. Earum laborum et ipsum unde neque sit nemo. Corrupti est consequatur minima fugit. Illum voluptatem illo error ducimus officia qui debitis.\n\nDignissimos porro a autem harum aut. Aut id reprehenderit et exercitationem. Est et quisquam ipsa temporibus molestiae. Architecto natus dolore qui fugiat incidunt. Autem odit veniam excepturi et voluptatibus culpa ipsum eos.\n\nAmet quo quisquam dignissimos soluta modi dolores. Sint omnis eius optio corporis dolor. Eligendi animi porro quia placeat ut.",
- "created_at": "2016-03-22T15:20:35.927Z",
- "updated_at": "2016-03-22T15:20:35.927Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 39,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 2",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/78/p5_build_artifacts.zip"
- },
- "artifacts_metadata": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/78/p5_build_artifacts_metadata.gz"
- },
- "erased_by_id": null,
- "erased_at": null
- },
- {
- "id": 77,
- "project_id": 5,
- "status": "failed",
- "finished_at": null,
- "trace": "Rerum ut et suscipit est perspiciatis. Inventore debitis cum eius vitae. Ex incidunt id velit aut quo nisi. Laboriosam repellat deserunt eius reiciendis architecto et. Est harum quos nesciunt nisi consectetur.\n\nAlias esse omnis sint officia est consequatur in nobis. Dignissimos dolorum vel eligendi nesciunt dolores sit. Veniam mollitia ducimus et exercitationem molestiae libero sed. Atque omnis debitis laudantium voluptatibus qui. Repellendus tempore est commodi pariatur.\n\nExpedita voluptate illum est alias non. Modi nesciunt ab assumenda laborum nulla consequatur molestias doloremque. Magnam quod officia vel explicabo accusamus ut voluptatem incidunt. Rerum ut aliquid ullam saepe. Est eligendi debitis beatae blanditiis reiciendis.\n\nQui fuga sit dolores libero maiores et suscipit. Consectetur asperiores omnis minima impedit eos fugiat. Similique omnis nisi sed vero inventore ipsum aliquam exercitationem.\n\nBlanditiis magni iure dolorum omnis ratione delectus molestiae. Atque officia dolor voluptatem culpa quod. Incidunt suscipit quidem possimus veritatis non vel. Iusto aliquid et id quia quasi.\n\nVel facere velit blanditiis incidunt cupiditate sed maiores consequuntur. Quasi quia dicta consequuntur et quia voluptatem iste id. Incidunt et rerum fuga esse sint.",
- "created_at": "2016-03-22T15:20:35.905Z",
- "updated_at": "2016-03-22T15:20:35.905Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 39,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 1",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/77/p5_build_artifacts.zip"
- },
- "artifacts_metadata": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/77/p5_build_artifacts_metadata.gz"
- },
- "erased_by_id": null,
- "erased_at": null
+ "stages": [
+ {
+ "id": 23,
+ "project_id": 5,
+ "pipeline_id": 39,
+ "name": "test",
+ "status": 1,
+ "created_at": "2016-03-22T15:44:44.772Z",
+ "updated_at": "2016-03-29T06:44:44.634Z",
+ "statuses": [
+ {
+ "id": 78,
+ "project_id": 5,
+ "status": "success",
+ "finished_at": null,
+ "trace": "Dolorem deserunt quas quia error hic quo cum vel. Natus voluptatem cumque expedita numquam odit. Eos expedita nostrum corporis consequatur est recusandae.\n\nCulpa blanditiis rerum repudiandae alias voluptatem. Velit iusto est ullam consequatur doloribus porro. Corporis voluptas consectetur est veniam et quia quae.\n\nEt aut magni fuga nesciunt officiis molestias. Quaerat et nam necessitatibus qui rerum. Architecto quia officiis voluptatem laborum est recusandae. Quasi ducimus soluta odit necessitatibus labore numquam dignissimos. Quia facere sint temporibus inventore sunt nihil saepe dolorum.\n\nFacere dolores quis dolores a. Est minus nostrum nihil harum. Earum laborum et ipsum unde neque sit nemo. Corrupti est consequatur minima fugit. Illum voluptatem illo error ducimus officia qui debitis.\n\nDignissimos porro a autem harum aut. Aut id reprehenderit et exercitationem. Est et quisquam ipsa temporibus molestiae. Architecto natus dolore qui fugiat incidunt. Autem odit veniam excepturi et voluptatibus culpa ipsum eos.\n\nAmet quo quisquam dignissimos soluta modi dolores. Sint omnis eius optio corporis dolor. Eligendi animi porro quia placeat ut.",
+ "created_at": "2016-03-22T15:20:35.927Z",
+ "updated_at": "2016-03-22T15:20:35.927Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 39,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 2",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/78/p5_build_artifacts.zip"
+ },
+ "artifacts_metadata": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/78/p5_build_artifacts_metadata.gz"
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ },
+ {
+ "id": 77,
+ "project_id": 5,
+ "status": "failed",
+ "finished_at": null,
+ "trace": "Rerum ut et suscipit est perspiciatis. Inventore debitis cum eius vitae. Ex incidunt id velit aut quo nisi. Laboriosam repellat deserunt eius reiciendis architecto et. Est harum quos nesciunt nisi consectetur.\n\nAlias esse omnis sint officia est consequatur in nobis. Dignissimos dolorum vel eligendi nesciunt dolores sit. Veniam mollitia ducimus et exercitationem molestiae libero sed. Atque omnis debitis laudantium voluptatibus qui. Repellendus tempore est commodi pariatur.\n\nExpedita voluptate illum est alias non. Modi nesciunt ab assumenda laborum nulla consequatur molestias doloremque. Magnam quod officia vel explicabo accusamus ut voluptatem incidunt. Rerum ut aliquid ullam saepe. Est eligendi debitis beatae blanditiis reiciendis.\n\nQui fuga sit dolores libero maiores et suscipit. Consectetur asperiores omnis minima impedit eos fugiat. Similique omnis nisi sed vero inventore ipsum aliquam exercitationem.\n\nBlanditiis magni iure dolorum omnis ratione delectus molestiae. Atque officia dolor voluptatem culpa quod. Incidunt suscipit quidem possimus veritatis non vel. Iusto aliquid et id quia quasi.\n\nVel facere velit blanditiis incidunt cupiditate sed maiores consequuntur. Quasi quia dicta consequuntur et quia voluptatem iste id. Incidunt et rerum fuga esse sint.",
+ "created_at": "2016-03-22T15:20:35.905Z",
+ "updated_at": "2016-03-22T15:20:35.905Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 39,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 1",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/77/p5_build_artifacts.zip"
+ },
+ "artifacts_metadata": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/77/p5_build_artifacts_metadata.gz"
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ }
+ ]
}
]
},
@@ -6823,76 +6878,87 @@
"started_at": null,
"finished_at": null,
"duration": null,
- "statuses": [
- {
- "id": 79,
- "project_id": 5,
- "status": "failed",
- "finished_at": "2016-03-29T06:28:12.695Z",
- "trace": "Sed culpa est et facere saepe vel id ab. Quas temporibus aut similique dolorem consequatur corporis aut praesentium. Cum officia molestiae sit earum excepturi.\n\nSint possimus aut ratione quia. Quis nesciunt ratione itaque illo. Tenetur est dolor assumenda possimus voluptatem quia minima. Accusamus reprehenderit ut et itaque non reiciendis incidunt.\n\nRerum suscipit quibusdam dolore nam omnis. Consequatur ipsa nihil ut enim blanditiis delectus. Nulla quis hic occaecati mollitia qui placeat. Quo rerum sed perferendis a accusantium consequatur commodi ut. Sit quae et cumque vel eius tempora nostrum.\n\nUllam dolorem et itaque sint est. Ea molestias quia provident dolorem vitae error et et. Ea expedita officiis iste non. Qui vitae odit saepe illum. Dolores enim ratione deserunt tempore expedita amet non neque.\n\nEligendi asperiores voluptatibus omnis repudiandae expedita distinctio qui aliquid. Autem aut doloremque distinctio ab. Nostrum sapiente repudiandae aspernatur ea et quae voluptas. Officiis perspiciatis nisi laudantium asperiores error eligendi ab. Eius quia amet magni omnis exercitationem voluptatum et.\n\nVoluptatem ullam labore quas dicta est ex voluptas. Pariatur ea modi voluptas consequatur dolores perspiciatis similique. Numquam in distinctio perspiciatis ut qui earum. Quidem omnis mollitia facere aut beatae. Ea est iure et voluptatem.",
- "created_at": "2016-03-22T15:20:35.950Z",
- "updated_at": "2016-03-29T06:28:12.696Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 40,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 1",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": null
- },
- "artifacts_metadata": {
- "url": null
- },
- "erased_by_id": null,
- "erased_at": null
- },
- {
- "id": 80,
- "project_id": 5,
- "status": "success",
- "finished_at": null,
- "trace": "Impedit et optio nemo ipsa. Non ad non quis ut sequi laudantium omnis velit. Corporis a enim illo eos. Quia totam tempore inventore ad est.\n\nNihil recusandae cupiditate eaque voluptatem molestias sint. Consequatur id voluptatem cupiditate harum. Consequuntur iusto quaerat reiciendis aut autem libero est. Quisquam dolores veritatis rerum et sint maxime ullam libero. Id quas porro ut perspiciatis rem amet vitae.\n\nNemo inventore minus blanditiis magnam. Modi consequuntur nostrum aut voluptatem ex. Sunt rerum rem optio mollitia qui aliquam officiis officia. Aliquid eos et id aut minus beatae reiciendis.\n\nDolores non in temporibus dicta. Fugiat voluptatem est aspernatur expedita voluptatum nam qui. Quia et eligendi sit quae sint tempore exercitationem eos. Est sapiente corrupti quidem at. Qui magni odio repudiandae saepe tenetur optio dolore.\n\nEos placeat soluta at dolorem adipisci provident. Quo commodi id reprehenderit possimus quo tenetur. Ipsum et quae eligendi laborum. Et qui nesciunt at quasi quidem voluptatem cum rerum. Excepturi non facilis aut sunt vero sed.\n\nQui explicabo ratione ut eligendi recusandae. Quis quasi quas molestiae consequatur voluptatem et voluptatem. Ex repellat saepe occaecati aperiam ea eveniet dignissimos facilis.",
- "created_at": "2016-03-22T15:20:35.966Z",
- "updated_at": "2016-03-22T15:20:35.966Z",
- "started_at": null,
- "runner_id": null,
- "coverage": null,
- "commit_id": 40,
- "commands": "$ build command",
- "job_id": null,
- "name": "test build 2",
- "deploy": false,
- "options": null,
- "allow_failure": false,
- "stage": "test",
- "trigger_request_id": null,
- "stage_idx": 1,
- "tag": null,
- "ref": "master",
- "user_id": null,
- "target_url": null,
- "description": null,
- "artifacts_file": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/80/p5_build_artifacts.zip"
- },
- "artifacts_metadata": {
- "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/80/p5_build_artifacts_metadata.gz"
- },
- "erased_by_id": null,
- "erased_at": null
+ "stages": [
+ {
+ "id": 24,
+ "project_id": 5,
+ "pipeline_id": 40,
+ "name": "test",
+ "status": 1,
+ "created_at": "2016-03-22T15:44:44.772Z",
+ "updated_at": "2016-03-29T06:44:44.634Z",
+ "statuses": [
+ {
+ "id": 79,
+ "project_id": 5,
+ "status": "failed",
+ "finished_at": "2016-03-29T06:28:12.695Z",
+ "trace": "Sed culpa est et facere saepe vel id ab. Quas temporibus aut similique dolorem consequatur corporis aut praesentium. Cum officia molestiae sit earum excepturi.\n\nSint possimus aut ratione quia. Quis nesciunt ratione itaque illo. Tenetur est dolor assumenda possimus voluptatem quia minima. Accusamus reprehenderit ut et itaque non reiciendis incidunt.\n\nRerum suscipit quibusdam dolore nam omnis. Consequatur ipsa nihil ut enim blanditiis delectus. Nulla quis hic occaecati mollitia qui placeat. Quo rerum sed perferendis a accusantium consequatur commodi ut. Sit quae et cumque vel eius tempora nostrum.\n\nUllam dolorem et itaque sint est. Ea molestias quia provident dolorem vitae error et et. Ea expedita officiis iste non. Qui vitae odit saepe illum. Dolores enim ratione deserunt tempore expedita amet non neque.\n\nEligendi asperiores voluptatibus omnis repudiandae expedita distinctio qui aliquid. Autem aut doloremque distinctio ab. Nostrum sapiente repudiandae aspernatur ea et quae voluptas. Officiis perspiciatis nisi laudantium asperiores error eligendi ab. Eius quia amet magni omnis exercitationem voluptatum et.\n\nVoluptatem ullam labore quas dicta est ex voluptas. Pariatur ea modi voluptas consequatur dolores perspiciatis similique. Numquam in distinctio perspiciatis ut qui earum. Quidem omnis mollitia facere aut beatae. Ea est iure et voluptatem.",
+ "created_at": "2016-03-22T15:20:35.950Z",
+ "updated_at": "2016-03-29T06:28:12.696Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 40,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 1",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": null
+ },
+ "artifacts_metadata": {
+ "url": null
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ },
+ {
+ "id": 80,
+ "project_id": 5,
+ "status": "success",
+ "finished_at": null,
+ "trace": "Impedit et optio nemo ipsa. Non ad non quis ut sequi laudantium omnis velit. Corporis a enim illo eos. Quia totam tempore inventore ad est.\n\nNihil recusandae cupiditate eaque voluptatem molestias sint. Consequatur id voluptatem cupiditate harum. Consequuntur iusto quaerat reiciendis aut autem libero est. Quisquam dolores veritatis rerum et sint maxime ullam libero. Id quas porro ut perspiciatis rem amet vitae.\n\nNemo inventore minus blanditiis magnam. Modi consequuntur nostrum aut voluptatem ex. Sunt rerum rem optio mollitia qui aliquam officiis officia. Aliquid eos et id aut minus beatae reiciendis.\n\nDolores non in temporibus dicta. Fugiat voluptatem est aspernatur expedita voluptatum nam qui. Quia et eligendi sit quae sint tempore exercitationem eos. Est sapiente corrupti quidem at. Qui magni odio repudiandae saepe tenetur optio dolore.\n\nEos placeat soluta at dolorem adipisci provident. Quo commodi id reprehenderit possimus quo tenetur. Ipsum et quae eligendi laborum. Et qui nesciunt at quasi quidem voluptatem cum rerum. Excepturi non facilis aut sunt vero sed.\n\nQui explicabo ratione ut eligendi recusandae. Quis quasi quas molestiae consequatur voluptatem et voluptatem. Ex repellat saepe occaecati aperiam ea eveniet dignissimos facilis.",
+ "created_at": "2016-03-22T15:20:35.966Z",
+ "updated_at": "2016-03-22T15:20:35.966Z",
+ "started_at": null,
+ "runner_id": null,
+ "coverage": null,
+ "commit_id": 40,
+ "commands": "$ build command",
+ "job_id": null,
+ "name": "test build 2",
+ "deploy": false,
+ "options": null,
+ "allow_failure": false,
+ "stage": "test",
+ "trigger_request_id": null,
+ "stage_idx": 1,
+ "tag": null,
+ "ref": "master",
+ "user_id": null,
+ "target_url": null,
+ "description": null,
+ "artifacts_file": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/80/p5_build_artifacts.zip"
+ },
+ "artifacts_metadata": {
+ "url": "/Users/Test/Test/gitlab-development-kit/gitlab/shared/artifacts/2016_03/5/80/p5_build_artifacts_metadata.gz"
+ },
+ "erased_by_id": null,
+ "erased_at": null
+ }
+ ]
}
]
}
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index 0ab3afd0074..9dfd879a1bc 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -179,6 +179,32 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end
end
end
+
+ context 'when restoring hierarchy of pipeline, stages and jobs' do
+ it 'restores pipelines' do
+ expect(Ci::Pipeline.all.count).to be 5
+ end
+
+ it 'restores pipeline stages' do
+ expect(Ci::Stage.all.count).to be 6
+ end
+
+ it 'correctly restores association between stage and a pipeline' do
+ expect(Ci::Stage.all).to all(have_attributes(pipeline_id: a_value > 0))
+ end
+
+ it 'restores statuses' do
+ expect(CommitStatus.all.count).to be 10
+ end
+
+ it 'correctly restores association between a stage and a job' do
+ expect(CommitStatus.all).to all(have_attributes(stage_id: a_value > 0))
+ end
+
+ it 'correctly restores association between a pipeline and a job' do
+ expect(CommitStatus.all).to all(have_attributes(pipeline_id: a_value > 0))
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index 6faf3d82981..08e5bbbd400 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -109,12 +109,20 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
expect(saved_project_json['merge_requests'].first['notes'].first['author']).not_to be_empty
end
+ it 'has pipeline stages' do
+ expect(saved_project_json.dig('pipelines', 0, 'stages')).not_to be_empty
+ end
+
it 'has pipeline statuses' do
- expect(saved_project_json['pipelines'].first['statuses']).not_to be_empty
+ expect(saved_project_json.dig('pipelines', 0, 'stages', 0, 'statuses')).not_to be_empty
end
it 'has pipeline builds' do
- expect(saved_project_json['pipelines'].first['statuses'].count { |hash| hash['type'] == 'Ci::Build' }).to eq(1)
+ builds_count = saved_project_json
+ .dig('pipelines', 0, 'stages', 0, 'statuses')
+ .count { |hash| hash['type'] == 'Ci::Build' }
+
+ expect(builds_count).to eq(1)
end
it 'has no when YML attributes but only the DB column' do
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ec8fa99e0da..ec577903eb5 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -459,6 +459,7 @@ Project:
- delete_error
- merge_requests_ff_only_enabled
- merge_requests_rebase_enabled
+- jobs_cache_index
Author:
- name
ProjectFeature:
diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb
index ecb4034ec8b..f65e41dfea3 100644
--- a/spec/lib/google_api/cloud_platform/client_spec.rb
+++ b/spec/lib/google_api/cloud_platform/client_spec.rb
@@ -50,6 +50,30 @@ describe GoogleApi::CloudPlatform::Client do
end
end
+ describe '#projects_list' do
+ subject { client.projects_list }
+ let(:projects) { double }
+
+ before do
+ allow_any_instance_of(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService)
+ .to receive(:fetch_all).and_return(projects)
+ end
+
+ it { is_expected.to eq(projects) }
+ end
+
+ describe '#projects_get_billing_info' do
+ subject { client.projects_get_billing_info('project') }
+ let(:billing_info) { double }
+
+ before do
+ allow_any_instance_of(Google::Apis::CloudbillingV1::CloudbillingService)
+ .to receive(:get_project_billing_info).and_return(billing_info)
+ end
+
+ it { is_expected.to eq(billing_info) }
+ end
+
describe '#projects_zones_clusters_get' do
subject { client.projects_zones_clusters_get(spy, spy, spy) }
let(:gke_cluster) { double }
diff --git a/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb b/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb
index 57ee2adaaff..c81ec887ded 100644
--- a/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb
+++ b/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb
@@ -33,7 +33,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
let(:encrypted_gcp_token) { "'encrypted_gcp_token'" }
let(:encrypted_gcp_token_iv) { "'encrypted_gcp_token_iv'" }
- let(:cluster) { Clusters::Cluster.last }
+ let(:cluster) { described_class::Cluster.last }
let(:cluster_id) { cluster.id }
before do
@@ -46,12 +46,12 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
it 'correctly migrate to new clusters architectures' do
migrate!
- expect(Clusters::Cluster.count).to eq(1)
- expect(Clusters::Project.count).to eq(1)
- expect(Clusters::Providers::Gcp.count).to eq(1)
- expect(Clusters::Platforms::Kubernetes.count).to eq(1)
+ expect(described_class::Cluster.count).to eq(1)
+ expect(described_class::ClustersProject.count).to eq(1)
+ expect(described_class::ProvidersGcp.count).to eq(1)
+ expect(described_class::PlatformsKubernetes.count).to eq(1)
- expect(cluster.user).to eq(user)
+ expect(cluster.user_id).to eq(user.id)
expect(cluster.enabled).to be_truthy
expect(cluster.name).to eq(gcp_cluster_name.delete!("'"))
expect(cluster.provider_type).to eq('gcp')
@@ -59,7 +59,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
expect(cluster.project_ids).to include(project.id)
- expect(cluster.provider_gcp.cluster).to eq(cluster)
+ expect(cluster.provider_gcp.cluster_id).to eq(cluster.id)
expect(cluster.provider_gcp.status).to eq(status)
expect(cluster.provider_gcp.status_reason).to eq(tr(status_reason))
expect(cluster.provider_gcp.gcp_project_id).to eq(tr(gcp_project_id))
@@ -71,7 +71,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
expect(cluster.provider_gcp.encrypted_access_token).to eq(tr(encrypted_gcp_token))
expect(cluster.provider_gcp.encrypted_access_token_iv).to eq(tr(encrypted_gcp_token_iv))
- expect(cluster.platform_kubernetes.cluster).to eq(cluster)
+ expect(cluster.platform_kubernetes.cluster_id).to eq(cluster.id)
expect(cluster.platform_kubernetes.api_url).to be_nil
expect(cluster.platform_kubernetes.ca_cert).to be_nil
expect(cluster.platform_kubernetes.namespace).to eq(tr(project_namespace))
@@ -109,7 +109,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
let(:encrypted_gcp_token) { "'encrypted_gcp_token'" }
let(:encrypted_gcp_token_iv) { "'encrypted_gcp_token_iv'" }
- let(:cluster) { Clusters::Cluster.last }
+ let(:cluster) { described_class::Cluster.last }
let(:cluster_id) { cluster.id }
before do
@@ -122,12 +122,12 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
it 'correctly migrate to new clusters architectures' do
migrate!
- expect(Clusters::Cluster.count).to eq(1)
- expect(Clusters::Project.count).to eq(1)
- expect(Clusters::Providers::Gcp.count).to eq(1)
- expect(Clusters::Platforms::Kubernetes.count).to eq(1)
+ expect(described_class::Cluster.count).to eq(1)
+ expect(described_class::ClustersProject.count).to eq(1)
+ expect(described_class::ProvidersGcp.count).to eq(1)
+ expect(described_class::PlatformsKubernetes.count).to eq(1)
- expect(cluster.user).to eq(user)
+ expect(cluster.user_id).to eq(user.id)
expect(cluster.enabled).to be_truthy
expect(cluster.name).to eq(tr(gcp_cluster_name))
expect(cluster.provider_type).to eq('gcp')
@@ -135,7 +135,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
expect(cluster.project_ids).to include(project.id)
- expect(cluster.provider_gcp.cluster).to eq(cluster)
+ expect(cluster.provider_gcp.cluster_id).to eq(cluster.id)
expect(cluster.provider_gcp.status).to eq(status)
expect(cluster.provider_gcp.status_reason).to eq(tr(status_reason))
expect(cluster.provider_gcp.gcp_project_id).to eq(tr(gcp_project_id))
@@ -147,7 +147,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do
expect(cluster.provider_gcp.encrypted_access_token).to eq(tr(encrypted_gcp_token))
expect(cluster.provider_gcp.encrypted_access_token_iv).to eq(tr(encrypted_gcp_token_iv))
- expect(cluster.platform_kubernetes.cluster).to eq(cluster)
+ expect(cluster.platform_kubernetes.cluster_id).to eq(cluster.id)
expect(cluster.platform_kubernetes.api_url).to eq('https://' + tr(endpoint))
expect(cluster.platform_kubernetes.ca_cert).to eq(tr(ca_cert))
expect(cluster.platform_kubernetes.namespace).to eq(tr(project_namespace))
diff --git a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
index 9b92f4b70b0..a837498e1b1 100644
--- a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
+++ b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
@@ -35,9 +35,9 @@ describe MigrateStageIdReferenceInBackground, :migration, :sidekiq do
Timecop.freeze do
migrate!
- expect(described_class::MIGRATION).to be_scheduled_migration(2.minutes, 1, 2)
- expect(described_class::MIGRATION).to be_scheduled_migration(2.minutes, 3, 3)
- expect(described_class::MIGRATION).to be_scheduled_migration(4.minutes, 4, 5)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 3, 3)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, 4, 5)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
diff --git a/spec/migrations/migrate_stages_statuses_spec.rb b/spec/migrations/migrate_stages_statuses_spec.rb
index 094c9bc604e..79d2708f9ad 100644
--- a/spec/migrations/migrate_stages_statuses_spec.rb
+++ b/spec/migrations/migrate_stages_statuses_spec.rb
@@ -50,9 +50,9 @@ describe MigrateStagesStatuses, :migration do
Timecop.freeze do
migrate!
- expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes, 1, 1)
- expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes, 2, 2)
- expect(described_class::MIGRATION).to be_scheduled_migration(10.minutes, 3, 3)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, 1, 1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, 2, 2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, 3, 3)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
diff --git a/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb b/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb
index 0e884a7d910..65ec07da31c 100644
--- a/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb
+++ b/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb
@@ -2,18 +2,6 @@ require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20171005130944_schedule_create_gpg_key_subkeys_from_gpg_keys')
describe ScheduleCreateGpgKeySubkeysFromGpgKeys, :migration, :sidekiq do
- matcher :be_scheduled_migration do |*expected|
- match do |migration|
- BackgroundMigrationWorker.jobs.any? do |job|
- job['args'] == [migration, expected]
- end
- end
-
- failure_message do |migration|
- "Migration `#{migration}` with args `#{expected.inspect}` not scheduled!"
- end
- end
-
before do
create(:gpg_key, id: 1, key: GpgHelpers::User1.public_key)
create(:gpg_key, id: 2, key: GpgHelpers::User3.public_key)
diff --git a/spec/migrations/schedule_merge_request_diff_migrations_spec.rb b/spec/migrations/schedule_merge_request_diff_migrations_spec.rb
index 76afb6c19cf..d230f064444 100644
--- a/spec/migrations/schedule_merge_request_diff_migrations_spec.rb
+++ b/spec/migrations/schedule_merge_request_diff_migrations_spec.rb
@@ -24,9 +24,9 @@ describe ScheduleMergeRequestDiffMigrations, :migration, :sidekiq do
Timecop.freeze do
migrate!
- expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes, 1, 1)
- expect(described_class::MIGRATION).to be_scheduled_migration(10.minutes, 2, 2)
- expect(described_class::MIGRATION).to be_scheduled_migration(15.minutes, 4, 4)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, 1, 1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, 2, 2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(15.minutes, 4, 4)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
diff --git a/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb b/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb
index cf323973384..1aab4ae1650 100644
--- a/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb
+++ b/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb
@@ -24,9 +24,9 @@ describe ScheduleMergeRequestDiffMigrationsTakeTwo, :migration, :sidekiq do
Timecop.freeze do
migrate!
- expect(described_class::MIGRATION).to be_scheduled_migration(10.minutes, 1, 1)
- expect(described_class::MIGRATION).to be_scheduled_migration(20.minutes, 2, 2)
- expect(described_class::MIGRATION).to be_scheduled_migration(30.minutes, 4, 4)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, 1, 1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(20.minutes, 2, 2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(30.minutes, 4, 4)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
diff --git a/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb b/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb
index 158d0bc02ed..c9fdbe95d13 100644
--- a/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb
+++ b/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb
@@ -44,9 +44,9 @@ describe ScheduleMergeRequestLatestMergeRequestDiffIdMigrations, :migration, :si
Timecop.freeze do
migrate!
- expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes, merge_request_1.id, merge_request_1.id)
- expect(described_class::MIGRATION).to be_scheduled_migration(10.minutes, merge_request_2.id, merge_request_2.id)
- expect(described_class::MIGRATION).to be_scheduled_migration(15.minutes, merge_request_4.id, merge_request_4.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, merge_request_1.id, merge_request_1.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, merge_request_2.id, merge_request_2.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(15.minutes, merge_request_4.id, merge_request_4.id)
expect(BackgroundMigrationWorker.jobs.size).to eq 3
end
end
diff --git a/spec/migrations/schedule_populate_merge_request_metrics_with_events_data_spec.rb b/spec/migrations/schedule_populate_merge_request_metrics_with_events_data_spec.rb
index 97e089c5cb8..2e6b2cff0ab 100644
--- a/spec/migrations/schedule_populate_merge_request_metrics_with_events_data_spec.rb
+++ b/spec/migrations/schedule_populate_merge_request_metrics_with_events_data_spec.rb
@@ -12,10 +12,10 @@ describe SchedulePopulateMergeRequestMetricsWithEventsData, :migration, :sidekiq
migrate!
expect(described_class::MIGRATION)
- .to be_scheduled_migration(10.minutes, mrs.first.id, mrs.second.id)
+ .to be_scheduled_delayed_migration(10.minutes, mrs.first.id, mrs.second.id)
expect(described_class::MIGRATION)
- .to be_scheduled_migration(20.minutes, mrs.third.id, mrs.third.id)
+ .to be_scheduled_delayed_migration(20.minutes, mrs.third.id, mrs.third.id)
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
end
diff --git a/spec/migrations/track_untracked_uploads_spec.rb b/spec/migrations/track_untracked_uploads_spec.rb
index 7fe7a140e2f..fe4d5b8a279 100644
--- a/spec/migrations/track_untracked_uploads_spec.rb
+++ b/spec/migrations/track_untracked_uploads_spec.rb
@@ -4,18 +4,6 @@ require Rails.root.join('db', 'post_migrate', '20171103140253_track_untracked_up
describe TrackUntrackedUploads, :migration, :sidekiq do
include TrackUntrackedUploadsHelpers
- matcher :be_scheduled_migration do
- match do |migration|
- BackgroundMigrationWorker.jobs.any? do |job|
- job['args'] == [migration]
- end
- end
-
- failure_message do |migration|
- "Migration `#{migration}` with args `#{expected.inspect}` not scheduled!"
- end
- end
-
it 'correctly schedules the follow-up background migration' do
Sidekiq::Testing.fake! do
migrate!
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 871e8b47650..3eaeeebf97d 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -255,6 +255,42 @@ describe Ci::Build do
end
end
+ describe '#cache' do
+ let(:options) { { cache: { key: "key", paths: ["public"], policy: "pull-push" } } }
+
+ subject { build.cache }
+
+ context 'when build has cache' do
+ before do
+ allow(build).to receive(:options).and_return(options)
+ end
+
+ context 'when project has jobs_cache_index' do
+ before do
+ allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(1)
+ end
+
+ it { is_expected.to be_an(Array).and all(include(key: "key:1")) }
+ end
+
+ context 'when project does not have jobs_cache_index' do
+ before do
+ allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(nil)
+ end
+
+ it { is_expected.to eq([options[:cache]]) }
+ end
+ end
+
+ context 'when build does not have cache' do
+ before do
+ allow(build).to receive(:options).and_return({})
+ end
+
+ it { is_expected.to eq([nil]) }
+ end
+ end
+
describe '#depends_on_builds' do
let!(:build) { create(:ci_build, pipeline: pipeline, name: 'build', stage_idx: 0, stage: 'build') }
let!(:rspec_test) { create(:ci_build, pipeline: pipeline, name: 'rspec', stage_idx: 1, stage: 'test') }
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 4f02dc33cd8..817254c7d1e 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -181,7 +181,6 @@ eos
it { is_expected.to respond_to(:parents) }
it { is_expected.to respond_to(:date) }
it { is_expected.to respond_to(:diffs) }
- it { is_expected.to respond_to(:tree) }
it { is_expected.to respond_to(:id) }
it { is_expected.to respond_to(:to_patch) }
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index d8ebd46faab..07b3e1c1758 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1903,4 +1903,50 @@ describe MergeRequest do
end
end
end
+
+ describe '#should_be_rebased?' do
+ let(:project) { create(:project, :repository) }
+
+ it 'returns false for the same source and target branches' do
+ merge_request = create(:merge_request, source_project: project, target_project: project)
+
+ expect(merge_request.should_be_rebased?).to be_falsey
+ end
+ end
+
+ describe '#rebase_in_progress?' do
+ # Create merge request and project before we stub file calls
+ before do
+ subject
+ end
+
+ it 'returns true when there is a current rebase directory' do
+ allow(File).to receive(:exist?).and_return(true)
+ allow(File).to receive(:mtime).and_return(Time.now)
+
+ expect(subject.rebase_in_progress?).to be_truthy
+ end
+
+ it 'returns false when there is no rebase directory' do
+ allow(File).to receive(:exist?).and_return(false)
+
+ expect(subject.rebase_in_progress?).to be_falsey
+ end
+
+ it 'returns false when the rebase directory has expired' do
+ allow(File).to receive(:exist?).and_return(true)
+ allow(File).to receive(:mtime).and_return(20.minutes.ago)
+
+ expect(subject.rebase_in_progress?).to be_falsey
+ end
+
+ it 'returns false when the source project has been removed' do
+ allow(subject).to receive(:source_project).and_return(nil)
+ allow(File).to receive(:exist?).and_return(true)
+ allow(File).to receive(:mtime).and_return(Time.now)
+
+ expect(File).not_to have_received(:exist?)
+ expect(subject.rebase_in_progress?).to be_falsey
+ end
+ end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 0678cae9b93..b3f160f3119 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -250,9 +250,13 @@ describe Namespace do
parent.update(path: 'mygroup_new')
- expect(project_in_parent_group.repo.config['gitlab.fullpath']).to eq "mygroup_new/#{project_in_parent_group.path}"
- expect(hashed_project_in_subgroup.repo.config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{hashed_project_in_subgroup.path}"
- expect(legacy_project_in_subgroup.repo.config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{legacy_project_in_subgroup.path}"
+ expect(project_rugged(project_in_parent_group).config['gitlab.fullpath']).to eq "mygroup_new/#{project_in_parent_group.path}"
+ expect(project_rugged(hashed_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{hashed_project_in_subgroup.path}"
+ expect(project_rugged(legacy_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{legacy_project_in_subgroup.path}"
+ end
+
+ def project_rugged(project)
+ project.repository.rugged
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 3c2ed043b82..00afa09f1a3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -418,14 +418,21 @@ describe Project do
end
describe '#merge_method' do
- it 'returns "ff" merge_method when ff is enabled' do
- project = build(:project, merge_requests_ff_only_enabled: true)
- expect(project.merge_method).to be :ff
+ using RSpec::Parameterized::TableSyntax
+
+ where(:ff, :rebase, :method) do
+ true | true | :ff
+ true | false | :ff
+ false | true | :rebase_merge
+ false | false | :merge
end
- it 'returns "merge" merge_method when ff is disabled' do
- project = build(:project, merge_requests_ff_only_enabled: false)
- expect(project.merge_method).to be :merge
+ with_them do
+ let(:project) { build(:project, merge_requests_rebase_enabled: rebase, merge_requests_ff_only_enabled: ff) }
+
+ subject { project.merge_method }
+
+ it { is_expected.to eq(method) }
end
end
@@ -2632,7 +2639,7 @@ describe Project do
project.rename_repo
- expect(project.repo.config['gitlab.fullpath']).to eq(project.full_path)
+ expect(project.repository.rugged.config['gitlab.fullpath']).to eq(project.full_path)
end
end
@@ -2793,7 +2800,7 @@ describe Project do
it 'updates project full path in .git/config' do
project.rename_repo
- expect(project.repo.config['gitlab.fullpath']).to eq(project.full_path)
+ expect(project.repository.rugged.config['gitlab.fullpath']).to eq(project.full_path)
end
end
@@ -3072,9 +3079,51 @@ describe Project do
expect(project).to receive(:import_finish)
expect(project).to receive(:update_project_counter_caches)
expect(project).to receive(:remove_import_jid)
+ expect(project).to receive(:after_create_default_branch)
project.after_import
end
+
+ context 'branch protection' do
+ let(:project) { create(:project, :repository) }
+
+ it 'does not protect when branch protection is disabled' do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_NONE)
+
+ project.after_import
+
+ expect(project.protected_branches).to be_empty
+ end
+
+ it "gives developer access to push when branch protection is set to 'developers can push'" do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
+
+ project.after_import
+
+ expect(project.protected_branches).not_to be_empty
+ expect(project.default_branch).to eq(project.protected_branches.first.name)
+ expect(project.protected_branches.first.push_access_levels.map(&:access_level)).to eq([Gitlab::Access::DEVELOPER])
+ end
+
+ it "gives developer access to merge when branch protection is set to 'developers can merge'" do
+ stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
+
+ project.after_import
+
+ expect(project.protected_branches).not_to be_empty
+ expect(project.default_branch).to eq(project.protected_branches.first.name)
+ expect(project.protected_branches.first.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::DEVELOPER])
+ end
+
+ it 'protects default branch' do
+ project.after_import
+
+ expect(project.protected_branches).not_to be_empty
+ expect(project.default_branch).to eq(project.protected_branches.first.name)
+ expect(project.protected_branches.first.push_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER])
+ expect(project.protected_branches.first.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER])
+ end
+ end
end
describe '#update_project_counter_caches' do
@@ -3143,13 +3192,13 @@ describe Project do
it 'writes full path in .git/config when key is missing' do
project.write_repository_config
- expect(project.repo.config['gitlab.fullpath']).to eq project.full_path
+ expect(project.repository.rugged.config['gitlab.fullpath']).to eq project.full_path
end
it 'updates full path in .git/config when key is present' do
project.write_repository_config(gl_full_path: 'old/path')
- expect { project.write_repository_config }.to change { project.repo.config['gitlab.fullpath'] }.from('old/path').to(project.full_path)
+ expect { project.write_repository_config }.to change { project.repository.rugged.config['gitlab.fullpath'] }.from('old/path').to(project.full_path)
end
it 'does not raise an error with an empty repository' do
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 9a68ae086ea..c0db2c1b386 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -582,38 +582,6 @@ describe Repository do
end
end
- describe '#get_committer_and_author' do
- it 'returns the committer and author data' do
- options = repository.get_committer_and_author(user)
- expect(options[:committer][:email]).to eq(user.email)
- expect(options[:author][:email]).to eq(user.email)
- end
-
- context 'when the email/name are given' do
- it 'returns an object containing the email/name' do
- options = repository.get_committer_and_author(user, email: author_email, name: author_name)
- expect(options[:author][:email]).to eq(author_email)
- expect(options[:author][:name]).to eq(author_name)
- end
- end
-
- context 'when the email is given but the name is not' do
- it 'returns the committer as the author' do
- options = repository.get_committer_and_author(user, email: author_email)
- expect(options[:author][:email]).to eq(user.email)
- expect(options[:author][:name]).to eq(user.name)
- end
- end
-
- context 'when the name is given but the email is not' do
- it 'returns nil' do
- options = repository.get_committer_and_author(user, name: author_name)
- expect(options[:author][:email]).to eq(user.email)
- expect(options[:author][:name]).to eq(user.name)
- end
- end
- end
-
describe "search_files_by_content" do
let(:results) { repository.search_files_by_content('feature', 'master') }
subject { results }
@@ -1112,16 +1080,16 @@ describe Repository do
allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, ''])
end
- it 'expires branch cache' do
- expect(repository).not_to receive(:expire_exists_cache)
- expect(repository).not_to receive(:expire_root_ref_cache)
- expect(repository).not_to receive(:expire_emptiness_caches)
- expect(repository).to receive(:expire_branches_cache)
-
- repository.with_branch(user, 'new-feature') do
+ subject do
+ Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch('new-feature') do
new_rev
end
end
+
+ it 'returns branch_created as true' do
+ expect(subject).not_to be_repo_created
+ expect(subject).to be_branch_created
+ end
end
context 'when repository is empty' do
@@ -2215,6 +2183,15 @@ describe Repository do
end
end
+ describe '#diverging_commit_counts' do
+ it 'returns the commit counts behind and ahead of default branch' do
+ result = repository.diverging_commit_counts(
+ repository.find_branch('fix'))
+
+ expect(result).to eq(behind: 29, ahead: 2)
+ end
+ end
+
describe '#cache_method_output', :use_clean_rails_memory_store_caching do
let(:fallback) { 10 }
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index 969c4753f33..e3b37739e8e 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -404,4 +404,67 @@ describe MergeRequestPresenter do
.to eq("<a href=\"/#{resource.source_project.full_path}/tree/#{resource.source_branch}\">#{resource.source_branch}</a>")
end
end
+
+ describe '#rebase_path' do
+ before do
+ allow(resource).to receive(:rebase_in_progress?) { rebase_in_progress }
+ allow(resource).to receive(:should_be_rebased?) { should_be_rebased }
+
+ allow_any_instance_of(Gitlab::UserAccess::RequestCacheExtension)
+ .to receive(:can_push_to_branch?)
+ .with(resource.source_branch)
+ .and_return(can_push_to_branch)
+ end
+
+ subject do
+ described_class.new(resource, current_user: user).rebase_path
+ end
+
+ context 'when can rebase' do
+ let(:rebase_in_progress) { false }
+ let(:can_push_to_branch) { true }
+ let(:should_be_rebased) { true }
+
+ before do
+ allow(resource).to receive(:source_branch_exists?) { true }
+ end
+
+ it 'returns path' do
+ is_expected
+ .to eq("/#{project.full_path}/merge_requests/#{resource.iid}/rebase")
+ end
+ end
+
+ context 'when cannot rebase' do
+ context 'when rebase in progress' do
+ let(:rebase_in_progress) { true }
+ let(:can_push_to_branch) { true }
+ let(:should_be_rebased) { true }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when user cannot merge' do
+ let(:rebase_in_progress) { false }
+ let(:can_push_to_branch) { false }
+ let(:should_be_rebased) { true }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+
+ context 'should not be rebased' do
+ let(:rebase_in_progress) { false }
+ let(:can_push_to_branch) { true }
+ let(:should_be_rebased) { false }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 00d9c795619..320217f2032 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -1582,4 +1582,16 @@ describe API::Issues, :mailer do
expect(json_response).to be_an Array
expect(json_response.length).to eq(size) if size
end
+
+ describe 'GET projects/:id/issues/:issue_iid/participants' do
+ it_behaves_like 'issuable participants endpoint' do
+ let(:entity) { issue }
+ end
+
+ it 'returns 404 if the issue is confidential' do
+ post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/participants", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
end
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index e77745acbb7..805496e4a54 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -11,7 +11,7 @@ describe API::Jobs do
ref: project.default_branch)
end
- let!(:job) { create(:ci_build, pipeline: pipeline) }
+ let!(:job) { create(:ci_build, :success, pipeline: pipeline) }
let(:user) { create(:user) }
let(:api_user) { user }
@@ -443,7 +443,7 @@ describe API::Jobs do
context 'user with :update_build persmission' do
it 'cancels running or pending job' do
expect(response).to have_gitlab_http_status(201)
- expect(project.builds.first.status).to eq('canceled')
+ expect(project.builds.first.status).to eq('success')
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index ef3f610740d..0c9fbb1f187 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -500,6 +500,12 @@ describe API::MergeRequests do
end
end
+ describe 'GET /projects/:id/merge_requests/:merge_request_iid/participants' do
+ it_behaves_like 'issuable participants endpoint' do
+ let(:entity) { merge_request }
+ end
+ end
+
describe 'GET /projects/:id/merge_requests/:merge_request_iid/commits' do
it 'returns a 200 when merge request is valid' do
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/commits", user)
diff --git a/spec/serializers/group_child_entity_spec.rb b/spec/serializers/group_child_entity_spec.rb
index 452754d7a79..505a9eaac5a 100644
--- a/spec/serializers/group_child_entity_spec.rb
+++ b/spec/serializers/group_child_entity_spec.rb
@@ -22,6 +22,7 @@ describe GroupChildEntity do
avatar_url
name
description
+ markdown_description
visibility
type
can_edit
@@ -60,9 +61,10 @@ describe GroupChildEntity do
end
describe 'for a group', :nested_groups do
+ let(:description) { 'Awesomeness' }
let(:object) do
create(:group, :nested, :with_avatar,
- description: 'Awesomeness')
+ description: description)
end
before do
@@ -96,6 +98,14 @@ describe GroupChildEntity do
expect(json[:edit_path]).to eq(edit_group_path(object))
end
+ context 'emoji in description' do
+ let(:description) { ':smile:' }
+
+ it 'has the correct markdown_description' do
+ expect(json[:markdown_description]).to eq('<p dir="auto"><gl-emoji title="smiling face with open mouth and smiling eyes" data-name="smile" data-unicode-version="6.0">😄</gl-emoji></p>')
+ end
+ end
+
it_behaves_like 'group child json'
end
end
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index e25552eb0d8..80a271ba7fb 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -190,4 +190,20 @@ describe MergeRequestWidgetEntity do
end
end
end
+
+ describe 'when source project is deleted' do
+ let(:project) { create(:project, :repository) }
+ let(:fork_project) { create(:project, :repository, forked_from_project: project) }
+ let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) }
+
+ it 'returns a blank rebase_path' do
+ allow(merge_request).to receive(:should_be_rebased?).and_return(true)
+ fork_project.destroy
+ merge_request.reload
+
+ entity = described_class.new(merge_request, request: request).as_json
+
+ expect(entity[:rebase_path]).to be_nil
+ end
+ end
end
diff --git a/spec/services/check_gcp_project_billing_service_spec.rb b/spec/services/check_gcp_project_billing_service_spec.rb
new file mode 100644
index 00000000000..f0e39ba6f49
--- /dev/null
+++ b/spec/services/check_gcp_project_billing_service_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe CheckGcpProjectBillingService do
+ let(:service) { described_class.new }
+ let(:projects) { [double(name: 'first_project'), double(name: 'second_project')] }
+
+ describe '#execute' do
+ before do
+ expect_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive(:projects_list).and_return(projects)
+
+ allow_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive_message_chain(:projects_get_billing_info, :billingEnabled)
+ .and_return(project_billing_enabled)
+ end
+
+ subject { service.execute('bogustoken') }
+
+ context 'google account has a billing enabled gcp project' do
+ let(:project_billing_enabled) { true }
+
+ it { is_expected.to eq(projects) }
+ end
+
+ context 'google account does not have a billing enabled gcp project' do
+ let(:project_billing_enabled) { false }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+end
diff --git a/spec/services/files/multi_service_spec.rb b/spec/services/files/multi_service_spec.rb
index 2b79609930c..b9971776b33 100644
--- a/spec/services/files/multi_service_spec.rb
+++ b/spec/services/files/multi_service_spec.rb
@@ -41,7 +41,7 @@ describe Files::MultiService do
describe '#execute' do
context 'with a valid action' do
- it 'returns a hash with the :success status ' do
+ it 'returns a hash with the :success status' do
results = subject.execute
expect(results[:status]).to eq(:success)
@@ -51,7 +51,7 @@ describe Files::MultiService do
context 'with an invalid action' do
let(:action) { 'rename' }
- it 'returns a hash with the :error status ' do
+ it 'returns a hash with the :error status' do
results = subject.execute
expect(results[:status]).to eq(:error)
diff --git a/spec/services/merge_requests/rebase_service_spec.rb b/spec/services/merge_requests/rebase_service_spec.rb
new file mode 100644
index 00000000000..d1b37cdd073
--- /dev/null
+++ b/spec/services/merge_requests/rebase_service_spec.rb
@@ -0,0 +1,134 @@
+require 'spec_helper'
+
+describe MergeRequests::RebaseService do
+ include ProjectForksHelper
+
+ let(:user) { create(:user) }
+ let(:merge_request) do
+ create(:merge_request,
+ source_branch: 'feature_conflict',
+ target_branch: 'master')
+ end
+ let(:project) { merge_request.project }
+ let(:repository) { project.repository.raw }
+
+ subject(:service) { described_class.new(project, user, {}) }
+
+ before do
+ project.add_master(user)
+ end
+
+ describe '#execute' do
+ context 'when another rebase is already in progress' do
+ before do
+ allow(merge_request).to receive(:rebase_in_progress?).and_return(true)
+ end
+
+ it 'saves the error message' do
+ subject.execute(merge_request)
+
+ expect(merge_request.reload.merge_error).to eq 'Rebase task canceled: Another rebase is already in progress'
+ end
+
+ it 'returns an error' do
+ expect(service.execute(merge_request)).to match(status: :error,
+ message: 'Failed to rebase. Should be done manually')
+ end
+ end
+
+ context 'when unexpected error occurs' do
+ before do
+ allow(repository).to receive(:run_git!).and_raise('Something went wrong')
+ end
+
+ it 'saves the error message' do
+ subject.execute(merge_request)
+
+ expect(merge_request.reload.merge_error).to eq 'Something went wrong'
+ end
+
+ it 'returns an error' do
+ expect(service.execute(merge_request)).to match(status: :error,
+ message: 'Failed to rebase. Should be done manually')
+ end
+ end
+
+ context 'with git command failure' do
+ before do
+ allow(repository).to receive(:run_git!).and_raise(Gitlab::Git::Repository::GitError, 'Something went wrong')
+ end
+
+ it 'saves the error message' do
+ subject.execute(merge_request)
+
+ expect(merge_request.reload.merge_error).to eq 'Something went wrong'
+ end
+
+ it 'returns an error' do
+ expect(service.execute(merge_request)).to match(status: :error,
+ message: 'Failed to rebase. Should be done manually')
+ end
+ end
+
+ context 'valid params' do
+ before do
+ service.execute(merge_request)
+ end
+
+ it 'rebases source branch' do
+ parent_sha = merge_request.source_project.repository.commit(merge_request.source_branch).parents.first.sha
+ target_branch_sha = merge_request.target_project.repository.commit(merge_request.target_branch).sha
+ expect(parent_sha).to eq(target_branch_sha)
+ end
+
+ it 'records the new SHA on the merge request' do
+ head_sha = merge_request.source_project.repository.commit(merge_request.source_branch).sha
+ expect(merge_request.reload.rebase_commit_sha).to eq(head_sha)
+ end
+
+ it 'logs correct author and commiter' do
+ head_commit = merge_request.source_project.repository.commit(merge_request.source_branch)
+
+ expect(head_commit.author_email).to eq('dmitriy.zaporozhets@gmail.com')
+ expect(head_commit.author_name).to eq('Dmitriy Zaporozhets')
+ expect(head_commit.committer_email).to eq(user.email)
+ expect(head_commit.committer_name).to eq(user.name)
+ end
+
+ context 'git commands' do
+ it 'sets GL_REPOSITORY env variable when calling git commands' do
+ expect(repository).to receive(:popen).exactly(3)
+ .with(anything, anything, hash_including('GL_REPOSITORY'))
+ .and_return(['', 0])
+
+ service.execute(merge_request)
+ end
+ end
+
+ context 'fork' do
+ let(:forked_project) do
+ fork_project(project, user, repository: true)
+ end
+
+ let(:merge_request_from_fork) do
+ forked_project.repository.create_file(
+ user,
+ 'new-file-to-target',
+ '',
+ message: 'Add new file to target',
+ branch_name: 'master')
+
+ create(:merge_request,
+ source_branch: 'master', source_project: forked_project,
+ target_branch: 'master', target_project: project)
+ end
+
+ it 'rebases source branch' do
+ parent_sha = forked_project.repository.commit(merge_request_from_fork.source_branch).parents.first.sha
+ target_branch_sha = project.repository.commit(merge_request_from_fork.target_branch).sha
+ expect(parent_sha).to eq(target_branch_sha)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 1833078f37c..9a44dfde41b 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -255,7 +255,7 @@ describe Projects::CreateService, '#execute' do
it 'writes project full path to .git/config' do
project = create_project(user, opts)
- expect(project.repo.config['gitlab.fullpath']).to eq project.full_path
+ expect(project.repository.rugged.config['gitlab.fullpath']).to eq project.full_path
end
def create_project(user, opts)
diff --git a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
index ded864beb1d..7b536cc05cb 100644
--- a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
+++ b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
@@ -37,7 +37,7 @@ describe Projects::HashedStorage::MigrateRepositoryService do
it 'writes project full path to .git/config' do
service.execute
- expect(project.repo.config['gitlab.fullpath']).to eq project.full_path
+ expect(project.repository.rugged.config['gitlab.fullpath']).to eq project.full_path
end
end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 7377c748698..39f6388c25e 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -58,7 +58,7 @@ describe Projects::TransferService do
it 'updates project full path in .git/config' do
transfer_project(project, user, group)
- expect(project.repo.config['gitlab.fullpath']).to eq "#{group.full_path}/#{project.path}"
+ expect(project.repository.rugged.config['gitlab.fullpath']).to eq "#{group.full_path}/#{project.path}"
end
end
@@ -95,7 +95,7 @@ describe Projects::TransferService do
it 'rolls back project full path in .git/config' do
attempt_project_transfer
- expect(project.repo.config['gitlab.fullpath']).to eq project.full_path
+ expect(project.repository.rugged.config['gitlab.fullpath']).to eq project.full_path
end
it "doesn't send move notifications" do
diff --git a/spec/services/protected_branches/create_service_spec.rb b/spec/services/protected_branches/create_service_spec.rb
index 835e83d6dba..53b3e5e365d 100644
--- a/spec/services/protected_branches/create_service_spec.rb
+++ b/spec/services/protected_branches/create_service_spec.rb
@@ -19,5 +19,21 @@ describe ProtectedBranches::CreateService do
expect(project.protected_branches.last.push_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER])
expect(project.protected_branches.last.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER])
end
+
+ context 'when user does not have permission' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+ end
+
+ it 'creates a new protected branch if we skip authorization step' do
+ expect { service.execute(skip_authorization: true) }.to change(ProtectedBranch, :count).by(1)
+ end
+
+ it 'raises Gitlab::Access:AccessDeniedError' do
+ expect { service.execute }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
+ end
end
end
diff --git a/spec/services/reset_project_cache_service_spec.rb b/spec/services/reset_project_cache_service_spec.rb
new file mode 100644
index 00000000000..de475d16586
--- /dev/null
+++ b/spec/services/reset_project_cache_service_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe ResetProjectCacheService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ subject { described_class.new(project, user).execute }
+
+ context 'when project cache_index is nil' do
+ before do
+ project.jobs_cache_index = nil
+ end
+
+ it 'sets project cache_index to one' do
+ expect { subject }.to change { project.reload.jobs_cache_index }.from(nil).to(1)
+ end
+ end
+
+ context 'when project cache_index is a numeric value' do
+ before do
+ project.update_attributes(jobs_cache_index: 1)
+ end
+
+ it 'increments project cache index' do
+ expect { subject }.to change { project.reload.jobs_cache_index }.by(1)
+ end
+ end
+end
diff --git a/spec/support/background_migrations_matchers.rb b/spec/support/background_migrations_matchers.rb
index 423c0e4cefc..f4127efc6ae 100644
--- a/spec/support/background_migrations_matchers.rb
+++ b/spec/support/background_migrations_matchers.rb
@@ -1,4 +1,4 @@
-RSpec::Matchers.define :be_scheduled_migration do |delay, *expected|
+RSpec::Matchers.define :be_scheduled_delayed_migration do |delay, *expected|
match do |migration|
BackgroundMigrationWorker.jobs.any? do |job|
job['args'] == [migration, expected] &&
@@ -11,3 +11,16 @@ RSpec::Matchers.define :be_scheduled_migration do |delay, *expected|
'not scheduled in expected time!'
end
end
+
+RSpec::Matchers.define :be_scheduled_migration do |*expected|
+ match do |migration|
+ BackgroundMigrationWorker.jobs.any? do |job|
+ args = job['args'].size == 1 ? [BackgroundMigrationWorker.jobs[0]['args'][0], []] : job['args']
+ args == [migration, expected]
+ end
+ end
+
+ failure_message do |migration|
+ "Migration `#{migration}` with args `#{expected.inspect}` not scheduled!"
+ end
+end
diff --git a/spec/support/google_api/cloud_platform_helpers.rb b/spec/support/google_api/cloud_platform_helpers.rb
index 8a073e58db8..99752ed396e 100644
--- a/spec/support/google_api/cloud_platform_helpers.rb
+++ b/spec/support/google_api/cloud_platform_helpers.rb
@@ -10,6 +10,12 @@ module GoogleApi
request.session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] = 1.hour.ago.to_i.to_s
end
+ def stub_google_project_billing_status
+ redis_double = double
+ allow(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis_double)
+ allow(redis_double).to receive(:get).with(CheckGcpProjectBillingWorker.redis_shared_state_key_for('token')).and_return('true')
+ end
+
def stub_cloud_platform_get_zone_cluster(project_id, zone, cluster_id, **options)
WebMock.stub_request(:get, cloud_platform_get_zone_cluster_url(project_id, zone, cluster_id))
.to_return(cloud_platform_response(cloud_platform_cluster_body(options)))
diff --git a/spec/support/shared_examples/requests/api/issuable_participants_examples.rb b/spec/support/shared_examples/requests/api/issuable_participants_examples.rb
new file mode 100644
index 00000000000..96d59e0c472
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/issuable_participants_examples.rb
@@ -0,0 +1,29 @@
+shared_examples 'issuable participants endpoint' do
+ let(:area) { entity.class.name.underscore.pluralize }
+
+ it 'returns participants' do
+ get api("/projects/#{project.id}/#{area}/#{entity.iid}/participants", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(entity.participants.size)
+
+ last_participant = entity.participants.last
+ expect(json_response.last['id']).to eq(last_participant.id)
+ expect(json_response.last['name']).to eq(last_participant.name)
+ expect(json_response.last['username']).to eq(last_participant.username)
+ end
+
+ it 'returns a 404 when iid does not exist' do
+ get api("/projects/#{project.id}/#{area}/999/participants", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns a 404 when id is used instead of iid' do
+ get api("/projects/#{project.id}/#{area}/#{entity.id}/participants", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+end
diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb
index 28d54c2fb77..264e0ce0b40 100644
--- a/spec/views/projects/merge_requests/show.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb
@@ -54,6 +54,8 @@ describe 'projects/merge_requests/show.html.haml' do
it 'closes the merge request if the source project does not exist' do
closed_merge_request.update_attributes(state: 'open')
forked_project.destroy
+ # Reload merge request so MergeRequest#source_project turns to `nil`
+ closed_merge_request.reload
render
diff --git a/spec/workers/check_gcp_project_billing_worker_spec.rb b/spec/workers/check_gcp_project_billing_worker_spec.rb
new file mode 100644
index 00000000000..f52a903327c
--- /dev/null
+++ b/spec/workers/check_gcp_project_billing_worker_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+describe CheckGcpProjectBillingWorker do
+ describe '.perform' do
+ let(:token) { 'bogustoken' }
+
+ subject { described_class.new.perform('token_key') }
+
+ context 'when there is a token in redis' do
+ before do
+ allow_any_instance_of(described_class).to receive(:get_session_token).and_return(token)
+ end
+
+ context 'when there is no lease' do
+ before do
+ allow_any_instance_of(described_class).to receive(:try_obtain_lease_for).and_return('randomuuid')
+ end
+
+ it 'calls the service' do
+ expect(CheckGcpProjectBillingService).to receive_message_chain(:new, :execute).and_return([double])
+
+ subject
+ end
+
+ it 'stores billing status in redis' do
+ redis_double = double
+
+ expect(CheckGcpProjectBillingService).to receive_message_chain(:new, :execute).and_return([double])
+ expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis_double)
+ expect(redis_double).to receive(:set).with(described_class.redis_shared_state_key_for(token), anything, anything)
+
+ subject
+ end
+ end
+
+ context 'when there is a lease' do
+ before do
+ allow_any_instance_of(described_class).to receive(:try_obtain_lease_for).and_return(false)
+ end
+
+ it 'does not call the service' do
+ expect(CheckGcpProjectBillingService).not_to receive(:new)
+
+ subject
+ end
+ end
+ end
+
+ context 'when there is no token in redis' do
+ before do
+ allow_any_instance_of(described_class).to receive(:get_session_token).and_return(nil)
+ end
+
+ it 'does not call the service' do
+ expect(CheckGcpProjectBillingService).not_to receive(:new)
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/workers/rebase_worker_spec.rb b/spec/workers/rebase_worker_spec.rb
new file mode 100644
index 00000000000..20aff020dbb
--- /dev/null
+++ b/spec/workers/rebase_worker_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe RebaseWorker, '#perform' do
+ context 'when rebasing an MR from a fork where upstream has protected branches' do
+ let(:upstream_project) { create(:project, :repository) }
+ let(:fork_project) { create(:project, :repository) }
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: fork_project,
+ source_branch: 'feature_conflict',
+ target_project: upstream_project,
+ target_branch: 'master')
+ end
+
+ before do
+ create(:forked_project_link, forked_to_project: fork_project, forked_from_project: upstream_project)
+ end
+
+ it 'sets the correct project for running hooks' do
+ expect(MergeRequests::RebaseService)
+ .to receive(:new).with(fork_project, merge_request.author).and_call_original
+
+ subject.perform(merge_request, merge_request.author)
+ end
+ end
+end
diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb
index 85ac14eb347..7274a9f00f9 100644
--- a/spec/workers/repository_import_worker_spec.rb
+++ b/spec/workers/repository_import_worker_spec.rb
@@ -32,6 +32,7 @@ describe RepositoryImportWorker do
expect_any_instance_of(Projects::ImportService).to receive(:execute)
.and_return({ status: :ok })
+ expect_any_instance_of(Project).to receive(:after_import).and_call_original
expect_any_instance_of(Repository).to receive(:expire_emptiness_caches)
expect_any_instance_of(Project).to receive(:import_finish)