summaryrefslogtreecommitdiff
path: root/spec/lib
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-08-08 10:14:21 +0200
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2016-08-08 10:14:21 +0200
commit8ae222092dc63d672dc505358d7bdfbb8478c774 (patch)
tree44082b65f583923ff48fd1315e0ccf44c2293b6e /spec/lib
parent1b5e2303debf00784603d6bd9d87d613de3c8091 (diff)
parent91030230545a199a86c2742600a7a2e68ef75c98 (diff)
downloadgitlab-ce-8ae222092dc63d672dc505358d7bdfbb8478c774.tar.gz
Merge branch 'master' into feature/svg-badge-template
* master: (363 commits) Added changelog item for issuable form dropdowns Add 'run tests' docs from GDK Bump gitlab_git to lazy load compare commits Add examples to repository files API (!5465) Ignore URLs starting with // (!5677) Add failing test for #7032 Update timeago to shorter representation Add missing DOWNTIME constant to the AddTimestampsToMembersAgain migration Added guide about migrations and downtime Update CHANGELOG for 8.10.4 Add a data migration to fix some missing timestamps in the members table (again) Move abilities by subject class to a dedicated method Remove unnecessary empty line after css var Set consistency in list text height css Add description to text/plain emails Fix Rename `add_users_into_project` and `projects_ids` fix spec Underscore variable to camelCase using shared path for project import uploads and refactored gitlab remove export worker Structure the development documentation ...
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/banzai/filter/relative_link_filter_spec.rb17
-rw-r--r--spec/lib/banzai/reference_parser/issue_parser_spec.rb12
-rw-r--r--spec/lib/ci/gitlab_ci_yaml_processor_spec.rb67
-rw-r--r--spec/lib/gitlab/akismet_helper_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/config/node/artifacts_spec.rb45
-rw-r--r--spec/lib/gitlab/ci/config/node/attributable_spec.rb43
-rw-r--r--spec/lib/gitlab/ci/config/node/commands_spec.rb49
-rw-r--r--spec/lib/gitlab/ci/config/node/factory_spec.rb38
-rw-r--r--spec/lib/gitlab/ci/config/node/global_spec.rb66
-rw-r--r--spec/lib/gitlab/ci/config/node/hidden_job_spec.rb58
-rw-r--r--spec/lib/gitlab/ci/config/node/job_spec.rb86
-rw-r--r--spec/lib/gitlab/ci/config/node/jobs_spec.rb87
-rw-r--r--spec/lib/gitlab/ci/config/node/null_spec.rb41
-rw-r--r--spec/lib/gitlab/ci/config/node/stage_spec.rb38
-rw-r--r--spec/lib/gitlab/ci/config/node/trigger_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/config/node/undefined_spec.rb32
-rw-r--r--spec/lib/gitlab/closing_issue_extractor_spec.rb11
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/highlight_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/line_mapper_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/parallel_diff_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/parser_spec.rb2
-rw-r--r--spec/lib/gitlab/email/email_shared_blocks.rb41
-rw-r--r--spec/lib/gitlab/email/handler/create_issue_handler_spec.rb79
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb116
-rw-r--r--spec/lib/gitlab/email/message/repository_push_spec.rb13
-rw-r--r--spec/lib/gitlab/email/receiver_spec.rb157
-rw-r--r--spec/lib/gitlab/git_access_spec.rb92
-rw-r--r--spec/lib/gitlab/highlight_spec.rb12
-rw-r--r--spec/lib/gitlab/import_export/project.json176
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb12
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb30
-rw-r--r--spec/lib/gitlab/import_export/version_checker_spec.rb30
-rw-r--r--spec/lib/gitlab/incoming_email_spec.rb4
-rw-r--r--spec/lib/gitlab/metrics/instrumentation_spec.rb12
-rw-r--r--spec/lib/gitlab/metrics/system_spec.rb12
-rw-r--r--spec/lib/gitlab/metrics/transaction_spec.rb16
-rw-r--r--spec/lib/gitlab/metrics_spec.rb6
-rw-r--r--spec/lib/gitlab/user_access_spec.rb4
39 files changed, 1126 insertions, 454 deletions
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb
index 9921171f2aa..bda8d2ce38a 100644
--- a/spec/lib/banzai/filter/relative_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb
@@ -78,12 +78,29 @@ describe Banzai::Filter::RelativeLinkFilter, lib: true do
end
context 'with a valid repository' do
+ it 'rebuilds absolute URL for a file in the repo' do
+ doc = filter(link('/doc/api/README.md'))
+ expect(doc.at_css('a')['href']).
+ to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
+ end
+
+ it 'ignores absolute URLs with two leading slashes' do
+ doc = filter(link('//doc/api/README.md'))
+ expect(doc.at_css('a')['href']).to eq '//doc/api/README.md'
+ end
+
it 'rebuilds relative URL for a file in the repo' do
doc = filter(link('doc/api/README.md'))
expect(doc.at_css('a')['href']).
to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
end
+ it 'rebuilds relative URL for a file in the repo with leading ./' do
+ doc = filter(link('./doc/api/README.md'))
+ expect(doc.at_css('a')['href']).
+ to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
+ end
+
it 'rebuilds relative URL for a file in the repo up one directory' do
relative_link = link('../api/README.md')
doc = filter(relative_link, requested_path: 'doc/update/7.14-to-8.0.md')
diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb
index 514c752546d..85cfe728b6a 100644
--- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb
@@ -16,17 +16,17 @@ describe Banzai::ReferenceParser::IssueParser, lib: true do
end
it 'returns the nodes when the user can read the issue' do
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_issue, issue).
- and_return(true)
+ expect(Ability).to receive(:issues_readable_by_user).
+ with([issue], user).
+ and_return([issue])
expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
end
it 'returns an empty Array when the user can not read the issue' do
- expect(Ability.abilities).to receive(:allowed?).
- with(user, :read_issue, issue).
- and_return(false)
+ expect(Ability).to receive(:issues_readable_by_user).
+ with([issue], user).
+ and_return([])
expect(subject.nodes_visible_to_user(user, [link])).to eq([])
end
diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
index d20fd4ab7dd..61490555ff5 100644
--- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
+++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
@@ -162,7 +162,7 @@ module Ci
shared_examples 'raises an error' do
it do
- expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'rspec job: only parameter should be an array of strings or regexps')
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:only config should be an array of strings or regexps')
end
end
@@ -318,7 +318,7 @@ module Ci
shared_examples 'raises an error' do
it do
- expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'rspec job: except parameter should be an array of strings or regexps')
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:except config should be an array of strings or regexps')
end
end
@@ -559,7 +559,7 @@ module Ci
it 'raises error' do
expect { subject }
.to raise_error(GitlabCiYamlProcessor::ValidationError,
- /job: variables should be a map/)
+ /jobs:rspec:variables config should be a hash of key value pairs/)
end
end
@@ -774,7 +774,7 @@ module Ci
let(:environment) { 1 }
it 'raises error' do
- expect { builds }.to raise_error("deploy_to_production job: environment parameter #{Gitlab::Regex.environment_name_regex_message}")
+ expect { builds }.to raise_error("jobs:deploy_to_production environment #{Gitlab::Regex.environment_name_regex_message}")
end
end
@@ -782,7 +782,7 @@ module Ci
let(:environment) { 'production staging' }
it 'raises error' do
- expect { builds }.to raise_error("deploy_to_production job: environment parameter #{Gitlab::Regex.environment_name_regex_message}")
+ expect { builds }.to raise_error("jobs:deploy_to_production environment #{Gitlab::Regex.environment_name_regex_message}")
end
end
end
@@ -973,7 +973,7 @@ EOT
config = YAML.dump({ rspec: { script: "test", tags: "mysql" } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: tags parameter should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec tags should be an array of strings")
end
it "returns errors if before_script parameter is invalid" do
@@ -987,7 +987,7 @@ EOT
config = YAML.dump({ rspec: { script: "test", before_script: [10, "test"] } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: before_script should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:before_script config should be an array of strings")
end
it "returns errors if after_script parameter is invalid" do
@@ -1001,7 +1001,7 @@ EOT
config = YAML.dump({ rspec: { script: "test", after_script: [10, "test"] } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: after_script should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:after_script config should be an array of strings")
end
it "returns errors if image parameter is invalid" do
@@ -1015,21 +1015,21 @@ EOT
config = YAML.dump({ '' => { script: "test" } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "job name should be non-empty string")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:job name can't be blank")
end
it "returns errors if job name is non-string" do
config = YAML.dump({ 10 => { script: "test" } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "job name should be non-empty string")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:10 name should be a symbol")
end
it "returns errors if job image parameter is invalid" do
config = YAML.dump({ rspec: { script: "test", image: ["test"] } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: image should be a string")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:image config should be a string")
end
it "returns errors if services parameter is not an array" do
@@ -1050,49 +1050,56 @@ EOT
config = YAML.dump({ rspec: { script: "test", services: "test" } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: services should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:services config should be an array of strings")
end
it "returns errors if job services parameter is not an array of strings" do
config = YAML.dump({ rspec: { script: "test", services: [10, "test"] } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: services should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:services config should be an array of strings")
end
- it "returns errors if there are unknown parameters" do
+ it "returns error if job configuration is invalid" do
config = YAML.dump({ extra: "bundle update" })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Unknown parameter: extra")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:extra config should be a hash")
end
it "returns errors if there are unknown parameters that are hashes, but doesn't have a script" do
config = YAML.dump({ extra: { services: "test" } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Unknown parameter: extra")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:extra:services config should be an array of strings")
end
it "returns errors if there are no jobs defined" do
config = YAML.dump({ before_script: ["bundle update"] })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Please define at least one job")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs config should contain at least one visible job")
+ end
+
+ it "returns errors if there are no visible jobs defined" do
+ config = YAML.dump({ before_script: ["bundle update"], '.hidden'.to_sym => { script: 'ls' } })
+ expect do
+ GitlabCiYamlProcessor.new(config, path)
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs config should contain at least one visible job")
end
it "returns errors if job allow_failure parameter is not an boolean" do
config = YAML.dump({ rspec: { script: "test", allow_failure: "string" } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: allow_failure parameter should be an boolean")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec allow failure should be a boolean value")
end
it "returns errors if job stage is not a string" do
config = YAML.dump({ rspec: { script: "test", type: 1 } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test, deploy")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:type config should be a string")
end
it "returns errors if job stage is not a pre-defined stage" do
@@ -1141,49 +1148,49 @@ EOT
config = YAML.dump({ rspec: { script: "test", when: 1 } })
expect do
GitlabCiYamlProcessor.new(config, path)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: when parameter should be on_success, on_failure, always or manual")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec when should be on_success, on_failure, always or manual")
end
it "returns errors if job artifacts:name is not an a string" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { name: 1 } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:name parameter should be a string")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts name should be a string")
end
it "returns errors if job artifacts:when is not an a predefined value" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { when: 1 } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:when parameter should be on_success, on_failure or always")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts when should be on_success, on_failure or always")
end
it "returns errors if job artifacts:expire_in is not an a string" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { expire_in: 1 } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:expire_in parameter should be a duration")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts expire in should be a duration")
end
it "returns errors if job artifacts:expire_in is not an a valid duration" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { expire_in: "7 elephants" } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:expire_in parameter should be a duration")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts expire in should be a duration")
end
it "returns errors if job artifacts:untracked is not an array of strings" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { untracked: "string" } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:untracked parameter should be an boolean")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts untracked should be a boolean value")
end
it "returns errors if job artifacts:paths is not an array of strings" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", artifacts: { paths: "string" } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: artifacts:paths parameter should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:artifacts paths should be an array of strings")
end
it "returns errors if cache:untracked is not an array of strings" do
@@ -1211,28 +1218,28 @@ EOT
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { key: 1 } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:key parameter should be a string")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:cache:key config should be a string or symbol")
end
it "returns errors if job cache:untracked is not an array of strings" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { untracked: "string" } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:untracked parameter should be an boolean")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:cache:untracked config should be a boolean value")
end
it "returns errors if job cache:paths is not an array of strings" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { paths: "string" } } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:paths parameter should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec:cache:paths config should be an array of strings")
end
it "returns errors if job dependencies is not an array of strings" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", dependencies: "string" } })
expect do
GitlabCiYamlProcessor.new(config)
- end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: dependencies parameter should be an array of strings")
+ end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:rspec dependencies should be an array of strings")
end
end
diff --git a/spec/lib/gitlab/akismet_helper_spec.rb b/spec/lib/gitlab/akismet_helper_spec.rb
index 88a71528867..b08396da4d2 100644
--- a/spec/lib/gitlab/akismet_helper_spec.rb
+++ b/spec/lib/gitlab/akismet_helper_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::AkismetHelper, type: :helper do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :public) }
let(:user) { create(:user) }
before do
@@ -11,13 +11,13 @@ describe Gitlab::AkismetHelper, type: :helper do
end
describe '#check_for_spam?' do
- it 'returns true for non-member' do
- expect(helper.check_for_spam?(project, user)).to eq(true)
+ it 'returns true for public project' do
+ expect(helper.check_for_spam?(project)).to eq(true)
end
- it 'returns false for member' do
- project.team << [user, :guest]
- expect(helper.check_for_spam?(project, user)).to eq(false)
+ it 'returns false for private project' do
+ project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
+ expect(helper.check_for_spam?(project)).to eq(false)
end
end
diff --git a/spec/lib/gitlab/ci/config/node/artifacts_spec.rb b/spec/lib/gitlab/ci/config/node/artifacts_spec.rb
new file mode 100644
index 00000000000..c09a0a9c793
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/artifacts_spec.rb
@@ -0,0 +1,45 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Artifacts do
+ let(:entry) { described_class.new(config) }
+
+ describe 'validation' do
+ context 'when entry config value is correct' do
+ let(:config) { { paths: %w[public/] } }
+
+ describe '#value' do
+ it 'returns artifacs configuration' do
+ expect(entry.value).to eq config
+ end
+ end
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when entry value is not correct' do
+ describe '#errors' do
+ context 'when value of attribute is invalid' do
+ let(:config) { { name: 10 } }
+
+ it 'reports error' do
+ expect(entry.errors)
+ .to include 'artifacts name should be a string'
+ end
+ end
+
+ context 'when there is an unknown key present' do
+ let(:config) { { test: 100 } }
+
+ it 'reports error' do
+ expect(entry.errors)
+ .to include 'artifacts config contains unknown keys: test'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/attributable_spec.rb b/spec/lib/gitlab/ci/config/node/attributable_spec.rb
new file mode 100644
index 00000000000..24d9daafd88
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/attributable_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Attributable do
+ let(:node) { Class.new }
+ let(:instance) { node.new }
+
+ before do
+ node.include(described_class)
+
+ node.class_eval do
+ attributes :name, :test
+ end
+ end
+
+ context 'config is a hash' do
+ before do
+ allow(instance)
+ .to receive(:config)
+ .and_return({ name: 'some name', test: 'some test' })
+ end
+
+ it 'returns the value of config' do
+ expect(instance.name).to eq 'some name'
+ expect(instance.test).to eq 'some test'
+ end
+
+ it 'returns no method error for unknown attributes' do
+ expect { instance.unknown }.to raise_error(NoMethodError)
+ end
+ end
+
+ context 'config is not a hash' do
+ before do
+ allow(instance)
+ .to receive(:config)
+ .and_return('some test')
+ end
+
+ it 'returns nil' do
+ expect(instance.test).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/commands_spec.rb b/spec/lib/gitlab/ci/config/node/commands_spec.rb
new file mode 100644
index 00000000000..e373c40706f
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/commands_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Commands do
+ let(:entry) { described_class.new(config) }
+
+ context 'when entry config value is an array' do
+ let(:config) { ['ls', 'pwd'] }
+
+ describe '#value' do
+ it 'returns array of strings' do
+ expect(entry.value).to eq config
+ end
+ end
+
+ describe '#errors' do
+ it 'does not append errors' do
+ expect(entry.errors).to be_empty
+ end
+ end
+ end
+
+ context 'when entry config value is a string' do
+ let(:config) { 'ls' }
+
+ describe '#value' do
+ it 'returns array with single element' do
+ expect(entry.value).to eq ['ls']
+ end
+ end
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when entry value is not valid' do
+ let(:config) { 1 }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors)
+ .to include 'commands config should be a ' \
+ 'string or an array of strings'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/factory_spec.rb b/spec/lib/gitlab/ci/config/node/factory_spec.rb
index 91ddef7bfbf..d26185ba585 100644
--- a/spec/lib/gitlab/ci/config/node/factory_spec.rb
+++ b/spec/lib/gitlab/ci/config/node/factory_spec.rb
@@ -2,13 +2,13 @@ require 'spec_helper'
describe Gitlab::Ci::Config::Node::Factory do
describe '#create!' do
- let(:factory) { described_class.new(entry_class) }
- let(:entry_class) { Gitlab::Ci::Config::Node::Script }
+ let(:factory) { described_class.new(node) }
+ let(:node) { Gitlab::Ci::Config::Node::Script }
- context 'when setting up a value' do
+ context 'when setting a concrete value' do
it 'creates entry with valid value' do
entry = factory
- .with(value: ['ls', 'pwd'])
+ .value(['ls', 'pwd'])
.create!
expect(entry.value).to eq ['ls', 'pwd']
@@ -17,7 +17,7 @@ describe Gitlab::Ci::Config::Node::Factory do
context 'when setting description' do
it 'creates entry with description' do
entry = factory
- .with(value: ['ls', 'pwd'])
+ .value(['ls', 'pwd'])
.with(description: 'test description')
.create!
@@ -29,7 +29,8 @@ describe Gitlab::Ci::Config::Node::Factory do
context 'when setting key' do
it 'creates entry with custom key' do
entry = factory
- .with(value: ['ls', 'pwd'], key: 'test key')
+ .value(['ls', 'pwd'])
+ .with(key: 'test key')
.create!
expect(entry.key).to eq 'test key'
@@ -37,19 +38,20 @@ describe Gitlab::Ci::Config::Node::Factory do
end
context 'when setting a parent' do
- let(:parent) { Object.new }
+ let(:object) { Object.new }
it 'creates entry with valid parent' do
entry = factory
- .with(value: 'ls', parent: parent)
+ .value('ls')
+ .with(parent: object)
.create!
- expect(entry.parent).to eq parent
+ expect(entry.parent).to eq object
end
end
end
- context 'when not setting up a value' do
+ context 'when not setting a value' do
it 'raises error' do
expect { factory.create! }.to raise_error(
Gitlab::Ci::Config::Node::Factory::InvalidFactory
@@ -60,11 +62,25 @@ describe Gitlab::Ci::Config::Node::Factory do
context 'when creating entry with nil value' do
it 'creates an undefined entry' do
entry = factory
- .with(value: nil)
+ .value(nil)
.create!
expect(entry).to be_an_instance_of Gitlab::Ci::Config::Node::Undefined
end
end
+
+ context 'when passing metadata' do
+ let(:node) { spy('node') }
+
+ it 'passes metadata as a parameter' do
+ factory
+ .value('some value')
+ .metadata(some: 'hash')
+ .create!
+
+ expect(node).to have_received(:new)
+ .with('some value', { some: 'hash' })
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/node/global_spec.rb b/spec/lib/gitlab/ci/config/node/global_spec.rb
index c87c9e97bc8..2f87d270b36 100644
--- a/spec/lib/gitlab/ci/config/node/global_spec.rb
+++ b/spec/lib/gitlab/ci/config/node/global_spec.rb
@@ -22,38 +22,40 @@ describe Gitlab::Ci::Config::Node::Global do
variables: { VAR: 'value' },
after_script: ['make clean'],
stages: ['build', 'pages'],
- cache: { key: 'k', untracked: true, paths: ['public/'] } }
+ cache: { key: 'k', untracked: true, paths: ['public/'] },
+ rspec: { script: %w[rspec ls] },
+ spinach: { script: 'spinach' } }
end
describe '#process!' do
before { global.process! }
it 'creates nodes hash' do
- expect(global.nodes).to be_an Array
+ expect(global.descendants).to be_an Array
end
it 'creates node object for each entry' do
- expect(global.nodes.count).to eq 8
+ expect(global.descendants.count).to eq 8
end
it 'creates node object using valid class' do
- expect(global.nodes.first)
+ expect(global.descendants.first)
.to be_an_instance_of Gitlab::Ci::Config::Node::Script
- expect(global.nodes.second)
+ expect(global.descendants.second)
.to be_an_instance_of Gitlab::Ci::Config::Node::Image
end
it 'sets correct description for nodes' do
- expect(global.nodes.first.description)
+ expect(global.descendants.first.description)
.to eq 'Script that will be executed before each job.'
- expect(global.nodes.second.description)
+ expect(global.descendants.second.description)
.to eq 'Docker image that will be used to execute jobs.'
end
- end
- describe '#leaf?' do
- it 'is not leaf' do
- expect(global).not_to be_leaf
+ describe '#leaf?' do
+ it 'is not leaf' do
+ expect(global).not_to be_leaf
+ end
end
end
@@ -63,6 +65,12 @@ describe Gitlab::Ci::Config::Node::Global do
expect(global.before_script).to be nil
end
end
+
+ describe '#leaf?' do
+ it 'is leaf' do
+ expect(global).to be_leaf
+ end
+ end
end
context 'when processed' do
@@ -106,7 +114,10 @@ describe Gitlab::Ci::Config::Node::Global do
end
context 'when deprecated types key defined' do
- let(:hash) { { types: ['test', 'deploy'] } }
+ let(:hash) do
+ { types: ['test', 'deploy'],
+ rspec: { script: 'rspec' } }
+ end
it 'returns array of types as stages' do
expect(global.stages).to eq %w[test deploy]
@@ -120,20 +131,33 @@ describe Gitlab::Ci::Config::Node::Global do
.to eq(key: 'k', untracked: true, paths: ['public/'])
end
end
+
+ describe '#jobs' do
+ it 'returns jobs configuration' do
+ expect(global.jobs).to eq(
+ rspec: { name: :rspec,
+ script: %w[rspec ls],
+ stage: 'test' },
+ spinach: { name: :spinach,
+ script: %w[spinach],
+ stage: 'test' }
+ )
+ end
+ end
end
end
context 'when most of entires not defined' do
- let(:hash) { { cache: { key: 'a' }, rspec: {} } }
+ let(:hash) { { cache: { key: 'a' }, rspec: { script: %w[ls] } } }
before { global.process! }
describe '#nodes' do
it 'instantizes all nodes' do
- expect(global.nodes.count).to eq 8
+ expect(global.descendants.count).to eq 8
end
it 'contains undefined nodes' do
- expect(global.nodes.first)
+ expect(global.descendants.first)
.to be_an_instance_of Gitlab::Ci::Config::Node::Undefined
end
end
@@ -164,7 +188,7 @@ describe Gitlab::Ci::Config::Node::Global do
# details.
#
context 'when entires specified but not defined' do
- let(:hash) { { variables: nil } }
+ let(:hash) { { variables: nil, rspec: { script: 'rspec' } } }
before { global.process! }
describe '#variables' do
@@ -196,10 +220,8 @@ describe Gitlab::Ci::Config::Node::Global do
end
describe '#before_script' do
- it 'raises error' do
- expect { global.before_script }.to raise_error(
- Gitlab::Ci::Config::Node::Entry::InvalidError
- )
+ it 'returns nil' do
+ expect(global.before_script).to be_nil
end
end
end
@@ -220,9 +242,9 @@ describe Gitlab::Ci::Config::Node::Global do
end
end
- describe '#defined?' do
+ describe '#specified?' do
it 'is concrete entry that is defined' do
- expect(global.defined?).to be true
+ expect(global.specified?).to be true
end
end
end
diff --git a/spec/lib/gitlab/ci/config/node/hidden_job_spec.rb b/spec/lib/gitlab/ci/config/node/hidden_job_spec.rb
new file mode 100644
index 00000000000..cc44e2cc054
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/hidden_job_spec.rb
@@ -0,0 +1,58 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::HiddenJob do
+ let(:entry) { described_class.new(config) }
+
+ describe 'validations' do
+ context 'when entry config value is correct' do
+ let(:config) { { image: 'ruby:2.2' } }
+
+ describe '#value' do
+ it 'returns key value' do
+ expect(entry.value).to eq(image: 'ruby:2.2')
+ end
+ end
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when entry value is not correct' do
+ context 'incorrect config value type' do
+ let(:config) { ['incorrect'] }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors)
+ .to include 'hidden job config should be a hash'
+ end
+ end
+ end
+
+ context 'when config is empty' do
+ let(:config) { {} }
+
+ describe '#valid' do
+ it 'is invalid' do
+ expect(entry).not_to be_valid
+ end
+ end
+ end
+ end
+ end
+
+ describe '#leaf?' do
+ it 'is a leaf' do
+ expect(entry).to be_leaf
+ end
+ end
+
+ describe '#relevant?' do
+ it 'is not a relevant entry' do
+ expect(entry).not_to be_relevant
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/job_spec.rb b/spec/lib/gitlab/ci/config/node/job_spec.rb
new file mode 100644
index 00000000000..1484fb60dd8
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/job_spec.rb
@@ -0,0 +1,86 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Job do
+ let(:entry) { described_class.new(config, name: :rspec) }
+
+ before { entry.process! }
+
+ describe 'validations' do
+ context 'when entry config value is correct' do
+ let(:config) { { script: 'rspec' } }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ context 'when job name is empty' do
+ let(:entry) { described_class.new(config, name: ''.to_sym) }
+
+ it 'reports error' do
+ expect(entry.errors)
+ .to include "job name can't be blank"
+ end
+ end
+ end
+
+ context 'when entry value is not correct' do
+ context 'incorrect config value type' do
+ let(:config) { ['incorrect'] }
+
+ describe '#errors' do
+ it 'reports error about a config type' do
+ expect(entry.errors)
+ .to include 'job config should be a hash'
+ end
+ end
+ end
+
+ context 'when config is empty' do
+ let(:config) { {} }
+
+ describe '#valid' do
+ it 'is invalid' do
+ expect(entry).not_to be_valid
+ end
+ end
+ end
+
+ context 'when unknown keys detected' do
+ let(:config) { { unknown: true } }
+
+ describe '#valid' do
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ end
+ end
+ end
+ end
+ end
+
+ describe '#value' do
+ context 'when entry is correct' do
+ let(:config) do
+ { before_script: %w[ls pwd],
+ script: 'rspec',
+ after_script: %w[cleanup] }
+ end
+
+ it 'returns correct value' do
+ expect(entry.value)
+ .to eq(name: :rspec,
+ before_script: %w[ls pwd],
+ script: %w[rspec],
+ stage: 'test',
+ after_script: %w[cleanup])
+ end
+ end
+ end
+
+ describe '#relevant?' do
+ it 'is a relevant entry' do
+ expect(entry).to be_relevant
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/jobs_spec.rb b/spec/lib/gitlab/ci/config/node/jobs_spec.rb
new file mode 100644
index 00000000000..b8d9c70479c
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/jobs_spec.rb
@@ -0,0 +1,87 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Jobs do
+ let(:entry) { described_class.new(config) }
+
+ describe 'validations' do
+ before { entry.process! }
+
+ context 'when entry config value is correct' do
+ let(:config) { { rspec: { script: 'rspec' } } }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when entry value is not correct' do
+ describe '#errors' do
+ context 'incorrect config value type' do
+ let(:config) { ['incorrect'] }
+
+ it 'returns error about incorrect type' do
+ expect(entry.errors)
+ .to include 'jobs config should be a hash'
+ end
+ end
+
+ context 'when job is unspecified' do
+ let(:config) { { rspec: nil } }
+
+ it 'reports error' do
+ expect(entry.errors).to include "rspec config can't be blank"
+ end
+ end
+
+ context 'when no visible jobs present' do
+ let(:config) { { '.hidden'.to_sym => { script: [] } } }
+
+ it 'returns error about no visible jobs defined' do
+ expect(entry.errors)
+ .to include 'jobs config should contain at least one visible job'
+ end
+ end
+ end
+ end
+ end
+
+ context 'when valid job entries processed' do
+ before { entry.process! }
+
+ let(:config) do
+ { rspec: { script: 'rspec' },
+ spinach: { script: 'spinach' },
+ '.hidden'.to_sym => {} }
+ end
+
+ describe '#value' do
+ it 'returns key value' do
+ expect(entry.value).to eq(
+ rspec: { name: :rspec,
+ script: %w[rspec],
+ stage: 'test' },
+ spinach: { name: :spinach,
+ script: %w[spinach],
+ stage: 'test' })
+ end
+ end
+
+ describe '#descendants' do
+ it 'creates valid descendant nodes' do
+ expect(entry.descendants.count).to eq 3
+ expect(entry.descendants.first(2))
+ .to all(be_an_instance_of(Gitlab::Ci::Config::Node::Job))
+ expect(entry.descendants.last)
+ .to be_an_instance_of(Gitlab::Ci::Config::Node::HiddenJob)
+ end
+ end
+
+ describe '#value' do
+ it 'returns value of visible jobs only' do
+ expect(entry.value.keys).to eq [:rspec, :spinach]
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/null_spec.rb b/spec/lib/gitlab/ci/config/node/null_spec.rb
new file mode 100644
index 00000000000..1ab5478dcfa
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/null_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Null do
+ let(:null) { described_class.new(nil) }
+
+ describe '#leaf?' do
+ it 'is leaf node' do
+ expect(null).to be_leaf
+ end
+ end
+
+ describe '#valid?' do
+ it 'is always valid' do
+ expect(null).to be_valid
+ end
+ end
+
+ describe '#errors' do
+ it 'is does not contain errors' do
+ expect(null.errors).to be_empty
+ end
+ end
+
+ describe '#value' do
+ it 'returns nil' do
+ expect(null.value).to eq nil
+ end
+ end
+
+ describe '#relevant?' do
+ it 'is not relevant' do
+ expect(null.relevant?).to eq false
+ end
+ end
+
+ describe '#specified?' do
+ it 'is not defined' do
+ expect(null.specified?).to eq false
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/stage_spec.rb b/spec/lib/gitlab/ci/config/node/stage_spec.rb
new file mode 100644
index 00000000000..fb9ec70762a
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/stage_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Stage do
+ let(:stage) { described_class.new(config) }
+
+ describe 'validations' do
+ context 'when stage config value is correct' do
+ let(:config) { 'build' }
+
+ describe '#value' do
+ it 'returns a stage key' do
+ expect(stage.value).to eq config
+ end
+ end
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(stage).to be_valid
+ end
+ end
+ end
+
+ context 'when value has a wrong type' do
+ let(:config) { { test: true } }
+
+ it 'reports errors about wrong type' do
+ expect(stage.errors)
+ .to include 'stage config should be a string'
+ end
+ end
+ end
+
+ describe '.default' do
+ it 'returns default stage' do
+ expect(described_class.default).to eq 'test'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/trigger_spec.rb b/spec/lib/gitlab/ci/config/node/trigger_spec.rb
new file mode 100644
index 00000000000..a4a3e36754e
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/node/trigger_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Node::Trigger do
+ let(:entry) { described_class.new(config) }
+
+ describe 'validations' do
+ context 'when entry config value is valid' do
+ context 'when config is a branch or tag name' do
+ let(:config) { %w[master feature/branch] }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ describe '#value' do
+ it 'returns key value' do
+ expect(entry.value).to eq config
+ end
+ end
+ end
+
+ context 'when config is a regexp' do
+ let(:config) { ['/^issue-.*$/'] }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when config is a special keyword' do
+ let(:config) { %w[tags triggers branches] }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+ end
+
+ context 'when entry value is not valid' do
+ let(:config) { [1] }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors)
+ .to include 'trigger config should be an array of strings or regexps'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/node/undefined_spec.rb b/spec/lib/gitlab/ci/config/node/undefined_spec.rb
index 0c6608d906d..2d43e1c1a9d 100644
--- a/spec/lib/gitlab/ci/config/node/undefined_spec.rb
+++ b/spec/lib/gitlab/ci/config/node/undefined_spec.rb
@@ -2,39 +2,31 @@ require 'spec_helper'
describe Gitlab::Ci::Config::Node::Undefined do
let(:undefined) { described_class.new(entry) }
- let(:entry) { Class.new }
-
- describe '#leaf?' do
- it 'is leaf node' do
- expect(undefined).to be_leaf
- end
- end
+ let(:entry) { spy('Entry') }
describe '#valid?' do
- it 'is always valid' do
- expect(undefined).to be_valid
+ it 'delegates method to entry' do
+ expect(undefined.valid).to eq entry
end
end
describe '#errors' do
- it 'is does not contain errors' do
- expect(undefined.errors).to be_empty
+ it 'delegates method to entry' do
+ expect(undefined.errors).to eq entry
end
end
describe '#value' do
- before do
- allow(entry).to receive(:default).and_return('some value')
- end
-
- it 'returns default value for entry' do
- expect(undefined.value).to eq 'some value'
+ it 'delegates method to entry' do
+ expect(undefined.value).to eq entry
end
end
- describe '#undefined?' do
- it 'is not a defined entry' do
- expect(undefined.defined?).to be false
+ describe '#specified?' do
+ it 'is always false' do
+ allow(entry).to receive(:specified?).and_return(true)
+
+ expect(undefined.specified?).to be false
end
end
end
diff --git a/spec/lib/gitlab/closing_issue_extractor_spec.rb b/spec/lib/gitlab/closing_issue_extractor_spec.rb
index e9b8ce6b5bb..de3f64249a2 100644
--- a/spec/lib/gitlab/closing_issue_extractor_spec.rb
+++ b/spec/lib/gitlab/closing_issue_extractor_spec.rb
@@ -3,10 +3,12 @@ require 'spec_helper'
describe Gitlab::ClosingIssueExtractor, lib: true do
let(:project) { create(:project) }
let(:project2) { create(:project) }
+ let(:forked_project) { Projects::ForkService.new(project, project.creator).execute }
let(:issue) { create(:issue, project: project) }
let(:issue2) { create(:issue, project: project2) }
let(:reference) { issue.to_reference }
let(:cross_reference) { issue2.to_reference(project) }
+ let(:fork_cross_reference) { issue.to_reference(forked_project) }
subject { described_class.new(project, project.creator) }
@@ -278,6 +280,15 @@ describe Gitlab::ClosingIssueExtractor, lib: true do
end
end
+ context "with a cross-project fork reference" do
+ subject { described_class.new(forked_project, forked_project.creator) }
+
+ it do
+ message = "Closes #{fork_cross_reference}"
+ expect(subject.closed_by_message(message)).to be_empty
+ end
+ end
+
context "with an invalid URL" do
it do
message = "Closes https://google.com#{urls.namespace_project_issue_path(issue2.project.namespace, issue2.project, issue2)}"
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index e883a6eb9c2..0650cb291e5 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -5,7 +5,7 @@ describe Gitlab::Diff::File, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
- let(:diff) { commit.diffs.first }
+ let(:diff) { commit.raw_diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
describe '#diff_lines' do
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index 88e4115c453..1c2ddeed692 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -5,7 +5,7 @@ describe Gitlab::Diff::Highlight, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
- let(:diff) { commit.diffs.first }
+ let(:diff) { commit.raw_diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
describe '#highlight' do
diff --git a/spec/lib/gitlab/diff/line_mapper_spec.rb b/spec/lib/gitlab/diff/line_mapper_spec.rb
index 4e50e03bb7e..4b943fa382d 100644
--- a/spec/lib/gitlab/diff/line_mapper_spec.rb
+++ b/spec/lib/gitlab/diff/line_mapper_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::Diff::LineMapper, lib: true do
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:commit) { project.commit(sample_commit.id) }
- let(:diffs) { commit.diffs }
+ let(:diffs) { commit.raw_diffs }
let(:diff) { diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: repository) }
subject { described_class.new(diff_file) }
diff --git a/spec/lib/gitlab/diff/parallel_diff_spec.rb b/spec/lib/gitlab/diff/parallel_diff_spec.rb
index 2aa5ae44f54..af18d3c25a6 100644
--- a/spec/lib/gitlab/diff/parallel_diff_spec.rb
+++ b/spec/lib/gitlab/diff/parallel_diff_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::Diff::ParallelDiff, lib: true do
let(:project) { create(:project) }
let(:repository) { project.repository }
let(:commit) { project.commit(sample_commit.id) }
- let(:diffs) { commit.diffs }
+ let(:diffs) { commit.raw_diffs }
let(:diff) { diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: repository) }
subject { described_class.new(diff_file) }
diff --git a/spec/lib/gitlab/diff/parser_spec.rb b/spec/lib/gitlab/diff/parser_spec.rb
index c3359627652..b983d73f8be 100644
--- a/spec/lib/gitlab/diff/parser_spec.rb
+++ b/spec/lib/gitlab/diff/parser_spec.rb
@@ -5,7 +5,7 @@ describe Gitlab::Diff::Parser, lib: true do
let(:project) { create(:project) }
let(:commit) { project.commit(sample_commit.id) }
- let(:diff) { commit.diffs.first }
+ let(:diff) { commit.raw_diffs.first }
let(:parser) { Gitlab::Diff::Parser.new }
describe '#parse' do
diff --git a/spec/lib/gitlab/email/email_shared_blocks.rb b/spec/lib/gitlab/email/email_shared_blocks.rb
new file mode 100644
index 00000000000..19298e261e3
--- /dev/null
+++ b/spec/lib/gitlab/email/email_shared_blocks.rb
@@ -0,0 +1,41 @@
+require 'gitlab/email/receiver'
+
+shared_context :email_shared_context do
+ let(:mail_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" }
+ let(:receiver) { Gitlab::Email::Receiver.new(email_raw) }
+ let(:markdown) { "![image](uploads/image.png)" }
+
+ def setup_attachment
+ allow_any_instance_of(Gitlab::Email::AttachmentUploader).to receive(:execute).and_return(
+ [
+ {
+ url: "uploads/image.png",
+ alt: "image",
+ markdown: markdown
+ }
+ ]
+ )
+ end
+end
+
+shared_examples :email_shared_examples do
+ context "when the user could not be found" do
+ before do
+ user.destroy
+ end
+
+ it "raises a UserNotFoundError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)
+ end
+ end
+
+ context "when the user is not authorized to the project" do
+ before do
+ project.update_attribute(:visibility_level, Project::PRIVATE)
+ end
+
+ it "raises a ProjectNotFound" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
new file mode 100644
index 00000000000..e1153154778
--- /dev/null
+++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
@@ -0,0 +1,79 @@
+require 'spec_helper'
+require_relative '../email_shared_blocks'
+
+describe Gitlab::Email::Handler::CreateIssueHandler, lib: true do
+ include_context :email_shared_context
+ it_behaves_like :email_shared_examples
+
+ before do
+ stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo")
+ stub_config_setting(host: 'localhost')
+ end
+
+ let(:email_raw) { fixture_file('emails/valid_new_issue.eml') }
+ let(:namespace) { create(:namespace, path: 'gitlabhq') }
+
+ let!(:project) { create(:project, :public, namespace: namespace) }
+ let!(:user) do
+ create(
+ :user,
+ email: 'jake@adventuretime.ooo',
+ authentication_token: 'auth_token'
+ )
+ end
+
+ context "when everything is fine" do
+ it "creates a new issue" do
+ setup_attachment
+
+ expect { receiver.execute }.to change { project.issues.count }.by(1)
+ issue = project.issues.last
+
+ expect(issue.author).to eq(user)
+ expect(issue.title).to eq('New Issue by email')
+ expect(issue.description).to include('reply by email')
+ expect(issue.description).to include(markdown)
+ end
+
+ context "when the reply is blank" do
+ let(:email_raw) { fixture_file("emails/valid_new_issue_empty.eml") }
+
+ it "creates a new issue" do
+ expect { receiver.execute }.to change { project.issues.count }.by(1)
+ issue = project.issues.last
+
+ expect(issue.author).to eq(user)
+ expect(issue.title).to eq('New Issue by email')
+ expect(issue.description).to eq('')
+ end
+ end
+ end
+
+ context "something is wrong" do
+ context "when the issue could not be saved" do
+ before do
+ allow_any_instance_of(Issue).to receive(:persisted?).and_return(false)
+ end
+
+ it "raises an InvalidIssueError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidIssueError)
+ end
+ end
+
+ context "when we can't find the authentication_token" do
+ let(:email_raw) { fixture_file("emails/wrong_authentication_token.eml") }
+
+ it "raises an UserNotFoundError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError)
+ end
+ end
+
+ context "when project is private" do
+ let(:project) { create(:project, :private, namespace: namespace) }
+
+ it "raises a ProjectNotFound if the user is not a member" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
new file mode 100644
index 00000000000..a2119b0dadf
--- /dev/null
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -0,0 +1,116 @@
+require 'spec_helper'
+require_relative '../email_shared_blocks'
+
+describe Gitlab::Email::Handler::CreateNoteHandler, lib: true do
+ include_context :email_shared_context
+ it_behaves_like :email_shared_examples
+
+ before do
+ stub_incoming_email_setting(enabled: true, address: "reply+%{key}@appmail.adventuretime.ooo")
+ stub_config_setting(host: 'localhost')
+ end
+
+ let(:email_raw) { fixture_file('emails/valid_reply.eml') }
+ let(:project) { create(:project, :public) }
+ let(:noteable) { create(:issue, project: project) }
+ let(:user) { create(:user) }
+
+ let!(:sent_notification) { SentNotification.record(noteable, user.id, mail_key) }
+
+ context "when the recipient address doesn't include a mail key" do
+ let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "") }
+
+ it "raises a UnknownIncomingEmail" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail)
+ end
+ end
+
+ context "when no sent notification for the mail key could be found" do
+ let(:email_raw) { fixture_file('emails/wrong_mail_key.eml') }
+
+ it "raises a SentNotificationNotFoundError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::SentNotificationNotFoundError)
+ end
+ end
+
+ context "when the email was auto generated" do
+ let!(:mail_key) { '636ca428858779856c226bb145ef4fad' }
+ let!(:email_raw) { fixture_file("emails/auto_reply.eml") }
+
+ it "raises an AutoGeneratedEmailError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::AutoGeneratedEmailError)
+ end
+ end
+
+ context "when the noteable could not be found" do
+ before do
+ noteable.destroy
+ end
+
+ it "raises a NoteableNotFoundError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::NoteableNotFoundError)
+ end
+ end
+
+ context "when the note could not be saved" do
+ before do
+ allow_any_instance_of(Note).to receive(:persisted?).and_return(false)
+ end
+
+ it "raises an InvalidNoteError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidNoteError)
+ end
+ end
+
+ context "when the reply is blank" do
+ let!(:email_raw) { fixture_file("emails/no_content_reply.eml") }
+
+ it "raises an EmptyEmailError" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::EmptyEmailError)
+ end
+ end
+
+ context "when everything is fine" do
+ before do
+ setup_attachment
+ end
+
+ it "creates a comment" do
+ expect { receiver.execute }.to change { noteable.notes.count }.by(1)
+ note = noteable.notes.last
+
+ expect(note.author).to eq(sent_notification.recipient)
+ expect(note.note).to include("I could not disagree more.")
+ end
+
+ it "adds all attachments" do
+ receiver.execute
+
+ note = noteable.notes.last
+
+ expect(note.note).to include(markdown)
+ end
+
+ context 'when sub-addressing is not supported' do
+ before do
+ stub_incoming_email_setting(enabled: true, address: nil)
+ end
+
+ shared_examples 'an email that contains a mail key' do |header|
+ it "fetches the mail key from the #{header} header and creates a comment" do
+ expect { receiver.execute }.to change { noteable.notes.count }.by(1)
+ note = noteable.notes.last
+
+ expect(note.author).to eq(sent_notification.recipient)
+ expect(note.note).to include('I could not disagree more.')
+ end
+ end
+
+ context 'mail key is in the References header' do
+ let(:email_raw) { fixture_file('emails/reply_without_subaddressing_and_key_inside_references.eml') }
+
+ it_behaves_like 'an email that contains a mail key', 'References'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/email/message/repository_push_spec.rb b/spec/lib/gitlab/email/message/repository_push_spec.rb
index c19f33e2224..5b966bddb6a 100644
--- a/spec/lib/gitlab/email/message/repository_push_spec.rb
+++ b/spec/lib/gitlab/email/message/repository_push_spec.rb
@@ -16,9 +16,12 @@ describe Gitlab::Email::Message::RepositoryPush do
{ author_id: author.id, ref: 'master', action: :push, compare: compare,
send_from_committer_email: true }
end
- let(:compare) do
+ let(:raw_compare) do
Gitlab::Git::Compare.new(project.repository.raw_repository,
- sample_image_commit.id, sample_commit.id)
+ sample_image_commit.id, sample_commit.id)
+ end
+ let(:compare) do
+ Compare.decorate(raw_compare, project)
end
describe '#project' do
@@ -62,17 +65,17 @@ describe Gitlab::Email::Message::RepositoryPush do
describe '#diffs_count' do
subject { message.diffs_count }
- it { is_expected.to eq compare.diffs.count }
+ it { is_expected.to eq raw_compare.diffs.size }
end
describe '#compare' do
subject { message.compare }
- it { is_expected.to be_an_instance_of Gitlab::Git::Compare }
+ it { is_expected.to be_an_instance_of Compare }
end
describe '#compare_timeout' do
subject { message.compare_timeout }
- it { is_expected.to eq compare.diffs.overflow? }
+ it { is_expected.to eq raw_compare.diffs.overflow? }
end
describe '#reverse_compare?' do
diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb
index 84d2584a791..2a86b427806 100644
--- a/spec/lib/gitlab/email/receiver_spec.rb
+++ b/spec/lib/gitlab/email/receiver_spec.rb
@@ -1,34 +1,14 @@
-require "spec_helper"
+require 'spec_helper'
+require_relative 'email_shared_blocks'
describe Gitlab::Email::Receiver, lib: true do
- before do
- stub_incoming_email_setting(enabled: true, address: "reply+%{key}@appmail.adventuretime.ooo")
- stub_config_setting(host: 'localhost')
- end
-
- let(:reply_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" }
- let(:email_raw) { fixture_file('emails/valid_reply.eml') }
-
- let(:project) { create(:project, :public) }
- let(:noteable) { create(:issue, project: project) }
- let(:user) { create(:user) }
- let!(:sent_notification) { SentNotification.record(noteable, user.id, reply_key) }
-
- let(:receiver) { described_class.new(email_raw) }
-
- context "when the recipient address doesn't include a reply key" do
- let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(reply_key, "") }
-
- it "raises a SentNotificationNotFoundError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::SentNotificationNotFoundError)
- end
- end
+ include_context :email_shared_context
- context "when no sent notificiation for the reply key could be found" do
- let(:email_raw) { fixture_file('emails/wrong_reply_key.eml') }
+ context "when we cannot find a capable handler" do
+ let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "!!!") }
- it "raises a SentNotificationNotFoundError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::SentNotificationNotFoundError)
+ it "raises a UnknownIncomingEmail" do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail)
end
end
@@ -36,128 +16,7 @@ describe Gitlab::Email::Receiver, lib: true do
let(:email_raw) { "" }
it "raises an EmptyEmailError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::EmptyEmailError)
- end
- end
-
- context "when the email was auto generated" do
- let!(:reply_key) { '636ca428858779856c226bb145ef4fad' }
- let!(:email_raw) { fixture_file("emails/auto_reply.eml") }
-
- it "raises an AutoGeneratedEmailError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::AutoGeneratedEmailError)
- end
- end
-
- context "when the user could not be found" do
- before do
- user.destroy
- end
-
- it "raises a UserNotFoundError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::UserNotFoundError)
- end
- end
-
- context "when the user has been blocked" do
- before do
- user.block
- end
-
- it "raises a UserBlockedError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::UserBlockedError)
- end
- end
-
- context "when the user is not authorized to create a note" do
- before do
- project.update_attribute(:visibility_level, Project::PRIVATE)
- end
-
- it "raises a UserNotAuthorizedError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::UserNotAuthorizedError)
- end
- end
-
- context "when the noteable could not be found" do
- before do
- noteable.destroy
- end
-
- it "raises a NoteableNotFoundError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::NoteableNotFoundError)
- end
- end
-
- context "when the reply is blank" do
- let!(:email_raw) { fixture_file("emails/no_content_reply.eml") }
-
- it "raises an EmptyEmailError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::EmptyEmailError)
- end
- end
-
- context "when the note could not be saved" do
- before do
- allow_any_instance_of(Note).to receive(:persisted?).and_return(false)
- end
-
- it "raises an InvalidNoteError" do
- expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::InvalidNoteError)
- end
- end
-
- context "when everything is fine" do
- let(:markdown) { "![image](uploads/image.png)" }
-
- before do
- allow_any_instance_of(Gitlab::Email::AttachmentUploader).to receive(:execute).and_return(
- [
- {
- url: "uploads/image.png",
- alt: "image",
- markdown: markdown
- }
- ]
- )
- end
-
- it "creates a comment" do
- expect { receiver.execute }.to change { noteable.notes.count }.by(1)
- note = noteable.notes.last
-
- expect(note.author).to eq(sent_notification.recipient)
- expect(note.note).to include("I could not disagree more.")
- end
-
- it "adds all attachments" do
- receiver.execute
-
- note = noteable.notes.last
-
- expect(note.note).to include(markdown)
- end
-
- context 'when sub-addressing is not supported' do
- before do
- stub_incoming_email_setting(enabled: true, address: nil)
- end
-
- shared_examples 'an email that contains a reply key' do |header|
- it "fetches the reply key from the #{header} header and creates a comment" do
- expect { receiver.execute }.to change { noteable.notes.count }.by(1)
- note = noteable.notes.last
-
- expect(note.author).to eq(sent_notification.recipient)
- expect(note.note).to include('I could not disagree more.')
- end
- end
-
- context 'reply key is in the References header' do
- let(:email_raw) { fixture_file('emails/reply_without_subaddressing_and_key_inside_references.eml') }
-
- it_behaves_like 'an email that contains a reply key', 'References'
- end
+ expect { receiver.execute }.to raise_error(Gitlab::Email::EmptyEmailError)
end
end
end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index ae064a878b0..8447305a316 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -151,7 +151,13 @@ describe Gitlab::GitAccess, lib: true do
def self.run_permission_checks(permissions_matrix)
permissions_matrix.keys.each do |role|
describe "#{role} access" do
- before { project.team << [user, role] }
+ before do
+ if role == :admin
+ user.update_attribute(:admin, true)
+ else
+ project.team << [user, role]
+ end
+ end
permissions_matrix[role].each do |action, allowed|
context action do
@@ -165,6 +171,17 @@ describe Gitlab::GitAccess, lib: true do
end
permissions_matrix = {
+ admin: {
+ push_new_branch: true,
+ push_master: true,
+ push_protected_branch: true,
+ push_remove_protected_branch: false,
+ push_tag: true,
+ push_new_tag: true,
+ push_all: true,
+ merge_into_protected_branch: true
+ },
+
master: {
push_new_branch: true,
push_master: true,
@@ -217,19 +234,20 @@ describe Gitlab::GitAccess, lib: true do
run_permission_checks(permissions_matrix)
end
- context "when 'developers can push' is turned on for the #{protected_branch_type} protected branch" do
- before { create(:protected_branch, name: protected_branch_name, developers_can_push: true, project: project) }
+ context "when developers are allowed to push into the #{protected_branch_type} protected branch" do
+ before { create(:protected_branch, :developers_can_push, name: protected_branch_name, project: project) }
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: true, push_all: true, merge_into_protected_branch: true }))
end
- context "when 'developers can merge' is turned on for the #{protected_branch_type} protected branch" do
- before { create(:protected_branch, name: protected_branch_name, developers_can_merge: true, project: project) }
+ context "developers are allowed to merge into the #{protected_branch_type} protected branch" do
+ before { create(:protected_branch, :developers_can_merge, name: protected_branch_name, project: project) }
context "when a merge request exists for the given source/target branch" do
context "when the merge request is in progress" do
before do
- create(:merge_request, source_project: project, source_branch: unprotected_branch, target_branch: 'feature', state: 'locked', in_progress_merge_commit_sha: merge_into_protected_branch)
+ create(:merge_request, source_project: project, source_branch: unprotected_branch, target_branch: 'feature',
+ state: 'locked', in_progress_merge_commit_sha: merge_into_protected_branch)
end
run_permission_checks(permissions_matrix.deep_merge(developer: { merge_into_protected_branch: true }))
@@ -242,51 +260,59 @@ describe Gitlab::GitAccess, lib: true do
run_permission_checks(permissions_matrix.deep_merge(developer: { merge_into_protected_branch: false }))
end
- end
- context "when a merge request does not exist for the given source/target branch" do
- run_permission_checks(permissions_matrix.deep_merge(developer: { merge_into_protected_branch: false }))
+ context "when a merge request does not exist for the given source/target branch" do
+ run_permission_checks(permissions_matrix.deep_merge(developer: { merge_into_protected_branch: false }))
+ end
end
end
- context "when 'developers can merge' and 'developers can push' are turned on for the #{protected_branch_type} protected branch" do
- before { create(:protected_branch, name: protected_branch_name, developers_can_merge: true, developers_can_push: true, project: project) }
+ context "when developers are allowed to push and merge into the #{protected_branch_type} protected branch" do
+ before { create(:protected_branch, :developers_can_merge, :developers_can_push, name: protected_branch_name, project: project) }
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: true, push_all: true, merge_into_protected_branch: true }))
end
+
+ context "when no one is allowed to push to the #{protected_branch_name} protected branch" do
+ before { create(:protected_branch, :no_one_can_push, name: protected_branch_name, project: project) }
+
+ run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
+ master: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
+ admin: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false }))
+ end
end
+ end
- describe 'deploy key permissions' do
- let(:key) { create(:deploy_key) }
- let(:actor) { key }
+ describe 'deploy key permissions' do
+ let(:key) { create(:deploy_key) }
+ let(:actor) { key }
- context 'push code' do
- subject { access.check('git-receive-pack') }
+ context 'push code' do
+ subject { access.check('git-receive-pack') }
- context 'when project is authorized' do
- before { key.projects << project }
+ context 'when project is authorized' do
+ before { key.projects << project }
- it { expect(subject).not_to be_allowed }
- end
+ it { expect(subject).not_to be_allowed }
+ end
- context 'when unauthorized' do
- context 'to public project' do
- let(:project) { create(:project, :public) }
+ context 'when unauthorized' do
+ context 'to public project' do
+ let(:project) { create(:project, :public) }
- it { expect(subject).not_to be_allowed }
- end
+ it { expect(subject).not_to be_allowed }
+ end
- context 'to internal project' do
- let(:project) { create(:project, :internal) }
+ context 'to internal project' do
+ let(:project) { create(:project, :internal) }
- it { expect(subject).not_to be_allowed }
- end
+ it { expect(subject).not_to be_allowed }
+ end
- context 'to private project' do
- let(:project) { create(:project, :internal) }
+ context 'to private project' do
+ let(:project) { create(:project, :internal) }
- it { expect(subject).not_to be_allowed }
- end
+ it { expect(subject).not_to be_allowed }
end
end
end
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index 364532e94e3..fc021416d92 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -17,6 +17,18 @@ describe Gitlab::Highlight, lib: true do
expect(lines[21]).to eq(%Q{<span id="LC22" class="line"> <span class="k">unless</span> <span class="no">File</span><span class="p">.</span><span class="nf">directory?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>\n})
expect(lines[26]).to eq(%Q{<span id="LC27" class="line"> <span class="vi">@cmd_status</span> <span class="o">=</span> <span class="mi">0</span></span>\n})
end
+
+ describe 'with CRLF' do
+ let(:branch) { 'crlf-diff' }
+ let(:blob) { repository.blob_at_branch(branch, path) }
+ let(:lines) do
+ Gitlab::Highlight.highlight_lines(project.repository, 'crlf-diff', 'files/whitespace')
+ end
+
+ it 'strips extra LFs' do
+ expect(lines[0]).to eq("<span id=\"LC1\" class=\"line\">test </span>")
+ end
+ end
end
describe 'custom highlighting from .gitattributes' do
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index b1a5d72c624..b5550ca1963 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -18,7 +18,6 @@
"position": 0,
"branch_name": null,
"description": "Aliquam enim illo et possimus.",
- "milestone_id": 18,
"state": "opened",
"iid": 10,
"updated_by_id": null,
@@ -27,6 +26,52 @@
"due_date": null,
"moved_to_id": null,
"test_ee_field": "test",
+ "milestone": {
+ "id": 1,
+ "title": "v0.0",
+ "project_id": 8,
+ "description": "test milestone",
+ "due_date": null,
+ "created_at": "2016-06-14T15:02:04.415Z",
+ "updated_at": "2016-06-14T15:02:04.415Z",
+ "state": "active",
+ "iid": 1,
+ "events": [
+ {
+ "id": 487,
+ "target_type": "Milestone",
+ "target_id": 1,
+ "title": null,
+ "data": null,
+ "project_id": 46,
+ "created_at": "2016-06-14T15:02:04.418Z",
+ "updated_at": "2016-06-14T15:02:04.418Z",
+ "action": 1,
+ "author_id": 18
+ }
+ ]
+ },
+ "label_links": [
+ {
+ "id": 2,
+ "label_id": 2,
+ "target_id": 3,
+ "target_type": "Issue",
+ "created_at": "2016-07-22T08:57:02.840Z",
+ "updated_at": "2016-07-22T08:57:02.840Z",
+ "label": {
+ "id": 2,
+ "title": "test2",
+ "color": "#428bca",
+ "project_id": 8,
+ "created_at": "2016-07-22T08:55:44.161Z",
+ "updated_at": "2016-07-22T08:55:44.161Z",
+ "template": false,
+ "description": "",
+ "priority": null
+ }
+ }
+ ],
"notes": [
{
"id": 351,
@@ -233,7 +278,6 @@
"position": 0,
"branch_name": null,
"description": "Voluptate vel reprehenderit facilis omnis voluptas magnam tenetur.",
- "milestone_id": 16,
"state": "opened",
"iid": 9,
"updated_by_id": null,
@@ -447,7 +491,6 @@
"position": 0,
"branch_name": null,
"description": "Ea recusandae neque autem tempora.",
- "milestone_id": 16,
"state": "closed",
"iid": 8,
"updated_by_id": null,
@@ -661,7 +704,6 @@
"position": 0,
"branch_name": null,
"description": "Maiores architecto quos in dolorem.",
- "milestone_id": 17,
"state": "opened",
"iid": 7,
"updated_by_id": null,
@@ -875,7 +917,6 @@
"position": 0,
"branch_name": null,
"description": "Ut aut ut et tenetur velit aut id modi.",
- "milestone_id": 16,
"state": "opened",
"iid": 6,
"updated_by_id": null,
@@ -1089,7 +1130,6 @@
"position": 0,
"branch_name": null,
"description": "Dicta nisi nihil non ipsa velit.",
- "milestone_id": 20,
"state": "closed",
"iid": 5,
"updated_by_id": null,
@@ -1303,7 +1343,6 @@
"position": 0,
"branch_name": null,
"description": "Ut et explicabo vel voluptatem consequuntur ut sed.",
- "milestone_id": 19,
"state": "closed",
"iid": 4,
"updated_by_id": null,
@@ -1517,7 +1556,6 @@
"position": 0,
"branch_name": null,
"description": "Non asperiores velit accusantium voluptate.",
- "milestone_id": 18,
"state": "closed",
"iid": 3,
"updated_by_id": null,
@@ -1731,7 +1769,6 @@
"position": 0,
"branch_name": null,
"description": "Molestiae corporis magnam et fugit aliquid nulla quia.",
- "milestone_id": 17,
"state": "closed",
"iid": 2,
"updated_by_id": null,
@@ -1945,7 +1982,6 @@
"position": 0,
"branch_name": null,
"description": "Quod ad architecto qui est sed quia.",
- "milestone_id": 20,
"state": "closed",
"iid": 1,
"updated_by_id": null,
@@ -2259,117 +2295,6 @@
"author_id": 25
}
]
- },
- {
- "id": 18,
- "title": "v2.0",
- "project_id": 5,
- "description": "Error dolorem rerum aut nulla.",
- "due_date": null,
- "created_at": "2016-06-14T15:02:04.576Z",
- "updated_at": "2016-06-14T15:02:04.576Z",
- "state": "active",
- "iid": 3,
- "events": [
- {
- "id": 242,
- "target_type": "Milestone",
- "target_id": 18,
- "title": null,
- "data": null,
- "project_id": 36,
- "created_at": "2016-06-14T15:02:04.579Z",
- "updated_at": "2016-06-14T15:02:04.579Z",
- "action": 1,
- "author_id": 1
- },
- {
- "id": 58,
- "target_type": "Milestone",
- "target_id": 18,
- "title": null,
- "data": null,
- "project_id": 5,
- "created_at": "2016-06-14T15:02:04.579Z",
- "updated_at": "2016-06-14T15:02:04.579Z",
- "action": 1,
- "author_id": 22
- }
- ]
- },
- {
- "id": 17,
- "title": "v1.0",
- "project_id": 5,
- "description": "Molestiae perspiciatis voluptates doloremque commodi veniam consequatur.",
- "due_date": null,
- "created_at": "2016-06-14T15:02:04.569Z",
- "updated_at": "2016-06-14T15:02:04.569Z",
- "state": "active",
- "iid": 2,
- "events": [
- {
- "id": 243,
- "target_type": "Milestone",
- "target_id": 17,
- "title": null,
- "data": null,
- "project_id": 36,
- "created_at": "2016-06-14T15:02:04.570Z",
- "updated_at": "2016-06-14T15:02:04.570Z",
- "action": 1,
- "author_id": 1
- },
- {
- "id": 57,
- "target_type": "Milestone",
- "target_id": 17,
- "title": null,
- "data": null,
- "project_id": 5,
- "created_at": "2016-06-14T15:02:04.570Z",
- "updated_at": "2016-06-14T15:02:04.570Z",
- "action": 1,
- "author_id": 20
- }
- ]
- },
- {
- "id": 16,
- "title": "v0.0",
- "project_id": 5,
- "description": "Velit numquam et sed sit.",
- "due_date": null,
- "created_at": "2016-06-14T15:02:04.561Z",
- "updated_at": "2016-06-14T15:02:04.561Z",
- "state": "closed",
- "iid": 1,
- "events": [
- {
- "id": 244,
- "target_type": "Milestone",
- "target_id": 16,
- "title": null,
- "data": null,
- "project_id": 36,
- "created_at": "2016-06-14T15:02:04.563Z",
- "updated_at": "2016-06-14T15:02:04.563Z",
- "action": 1,
- "author_id": 26
- },
- {
- "id": 56,
- "target_type": "Milestone",
- "target_id": 16,
- "title": null,
- "data": null,
- "project_id": 5,
- "created_at": "2016-06-14T15:02:04.563Z",
- "updated_at": "2016-06-14T15:02:04.563Z",
- "action": 1,
- "author_id": 26
- }
- ]
}
],
"snippets": [
@@ -2471,7 +2396,6 @@
"title": "Cannot be automatically merged",
"created_at": "2016-06-14T15:02:36.568Z",
"updated_at": "2016-06-14T15:02:56.815Z",
- "milestone_id": null,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -2909,7 +2833,6 @@
"title": "Can be automatically merged",
"created_at": "2016-06-14T15:02:36.418Z",
"updated_at": "2016-06-14T15:02:57.013Z",
- "milestone_id": null,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -3194,7 +3117,6 @@
"title": "Qui accusantium et inventore facilis doloribus occaecati officiis.",
"created_at": "2016-06-14T15:02:25.168Z",
"updated_at": "2016-06-14T15:02:59.521Z",
- "milestone_id": 17,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -3479,7 +3401,6 @@
"title": "In voluptas aut sequi voluptatem ullam vel corporis illum consequatur.",
"created_at": "2016-06-14T15:02:24.760Z",
"updated_at": "2016-06-14T15:02:59.749Z",
- "milestone_id": 20,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -4170,7 +4091,6 @@
"title": "Voluptates consequatur eius nemo amet libero animi illum delectus tempore.",
"created_at": "2016-06-14T15:02:24.415Z",
"updated_at": "2016-06-14T15:02:59.958Z",
- "milestone_id": 17,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -4719,7 +4639,6 @@
"title": "In a rerum harum nihil accusamus aut quia nobis non.",
"created_at": "2016-06-14T15:02:24.000Z",
"updated_at": "2016-06-14T15:03:00.225Z",
- "milestone_id": 19,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -5219,7 +5138,6 @@
"title": "Corporis provident similique perspiciatis dolores eos animi.",
"created_at": "2016-06-14T15:02:23.767Z",
"updated_at": "2016-06-14T15:03:00.475Z",
- "milestone_id": 18,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -5480,7 +5398,6 @@
"title": "Eligendi reprehenderit doloribus quia et sit id.",
"created_at": "2016-06-14T15:02:23.014Z",
"updated_at": "2016-06-14T15:03:00.685Z",
- "milestone_id": 20,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
@@ -6171,7 +6088,6 @@
"title": "Et ipsam voluptas velit sequi illum ut.",
"created_at": "2016-06-14T15:02:22.825Z",
"updated_at": "2016-06-14T15:03:00.904Z",
- "milestone_id": 16,
"state": "opened",
"merge_status": "unchecked",
"target_project_id": 5,
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 6ae20c943b1..32c0d6462f1 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -60,6 +60,18 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do
expect { restored_project_json }.to change(MergeRequestDiff.where.not(st_diffs: nil), :count).by(9)
end
+
+ it 'has labels associated to label links, associated to issues' do
+ restored_project_json
+
+ expect(Label.first.label_links.first.target).not_to be_nil
+ end
+
+ it 'has milestones associated to issues' do
+ restored_project_json
+
+ expect(Milestone.find_by_description('test milestone').issues).not_to be_empty
+ 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 057ef6e76a0..3a86a4ce07c 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -31,10 +31,6 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
expect(saved_project_json).to include({ "visibility_level" => 20 })
end
- it 'has events' do
- expect(saved_project_json['milestones'].first['events']).not_to be_empty
- end
-
it 'has milestones' do
expect(saved_project_json['milestones']).not_to be_empty
end
@@ -43,8 +39,12 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
expect(saved_project_json['merge_requests']).not_to be_empty
end
- it 'has labels' do
- expect(saved_project_json['labels']).not_to be_empty
+ it 'has merge request\'s milestones' do
+ expect(saved_project_json['merge_requests'].first['milestone']).not_to be_empty
+ end
+
+ it 'has events' do
+ expect(saved_project_json['merge_requests'].first['milestone']['events']).not_to be_empty
end
it 'has snippets' do
@@ -103,6 +103,14 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
expect(saved_project_json['pipelines'].first['notes']).not_to be_empty
end
+ it 'has labels with no associations' do
+ expect(saved_project_json['labels']).not_to be_empty
+ end
+
+ it 'has labels associated to records' do
+ expect(saved_project_json['issues'].first['label_links'].first['label']).not_to be_empty
+ end
+
it 'does not complain about non UTF-8 characters in MR diffs' do
ActiveRecord::Base.connection.execute("UPDATE merge_request_diffs SET st_diffs = '---\n- :diff: !binary |-\n LS0tIC9kZXYvbnVsbAorKysgYi9pbWFnZXMvbnVjb3IucGRmCkBAIC0wLDAg\n KzEsMTY3OSBAQAorJVBERi0xLjUNJeLjz9MNCisxIDAgb2JqDTw8L01ldGFk\n YXR'")
@@ -113,19 +121,19 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
def setup_project
issue = create(:issue, assignee: user)
- label = create(:label)
snippet = create(:project_snippet)
release = create(:release)
project = create(:project,
:public,
issues: [issue],
- labels: [label],
snippets: [snippet],
releases: [release]
)
-
- merge_request = create(:merge_request, source_project: project)
+ label = create(:label, project: project)
+ create(:label_link, label: label, target: issue)
+ milestone = create(:milestone, project: project)
+ merge_request = create(:merge_request, source_project: project, milestone: milestone)
commit_status = create(:commit_status, project: project)
ci_pipeline = create(:ci_pipeline,
@@ -135,7 +143,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do
statuses: [commit_status])
create(:ci_build, pipeline: ci_pipeline, project: project)
- milestone = create(:milestone, project: project)
+ create(:milestone, project: project)
create(:note, noteable: issue, project: project)
create(:note, noteable: merge_request, project: project)
create(:note, noteable: snippet, project: project)
diff --git a/spec/lib/gitlab/import_export/version_checker_spec.rb b/spec/lib/gitlab/import_export/version_checker_spec.rb
new file mode 100644
index 00000000000..90c6d1c67f6
--- /dev/null
+++ b/spec/lib/gitlab/import_export/version_checker_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe Gitlab::ImportExport::VersionChecker, services: true do
+ describe 'bundle a project Git repo' do
+ let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: '') }
+ let(:version) { Gitlab::ImportExport.version }
+
+ before do
+ allow(File).to receive(:open).and_return(version)
+ end
+
+ it 'returns true if Import/Export have the same version' do
+ expect(described_class.check!(shared: shared)).to be true
+ end
+
+ context 'newer version' do
+ let(:version) { '900.0'}
+
+ it 'returns false if export version is newer' do
+ expect(described_class.check!(shared: shared)).to be false
+ end
+
+ it 'shows the correct error message' do
+ described_class.check!(shared: shared)
+
+ expect(shared.errors.first).to eq("Import version mismatch: Required <= #{Gitlab::ImportExport.version} but was #{version}")
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/incoming_email_spec.rb b/spec/lib/gitlab/incoming_email_spec.rb
index afb3e26f8fb..1dcf2c0668b 100644
--- a/spec/lib/gitlab/incoming_email_spec.rb
+++ b/spec/lib/gitlab/incoming_email_spec.rb
@@ -43,9 +43,9 @@ describe Gitlab::IncomingEmail, lib: true do
end
end
- context 'self.key_from_fallback_reply_message_id' do
+ context 'self.key_from_fallback_message_id' do
it 'returns reply key' do
- expect(described_class.key_from_fallback_reply_message_id('reply-key@localhost')).to eq('key')
+ expect(described_class.key_from_fallback_message_id('reply-key@localhost')).to eq('key')
end
end
end
diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb
index 8809b7e3f12..d88bcae41fb 100644
--- a/spec/lib/gitlab/metrics/instrumentation_spec.rb
+++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb
@@ -39,6 +39,12 @@ describe Gitlab::Metrics::Instrumentation do
allow(@dummy).to receive(:name).and_return('Dummy')
end
+ describe '.series' do
+ it 'returns a String' do
+ expect(described_class.series).to be_an_instance_of(String)
+ end
+ end
+
describe '.configure' do
it 'yields self' do
described_class.configure do |c|
@@ -78,8 +84,7 @@ describe Gitlab::Metrics::Instrumentation do
allow(described_class).to receive(:transaction).
and_return(transaction)
- expect(transaction).to receive(:measure_method).
- with('Dummy.foo')
+ expect_any_instance_of(Gitlab::Metrics::MethodCall).to receive(:measure)
@dummy.foo
end
@@ -157,8 +162,7 @@ describe Gitlab::Metrics::Instrumentation do
allow(described_class).to receive(:transaction).
and_return(transaction)
- expect(transaction).to receive(:measure_method).
- with('Dummy#bar')
+ expect_any_instance_of(Gitlab::Metrics::MethodCall).to receive(:measure)
@dummy.new.bar
end
diff --git a/spec/lib/gitlab/metrics/system_spec.rb b/spec/lib/gitlab/metrics/system_spec.rb
index cf0e282c2fb..9e2ea89a712 100644
--- a/spec/lib/gitlab/metrics/system_spec.rb
+++ b/spec/lib/gitlab/metrics/system_spec.rb
@@ -28,20 +28,20 @@ describe Gitlab::Metrics::System do
end
describe '.cpu_time' do
- it 'returns a Float' do
- expect(described_class.cpu_time).to be_an_instance_of(Float)
+ it 'returns a Fixnum' do
+ expect(described_class.cpu_time).to be_an_instance_of(Fixnum)
end
end
describe '.real_time' do
- it 'returns a Float' do
- expect(described_class.real_time).to be_an_instance_of(Float)
+ it 'returns a Fixnum' do
+ expect(described_class.real_time).to be_an_instance_of(Fixnum)
end
end
describe '.monotonic_time' do
- it 'returns a Float' do
- expect(described_class.monotonic_time).to be_an_instance_of(Float)
+ it 'returns a Fixnum' do
+ expect(described_class.monotonic_time).to be_an_instance_of(Fixnum)
end
end
end
diff --git a/spec/lib/gitlab/metrics/transaction_spec.rb b/spec/lib/gitlab/metrics/transaction_spec.rb
index 3b1c67a2147..f1a191d9410 100644
--- a/spec/lib/gitlab/metrics/transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/transaction_spec.rb
@@ -46,19 +46,11 @@ describe Gitlab::Metrics::Transaction do
end
end
- describe '#measure_method' do
- it 'adds a new method if it does not exist already' do
- transaction.measure_method('Foo#bar') { 'foo' }
+ describe '#method_call_for' do
+ it 'returns a MethodCall' do
+ method = transaction.method_call_for('Foo#bar')
- expect(transaction.methods['Foo#bar']).
- to be_an_instance_of(Gitlab::Metrics::MethodCall)
- end
-
- it 'adds timings to an existing method call' do
- transaction.measure_method('Foo#bar') { 'foo' }
- transaction.measure_method('Foo#bar') { 'foo' }
-
- expect(transaction.methods['Foo#bar'].call_count).to eq(2)
+ expect(method).to be_an_instance_of(Gitlab::Metrics::MethodCall)
end
end
diff --git a/spec/lib/gitlab/metrics_spec.rb b/spec/lib/gitlab/metrics_spec.rb
index 96f7eabbca6..84f9475a0f8 100644
--- a/spec/lib/gitlab/metrics_spec.rb
+++ b/spec/lib/gitlab/metrics_spec.rb
@@ -147,4 +147,10 @@ describe Gitlab::Metrics do
end
end
end
+
+ describe '#series_prefix' do
+ it 'returns a String' do
+ expect(described_class.series_prefix).to be_an_instance_of(String)
+ end
+ end
end
diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb
index aa9ec243498..5bb095366fa 100644
--- a/spec/lib/gitlab/user_access_spec.rb
+++ b/spec/lib/gitlab/user_access_spec.rb
@@ -44,7 +44,7 @@ describe Gitlab::UserAccess, lib: true do
describe 'push to protected branch if allowed for developers' do
before do
- @branch = create :protected_branch, project: project, developers_can_push: true
+ @branch = create :protected_branch, :developers_can_push, project: project
end
it 'returns true if user is a master' do
@@ -65,7 +65,7 @@ describe Gitlab::UserAccess, lib: true do
describe 'merge to protected branch if allowed for developers' do
before do
- @branch = create :protected_branch, project: project, developers_can_merge: true
+ @branch = create :protected_branch, :developers_can_merge, project: project
end
it 'returns true if user is a master' do