summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorClement Ho <clemmakesapps@gmail.com>2018-05-10 16:00:33 +0000
committerClement Ho <clemmakesapps@gmail.com>2018-05-10 16:00:33 +0000
commitd77433a8ff87959d1e7bafd5aca093975106b891 (patch)
tree18913b14f8bcec7adf57e8abb36c880f6ccb23f3 /spec
parentf6e47f6f222380eead684ae8ba0ae522f7fcd789 (diff)
parent0afcfd31bdf8d23bc180d5a36796aba8e66dbd33 (diff)
downloadgitlab-ce-d77433a8ff87959d1e7bafd5aca093975106b891.tar.gz
Merge branch 'master' into 'bootstrap4'
# Conflicts: # app/views/shared/runners/_form.html.haml
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/ci/runners.rb2
-rw-r--r--spec/factories/merge_requests.rb5
-rw-r--r--spec/features/issuables/markdown_references/internal_references_spec.rb80
-rw-r--r--spec/features/issuables/markdown_references/jira_spec.rb187
-rw-r--r--spec/features/issuables/markdown_references_spec.rb193
-rw-r--r--spec/features/projects/merge_requests/user_merges_merge_request_spec.rb43
-rw-r--r--spec/features/projects/merge_requests/user_rebases_merge_request_spec.rb34
-rw-r--r--spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb125
-rw-r--r--spec/helpers/projects_helper_spec.rb2
-rw-r--r--spec/javascripts/deploy_keys/components/app_spec.js23
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/actions_spec.js14
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/form_spec.js3
-rw-r--r--spec/javascripts/ide/lib/common/model_spec.js4
-rw-r--r--spec/javascripts/ide/mock_data.js1
-rw-r--r--spec/javascripts/ide/stores/actions/file_spec.js16
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb20
-rw-r--r--spec/lib/gitlab/git/raw_diff_change_spec.rb2
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb17
-rw-r--r--spec/lib/gitlab/metrics/prometheus_spec.rb18
-rw-r--r--spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb18
-rw-r--r--spec/migrations/add_pipeline_build_foreign_key_spec.rb32
-rw-r--r--spec/models/ci/runner_spec.rb3
-rw-r--r--spec/models/clusters/applications/runner_spec.rb3
-rw-r--r--spec/models/concerns/issuable_spec.rb18
-rw-r--r--spec/models/project_spec.rb48
-rw-r--r--spec/models/project_wiki_spec.rb11
-rw-r--r--spec/models/repository_spec.rb33
-rw-r--r--spec/requests/api/runner_spec.rb23
-rw-r--r--spec/spec_helper.rb7
-rw-r--r--spec/support/api/time_tracking_shared_examples.rb28
-rw-r--r--spec/support/forgery_protection.rb17
-rw-r--r--spec/support/helpers/migrations_helpers.rb10
-rw-r--r--spec/support/services/migrate_to_ghost_user_service_shared_examples.rb2
-rw-r--r--spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb165
34 files changed, 885 insertions, 322 deletions
diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb
index 34b8b246d0f..cdc170b9ccb 100644
--- a/spec/factories/ci/runners.rb
+++ b/spec/factories/ci/runners.rb
@@ -6,6 +6,7 @@ FactoryBot.define do
is_shared false
active true
access_level :not_protected
+ runner_type :project_type
trait :online do
contacted_at Time.now
@@ -13,6 +14,7 @@ FactoryBot.define do
trait :shared do
is_shared true
+ runner_type :instance_type
end
trait :specific do
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index d26cb0c3417..fab0ec22450 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -41,6 +41,11 @@ FactoryBot.define do
state :merged
end
+ trait :merged_target do
+ source_branch "merged-target"
+ target_branch "improve/awesome"
+ end
+
trait :closed do
state :closed
end
diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb
new file mode 100644
index 00000000000..8af4b157cd8
--- /dev/null
+++ b/spec/features/issuables/markdown_references/internal_references_spec.rb
@@ -0,0 +1,80 @@
+require "rails_helper"
+
+describe "Internal references", :js do
+ include Spec::Support::Helpers::Features::NotesHelpers
+
+ let(:private_project_user) { private_project.owner }
+ let(:private_project) { create(:project, :private, :repository) }
+ let(:private_project_issue) { create(:issue, project: private_project) }
+ let(:private_project_merge_request) { create(:merge_request, source_project: private_project) }
+ let(:public_project_user) { public_project.owner }
+ let(:public_project) { create(:project, :public, :repository) }
+ let(:public_project_issue) { create(:issue, project: public_project) }
+
+ context "when referencing to open issue" do
+ context "from private project" do
+ context "from issue" do
+ before do
+ sign_in(private_project_user)
+
+ visit(project_issue_path(private_project, private_project_issue))
+
+ add_note("##{public_project_issue.to_reference(private_project)}")
+ end
+
+ context "when user doesn't have access to private project" do
+ before do
+ sign_in(public_project_user)
+
+ visit(project_issue_path(public_project, public_project_issue))
+ end
+
+ it { expect(page).not_to have_css(".note") }
+ end
+ end
+
+ context "from merge request" do
+ before do
+ sign_in(private_project_user)
+
+ visit(project_merge_request_path(private_project, private_project_merge_request))
+
+ add_note("##{public_project_issue.to_reference(private_project)}")
+ end
+
+ context "when user doesn't have access to private project" do
+ before do
+ sign_in(public_project_user)
+
+ visit(project_issue_path(public_project, public_project_issue))
+ end
+
+ it "doesn't show any references" do
+ page.within(".issue-details") do
+ expect(page).not_to have_content("#merge-requests .merge-requests-title")
+ end
+ end
+ end
+
+ context "when user has access to private project" do
+ before do
+ visit(project_issue_path(public_project, public_project_issue))
+ end
+
+ it "shows references" do
+ page.within("#merge-requests .merge-requests-title") do
+ expect(page).to have_content("1 Related Merge Request")
+ end
+
+ page.within("#merge-requests ul") do
+ expect(page).to have_content(private_project_merge_request.title)
+ end
+
+ expect(page).to have_content("mentioned in merge request #{private_project_merge_request.to_reference(public_project)}")
+ .and have_content(private_project_user.name)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb
new file mode 100644
index 00000000000..fa0ab88624e
--- /dev/null
+++ b/spec/features/issuables/markdown_references/jira_spec.rb
@@ -0,0 +1,187 @@
+require "rails_helper"
+
+describe "Jira", :js do
+ let(:user) { create(:user) }
+ let(:actual_project) { create(:project, :public, :repository) }
+ let(:merge_request) { create(:merge_request, target_project: actual_project, source_project: actual_project) }
+ let(:issue_actual_project) { create(:issue, project: actual_project) }
+ let!(:other_project) { create(:project, :public) }
+ let!(:issue_other_project) { create(:issue, project: other_project) }
+ let(:issues) { [issue_actual_project, issue_other_project] }
+
+ shared_examples "correct references" do
+ before do
+ remotelink = double(:remotelink, all: [], build: double(save!: true))
+
+ stub_request(:get, "https://jira.example.com/rest/api/2/issue/JIRA-5")
+ stub_request(:post, "https://jira.example.com/rest/api/2/issue/JIRA-5/comment")
+ allow_any_instance_of(JIRA::Resource::Issue).to receive(:remotelink).and_return(remotelink)
+
+ sign_in(user)
+
+ visit(merge_request_path(merge_request))
+
+ build_note
+ end
+
+ it "creates a link to the referenced issue on the preview" do
+ find(".js-md-preview-button").click
+
+ wait_for_requests
+
+ page.within(".md-preview-holder") do
+ links_expectations
+ end
+ end
+
+ it "creates a link to the referenced issue after submit" do
+ click_button("Comment")
+
+ wait_for_requests
+
+ page.within("#diff-notes-app") do
+ links_expectations
+ end
+ end
+
+ it "creates a note on the referenced issues" do
+ click_button("Comment")
+
+ wait_for_requests
+
+ if referenced_issues.include?(issue_actual_project)
+ visit(issue_path(issue_actual_project))
+
+ page.within("#notes") do
+ expect(page).to have_content("#{user.to_reference} mentioned in merge request #{merge_request.to_reference}")
+ end
+ end
+
+ if referenced_issues.include?(issue_other_project)
+ visit(issue_path(issue_other_project))
+
+ page.within("#notes") do
+ expect(page).to have_content("#{user.to_reference} mentioned in merge request #{merge_request.to_reference(other_project)}")
+ end
+ end
+ end
+ end
+
+ context "when internal issues tracker is enabled for the other project" do
+ context "when only internal issues tracker is enabled for the actual project" do
+ include_examples "correct references" do
+ let(:referenced_issues) { [issue_actual_project, issue_other_project] }
+ let(:jira_referenced) { false }
+ end
+ end
+
+ context "when both external and internal issues trackers are enabled for the actual project" do
+ before do
+ create(:jira_service, project: actual_project)
+ end
+
+ include_examples "correct references" do
+ let(:referenced_issues) { [issue_actual_project, issue_other_project] }
+ let(:jira_referenced) { true }
+ end
+ end
+
+ context "when only external issues tracker is enabled for the actual project" do
+ let(:actual_project) { create(:project, :public, :repository, :issues_disabled) }
+
+ before do
+ create(:jira_service, project: actual_project)
+ end
+
+ include_examples "correct references" do
+ let(:referenced_issues) { [issue_other_project] }
+ let(:jira_referenced) { true }
+ end
+ end
+
+ context "when no tracker is enabled for the actual project" do
+ let(:actual_project) { create(:project, :public, :repository, :issues_disabled) }
+
+ include_examples 'correct references' do
+ let(:referenced_issues) { [issue_other_project] }
+ let(:jira_referenced) { false }
+ end
+ end
+ end
+
+ context "when internal issues tracker is disabled for the other project" do
+ let(:other_project) { create(:project, :public, :repository, :issues_disabled) }
+
+ context "when only internal issues tracker is enabled for the actual project" do
+ include_examples "correct references" do
+ let(:referenced_issues) { [issue_actual_project] }
+ let(:jira_referenced) { false }
+ end
+ end
+
+ context "when both external and internal issues trackers are enabled for the actual project" do
+ before do
+ create(:jira_service, project: actual_project)
+ end
+
+ include_examples "correct references" do
+ let(:referenced_issues) { [issue_actual_project] }
+ let(:jira_referenced) { true }
+ end
+ end
+
+ context "when only external issues tracker is enabled for the actual project" do
+ let(:actual_project) { create(:project, :public, :repository, :issues_disabled) }
+
+ before do
+ create(:jira_service, project: actual_project)
+ end
+
+ include_examples "correct references" do
+ let(:referenced_issues) { [] }
+ let(:jira_referenced) { true }
+ end
+ end
+
+ context "when no issues tracker is enabled for the actual project" do
+ let(:actual_project) { create(:project, :public, :repository, :issues_disabled) }
+
+ include_examples "correct references" do
+ let(:referenced_issues) { [] }
+ let(:jira_referenced) { false }
+ end
+ end
+ end
+
+ private
+
+ def build_note
+ markdown = <<~HEREDOC
+ Referencing internal issue #{issue_actual_project.to_reference},
+ cross-project #{issue_other_project.to_reference(actual_project)} external JIRA-5
+ and non existing #999
+ HEREDOC
+
+ page.within("#diff-notes-app") do
+ fill_in("note_note", with: markdown)
+ end
+ end
+
+ def links_expectations
+ issues.each do |issue|
+ if referenced_issues.include?(issue)
+ expect(page).to have_link(issue.to_reference, href: issue_path(issue))
+ else
+ expect(page).not_to have_link(issue.to_reference, href: issue_path(issue))
+ end
+ end
+
+ if jira_referenced
+ expect(page).to have_link("JIRA-5", href: "https://jira.example.com/browse/JIRA-5")
+ else
+ expect(page).not_to have_link("JIRA-5", href: "https://jira.example.com/browse/JIRA-5")
+ end
+
+ expect(page).not_to have_link("#999")
+ end
+end
diff --git a/spec/features/issuables/markdown_references_spec.rb b/spec/features/issuables/markdown_references_spec.rb
deleted file mode 100644
index dd4e10a9886..00000000000
--- a/spec/features/issuables/markdown_references_spec.rb
+++ /dev/null
@@ -1,193 +0,0 @@
-require 'rails_helper'
-
-describe 'Markdown References', :js do
- let(:user) { create(:user) }
- let(:actual_project) { create(:project, :public, :repository) }
- let(:merge_request) { create(:merge_request, target_project: actual_project, source_project: actual_project)}
- let(:issue_actual_project) { create(:issue, project: actual_project) }
- let!(:other_project) { create(:project, :public) }
- let!(:issue_other_project) { create(:issue, project: other_project) }
- let(:issues) { [issue_actual_project, issue_other_project] }
-
- def build_note
- markdown = "Referencing internal issue #{issue_actual_project.to_reference}, " +
- "cross-project #{issue_other_project.to_reference(actual_project)} external JIRA-5 " +
- "and non existing #999"
-
- page.within('#diff-notes-app') do
- fill_in 'note_note', with: markdown
- end
- end
-
- shared_examples 'correct references' do
- before do
- remotelink = double(:remotelink, all: [], build: double(save!: true))
-
- stub_request(:get, "https://jira.example.com/rest/api/2/issue/JIRA-5")
- stub_request(:post, "https://jira.example.com/rest/api/2/issue/JIRA-5/comment")
- allow_any_instance_of(JIRA::Resource::Issue).to receive(:remotelink).and_return(remotelink)
-
- sign_in(user)
- visit merge_request_path(merge_request)
- build_note
- end
-
- def links_expectations
- issues.each do |issue|
- if referenced_issues.include?(issue)
- expect(page).to have_link(issue.to_reference, href: issue_path(issue))
- else
- expect(page).not_to have_link(issue.to_reference, href: issue_path(issue))
- end
- end
-
- if jira_referenced
- expect(page).to have_link('JIRA-5', href: 'https://jira.example.com/browse/JIRA-5')
- else
- expect(page).not_to have_link('JIRA-5', href: 'https://jira.example.com/browse/JIRA-5')
- end
-
- expect(page).not_to have_link('#999')
- end
-
- it 'creates a link to the referenced issue on the preview' do
- find('.js-md-preview-button').click
- wait_for_requests
-
- page.within('.md-preview-holder') do
- links_expectations
- end
- end
-
- it 'creates a link to the referenced issue after submit' do
- click_button 'Comment'
- wait_for_requests
-
- page.within('#diff-notes-app') do
- links_expectations
- end
- end
-
- it 'creates a note on the referenced issues' do
- click_button 'Comment'
- wait_for_requests
-
- if referenced_issues.include?(issue_actual_project)
- visit issue_path(issue_actual_project)
-
- page.within('#notes') do
- expect(page).to have_content(
- "#{user.to_reference} mentioned in merge request #{merge_request.to_reference}"
- )
- end
- end
-
- if referenced_issues.include?(issue_other_project)
- visit issue_path(issue_other_project)
-
- page.within('#notes') do
- expect(page).to have_content(
- "#{user.to_reference} mentioned in merge request #{merge_request.to_reference(other_project)}"
- )
- end
- end
- end
- end
-
- context 'when internal issues tracker is enabled for the other project' do
- context 'when only internal issues tracker is enabled for the actual project' do
- include_examples 'correct references' do
- let(:referenced_issues) { [issue_actual_project, issue_other_project] }
- let(:jira_referenced) { false }
- end
- end
-
- context 'when both external and internal issues trackers are enabled for the actual project' do
- before do
- create(:jira_service, project: actual_project)
- end
-
- include_examples 'correct references' do
- let(:referenced_issues) { [issue_actual_project, issue_other_project] }
- let(:jira_referenced) { true }
- end
- end
-
- context 'when only external issues tracker is enabled for the actual project' do
- before do
- create(:jira_service, project: actual_project)
-
- actual_project.issues_enabled = false
- actual_project.save!
- end
-
- include_examples 'correct references' do
- let(:referenced_issues) { [issue_other_project] }
- let(:jira_referenced) { true }
- end
- end
-
- context 'when no tracker is enabled for the actual project' do
- before do
- actual_project.issues_enabled = false
- actual_project.save!
- end
-
- include_examples 'correct references' do
- let(:referenced_issues) { [issue_other_project] }
- let(:jira_referenced) { false }
- end
- end
- end
-
- context 'when internal issues tracker is disabled for the other project' do
- before do
- other_project.issues_enabled = false
- other_project.save!
- end
-
- context 'when only internal issues tracker is enabled for the actual project' do
- include_examples 'correct references' do
- let(:referenced_issues) { [issue_actual_project] }
- let(:jira_referenced) { false }
- end
- end
-
- context 'when both external and internal issues trackers are enabled for the actual project' do
- before do
- create(:jira_service, project: actual_project)
- end
-
- include_examples 'correct references' do
- let(:referenced_issues) { [issue_actual_project] }
- let(:jira_referenced) { true }
- end
- end
-
- context 'when only external issues tracker is enabled for the actual project' do
- before do
- create(:jira_service, project: actual_project)
-
- actual_project.issues_enabled = false
- actual_project.save!
- end
-
- include_examples 'correct references' do
- let(:referenced_issues) { [] }
- let(:jira_referenced) { true }
- end
- end
-
- context 'when no issues tracker is enabled for the actual project' do
- before do
- actual_project.issues_enabled = false
- actual_project.save!
- end
-
- include_examples 'correct references' do
- let(:referenced_issues) { [] }
- let(:jira_referenced) { false }
- end
- end
- end
-end
diff --git a/spec/features/projects/merge_requests/user_merges_merge_request_spec.rb b/spec/features/projects/merge_requests/user_merges_merge_request_spec.rb
new file mode 100644
index 00000000000..6539e6e9208
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_merges_merge_request_spec.rb
@@ -0,0 +1,43 @@
+require "spec_helper"
+
+describe "User merges a merge request", :js do
+ let(:user) { project.owner }
+
+ before do
+ sign_in(user)
+ end
+
+ shared_examples "fast forward merge a merge request" do
+ it "merges a merge request" do
+ expect(page).to have_content("Fast-forward merge without a merge commit").and have_button("Merge")
+
+ page.within(".mr-state-widget") do
+ click_button("Merge")
+ end
+
+ page.within(".status-box") do
+ expect(page).to have_content("Merged")
+ end
+ end
+ end
+
+ context "ff-only merge" do
+ let(:project) { create(:project, :public, :repository, merge_requests_ff_only_enabled: true) }
+
+ before do
+ visit(merge_request_path(merge_request))
+ end
+
+ context "when branch is rebased" do
+ let!(:merge_request) { create(:merge_request, :rebased, source_project: project) }
+
+ it_behaves_like "fast forward merge a merge request"
+ end
+
+ context "when branch is merged" do
+ let!(:merge_request) { create(:merge_request, :merged_target, source_project: project) }
+
+ it_behaves_like "fast forward merge a merge request"
+ end
+ end
+end
diff --git a/spec/features/projects/merge_requests/user_rebases_merge_request_spec.rb b/spec/features/projects/merge_requests/user_rebases_merge_request_spec.rb
new file mode 100644
index 00000000000..92e1c9942b1
--- /dev/null
+++ b/spec/features/projects/merge_requests/user_rebases_merge_request_spec.rb
@@ -0,0 +1,34 @@
+require "spec_helper"
+
+describe "User rebases a merge request", :js do
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
+ let(:user) { project.owner }
+
+ before do
+ sign_in(user)
+ end
+
+ shared_examples "rebases" do
+ it "rebases" do
+ visit(merge_request_path(merge_request))
+
+ expect(page).to have_button("Rebase")
+
+ click_button("Rebase")
+
+ expect(page).to have_content("Rebase in progress")
+ end
+ end
+
+ context "when merge is regular" do
+ let(:project) { create(:project, :public, :repository, merge_requests_rebase_enabled: true) }
+
+ it_behaves_like "rebases"
+ end
+
+ context "when merge is ff-only" do
+ let(:project) { create(:project, :public, :repository, merge_requests_ff_only_enabled: true) }
+
+ it_behaves_like "rebases"
+ end
+end
diff --git a/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
new file mode 100644
index 00000000000..71a077039b7
--- /dev/null
+++ b/spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb
@@ -0,0 +1,125 @@
+require "spec_helper"
+
+describe "User interacts with deploy keys", :js do
+ let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
+
+ before do
+ sign_in(user)
+ end
+
+ shared_examples "attaches a key" do
+ it "attaches key" do
+ visit(project_deploy_keys_path(project))
+
+ page.within(".deploy-keys") do
+ find(".badge", text: "1").click
+
+ click_button("Enable")
+
+ expect(page).not_to have_selector(".fa-spinner")
+ expect(current_path).to eq(project_settings_repository_path(project))
+
+ find(".js-deployKeys-tab-enabled_keys").click
+
+ expect(page).to have_content(deploy_key.title)
+ end
+ end
+ end
+
+ context "viewing deploy keys" do
+ let(:deploy_key) { create(:deploy_key) }
+
+ context "when project has keys" do
+ before do
+ create(:deploy_keys_project, project: project, deploy_key: deploy_key)
+ end
+
+ it "shows deploy keys" do
+ visit(project_deploy_keys_path(project))
+
+ page.within(".deploy-keys") do
+ expect(page).to have_content(deploy_key.title)
+ end
+ end
+ end
+
+ context "when another project has keys" do
+ let(:another_project) { create(:project) }
+
+ before do
+ create(:deploy_keys_project, project: another_project, deploy_key: deploy_key)
+
+ another_project.add_master(user)
+ end
+
+ it "shows deploy keys" do
+ visit(project_deploy_keys_path(project))
+
+ page.within(".deploy-keys") do
+ find('.js-deployKeys-tab-available_project_keys').click
+
+ expect(page).to have_content(deploy_key.title)
+ expect(find(".js-deployKeys-tab-available_project_keys .badge")).to have_content("1")
+ end
+ end
+ end
+
+ context "when there are public deploy keys" do
+ let!(:deploy_key) { create(:deploy_key, public: true) }
+
+ it "shows public deploy keys" do
+ visit(project_deploy_keys_path(project))
+
+ page.within(".deploy-keys") do
+ find(".js-deployKeys-tab-public_keys").click
+
+ expect(page).to have_content(deploy_key.title)
+ end
+ end
+ end
+ end
+
+ context "adding deploy keys" do
+ before do
+ visit(project_deploy_keys_path(project))
+ end
+
+ it "adds new key" do
+ DEPLOY_KEY_TITLE = attributes_for(:key)[:title]
+ DEPLOY_KEY_BODY = attributes_for(:key)[:key]
+
+ fill_in("deploy_key_title", with: DEPLOY_KEY_TITLE)
+ fill_in("deploy_key_key", with: DEPLOY_KEY_BODY)
+
+ click_button("Add key")
+
+ expect(current_path).to eq(project_settings_repository_path(project))
+
+ page.within(".deploy-keys") do
+ expect(page).to have_content(DEPLOY_KEY_TITLE)
+ end
+ end
+ end
+
+ context "attaching existing keys" do
+ context "from another project" do
+ let(:another_project) { create(:project) }
+ let(:deploy_key) { create(:deploy_key) }
+
+ before do
+ create(:deploy_keys_project, project: another_project, deploy_key: deploy_key)
+
+ another_project.add_master(user)
+ end
+
+ it_behaves_like "attaches a key"
+ end
+
+ context "when keys are public" do
+ let!(:deploy_key) { create(:deploy_key, public: true) }
+
+ it_behaves_like "attaches a key"
+ end
+ end
+end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 8fcb175416f..f8877b6d1aa 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -283,7 +283,7 @@ describe ProjectsHelper do
end
it 'removes the repo path' do
- repo = "#{storage_path}/namespace/test.git"
+ repo = File.join(storage_path, 'namespace/test.git')
import_error = "Could not clone #{repo}\n"
expect(sanitize_repo_path(project, import_error)).to eq('Could not clone [REPOS PATH]/namespace/test.git')
diff --git a/spec/javascripts/deploy_keys/components/app_spec.js b/spec/javascripts/deploy_keys/components/app_spec.js
index 3f9e25a8862..183d7cf2d41 100644
--- a/spec/javascripts/deploy_keys/components/app_spec.js
+++ b/spec/javascripts/deploy_keys/components/app_spec.js
@@ -1,28 +1,25 @@
-import _ from 'underscore';
import Vue from 'vue';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
import eventHub from '~/deploy_keys/eventhub';
import deployKeysApp from '~/deploy_keys/components/app.vue';
+import { TEST_HOST } from 'spec/test_constants';
describe('Deploy keys app component', () => {
const data = getJSONFixture('deploy_keys/keys.json');
let vm;
+ let mock;
- const deployKeysResponse = (request, next) => {
- next(
- request.respondWith(JSON.stringify(data), {
- status: 200,
- }),
- );
- };
+ beforeEach((done) => {
+ // setup axios mock before component
+ mock = new MockAdapter(axios);
+ mock.onGet(`${TEST_HOST}/dummy/`).replyOnce(200, data);
- beforeEach(done => {
const Component = Vue.extend(deployKeysApp);
- Vue.http.interceptors.push(deployKeysResponse);
-
vm = new Component({
propsData: {
- endpoint: '/test',
+ endpoint: `${TEST_HOST}/dummy`,
projectId: '8',
},
}).$mount();
@@ -31,7 +28,7 @@ describe('Deploy keys app component', () => {
});
afterEach(() => {
- Vue.http.interceptors = _.without(Vue.http.interceptors, deployKeysResponse);
+ mock.restore();
});
it('renders loading icon', done => {
diff --git a/spec/javascripts/ide/components/commit_sidebar/actions_spec.js b/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
index 144e78d14b5..27f10caccb1 100644
--- a/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
@@ -3,6 +3,7 @@ import store from '~/ide/stores';
import commitActions from '~/ide/components/commit_sidebar/actions.vue';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from 'spec/ide/helpers';
+import { projectData } from 'spec/ide/mock_data';
describe('IDE commit sidebar actions', () => {
let vm;
@@ -13,6 +14,8 @@ describe('IDE commit sidebar actions', () => {
vm = createComponentWithStore(Component, store);
vm.$store.state.currentBranchId = 'master';
+ vm.$store.state.currentProjectId = 'abcproject';
+ Vue.set(vm.$store.state.projects, 'abcproject', { ...projectData });
vm.$mount();
@@ -32,4 +35,15 @@ describe('IDE commit sidebar actions', () => {
it('renders current branch text', () => {
expect(vm.$el.textContent).toContain('Commit to master branch');
});
+
+ it('hides merge request option when project merge requests are disabled', done => {
+ vm.$store.state.projects.abcproject.merge_requests_enabled = false;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelectorAll('input[type="radio"]').length).toBe(2);
+ expect(vm.$el.textContent).not.toContain('Create a new branch and merge request');
+
+ done();
+ });
+ });
});
diff --git a/spec/javascripts/ide/components/commit_sidebar/form_spec.js b/spec/javascripts/ide/components/commit_sidebar/form_spec.js
index ce7c134bc97..8b47a365582 100644
--- a/spec/javascripts/ide/components/commit_sidebar/form_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/form_spec.js
@@ -4,6 +4,7 @@ import CommitForm from '~/ide/components/commit_sidebar/form.vue';
import { activityBarViews } from '~/ide/constants';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
+import { projectData } from 'spec/ide/mock_data';
import { resetStore } from '../../helpers';
describe('IDE commit form', () => {
@@ -14,6 +15,8 @@ describe('IDE commit form', () => {
spyOnProperty(window, 'innerHeight').and.returnValue(800);
store.state.changedFiles.push('test');
+ store.state.currentProjectId = 'abcproject';
+ Vue.set(store.state.projects, 'abcproject', { ...projectData });
vm = createComponentWithStore(Component, store).$mount();
});
diff --git a/spec/javascripts/ide/lib/common/model_spec.js b/spec/javascripts/ide/lib/common/model_spec.js
index 7a6c22b6d27..c278bf92b08 100644
--- a/spec/javascripts/ide/lib/common/model_spec.js
+++ b/spec/javascripts/ide/lib/common/model_spec.js
@@ -28,6 +28,10 @@ describe('Multi-file editor library model', () => {
expect(model.originalModel).not.toBeNull();
expect(model.model).not.toBeNull();
expect(model.baseModel).not.toBeNull();
+
+ expect(model.originalModel.uri.path).toBe('original/path--path');
+ expect(model.model.uri.path).toBe('path--path');
+ expect(model.baseModel.uri.path).toBe('target/path--path');
});
it('creates model with head file to compare against', () => {
diff --git a/spec/javascripts/ide/mock_data.js b/spec/javascripts/ide/mock_data.js
index 3c6d75ab5e4..c059862b9d1 100644
--- a/spec/javascripts/ide/mock_data.js
+++ b/spec/javascripts/ide/mock_data.js
@@ -12,4 +12,5 @@ export const projectData = {
},
},
mergeRequests: {},
+ merge_requests_enabled: true,
};
diff --git a/spec/javascripts/ide/stores/actions/file_spec.js b/spec/javascripts/ide/stores/actions/file_spec.js
index 3ef5a859001..7bebc2288e3 100644
--- a/spec/javascripts/ide/stores/actions/file_spec.js
+++ b/spec/javascripts/ide/stores/actions/file_spec.js
@@ -569,6 +569,22 @@ describe('IDE store file actions', () => {
.catch(done.fail);
});
+ it('returns false when already opened', done => {
+ store.state.openFiles.push({
+ ...f,
+ active: true,
+ key: `pending-${f.key}`,
+ });
+
+ store
+ .dispatch('openPendingTab', { file: f, keyPrefix: 'pending' })
+ .then(added => {
+ expect(added).toBe(false);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
it('pushes router URL when added', done => {
store.state.currentBranchId = 'master';
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index 67d898e787e..e2547ed0311 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -251,6 +251,26 @@ describe Gitlab::Git::Blob, seed_helper: true do
end
end
+ describe '.batch_metadata' do
+ let(:blob_references) do
+ [
+ [SeedRepo::Commit::ID, "files/ruby/popen.rb"],
+ [SeedRepo::Commit::ID, 'six']
+ ]
+ end
+
+ subject { described_class.batch_metadata(repository, blob_references) }
+
+ it 'returns an empty data attribute' do
+ first_blob, last_blob = subject
+
+ expect(first_blob.data).to be_blank
+ expect(first_blob.path).to eq("files/ruby/popen.rb")
+ expect(last_blob.data).to be_blank
+ expect(last_blob.path).to eq("six")
+ end
+ end
+
describe '.batch_lfs_pointers' do
let(:tree_object) { repository.rugged.rev_parse('master^{tree}') }
diff --git a/spec/lib/gitlab/git/raw_diff_change_spec.rb b/spec/lib/gitlab/git/raw_diff_change_spec.rb
index eedde34534f..a0bb37fd84a 100644
--- a/spec/lib/gitlab/git/raw_diff_change_spec.rb
+++ b/spec/lib/gitlab/git/raw_diff_change_spec.rb
@@ -12,7 +12,7 @@ describe Gitlab::Git::RawDiffChange do
expect(change.operation).to eq(:unknown)
expect(change.old_path).to be_blank
expect(change.new_path).to be_blank
- expect(change.blob_size).to be_blank
+ expect(change.blob_size).to eq(0)
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 9f091975959..cce84276fe3 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -2275,7 +2275,22 @@ describe Gitlab::Git::Repository, seed_helper: true do
expect(empty_repo.checksum).to eq '0000000000000000000000000000000000000000'
end
- it 'raises a no repository exception when there is no repo' do
+ it 'raises Gitlab::Git::Repository::InvalidRepository error for non-valid git repo' do
+ FileUtils.rm_rf(File.join(storage_path, 'non-valid.git'))
+
+ system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} non-valid.git),
+ chdir: SEED_STORAGE_PATH,
+ out: '/dev/null',
+ err: '/dev/null')
+
+ File.truncate(File.join(storage_path, 'non-valid.git/HEAD'), 0)
+
+ non_valid = described_class.new('default', 'non-valid.git', '')
+
+ expect { non_valid.checksum }.to raise_error(Gitlab::Git::Repository::InvalidRepository)
+ end
+
+ it 'raises Gitlab::Git::Repository::NoRepository error when there is no repo' do
broken_repo = described_class.new('default', 'a/path.git', '')
expect { broken_repo.checksum }.to raise_error(Gitlab::Git::Repository::NoRepository)
diff --git a/spec/lib/gitlab/metrics/prometheus_spec.rb b/spec/lib/gitlab/metrics/prometheus_spec.rb
new file mode 100644
index 00000000000..3d4dd5fdf01
--- /dev/null
+++ b/spec/lib/gitlab/metrics/prometheus_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Prometheus, :prometheus do
+ let(:all_metrics) { Gitlab::Metrics }
+ let(:registry) { all_metrics.registry }
+
+ describe '#reset_registry!' do
+ it 'clears existing metrics' do
+ registry.counter(:test, 'test metric')
+
+ expect(registry.metrics.count).to eq(1)
+
+ all_metrics.reset_registry!
+
+ expect(all_metrics.registry.metrics.count).to eq(0)
+ end
+ end
+end
diff --git a/spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb b/spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb
new file mode 100644
index 00000000000..6fd3cb1f44e
--- /dev/null
+++ b/spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb')
+
+describe AddNotNullConstraintToProjectMirrorDataForeignKey, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:import_state) { table(:project_mirror_data) }
+
+ before do
+ import_state.create!(id: 1, project_id: nil, status: :started)
+ end
+
+ it 'removes every import state without an associated project_id' do
+ expect do
+ subject.up
+ end.to change { import_state.count }.from(1).to(0)
+ end
+end
diff --git a/spec/migrations/add_pipeline_build_foreign_key_spec.rb b/spec/migrations/add_pipeline_build_foreign_key_spec.rb
new file mode 100644
index 00000000000..e9413f52f19
--- /dev/null
+++ b/spec/migrations/add_pipeline_build_foreign_key_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20180420010016_add_pipeline_build_foreign_key.rb')
+
+describe AddPipelineBuildForeignKey, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:pipelines) { table(:ci_pipelines) }
+ let(:builds) { table(:ci_builds) }
+
+ before do
+ namespaces.create(id: 10, name: 'gitlab-org', path: 'gitlab-org')
+ projects.create!(id: 11, namespace_id: 10, name: 'gitlab', path: 'gitlab')
+ pipelines.create!(id: 12, project_id: 11, ref: 'master', sha: 'adf43c3a')
+
+ builds.create!(id: 101, commit_id: 12, project_id: 11)
+ builds.create!(id: 102, commit_id: 222, project_id: 11)
+ builds.create!(id: 103, commit_id: 333, project_id: 11)
+ builds.create!(id: 104, commit_id: 12, project_id: 11)
+ builds.create!(id: 106, commit_id: nil, project_id: 11)
+ builds.create!(id: 107, commit_id: 12, project_id: nil)
+ end
+
+ it 'adds foreign key after removing orphans' do
+ expect(builds.all.count).to eq 6
+ expect(foreign_key_exists?(:ci_builds, :ci_pipelines, column: :commit_id)).to be_falsey
+
+ migrate!
+
+ expect(builds.all.pluck(:id)).to eq [101, 104]
+ expect(foreign_key_exists?(:ci_builds, :ci_pipelines, column: :commit_id)).to be_truthy
+ end
+end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index cc4d4e5e4ae..eb59ba7cbe9 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe Ci::Runner do
describe 'validation' do
it { is_expected.to validate_presence_of(:access_level) }
+ it { is_expected.to validate_presence_of(:runner_type) }
context 'when runner is not allowed to pick untagged jobs' do
context 'when runner does not have tags' do
@@ -198,7 +199,7 @@ describe Ci::Runner do
end
describe '#assign_to' do
- let!(:project) { FactoryBot.create :project }
+ let!(:project) { FactoryBot.create(:project) }
let!(:shared_runner) { FactoryBot.create(:ci_runner, :shared) }
before do
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 64d995a73c1..5f2c723d483 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -74,9 +74,8 @@ describe Clusters::Applications::Runner do
it 'assigns the new runner to runner' do
subject
- gitlab_runner.reload
- expect(gitlab_runner.runner).not_to be_nil
+ expect(gitlab_runner.reload.runner).to be_project_type
end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 05693f067e1..3d3092b8ac9 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -495,6 +495,14 @@ describe Issuable do
expect(issue.total_time_spent).to eq(1800)
end
+
+ it 'updates issues updated_at' do
+ issue
+
+ Timecop.travel(1.minute.from_now) do
+ expect { spend_time(1800) }.to change { issue.updated_at }
+ end
+ end
end
context 'substracting time' do
@@ -510,9 +518,13 @@ describe Issuable do
context 'when time to substract exceeds the total time spent' do
it 'raise a validation error' do
- expect do
- spend_time(-3600)
- end.to raise_error(ActiveRecord::RecordInvalid)
+ Timecop.travel(1.minute.from_now) do
+ expect do
+ expect do
+ spend_time(-3600)
+ end.to raise_error(ActiveRecord::RecordInvalid)
+ end.not_to change { issue.updated_at }
+ end
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index a6e835e563d..5b452f17979 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -309,12 +309,12 @@ describe Project do
describe 'project token' do
it 'sets an random token if none provided' do
- project = FactoryBot.create :project, runners_token: ''
+ project = FactoryBot.create(:project, runners_token: '')
expect(project.runners_token).not_to eq('')
end
it 'does not set an random token if one provided' do
- project = FactoryBot.create :project, runners_token: 'my-token'
+ project = FactoryBot.create(:project, runners_token: 'my-token')
expect(project.runners_token).to eq('my-token')
end
end
@@ -639,7 +639,7 @@ describe Project do
describe '#to_param' do
context 'with namespace' do
before do
- @group = create :group, name: 'gitlab'
+ @group = create(:group, name: 'gitlab')
@project = create(:project, name: 'gitlabhq', namespace: @group)
end
@@ -866,8 +866,8 @@ describe Project do
describe '#star_count' do
it 'counts stars from multiple users' do
- user1 = create :user
- user2 = create :user
+ user1 = create(:user)
+ user2 = create(:user)
project = create(:project, :public)
expect(project.star_count).to eq(0)
@@ -889,7 +889,7 @@ describe Project do
end
it 'counts stars on the right project' do
- user = create :user
+ user = create(:user)
project1 = create(:project, :public)
project2 = create(:project, :public)
@@ -1148,9 +1148,9 @@ describe Project do
describe '#any_runners?' do
context 'shared runners' do
- let(:project) { create :project, shared_runners_enabled: shared_runners_enabled }
- let(:specific_runner) { create :ci_runner }
- let(:shared_runner) { create :ci_runner, :shared }
+ let(:project) { create(:project, shared_runners_enabled: shared_runners_enabled) }
+ let(:specific_runner) { create(:ci_runner) }
+ let(:shared_runner) { create(:ci_runner, :shared) }
context 'for shared runners disabled' do
let(:shared_runners_enabled) { false }
@@ -1208,9 +1208,9 @@ describe Project do
end
context 'group runners' do
- let(:project) { create :project, group_runners_enabled: group_runners_enabled }
- let(:group) { create :group, projects: [project] }
- let(:group_runner) { create :ci_runner, groups: [group] }
+ let(:project) { create(:project, group_runners_enabled: group_runners_enabled) }
+ let(:group) { create(:group, projects: [project]) }
+ let(:group_runner) { create(:ci_runner, groups: [group]) }
context 'for group runners disabled' do
let(:group_runners_enabled) { false }
@@ -1292,7 +1292,7 @@ describe Project do
end
describe '#pages_deployed?' do
- let(:project) { create :project }
+ let(:project) { create(:project) }
subject { project.pages_deployed? }
@@ -1310,8 +1310,8 @@ describe Project do
end
describe '#pages_url' do
- let(:group) { create :group, name: group_name }
- let(:project) { create :project, namespace: group, name: project_name }
+ let(:group) { create(:group, name: group_name) }
+ let(:project) { create(:project, namespace: group, name: project_name) }
let(:domain) { 'Example.com' }
subject { project.pages_url }
@@ -1337,8 +1337,8 @@ describe Project do
end
describe '#pages_group_url' do
- let(:group) { create :group, name: group_name }
- let(:project) { create :project, namespace: group, name: project_name }
+ let(:group) { create(:group, name: group_name) }
+ let(:project) { create(:project, namespace: group, name: project_name) }
let(:domain) { 'Example.com' }
let(:port) { 1234 }
@@ -1455,8 +1455,8 @@ describe Project do
let(:private_group) { create(:group, visibility_level: 0) }
let(:internal_group) { create(:group, visibility_level: 10) }
- let(:private_project) { create :project, :private, group: private_group }
- let(:internal_project) { create :project, :internal, group: internal_group }
+ let(:private_project) { create(:project, :private, group: private_group) }
+ let(:internal_project) { create(:project, :internal, group: internal_group) }
context 'when group is private project can not be internal' do
it { expect(private_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_falsey }
@@ -2450,8 +2450,8 @@ describe Project do
end
describe '#pages_url' do
- let(:group) { create :group, name: 'Group' }
- let(:nested_group) { create :group, parent: group }
+ let(:group) { create(:group, name: 'Group') }
+ let(:nested_group) { create(:group, parent: group) }
let(:domain) { 'Example.com' }
subject { project.pages_url }
@@ -2462,7 +2462,7 @@ describe Project do
end
context 'top-level group' do
- let(:project) { create :project, namespace: group, name: project_name }
+ let(:project) { create(:project, namespace: group, name: project_name) }
context 'group page' do
let(:project_name) { 'group.example.com' }
@@ -2478,7 +2478,7 @@ describe Project do
end
context 'nested group' do
- let(:project) { create :project, namespace: nested_group, name: project_name }
+ let(:project) { create(:project, namespace: nested_group, name: project_name) }
let(:expected_url) { "http://group.example.com/#{nested_group.path}/#{project.path}" }
context 'group page' do
@@ -2496,7 +2496,7 @@ describe Project do
end
describe '#http_url_to_repo' do
- let(:project) { create :project }
+ let(:project) { create(:project) }
it 'returns the url to the repo without a username' do
expect(project.http_url_to_repo).to eq("#{project.web_url}.git")
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index d6c4031329d..f1142832f1a 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -159,6 +159,17 @@ describe ProjectWiki do
expect(page.title).to eq("autre pagé")
end
end
+
+ context 'pages with invalidly-encoded content' do
+ before do
+ create_page("encoding is fun", "f\xFCr".b)
+ end
+
+ it "can find the page" do
+ page = subject.find_page("encoding is fun")
+ expect(page.content).to eq("fr")
+ end
+ end
end
context 'when Gitaly wiki_find_page is enabled' do
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 4b736b02b7d..a7755a505d8 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1733,7 +1733,8 @@ describe Repository do
:gitlab_ci,
:avatar,
:issue_template,
- :merge_request_template
+ :merge_request_template,
+ :xcode_config
])
repository.after_change_head
@@ -2058,6 +2059,36 @@ describe Repository do
end
end
+ describe '#xcode_project?' do
+ before do
+ allow(repository).to receive(:tree).with(:head).and_return(double(:tree, blobs: [blob]))
+ end
+
+ context 'when the root contains a *.xcodeproj file' do
+ let(:blob) { double(:blob, path: 'Foo.xcodeproj') }
+
+ it 'returns true' do
+ expect(repository.xcode_project?).to be_truthy
+ end
+ end
+
+ context 'when the root contains a *.xcworkspace file' do
+ let(:blob) { double(:blob, path: 'Foo.xcworkspace') }
+
+ it 'returns true' do
+ expect(repository.xcode_project?).to be_truthy
+ end
+ end
+
+ context 'when the root contains no XCode config file' do
+ let(:blob) { double(:blob, path: 'subdir/Foo.xcworkspace') }
+
+ it 'returns false' do
+ expect(repository.xcode_project?).to be_falsey
+ end
+ end
+ end
+
describe "#keep_around" do
it "does not fail if we attempt to reference bad commit" do
expect(repository.kept_around?('abc1234')).to be_falsey
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index 082605827b7..da392c5ab81 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -41,6 +41,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
expect(json_response['id']).to eq(runner.id)
expect(json_response['token']).to eq(runner.token)
expect(runner.run_untagged).to be true
+ expect(runner.active).to be true
expect(runner.token).not_to eq(registration_token)
expect(runner).to be_instance_type
end
@@ -129,6 +130,28 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when option for activating a Runner is provided' do
+ context 'when active is set to true' do
+ it 'creates runner' do
+ post api('/runners'), token: registration_token,
+ active: true
+
+ expect(response).to have_gitlab_http_status 201
+ expect(Ci::Runner.first.active).to be true
+ end
+ end
+
+ context 'when active is set to false' do
+ it 'creates runner' do
+ post api('/runners'), token: registration_token,
+ active: false
+
+ expect(response).to have_gitlab_http_status 201
+ expect(Ci::Runner.first.active).to be false
+ end
+ end
+ end
+
context 'when maximum job timeout is specified' do
it 'creates runner' do
post api('/runners'), token: registration_token,
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index b4fc596a751..d3de2331244 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -137,6 +137,13 @@ RSpec.configure do |config|
reset_delivered_emails!
end
+ config.before(:example, :prometheus) do
+ matching_files = File.join(::Prometheus::Client.configuration.multiprocess_files_dir, "*.db")
+ Dir[matching_files].map { |filename| File.delete(filename) if File.file?(filename) }
+
+ Gitlab::Metrics.reset_registry!
+ end
+
config.around(:each, :use_clean_rails_memory_store_caching) do |example|
caching_store = Rails.cache
Rails.cache = ActiveSupport::Cache::MemoryStore.new
diff --git a/spec/support/api/time_tracking_shared_examples.rb b/spec/support/api/time_tracking_shared_examples.rb
index dd3089d22e5..52e1bc55191 100644
--- a/spec/support/api/time_tracking_shared_examples.rb
+++ b/spec/support/api/time_tracking_shared_examples.rb
@@ -70,8 +70,12 @@ shared_examples 'time tracking endpoints' do |issuable_name|
end
it "add spent time for #{issuable_name}" do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
- duration: '2h'
+ Timecop.travel(1.minute.from_now) do
+ expect do
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
+ duration: '2h'
+ end.to change { issuable.reload.updated_at }
+ end
expect(response).to have_gitlab_http_status(201)
expect(json_response['human_total_time_spent']).to eq('2h')
@@ -79,7 +83,11 @@ shared_examples 'time tracking endpoints' do |issuable_name|
context 'when subtracting time' do
it 'subtracts time of the total spent time' do
- issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
+ Timecop.travel(1.minute.from_now) do
+ expect do
+ issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
+ end.to change { issuable.reload.updated_at }
+ end
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
duration: '-1h'
@@ -93,8 +101,12 @@ shared_examples 'time tracking endpoints' do |issuable_name|
it 'does not modify the total time spent' do
issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
- duration: '-1w'
+ Timecop.travel(1.minute.from_now) do
+ expect do
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
+ duration: '-1w'
+ end.not_to change { issuable.reload.updated_at }
+ end
expect(response).to have_gitlab_http_status(400)
expect(json_response['message']['time_spent'].first).to match(/exceeds the total time spent/)
@@ -110,7 +122,11 @@ shared_examples 'time tracking endpoints' do |issuable_name|
end
it "resets spent time for #{issuable_name}" do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/reset_spent_time", user)
+ Timecop.travel(1.minute.from_now) do
+ expect do
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/reset_spent_time", user)
+ end.to change { issuable.reload.updated_at }
+ end
expect(response).to have_gitlab_http_status(200)
expect(json_response['total_time_spent']).to eq(0)
diff --git a/spec/support/forgery_protection.rb b/spec/support/forgery_protection.rb
index a5e7b761651..fa87d5fa881 100644
--- a/spec/support/forgery_protection.rb
+++ b/spec/support/forgery_protection.rb
@@ -1,11 +1,18 @@
+module ForgeryProtection
+ def with_forgery_protection
+ ActionController::Base.allow_forgery_protection = true
+ yield
+ ensure
+ ActionController::Base.allow_forgery_protection = false
+ end
+
+ module_function :with_forgery_protection
+end
+
RSpec.configure do |config|
config.around(:each, :allow_forgery_protection) do |example|
- begin
- ActionController::Base.allow_forgery_protection = true
-
+ ForgeryProtection.with_forgery_protection do
example.call
- ensure
- ActionController::Base.allow_forgery_protection = false
end
end
end
diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb
index 5d6f662e8fe..84abec75c26 100644
--- a/spec/support/helpers/migrations_helpers.rb
+++ b/spec/support/helpers/migrations_helpers.rb
@@ -24,6 +24,16 @@ module MigrationsHelpers
end
end
+ def foreign_key_exists?(source, target = nil, column: nil)
+ ActiveRecord::Base.connection.foreign_keys(source).any? do |key|
+ if column
+ key.options[:column].to_s == column.to_s
+ else
+ key.to_table.to_s == target.to_s
+ end
+ end
+ end
+
def reset_column_in_all_models
clear_schema_cache!
diff --git a/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb b/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb
index adfd256dff1..1478c6b5a47 100644
--- a/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb
+++ b/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb
@@ -86,7 +86,7 @@ shared_examples "migrating a deleted user's associated records to the ghost user
end
it "blocks the user before #{record_class_name} migration begins" do
- expect(service).to receive("migrate_#{record_class_name.parameterize('_')}s".to_sym) do
+ expect(service).to receive("migrate_#{record_class_name.parameterize('_').pluralize}".to_sym) do
expect(user.reload).to be_blocked
end
diff --git a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
index 7a7dcb71680..aed62f97448 100644
--- a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
+++ b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
@@ -7,113 +7,138 @@ describe ObjectStorage::MigrateUploadsWorker, :sidekiq do
end
end
- let!(:projects) { create_list(:project, 10, :with_avatar) }
- let(:uploads) { Upload.all }
let(:model_class) { Project }
- let(:mounted_as) { :avatar }
+ let(:uploads) { Upload.all }
let(:to_store) { ObjectStorage::Store::REMOTE }
- before do
- stub_uploads_object_storage(AvatarUploader)
- end
-
- describe '.enqueue!' do
- def enqueue!
- described_class.enqueue!(uploads, Project, mounted_as, to_store)
- end
+ shared_examples "uploads migration worker" do
+ describe '.enqueue!' do
+ def enqueue!
+ described_class.enqueue!(uploads, Project, mounted_as, to_store)
+ end
- it 'is guarded by .sanity_check!' do
- expect(described_class).to receive(:perform_async)
- expect(described_class).to receive(:sanity_check!)
+ it 'is guarded by .sanity_check!' do
+ expect(described_class).to receive(:perform_async)
+ expect(described_class).to receive(:sanity_check!)
- enqueue!
- end
+ enqueue!
+ end
- context 'sanity_check! fails' do
- include_context 'sanity_check! fails'
+ context 'sanity_check! fails' do
+ include_context 'sanity_check! fails'
- it 'does not enqueue a job' do
- expect(described_class).not_to receive(:perform_async)
+ it 'does not enqueue a job' do
+ expect(described_class).not_to receive(:perform_async)
- expect { enqueue! }.to raise_error(described_class::SanityCheckError)
+ expect { enqueue! }.to raise_error(described_class::SanityCheckError)
+ end
end
end
- end
- describe '.sanity_check!' do
- shared_examples 'raises a SanityCheckError' do
- let(:mount_point) { nil }
+ describe '.sanity_check!' do
+ shared_examples 'raises a SanityCheckError' do
+ let(:mount_point) { nil }
- it do
- expect { described_class.sanity_check!(uploads, model_class, mount_point) }
- .to raise_error(described_class::SanityCheckError)
+ it do
+ expect { described_class.sanity_check!(uploads, model_class, mount_point) }
+ .to raise_error(described_class::SanityCheckError)
+ end
end
- end
- context 'uploader types mismatch' do
- let!(:outlier) { create(:upload, uploader: 'FileUploader') }
+ before do
+ stub_const("WrongModel", Class.new)
+ end
- include_examples 'raises a SanityCheckError'
- end
+ context 'uploader types mismatch' do
+ let!(:outlier) { create(:upload, uploader: 'GitlabUploader') }
- context 'model types mismatch' do
- let!(:outlier) { create(:upload, model_type: 'Potato') }
+ include_examples 'raises a SanityCheckError'
+ end
- include_examples 'raises a SanityCheckError'
- end
+ context 'model types mismatch' do
+ let!(:outlier) { create(:upload, model_type: 'WrongModel') }
- context 'mount point not found' do
- include_examples 'raises a SanityCheckError' do
- let(:mount_point) { :potato }
+ include_examples 'raises a SanityCheckError'
end
- end
- end
- describe '#perform' do
- def perform
- described_class.new.perform(uploads.ids, model_class.to_s, mounted_as, to_store)
- rescue ObjectStorage::MigrateUploadsWorker::Report::MigrationFailures
- # swallow
+ context 'mount point not found' do
+ include_examples 'raises a SanityCheckError' do
+ let(:mount_point) { :potato }
+ end
+ end
end
- shared_examples 'outputs correctly' do |success: 0, failures: 0|
- total = success + failures
+ describe '#perform' do
+ def perform
+ described_class.new.perform(uploads.ids, model_class.to_s, mounted_as, to_store)
+ rescue ObjectStorage::MigrateUploadsWorker::Report::MigrationFailures
+ # swallow
+ end
+
+ shared_examples 'outputs correctly' do |success: 0, failures: 0|
+ total = success + failures
- if success > 0
- it 'outputs the reports' do
- expect(Rails.logger).to receive(:info).with(%r{Migrated #{success}/#{total} files})
+ if success > 0
+ it 'outputs the reports' do
+ expect(Rails.logger).to receive(:info).with(%r{Migrated #{success}/#{total} files})
- perform
+ perform
+ end
end
- end
- if failures > 0
- it 'outputs upload failures' do
- expect(Rails.logger).to receive(:warn).with(/Error .* I am a teapot/)
+ if failures > 0
+ it 'outputs upload failures' do
+ expect(Rails.logger).to receive(:warn).with(/Error .* I am a teapot/)
- perform
+ perform
+ end
end
end
- end
- it_behaves_like 'outputs correctly', success: 10
+ it_behaves_like 'outputs correctly', success: 10
+
+ it 'migrates files' do
+ perform
- it 'migrates files' do
- perform
+ expect(Upload.where(store: ObjectStorage::Store::LOCAL).count).to eq(0)
+ end
- aggregate_failures do
- projects.each do |project|
- expect(project.reload.avatar.upload.local?).to be_falsey
+ context 'migration is unsuccessful' do
+ before do
+ allow_any_instance_of(ObjectStorage::Concern)
+ .to receive(:migrate!).and_raise(CarrierWave::UploadError, "I am a teapot.")
end
+
+ it_behaves_like 'outputs correctly', failures: 10
end
end
+ end
- context 'migration is unsuccessful' do
- before do
- allow_any_instance_of(ObjectStorage::Concern).to receive(:migrate!).and_raise(CarrierWave::UploadError, "I am a teapot.")
- end
+ context "for AvatarUploader" do
+ let!(:projects) { create_list(:project, 10, :with_avatar) }
+ let(:mounted_as) { :avatar }
- it_behaves_like 'outputs correctly', failures: 10
+ before do
+ stub_uploads_object_storage(AvatarUploader)
+ end
+
+ it_behaves_like "uploads migration worker"
+ end
+
+ context "for FileUploader" do
+ let!(:projects) { create_list(:project, 10) }
+ let(:secret) { SecureRandom.hex }
+ let(:mounted_as) { nil }
+
+ before do
+ stub_uploads_object_storage(FileUploader)
+
+ projects.map do |project|
+ uploader = FileUploader.new(project)
+ uploader.store!(fixture_file_upload('spec/fixtures/doc_sample.txt'))
+ end
end
+
+ it_behaves_like "uploads migration worker"
end
end