From 3aa1264dc6c0de3625bb1a2d6a0ee90140a2f519 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sun, 29 Jan 2017 22:01:31 -0600 Subject: [PATCH] Add tests --- app/models/ci/pipeline.rb | 2 +- app/models/project.rb | 6 +- app/models/repository.rb | 4 +- lib/gitlab/route_map.rb | 2 + .../projects/blobs/view_on_env_spec.rb | 7 + .../{commits => commit}/cherry_pick_spec.rb | 0 .../projects/commit/view_on_env_spec.rb | 9 ++ .../projects/compare/view_on_env_spec.rb | 9 ++ spec/features/{ => projects}/compare_spec.rb | 0 .../merge_requests/view_on_env_spec.rb | 9 ++ spec/helpers/commits_helper_spec.rb | 19 +++ spec/lib/gitlab/route_map_spec.rb | 89 +++++++++++++ spec/models/environment_spec.rb | 48 +++++++ spec/models/merge_request_spec.rb | 24 ++++ spec/models/project_spec.rb | 123 ++++++++++++++++++ spec/models/repository_spec.rb | 36 +++++ 16 files changed, 381 insertions(+), 6 deletions(-) create mode 100644 spec/features/projects/blobs/view_on_env_spec.rb rename spec/features/projects/{commits => commit}/cherry_pick_spec.rb (100%) create mode 100644 spec/features/projects/commit/view_on_env_spec.rb create mode 100644 spec/features/projects/compare/view_on_env_spec.rb rename spec/features/{ => projects}/compare_spec.rb (100%) create mode 100644 spec/features/projects/merge_requests/view_on_env_spec.rb create mode 100644 spec/lib/gitlab/route_map_spec.rb diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 8db53ea56dd..70bb4a224a1 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -283,7 +283,7 @@ module Ci def ci_yaml_file return @ci_yaml_file if defined?(@ci_yaml_file) - @ci_yaml_file ||= project.repository.ci_yaml_file(sha) + @ci_yaml_file ||= project.repository.gitlab_ci_yml_for(sha) end def has_yaml_errors? diff --git a/app/models/project.rb b/app/models/project.rb index 42a79557136..15c6e25e73f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1342,10 +1342,10 @@ class Project < ActiveRecord::Base end end - def route_map_for_commit(commit_sha) + def route_map_for(commit_sha) @route_maps_by_commit ||= Hash.new do |h, sha| h[sha] = begin - data = repository.route_map_file(sha) + data = repository.route_map_for(sha) next unless data Gitlab::RouteMap.new(data) @@ -1358,7 +1358,7 @@ class Project < ActiveRecord::Base end def public_path_for_source_path(path, commit_sha) - map = route_map_for_commit(commit_sha) + map = route_map_for(commit_sha) return unless map map.public_path_for_source_path(path) diff --git a/app/models/repository.rb b/app/models/repository.rb index 9aa0cc250f0..ba9c038b66d 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1187,14 +1187,14 @@ class Repository end end - def route_map_file(sha) + def route_map_for(sha) blob = blob_at(sha, ROUTE_MAP_PATH) return unless blob blob.load_all_data!(self) blob.data end - def ci_yaml_file(sha) + def gitlab_ci_yml_for(sha) blob = blob_at(sha, GITLAB_CI_YML_PATH) return unless blob blob.load_all_data!(self) diff --git a/lib/gitlab/route_map.rb b/lib/gitlab/route_map.rb index 89985d90c10..b1a93d44a45 100644 --- a/lib/gitlab/route_map.rb +++ b/lib/gitlab/route_map.rb @@ -2,6 +2,8 @@ module Gitlab class RouteMap class FormatError < StandardError; end + attr_reader :map + def initialize(data) begin entries = YAML.safe_load(data) diff --git a/spec/features/projects/blobs/view_on_env_spec.rb b/spec/features/projects/blobs/view_on_env_spec.rb new file mode 100644 index 00000000000..360f9d66609 --- /dev/null +++ b/spec/features/projects/blobs/view_on_env_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' + +feature 'Blob' do + describe 'View on environment' do + # TODO: Test + end +end diff --git a/spec/features/projects/commits/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb similarity index 100% rename from spec/features/projects/commits/cherry_pick_spec.rb rename to spec/features/projects/commit/cherry_pick_spec.rb diff --git a/spec/features/projects/commit/view_on_env_spec.rb b/spec/features/projects/commit/view_on_env_spec.rb new file mode 100644 index 00000000000..eee2814089a --- /dev/null +++ b/spec/features/projects/commit/view_on_env_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +feature 'Commit' do + describe 'Diff' do + describe 'View on environment' do + # TODO: Test + end + end +end diff --git a/spec/features/projects/compare/view_on_env_spec.rb b/spec/features/projects/compare/view_on_env_spec.rb new file mode 100644 index 00000000000..0a4ec03b17f --- /dev/null +++ b/spec/features/projects/compare/view_on_env_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +feature 'Compare' do + describe 'Diff' do + describe 'View on environment' do + # TODO: Test + end + end +end diff --git a/spec/features/compare_spec.rb b/spec/features/projects/compare_spec.rb similarity index 100% rename from spec/features/compare_spec.rb rename to spec/features/projects/compare_spec.rb diff --git a/spec/features/projects/merge_requests/view_on_env_spec.rb b/spec/features/projects/merge_requests/view_on_env_spec.rb new file mode 100644 index 00000000000..b25e499acd6 --- /dev/null +++ b/spec/features/projects/merge_requests/view_on_env_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +feature 'Merge Request' do + describe 'Diff' do + describe 'View on environment' do + # TODO: Test + end + end +end diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb index 727c25ff529..85c663030d8 100644 --- a/spec/helpers/commits_helper_spec.rb +++ b/spec/helpers/commits_helper_spec.rb @@ -26,4 +26,23 @@ describe CommitsHelper do not_to include('onmouseover="alert(1)"') end end + + describe '#view_on_environment_btn' do + let(:project) { create(:empty_project) } + let(:environment) { create(:environment, external_url: 'http://example.com') } + let(:path) { 'source/file.html' } + let(:sha) { RepoHelpers.sample_commit.id } + + before do + allow(environment).to receive(:external_url_for).with(path, sha).and_return('http://example.com/file.html') + end + + it 'returns a link tag linking to the file in the environment' do + html = helper.view_on_environment_btn(sha, path, environment) + node = Nokogiri::HTML.parse(html).at_css('a') + + expect(node[:title]).to eq('View on example.com') + expect(node[:href]).to eq('http://example.com/file.html') + end + end end diff --git a/spec/lib/gitlab/route_map_spec.rb b/spec/lib/gitlab/route_map_spec.rb new file mode 100644 index 00000000000..d56380bec50 --- /dev/null +++ b/spec/lib/gitlab/route_map_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +describe Gitlab::RouteMap, lib: true do + describe '#initialize' do + context 'when the data is not YAML' do + it 'raises an error' do + expect { described_class.new('"') }. + to raise_error(Gitlab::RouteMap::FormatError, /valid YAML/) + end + end + + context 'when the data is not a YAML array' do + it 'raises an error' do + expect { described_class.new(YAML.dump('foo')) }. + to raise_error(Gitlab::RouteMap::FormatError, /an array/) + end + end + + context 'when an entry is not a hash' do + it 'raises an error' do + expect { described_class.new(YAML.dump(['foo'])) }. + to raise_error(Gitlab::RouteMap::FormatError, /a hash/) + end + end + + context 'when an entry does not have a source key' do + it 'raises an error' do + expect { described_class.new(YAML.dump([{ 'public' => 'index.html' }])) }. + to raise_error(Gitlab::RouteMap::FormatError, /source key/) + end + end + + context 'when an entry does not have a public key' do + it 'raises an error' do + expect { described_class.new(YAML.dump([{ 'source' => '/index\.html/' }])) }. + to raise_error(Gitlab::RouteMap::FormatError, /public key/) + end + end + + context 'when an entry source does not start and end with a slash' do + it 'raises an error' do + expect { described_class.new(YAML.dump([{ 'source' => 'index.html', 'public' => 'index.html' }])) }. + to raise_error(Gitlab::RouteMap::FormatError, /a slash/) + end + end + + context 'when an entry source is not a valid regex' do + it 'raises an error' do + expect { described_class.new(YAML.dump([{ 'source' => '/[/', 'public' => 'index.html' }])) }. + to raise_error(Gitlab::RouteMap::FormatError, /regular expression/) + end + end + + context 'when all is good' do + it 'returns a route map' do + route_map = described_class.new(YAML.dump([{ 'source' => '/index\.html/', 'public' => 'index.html' }])) + expect(route_map.map).to eq([{ source: /^index\.html$/, public: 'index.html' }]) + end + end + end + + describe '#public_path_for_source_path' do + subject do + described_class.new(<<-'MAP'.strip_heredoc) + # Blogposts + - source: /source/posts/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb + public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/ + + # HTML files + - source: /source/(.+?\.html).*/ # source/index.html.haml + public: '\1' # index.html + + # Other files + - source: /source/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png + public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png + MAP + end + + it 'returns the public path for a provided source path' do + expect(subject.public_path_for_source_path('source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb')).to eq('2017/01/30/around-the-world-in-6-releases/') + + expect(subject.public_path_for_source_path('source/index.html.haml')).to eq('index.html') + + expect(subject.public_path_for_source_path('source/images/blogimages/around-the-world-in-6-releases-cover.png')).to eq('images/blogimages/around-the-world-in-6-releases-cover.png') + + expect(subject.public_path_for_source_path('.gitlab/route-map.yml')).to be_nil + end + end +end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index eba392044bf..e40a9bf4fbe 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -22,6 +22,25 @@ describe Environment, models: true do it { is_expected.to validate_length_of(:external_url).is_at_most(255) } it { is_expected.to validate_uniqueness_of(:external_url).scoped_to(:project_id) } + describe '.latest_for_commit' do + let!(:environment1) { create(:environment, project: project) } + let!(:environment2) { create(:environment, project: project) } + let!(:environment3) { create(:environment, project: project) } + let!(:deployment1) { create(:deployment, environment: environment1) } + let!(:deployment2) { create(:deployment, environment: environment2) } + let(:commit) { RepoHelpers.sample_commit } + + before do + allow(environment1).to receive(:first_deployment_for).with(commit).and_return(deployment1) + allow(environment2).to receive(:first_deployment_for).with(commit).and_return(deployment2) + allow(environment3).to receive(:first_deployment_for).with(commit).and_return(nil) + end + + it 'returns the environment that the commit was last deployed to' do + expect(Environment.latest_for_commit([environment1, environment2, environment3], commit)).to be(environment2) + end + end + describe '#nullify_external_url' do it 'replaces a blank url with nil' do env = build(:environment, external_url: "") @@ -301,4 +320,33 @@ describe Environment, models: true do end end end + + describe '#external_url_for' do + let(:source_path) { 'source/file.html' } + let(:sha) { RepoHelpers.sample_commit.id } + + before do + environment.external_url = 'http://example.com' + end + + context 'when the public path is not known' do + before do + allow(project).to receive(:public_path_for_source_path).with(source_path, sha).and_return(nil) + end + + it 'returns nil' do + expect(environment.external_url_for(source_path, sha)).to be_nil + end + end + + context 'when the public path is known' do + before do + allow(project).to receive(:public_path_for_source_path).with(source_path, sha).and_return('file.html') + end + + it 'returns the full external URL' do + expect(environment.external_url_for(source_path, sha)).to eq('http://example.com/file.html') + end + end + end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 32ed1e96749..91a8f2d77ab 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1069,6 +1069,30 @@ describe MergeRequest, models: true do end end + describe '#latest_environment' do + let(:project) { subject.project } + let!(:environment1) { create(:environment, project: project) } + let!(:environment2) { create(:environment, project: project) } + let!(:environment3) { create(:environment, project: project) } + let!(:deployment1) { create(:deployment, environment: environment1, ref: 'master', sha: commit.id) } + let!(:deployment2) { create(:deployment, environment: environment2, ref: 'feature', sha: commit.id) } + let(:commit) { subject.diff_head_commit } + + before do + allow(environment1).to receive(:first_deployment_for).with(commit).and_return(deployment1) + allow(environment2).to receive(:first_deployment_for).with(commit).and_return(deployment2) + allow(environment3).to receive(:first_deployment_for).with(commit).and_return(nil) + end + + before do + allow(subject).to receive(:environments).and_return([environment1, environment2, environment3]) + end + + it 'returns the environment that the commit was last deployed to' do + expect(subject.latest_environment).to eq(environment2) + end + end + describe "#reload_diff" do let(:note) { create(:diff_note_on_merge_request, project: subject.project, noteable: subject) } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index d7e6da02261..1072b324b22 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1766,6 +1766,53 @@ describe Project, models: true do .to contain_exactly(environment) end end + + context 'commit deployment' do + before do + create(:deployment, environment: environment, ref: 'master', sha: project.commit.id) + end + + it 'returns environment' do + expect(project.environments_for(nil, commit: project.commit)) + .to contain_exactly(environment) + end + end + end + + describe '#latest_environment_for' do + let(:project) { create(:project) } + let!(:environment1) { create(:environment, project: project) } + let!(:environment2) { create(:environment, project: project) } + let!(:environment3) { create(:environment, project: project) } + let!(:deployment1) { create(:deployment, environment: environment1, ref: 'master', sha: commit.id) } + let!(:deployment2) { create(:deployment, environment: environment2, ref: 'feature', sha: commit.id) } + let(:commit) { project.commit } + + before do + allow(environment1).to receive(:first_deployment_for).with(commit).and_return(deployment1) + allow(environment2).to receive(:first_deployment_for).with(commit).and_return(deployment2) + allow(environment3).to receive(:first_deployment_for).with(commit).and_return(nil) + end + + context 'when specifying a ref' do + before do + allow(project).to receive(:environments_for).with('master', commit: commit).and_return([environment1]) + end + + it 'returns the environment that the commit was last deployed to from that ref' do + expect(project.latest_environment_for(commit, ref: 'master')).to eq(environment1) + end + end + + context 'when not specifying a ref' do + before do + allow(project).to receive(:environments_for).with(nil, commit: commit).and_return([environment1, environment2]) + end + + it 'returns the environment that the commit was last deployed to' do + expect(project.latest_environment_for(commit)).to eq(environment2) + end + end end describe '#environments_recently_updated_on_branch' do @@ -1858,6 +1905,82 @@ describe Project, models: true do it { expect(Project.inside_path(path)).to eq([project1]) } end + describe '#route_map_for' do + let(:project) { create(:project) } + let(:route_map) do + <<-MAP.strip_heredoc + - source: /source/(.*)/ + public: '\\1' + MAP + end + + before do + project.repository.commit_file(User.last, '.gitlab/route-map.yml', route_map, 'Add .gitlab/route-map.yml', 'master', false) + end + + context 'when there is a .gitlab/route-map.yml at the commit' do + context 'when the route map is valid' do + it 'returns a route map' do + map = project.route_map_for(project.commit.sha) + expect(map).to be_a_kind_of(Gitlab::RouteMap) + end + end + + context 'when the route map is invalid' do + let(:route_map) { 'INVALID' } + + it 'returns nil' do + expect(project.route_map_for(project.commit.sha)).to be_nil + end + end + end + + context 'when there is no .gitlab/route-map.yml at the commit' do + it 'returns nil' do + expect(project.route_map_for(project.commit.parent.sha)).to be_nil + end + end + end + + describe '#public_path_for_source_path' do + let(:project) { create(:project) } + let(:route_map) do + Gitlab::RouteMap.new(<<-MAP.strip_heredoc) + - source: /source/(.*)/ + public: '\\1' + MAP + end + let(:sha) { project.commit.id } + + context 'when there is a route map' do + before do + allow(project).to receive(:route_map_for).with(sha).and_return(route_map) + end + + context 'when the source path is mapped' do + it 'returns the public path' do + expect(project.public_path_for_source_path('source/file.html', sha)).to eq('file.html') + end + end + + context 'when the source path is not mapped' do + it 'returns nil' do + expect(project.public_path_for_source_path('file.html', sha)).to be_nil + end + end + end + + context 'when there is no route map' do + before do + allow(project).to receive(:route_map_for).with(sha).and_return(nil) + end + + it 'returns nil' do + expect(project.public_path_for_source_path('source/file.html', sha)).to be_nil + end + end + end + def enable_lfs allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 53b98ba05f8..7f97319aa2f 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1782,4 +1782,40 @@ describe Repository, models: true do repository.refresh_method_caches(%i(readme license)) end end + + describe '#gitlab_ci_yml_for' do + before do + repository.commit_file(User.last, '.gitlab-ci.yml', 'CONTENT', 'Add .gitlab-ci.yml', 'master', false) + end + + context 'when there is a .gitlab-ci.yml at the commit' do + it 'returns the content' do + expect(repository.gitlab_ci_yml_for(repository.commit.sha)).to eq('CONTENT') + end + end + + context 'when there is no .gitlab-ci.yml at the commit' do + it 'returns nil' do + expect(repository.gitlab_ci_yml_for(repository.commit.parent.sha)).to be_nil + end + end + end + + describe '#route_map_for' do + before do + repository.commit_file(User.last, '.gitlab/route-map.yml', 'CONTENT', 'Add .gitlab/route-map.yml', 'master', false) + end + + context 'when there is a .gitlab/route-map.yml at the commit' do + it 'returns the content' do + expect(repository.route_map_for(repository.commit.sha)).to eq('CONTENT') + end + end + + context 'when there is no .gitlab/route-map.yml at the commit' do + it 'returns nil' do + expect(repository.route_map_for(repository.commit.parent.sha)).to be_nil + end + end + end end