summaryrefslogtreecommitdiff
path: root/spec/models
diff options
context:
space:
mode:
authorKushal Pandya <kushalspandya@gmail.com>2017-04-06 09:46:50 +0000
committerKushal Pandya <kushalspandya@gmail.com>2017-04-06 09:46:50 +0000
commit18506d4b8b8bc780b3b1e4c61339af38b5c49bb2 (patch)
tree6aab0c83abe14064433c326996ccbe8097495454 /spec/models
parentcd5b36d04e79ed8fcd649127e0d47e09ec325242 (diff)
parent49bdd8d63b577f079cdc47f7dd10ba83c677771a (diff)
downloadgitlab-ce-18506d4b8b8bc780b3b1e4c61339af38b5c49bb2.tar.gz
Merge branch 'master' into '18471-restrict-tag-pushes-protected-tags'
# Conflicts: # app/assets/javascripts/dispatcher.js # app/assets/stylesheets/pages/projects.scss
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/blob_spec.rb61
-rw-r--r--spec/models/ci/pipeline_spec.rb7
-rw-r--r--spec/models/commit_status_spec.rb36
-rw-r--r--spec/models/concerns/has_status_spec.rb18
-rw-r--r--spec/models/concerns/issuable_spec.rb28
-rw-r--r--spec/models/cycle_analytics/plan_spec.rb4
-rw-r--r--spec/models/cycle_analytics/production_spec.rb2
-rw-r--r--spec/models/cycle_analytics/staging_spec.rb2
-rw-r--r--spec/models/hooks/system_hook_spec.rb5
-rw-r--r--spec/models/issue_spec.rb45
-rw-r--r--spec/models/list_spec.rb22
-rw-r--r--spec/models/milestone_spec.rb2
-rw-r--r--spec/models/namespace_spec.rb108
-rw-r--r--spec/models/pages_domain_spec.rb14
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb89
-rw-r--r--spec/models/project_spec.rb15
-rw-r--r--spec/models/project_wiki_spec.rb21
-rw-r--r--spec/models/repository_spec.rb40
-rw-r--r--spec/models/route_spec.rb20
-rw-r--r--spec/models/snippet_spec.rb43
-rw-r--r--spec/models/system_note_metadata_spec.rb27
-rw-r--r--spec/models/user_spec.rb13
22 files changed, 492 insertions, 130 deletions
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index 94c25a454aa..09b1fda3796 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -53,6 +53,48 @@ describe Blob do
end
end
+ describe '#pdf?' do
+ it 'is falsey when file extension is not .pdf' do
+ git_blob = double(name: 'git_blob.txt')
+
+ expect(described_class.decorate(git_blob)).not_to be_pdf
+ end
+
+ it 'is truthy when file extension is .pdf' do
+ git_blob = double(name: 'git_blob.pdf')
+
+ expect(described_class.decorate(git_blob)).to be_pdf
+ end
+ end
+
+ describe '#ipython_notebook?' do
+ it 'is falsey when language is not Jupyter Notebook' do
+ git_blob = double(text?: true, language: double(name: 'JSON'))
+
+ expect(described_class.decorate(git_blob)).not_to be_ipython_notebook
+ end
+
+ it 'is truthy when language is Jupyter Notebook' do
+ git_blob = double(text?: true, language: double(name: 'Jupyter Notebook'))
+
+ expect(described_class.decorate(git_blob)).to be_ipython_notebook
+ end
+ end
+
+ describe '#sketch?' do
+ it 'is falsey with image extension' do
+ git_blob = Gitlab::Git::Blob.new(name: "design.png")
+
+ expect(described_class.decorate(git_blob)).not_to be_sketch
+ end
+
+ it 'is truthy with sketch extension' do
+ git_blob = Gitlab::Git::Blob.new(name: "design.sketch")
+
+ expect(described_class.decorate(git_blob)).to be_sketch
+ end
+ end
+
describe '#video?' do
it 'is falsey with image extension' do
git_blob = Gitlab::Git::Blob.new(name: 'image.png')
@@ -74,11 +116,13 @@ describe Blob do
def stubbed_blob(overrides = {})
overrides.reverse_merge!(
+ name: nil,
image?: false,
language: nil,
lfs_pointer?: false,
svg?: false,
- text?: false
+ text?: false,
+ binary?: false
)
described_class.decorate(double).tap do |blob|
@@ -116,6 +160,21 @@ describe Blob do
blob = stubbed_blob
expect(blob.to_partial_path(project)).to eq 'download'
end
+
+ it 'handles PDFs' do
+ blob = stubbed_blob(name: 'blob.pdf', pdf?: true)
+ expect(blob.to_partial_path(project)).to eq 'pdf'
+ end
+
+ it 'handles iPython notebooks' do
+ blob = stubbed_blob(text?: true, ipython_notebook?: true)
+ expect(blob.to_partial_path(project)).to eq 'notebook'
+ end
+
+ it 'handles Sketch files' do
+ blob = stubbed_blob(text?: true, sketch?: true, binary?: true)
+ expect(blob.to_partial_path(project)).to eq 'sketch'
+ end
end
describe '#size_within_svg_limits?' do
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 53282b999dc..e4a24fd63c2 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1055,10 +1055,13 @@ describe Ci::Pipeline, models: true do
end
before do
- reset_delivered_emails!
-
project.team << [pipeline.user, Gitlab::Access::DEVELOPER]
+ pipeline.user.global_notification_setting.
+ update(level: 'custom', failed_pipeline: true, success_pipeline: true)
+
+ reset_delivered_emails!
+
perform_enqueued_jobs do
pipeline.enqueue
pipeline.run
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index ea5e4e21039..7343b735a74 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -297,4 +297,40 @@ describe CommitStatus, :models do
end
end
end
+
+ describe '#locking_enabled?' do
+ before do
+ commit_status.lock_version = 100
+ end
+
+ subject { commit_status.locking_enabled? }
+
+ context "when changing status" do
+ before do
+ commit_status.status = "running"
+ end
+
+ it "lock" do
+ is_expected.to be true
+ end
+
+ it "raise exception when trying to update" do
+ expect{ commit_status.save }.to raise_error(ActiveRecord::StaleObjectError)
+ end
+ end
+
+ context "when changing description" do
+ before do
+ commit_status.description = "test"
+ end
+
+ it "do not lock" do
+ is_expected.to be false
+ end
+
+ it "save correctly" do
+ expect(commit_status.save).to be true
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb
index f134da441c2..82abad0e2f6 100644
--- a/spec/models/concerns/has_status_spec.rb
+++ b/spec/models/concerns/has_status_spec.rb
@@ -110,6 +110,24 @@ describe HasStatus do
it { is_expected.to eq 'running' }
end
+ context 'when one status finished and second is still created' do
+ let!(:statuses) do
+ [create(type, status: :success), create(type, status: :created)]
+ end
+
+ it { is_expected.to eq 'running' }
+ end
+
+ context 'when there is a manual status before created status' do
+ let!(:statuses) do
+ [create(type, status: :success),
+ create(type, status: :manual, allow_failure: false),
+ create(type, status: :created)]
+ end
+
+ it { is_expected.to eq 'manual' }
+ end
+
context 'when one status is a blocking manual action' do
let!(:statuses) do
[create(type, status: :failed),
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 9574796a945..4522206fab1 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -44,6 +44,34 @@ describe Issue, "Issuable" do
it { expect(described_class).to respond_to(:assigned) }
end
+ describe 'author_name' do
+ it 'is delegated to author' do
+ expect(issue.author_name).to eq issue.author.name
+ end
+
+ it 'returns nil when author is nil' do
+ issue.author_id = nil
+ issue.save(validate: false)
+
+ expect(issue.author_name).to eq nil
+ end
+ end
+
+ describe 'assignee_name' do
+ it 'is delegated to assignee' do
+ issue.update!(assignee: create(:user))
+
+ expect(issue.assignee_name).to eq issue.assignee.name
+ end
+
+ it 'returns nil when assignee is nil' do
+ issue.assignee_id = nil
+ issue.save(validate: false)
+
+ expect(issue.assignee_name).to eq nil
+ end
+ end
+
describe "before_save" do
describe "#update_cache_counts" do
context "when previous assignee exists" do
diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb
index 55483fc876a..4f33f3c6d69 100644
--- a/spec/models/cycle_analytics/plan_spec.rb
+++ b/spec/models/cycle_analytics/plan_spec.rb
@@ -13,7 +13,7 @@ describe 'CycleAnalytics#plan', feature: true do
data_fn: -> (context) do
{
issue: context.create(:issue, project: context.project),
- branch_name: context.random_git_name
+ branch_name: context.generate(:branch)
}
end,
start_time_conditions: [["issue associated with a milestone",
@@ -35,7 +35,7 @@ describe 'CycleAnalytics#plan', feature: true do
context "when a regular label (instead of a list label) is added to the issue" do
it "returns nil" do
- branch_name = random_git_name
+ branch_name = generate(:branch)
label = create(:label)
issue = create(:issue, project: project)
issue.update(label_ids: [label.id])
diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb
index e6a826a9418..4744b9e05ea 100644
--- a/spec/models/cycle_analytics/production_spec.rb
+++ b/spec/models/cycle_analytics/production_spec.rb
@@ -23,7 +23,7 @@ describe 'CycleAnalytics#production', feature: true do
# Make other changes on master
sha = context.project.repository.create_file(
context.user,
- context.random_git_name,
+ context.generate(:branch),
'content',
message: 'commit message',
branch_name: 'master')
diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb
index 3a02ed81adb..f78d7a23105 100644
--- a/spec/models/cycle_analytics/staging_spec.rb
+++ b/spec/models/cycle_analytics/staging_spec.rb
@@ -28,7 +28,7 @@ describe 'CycleAnalytics#staging', feature: true do
# Make other changes on master
sha = context.project.repository.create_file(
context.user,
- context.random_git_name,
+ context.generate(:branch),
'content',
message: 'commit message',
branch_name: 'master')
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index e8caad00c44..8acec805584 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -6,6 +6,9 @@ describe SystemHook, models: true do
let(:user) { create(:user) }
let(:project) { create(:empty_project, namespace: user.namespace) }
let(:group) { create(:group) }
+ let(:params) do
+ { name: 'John Doe', username: 'jduser', email: 'jg@example.com', password: 'mydummypass' }
+ end
before do
WebMock.stub_request(:post, system_hook.url)
@@ -29,7 +32,7 @@ describe SystemHook, models: true do
end
it "user_create hook" do
- create(:user)
+ Users::CreateService.new(nil, params).execute
expect(WebMock).to have_requested(:post, system_hook.url).with(
body: /user_create/,
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 73977d031f9..4bdd46a581d 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -51,14 +51,6 @@ describe Issue, models: true do
expect(issue.closed_at).to eq(now)
end
-
- it 'sets closed_at to nil when issue is reopened' do
- issue = create(:issue, state: 'closed')
-
- issue.reopen
-
- expect(issue.closed_at).to be_nil
- end
end
describe '#to_reference' do
@@ -670,4 +662,41 @@ describe Issue, models: true do
expect(attrs_hash).to include('time_estimate')
end
end
+
+ describe '#check_for_spam' do
+ let(:project) { create :project, visibility_level: visibility_level }
+ let(:issue) { create :issue, project: project }
+
+ subject do
+ issue.assign_attributes(description: description)
+ issue.check_for_spam?
+ end
+
+ context 'when project is public and spammable attributes changed' do
+ let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:description) { 'woo' }
+
+ it 'returns true' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when project is private' do
+ let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
+ let(:description) { issue.description }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'when spammable attributes have not changed' do
+ let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:description) { issue.description }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
index e6ca4853873..db2c2619968 100644
--- a/spec/models/list_spec.rb
+++ b/spec/models/list_spec.rb
@@ -19,8 +19,8 @@ describe List do
expect(subject).to validate_uniqueness_of(:label_id).scoped_to(:board_id)
end
- context 'when list_type is set to done' do
- subject { described_class.new(list_type: :done) }
+ context 'when list_type is set to closed' do
+ subject { described_class.new(list_type: :closed) }
it { is_expected.not_to validate_presence_of(:label) }
it { is_expected.not_to validate_presence_of(:position) }
@@ -34,8 +34,8 @@ describe List do
expect(subject.destroy).to be_truthy
end
- it 'can not be destroyed when when list_type is set to done' do
- subject = create(:done_list)
+ it 'can not be destroyed when when list_type is set to closed' do
+ subject = create(:closed_list)
expect(subject.destroy).to be_falsey
end
@@ -48,8 +48,8 @@ describe List do
expect(subject).to be_destroyable
end
- it 'returns false when list_type is set to done' do
- subject.list_type = :done
+ it 'returns false when list_type is set to closed' do
+ subject.list_type = :closed
expect(subject).not_to be_destroyable
end
@@ -62,8 +62,8 @@ describe List do
expect(subject).to be_movable
end
- it 'returns false when list_type is set to done' do
- subject.list_type = :done
+ it 'returns false when list_type is set to closed' do
+ subject.list_type = :closed
expect(subject).not_to be_movable
end
@@ -77,10 +77,10 @@ describe List do
expect(subject.title).to eq 'Development'
end
- it 'returns Done when list_type is set to done' do
- subject.list_type = :done
+ it 'returns Closed when list_type is set to closed' do
+ subject.list_type = :closed
- expect(subject.title).to eq 'Done'
+ expect(subject.title).to eq 'Closed'
end
end
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 3cee2b7714f..f3f48f951a8 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -109,7 +109,7 @@ describe Milestone, models: true do
it { expect(milestone.percent_complete(user)).to eq(75) }
end
- describe :items_count do
+ describe '#is_empty?' do
before do
milestone.issues << create(:issue, project: project)
milestone.issues << create(:closed_issue, project: project)
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 757f3921450..d9216112259 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -129,10 +129,10 @@ describe Namespace, models: true do
end
end
- describe '#move_dir' do
+ describe '#move_dir', repository: true do
before do
@namespace = create :namespace
- @project = create(:empty_project, namespace: @namespace)
+ @project = create(:project_empty_repo, namespace: @namespace)
allow(@namespace).to receive(:path_changed?).and_return(true)
end
@@ -141,9 +141,9 @@ describe Namespace, models: true do
end
it "moves dir if path changed" do
- new_path = @namespace.path + "_new"
- allow(@namespace).to receive(:path_was).and_return(@namespace.path)
- allow(@namespace).to receive(:path).and_return(new_path)
+ new_path = @namespace.full_path + "_new"
+ allow(@namespace).to receive(:full_path_was).and_return(@namespace.full_path)
+ allow(@namespace).to receive(:full_path).and_return(new_path)
expect(@namespace).to receive(:remove_exports!)
expect(@namespace.move_dir).to be_truthy
end
@@ -161,16 +161,91 @@ describe Namespace, models: true do
it { expect { @namespace.move_dir }.to raise_error('Namespace cannot be moved, because at least one project has tags in container registry') }
end
+
+ context 'with subgroups' do
+ let(:parent) { create(:group, name: 'parent', path: 'parent') }
+ let(:child) { create(:group, name: 'child', path: 'child', parent: parent) }
+ let!(:project) { create(:project_empty_repo, path: 'the-project', namespace: child) }
+ let(:uploads_dir) { File.join(CarrierWave.root, 'uploads') }
+ let(:pages_dir) { TestEnv.pages_path }
+
+ before do
+ FileUtils.mkdir_p(File.join(uploads_dir, 'parent', 'child', 'the-project'))
+ FileUtils.mkdir_p(File.join(pages_dir, 'parent', 'child', 'the-project'))
+ end
+
+ context 'renaming child' do
+ it 'correctly moves the repository, uploads and pages' do
+ expected_repository_path = File.join(TestEnv.repos_path, 'parent', 'renamed', 'the-project.git')
+ expected_upload_path = File.join(uploads_dir, 'parent', 'renamed', 'the-project')
+ expected_pages_path = File.join(pages_dir, 'parent', 'renamed', 'the-project')
+
+ child.update_attributes!(path: 'renamed')
+
+ expect(File.directory?(expected_repository_path)).to be(true)
+ expect(File.directory?(expected_upload_path)).to be(true)
+ expect(File.directory?(expected_pages_path)).to be(true)
+ end
+ end
+
+ context 'renaming parent' do
+ it 'correctly moves the repository, uploads and pages' do
+ expected_repository_path = File.join(TestEnv.repos_path, 'renamed', 'child', 'the-project.git')
+ expected_upload_path = File.join(uploads_dir, 'renamed', 'child', 'the-project')
+ expected_pages_path = File.join(pages_dir, 'renamed', 'child', 'the-project')
+
+ parent.update_attributes!(path: 'renamed')
+
+ expect(File.directory?(expected_repository_path)).to be(true)
+ expect(File.directory?(expected_upload_path)).to be(true)
+ expect(File.directory?(expected_pages_path)).to be(true)
+ end
+ end
+ end
end
- describe :rm_dir do
- let!(:project) { create(:empty_project, namespace: namespace) }
- let!(:path) { File.join(Gitlab.config.repositories.storages.default['path'], namespace.full_path) }
+ describe '#rm_dir', 'callback', repository: true do
+ let!(:project) { create(:project_empty_repo, namespace: namespace) }
+ let(:repository_storage_path) { Gitlab.config.repositories.storages.default['path'] }
+ let(:path_in_dir) { File.join(repository_storage_path, namespace.full_path) }
+ let(:deleted_path) { namespace.full_path.gsub(namespace.path, "#{namespace.full_path}+#{namespace.id}+deleted") }
+ let(:deleted_path_in_dir) { File.join(repository_storage_path, deleted_path) }
+
+ it 'renames its dirs when deleted' do
+ allow(GitlabShellWorker).to receive(:perform_in)
- it "removes its dirs when deleted" do
namespace.destroy
- expect(File.exist?(path)).to be(false)
+ expect(File.exist?(deleted_path_in_dir)).to be(true)
+ end
+
+ it 'schedules the namespace for deletion' do
+ expect(GitlabShellWorker).to receive(:perform_in).with(5.minutes, :rm_namespace, repository_storage_path, deleted_path)
+
+ namespace.destroy
+ end
+
+ context 'in sub-groups' do
+ let(:parent) { create(:namespace, path: 'parent') }
+ let(:child) { create(:namespace, parent: parent, path: 'child') }
+ let!(:project) { create(:project_empty_repo, namespace: child) }
+ let(:path_in_dir) { File.join(repository_storage_path, 'parent', 'child') }
+ let(:deleted_path) { File.join('parent', "child+#{child.id}+deleted") }
+ let(:deleted_path_in_dir) { File.join(repository_storage_path, deleted_path) }
+
+ it 'renames its dirs when deleted' do
+ allow(GitlabShellWorker).to receive(:perform_in)
+
+ child.destroy
+
+ expect(File.exist?(deleted_path_in_dir)).to be(true)
+ end
+
+ it 'schedules the namespace for deletion' do
+ expect(GitlabShellWorker).to receive(:perform_in).with(5.minutes, :rm_namespace, repository_storage_path, deleted_path)
+
+ child.destroy
+ end
end
it 'removes the exports folder' do
@@ -215,10 +290,12 @@ describe Namespace, models: true do
end
describe '#descendants' do
- let!(:group) { create(:group) }
+ let!(:group) { create(:group, path: 'git_lab') }
let!(:nested_group) { create(:group, parent: group) }
let!(:deep_nested_group) { create(:group, parent: nested_group) }
let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let!(:another_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
it 'returns the correct descendants' do
expect(very_deep_nested_group.descendants.to_a).to eq([])
@@ -234,4 +311,13 @@ describe Namespace, models: true do
to eq([namespace.owner_id])
end
end
+
+ describe '#all_projects' do
+ let(:group) { create(:group) }
+ let(:child) { create(:group, parent: group) }
+ let!(:project1) { create(:project_empty_repo, namespace: group) }
+ let!(:project2) { create(:project_empty_repo, namespace: child) }
+
+ it { expect(group.all_projects.to_a).to eq([project2, project1]) }
+ end
end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index e6a4583a8fb..c6c45d78990 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -5,7 +5,7 @@ describe PagesDomain, models: true do
it { is_expected.to belong_to(:project) }
end
- describe :validate_domain do
+ describe 'validate domain' do
subject { build(:pages_domain, domain: domain) }
context 'is unique' do
@@ -75,7 +75,7 @@ describe PagesDomain, models: true do
end
end
- describe :url do
+ describe '#url' do
subject { domain.url }
context 'without the certificate' do
@@ -91,7 +91,7 @@ describe PagesDomain, models: true do
end
end
- describe :has_matching_key? do
+ describe '#has_matching_key?' do
subject { domain.has_matching_key? }
context 'for matching key' do
@@ -107,7 +107,7 @@ describe PagesDomain, models: true do
end
end
- describe :has_intermediates? do
+ describe '#has_intermediates?' do
subject { domain.has_intermediates? }
context 'for self signed' do
@@ -133,7 +133,7 @@ describe PagesDomain, models: true do
end
end
- describe :expired? do
+ describe '#expired?' do
subject { domain.expired? }
context 'for valid' do
@@ -149,7 +149,7 @@ describe PagesDomain, models: true do
end
end
- describe :subject do
+ describe '#subject' do
let(:domain) { build(:pages_domain, :with_certificate) }
subject { domain.subject }
@@ -157,7 +157,7 @@ describe PagesDomain, models: true do
it { is_expected.to eq('/CN=test-certificate') }
end
- describe :certificate_text do
+ describe '#certificate_text' do
let(:domain) { build(:pages_domain, :with_certificate) }
subject { domain.certificate_text }
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index bf7950ef1c9..e69eb0098dd 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -4,7 +4,7 @@ describe KubernetesService, models: true, caching: true do
include KubernetesHelpers
include ReactiveCachingHelpers
- let(:project) { create(:kubernetes_project) }
+ let(:project) { build_stubbed(:kubernetes_project) }
let(:service) { project.kubernetes_service }
# We use Kubeclient to interactive with the Kubernetes API. It will
@@ -32,7 +32,8 @@ describe KubernetesService, models: true, caching: true do
describe 'Validations' do
context 'when service is active' do
before { subject.active = true }
- it { is_expected.to validate_presence_of(:namespace) }
+
+ it { is_expected.not_to validate_presence_of(:namespace) }
it { is_expected.to validate_presence_of(:api_url) }
it { is_expected.to validate_presence_of(:token) }
@@ -55,7 +56,7 @@ describe KubernetesService, models: true, caching: true do
'a.b' => false,
'a*b' => false,
}.each do |namespace, validity|
- it "should validate #{namespace} as #{validity ? 'valid' : 'invalid'}" do
+ it "validates #{namespace} as #{validity ? 'valid' : 'invalid'}" do
subject.namespace = namespace
expect(subject.valid?).to eq(validity)
@@ -66,24 +67,40 @@ describe KubernetesService, models: true, caching: true do
context 'when service is inactive' do
before { subject.active = false }
- it { is_expected.not_to validate_presence_of(:namespace) }
+
it { is_expected.not_to validate_presence_of(:api_url) }
it { is_expected.not_to validate_presence_of(:token) }
end
end
describe '#initialize_properties' do
- context 'with a project' do
- let(:namespace_name) { "#{project.path}-#{project.id}" }
+ context 'without a project' do
+ it 'leaves the namespace unset' do
+ expect(described_class.new.namespace).to be_nil
+ end
+ end
+ end
+
+ describe '#fields' do
+ let(:kube_namespace) do
+ subject.fields.find { |h| h[:name] == 'namespace' }
+ end
+
+ context 'as template' do
+ before { subject.template = true }
- it 'defaults to the project name with ID' do
- expect(described_class.new(project: project).namespace).to eq(namespace_name)
+ it 'sets the namespace to the default' do
+ expect(kube_namespace).not_to be_nil
+ expect(kube_namespace[:placeholder]).to eq(subject.class::TEMPLATE_PLACEHOLDER)
end
end
- context 'without a project' do
- it 'leaves the namespace unset' do
- expect(described_class.new.namespace).to be_nil
+ context 'with associated project' do
+ before { subject.project = project }
+
+ it 'sets the namespace to the default' do
+ expect(kube_namespace).not_to be_nil
+ expect(kube_namespace[:placeholder]).to match(/\A#{Gitlab::Regex::PATH_REGEX_STR}-\d+\z/)
end
end
end
@@ -138,38 +155,40 @@ describe KubernetesService, models: true, caching: true do
before do
subject.api_url = 'https://kube.domain.com'
subject.token = 'token'
- subject.namespace = 'my-project'
subject.ca_pem = 'CA PEM DATA'
+ subject.project = project
end
- it 'sets KUBE_URL' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true }
- )
- end
+ context 'namespace is provided' do
+ before { subject.namespace = 'my-project' }
- it 'sets KUBE_TOKEN' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_TOKEN', value: 'token', public: false }
- )
+ it 'sets the variables' do
+ expect(subject.predefined_variables).to include(
+ { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
+ { key: 'KUBE_TOKEN', value: 'token', public: false },
+ { key: 'KUBE_NAMESPACE', value: 'my-project', public: true },
+ { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true },
+ { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true },
+ )
+ end
end
- it 'sets KUBE_NAMESPACE' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_NAMESPACE', value: 'my-project', public: true }
- )
- end
+ context 'no namespace provided' do
+ it 'sets the variables' do
+ expect(subject.predefined_variables).to include(
+ { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
+ { key: 'KUBE_TOKEN', value: 'token', public: false },
+ { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true },
+ { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true },
+ )
+ end
- it 'sets KUBE_CA_PEM' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true }
- )
- end
+ it 'sets the KUBE_NAMESPACE' do
+ kube_namespace = subject.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
- it 'sets KUBE_CA_PEM_FILE' do
- expect(subject.predefined_variables).to include(
- { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true }
- )
+ expect(kube_namespace).not_to be_nil
+ expect(kube_namespace[:value]).to match(/\A#{Gitlab::Regex::PATH_REGEX_STR}-\d+\z/)
+ end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e6b23a1cc05..f9839d33a92 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1687,11 +1687,14 @@ describe Project, models: true do
end
describe 'inside_path' do
- let!(:project1) { create(:empty_project) }
+ let!(:project1) { create(:empty_project, namespace: create(:namespace, path: 'name_pace')) }
let!(:project2) { create(:empty_project) }
+ let!(:project3) { create(:empty_project, namespace: create(:namespace, path: 'namespace')) }
let!(:path) { project1.namespace.full_path }
- it { expect(Project.inside_path(path)).to eq([project1]) }
+ it 'returns correct project' do
+ expect(Project.inside_path(path)).to eq([project1])
+ end
end
describe '#route_map_for' do
@@ -1839,10 +1842,8 @@ describe Project, models: true do
context 'when no user is given' do
it 'returns the url to the repo without a username' do
- url = project.http_url_to_repo
-
- expect(url).to eq(project.http_url_to_repo)
- expect(url).not_to include('@')
+ expect(project.http_url_to_repo).to eq("#{project.web_url}.git")
+ expect(project.http_url_to_repo).not_to include('@')
end
end
@@ -1850,7 +1851,7 @@ describe Project, models: true do
it 'returns the url to the repo with the username' do
user = build_stubbed(:user)
- expect(project.http_url_to_repo(user)).to match(%r{https?:\/\/#{user.username}@})
+ expect(project.http_url_to_repo(user)).to start_with("http://#{user.username}@")
end
end
end
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 58b57bd4fef..b5b9cd024b0 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -35,10 +35,23 @@ describe ProjectWiki, models: true do
end
describe "#http_url_to_repo" do
- it "provides the full http url to the repo" do
- gitlab_url = Gitlab.config.gitlab.url
- repo_http_url = "#{gitlab_url}/#{subject.path_with_namespace}.git"
- expect(subject.http_url_to_repo).to eq(repo_http_url)
+ let(:project) { create :empty_project }
+
+ context 'when no user is given' do
+ it 'returns the url to the repo without a username' do
+ expected_url = "#{Gitlab.config.gitlab.url}/#{subject.path_with_namespace}.git"
+
+ expect(project_wiki.http_url_to_repo).to eq(expected_url)
+ expect(project_wiki.http_url_to_repo).not_to include('@')
+ end
+ end
+
+ context 'when user is given' do
+ it 'returns the url to the repo with the username' do
+ user = build_stubbed(:user)
+
+ expect(project_wiki.http_url_to_repo(user)).to start_with("http://#{user.username}@")
+ end
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 274e4f00a0a..d805e65b3c6 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -24,21 +24,8 @@ describe Repository, models: true do
repository.commit(merge_commit_id)
end
- let(:author_email) { FFaker::Internet.email }
-
- # I have to remove periods from the end of the name
- # This happened when the user's name had a suffix (i.e. "Sr.")
- # This seems to be what git does under the hood. For example, this commit:
- #
- # $ git commit --author='Foo Sr. <foo@example.com>' -m 'Where's my trailing period?'
- #
- # results in this:
- #
- # $ git show --pretty
- # ...
- # Author: Foo Sr <foo@example.com>
- # ...
- let(:author_name) { FFaker::Name.name.chomp("\.") }
+ let(:author_email) { 'user@example.org' }
+ let(:author_name) { 'John Doe' }
describe '#branch_names_contains' do
subject { repository.branch_names_contains(sample_commit.id) }
@@ -1083,7 +1070,7 @@ describe Repository, models: true do
end
end
- describe :skip_merged_commit do
+ describe 'skip_merges option' do
subject { repository.commits(Gitlab::Git::BRANCH_REF_PREFIX + "'test'", limit: 100, skip_merges: true).map{ |k| k.id } }
it { is_expected.not_to include('e56497bb5f03a90a51293fc6d516788730953899') }
@@ -1293,14 +1280,6 @@ describe Repository, models: true do
end
end
- describe '#before_import' do
- it 'flushes the repository caches' do
- expect(repository).to receive(:expire_content_cache)
-
- repository.before_import
- end
- end
-
describe '#after_import' do
it 'flushes and builds the cache' do
expect(repository).to receive(:expire_content_cache)
@@ -1851,4 +1830,17 @@ describe Repository, models: true do
end
end
end
+
+ describe '#is_ancestor?' do
+ context 'Gitaly is_ancestor feature enabled' do
+ it 'asks Gitaly server if it\'s an ancestor' do
+ commit = repository.commit
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(:is_ancestor).and_return(true)
+ expect(Gitlab::GitalyClient::Commit).to receive(:is_ancestor).
+ with(repository.raw_repository, commit.id, commit.id).and_return(true)
+
+ expect(repository.is_ancestor?(commit.id, commit.id)).to be true
+ end
+ end
+ end
end
diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb
index bc8ae4ae5a8..171a51fcc5b 100644
--- a/spec/models/route_spec.rb
+++ b/spec/models/route_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Route, models: true do
- let!(:group) { create(:group, path: 'gitlab', name: 'gitlab') }
+ let!(:group) { create(:group, path: 'git_lab', name: 'git_lab') }
let!(:route) { group.route }
describe 'relationships' do
@@ -14,10 +14,24 @@ describe Route, models: true do
it { is_expected.to validate_uniqueness_of(:path) }
end
+ describe '.inside_path' do
+ let!(:nested_group) { create(:group, path: 'test', name: 'test', parent: group) }
+ let!(:deep_nested_group) { create(:group, path: 'foo', name: 'foo', parent: nested_group) }
+ let!(:another_group) { create(:group, path: 'other') }
+ let!(:similar_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'another', name: 'another', parent: similar_group) }
+
+ it 'returns correct routes' do
+ expect(Route.inside_path('git_lab')).to match_array([nested_group.route, deep_nested_group.route])
+ end
+ end
+
describe '#rename_descendants' do
let!(:nested_group) { create(:group, path: 'test', name: 'test', parent: group) }
let!(:deep_nested_group) { create(:group, path: 'foo', name: 'foo', parent: nested_group) }
let!(:similar_group) { create(:group, path: 'gitlab-org', name: 'gitlab-org') }
+ let!(:another_group) { create(:group, path: 'gittlab', name: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'git_lab', name: 'git_lab', parent: another_group) }
context 'path update' do
context 'when route name is set' do
@@ -28,6 +42,8 @@ describe Route, models: true do
expect(described_class.exists?(path: 'bar/test')).to be_truthy
expect(described_class.exists?(path: 'bar/test/foo')).to be_truthy
expect(described_class.exists?(path: 'gitlab-org')).to be_truthy
+ expect(described_class.exists?(path: 'gittlab')).to be_truthy
+ expect(described_class.exists?(path: 'gittlab/git_lab')).to be_truthy
end
end
@@ -44,7 +60,7 @@ describe Route, models: true do
context 'name update' do
it "updates children routes with new path" do
- route.update_attributes(name: 'bar')
+ route.update_attributes(name: 'bar')
expect(described_class.exists?(name: 'bar')).to be_truthy
expect(described_class.exists?(name: 'bar / test')).to be_truthy
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 219ab1989ea..8095d01b69e 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -198,4 +198,47 @@ describe Snippet, models: true do
expect(snippet.participants).to include(note1.author, note2.author)
end
end
+
+ describe '#check_for_spam' do
+ let(:snippet) { create :snippet, visibility_level: visibility_level }
+
+ subject do
+ snippet.assign_attributes(title: title)
+ snippet.check_for_spam?
+ end
+
+ context 'when public and spammable attributes changed' do
+ let(:visibility_level) { Snippet::PUBLIC }
+ let(:title) { 'woo' }
+
+ it 'returns true' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when private' do
+ let(:visibility_level) { Snippet::PRIVATE }
+ let(:title) { snippet.title }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+
+ it 'returns true when switching to public' do
+ snippet.save!
+ snippet.visibility_level = Snippet::PUBLIC
+
+ expect(snippet.check_for_spam?).to be_truthy
+ end
+ end
+
+ context 'when spammable attributes have not changed' do
+ let(:visibility_level) { Snippet::PUBLIC }
+ let(:title) { snippet.title }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/models/system_note_metadata_spec.rb b/spec/models/system_note_metadata_spec.rb
new file mode 100644
index 00000000000..d238e28209a
--- /dev/null
+++ b/spec/models/system_note_metadata_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe SystemNoteMetadata, models: true do
+ describe 'associations' do
+ it { is_expected.to belong_to(:note) }
+ end
+
+ describe 'validation' do
+ it { is_expected.to validate_presence_of(:note) }
+
+ context 'when action type is invalid' do
+ subject do
+ build(:system_note_metadata, note: build(:note), action: 'invalid_type' )
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'when action type is valid' do
+ subject do
+ build(:system_note_metadata, note: build(:note), action: 'merge' )
+ end
+
+ it { is_expected.to be_valid }
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 90378179e32..a9e37be1157 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -81,6 +81,7 @@ describe User, models: true do
it { is_expected.to validate_numericality_of(:projects_limit) }
it { is_expected.to allow_value(0).for(:projects_limit) }
it { is_expected.not_to allow_value(-1).for(:projects_limit) }
+ it { is_expected.not_to allow_value(Gitlab::Database::MAX_INT_VALUE + 1).for(:projects_limit) }
it { is_expected.to validate_length_of(:bio).is_at_most(255) }
@@ -360,22 +361,10 @@ describe User, models: true do
end
describe '#generate_password' do
- it "executes callback when force_random_password specified" do
- user = build(:user, force_random_password: true)
- expect(user).to receive(:generate_password)
- user.save
- end
-
it "does not generate password by default" do
user = create(:user, password: 'abcdefghe')
expect(user.password).to eq('abcdefghe')
end
-
- it "generates password when forcing random password" do
- allow(Devise).to receive(:friendly_token).and_return('123456789')
- user = create(:user, password: 'abcdefg', force_random_password: true)
- expect(user.password).to eq('12345678')
- end
end
describe 'authentication token' do