diff options
Diffstat (limited to 'spec')
91 files changed, 685 insertions, 1990 deletions
diff --git a/spec/bin/changelog_spec.rb b/spec/bin/changelog_spec.rb index ce7f7648c0c..c3a5abf2b7a 100644 --- a/spec/bin/changelog_spec.rb +++ b/spec/bin/changelog_spec.rb @@ -69,14 +69,6 @@ describe 'bin/changelog' do end end - it 'parses --ee and -e' do - %w[--ee -e].each do |flag| - options = described_class.parse(%W[foo #{flag} security]) - - expect(options.ee).to eq true - end - end - it 'parses -h' do expect do expect { described_class.parse(%w[foo -h bar]) }.to output.to_stdout diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb index d62e0a97609..4eb0545eb6c 100644 --- a/spec/controllers/admin/application_settings_controller_spec.rb +++ b/spec/controllers/admin/application_settings_controller_spec.rb @@ -118,7 +118,32 @@ describe Admin::ApplicationSettingsController do end describe 'verify panel actions' do - (Admin::ApplicationSettingsController::VALID_SETTING_PANELS - %w(templates geo)).each do |valid_action| + shared_examples 'renders correct panels' do + it 'renders correct action on error' do + expect_next_instance_of(ApplicationSettings::UpdateService) do |service| + allow(service).to receive(:execute).and_return(false) + end + + patch action, params: { application_setting: { unused_param: true } } + + expect(subject).to render_template(action) + end + + it 'redirects to same panel on success' do + expect_next_instance_of(ApplicationSettings::UpdateService) do |service| + allow(service).to receive(:execute).and_return(true) + end + + referer_path = public_send("#{action}_admin_application_settings_path") + request.env["HTTP_REFERER"] = referer_path + + patch action, params: { application_setting: { unused_param: true } } + + expect(subject).to redirect_to(referer_path) + end + end + + (Admin::ApplicationSettingsController::VALID_SETTING_PANELS - %w(show templates geo)).each do |valid_action| it_behaves_like 'renders correct panels' do let(:action) { valid_action } end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index d7134d3d25a..0b3833e6515 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' @@ -170,40 +171,16 @@ describe ApplicationController do end describe '#route_not_found' do - controller(described_class) do - def index - route_not_found - end - end - it 'renders 404 if authenticated' do - sign_in(user) - - get :index - - expect(response).to have_gitlab_http_status(404) - end - - it 'redirects to login page via authenticate_user! if not authenticated' do - get :index - - expect(response).to redirect_to new_user_session_path + allow(controller).to receive(:current_user).and_return(user) + expect(controller).to receive(:not_found) + controller.send(:route_not_found) end - context 'request format is unknown' do - it 'redirects if unauthenticated' do - get :index, format: 'unknown' - - expect(response).to redirect_to new_user_session_path - end - - it 'returns a 401 if the feature flag is disabled' do - stub_feature_flags(devise_redirect_unknown_formats: false) - - get :index, format: 'unknown' - - expect(response).to have_gitlab_http_status(401) - end + it 'does redirect to login page via authenticate_user! if not authenticated' do + allow(controller).to receive(:current_user).and_return(nil) + expect(controller).to receive(:authenticate_user!) + controller.send(:route_not_found) end end diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb index 4110be721ad..3bf0ec799c7 100644 --- a/spec/controllers/concerns/send_file_upload_spec.rb +++ b/spec/controllers/concerns/send_file_upload_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index 53d32665b0c..b455b55bd11 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index eda8c282341..e1f67054d0a 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -1289,7 +1289,7 @@ describe Projects::MergeRequestsController do expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection| note_diff_file = commit_diff_note.note_diff_file - expect(collection).to receive(:load_highlight).and_call_original + expect(collection).to receive(:load_highlight).with([note_diff_file.id]).and_call_original expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original end @@ -1306,7 +1306,7 @@ describe Projects::MergeRequestsController do expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection| note_diff_file = diff_note.note_diff_file - expect(collection).to receive(:load_highlight).and_call_original + expect(collection).to receive(:load_highlight).with([note_diff_file.id]).and_call_original expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original end @@ -1319,7 +1319,7 @@ describe Projects::MergeRequestsController do expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection| note_diff_file = diff_note.note_diff_file - expect(collection).to receive(:load_highlight).and_call_original + expect(collection).to receive(:load_highlight).with([]).and_call_original expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original end diff --git a/spec/factories/services.rb b/spec/factories/services.rb index c4cb3f07fe7..b2d6ada91fa 100644 --- a/spec/factories/services.rb +++ b/spec/factories/services.rb @@ -9,7 +9,11 @@ FactoryBot.define do factory :custom_issue_tracker_service, class: CustomIssueTrackerService do project active true - issue_tracker + properties( + project_url: 'https://project.url.com', + issues_url: 'https://issues.url.com', + new_issue_url: 'https://newissue.url.com' + ) end factory :emails_on_push_service do @@ -43,24 +47,12 @@ FactoryBot.define do factory :jira_service do project active true - - transient do - create_data true - url 'https://jira.example.com' - api_url nil - username 'jira_username' - password 'jira_password' - jira_issue_transition_id '56-1' - end - - after(:build) do |service, evaluator| - if evaluator.create_data - create(:jira_tracker_data, service: service, - url: evaluator.url, api_url: evaluator.api_url, jira_issue_transition_id: evaluator.jira_issue_transition_id, - username: evaluator.username, password: evaluator.password - ) - end - end + properties( + url: 'https://jira.example.com', + username: 'jira_user', + password: 'my-secret-password', + project_key: 'jira-key' + ) end factory :bugzilla_service do @@ -88,26 +80,20 @@ FactoryBot.define do end trait :issue_tracker do - transient do - create_data true - project_url 'http://issuetracker.example.com' - issues_url 'http://issues.example.com/issues/:id' - new_issue_url 'http://new-issue.example.com' - end - - after(:build) do |service, evaluator| - if evaluator.create_data - create(:issue_tracker_data, service: service, - project_url: evaluator.project_url, issues_url: evaluator.issues_url, new_issue_url: evaluator.new_issue_url - ) - end - end + properties( + project_url: 'http://issue-tracker.example.com', + issues_url: 'http://issue-tracker.example.com/issues/:id', + new_issue_url: 'http://issue-tracker.example.com' + ) end trait :jira_cloud_service do - url 'https://mysite.atlassian.net' - username 'jira_user' - password 'my-secret-password' + properties( + url: 'https://mysite.atlassian.net', + username: 'jira_user', + password: 'my-secret-password', + project_key: 'jira-key' + ) end factory :hipchat_service do @@ -116,21 +102,15 @@ FactoryBot.define do token 'test_token' end - # this is for testing storing values inside properties, which is deprecated and will be removed in - # https://gitlab.com/gitlab-org/gitlab-ce/issues/63084 trait :without_properties_callback do - jira_tracker_data nil - issue_tracker_data nil - create_data false - after(:build) do |service| - IssueTrackerService.skip_callback(:validation, :before, :handle_properties) + allow(service).to receive(:handle_properties) end - to_create { |instance| instance.save(validate: false)} - - after(:create) do - IssueTrackerService.set_callback(:validation, :before, :handle_properties) + after(:create) do |service| + # we have to remove the stub because the behaviour of + # handle_properties method is tested after the creation + allow(service).to receive(:handle_properties).and_call_original end end end diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb index bc757d72a49..4c3c0904a06 100644 --- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb +++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb @@ -76,7 +76,6 @@ describe 'Admin disables Git access protocol', :js do context 'with nothing disabled' do before do create(:personal_key, user: admin) - allow_all_protocols end it 'shows default SSH url and protocol selection dropdown' do @@ -108,10 +107,6 @@ describe 'Admin disables Git access protocol', :js do visit project_path(project) end - def allow_all_protocols - switch_git_protocol(1) - end - def disable_http_protocol switch_git_protocol(2) end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index ab58d9fb9d5..be34315118d 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -15,7 +15,7 @@ describe 'Admin updates settings' do context 'General page' do before do - visit general_admin_application_settings_path + visit admin_application_settings_path end it 'Change visibility settings' do diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index a17ff1ad50d..ef8749be0be 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -21,28 +21,15 @@ describe IssuesFinder do let(:expected_issuables) { [issue1, issue2] } end - it_behaves_like 'assignee NOT ID filter' do - let(:params) { { not: { assignee_id: user.id } } } - let(:expected_issuables) { [issue3, issue4] } - end - - context 'filter by username' do - set(:user3) { create(:user) } - + it_behaves_like 'assignee username filter' do before do project2.add_developer(user3) issue3.assignees = [user2, user3] end - it_behaves_like 'assignee username filter' do - let(:params) { { assignee_username: [user2.username, user3.username] } } - let(:expected_issuables) { [issue3] } - end - - it_behaves_like 'assignee NOT username filter' do - let(:params) { { not: { assignee_username: [user2.username, user3.username] } } } - let(:expected_issuables) { [issue1, issue2, issue4] } - end + set(:user3) { create(:user) } + let(:params) { { assignee_username: [user2.username, user3.username] } } + let(:expected_issuables) { [issue3] } end it_behaves_like 'no assignee filter' do @@ -125,26 +112,6 @@ describe IssuesFinder do end end - context 'filtering by NOT group_id' do - let(:params) { { not: { group_id: group.id } } } - - context 'when include_subgroup param not set' do - it 'returns all other group issues' do - expect(issues).to contain_exactly(issue2, issue3, issue4) - end - end - - context 'when include_subgroup param is true', :nested_groups do - before do - params[:include_subgroups] = true - end - - it 'returns all other group and subgroup issues' do - expect(issues).to contain_exactly(issue2, issue3) - end - end - end - context 'filtering by author ID' do let(:params) { { author_id: user2.id } } @@ -153,14 +120,6 @@ describe IssuesFinder do end end - context 'filtering by not author ID' do - let(:params) { { not: { author_id: user2.id } } } - - it 'returns issues not created by that user' do - expect(issues).to contain_exactly(issue1, issue2, issue4) - end - end - context 'filtering by milestone' do let(:params) { { milestone_title: milestone.title } } @@ -169,14 +128,6 @@ describe IssuesFinder do end end - context 'filtering by not milestone' do - let(:params) { { not: { milestone_title: milestone.title } } } - - it 'returns issues not assigned to that milestone' do - expect(issues).to contain_exactly(issue2, issue3, issue4) - end - end - context 'filtering by group milestone' do let!(:group) { create(:group, :public) } let(:group_milestone) { create(:milestone, group: group) } @@ -192,14 +143,6 @@ describe IssuesFinder do it 'returns issues assigned to that group milestone' do expect(issues).to contain_exactly(issue2, issue3) end - - context 'using NOT' do - let(:params) { { not: { milestone_title: group_milestone.title } } } - - it 'returns issues not assigned to that group milestone' do - expect(issues).to contain_exactly(issue1, issue4) - end - end end context 'filtering by no milestone' do @@ -241,10 +184,10 @@ describe IssuesFinder do let(:project_next_8_8) { create(:project, :public) } let(:project_in_group) { create(:project, :public, namespace: group) } - let(:yesterday) { Date.current - 1.day } - let(:tomorrow) { Date.current + 1.day } - let(:two_days_from_now) { Date.current + 2.days } - let(:ten_days_from_now) { Date.current + 10.days } + let(:yesterday) { Date.today - 1.day } + let(:tomorrow) { Date.today + 1.day } + let(:two_days_from_now) { Date.today + 2.days } + let(:ten_days_from_now) { Date.today + 10.days } let(:milestones) do [ @@ -258,7 +201,7 @@ describe IssuesFinder do end before do - @created_issues = milestones.map do |milestone| + milestones.each do |milestone| create(:issue, project: milestone.project || project_in_group, milestone: milestone, author: user, assignees: [user]) end end @@ -267,18 +210,6 @@ describe IssuesFinder do expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.1', '8.8', '9.9') expect(issues.map { |issue| issue.milestone.due_date }).to contain_exactly(tomorrow, two_days_from_now, tomorrow) end - - context 'using NOT' do - let(:params) { { not: { milestone_title: Milestone::Upcoming.name } } } - - it 'returns issues not in upcoming milestones for each project or group' do - target_issues = @created_issues.reject do |issue| - issue.milestone&.due_date && issue.milestone.due_date > Date.current - end + @created_issues.select { |issue| issue.milestone&.title == '8.9' } - - expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, *target_issues) - end - end end context 'filtering by started milestone' do @@ -288,10 +219,10 @@ describe IssuesFinder do let(:project_started_1_and_2) { create(:project, :public) } let(:project_started_8) { create(:project, :public) } - let(:yesterday) { Date.current - 1.day } - let(:tomorrow) { Date.current + 1.day } - let(:two_days_ago) { Date.current - 2.days } - let(:three_days_ago) { Date.current - 3.days } + let(:yesterday) { Date.today - 1.day } + let(:tomorrow) { Date.today + 1.day } + let(:two_days_ago) { Date.today - 2.days } + let(:three_days_ago) { Date.today - 3.days } let(:milestones) do [ @@ -317,16 +248,6 @@ describe IssuesFinder do expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.0', '2.0', '8.0') expect(issues.map { |issue| issue.milestone.start_date }).to contain_exactly(two_days_ago, yesterday, yesterday) end - - context 'using NOT' do - let(:params) { { not: { milestone_title: Milestone::Started.name } } } - - it 'returns issues not in the started milestones for each project' do - target_issues = Issue.where.not(milestone: Milestone.started) - - expect(issues).to contain_exactly(issue2, issue3, issue4, *target_issues) - end - end end context 'filtering by label' do @@ -335,33 +256,6 @@ describe IssuesFinder do it 'returns issues with that label' do expect(issues).to contain_exactly(issue2) end - - context 'using NOT' do - let(:params) { { not: { label_name: label.title } } } - - it 'returns issues that do not have that label' do - expect(issues).to contain_exactly(issue1, issue3, issue4) - end - - # IssuableFinder first filters using the outer params (the ones not inside the `not` key.) - # Afterwards, it applies the `not` params to that resultset. This means that things inside the `not` param - # do not take precedence over the outer params with the same name. - context 'shadowing the same outside param' do - let(:params) { { label_name: label2.title, not: { label_name: label.title } } } - - it 'does not take precedence over labels outside NOT' do - expect(issues).to contain_exactly(issue3) - end - end - - context 'further filtering outside params' do - let(:params) { { label_name: label2.title, not: { assignee_username: user2.username } } } - - it 'further filters on the returned resultset' do - expect(issues).to be_empty - end - end - end end context 'filtering by multiple labels' do @@ -375,14 +269,6 @@ describe IssuesFinder do it 'returns the unique issues with all those labels' do expect(issues).to contain_exactly(issue2) end - - context 'using NOT' do - let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } } - - it 'returns issues that do not have ALL labels provided' do - expect(issues).to contain_exactly(issue1, issue3, issue4) - end - end end context 'filtering by a label that includes any or none in the title' do @@ -390,28 +276,18 @@ describe IssuesFinder do let(:label) { create(:label, title: 'any foo', project: project2) } let(:label2) { create(:label, title: 'bar none', project: project2) } - before do + it 'returns the unique issues with all those labels' do create(:label_link, label: label2, target: issue2) - end - it 'returns the unique issues with all those labels' do expect(issues).to contain_exactly(issue2) end - - context 'using NOT' do - let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } } - - it 'returns issues that do not have ALL labels provided' do - expect(issues).to contain_exactly(issue1, issue3, issue4) - end - end end context 'filtering by no label' do let(:params) { { label_name: described_class::FILTER_NONE } } it 'returns issues with no labels' do - expect(issues).to contain_exactly(issue1, issue4) + expect(issues).to contain_exactly(issue1, issue3, issue4) end end @@ -433,14 +309,6 @@ describe IssuesFinder do it 'returns issues with title and description match for search term' do expect(issues).to contain_exactly(issue1, issue2) end - - context 'using NOT' do - let(:params) { { not: { search: 'git' } } } - - it 'returns issues with no title and description match for search term' do - expect(issues).to contain_exactly(issue3, issue4) - end - end end context 'filtering by issue term in title' do @@ -449,14 +317,6 @@ describe IssuesFinder do it 'returns issues with title match for search term' do expect(issues).to contain_exactly(issue1) end - - context 'using NOT' do - let(:params) { { not: { search: 'git', in: 'title' } } } - - it 'returns issues with no title match for search term' do - expect(issues).to contain_exactly(issue2, issue3, issue4) - end - end end context 'filtering by issues iids' do @@ -465,14 +325,6 @@ describe IssuesFinder do it 'returns issues with iids match' do expect(issues).to contain_exactly(issue3) end - - context 'using NOT' do - let(:params) { { not: { iids: issue3.iid } } } - - it 'returns issues with no iids match' do - expect(issues).to contain_exactly(issue1, issue2, issue4) - end - end end context 'filtering by state' do @@ -614,14 +466,6 @@ describe IssuesFinder do it 'returns issues that the user thumbsup to' do expect(issues).to contain_exactly(issue1) end - - context 'using NOT' do - let(:params) { { not: { my_reaction_emoji: 'thumbsup' } } } - - it 'returns issues that the user did not thumbsup to' do - expect(issues).to contain_exactly(issue2, issue3, issue4) - end - end end context 'user2 searches by "thumbsup" reaction' do @@ -632,14 +476,6 @@ describe IssuesFinder do it 'returns issues that the user2 thumbsup to' do expect(issues).to contain_exactly(issue2) end - - context 'using NOT' do - let(:params) { { not: { my_reaction_emoji: 'thumbsup' } } } - - it 'returns issues that the user2 thumbsup to' do - expect(issues).to contain_exactly(issue3) - end - end end context 'user searches by "thumbsdown" reaction' do @@ -648,14 +484,6 @@ describe IssuesFinder do it 'returns issues that the user thumbsdown to' do expect(issues).to contain_exactly(issue3) end - - context 'using NOT' do - let(:params) { { not: { my_reaction_emoji: 'thumbsdown' } } } - - it 'returns issues that the user thumbsdown to' do - expect(issues).to contain_exactly(issue1, issue2, issue4) - end - end end end diff --git a/spec/fixtures/api/schemas/public_api/v4/release.json b/spec/fixtures/api/schemas/public_api/v4/release.json index 662e61a9c06..078b1c0b982 100644 --- a/spec/fixtures/api/schemas/public_api/v4/release.json +++ b/spec/fixtures/api/schemas/public_api/v4/release.json @@ -15,10 +15,7 @@ "author": { "oneOf": [{ "type": "null" }, { "$ref": "user/basic.json" }] }, - "milestones": { - "type": "array", - "items": { "$ref": "milestone.json" } - }, + "milestone": { "type": "string" }, "assets": { "required": ["count", "links", "sources"], "properties": { diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js index 80816faa5fc..517d8781600 100644 --- a/spec/frontend/clusters/clusters_bundle_spec.js +++ b/spec/frontend/clusters/clusters_bundle_spec.js @@ -11,6 +11,8 @@ import { loadHTMLFixture } from 'helpers/fixtures'; import { setTestTimeout } from 'helpers/timeout'; import $ from 'jquery'; +jest.mock('~/lib/utils/poll'); + const { INSTALLING, INSTALLABLE, INSTALLED, UNINSTALLING } = APPLICATION_STATUS; describe('Clusters', () => { @@ -44,6 +46,17 @@ describe('Clusters', () => { mock.restore(); }); + describe('class constructor', () => { + beforeEach(() => { + jest.spyOn(Clusters.prototype, 'initPolling'); + cluster = new Clusters(); + }); + + it('should call initPolling on construct', () => { + expect(cluster.initPolling).toHaveBeenCalled(); + }); + }); + describe('toggle', () => { it('should update the button and the input field on click', done => { const toggleButton = document.querySelector( @@ -327,14 +340,31 @@ describe('Clusters', () => { }); }); - describe('handleSuccess', () => { + describe('fetch cluster environments success', () => { + beforeEach(() => { + jest.spyOn(cluster.store, 'toggleFetchEnvironments').mockReturnThis(); + jest.spyOn(cluster.store, 'updateEnvironments').mockReturnThis(); + + cluster.handleClusterEnvironmentsSuccess({ data: {} }); + }); + + it('toggles the cluster environments loading icon', () => { + expect(cluster.store.toggleFetchEnvironments).toHaveBeenCalled(); + }); + + it('updates the store when cluster environments is retrieved', () => { + expect(cluster.store.updateEnvironments).toHaveBeenCalled(); + }); + }); + + describe('handleClusterStatusSuccess', () => { beforeEach(() => { jest.spyOn(cluster.store, 'updateStateFromServer').mockReturnThis(); jest.spyOn(cluster, 'toggleIngressDomainHelpText').mockReturnThis(); jest.spyOn(cluster, 'checkForNewInstalls').mockReturnThis(); jest.spyOn(cluster, 'updateContainer').mockReturnThis(); - cluster.handleSuccess({ data: {} }); + cluster.handleClusterStatusSuccess({ data: {} }); }); it('updates clusters store', () => { diff --git a/spec/frontend/create_cluster/eks_cluster/components/cluster_form_dropdown_spec.js b/spec/frontend/create_cluster/eks_cluster/components/cluster_form_dropdown_spec.js deleted file mode 100644 index e873ef0b2fa..00000000000 --- a/spec/frontend/create_cluster/eks_cluster/components/cluster_form_dropdown_spec.js +++ /dev/null @@ -1,137 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; - -import ClusterFormDropdown from '~/create_cluster/eks_cluster/components/cluster_form_dropdown.vue'; -import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue'; -import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue'; -import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue'; - -describe('ClusterFormDropdown', () => { - let vm; - - beforeEach(() => { - vm = shallowMount(ClusterFormDropdown); - }); - afterEach(() => vm.destroy()); - - describe('when no item is selected', () => { - it('displays placeholder text', () => { - const placeholder = 'placeholder'; - - vm.setProps({ placeholder }); - - expect(vm.find(DropdownButton).props('toggleText')).toEqual(placeholder); - }); - }); - - describe('when an item is selected', () => { - const selectedItem = { name: 'Name', value: 'value' }; - - beforeEach(() => { - vm.setData({ selectedItem }); - }); - - it('displays selected item label', () => { - expect(vm.find(DropdownButton).props('toggleText')).toEqual(selectedItem.name); - }); - - it('sets selected value to dropdown hidden input', () => { - expect(vm.find(DropdownHiddenInput).props('value')).toEqual(selectedItem.value); - }); - }); - - describe('when an item is selected and has a custom label property', () => { - it('displays selected item custom label', () => { - const labelProperty = 'customLabel'; - const selectedItem = { [labelProperty]: 'Name' }; - - vm.setProps({ labelProperty }); - vm.setData({ selectedItem }); - - expect(vm.find(DropdownButton).props('toggleText')).toEqual(selectedItem[labelProperty]); - }); - }); - - describe('when loading', () => { - it('dropdown button isLoading', () => { - vm.setProps({ loading: true }); - - expect(vm.find(DropdownButton).props('isLoading')).toBe(true); - }); - }); - - describe('when loading and loadingText is provided', () => { - it('uses loading text as toggle button text', () => { - const loadingText = 'loading text'; - - vm.setProps({ loading: true, loadingText }); - - expect(vm.find(DropdownButton).props('toggleText')).toEqual(loadingText); - }); - }); - - describe('when disabled', () => { - it('dropdown button isDisabled', () => { - vm.setProps({ disabled: true }); - - expect(vm.find(DropdownButton).props('isDisabled')).toBe(true); - }); - }); - - describe('when disabled and disabledText is provided', () => { - it('uses disabled text as toggle button text', () => { - const disabledText = 'disabled text'; - - vm.setProps({ disabled: true, disabledText }); - - expect(vm.find(DropdownButton).props('toggleText')).toBe(disabledText); - }); - }); - - describe('when has errors', () => { - it('sets border-danger class selector to dropdown toggle', () => { - vm.setProps({ hasErrors: true }); - - expect(vm.find(DropdownButton).classes('border-danger')).toBe(true); - }); - }); - - describe('when has errors and an error message', () => { - it('displays error message', () => { - const errorMessage = 'error message'; - - vm.setProps({ hasErrors: true, errorMessage }); - - expect(vm.find('.js-eks-dropdown-error-message').text()).toEqual(errorMessage); - }); - }); - - describe('when no results are available', () => { - it('displays empty text', () => { - const emptyText = 'error message'; - - vm.setProps({ items: [], emptyText }); - - expect(vm.find('.js-empty-text').text()).toEqual(emptyText); - }); - }); - - it('displays search field placeholder', () => { - const searchFieldPlaceholder = 'Placeholder'; - - vm.setProps({ searchFieldPlaceholder }); - - expect(vm.find(DropdownSearchInput).props('placeholderText')).toEqual(searchFieldPlaceholder); - }); - - it('it filters results by search query', () => { - const secondItem = { name: 'second item' }; - const items = [{ name: 'first item' }, secondItem]; - const searchQuery = 'second'; - - vm.setProps({ items }); - vm.setData({ searchQuery }); - - expect(vm.findAll('.js-dropdown-item').length).toEqual(1); - expect(vm.find('.js-dropdown-item').text()).toEqual(secondItem.name); - }); -}); diff --git a/spec/frontend/create_cluster/eks_cluster/components/role_name_dropdown_spec.js b/spec/frontend/create_cluster/eks_cluster/components/role_name_dropdown_spec.js deleted file mode 100644 index 657637c1b56..00000000000 --- a/spec/frontend/create_cluster/eks_cluster/components/role_name_dropdown_spec.js +++ /dev/null @@ -1,43 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; - -import ClusterFormDropdown from '~/create_cluster/eks_cluster/components/cluster_form_dropdown.vue'; -import RoleNameDropdown from '~/create_cluster/eks_cluster/components/role_name_dropdown.vue'; - -describe('RoleNameDropdown', () => { - let vm; - - beforeEach(() => { - vm = shallowMount(RoleNameDropdown); - }); - afterEach(() => vm.destroy()); - - it('renders a cluster-form-dropdown', () => { - expect(vm.find(ClusterFormDropdown).exists()).toBe(true); - }); - - it('sets roles to cluster-form-dropdown items property', () => { - const roles = [{ name: 'basic' }]; - - vm.setProps({ roles }); - - expect(vm.find(ClusterFormDropdown).props('items')).toEqual(roles); - }); - - it('sets a loading text', () => { - expect(vm.find(ClusterFormDropdown).props('loadingText')).toEqual('Loading IAM Roles'); - }); - - it('sets a placeholder', () => { - expect(vm.find(ClusterFormDropdown).props('placeholder')).toEqual('Select role name'); - }); - - it('sets an empty results text', () => { - expect(vm.find(ClusterFormDropdown).props('emptyText')).toEqual('No IAM Roles found'); - }); - - it('sets a search field placeholder', () => { - expect(vm.find(ClusterFormDropdown).props('searchFieldPlaceholder')).toEqual( - 'Search IAM Roles', - ); - }); -}); diff --git a/spec/frontend/fixtures/application_settings.rb b/spec/frontend/fixtures/application_settings.rb index afe5949ed3b..38a060580c1 100644 --- a/spec/frontend/fixtures/application_settings.rb +++ b/spec/frontend/fixtures/application_settings.rb @@ -26,7 +26,7 @@ describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', type: :c it 'application_settings/accounts_and_limit.html' do stub_application_setting(user_default_external: false) - get :general + get :show expect(response).to be_successful end diff --git a/spec/frontend/jobs/store/utils_spec.js b/spec/frontend/jobs/store/utils_spec.js index 7b484ccfa07..1b96f95b5a5 100644 --- a/spec/frontend/jobs/store/utils_spec.js +++ b/spec/frontend/jobs/store/utils_spec.js @@ -28,12 +28,6 @@ describe('Jobs Store Utils', () => { content: [{ text: 'Pulling docker image postgres:9.6.14 ...', style: 'term-fg-l-green' }], sections: ['prepare-executor'], }, - { - offset: 1005, - content: [], - sections: ['prepare-executor'], - section_duration: '10:00', - }, ]; let result; @@ -64,16 +58,6 @@ describe('Jobs Store Utils', () => { expect(result[1].lines[1].content).toEqual(mockData[3].content); }); }); - - describe('section duration', () => { - it('adds the section information to the header section', () => { - expect(result[1].section_duration).toEqual(mockData[4].section_duration); - }); - - it('does not add section duration as a line', () => { - expect(result[1].lines.includes(mockData[4])).toEqual(false); - }); - }); }); describe('updateIncrementalTrace', () => { diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js index f582729d773..d3c8cf72376 100644 --- a/spec/frontend/notes/components/discussion_actions_spec.js +++ b/spec/frontend/notes/components/discussion_actions_spec.js @@ -7,6 +7,18 @@ import ResolveDiscussionButton from '~/notes/components/discussion_resolve_butto import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue'; import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue'; +// NOTE: clone mock_data so that it is not accidentally mutated +const createDiscussionMock = (props = {}) => + Object.assign(JSON.parse(JSON.stringify(discussionMock)), props); +const createNoteMock = (props = {}) => + Object.assign(JSON.parse(JSON.stringify(discussionMock.notes[0])), props); +const createResolvableNote = () => + createNoteMock({ resolvable: true, current_user: { can_resolve: true } }); +const createUnresolvableNote = () => + createNoteMock({ resolvable: false, current_user: { can_resolve: false } }); +const createUnallowedNote = () => + createNoteMock({ resolvable: true, current_user: { can_resolve: false } }); + describe('DiscussionActions', () => { let wrapper; const createComponentFactory = (shallow = true) => props => { @@ -66,13 +78,23 @@ describe('DiscussionActions', () => { expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false); }); - it('does not renders discussion button for non-member', () => { - const discussion = JSON.parse(JSON.stringify(discussionMock)); - discussion.notes[1].current_user.can_resolve = false; - createComponent({ discussion }); - - expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false); - expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false); + describe.each` + desc | notes | shouldRender + ${'with no notes'} | ${[]} | ${true} + ${'with resolvable notes'} | ${[createResolvableNote(), createResolvableNote()]} | ${true} + ${'with unresolvable notes'} | ${[createResolvableNote(), createUnresolvableNote()]} | ${true} + ${'with unallowed note'} | ${[createResolvableNote(), createUnallowedNote()]} | ${false} + `('$desc', ({ notes, shouldRender }) => { + beforeEach(() => { + createComponent({ + discussion: createDiscussionMock({ notes }), + }); + }); + + it(shouldRender ? 'renders resolve buttons' : 'does not render resolve buttons', () => { + expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(shouldRender); + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(shouldRender); + }); }); }); diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 2f481e237a7..4a3ff7e0095 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' describe ApplicationHelper do diff --git a/spec/helpers/defer_script_tag_helper_spec.rb b/spec/helpers/defer_script_tag_helper_spec.rb index 9ada3ae75ba..d10b6f134e4 100644 --- a/spec/helpers/defer_script_tag_helper_spec.rb +++ b/spec/helpers/defer_script_tag_helper_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' describe DeferScriptTagHelper do diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js index 11352140ba4..36bd7ada4f0 100644 --- a/spec/javascripts/boards/boards_store_spec.js +++ b/spec/javascripts/boards/boards_store_spec.js @@ -1,5 +1,7 @@ +/* eslint-disable no-unused-vars */ /* global ListIssue */ +import Vue from 'vue'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; import Cookies from 'js-cookie'; @@ -188,7 +190,7 @@ describe('Store', () => { it('moves the position of lists', () => { const listOne = boardsStore.addList(listObj); - boardsStore.addList(listObjDuplicate); + const listTwo = boardsStore.addList(listObjDuplicate); expect(boardsStore.state.lists.length).toBe(2); diff --git a/spec/javascripts/jobs/components/log/duration_badge_spec.js b/spec/javascripts/jobs/components/log/duration_badge_spec.js deleted file mode 100644 index 2ac34e78909..00000000000 --- a/spec/javascripts/jobs/components/log/duration_badge_spec.js +++ /dev/null @@ -1,31 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import DurationBadge from '~/jobs/components/log/duration_badge.vue'; - -describe('Job Log Duration Badge', () => { - let wrapper; - - const data = { - duration: '00:30:01', - }; - - const createComponent = (props = {}) => { - wrapper = shallowMount(DurationBadge, { - sync: false, - propsData: { - ...props, - }, - }); - }; - - beforeEach(() => { - createComponent(data); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('renders provided duration', () => { - expect(wrapper.text()).toBe(data.duration); - }); -}); diff --git a/spec/javascripts/jobs/components/log/line_header_spec.js b/spec/javascripts/jobs/components/log/line_header_spec.js index 2d2f92fad9d..4efd412a6cd 100644 --- a/spec/javascripts/jobs/components/log/line_header_spec.js +++ b/spec/javascripts/jobs/components/log/line_header_spec.js @@ -1,7 +1,6 @@ import { mount } from '@vue/test-utils'; import LineHeader from '~/jobs/components/log/line_header.vue'; import LineNumber from '~/jobs/components/log/line_number.vue'; -import DurationBadge from '~/jobs/components/log/duration_badge.vue'; describe('Job Log Header Line', () => { let wrapper; @@ -82,14 +81,4 @@ describe('Job Log Header Line', () => { expect(wrapper.emitted().toggleLine.length).toBe(1); }); }); - - describe('with duration', () => { - beforeEach(() => { - createComponent(Object.assign({}, data, { duration: '00:10' })); - }); - - it('renders the duration badge', () => { - expect(wrapper.contains(DurationBadge)).toBe(true); - }); - }); }); diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js index c0a999cfaa6..ce453d7c483 100644 --- a/spec/javascripts/test_bundle.js +++ b/spec/javascripts/test_bundle.js @@ -210,7 +210,7 @@ if (process.env.BABEL_ENV === 'coverage') { './terminal/terminal_bundle.js', './users/users_bundle.js', './issue_show/index.js', - './pages/admin/application_settings/general/index.js', + './pages/admin/application_settings/show/index.js', ]; describe('Uncovered files', function() { diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb index 47ea273ef3a..7eb63fea413 100644 --- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb @@ -34,7 +34,7 @@ describe Banzai::Pipeline::GfmPipeline do result = described_class.call(markdown, project: project)[:output] link = result.css('a').first - expect(link['href']).to eq 'http://issues.example.com/issues/12' + expect(link['href']).to eq 'http://issue-tracker.example.com/issues/12' end it 'parses cross-project references to regular issues' do @@ -63,7 +63,7 @@ describe Banzai::Pipeline::GfmPipeline do result = described_class.call(markdown, project: project)[:output] link = result.css('a').first - expect(link['href']).to eq 'http://issues.example.com/issues/12' + expect(link['href']).to eq 'http://issue-tracker.example.com/issues/12' end it 'allows to use long external reference syntax for Redmine' do @@ -72,7 +72,7 @@ describe Banzai::Pipeline::GfmPipeline do result = described_class.call(markdown, project: project)[:output] link = result.css('a').first - expect(link['href']).to eq 'http://issues.example.com/issues/12' + expect(link['href']).to eq 'http://issue-tracker.example.com/issues/12' end it 'parses cross-project references to regular issues' do diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb index 6c2b338bfcd..bc5fddd12ba 100644 --- a/spec/lib/container_registry/client_spec.rb +++ b/spec/lib/container_registry/client_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/lib/gitlab/background_migration/add_gitlab_instance_administration_project_spec.rb b/spec/lib/gitlab/background_migration/add_gitlab_instance_administration_project_spec.rb deleted file mode 100644 index 76062b191a8..00000000000 --- a/spec/lib/gitlab/background_migration/add_gitlab_instance_administration_project_spec.rb +++ /dev/null @@ -1,234 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Gitlab::BackgroundMigration::AddGitlabInstanceAdministrationProject, :migration, schema: 20190725080128 do - let(:application_settings) { table(:application_settings) } - let(:users) { table(:users) } - let(:projects) { table(:projects) } - let(:namespaces) { table(:namespaces) } - let(:members) { table(:members) } - - let(:service_class) do - Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService - end - - let(:prometheus_settings) do - { - enable: true, - listen_address: 'localhost:9090' - } - end - - before do - stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - - stub_config(prometheus: prometheus_settings) - end - - describe 'perform' do - context 'without application_settings' do - it 'does not fail' do - subject.perform - - expect(Project.count).to eq(0) - end - end - - context 'without admin users' do - let!(:application_setting) { application_settings.create! } - - it 'does not fail' do - subject.perform - - expect(Project.count).to eq(0) - end - end - - context 'with admin users' do - let(:project) { Project.last } - let(:group) { Group.last } - let!(:application_setting) { application_settings.create! } - let!(:user) { users.create!(admin: true, email: 'admin1@example.com', projects_limit: 10, state: :active) } - - before do - stub_application_setting(allow_local_requests_from_web_hooks_and_services: true) - end - - shared_examples 'has prometheus service' do |listen_address| - it do - subject.perform - - prometheus = project.prometheus_service - expect(prometheus).to be_persisted - expect(prometheus).not_to eq(nil) - expect(prometheus.api_url).to eq(listen_address) - expect(prometheus.active).to eq(true) - expect(prometheus.manual_configuration).to eq(true) - end - end - - it_behaves_like 'has prometheus service', 'http://localhost:9090' - - it 'creates GitLab Instance Administrator group' do - subject.perform - - expect(group).to be_persisted - expect(group.name).to eq('GitLab Instance Administrators') - expect(group.path).to start_with('gitlab-instance-administrators') - expect(group.path.split('-').last.length).to eq(8) - expect(group.visibility_level).to eq(service_class::VISIBILITY_LEVEL) - end - - it 'creates project with internal visibility' do - subject.perform - - expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL) - expect(project).to be_persisted - end - - it 'creates project with correct name and description' do - subject.perform - - path = 'administration/monitoring/gitlab_instance_administration_project/index' - docs_path = Rails.application.routes.url_helpers.help_page_path(path) - - expect(project.name).to eq(service_class::PROJECT_NAME) - expect(project.description).to eq( - 'This project is automatically generated and will be used to help monitor this GitLab instance. ' \ - "[More information](#{docs_path})" - ) - expect(File).to exist("doc/#{path}.md") - end - - it 'adds all admins as maintainers' do - admin1 = users.create!(admin: true, email: 'admin2@example.com', projects_limit: 10, state: :active) - admin2 = users.create!(admin: true, email: 'admin3@example.com', projects_limit: 10, state: :active) - users.create!(email: 'nonadmin1@example.com', projects_limit: 10, state: :active) - - subject.perform - - expect(project.owner).to eq(group) - expect(group.members.collect(&:user).collect(&:id)).to contain_exactly(user.id, admin1.id, admin2.id) - expect(group.members.collect(&:access_level)).to contain_exactly( - Gitlab::Access::OWNER, - Gitlab::Access::MAINTAINER, - Gitlab::Access::MAINTAINER - ) - end - - it 'saves the project id' do - subject.perform - - application_setting.reload - expect(application_setting.instance_administration_project_id).to eq(project.id) - end - - it 'does not fail when a project already exists' do - group = namespaces.create!( - path: 'gitlab-instance-administrators', - name: 'GitLab Instance Administrators', - type: 'Group' - ) - project = projects.create!( - namespace_id: group.id, - name: 'GitLab Instance Administration' - ) - - admin1 = users.create!(admin: true, email: 'admin4@example.com', projects_limit: 10, state: :active) - admin2 = users.create!(admin: true, email: 'admin5@example.com', projects_limit: 10, state: :active) - - members.create!( - user_id: admin1.id, - source_id: group.id, - source_type: 'Namespace', - type: 'GroupMember', - access_level: GroupMember::MAINTAINER, - notification_level: NotificationSetting.levels[:global] - ) - members.create!( - user_id: admin2.id, - source_id: group.id, - source_type: 'Namespace', - type: 'GroupMember', - access_level: GroupMember::MAINTAINER, - notification_level: NotificationSetting.levels[:global] - ) - - stub_application_setting(instance_administration_project: project) - - subject.perform - - expect(Project.last.id).to eq(project.id) - expect(Group.last.id).to eq(group.id) - end - - context 'when local requests from hooks and services are not allowed' do - before do - stub_application_setting(allow_local_requests_from_web_hooks_and_services: false) - end - - it_behaves_like 'has prometheus service', 'http://localhost:9090' - - it 'does not overwrite the existing whitelist' do - application_setting.update!(outbound_local_requests_whitelist: ['example.com']) - - subject.perform - - application_setting.reload - expect(application_setting.outbound_local_requests_whitelist).to contain_exactly( - 'example.com', 'localhost' - ) - end - end - - context 'with non default prometheus address' do - let(:prometheus_settings) do - { - enable: true, - listen_address: 'https://localhost:9090' - } - end - - it_behaves_like 'has prometheus service', 'https://localhost:9090' - end - - context 'when prometheus setting is not present in gitlab.yml' do - before do - allow(Gitlab.config).to receive(:prometheus).and_raise(Settingslogic::MissingSetting) - end - - it 'does not fail' do - subject.perform - - expect(project.prometheus_service).to be_nil - end - end - - context 'when prometheus setting is disabled in gitlab.yml' do - let(:prometheus_settings) do - { - enable: false, - listen_address: 'localhost:9090' - } - end - - it 'does not configure prometheus' do - subject.perform - - expect(project.prometheus_service).to be_nil - end - end - - context 'when prometheus listen address is blank in gitlab.yml' do - let(:prometheus_settings) { { enable: true, listen_address: '' } } - - it 'does not configure prometheus' do - subject.perform - - expect(project.prometheus_service).to be_nil - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/build/step_spec.rb b/spec/lib/gitlab/ci/build/step_spec.rb index 9c1a8cf5e91..84e6e0e177f 100644 --- a/spec/lib/gitlab/ci/build/step_spec.rb +++ b/spec/lib/gitlab/ci/build/step_spec.rb @@ -4,49 +4,39 @@ require 'spec_helper' describe Gitlab::Ci::Build::Step do describe '#from_commands' do - subject { described_class.from_commands(job) } + shared_examples 'has correct script' do + subject { described_class.from_commands(job) } - before do - job.run! - end + before do + job.run! + end - shared_examples 'has correct script' do it 'fabricates an object' do expect(subject.name).to eq(:script) expect(subject.script).to eq(script) + expect(subject.timeout).to eq(job.metadata_timeout) expect(subject.when).to eq('on_success') expect(subject.allow_failure).to be_falsey end end context 'when script option is specified' do - let(:job) { create(:ci_build, :no_options, options: { script: ["ls -la\necho aaa", "date"] }) } - let(:script) { ["ls -la\necho aaa", 'date'] } - - it_behaves_like 'has correct script' - end - - context 'when before and script option is specified' do - let(:job) do - create(:ci_build, options: { - before_script: ["ls -la\necho aaa"], - script: ["date"] - }) + it_behaves_like 'has correct script' do + let(:job) { create(:ci_build, :no_options, options: { script: ["ls -la\necho aaa", "date"] }) } + let(:script) { ["ls -la\necho aaa", 'date'] } end - - let(:script) { ["ls -la\necho aaa", 'date'] } - - it_behaves_like 'has correct script' end - context 'when timeout option is specified in seconds' do - let(:job) { create(:ci_build, options: { job_timeout: 3, script: ["ls -la\necho aaa", 'date'] }) } - let(:script) { ["ls -la\necho aaa", 'date'] } - - it_behaves_like 'has correct script' - - it 'has job level timeout' do - expect(subject.timeout).to eq(3) + context 'when before and script option is specified' do + it_behaves_like 'has correct script' do + let(:job) do + create(:ci_build, options: { + before_script: ["ls -la\necho aaa"], + script: ["date"] + }) + end + + let(:script) { ["ls -la\necho aaa", 'date'] } end end end @@ -67,12 +57,12 @@ describe Gitlab::Ci::Build::Step do end context 'when after_script is not empty' do - let(:job) { create(:ci_build, options: { job_timeout: 60, script: ['bash'], after_script: ['ls -la', 'date'] }) } + let(:job) { create(:ci_build, options: { script: ['bash'], after_script: ['ls -la', 'date'] }) } it 'fabricates an object' do expect(subject.name).to eq(:after_script) expect(subject.script).to eq(['ls -la', 'date']) - expect(subject.timeout).to eq(60) + expect(subject.timeout).to eq(job.metadata_timeout) expect(subject.when).to eq('always') expect(subject.allow_failure).to be_truthy end diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index 1c4887e87c4..1853efde350 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -417,37 +417,6 @@ describe Gitlab::Ci::Config::Entry::Job do end end end - - context 'when timeout value is not correct' do - context 'when it is higher than instance wide timeout' do - let(:config) { { timeout: '3 months' } } - - it 'returns error about value too high' do - expect(entry).not_to be_valid - expect(entry.errors) - .to include "job timeout should not exceed the limit" - end - end - - context 'when it is not a duration' do - let(:config) { { timeout: 100 } } - - it 'returns error about wrong value' do - expect(entry).not_to be_valid - expect(entry.errors).to include 'job timeout should be a duration' - end - end - end - - context 'when timeout value is correct' do - let(:config) { { script: 'echo', timeout: '1m 1s' } } - - it 'returns correct timeout' do - expect(entry).to be_valid - expect(entry.errors).to be_empty - expect(entry.timeout).to eq('1m 1s') - end - end end end diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index 8f2f23f6110..9d9a9ecda33 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -1134,48 +1134,6 @@ module Gitlab end end - describe "Timeout" do - let(:config) do - { - deploy_to_production: { - stage: 'deploy', - script: 'test' - } - } - end - - let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) } - let(:builds) { processor.stage_builds_attributes('deploy') } - - context 'when no timeout was provided' do - it 'does not include job_timeout' do - expect(builds.size).to eq(1) - expect(builds.first[:options]).not_to include(:job_timeout) - end - end - - context 'when an invalid timeout was provided' do - before do - config[:deploy_to_production][:timeout] = 'not-a-number' - end - - it 'raises an error for invalid number' do - expect { builds }.to raise_error('jobs:deploy_to_production timeout should be a duration') - end - end - - context 'when some valid timeout was provided' do - before do - config[:deploy_to_production][:timeout] = '1m 3s' - end - - it 'returns provided timeout value' do - expect(builds.size).to eq(1) - expect(builds.first[:options]).to include(job_timeout: 63) - end - end - end - describe "Dependencies" do let(:config) do { diff --git a/spec/lib/gitlab/discussions_diff/file_collection_spec.rb b/spec/lib/gitlab/discussions_diff/file_collection_spec.rb index 6ef1e41450f..0489206458b 100644 --- a/spec/lib/gitlab/discussions_diff/file_collection_spec.rb +++ b/spec/lib/gitlab/discussions_diff/file_collection_spec.rb @@ -22,13 +22,11 @@ describe Gitlab::DiscussionsDiff::FileCollection do note_diff_file_b.id => file_b_caching_content }) .and_call_original - subject.load_highlight + subject.load_highlight([note_diff_file_a.id, note_diff_file_b.id]) end it 'does not write cache for already cached file' do - file_a_caching_content = diff_note_a.diff_file.highlighted_diff_lines.map(&:to_hash) - Gitlab::DiscussionsDiff::HighlightCache - .write_multiple({ note_diff_file_a.id => file_a_caching_content }) + subject.load_highlight([note_diff_file_a.id]) file_b_caching_content = diff_note_b.diff_file.highlighted_diff_lines.map(&:to_hash) @@ -37,42 +35,27 @@ describe Gitlab::DiscussionsDiff::FileCollection do .with({ note_diff_file_b.id => file_b_caching_content }) .and_call_original - subject.load_highlight + subject.load_highlight([note_diff_file_a.id, note_diff_file_b.id]) end - it 'does not write cache for resolved notes' do - diff_note_a.update_column(:resolved_at, Time.now) - - file_b_caching_content = diff_note_b.diff_file.highlighted_diff_lines.map(&:to_hash) - - expect(Gitlab::DiscussionsDiff::HighlightCache) - .to receive(:write_multiple) - .with({ note_diff_file_b.id => file_b_caching_content }) - .and_call_original - - subject.load_highlight + it 'does not err when given ID does not exist in @collection' do + expect { subject.load_highlight([999]) }.not_to raise_error end it 'loaded diff files have highlighted lines loaded' do - subject.load_highlight + subject.load_highlight([note_diff_file_a.id]) - diff_file_a = subject.find_by_id(note_diff_file_a.id) - diff_file_b = subject.find_by_id(note_diff_file_b.id) + diff_file = subject.find_by_id(note_diff_file_a.id) - expect(diff_file_a).to be_highlight_loaded - expect(diff_file_b).to be_highlight_loaded + expect(diff_file.highlight_loaded?).to be(true) end it 'not loaded diff files does not have highlighted lines loaded' do - diff_note_a.update_column(:resolved_at, Time.now) - - subject.load_highlight + subject.load_highlight([note_diff_file_a.id]) - diff_file_a = subject.find_by_id(note_diff_file_a.id) - diff_file_b = subject.find_by_id(note_diff_file_b.id) + diff_file = subject.find_by_id(note_diff_file_b.id) - expect(diff_file_a).not_to be_highlight_loaded - expect(diff_file_b).to be_highlight_loaded + expect(diff_file.highlight_loaded?).to be(false) end end end diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb index fc08719fb33..b24b71522ec 100644 --- a/spec/lib/gitlab/encoding_helper_spec.rb +++ b/spec/lib/gitlab/encoding_helper_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require "spec_helper" diff --git a/spec/lib/gitlab/etag_caching/router_spec.rb b/spec/lib/gitlab/etag_caching/router_spec.rb index fbc49d894a6..8fcd4eb3c21 100644 --- a/spec/lib/gitlab/etag_caching/router_spec.rb +++ b/spec/lib/gitlab/etag_caching/router_spec.rb @@ -92,6 +92,15 @@ describe Gitlab::EtagCaching::Router do expect(result).to be_blank end + it 'matches the cluster environments path' do + result = described_class.match( + '/my-group/my-project/-/clusters/47/environments' + ) + + expect(result).to be_present + expect(result.name).to eq 'cluster_environments' + end + it 'matches the environments path' do result = described_class.match( '/my-group/my-project/environments.json' diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb index ac085e2c266..0010c0304eb 100644 --- a/spec/lib/gitlab/git/blame_spec.rb +++ b/spec/lib/gitlab/git/blame_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require "spec_helper" describe Gitlab::Git::Blame, :seed_helper do diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb index 7f680071969..1c24244c3a6 100644 --- a/spec/lib/gitlab/git/blob_spec.rb +++ b/spec/lib/gitlab/git/blob_spec.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 + require "spec_helper" describe Gitlab::Git::Blob, :seed_helper do diff --git a/spec/lib/gitlab/git/conflict/file_spec.rb b/spec/lib/gitlab/git/conflict/file_spec.rb index a6cabd4966a..afed6c32af6 100644 --- a/spec/lib/gitlab/git/conflict/file_spec.rb +++ b/spec/lib/gitlab/git/conflict/file_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' describe Gitlab::Git::Conflict::File do diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index e455c4c99ab..dccd50bc472 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require "spec_helper" describe Gitlab::Git::Repository, :seed_helper do diff --git a/spec/lib/gitlab/git_spec.rb b/spec/lib/gitlab/git_spec.rb index 505bc470644..6515be85ae3 100644 --- a/spec/lib/gitlab/git_spec.rb +++ b/spec/lib/gitlab/git_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' describe Gitlab::Git do diff --git a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb index 97a89b319ea..569d5dcc757 100644 --- a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb +++ b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb @@ -42,15 +42,7 @@ describe Gitlab::HookData::IssuableBuilder do [{ id: 1, title: 'foo' }], [{ id: 1, title: 'foo' }, { id: 2, title: 'bar' }] ], - total_time_spent: [1, 2], - assignees: [ - [], - [{ - name: "Foo Bar", - username: "foobar", - avatar_url: "http://www.example.com/my-avatar.jpg" - }] - ] + total_time_spent: [1, 2] } end let(:data) { builder.build(user: user, changes: changes) } @@ -66,14 +58,6 @@ describe Gitlab::HookData::IssuableBuilder do total_time_spent: { previous: 1, current: 2 - }, - assignees: { - previous: [], - current: [{ - name: "Foo Bar", - username: "foobar", - avatar_url: "http://www.example.com/my-avatar.jpg" - }] } })) end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index d3be1e86539..6d573a4f39a 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -65,8 +65,8 @@ milestone: - participants - events - boards -- milestone_releases -- releases +- milestone_release +- release snippets: - author - project @@ -77,8 +77,8 @@ releases: - author - project - links -- milestone_releases -- milestones +- milestone_release +- milestone links: - release project_members: diff --git a/spec/lib/gitlab/json_logger_spec.rb b/spec/lib/gitlab/json_logger_spec.rb index 3d4f9b5db86..d3d9fe9948a 100644 --- a/spec/lib/gitlab/json_logger_spec.rb +++ b/spec/lib/gitlab/json_logger_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 require 'spec_helper' describe Gitlab::JsonLogger do diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb index 0829a2b4334..7dcdad7ff92 100644 --- a/spec/lib/gitlab/path_regex_spec.rb +++ b/spec/lib/gitlab/path_regex_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/lib/gitlab/popen_spec.rb b/spec/lib/gitlab/popen_spec.rb index b398381a7e0..29afd9df74e 100644 --- a/spec/lib/gitlab/popen_spec.rb +++ b/spec/lib/gitlab/popen_spec.rb @@ -87,12 +87,4 @@ describe Gitlab::Popen do it { expect(@status).to be_zero } it { expect(@output).to eq('hello') } end - - context 'when binary is absent' do - it 'raises error' do - expect do - @klass.new.popen(%w[foobar]) - end.to raise_error - end - end end diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index d6e50c672e6..e0b9581c75c 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb index 3036e3a9754..e19210d8fbf 100644 --- a/spec/lib/gitlab/regex_spec.rb +++ b/spec/lib/gitlab/regex_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/lib/gitlab/search/found_blob_spec.rb b/spec/lib/gitlab/search/found_blob_spec.rb index a575f6e2f11..3496fb29836 100644 --- a/spec/lib/gitlab/search/found_blob_spec.rb +++ b/spec/lib/gitlab/search/found_blob_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb index 0e66e959b24..6ce002ad70e 100644 --- a/spec/lib/gitlab/url_blocker_spec.rb +++ b/spec/lib/gitlab/url_blocker_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 62787c5abaf..8eb64b97d6a 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -3,16 +3,14 @@ require 'spec_helper' describe Gitlab::UsageData do - let(:projects) { create_list(:project, 4) } + let(:projects) { create_list(:project, 3) } let!(:board) { create(:board, project: projects[0]) } describe '#data' do before do create(:jira_service, project: projects[0]) - create(:jira_service, :without_properties_callback, project: projects[1]) + create(:jira_service, project: projects[1]) create(:jira_service, :jira_cloud_service, project: projects[2]) - create(:jira_service, :without_properties_callback, project: projects[3], - properties: { url: 'https://mysite.atlassian.net' }) create(:prometheus_service, project: projects[1]) create(:service, project: projects[0], type: 'SlackSlashCommandsService', active: true) create(:service, project: projects[1], type: 'SlackService', active: true) @@ -158,7 +156,7 @@ describe Gitlab::UsageData do count_data = subject[:counts] expect(count_data[:boards]).to eq(1) - expect(count_data[:projects]).to eq(4) + expect(count_data[:projects]).to eq(3) expect(count_data.keys).to include(*expected_keys) expect(expected_keys - count_data.keys).to be_empty end @@ -166,14 +164,14 @@ describe Gitlab::UsageData do it 'gathers projects data correctly' do count_data = subject[:counts] - expect(count_data[:projects]).to eq(4) + expect(count_data[:projects]).to eq(3) expect(count_data[:projects_prometheus_active]).to eq(1) - expect(count_data[:projects_jira_active]).to eq(4) + expect(count_data[:projects_jira_active]).to eq(3) expect(count_data[:projects_jira_server_active]).to eq(2) - expect(count_data[:projects_jira_cloud_active]).to eq(2) + expect(count_data[:projects_jira_cloud_active]).to eq(1) expect(count_data[:projects_slack_notifications_active]).to eq(2) expect(count_data[:projects_slack_slash_active]).to eq(1) - expect(count_data[:projects_with_repositories_enabled]).to eq(3) + expect(count_data[:projects_with_repositories_enabled]).to eq(2) expect(count_data[:projects_with_error_tracking_enabled]).to eq(1) expect(count_data[:clusters_enabled]).to eq(7) diff --git a/spec/lib/gitlab_danger_spec.rb b/spec/lib/gitlab_danger_spec.rb index 26bf5d76756..623ac20fa7c 100644 --- a/spec/lib/gitlab_danger_spec.rb +++ b/spec/lib/gitlab_danger_spec.rb @@ -9,7 +9,7 @@ describe GitlabDanger do describe '.local_warning_message' do it 'returns an informational message with rules that can run' do - expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, gemfile, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, database, commit_messages') + expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, gemfile, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, database') end end diff --git a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb b/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb deleted file mode 100644 index 67ac40d4d39..00000000000 --- a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' -require Rails.root.join('db', 'post_migrate', '20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb') - -describe MigrateCodeOwnerApprovalStatusToProtectedBranchesInBatches, :migration do - let(:namespaces) { table(:namespaces) } - let(:projects) { table(:projects) } - let(:protected_branches) { table(:protected_branches) } - - let(:namespace) do - namespaces.create!( - path: 'gitlab-instance-administrators', - name: 'GitLab Instance Administrators' - ) - end - - let(:project) do - projects.create!( - namespace_id: namespace.id, - name: 'GitLab Instance Administration' - ) - end - - let!(:protected_branch_1) do - protected_branches.create!( - name: "branch name", - project_id: project.id - ) - end - - describe '#up' do - context "when there's no projects needing approval" do - it "doesn't change any protected branch records" do - expect { migrate! } - .not_to change { ProtectedBranch.where(code_owner_approval_required: true).count } - end - end - - context "when there's a project needing approval" do - let!(:project_needing_approval) do - projects.create!( - namespace_id: namespace.id, - name: 'GitLab Instance Administration', - merge_requests_require_code_owner_approval: true - ) - end - - let!(:protected_branch_2) do - protected_branches.create!( - name: "branch name", - project_id: project_needing_approval.id - ) - end - - it "changes N protected branch records" do - expect { migrate! } - .to change { ProtectedBranch.where(code_owner_approval_required: true).count } - .by(1) - end - end - end -end diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb index 2efab3076d8..62a75bde63b 100644 --- a/spec/models/blob_spec.rb +++ b/spec/models/blob_spec.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb index 67cd939b4c6..917a65ddf21 100644 --- a/spec/models/ci/build_metadata_spec.rb +++ b/spec/models/ci/build_metadata_spec.rb @@ -22,72 +22,42 @@ describe Ci::BuildMetadata do describe '#update_timeout_state' do subject { metadata } - shared_examples 'sets timeout' do |source, timeout| - it 'sets project_timeout_source' do - expect { subject.update_timeout_state }.to change { subject.reload.timeout_source }.to(source) + context 'when runner is not assigned to the job' do + it "doesn't change timeout value" do + expect { subject.update_timeout_state }.not_to change { subject.reload.timeout } end - it 'sets project timeout' do - expect { subject.update_timeout_state }.to change { subject.reload.timeout }.to(timeout) + it "doesn't change timeout_source value" do + expect { subject.update_timeout_state }.not_to change { subject.reload.timeout_source } end end - context 'when project timeout is set' do - context 'when runner is assigned to the job' do - before do - build.update!(runner: runner) - end - - context 'when runner timeout is not set' do - let(:runner) { create(:ci_runner, maximum_timeout: nil) } - - it_behaves_like 'sets timeout', 'project_timeout_source', 2000 - end - - context 'when runner timeout is lower than project timeout' do - let(:runner) { create(:ci_runner, maximum_timeout: 1900) } - - it_behaves_like 'sets timeout', 'runner_timeout_source', 1900 - end - - context 'when runner timeout is higher than project timeout' do - let(:runner) { create(:ci_runner, maximum_timeout: 2100) } - - it_behaves_like 'sets timeout', 'project_timeout_source', 2000 - end + context 'when runner is assigned to the job' do + before do + build.update(runner: runner) end - context 'when job timeout is set' do - context 'when job timeout is higher than project timeout' do - let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) } + context 'when runner timeout is lower than project timeout' do + let(:runner) { create(:ci_runner, maximum_timeout: 1900) } - it_behaves_like 'sets timeout', 'job_timeout_source', 3000 + it 'sets runner timeout' do + expect { subject.update_timeout_state }.to change { subject.reload.timeout }.to(1900) end - context 'when job timeout is lower than project timeout' do - let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1000 }) } - - it_behaves_like 'sets timeout', 'job_timeout_source', 1000 + it 'sets runner_timeout_source' do + expect { subject.update_timeout_state }.to change { subject.reload.timeout_source }.to('runner_timeout_source') end end - context 'when both runner and job timeouts are set' do - before do - build.update(runner: runner) - end - - context 'when job timeout is higher than runner timeout' do - let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) } - let(:runner) { create(:ci_runner, maximum_timeout: 2100) } + context 'when runner timeout is higher than project timeout' do + let(:runner) { create(:ci_runner, maximum_timeout: 2100) } - it_behaves_like 'sets timeout', 'runner_timeout_source', 2100 + it 'sets project timeout' do + expect { subject.update_timeout_state }.to change { subject.reload.timeout }.to(2000) end - context 'when job timeout is lower than runner timeout' do - let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1900 }) } - let(:runner) { create(:ci_runner, maximum_timeout: 2100) } - - it_behaves_like 'sets timeout', 'job_timeout_source', 1900 + it 'sets project_timeout_source' do + expect { subject.update_timeout_state }.to change { subject.reload.timeout_source }.to('project_timeout_source') end end end diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb index f984f6ba0ce..d9461ee8581 100644 --- a/spec/models/clusters/applications/ingress_spec.rb +++ b/spec/models/clusters/applications/ingress_spec.rb @@ -131,4 +131,41 @@ describe Clusters::Applications::Ingress do expect(values).to include('podAnnotations') end end + + describe '#values' do + let(:project) { build(:project) } + let(:cluster) { build(:cluster, projects: [project]) } + + context 'when ingress_modsecurity is enabled' do + before do + stub_feature_flags(ingress_modsecurity: true) + + allow(subject).to receive(:cluster).and_return(cluster) + end + + it 'includes modsecurity module enablement' do + expect(subject.values).to include("enable-modsecurity: 'true'") + end + + it 'includes modsecurity core ruleset enablement' do + expect(subject.values).to include("enable-owasp-modsecurity-crs: 'true'") + end + end + + context 'when ingress_modsecurity is disabled' do + before do + stub_feature_flags(ingress_modsecurity: false) + + allow(subject).to receive(:cluster).and_return(cluster) + end + + it 'excludes modsecurity module enablement' do + expect(subject.values).not_to include('enable-modsecurity') + end + + it 'excludes modsecurity core ruleset enablement' do + expect(subject.values).not_to include('enable-owasp-modsecurity-crs') + end + end + end end diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb index f78a089bc2e..cad705ee594 100644 --- a/spec/models/concerns/routable_spec.rb +++ b/spec/models/concerns/routable_spec.rb @@ -58,7 +58,7 @@ describe Group, 'Routable' do end end - context '.find_by_full_path' do + shared_examples_for '.find_by_full_path' do let!(:nested_group) { create(:group, parent: group) } context 'without any redirect routes' do @@ -117,6 +117,24 @@ describe Group, 'Routable' do end end + describe '.find_by_full_path' do + context 'with routable_two_step_lookup feature' do + before do + stub_feature_flags(routable_two_step_lookup: true) + end + + it_behaves_like '.find_by_full_path' + end + + context 'without routable_two_step_lookup feature' do + before do + stub_feature_flags(routable_two_step_lookup: false) + end + + it_behaves_like '.find_by_full_path' + end + end + describe '.where_full_path_in' do context 'without any paths' do it 'returns an empty relation' do diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 65cc1a4bd6b..fde1b096c76 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -650,35 +650,9 @@ describe MergeRequest do end end - describe '#discussions_diffs' do + describe '#preload_discussions_diff_highlight' do let(:merge_request) { create(:merge_request) } - shared_examples 'discussions diffs collection' do - it 'initializes Gitlab::DiscussionsDiff::FileCollection with correct data' do - note_diff_file = diff_note.note_diff_file - - expect(Gitlab::DiscussionsDiff::FileCollection) - .to receive(:new) - .with([note_diff_file]) - .and_call_original - - result = merge_request.discussions_diffs - - expect(result).to be_a(Gitlab::DiscussionsDiff::FileCollection) - end - - it 'eager loads relations' do - result = merge_request.discussions_diffs - - recorder = ActiveRecord::QueryRecorder.new do - result.first.diff_note - result.first.diff_note.project - end - - expect(recorder.count).to be_zero - end - end - context 'with commit diff note' do let(:other_merge_request) { create(:merge_request) } @@ -690,15 +664,40 @@ describe MergeRequest do create(:diff_note_on_commit, project: other_merge_request.project) end - it_behaves_like 'discussions diffs collection' + it 'preloads diff highlighting' do + expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection| + note_diff_file = diff_note.note_diff_file + + expect(collection) + .to receive(:load_highlight) + .with([note_diff_file.id]).and_call_original + end + + merge_request.preload_discussions_diff_highlight + end end context 'with merge request diff note' do - let!(:diff_note) do + let!(:unresolved_diff_note) do create(:diff_note_on_merge_request, project: merge_request.project, noteable: merge_request) end - it_behaves_like 'discussions diffs collection' + let!(:resolved_diff_note) do + create(:diff_note_on_merge_request, :resolved, project: merge_request.project, noteable: merge_request) + end + + it 'preloads diff highlighting' do + expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection| + note_diff_file = unresolved_diff_note.note_diff_file + + expect(collection) + .to receive(:load_highlight) + .with([note_diff_file.id]) + .and_call_original + end + + merge_request.preload_discussions_diff_highlight + end end end diff --git a/spec/models/milestone_release_spec.rb b/spec/models/milestone_release_spec.rb index 28cec7bbc17..d6f73275977 100644 --- a/spec/models/milestone_release_spec.rb +++ b/spec/models/milestone_release_spec.rb @@ -14,29 +14,23 @@ describe MilestoneRelease do it { is_expected.to belong_to(:release) } end - context 'when trying to create the same record in milestone_releases twice' do - it 'is not committing on the second time' do - create(:milestone_release, milestone: milestone, release: release) - - expect do - subject.save! - end.to raise_error(ActiveRecord::RecordNotUnique) - end - end - describe 'validations' do - subject(:milestone_release) { build(:milestone_release, milestone: milestone, release: release) } + it { is_expected.to validate_uniqueness_of(:milestone_id).scoped_to(:release_id) } context 'when milestone and release do not have the same project' do it 'is not valid' do - milestone_release.release = build(:release, project: create(:project)) - + other_project = create(:project) + release = build(:release, project: other_project) + milestone_release = described_class.new(milestone: milestone, release: release) expect(milestone_release).not_to be_valid end end context 'when milestone and release have the same project' do - it { is_expected.to be_valid } + it 'is valid' do + milestone_release = described_class.new(milestone: milestone, release: release) + expect(milestone_release).to be_valid + end end end end diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index 0c4952eebd7..64030f5b92a 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -55,20 +55,20 @@ describe Milestone do end end - describe 'milestone_releases' do + describe 'milestone_release' do let(:milestone) { build(:milestone, project: project) } context 'when it is tied to a release for another project' do it 'creates a validation error' do other_project = create(:project) - milestone.releases << build(:release, project: other_project) + milestone.release = build(:release, project: other_project) expect(milestone).not_to be_valid end end context 'when it is tied to a release for the same project' do it 'is valid' do - milestone.releases << build(:release, project: project) + milestone.release = build(:release, project: project) expect(milestone).to be_valid end end @@ -78,8 +78,7 @@ describe Milestone do describe "Associations" do it { is_expected.to belong_to(:project) } it { is_expected.to have_many(:issues) } - it { is_expected.to have_many(:releases) } - it { is_expected.to have_many(:milestone_releases) } + it { is_expected.to have_one(:release) } end let(:project) { create(:project, :public) } diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb index e25d87f61d6..74c85a13c88 100644 --- a/spec/models/project_services/bugzilla_service_spec.rb +++ b/spec/models/project_services/bugzilla_service_spec.rb @@ -48,7 +48,7 @@ describe BugzillaService do create(:bugzilla_service, :without_properties_callback, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in separated fields' do @@ -56,7 +56,7 @@ describe BugzillaService do create(:bugzilla_service, title: title, description: description, properties: access_params) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in both properties and separated fields' do @@ -65,7 +65,7 @@ describe BugzillaService do create(:bugzilla_service, :without_properties_callback, title: title, description: description, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when no title & description are set' do diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb index 8359bc6807a..5259357a254 100644 --- a/spec/models/project_services/custom_issue_tracker_service_spec.rb +++ b/spec/models/project_services/custom_issue_tracker_service_spec.rb @@ -62,7 +62,7 @@ describe CustomIssueTrackerService do create(:custom_issue_tracker_service, :without_properties_callback, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in separated fields' do @@ -70,7 +70,7 @@ describe CustomIssueTrackerService do create(:custom_issue_tracker_service, title: title, description: description, properties: access_params) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in both properties and separated fields' do @@ -79,7 +79,7 @@ describe CustomIssueTrackerService do create(:custom_issue_tracker_service, :without_properties_callback, title: title, description: description, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when no title & description are set' do diff --git a/spec/models/project_services/data_fields_spec.rb b/spec/models/project_services/data_fields_spec.rb deleted file mode 100644 index 146db0ae227..00000000000 --- a/spec/models/project_services/data_fields_spec.rb +++ /dev/null @@ -1,138 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe DataFields do - let(:url) { 'http://url.com' } - let(:username) { 'username_one' } - let(:properties) do - { url: url, username: username } - end - - shared_examples 'data fields' do - describe '#arg' do - it 'returns an argument correctly' do - expect(service.url).to eq(url) - end - end - - describe '{arg}_changed?' do - it 'returns false when the property has not been assigned a new value' do - service.username = 'new_username' - service.validate - expect(service.url_changed?).to be_falsy - end - - it 'returns true when the property has been assigned a different value' do - service.url = "http://example.com" - service.validate - expect(service.url_changed?).to be_truthy - end - - it 'returns true when the property has been assigned a different value twice' do - service.url = "http://example.com" - service.url = "http://example.com" - service.validate - expect(service.url_changed?).to be_truthy - end - - it 'returns false when the property has been re-assigned the same value' do - service.url = 'http://url.com' - service.validate - expect(service.url_changed?).to be_falsy - end - end - - describe '{arg}_touched?' do - it 'returns false when the property has not been assigned a new value' do - service.username = 'new_username' - service.validate - expect(service.url_changed?).to be_falsy - end - - it 'returns true when the property has been assigned a different value' do - service.url = "http://example.com" - service.validate - expect(service.url_changed?).to be_truthy - end - - it 'returns true when the property has been assigned a different value twice' do - service.url = "http://example.com" - service.url = "http://example.com" - service.validate - expect(service.url_changed?).to be_truthy - end - - it 'returns true when the property has been re-assigned the same value' do - service.url = 'http://url.com' - expect(service.url_touched?).to be_truthy - end - - it 'returns false when the property has been re-assigned the same value' do - service.url = 'http://url.com' - service.validate - expect(service.url_changed?).to be_falsy - end - end - end - - context 'when data are stored in data_fields' do - let(:service) do - create(:jira_service, url: url, username: username) - end - - it_behaves_like 'data fields' - - describe '{arg}_was?' do - it 'returns nil' do - service.url = 'http://example.com' - service.validate - expect(service.url_was).to be_nil - end - end - end - - context 'when data are stored in properties' do - let(:service) { create(:jira_service, :without_properties_callback, properties: properties) } - - it_behaves_like 'data fields' - - describe '{arg}_was?' do - it 'returns nil when the property has not been assigned a new value' do - service.username = 'new_username' - service.validate - expect(service.url_was).to be_nil - end - - it 'returns initial value when the property has been assigned a different value' do - service.url = 'http://example.com' - service.validate - expect(service.url_was).to eq('http://url.com') - end - - it 'returns initial value when the property has been re-assigned the same value' do - service.url = 'http://url.com' - service.validate - expect(service.url_was).to eq('http://url.com') - end - end - end - - context 'when data are stored in both properties and data_fields' do - let(:service) do - create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |service| - create(:jira_tracker_data, properties.merge(service: service)) - end - end - - it_behaves_like 'data fields' - - describe '{arg}_was?' do - it 'returns nil' do - service.url = 'http://example.com' - service.validate - expect(service.url_was).to be_nil - end - end - end -end diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb index 4f3736ca65b..0c4fc290a13 100644 --- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -65,7 +65,7 @@ describe GitlabIssueTrackerService do create(:gitlab_issue_tracker_service, :without_properties_callback, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in separated fields' do @@ -73,7 +73,7 @@ describe GitlabIssueTrackerService do create(:gitlab_issue_tracker_service, title: title, description: description, properties: access_params) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in both properties and separated fields' do @@ -82,7 +82,7 @@ describe GitlabIssueTrackerService do create(:gitlab_issue_tracker_service, :without_properties_callback, title: title, description: description, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when no title & description are set' do diff --git a/spec/models/project_services/issue_tracker_data_spec.rb b/spec/models/project_services/issue_tracker_data_spec.rb index db617cf0abb..aaab654f874 100644 --- a/spec/models/project_services/issue_tracker_data_spec.rb +++ b/spec/models/project_services/issue_tracker_data_spec.rb @@ -8,4 +8,28 @@ describe IssueTrackerData do describe 'Associations' do it { is_expected.to belong_to :service } end + + describe 'Validations' do + subject { described_class.new(service: service) } + + context 'url validations' do + context 'when service is inactive' do + it { is_expected.not_to validate_presence_of(:project_url) } + it { is_expected.not_to validate_presence_of(:issues_url) } + end + + context 'when service is active' do + before do + service.update(active: true) + end + + it_behaves_like 'issue tracker service URL attribute', :project_url + it_behaves_like 'issue tracker service URL attribute', :issues_url + it_behaves_like 'issue tracker service URL attribute', :new_issue_url + + it { is_expected.to validate_presence_of(:project_url) } + it { is_expected.to validate_presence_of(:issues_url) } + end + end + end end diff --git a/spec/models/project_services/issue_tracker_service_spec.rb b/spec/models/project_services/issue_tracker_service_spec.rb index f1cdee5c4a3..2fc4d69c2db 100644 --- a/spec/models/project_services/issue_tracker_service_spec.rb +++ b/spec/models/project_services/issue_tracker_service_spec.rb @@ -7,7 +7,7 @@ describe IssueTrackerService do let(:project) { create :project } describe 'only one issue tracker per project' do - let(:service) { RedmineService.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) } + let(:service) { RedmineService.new(project: project, active: true) } before do create(:custom_issue_tracker_service, project: project) diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index a976745023b..02060699e9a 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -6,18 +6,10 @@ describe JiraService do include Gitlab::Routing include AssetsHelpers - let(:title) { 'custom title' } - let(:description) { 'custom description' } - let(:url) { 'http://jira.example.com' } - let(:api_url) { 'http://api-jira.example.com' } - let(:username) { 'jira-username' } - let(:password) { 'jira-password' } - let(:transition_id) { 'test27' } - describe '#options' do let(:service) do - described_class.create( - project: create(:project), + described_class.new( + project: build_stubbed(:project), active: true, username: 'username', password: 'test', @@ -40,6 +32,78 @@ describe JiraService do describe 'Associations' do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } + it { is_expected.to allow_value(nil).for(:jira_issue_transition_id) } + it { is_expected.to allow_value('1,2,3').for(:jira_issue_transition_id) } + it { is_expected.to allow_value('1;2;3').for(:jira_issue_transition_id) } + it { is_expected.not_to allow_value('a,b,cd').for(:jira_issue_transition_id) } + end + + describe 'Validations' do + context 'when service is active' do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of(:url) } + it_behaves_like 'issue tracker service URL attribute', :url + end + + context 'when service is inactive' do + before do + subject.active = false + end + + it { is_expected.not_to validate_presence_of(:url) } + it { is_expected.not_to validate_presence_of(:username) } + it { is_expected.not_to validate_presence_of(:password) } + end + + context 'validating urls' do + let(:service) do + described_class.new( + project: create(:project), + active: true, + username: 'username', + password: 'test', + jira_issue_transition_id: 24, + url: 'http://jira.test.com' + ) + end + + it 'is valid when all fields have required values' do + expect(service).to be_valid + end + + it 'is not valid when url is not a valid url' do + service.url = 'not valid' + + expect(service).not_to be_valid + end + + it 'is not valid when api url is not a valid url' do + service.api_url = 'not valid' + + expect(service).not_to be_valid + end + + it 'is not valid when username is missing' do + service.username = nil + + expect(service).not_to be_valid + end + + it 'is not valid when password is missing' do + service.password = nil + + expect(service).not_to be_valid + end + + it 'is valid when api url is a valid url' do + service.api_url = 'http://jira.test.com/api' + + expect(service).to be_valid + end + end end describe '.reference_pattern' do @@ -54,260 +118,55 @@ describe JiraService do describe '#create' do let(:params) do { - project: create(:project), - title: 'custom title', description: 'custom description', - url: url, api_url: api_url, - username: username, password: password, - jira_issue_transition_id: transition_id + project: create(:project), title: 'custom title', description: 'custom description' } end subject { described_class.create(params) } - it 'does not store data into properties' do - expect(subject.properties).to be_nil - end - - it 'sets title correctly' do - service = subject - - expect(service.title).to eq('custom title') + it 'does not store title & description into properties' do + expect(subject.properties.keys).not_to include('title', 'description') end - it 'sets service data correctly' do + it 'sets title & description correctly' do service = subject expect(service.title).to eq('custom title') expect(service.description).to eq('custom description') end - - it 'stores data in data_fields correcty' do - service = subject - - expect(service.jira_tracker_data.url).to eq(url) - expect(service.jira_tracker_data.api_url).to eq(api_url) - expect(service.jira_tracker_data.username).to eq(username) - expect(service.jira_tracker_data.password).to eq(password) - expect(service.jira_tracker_data.jira_issue_transition_id).to eq(transition_id) - end end - # we need to make sure we are able to read both from properties and jira_tracker_data table - # TODO: change this as part of #63084 context 'overriding properties' do + let(:url) { 'http://issue_tracker.example.com' } let(:access_params) do - { url: url, api_url: api_url, username: username, password: password, - jira_issue_transition_id: transition_id } - end - let(:data_params) do - { - url: url, api_url: api_url, - username: username, password: password, - jira_issue_transition_id: transition_id - } - end - - shared_examples 'handles jira fields' do - let(:data_params) do - { - url: url, api_url: api_url, - username: username, password: password, - jira_issue_transition_id: transition_id - } - end - - context 'reading data' do - it 'reads data correctly' do - expect(service.url).to eq(url) - expect(service.api_url).to eq(api_url) - expect(service.username).to eq(username) - expect(service.password).to eq(password) - expect(service.jira_issue_transition_id).to eq(transition_id) - end - end - - context '#update' do - context 'basic update' do - let(:new_username) { 'new_username' } - let(:new_url) { 'http://jira-new.example.com' } - - before do - service.update(username: new_username, url: new_url) - end - - it 'leaves properties field emtpy' do - # expect(service.reload.properties).to be_empty - end - - it 'stores updated data in jira_tracker_data table' do - data = service.jira_tracker_data.reload - - expect(data.url).to eq(new_url) - expect(data.api_url).to eq(api_url) - expect(data.username).to eq(new_username) - expect(data.password).to eq(password) - expect(data.jira_issue_transition_id).to eq(transition_id) - end - end - - context 'stored password invalidation' do - context 'when a password was previously set' do - context 'when only web url present' do - let(:data_params) do - { - url: url, api_url: nil, - username: username, password: password, - jira_issue_transition_id: transition_id - } - end - - it 'resets password if url changed' do - service - service.url = 'http://jira_edited.example.com' - service.save - - expect(service.reload.url).to eq('http://jira_edited.example.com') - expect(service.password).to be_nil - end - - it 'does not reset password if url "changed" to the same url as before' do - service.title = 'aaaaaa' - service.url = 'http://jira.example.com' - service.save - - expect(service.reload.url).to eq('http://jira.example.com') - expect(service.password).not_to be_nil - end - - it 'resets password if url not changed but api url added' do - service.api_url = 'http://jira_edited.example.com/rest/api/2' - service.save - - expect(service.reload.api_url).to eq('http://jira_edited.example.com/rest/api/2') - expect(service.password).to be_nil - end - - it 'does not reset password if new url is set together with password, even if it\'s the same password' do - service.url = 'http://jira_edited.example.com' - service.password = password - service.save - - expect(service.password).to eq(password) - expect(service.url).to eq('http://jira_edited.example.com') - end - - it 'resets password if url changed, even if setter called multiple times' do - service.url = 'http://jira1.example.com/rest/api/2' - service.url = 'http://jira1.example.com/rest/api/2' - service.save - - expect(service.password).to be_nil - end - - it 'does not reset password if username changed' do - service.username = 'some_name' - service.save - - expect(service.reload.password).to eq(password) - end - - it 'does not reset password if password changed' do - service.url = 'http://jira_edited.example.com' - service.password = 'new_password' - service.save - - expect(service.reload.password).to eq('new_password') - end - - it 'does not reset password if the password is touched and same as before' do - service.url = 'http://jira_edited.example.com' - service.password = password - service.save - - expect(service.reload.password).to eq(password) - end - end - - context 'when both web and api url present' do - let(:data_params) do - { - url: url, api_url: 'http://jira.example.com/rest/api/2', - username: username, password: password, - jira_issue_transition_id: transition_id - } - end - - it 'resets password if api url changed' do - service.api_url = 'http://jira_edited.example.com/rest/api/2' - service.save - - expect(service.password).to be_nil - end - - it 'does not reset password if url changed' do - service.url = 'http://jira_edited.example.com' - service.save - - expect(service.password).to eq(password) - end - - it 'resets password if api url set to empty' do - service.update(api_url: '') - - expect(service.reload.password).to be_nil - end - end - end - - context 'when no password was previously set' do - let(:data_params) do - { - url: url, username: username - } - end - - it 'saves password if new url is set together with password' do - service.url = 'http://jira_edited.example.com/rest/api/2' - service.password = 'password' - service.save - expect(service.reload.password).to eq('password') - expect(service.reload.url).to eq('http://jira_edited.example.com/rest/api/2') - end - end - end - end + { url: url, username: 'username', password: 'password' } end # this will be removed as part of https://gitlab.com/gitlab-org/gitlab-ce/issues/63084 context 'when data are stored in properties' do - let(:properties) { data_params.merge(title: title, description: description) } - let!(:service) do + let(:properties) { access_params.merge(title: title, description: description) } + let(:service) do create(:jira_service, :without_properties_callback, properties: properties) end - it_behaves_like 'issue tracker fields' - it_behaves_like 'handles jira fields' + include_examples 'issue tracker fields' end context 'when data are stored in separated fields' do let(:service) do - create(:jira_service, data_params.merge(properties: {}, title: title, description: description)) + create(:jira_service, title: title, description: description, properties: access_params) end - it_behaves_like 'issue tracker fields' - it_behaves_like 'handles jira fields' + include_examples 'issue tracker fields' end context 'when data are stored in both properties and separated fields' do - let(:properties) { data_params.merge(title: title, description: description) } + let(:properties) { access_params.merge(title: 'wrong title', description: 'wrong description') } let(:service) do - create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |service| - create(:jira_tracker_data, data_params.merge(service: service)) - end + create(:jira_service, :without_properties_callback, title: title, description: description, properties: properties) end - it_behaves_like 'issue tracker fields' - it_behaves_like 'handles jira fields' + include_examples 'issue tracker fields' end context 'when no title & description are set' do @@ -551,6 +410,111 @@ describe JiraService do end end + describe 'Stored password invalidation' do + let(:project) { create(:project) } + + context 'when a password was previously set' do + before do + @jira_service = described_class.create!( + project: project, + properties: { + url: 'http://jira.example.com/web', + username: 'mic', + password: 'password' + } + ) + end + + context 'when only web url present' do + it 'reset password if url changed' do + @jira_service.url = 'http://jira_edited.example.com/rest/api/2' + @jira_service.save + + expect(@jira_service.password).to be_nil + end + + it 'reset password if url not changed but api url added' do + @jira_service.api_url = 'http://jira_edited.example.com/rest/api/2' + @jira_service.save + + expect(@jira_service.password).to be_nil + end + end + + context 'when both web and api url present' do + before do + @jira_service.api_url = 'http://jira.example.com/rest/api/2' + @jira_service.password = 'password' + + @jira_service.save + end + it 'reset password if api url changed' do + @jira_service.api_url = 'http://jira_edited.example.com/rest/api/2' + @jira_service.save + + expect(@jira_service.password).to be_nil + end + + it 'does not reset password if url changed' do + @jira_service.url = 'http://jira_edited.example.com/rweb' + @jira_service.save + + expect(@jira_service.password).to eq('password') + end + + it 'reset password if api url set to empty' do + @jira_service.api_url = '' + @jira_service.save + + expect(@jira_service.password).to be_nil + end + end + + it 'does not reset password if username changed' do + @jira_service.username = 'some_name' + @jira_service.save + + expect(@jira_service.password).to eq('password') + end + + it 'does not reset password if new url is set together with password, even if it\'s the same password' do + @jira_service.url = 'http://jira_edited.example.com/rest/api/2' + @jira_service.password = 'password' + @jira_service.save + + expect(@jira_service.password).to eq('password') + expect(@jira_service.url).to eq('http://jira_edited.example.com/rest/api/2') + end + + it 'resets password if url changed, even if setter called multiple times' do + @jira_service.url = 'http://jira1.example.com/rest/api/2' + @jira_service.url = 'http://jira1.example.com/rest/api/2' + @jira_service.save + expect(@jira_service.password).to be_nil + end + end + + context 'when no password was previously set' do + before do + @jira_service = described_class.create( + project: project, + properties: { + url: 'http://jira.example.com/rest/api/2', + username: 'mic' + } + ) + end + + it 'saves password if new url is set together with password' do + @jira_service.url = 'http://jira_edited.example.com/rest/api/2' + @jira_service.password = 'password' + @jira_service.save + expect(@jira_service.password).to eq('password') + expect(@jira_service.url).to eq('http://jira_edited.example.com/rest/api/2') + end + end + end + describe 'description and title' do let(:title) { 'Jira One' } let(:description) { 'Jira One issue tracker' } @@ -575,7 +539,7 @@ describe JiraService do context 'when it is set in properties' do it 'values from properties are returned' do - service = create(:jira_service, :without_properties_callback, properties: properties) + service = create(:jira_service, properties: properties) expect(service.title).to eq(title) expect(service.description).to eq(description) @@ -638,8 +602,8 @@ describe JiraService do project = create(:project) service = project.create_jira_service(active: true) - expect(service.url).to eq('http://jira.sample/projects/project_a') - expect(service.api_url).to eq('http://jira.sample/api') + expect(service.properties['url']).to eq('http://jira.sample/projects/project_a') + expect(service.properties['api_url']).to eq('http://jira.sample/api') end end diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb index 6cd3eb33d9b..1b6ece8531b 100644 --- a/spec/models/project_services/jira_tracker_data_spec.rb +++ b/spec/models/project_services/jira_tracker_data_spec.rb @@ -8,4 +8,35 @@ describe JiraTrackerData do describe 'Associations' do it { is_expected.to belong_to(:service) } end + + describe 'Validations' do + subject { described_class.new(service: service) } + + context 'jira_issue_transition_id' do + it { is_expected.to allow_value(nil).for(:jira_issue_transition_id) } + it { is_expected.to allow_value('1,2,3').for(:jira_issue_transition_id) } + it { is_expected.to allow_value('1;2;3').for(:jira_issue_transition_id) } + it { is_expected.not_to allow_value('a,b,cd').for(:jira_issue_transition_id) } + end + + context 'url validations' do + context 'when service is inactive' do + it { is_expected.not_to validate_presence_of(:url) } + it { is_expected.not_to validate_presence_of(:username) } + it { is_expected.not_to validate_presence_of(:password) } + end + + context 'when service is active' do + before do + service.update(active: true) + end + + it_behaves_like 'issue tracker service URL attribute', :url + + it { is_expected.to validate_presence_of(:url) } + it { is_expected.to validate_presence_of(:username) } + it { is_expected.to validate_presence_of(:password) } + end + end + end end diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb index 4ef4064d069..c1ee6546b12 100644 --- a/spec/models/project_services/redmine_service_spec.rb +++ b/spec/models/project_services/redmine_service_spec.rb @@ -9,15 +9,6 @@ describe RedmineService do end describe 'Validations' do - # if redmine is set in setting the urls are set to defaults - # therefore the validation passes as the values are not nil - before do - settings = { - 'redmine' => {} - } - allow(Gitlab.config).to receive(:issues_tracker).and_return(settings) - end - context 'when service is active' do before do subject.active = true @@ -26,7 +17,6 @@ describe RedmineService do it { is_expected.to validate_presence_of(:project_url) } it { is_expected.to validate_presence_of(:issues_url) } it { is_expected.to validate_presence_of(:new_issue_url) } - it_behaves_like 'issue tracker service URL attribute', :project_url it_behaves_like 'issue tracker service URL attribute', :issues_url it_behaves_like 'issue tracker service URL attribute', :new_issue_url @@ -64,7 +54,7 @@ describe RedmineService do create(:redmine_service, :without_properties_callback, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in separated fields' do @@ -72,7 +62,7 @@ describe RedmineService do create(:redmine_service, title: title, description: description, properties: access_params) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in both properties and separated fields' do @@ -81,7 +71,7 @@ describe RedmineService do create(:redmine_service, :without_properties_callback, title: title, description: description, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when no title & description are set' do diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb index eff9f451b1a..c48bf487af0 100644 --- a/spec/models/project_services/youtrack_service_spec.rb +++ b/spec/models/project_services/youtrack_service_spec.rb @@ -16,7 +16,6 @@ describe YoutrackService do it { is_expected.to validate_presence_of(:project_url) } it { is_expected.to validate_presence_of(:issues_url) } - it_behaves_like 'issue tracker service URL attribute', :project_url it_behaves_like 'issue tracker service URL attribute', :issues_url end @@ -52,7 +51,7 @@ describe YoutrackService do create(:youtrack_service, :without_properties_callback, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in separated fields' do @@ -60,7 +59,7 @@ describe YoutrackService do create(:youtrack_service, title: title, description: description, properties: access_params) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when data are stored in both properties and separated fields' do @@ -69,7 +68,7 @@ describe YoutrackService do create(:youtrack_service, :without_properties_callback, title: title, description: description, properties: properties) end - it_behaves_like 'issue tracker fields' + include_examples 'issue tracker fields' end context 'when no title & description are set' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 67f64822184..5b4b9c516a0 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -2027,43 +2027,6 @@ describe Project do end end - describe '#latest_pipeline_for_ref' do - let(:project) { create(:project, :repository) } - let(:second_branch) { project.repository.branches[2] } - - let!(:pipeline_for_default_branch) do - create(:ci_empty_pipeline, project: project, sha: project.commit.id, - ref: project.default_branch) - end - let!(:pipeline_for_second_branch) do - create(:ci_empty_pipeline, project: project, sha: second_branch.target, - ref: second_branch.name) - end - - before do - create(:ci_empty_pipeline, project: project, sha: project.commit.parent.id, - ref: project.default_branch) - end - - context 'default repository branch' do - subject { project.latest_pipeline_for_ref(project.default_branch) } - - it { is_expected.to eq(pipeline_for_default_branch) } - end - - context 'provided ref' do - subject { project.latest_pipeline_for_ref(second_branch.name) } - - it { is_expected.to eq(pipeline_for_second_branch) } - end - - context 'bad ref' do - subject { project.latest_pipeline_for_ref(SecureRandom.uuid) } - - it { is_expected.to be_nil } - end - end - describe '#latest_successful_build_for_sha' do let(:project) { create(:project, :repository) } let(:pipeline) { create_pipeline(project) } diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 8714c67f29d..c690390e24d 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -13,8 +13,7 @@ RSpec.describe Release do it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:author).class_name('User') } it { is_expected.to have_many(:links).class_name('Releases::Link') } - it { is_expected.to have_many(:milestones) } - it { is_expected.to have_many(:milestone_releases) } + it { is_expected.to have_one(:milestone) } end describe 'validation' do @@ -39,15 +38,15 @@ RSpec.describe Release do context 'when a release is tied to a milestone for another project' do it 'creates a validation error' do - milestone = build(:milestone, project: create(:project)) - expect { release.milestones << milestone }.to raise_error + release.milestone = build(:milestone, project: create(:project)) + expect(release).not_to be_valid end end context 'when a release is tied to a milestone linked to the same project' do - it 'successfully links this release to this milestone' do - milestone = build(:milestone, project: project) - expect { release.milestones << milestone }.to change { MilestoneRelease.count }.by(1) + it 'is valid' do + release.milestone = build(:milestone, project: project) + expect(release).to be_valid end end end diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index d96e1398677..0797b9a9d83 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -257,8 +257,8 @@ describe Service do expect(service.title).to eq('random title') end - it 'sets data correctly' do - expect(service.data_fields.project_url).to eq('http://gitlab.example.com') + it 'creates the properties' do + expect(service.properties).to eq({ "project_url" => "http://gitlab.example.com" }) end end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index b3acf531ccb..0893dcb39b6 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -59,16 +59,6 @@ describe API::Groups do .to satisfy_one { |group| group['name'] == group1.name } end - it "does not include runners_token information" do - get api("/groups", user1) - - expect(response).to have_gitlab_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.length).to eq(1) - expect(json_response.first).not_to include('runners_token') - end - it "does not include statistics" do get api("/groups", user1), params: { statistics: true } @@ -89,16 +79,6 @@ describe API::Groups do expect(json_response.length).to eq(2) end - it "does not include runners_token information" do - get api("/groups", admin) - - expect(response).to have_gitlab_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.length).to eq(2) - expect(json_response.first).not_to include('runners_token') - end - it "does not include statistics by default" do get api("/groups", admin) @@ -312,7 +292,6 @@ describe API::Groups do get api("/groups/#{group1.id}") expect(response).to have_gitlab_http_status(200) - expect(json_response).not_to include('runners_token') end it 'returns only public projects in the group' do @@ -371,22 +350,6 @@ describe API::Groups do expect(response).to have_gitlab_http_status(200) expect(json_response['projects']).to be_nil expect(json_response['shared_projects']).to be_nil - expect(json_response).not_to include('runners_token') - end - - it "doesn't return runners_token if the user is not the owner of the group" do - get api("/groups/#{group1.id}", user3) - - expect(response).to have_gitlab_http_status(200) - expect(json_response).not_to include('runners_token') - end - - it "returns runners_token if the user is the owner of the group" do - group1.add_owner(user3) - get api("/groups/#{group1.id}", user3) - - expect(response).to have_gitlab_http_status(200) - expect(json_response).to include('runners_token') end it "does not return a non existing group" do @@ -444,13 +407,6 @@ describe API::Groups do expect(json_response['name']).to eq(group2.name) end - it "returns information of the runners_token for the group" do - get api("/groups/#{group2.id}", admin) - - expect(response).to have_gitlab_http_status(200) - expect(json_response).to include('runners_token') - end - it "does not return a non existing group" do get api("/groups/1328", admin) diff --git a/spec/requests/api/issues/get_group_issues_spec.rb b/spec/requests/api/issues/get_group_issues_spec.rb index 3ee08758f99..c487471e4a1 100644 --- a/spec/requests/api/issues/get_group_issues_spec.rb +++ b/spec/requests/api/issues/get_group_issues_spec.rb @@ -437,21 +437,17 @@ describe API::Issues do end context 'with labeled issues' do - let(:group_issue2) { create :issue, project: group_project } let(:label_b) { create(:label, title: 'foo', project: group_project) } let(:label_c) { create(:label, title: 'bar', project: group_project) } before do - create(:label_link, label: group_label, target: group_issue2) create(:label_link, label: label_b, target: group_issue) - create(:label_link, label: label_b, target: group_issue2) create(:label_link, label: label_c, target: group_issue) get api(base_url, user), params: params end let(:issue) { group_issue } - let(:issue2) { group_issue2 } let(:label) { group_label } it_behaves_like 'labeled issues with labels and label_name params' diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb index c10f5b2bd58..b7aa3f93451 100644 --- a/spec/requests/api/issues/get_project_issues_spec.rb +++ b/spec/requests/api/issues/get_project_issues_spec.rb @@ -283,14 +283,11 @@ describe API::Issues do end context 'with labeled issues' do - let(:issue2) { create :issue, project: project } let(:label_b) { create(:label, title: 'foo', project: project) } let(:label_c) { create(:label, title: 'bar', project: project) } before do - create(:label_link, label: label, target: issue2) create(:label_link, label: label_b, target: issue) - create(:label_link, label: label_b, target: issue2) create(:label_link, label: label_c, target: issue) get api('/issues', user), params: params diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb index 61a94b682be..f19c2dcc6fe 100644 --- a/spec/requests/api/issues/issues_spec.rb +++ b/spec/requests/api/issues/issues_spec.rb @@ -427,12 +427,9 @@ describe API::Issues do context 'with labeled issues' do let(:label_b) { create(:label, title: 'foo', project: project) } let(:label_c) { create(:label, title: 'bar', project: project) } - let(:issue2) { create(:issue, author: user, project: project) } before do - create(:label_link, label: label, target: issue2) create(:label_link, label: label_b, target: issue) - create(:label_link, label: label_b, target: issue2) create(:label_link, label: label_c, target: issue) get api('/issues', user), params: params @@ -500,74 +497,46 @@ describe API::Issues do end end - context 'filter by milestone' do - it 'returns an empty array if no issue matches milestone' do - get api("/issues?milestone=#{empty_milestone.title}", user) + it 'returns an empty array if no issue matches milestone' do + get api("/issues?milestone=#{empty_milestone.title}", user) - expect_paginated_array_response([]) - end - - it 'returns an empty array if milestone does not exist' do - get api('/issues?milestone=foo', user) - - expect_paginated_array_response([]) - end - - it 'returns an array of issues in given milestone' do - get api("/issues?milestone=#{milestone.title}", user) - - expect_paginated_array_response([issue.id, closed_issue.id]) - end - - it 'returns an array of issues in given milestone_title param' do - get api("/issues?milestone_title=#{milestone.title}", user) - - expect_paginated_array_response([issue.id, closed_issue.id]) - end - - it 'returns an array of issues matching state in milestone' do - get api("/issues?milestone=#{milestone.title}&state=closed", user) - - expect_paginated_array_response(closed_issue.id) - end + expect_paginated_array_response([]) + end - it 'returns an array of issues with no milestone' do - get api("/issues?milestone=#{no_milestone_title}", author) + it 'returns an empty array if milestone does not exist' do + get api('/issues?milestone=foo', user) - expect_paginated_array_response(confidential_issue.id) - end + expect_paginated_array_response([]) + end - it 'returns an array of issues with no milestone using milestone_title param' do - get api("/issues?milestone_title=#{no_milestone_title}", author) + it 'returns an array of issues in given milestone' do + get api("/issues?milestone=#{milestone.title}", user) - expect_paginated_array_response(confidential_issue.id) - end + expect_paginated_array_response([issue.id, closed_issue.id]) + end - context 'negated' do - it 'returns all issues if milestone does not exist' do - get api('/issues?not[milestone]=foo', user) + it 'returns an array of issues in given milestone_title param' do + get api("/issues?milestone_title=#{milestone.title}", user) - expect_paginated_array_response([issue.id, closed_issue.id]) - end + expect_paginated_array_response([issue.id, closed_issue.id]) + end - it 'returns all issues that do not belong to a milestone but have a milestone' do - get api("/issues?not[milestone]=#{empty_milestone.title}", user) + it 'returns an array of issues matching state in milestone' do + get api("/issues?milestone=#{milestone.title}&state=closed", user) - expect_paginated_array_response([issue.id, closed_issue.id]) - end + expect_paginated_array_response(closed_issue.id) + end - it 'returns an array of issues with any milestone' do - get api("/issues?not[milestone]=#{no_milestone_title}", user) + it 'returns an array of issues with no milestone' do + get api("/issues?milestone=#{no_milestone_title}", author) - expect_paginated_array_response([issue.id, closed_issue.id]) - end + expect_paginated_array_response(confidential_issue.id) + end - it 'returns an array of issues matching state not in milestone' do - get api("/issues?not[milestone]=#{empty_milestone.title}&state=closed", user) + it 'returns an array of issues with no milestone using milestone_title param' do + get api("/issues?milestone_title=#{no_milestone_title}", author) - expect_paginated_array_response(closed_issue.id) - end - end + expect_paginated_array_response(confidential_issue.id) end it 'returns an array of issues found by iids' do diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index 3a3f0e970a4..174b3214d13 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -459,54 +459,6 @@ describe API::Pipelines do end end - describe 'GET /projects/:id/pipelines/latest' do - context 'authorized user' do - let(:second_branch) { project.repository.branches[2] } - - let!(:second_pipeline) do - create(:ci_empty_pipeline, project: project, sha: second_branch.target, - ref: second_branch.name, user: user) - end - - before do - create(:ci_empty_pipeline, project: project, sha: project.commit.parent.id, - ref: project.default_branch, user: user) - end - - context 'default repository branch' do - it 'gets the latest pipleine' do - get api("/projects/#{project.id}/pipelines/latest", user) - - expect(response).to have_gitlab_http_status(200) - expect(response).to match_response_schema('public_api/v4/pipeline/detail') - expect(json_response['ref']).to eq(project.default_branch) - expect(json_response['sha']).to eq(project.commit.id) - end - end - - context 'ref parameter' do - it 'gets the latest pipleine' do - get api("/projects/#{project.id}/pipelines/latest", user), params: { ref: second_branch.name } - - expect(response).to have_gitlab_http_status(200) - expect(response).to match_response_schema('public_api/v4/pipeline/detail') - expect(json_response['ref']).to eq(second_branch.name) - expect(json_response['sha']).to eq(second_branch.target) - end - end - end - - context 'unauthorized user' do - it 'does not return a project pipeline' do - get api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member) - - expect(response).to have_gitlab_http_status(404) - expect(json_response['message']).to eq '404 Project Not Found' - expect(json_response['id']).to be nil - end - end - end - describe 'GET /projects/:id/pipelines/:pipeline_id/variables' do subject { get api("/projects/#{project.id}/pipelines/#{pipeline.id}/variables", api_user) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 2d8ef9c06dc..550c7d135a6 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require 'spec_helper' shared_examples 'languages and percentages JSON response' do @@ -630,33 +631,6 @@ describe API::Projects do expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED) end - it 'creates a project using a template' do - expect { post api('/projects', user), params: { template_name: 'rails', name: 'rails-test' } } - .to change { Project.count }.by(1) - - expect(response).to have_gitlab_http_status(201) - - project = Project.find(json_response['id']) - expect(project).to be_saved - expect(project.import_type).to eq('gitlab_project') - end - - it 'returns 400 for an invalid template' do - expect { post api('/projects', user), params: { template_name: 'unknown', name: 'rails-test' } } - .not_to change { Project.count } - - expect(response).to have_gitlab_http_status(400) - expect(json_response['message']['template_name']).to eq(["'unknown' is unknown or invalid"]) - end - - it 'disallows creating a project with an import_url and template' do - project_params = { import_url: 'http://example.com', template_name: 'rails', name: 'rails-test' } - expect { post api('/projects', user), params: project_params } - .not_to change { Project.count } - - expect(response).to have_gitlab_http_status(400) - end - it 'sets a project as public' do project = attributes_for(:project, visibility: 'public') @@ -893,7 +867,7 @@ describe API::Projects do expect { post api("/projects/user/#{user.id}", admin), params: { name: 'Foo Project' } }.to change { Project.count }.by(1) expect(response).to have_gitlab_http_status(201) - project = Project.find(json_response['id']) + project = Project.last expect(project.name).to eq('Foo Project') expect(project.path).to eq('foo-project') @@ -904,7 +878,7 @@ describe API::Projects do .to change { Project.count }.by(1) expect(response).to have_gitlab_http_status(201) - project = Project.find(json_response['id']) + project = Project.last expect(project.name).to eq('Foo Project') expect(project.path).to eq('path-project-Foo') diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 7153fcc99d7..76a70ab6e9e 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -100,15 +100,9 @@ describe API::Services do expect(json_response['properties'].keys).to match_array(service_instance.api_field_names) end - it "returns empty hash if properties and data fields are empty" do + it "returns empty hash if properties are empty" do # deprecated services are not valid for update initialized_service.update_attribute(:properties, {}) - - if initialized_service.data_fields_present? - initialized_service.data_fields.destroy - initialized_service.reload - end - get api("/projects/#{project.id}/services/#{dashed_service}", user) expect(response).to have_gitlab_http_status(200) diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb deleted file mode 100644 index 5945561aa7b..00000000000 --- a/spec/requests/projects/merge_requests_discussions_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe 'merge requests discussions' do - # Further tests can be found at merge_requests_controller_spec.rb - describe 'GET /:namespace/:project/merge_requests/:iid/discussions' do - let(:project) { create(:project, :repository) } - let(:user) { project.owner } - let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } - - before do - project.add_developer(user) - login_as(user) - end - - def send_request - get discussions_namespace_project_merge_request_path(namespace_id: project.namespace, project_id: project, id: merge_request.iid) - end - - it 'returns 200' do - send_request - - expect(response.status).to eq(200) - end - - # https://docs.gitlab.com/ee/development/query_recorder.html#use-request-specs-instead-of-controller-specs - it 'avoids N+1 DB queries', :request_store do - control = ActiveRecord::QueryRecorder.new { send_request } - - create(:diff_note_on_merge_request, noteable: merge_request, - project: merge_request.project) - - expect do - send_request - end.not_to exceed_query_limit(control) - end - - it 'limits Gitaly queries', :request_store do - Gitlab::GitalyClient.allow_n_plus_1_calls do - create_list(:diff_note_on_merge_request, 7, noteable: merge_request, - project: merge_request.project) - end - - # The creations above write into the Gitaly counts - Gitlab::GitalyClient.reset_counts - - expect { send_request } - .to change { Gitlab::GitalyClient.get_request_count }.by_at_most(4) - end - end -end diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index 1a5fdac1c95..4cd2a12e272 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -766,22 +766,6 @@ describe Ci::CreatePipelineService do end end - context 'with timeout' do - context 'when builds with custom timeouts are configured' do - before do - config = YAML.dump(rspec: { script: 'rspec', timeout: '2m 3s' }) - stub_ci_pipeline_yaml_file(config) - end - - it 'correctly creates builds with custom timeout value configured' do - pipeline = execute_service - - expect(pipeline).to be_persisted - expect(pipeline.builds.find_by(name: 'rspec').options[:job_timeout]).to eq 123 - end - end - end - shared_examples 'when ref is protected' do let(:user) { create(:user) } diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 55254b61ac8..fd9a63b79cc 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8 # frozen_string_literal: true require 'spec_helper' diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb index 4f16421c39f..ff1e1256166 100644 --- a/spec/services/milestones/destroy_service_spec.rb +++ b/spec/services/milestones/destroy_service_spec.rb @@ -72,7 +72,7 @@ describe Milestones::DestroyService do :release, tag: 'v1.0', project: project, - milestones: [milestone] + milestone: milestone ) expect { service.execute(milestone) }.not_to change { Release.count } diff --git a/spec/services/projects/create_from_template_service_spec.rb b/spec/services/projects/create_from_template_service_spec.rb index 0b4772e8f02..6c244d23877 100644 --- a/spec/services/projects/create_from_template_service_spec.rb +++ b/spec/services/projects/create_from_template_service_spec.rb @@ -25,7 +25,7 @@ describe Projects::CreateFromTemplateService do subject.execute end - it 'returns the project that is created' do + it 'returns the project thats created' do project = subject.execute expect(project).to be_saved @@ -37,7 +37,7 @@ describe Projects::CreateFromTemplateService do let(:project) { subject.execute } before do - expect(project).not_to be_saved + expect(project).to be_saved end it 'does not set import set import type' do diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb index b624b9475e3..5c9d6537df1 100644 --- a/spec/services/releases/create_service_spec.rb +++ b/spec/services/releases/create_service_spec.rb @@ -75,12 +75,10 @@ describe Releases::CreateService do context 'when a passed-in milestone does not exist for this project' do it 'raises an error saying the milestone is inexistent' do - inexistent_milestone_tag = 'v111.0' - service = described_class.new(project, user, params.merge!({ milestones: [inexistent_milestone_tag] })) + service = described_class.new(project, user, params.merge!({ milestone: 'v111.0' })) result = service.execute - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq("Milestone(s) not found: #{inexistent_milestone_tag}") + expect(result[:message]).to eq('Milestone does not exist') end end end @@ -95,10 +93,10 @@ describe Releases::CreateService do context 'when existing milestone is passed in' do let(:title) { 'v1.0' } let(:milestone) { create(:milestone, :active, project: project, title: title) } - let(:params_with_milestone) { params.merge!({ milestones: [title] }) } - let(:service) { described_class.new(milestone.project, user, params_with_milestone) } + let(:params_with_milestone) { params.merge!({ milestone: title }) } it 'creates a release and ties this milestone to it' do + service = described_class.new(milestone.project, user, params_with_milestone) result = service.execute expect(project.releases.count).to eq(1) @@ -106,66 +104,29 @@ describe Releases::CreateService do release = project.releases.last - expect(release.milestones).to match_array([milestone]) + expect(release.milestone).to eq(milestone) end context 'when another release was previously created with that same milestone linked' do it 'also creates another release tied to that same milestone' do - other_release = create(:release, milestones: [milestone], project: project, tag: 'v1.0') + other_release = create(:release, milestone: milestone, project: project, tag: 'v1.0') + service = described_class.new(milestone.project, user, params_with_milestone) service.execute release = project.releases.last - expect(release.milestones).to match_array([milestone]) - expect(other_release.milestones).to match_array([milestone]) + expect(release.milestone).to eq(milestone) + expect(other_release.milestone).to eq(milestone) expect(release.id).not_to eq(other_release.id) end end end - context 'when multiple existing milestone titles are passed in' do - let(:title_1) { 'v1.0' } - let(:title_2) { 'v1.0-rc' } - let!(:milestone_1) { create(:milestone, :active, project: project, title: title_1) } - let!(:milestone_2) { create(:milestone, :active, project: project, title: title_2) } - let!(:params_with_milestones) { params.merge!({ milestones: [title_1, title_2] }) } - - it 'creates a release and ties it to these milestones' do - described_class.new(project, user, params_with_milestones).execute - release = project.releases.last - - expect(release.milestones.map(&:title)).to include(title_1, title_2) - end - end - - context 'when multiple miletone titles are passed in but one of them does not exist' do - let(:title) { 'v1.0' } - let(:inexistent_title) { 'v111.0' } - let!(:milestone) { create(:milestone, :active, project: project, title: title) } - let!(:params_with_milestones) { params.merge!({ milestones: [title, inexistent_title] }) } - let(:service) { described_class.new(milestone.project, user, params_with_milestones) } - - it 'raises an error' do - result = service.execute - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq("Milestone(s) not found: #{inexistent_title}") - end - - it 'does not create any release' do - expect do - service.execute - end.not_to change(Release, :count) - end - end - context 'when no milestone is passed in' do it 'creates a release without a milestone tied to it' do - expect(params.key? :milestones).to be_falsey - + expect(params.key? :milestone).to be_falsey service.execute release = project.releases.last - - expect(release.milestones).to be_empty + expect(release.milestone).to be_nil end it 'does not create any new MilestoneRelease object' do @@ -175,11 +136,10 @@ describe Releases::CreateService do context 'when an empty value is passed as a milestone' do it 'creates a release without a milestone tied to it' do - service = described_class.new(project, user, params.merge!({ milestones: [] })) + service = described_class.new(project, user, params.merge!({ milestone: '' })) service.execute release = project.releases.last - - expect(release.milestones).to be_empty + expect(release.milestone).to be_nil end end end diff --git a/spec/services/releases/destroy_service_spec.rb b/spec/services/releases/destroy_service_spec.rb index 9d027767cd2..c3172e5edbc 100644 --- a/spec/services/releases/destroy_service_spec.rb +++ b/spec/services/releases/destroy_service_spec.rb @@ -60,7 +60,7 @@ describe Releases::DestroyService do context 'when a milestone is tied to the release' do let!(:milestone) { create(:milestone, :active, project: project, title: 'v1.0') } - let!(:release) { create(:release, milestones: [milestone], project: project, tag: tag) } + let!(:release) { create(:release, milestone: milestone, project: project, tag: tag) } it 'destroys the release but leave the milestone intact' do expect { subject }.not_to change { Milestone.count } diff --git a/spec/services/releases/update_service_spec.rb b/spec/services/releases/update_service_spec.rb index 178bac3574f..944f3d8c9ad 100644 --- a/spec/services/releases/update_service_spec.rb +++ b/spec/services/releases/update_service_spec.rb @@ -50,60 +50,39 @@ describe Releases::UpdateService do end context 'when a milestone is passed in' do + let(:old_title) { 'v1.0' } let(:new_title) { 'v2.0' } - let(:milestone) { create(:milestone, project: project, title: 'v1.0') } + let(:milestone) { create(:milestone, project: project, title: old_title) } let(:new_milestone) { create(:milestone, project: project, title: new_title) } - let(:params_with_milestone) { params.merge!({ milestones: [new_title] }) } - let(:service) { described_class.new(new_milestone.project, user, params_with_milestone) } + let(:params_with_milestone) { params.merge!({ milestone: new_title }) } before do - release.milestones << milestone + release.milestone = milestone + release.save! - service.execute + described_class.new(new_milestone.project, user, params_with_milestone).execute release.reload end it 'updates the related milestone accordingly' do - expect(release.milestones.first.title).to eq(new_title) + expect(release.milestone.title).to eq(new_title) end end context "when an 'empty' milestone is passed in" do let(:milestone) { create(:milestone, project: project, title: 'v1.0') } - let(:params_with_empty_milestone) { params.merge!({ milestones: [] }) } + let(:params_with_empty_milestone) { params.merge!({ milestone: '' }) } before do - release.milestones << milestone + release.milestone = milestone + release.save! - service.params = params_with_empty_milestone - service.execute + described_class.new(milestone.project, user, params_with_empty_milestone).execute release.reload end it 'removes the old milestone and does not associate any new milestone' do - expect(release.milestones).not_to be_present - end - end - - context "when multiple new milestones are passed in" do - let(:new_title_1) { 'v2.0' } - let(:new_title_2) { 'v2.0-rc' } - let(:milestone) { create(:milestone, project: project, title: 'v1.0') } - let(:params_with_milestones) { params.merge!({ milestones: [new_title_1, new_title_2] }) } - let(:service) { described_class.new(project, user, params_with_milestones) } - - before do - create(:milestone, project: project, title: new_title_1) - create(:milestone, project: project, title: new_title_2) - release.milestones << milestone - - service.execute - release.reload - end - - it 'removes the old milestone and update the release with the new ones' do - milestone_titles = release.milestones.map(&:title) - expect(milestone_titles).to match_array([new_title_1, new_title_2]) + expect(release.milestone).to be_nil end end end diff --git a/spec/services/service_response_spec.rb b/spec/services/service_response_spec.rb index a6567f52c6f..e790d272e61 100644 --- a/spec/services/service_response_spec.rb +++ b/spec/services/service_response_spec.rb @@ -23,20 +23,6 @@ describe ServiceResponse do expect(response).to be_success expect(response.payload).to eq(good: 'orange') end - - it 'creates a successful response with default HTTP status' do - response = described_class.success - - expect(response).to be_success - expect(response.http_status).to eq(:ok) - end - - it 'creates a successful response with custom HTTP status' do - response = described_class.success(http_status: 204) - - expect(response).to be_success - expect(response.http_status).to eq(204) - end end describe '.error' do diff --git a/spec/support/helpers/jira_service_helper.rb b/spec/support/helpers/jira_service_helper.rb index c23a8d52c84..57c33c81ea3 100644 --- a/spec/support/helpers/jira_service_helper.rb +++ b/spec/support/helpers/jira_service_helper.rb @@ -5,16 +5,16 @@ module JiraServiceHelper JIRA_API = JIRA_URL + "/rest/api/2" def jira_service_settings - title = "Jira tracker" - url = JIRA_URL - username = 'jira-user' - password = 'my-secret-password' - jira_issue_transition_id = '1' + properties = { + title: "Jira tracker", + url: JIRA_URL, + username: 'jira-user', + password: 'my-secret-password', + project_key: "JIRA", + jira_issue_transition_id: '1' + } - jira_tracker.update( - title: title, url: url, username: username, password: password, - jira_issue_transition_id: jira_issue_transition_id, active: true - ) + jira_tracker.update(properties: properties, active: true) end def jira_issue_comments diff --git a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb index 6c96b18d834..26ab6fbd400 100644 --- a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb +++ b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb @@ -12,7 +12,6 @@ RSpec.shared_context 'IssuesFinder context' do set(:project3) { create(:project, group: subgroup) } set(:milestone) { create(:milestone, project: project1) } set(:label) { create(:label, project: project2) } - set(:label2) { create(:label, project: project2) } set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago, updated_at: 1.week.ago) } set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab', created_at: 1.week.from_now, updated_at: 1.week.from_now) } set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 2.weeks.from_now, updated_at: 2.weeks.from_now) } @@ -25,7 +24,6 @@ end RSpec.shared_context 'IssuesFinder#execute context' do let!(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') } let!(:label_link) { create(:label_link, label: label, target: issue2) } - let!(:label_link2) { create(:label_link, label: label2, target: issue3) } let(:search_user) { user } let(:params) { {} } let(:issues) { described_class.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute } diff --git a/spec/support/shared_examples/controllers/application_settings_shared_examples.rb b/spec/support/shared_examples/controllers/application_settings_shared_examples.rb deleted file mode 100644 index 9619451cd14..00000000000 --- a/spec/support/shared_examples/controllers/application_settings_shared_examples.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -shared_examples 'renders correct panels' do - it 'renders correct action on error' do - expect_next_instance_of(ApplicationSettings::UpdateService) do |service| - allow(service).to receive(:execute).and_return(false) - end - - patch action, params: { application_setting: { unused_param: true } } - - expect(subject).to render_template(action) - end - - it 'redirects to same panel on success' do - expect_next_instance_of(ApplicationSettings::UpdateService) do |service| - allow(service).to receive(:execute).and_return(true) - end - - referer_path = public_send("#{action}_admin_application_settings_path") - request.env["HTTP_REFERER"] = referer_path - - patch action, params: { application_setting: { unused_param: true } } - - expect(subject).to redirect_to(referer_path) - end -end diff --git a/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb index f1df1052ef2..a931c4df99f 100644 --- a/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb +++ b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb @@ -6,24 +6,12 @@ shared_examples 'assignee ID filter' do end end -shared_examples 'assignee NOT ID filter' do - it 'returns issuables not assigned to that user' do - expect(issuables).to contain_exactly(*expected_issuables) - end -end - shared_examples 'assignee username filter' do it 'returns issuables assigned to those users' do expect(issuables).to contain_exactly(*expected_issuables) end end -shared_examples 'assignee NOT username filter' do - it 'returns issuables not assigned to those users' do - expect(issuables).to contain_exactly(*expected_issuables) - end -end - shared_examples 'no assignee filter' do let(:params) { { assignee_id: 'None' } } diff --git a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb index affe88be475..8e58cc7ba22 100644 --- a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb +++ b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb @@ -21,8 +21,4 @@ shared_examples 'cluster application core specs' do |application_name| expect(Clusters::Cluster::APPLICATIONS[subject.name]).to eq(described_class) end end - - describe '.association_name' do - it { expect(described_class.association_name).to eq(:"application_#{subject.name}") } - end end diff --git a/spec/support/shared_examples/requests/api/issues_shared_examples.rb b/spec/support/shared_examples/requests/api/issues_shared_examples.rb index d22210edf99..1133e95e44e 100644 --- a/spec/support/shared_examples/requests/api/issues_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/issues_shared_examples.rb @@ -8,13 +8,6 @@ shared_examples 'labeled issues with labels and label_name params' do end end - shared_examples 'returns negated label names' do - it 'returns label names' do - expect_paginated_array_response(issue2.id) - expect(json_response.first['labels']).to eq([label_b.title, label.title]) - end - end - shared_examples 'returns basic label entity' do it 'returns basic label entity' do expect_paginated_array_response(issue.id) @@ -35,20 +28,6 @@ shared_examples 'labeled issues with labels and label_name params' do it_behaves_like 'returns label names' end - context 'negation' do - context 'array of labeled issues when all labels match with negation' do - let(:params) { { labels: "#{label.title},#{label_b.title}", not: { labels: "#{label_c.title}" } } } - - it_behaves_like 'returns negated label names' - end - - context 'array of labeled issues when all labels match with negation with label params as array' do - let(:params) { { labels: [label.title, label_b.title], not: { labels: [label_c.title] } } } - - it_behaves_like 'returns negated label names' - end - end - context 'when with_labels_details provided' do context 'array of labeled issues when all labels match' do let(:params) { { labels: "#{label.title},#{label_b.title},#{label_c.title}", with_labels_details: true } } |