diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-18 12:07:48 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-18 12:07:48 +0000 |
commit | 79d62647bcfad69d7272020acb7d8be5ee5df003 (patch) | |
tree | 008d96a4c5fdfdecda79dae5e942c7df07511c77 /spec | |
parent | 1a9d9cc14ec54036548824e3ce17da03960f5f81 (diff) | |
download | gitlab-ce-79d62647bcfad69d7272020acb7d8be5ee5df003.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
17 files changed, 821 insertions, 40 deletions
diff --git a/spec/fixtures/sentry/issue_sample_response.json b/spec/fixtures/sentry/issue_sample_response.json new file mode 100644 index 00000000000..a320a21de34 --- /dev/null +++ b/spec/fixtures/sentry/issue_sample_response.json @@ -0,0 +1,311 @@ +{ + "activity": [ + { + "data": {}, + "dateCreated": "2018-11-06T21:19:55Z", + "id": "0", + "type": "first_seen", + "user": null + } + ], + "annotations": [], + "assignedTo": null, + "count": "1", + "culprit": "raven.scripts.runner in main", + "firstRelease": { + "authors": [], + "commitCount": 0, + "data": {}, + "dateCreated": "2018-11-06T21:19:55.146Z", + "dateReleased": null, + "deployCount": 0, + "firstEvent": "2018-11-06T21:19:55.271Z", + "lastCommit": null, + "lastDeploy": null, + "lastEvent": "2018-11-06T21:19:55.271Z", + "newGroups": 0, + "owner": null, + "projects": [ + { + "name": "Pump Station", + "slug": "pump-station" + } + ], + "ref": null, + "shortVersion": "1764232", + "url": null, + "version": "17642328ead24b51867165985996d04b29310337" + }, + "firstSeen": "2018-11-06T21:19:55Z", + "hasSeen": false, + "id": "503504", + "isBookmarked": false, + "isPublic": false, + "isSubscribed": true, + "lastRelease": null, + "lastSeen": "2018-11-06T21:19:55Z", + "level": "error", + "logger": null, + "metadata": { + "title": "This is an example Python exception" + }, + "numComments": 0, + "participants": [], + "permalink": "https://sentrytest.gitlab.com/sentry-org/sentry-project/issues/503504/", + "pluginActions": [], + "pluginContexts": [], + "pluginIssues": [ + { + "id": "gitlab", + "issue": { + "url": "https://gitlab.com/gitlab-org/gitlab/issues/1" + } + } + ], + "project": { + "id": "2", + "name": "Pump Station", + "slug": "pump-station" + }, + "seenBy": [], + "shareId": null, + "shortId": "PUMP-STATION-1", + "stats": { + "24h": [ + [ + 1541451600.0, + 557 + ], + [ + 1541455200.0, + 473 + ], + [ + 1541458800.0, + 914 + ], + [ + 1541462400.0, + 991 + ], + [ + 1541466000.0, + 925 + ], + [ + 1541469600.0, + 881 + ], + [ + 1541473200.0, + 182 + ], + [ + 1541476800.0, + 490 + ], + [ + 1541480400.0, + 820 + ], + [ + 1541484000.0, + 322 + ], + [ + 1541487600.0, + 836 + ], + [ + 1541491200.0, + 565 + ], + [ + 1541494800.0, + 758 + ], + [ + 1541498400.0, + 880 + ], + [ + 1541502000.0, + 677 + ], + [ + 1541505600.0, + 381 + ], + [ + 1541509200.0, + 814 + ], + [ + 1541512800.0, + 329 + ], + [ + 1541516400.0, + 446 + ], + [ + 1541520000.0, + 731 + ], + [ + 1541523600.0, + 111 + ], + [ + 1541527200.0, + 926 + ], + [ + 1541530800.0, + 772 + ], + [ + 1541534400.0, + 400 + ], + [ + 1541538000.0, + 943 + ] + ], + "30d": [ + [ + 1538870400.0, + 565 + ], + [ + 1538956800.0, + 12862 + ], + [ + 1539043200.0, + 15617 + ], + [ + 1539129600.0, + 10809 + ], + [ + 1539216000.0, + 15065 + ], + [ + 1539302400.0, + 12927 + ], + [ + 1539388800.0, + 12994 + ], + [ + 1539475200.0, + 13139 + ], + [ + 1539561600.0, + 11838 + ], + [ + 1539648000.0, + 12088 + ], + [ + 1539734400.0, + 12338 + ], + [ + 1539820800.0, + 12768 + ], + [ + 1539907200.0, + 12816 + ], + [ + 1539993600.0, + 15356 + ], + [ + 1540080000.0, + 10910 + ], + [ + 1540166400.0, + 12306 + ], + [ + 1540252800.0, + 12912 + ], + [ + 1540339200.0, + 14700 + ], + [ + 1540425600.0, + 11890 + ], + [ + 1540512000.0, + 11684 + ], + [ + 1540598400.0, + 13510 + ], + [ + 1540684800.0, + 12625 + ], + [ + 1540771200.0, + 12811 + ], + [ + 1540857600.0, + 13180 + ], + [ + 1540944000.0, + 14651 + ], + [ + 1541030400.0, + 14161 + ], + [ + 1541116800.0, + 12612 + ], + [ + 1541203200.0, + 14316 + ], + [ + 1541289600.0, + 14742 + ], + [ + 1541376000.0, + 12505 + ], + [ + 1541462400.0, + 14180 + ] + ] + }, + "status": "unresolved", + "statusDetails": {}, + "subscriptionDetails": null, + "tags": [], + "title": "This is an example Python exception", + "type": "default", + "userCount": 0, + "userReportCount": 0 +} diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js index 581581405b6..d0893c0de01 100644 --- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js +++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js @@ -272,6 +272,7 @@ describe('ErrorTrackingList', () => { describe('When pagination is not required', () => { beforeEach(() => { + store.state.list.loading = false; store.state.list.pagination = {}; mountComponent(); }); @@ -284,6 +285,7 @@ describe('ErrorTrackingList', () => { describe('When pagination is required', () => { describe('and the user is on the first page', () => { beforeEach(() => { + store.state.list.loading = false; mountComponent({ sync: false }); }); @@ -295,6 +297,7 @@ describe('ErrorTrackingList', () => { describe('and the user is not on the first page', () => { describe('and the previous button is clicked', () => { beforeEach(() => { + store.state.list.loading = false; mountComponent({ sync: false }); wrapper.setData({ pageValue: 2 }); }); @@ -313,6 +316,7 @@ describe('ErrorTrackingList', () => { describe('and the next page button is clicked', () => { beforeEach(() => { + store.state.list.loading = false; mountComponent({ sync: false }); }); diff --git a/spec/frontend/fixtures/static/mock-video.mp4 b/spec/frontend/fixtures/static/mock-video.mp4 Binary files differnew file mode 100644 index 00000000000..1fc478842f5 --- /dev/null +++ b/spec/frontend/fixtures/static/mock-video.mp4 diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js index 4cd0f62da0f..2569f2f02a7 100644 --- a/spec/frontend/vue_shared/components/markdown/field_spec.js +++ b/spec/frontend/vue_shared/components/markdown/field_spec.js @@ -1,9 +1,9 @@ import { mount, createLocalVue } from '@vue/test-utils'; -import { TEST_HOST } from 'spec/test_constants'; +import fieldComponent from '~/vue_shared/components/markdown/field.vue'; +import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants'; import AxiosMockAdapter from 'axios-mock-adapter'; import $ from 'jquery'; import axios from '~/lib/utils/axios_utils'; -import fieldComponent from '~/vue_shared/components/markdown/field.vue'; const markdownPreviewPath = `${TEST_HOST}/preview`; const markdownDocsPath = `${TEST_HOST}/docs`; @@ -19,6 +19,7 @@ function createComponent() { propsData: { markdownDocsPath, markdownPreviewPath, + isSubmitting: false, }, slots: { textarea: '<textarea>testing\n123</textarea>', @@ -27,6 +28,7 @@ function createComponent() { <field-component markdown-preview-path="${markdownPreviewPath}" markdown-docs-path="${markdownDocsPath}" + :isSubmitting="false" > <textarea slot="textarea" @@ -44,6 +46,7 @@ const getPreviewLink = wrapper => wrapper.find('.nav-links .js-preview-link'); const getWriteLink = wrapper => wrapper.find('.nav-links .js-write-link'); const getMarkdownButton = wrapper => wrapper.find('.js-md'); const getAllMarkdownButtons = wrapper => wrapper.findAll('.js-md'); +const getVideo = wrapper => wrapper.find('video'); describe('Markdown field component', () => { let axiosMock; @@ -59,7 +62,10 @@ describe('Markdown field component', () => { describe('mounted', () => { let wrapper; - const previewHTML = '<p>markdown preview</p>'; + const previewHTML = ` + <p>markdown preview</p> + <video src="${FIXTURES_PATH}/static/mock-video.mp4" muted="muted"></video> + `; let previewLink; let writeLink; @@ -112,9 +118,35 @@ describe('Markdown field component', () => { previewLink.trigger('click'); - setTimeout(() => { - expect($.fn.renderGFM).toHaveBeenCalled(); - }, 0); + return axios.waitFor(markdownPreviewPath).then(() => { + expect(wrapper.find('.md-preview-holder').element.innerHTML).toContain(previewHTML); + }); + }); + + it('calls video.pause() on comment input when isSubmitting is changed to true', () => { + wrapper = createComponent(); + previewLink = getPreviewLink(wrapper); + previewLink.trigger('click'); + + let callPause; + + return axios + .waitFor(markdownPreviewPath) + .then(() => { + const video = getVideo(wrapper); + callPause = jest.spyOn(video.element, 'pause').mockImplementation(() => true); + + wrapper.setProps({ + isSubmitting: true, + markdownPreviewPath, + markdownDocsPath, + }); + + return wrapper.vm.$nextTick(); + }) + .then(() => { + expect(callPause).toHaveBeenCalled(); + }); }); it('clicking already active write or preview link does nothing', () => { diff --git a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb index 7ebe5842fd0..f84f10bdc46 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb @@ -40,7 +40,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'auto_devops_source' - template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') + template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') expect(command.config_content).to eq(template.content) end end @@ -52,7 +52,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'auto_devops_source' - template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') + template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') expect(command.config_content).to eq(template.content) end end @@ -82,12 +82,32 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do expect(project).to receive(:auto_devops_enabled?).and_return(true) end - it 'returns the content of AutoDevops template' do - subject.perform! + context 'when beta is enabled' do + before do + stub_feature_flags(auto_devops_beta: true) + end - expect(pipeline.config_source).to eq 'auto_devops_source' - template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') - expect(command.config_content).to eq(template.content) + it 'returns the content of AutoDevops template' do + subject.perform! + + expect(pipeline.config_source).to eq 'auto_devops_source' + template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') + expect(command.config_content).to eq(template.content) + end + end + + context 'when beta is disabled' do + before do + stub_feature_flags(auto_devops_beta: false) + end + + it 'returns the content of AutoDevops template' do + subject.perform! + + expect(pipeline.config_source).to eq 'auto_devops_source' + template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') + expect(command.config_content).to eq(template.content) + end end end @@ -190,15 +210,38 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do expect(project).to receive(:auto_devops_enabled?).and_return(true) end - it 'builds root config including the auto-devops template' do - subject.perform! + context 'when beta is enabled' do + before do + stub_feature_flags(auto_devops_beta: true) + end - expect(pipeline.config_source).to eq 'auto_devops_source' - expect(command.config_content).to eq(<<~EOY) - --- - include: - - template: Auto-DevOps.gitlab-ci.yml - EOY + it 'builds root config including the auto-devops template' do + subject.perform! + + expect(pipeline.config_source).to eq 'auto_devops_source' + expect(command.config_content).to eq(<<~EOY) + --- + include: + - template: Beta/Auto-DevOps.gitlab-ci.yml + EOY + end + end + + context 'when beta is disabled' do + before do + stub_feature_flags(auto_devops_beta: false) + end + + it 'builds root config including the auto-devops template' do + subject.perform! + + expect(pipeline.config_source).to eq 'auto_devops_source' + expect(command.config_content).to eq(<<~EOY) + --- + include: + - template: Auto-DevOps.gitlab-ci.yml + EOY + end end end diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb index c2f9930056a..12600d97b2f 100644 --- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb +++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb @@ -9,7 +9,7 @@ describe 'Auto-DevOps.gitlab-ci.yml' do let(:user) { create(:admin) } let(:default_branch) { 'master' } let(:pipeline_branch) { default_branch } - let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) } + let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) } let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) } let(:pipeline) { service.execute!(:push) } let(:build_names) { pipeline.builds.pluck(:name) } @@ -107,4 +107,52 @@ describe 'Auto-DevOps.gitlab-ci.yml' do end end end + + describe 'build-pack detection' do + using RSpec::Parameterized::TableSyntax + + where(:case_name, :files, :variables, :include_build_names, :not_include_build_names) do + 'No match' | { 'README.md' => '' } | {} | %w() | %w(build test) + 'Buildpack' | { 'README.md' => '' } | { 'BUILDPACK_URL' => 'http://example.com' } | %w(build test) | %w() + 'Explicit set' | { 'README.md' => '' } | { 'AUTO_DEVOPS_EXPLICITLY_ENABLED' => '1' } | %w(build test) | %w() + 'Explicit unset' | { 'README.md' => '' } | { 'AUTO_DEVOPS_EXPLICITLY_ENABLED' => '0' } | %w() | %w(build test) + 'Dockerfile' | { 'Dockerfile' => '' } | {} | %w(build test) | %w() + 'Clojure' | { 'project.clj' => '' } | {} | %w(build test) | %w() + 'Go modules' | { 'go.mod' => '' } | {} | %w(build test) | %w() + 'Go gb' | { 'src/gitlab.com/gopackage.go' => '' } | {} | %w(build test) | %w() + 'Gradle' | { 'gradlew' => '' } | {} | %w(build test) | %w() + 'Java' | { 'pom.xml' => '' } | {} | %w(build test) | %w() + 'Multi-buildpack' | { '.buildpacks' => '' } | {} | %w(build test) | %w() + 'NodeJS' | { 'package.json' => '' } | {} | %w(build test) | %w() + 'PHP' | { 'composer.json' => '' } | {} | %w(build test) | %w() + 'Play' | { 'conf/application.conf' => '' } | {} | %w(build test) | %w() + 'Python' | { 'Pipfile' => '' } | {} | %w(build test) | %w() + 'Ruby' | { 'Gemfile' => '' } | {} | %w(build test) | %w() + 'Scala' | { 'build.sbt' => '' } | {} | %w(build test) | %w() + 'Static' | { '.static' => '' } | {} | %w(build test) | %w() + end + + with_them do + subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') } + + let(:user) { create(:admin) } + let(:project) { create(:project, :custom_repo, files: files) } + let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) } + let(:pipeline) { service.execute(:push) } + let(:build_names) { pipeline.builds.pluck(:name) } + + before do + stub_ci_pipeline_yaml_file(template.content) + allow_any_instance_of(Ci::BuildScheduleWorker).to receive(:perform).and_return(true) + variables.each do |(key, value)| + create(:ci_variable, project: project, key: key, value: value) + end + end + + it 'creates a pipeline with the expected jobs' do + expect(build_names).to include(*include_build_names) + expect(build_names).not_to include(*not_include_build_names) + end + end + end end diff --git a/spec/lib/gitlab/dependency_linker/cargo_toml_linker_spec.rb b/spec/lib/gitlab/dependency_linker/cargo_toml_linker_spec.rb new file mode 100644 index 00000000000..86d5bc93bf7 --- /dev/null +++ b/spec/lib/gitlab/dependency_linker/cargo_toml_linker_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::DependencyLinker::CargoTomlLinker do + describe '.support?' do + it 'supports Cargo.toml' do + expect(described_class.support?('Cargo.toml')).to be_truthy + end + + it 'does not support other files' do + expect(described_class.support?('cargo.yaml')).to be_falsey + end + end + + describe '#link' do + let(:file_name) { "Cargo.toml" } + + let(:file_content) do + <<-CONTENT.strip_heredoc + # See https://doc.rust-lang.org/cargo/reference/manifest.html + [package] + # Package shouldn't be matched + name = "gitlab-test" + version = "0.0.1" + authors = ["Some User <some.user@example.org>"] + description = "A GitLab test Cargo.toml." + keywords = ["gitlab", "test", "rust", "crago"] + readme = "README.md" + + [dependencies] + # Default dependencies format with fixed version and version range + chrono = "0.4.7" + xml-rs = ">=0.8.0" + + [dependencies.memchr] + # Specific dependency with optional info + version = "2.2.1" + optional = true + + [dev-dependencies] + # Dev dependency with version modifier + commandspec = "~0.12.2" + + [build-dependencies] + # Build dependency with version wildcard + thread_local = "0.3.*" + CONTENT + end + + subject { Gitlab::Highlight.highlight(file_name, file_content) } + + def link(name, url) + %{<a href="#{url}" rel="nofollow noreferrer noopener" target="_blank">#{name}</a>} + end + + it 'links dependencies' do + expect(subject).to include(link('chrono', 'https://crates.io/crates/chrono')) + expect(subject).to include(link('xml-rs', 'https://crates.io/crates/xml-rs')) + expect(subject).to include(link('memchr', 'https://crates.io/crates/memchr')) + expect(subject).to include(link('commandspec', 'https://crates.io/crates/commandspec')) + expect(subject).to include(link('thread_local', 'https://crates.io/crates/thread_local')) + end + + it 'does not contain metadata identified as package' do + expect(subject).not_to include(link('version', 'https://crates.io/crates/version')) + end + end +end diff --git a/spec/lib/gitlab/dependency_linker_spec.rb b/spec/lib/gitlab/dependency_linker_spec.rb index 3ea3334caf0..570a994f520 100644 --- a/spec/lib/gitlab/dependency_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker_spec.rb @@ -83,5 +83,13 @@ describe Gitlab::DependencyLinker do described_class.link(blob_name, nil, nil) end + + it 'links using CargoTomlLinker' do + blob_name = 'Cargo.toml' + + expect(described_class::CargoTomlLinker).to receive(:link) + + described_class.link(blob_name, nil, nil) + end end end diff --git a/spec/lib/sentry/client/issue_spec.rb b/spec/lib/sentry/client/issue_spec.rb new file mode 100644 index 00000000000..17548e2081d --- /dev/null +++ b/spec/lib/sentry/client/issue_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Sentry::Client::Issue do + include SentryClientHelpers + + let(:token) { 'test-token' } + let(:client) { Sentry::Client.new(sentry_url, token) } + + describe '#issue_details' do + let(:issue_sample_response) do + Gitlab::Utils.deep_indifferent_access( + JSON.parse(fixture_file('sentry/issue_sample_response.json')) + ) + end + + let(:issue_id) { 503504 } + let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0' } + let(:sentry_request_url) { "#{sentry_url}/issues/#{issue_id}/" } + let!(:sentry_api_request) { stub_sentry_request(sentry_request_url, body: issue_sample_response) } + + subject { client.issue_details(issue_id: issue_id) } + + it_behaves_like 'calls sentry api' + + it 'escapes issue ID' do + allow(CGI).to receive(:escape).and_call_original + + subject + + expect(CGI).to have_received(:escape).with(issue_id.to_s) + end + + context 'error object created from sentry response' do + using RSpec::Parameterized::TableSyntax + + where(:error_object, :sentry_response) do + :id | :id + :first_seen | :firstSeen + :last_seen | :lastSeen + :title | :title + :type | :type + :user_count | :userCount + :count | :count + :message | [:metadata, :value] + :culprit | :culprit + :short_id | :shortId + :status | :status + :frequency | [:stats, '24h'] + :project_id | [:project, :id] + :project_name | [:project, :name] + :project_slug | [:project, :slug] + :first_release_last_commit | [:firstRelease, :lastCommit] + :last_release_last_commit | [:lastRelease, :lastCommit] + :first_release_short_version | [:firstRelease, :shortVersion] + :last_release_short_version | [:lastRelease, :shortVersion] + end + + with_them do + it do + expect(subject.public_send(error_object)).to eq(issue_sample_response.dig(*sentry_response)) + end + end + + it 'has a correct external URL' do + expect(subject.external_url).to eq('https://sentrytest.gitlab.com/api/0/issues/503504') + end + + it 'issue has a correct external base url' do + expect(subject.external_base_url).to eq('https://sentrytest.gitlab.com/api/0') + end + + it 'has a correct GitLab issue url' do + expect(subject.gitlab_issue).to eq('https://gitlab.com/gitlab-org/gitlab/issues/1') + end + end + end +end diff --git a/spec/lib/sentry/client_spec.rb b/spec/lib/sentry/client_spec.rb index cff06bf4a5f..8500f67b8e9 100644 --- a/spec/lib/sentry/client_spec.rb +++ b/spec/lib/sentry/client_spec.rb @@ -14,12 +14,6 @@ describe Sentry::Client do } end - let(:issues_sample_response) do - Gitlab::Utils.deep_indifferent_access( - JSON.parse(fixture_file('sentry/issues_sample_response.json')) - ) - end - subject(:client) { described_class.new(sentry_url, token) } shared_examples 'issues has correct return type' do |klass| @@ -33,6 +27,12 @@ describe Sentry::Client do end describe '#list_issues' do + let(:issues_sample_response) do + Gitlab::Utils.deep_indifferent_access( + JSON.parse(fixture_file('sentry/issues_sample_response.json')) + ) + end + let(:issue_status) { 'unresolved' } let(:limit) { 20 } let(:search_term) { '' } diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 900e0feaccc..20915e6d3b1 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -2245,14 +2245,24 @@ describe Ci::Build do end end - describe '#has_expiring_artifacts?' do + describe '#has_expiring_archive_artifacts?' do context 'when artifacts have expiration date set' do before do build.update(artifacts_expire_at: 1.day.from_now) end - it 'has expiring artifacts' do - expect(build).to have_expiring_artifacts + context 'and job artifacts file exists' do + let!(:archive) { create(:ci_job_artifact, :archive, job: build) } + + it 'has expiring artifacts' do + expect(build).to have_expiring_archive_artifacts + end + end + + context 'and job artifacts file does not exist' do + it 'does not have expiring artifacts' do + expect(build).not_to have_expiring_archive_artifacts + end end end @@ -2262,7 +2272,7 @@ describe Ci::Build do end it 'does not have expiring artifacts' do - expect(build).not_to have_expiring_artifacts + expect(build).not_to have_expiring_archive_artifacts end end end diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb index 601dac21e6a..ae493d5c081 100644 --- a/spec/models/diff_note_spec.rb +++ b/spec/models/diff_note_spec.rb @@ -91,18 +91,124 @@ describe DiffNote do end describe '#create_diff_file callback' do - let(:noteable) { create(:merge_request) } - let(:project) { noteable.project } - context 'merge request' do - let!(:diff_note) { create(:diff_note_on_merge_request, project: project, noteable: noteable) } + let(:position) do + Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb", + new_path: "files/ruby/popen.rb", + old_line: nil, + new_line: 9, + diff_refs: merge_request.diff_refs) + end - it 'creates a diff note file' do - expect(diff_note.reload.note_diff_file).to be_present + subject { build(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request) } + + let(:diff_file_from_repository) do + position.diff_file(project.repository) + end + + let(:diff_file) do + diffs = merge_request.diffs + raw_diff = diffs.diffable.raw_diffs(diffs.diff_options.merge(paths: ['files/ruby/popen.rb'])).first + Gitlab::Diff::File.new(raw_diff, + repository: diffs.project.repository, + diff_refs: diffs.diff_refs, + fallback_diff_refs: diffs.fallback_diff_refs) + end + + let(:diff_line) { diff_file.diff_lines.first } + + let(:line_code) { '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14' } + + before do + allow(subject.position).to receive(:line_code).and_return('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14') + end + + context 'when diffs are already created' do + before do + allow(subject).to receive(:created_at_diff?).and_return(true) + end + + context 'when diff_file is found in persisted diffs' do + before do + allow(merge_request).to receive_message_chain(:diffs, :diff_files, :first).and_return(diff_file) + end + + context 'when importing' do + before do + subject.importing = true + subject.line_code = line_code + end + + context 'when diff_line is found in persisted diff_file' do + before do + allow(diff_file).to receive(:line_for_position).with(position).and_return(diff_line) + end + + it 'creates a diff note file' do + subject.save + expect(subject.note_diff_file).to be_present + end + end + + context 'when diff_line is not found in persisted diff_file' do + before do + allow(diff_file).to receive(:line_for_position).and_return(nil) + end + + it_behaves_like 'a valid diff note with after commit callback' + end + end + + context 'when not importing' do + context 'when diff_line is not found' do + before do + allow(diff_file).to receive(:line_for_position).with(position).and_return(nil) + end + + it 'raises an error' do + expect { subject.save }.to raise_error(::DiffNote::NoteDiffFileCreationError, + "Failed to find diff line for: #{diff_file.file_path}, "\ + "old_line: #{position.old_line}"\ + ", new_line: #{position.new_line}") + end + end + + context 'when diff_line is found' do + before do + allow(diff_file).to receive(:line_for_position).with(position).and_return(diff_line) + end + + it 'creates a diff note file' do + subject.save + expect(subject.reload.note_diff_file).to be_present + end + end + end + end + + context 'when diff file is not found in persisted diffs' do + before do + allow_next_instance_of(Gitlab::Diff::FileCollection::MergeRequestDiff) do |merge_request_diff| + allow(merge_request_diff).to receive(:diff_files).and_return([]) + end + end + + it_behaves_like 'a valid diff note with after commit callback' + end + end + + context 'when diffs are not already created' do + before do + allow(subject).to receive(:created_at_diff?).and_return(false) + end + + it_behaves_like 'a valid diff note with after commit callback' end it 'does not create diff note file if it is a reply' do - expect { create(:diff_note_on_merge_request, noteable: noteable, in_reply_to: diff_note) } + diff_note = create(:diff_note_on_merge_request, project: project, noteable: merge_request) + + expect { create(:diff_note_on_merge_request, noteable: merge_request, in_reply_to: diff_note) } .not_to change(NoteDiffFile, :count) end end diff --git a/spec/serializers/build_artifact_entity_spec.rb b/spec/serializers/build_artifact_entity_spec.rb index 09fe094fff1..5f1d5093e0a 100644 --- a/spec/serializers/build_artifact_entity_spec.rb +++ b/spec/serializers/build_artifact_entity_spec.rb @@ -4,6 +4,8 @@ require 'spec_helper' describe BuildArtifactEntity do let(:job) { create(:ci_build, name: 'test:job', artifacts_expire_at: 1.hour.from_now) } + let!(:archive) { create(:ci_job_artifact, :archive, job: job) } + let!(:metadata) { create(:ci_job_artifact, :metadata, job: job) } let(:entity) do described_class.new(job, request: double) diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb index 91c5fd6bf2c..6fe9eaedfeb 100644 --- a/spec/serializers/build_details_entity_spec.rb +++ b/spec/serializers/build_details_entity_spec.rb @@ -176,5 +176,27 @@ describe BuildDetailsEntity do expect(subject[:reports].first[:file_type]).to eq('codequality') end end + + context 'when the build has no archive type artifacts' do + let!(:report) { create(:ci_job_artifact, :codequality, job: build) } + + it 'does not expose any artifact actions path' do + expect(subject[:artifact].keys).not_to include(:download_path, :browse_path, :keep_path) + end + end + + context 'when the build has archive type artifacts' do + let!(:report) { create(:ci_job_artifact, :codequality, job: build) } + let!(:archive) { create(:ci_job_artifact, :archive, job: build) } + let!(:metadata) { create(:ci_job_artifact, :metadata, job: build) } + + before do + build.update(artifacts_expire_at: 7.days.from_now) + end + + it 'exposes artifact details' do + expect(subject[:artifact].keys).to include(:download_path, :browse_path, :keep_path, :expire_at, :expired) + end + end end end diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index 04e57b1a2d4..5f760844046 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -493,6 +493,7 @@ describe Ci::CreatePipelineService do before do stub_ci_pipeline_yaml_file(nil) allow_any_instance_of(Project).to receive(:auto_devops_enabled?).and_return(true) + create(:project_auto_devops, project: project) end it 'pull it from Auto-DevOps' do diff --git a/spec/services/external_pull_requests/create_pipeline_service_spec.rb b/spec/services/external_pull_requests/create_pipeline_service_spec.rb index a4da5b38b97..03481baea87 100644 --- a/spec/services/external_pull_requests/create_pipeline_service_spec.rb +++ b/spec/services/external_pull_requests/create_pipeline_service_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' describe ExternalPullRequests::CreatePipelineService do describe '#execute' do - set(:project) { create(:project, :repository) } + set(:project) { create(:project, :auto_devops, :repository) } set(:user) { create(:user) } let(:pull_request) { create(:external_pull_request, project: project) } diff --git a/spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb b/spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb new file mode 100644 index 00000000000..835d2dfe757 --- /dev/null +++ b/spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +shared_examples 'a valid diff note with after commit callback' do + context 'when diff file is fetched from repository' do + before do + allow_any_instance_of(::Gitlab::Diff::Position).to receive(:diff_file).with(project.repository).and_return(diff_file_from_repository) + end + + context 'when diff_line is not found' do + it 'raises an error' do + allow(diff_file_from_repository).to receive(:line_for_position).with(position).and_return(nil) + + expect { subject.save }.to raise_error(::DiffNote::NoteDiffFileCreationError, + "Failed to find diff line for: #{diff_file_from_repository.file_path}, "\ + "old_line: #{position.old_line}"\ + ", new_line: #{position.new_line}") + end + end + + context 'when diff_line is found' do + before do + allow(diff_file_from_repository).to receive(:line_for_position).with(position).and_return(diff_line) + end + + it 'fallback to fetch file from repository' do + expect_any_instance_of(::Gitlab::Diff::Position).to receive(:diff_file).with(project.repository) + + subject.save + end + + it 'creates a diff note file' do + subject.save + + expect(subject.reload.note_diff_file).to be_present + end + end + end + + context 'when diff file is not found in repository' do + it 'raises an error' do + allow_any_instance_of(::Gitlab::Diff::Position).to receive(:diff_file).with(project.repository).and_return(nil) + + expect { subject.save }.to raise_error(::DiffNote::NoteDiffFileCreationError, 'Failed to find diff file') + end + end +end |