diff options
author | Kushal Pandya <kushalspandya@gmail.com> | 2017-04-06 09:46:50 +0000 |
---|---|---|
committer | Kushal Pandya <kushalspandya@gmail.com> | 2017-04-06 09:46:50 +0000 |
commit | 18506d4b8b8bc780b3b1e4c61339af38b5c49bb2 (patch) | |
tree | 6aab0c83abe14064433c326996ccbe8097495454 /spec/models | |
parent | cd5b36d04e79ed8fcd649127e0d47e09ec325242 (diff) | |
parent | 49bdd8d63b577f079cdc47f7dd10ba83c677771a (diff) | |
download | gitlab-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')
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 |