diff options
Diffstat (limited to 'spec')
13 files changed, 297 insertions, 76 deletions
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb index 708ce53b4fe..ad0e9b48903 100644 --- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb @@ -26,6 +26,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request', end before do + stub_feature_flags(new_pipelines_table: false) stub_application_setting(auto_devops_enabled: false) stub_ci_pipeline_yaml_file(YAML.dump(config)) project.add_maintainer(user) diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 2b407868f35..9037aa5c9a8 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -14,6 +14,7 @@ RSpec.describe 'Pipelines', :js do sign_in(user) stub_feature_flags(graphql_pipeline_details: false) stub_feature_flags(graphql_pipeline_details_users: false) + stub_feature_flags(new_pipelines_table: false) project.add_developer(user) project.update!(auto_devops_attributes: { enabled: false }) diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js index 14445132f48..496c5cda7c7 100644 --- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js +++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js @@ -1,7 +1,15 @@ -import { GlEmptyState, GlLoadingIcon, GlSearchBoxByClick, GlSprintf } from '@gitlab/ui'; +import { + GlEmptyState, + GlLoadingIcon, + GlSearchBoxByClick, + GlSprintf, + GlDropdown, + GlDropdownItem, +} from '@gitlab/ui'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { stubComponent } from 'helpers/stub_component'; import waitForPromises from 'helpers/wait_for_promises'; import { STATUSES } from '~/import_entities/constants'; import ImportTable from '~/import_entities/import_groups/components/import_table.vue'; @@ -16,10 +24,15 @@ import { availableNamespacesFixture, generateFakeEntry } from '../graphql/fixtur const localVue = createLocalVue(); localVue.use(VueApollo); +const GlDropdownStub = stubComponent(GlDropdown, { + template: '<div><h1 ref="text"><slot name="button-content"></slot></h1><slot></slot></div>', +}); + describe('import table', () => { let wrapper; let apolloProvider; + const SOURCE_URL = 'https://demo.host'; const FAKE_GROUP = generateFakeEntry({ id: 1, status: STATUSES.NONE }); const FAKE_GROUPS = [ generateFakeEntry({ id: 1, status: STATUSES.NONE }), @@ -27,6 +40,9 @@ describe('import table', () => { ]; const FAKE_PAGE_INFO = { page: 1, perPage: 20, total: 40, totalPages: 2 }; + const findPaginationDropdown = () => wrapper.findComponent(GlDropdown); + const findPaginationDropdownText = () => findPaginationDropdown().find({ ref: 'text' }).text(); + const createComponent = ({ bulkImportSourceGroups }) => { apolloProvider = createMockApollo([], { Query: { @@ -42,11 +58,12 @@ describe('import table', () => { wrapper = shallowMount(ImportTable, { propsData: { - sourceUrl: 'https://demo.host', groupPathRegex: /.*/, + sourceUrl: SOURCE_URL, }, stubs: { GlSprintf, + GlDropdown: GlDropdownStub, }, localVue, apolloProvider, @@ -152,6 +169,20 @@ describe('import table', () => { expect(wrapper.find(PaginationLinks).props().pageInfo).toStrictEqual(FAKE_PAGE_INFO); }); + it('renders pagination dropdown', () => { + expect(findPaginationDropdown().exists()).toBe(true); + }); + + it('updates page size when selected in Dropdown', async () => { + const otherOption = wrapper.findAllComponents(GlDropdownItem).at(1); + expect(otherOption.text()).toMatchInterpolatedText('50 items per page'); + + otherOption.vm.$emit('click'); + await waitForPromises(); + + expect(findPaginationDropdownText()).toMatchInterpolatedText('50 items per page'); + }); + it('updates page when page change is requested', async () => { const REQUESTED_PAGE = 2; wrapper.find(PaginationLinks).props().change(REQUESTED_PAGE); @@ -179,7 +210,7 @@ describe('import table', () => { wrapper.find(PaginationLinks).props().change(REQUESTED_PAGE); await waitForPromises(); - expect(wrapper.text()).toContain('Showing 21-21 of 38'); + expect(wrapper.text()).toContain('Showing 21-21 of 38 groups from'); }); }); @@ -225,7 +256,7 @@ describe('import table', () => { findFilterInput().vm.$emit('submit', FILTER_VALUE); await waitForPromises(); - expect(wrapper.text()).toContain('Showing 1-1 of 40 groups matching filter "foo"'); + expect(wrapper.text()).toContain('Showing 1-1 of 40 groups matching filter "foo" from'); }); it('properly resets filter in graphql query when search box is cleared', async () => { diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js index 64febd7311c..9541461097b 100644 --- a/spec/frontend/pipelines/pipelines_table_spec.js +++ b/spec/frontend/pipelines/pipelines_table_spec.js @@ -1,4 +1,6 @@ +import { GlTable } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import PipelinesTable from '~/pipelines/components/pipelines_list/pipelines_table.vue'; describe('Pipelines Table', () => { @@ -12,20 +14,28 @@ describe('Pipelines Table', () => { viewType: 'root', }; - const createComponent = (props = defaultProps) => { - wrapper = mount(PipelinesTable, { - propsData: props, - }); + const createComponent = (props = defaultProps, flagState = false) => { + wrapper = extendedWrapper( + mount(PipelinesTable, { + propsData: props, + provide: { + glFeatures: { + newPipelinesTable: flagState, + }, + }, + }), + ); }; + const findRows = () => wrapper.findAll('.commit.gl-responsive-table-row'); + const findGlTable = () => wrapper.findComponent(GlTable); + const findLegacyTable = () => wrapper.findByTestId('ci-table'); preloadFixtures(jsonFixtureName); beforeEach(() => { const { pipelines } = getJSONFixture(jsonFixtureName); pipeline = pipelines.find((p) => p.user !== null && p.commit !== null); - - createComponent(); }); afterEach(() => { @@ -33,33 +43,50 @@ describe('Pipelines Table', () => { wrapper = null; }); - describe('table', () => { - it('should render a table', () => { - expect(wrapper.classes()).toContain('ci-table'); - }); + describe('table with feature flag off', () => { + describe('renders the table correctly', () => { + beforeEach(() => { + createComponent(); + }); + + it('should render a table', () => { + expect(wrapper.classes()).toContain('ci-table'); + }); - it('should render table head with correct columns', () => { - expect(wrapper.find('.table-section.js-pipeline-status').text()).toEqual('Status'); + it('should render table head with correct columns', () => { + expect(wrapper.find('.table-section.js-pipeline-status').text()).toEqual('Status'); - expect(wrapper.find('.table-section.js-pipeline-info').text()).toEqual('Pipeline'); + expect(wrapper.find('.table-section.js-pipeline-info').text()).toEqual('Pipeline'); - expect(wrapper.find('.table-section.js-pipeline-commit').text()).toEqual('Commit'); + expect(wrapper.find('.table-section.js-pipeline-commit').text()).toEqual('Commit'); - expect(wrapper.find('.table-section.js-pipeline-stages').text()).toEqual('Stages'); + expect(wrapper.find('.table-section.js-pipeline-stages').text()).toEqual('Stages'); + }); }); - }); - describe('without data', () => { - it('should render an empty table', () => { - expect(findRows()).toHaveLength(0); + describe('without data', () => { + it('should render an empty table', () => { + createComponent(); + + expect(findRows()).toHaveLength(0); + }); + }); + + describe('with data', () => { + it('should render rows', () => { + createComponent({ pipelines: [pipeline], viewType: 'root' }); + + expect(findRows()).toHaveLength(1); + }); }); }); - describe('with data', () => { - it('should render rows', () => { - createComponent({ pipelines: [pipeline], viewType: 'root' }); + describe('table with feature flag on', () => { + it('displays new table', () => { + createComponent(defaultProps, true); - expect(findRows()).toHaveLength(1); + expect(findGlTable().exists()).toBe(true); + expect(findLegacyTable().exists()).toBe(false); }); }); }); diff --git a/spec/frontend/pipelines/time_ago_spec.js b/spec/frontend/pipelines/time_ago_spec.js index 55a19ef5165..4919efbb4c6 100644 --- a/spec/frontend/pipelines/time_ago_spec.js +++ b/spec/frontend/pipelines/time_ago_spec.js @@ -8,7 +8,11 @@ describe('Timeago component', () => { const createComponent = (props = {}) => { wrapper = shallowMount(TimeAgo, { propsData: { - ...props, + pipeline: { + details: { + ...props, + }, + }, }, data() { return { @@ -28,7 +32,7 @@ describe('Timeago component', () => { describe('with duration', () => { beforeEach(() => { - createComponent({ duration: 10, finishedTime: '' }); + createComponent({ duration: 10, finished_at: '' }); }); it('should render duration and timer svg', () => { @@ -41,7 +45,7 @@ describe('Timeago component', () => { describe('without duration', () => { beforeEach(() => { - createComponent({ duration: 0, finishedTime: '' }); + createComponent({ duration: 0, finished_at: '' }); }); it('should not render duration and timer svg', () => { @@ -51,7 +55,7 @@ describe('Timeago component', () => { describe('with finishedTime', () => { beforeEach(() => { - createComponent({ duration: 0, finishedTime: '2017-04-26T12:40:23.277Z' }); + createComponent({ duration: 0, finished_at: '2017-04-26T12:40:23.277Z' }); }); it('should render time and calendar icon', () => { @@ -66,7 +70,7 @@ describe('Timeago component', () => { describe('without finishedTime', () => { beforeEach(() => { - createComponent({ duration: 0, finishedTime: '' }); + createComponent({ duration: 0, finished_at: '' }); }); it('should not render time and calendar icon', () => { diff --git a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js index 7c67149b517..9f6878db785 100644 --- a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js +++ b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js @@ -7,6 +7,8 @@ import userDataMock from '../../user_data_mock'; describe('UncollapsedReviewerList component', () => { let wrapper; + const reviewerApprovalIcons = () => wrapper.findAll('[data-testid="re-approved"]'); + function createComponent(props = {}) { const propsData = { users: [], @@ -58,19 +60,29 @@ describe('UncollapsedReviewerList component', () => { const user = userDataMock(); createComponent({ - users: [user, { ...user, id: 2, username: 'hello-world' }], + users: [user, { ...user, id: 2, username: 'hello-world', approved: true }], }); }); - it('only has one user', () => { + it('has both users', () => { expect(wrapper.findAll(ReviewerAvatarLink).length).toBe(2); }); - it('shows one user with avatar, username and author name', () => { + it('shows both users with avatar, username and author name', () => { expect(wrapper.text()).toContain(`@root`); expect(wrapper.text()).toContain(`@hello-world`); }); + it('renders approval icon', () => { + expect(reviewerApprovalIcons().length).toBe(1); + }); + + it('shows that hello-world approved', () => { + const icon = reviewerApprovalIcons().at(0); + + expect(icon.attributes('title')).toEqual('Approved by @hello-world'); + }); + it('renders re-request loading icon', async () => { await wrapper.setData({ loadingStates: { 2: 'loading' } }); diff --git a/spec/frontend/sidebar/user_data_mock.js b/spec/frontend/sidebar/user_data_mock.js index 41d0331f34a..7c11551b0be 100644 --- a/spec/frontend/sidebar/user_data_mock.js +++ b/spec/frontend/sidebar/user_data_mock.js @@ -10,4 +10,5 @@ export default () => ({ can_merge: true, can_update_merge_request: true, reviewed: true, + approved: false, }); diff --git a/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js b/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js index 99671f1ffb7..566ca1817f2 100644 --- a/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js +++ b/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js @@ -1,3 +1,4 @@ +import { GlDropdown } from '@gitlab/ui'; import { getByText } from '@testing-library/dom'; import { shallowMount } from '@vue/test-utils'; import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue'; @@ -25,6 +26,9 @@ describe('MultiSelectDropdown Component', () => { slots: { search: '<p>Search</p>', }, + stubs: { + GlDropdown, + }, }); expect(getByText(wrapper.element, 'Search')).toBeDefined(); }); diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb index ea63406e615..366c3f68e1d 100644 --- a/spec/models/project_services/prometheus_service_spec.rb +++ b/spec/models/project_services/prometheus_service_spec.rb @@ -511,20 +511,23 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl type: 'checkbox', name: 'manual_configuration', title: s_('PrometheusService|Active'), + help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'), required: true }, { type: 'text', name: 'api_url', title: 'API URL', - placeholder: s_('PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/'), + placeholder: s_('PrometheusService|https://prometheus.example.com/'), + help: s_('PrometheusService|The Prometheus API base URL.'), required: true }, { type: 'text', name: 'google_iap_audience_client_id', title: 'Google IAP Audience Client ID', - placeholder: s_('PrometheusService|Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)'), + placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'), + help: s_('PrometheusService|PrometheusService|The ID of the IAP-secured resource.'), autocomplete: 'off', required: false }, @@ -532,7 +535,8 @@ RSpec.describe PrometheusService, :use_clean_rails_memory_store_caching, :snowpl type: 'textarea', name: 'google_iap_service_account_json', title: 'Google IAP Service Account JSON', - placeholder: s_('PrometheusService|Contents of the credentials.json file of your service account, like: { "type": "service_account", "project_id": ... }'), + placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'), + help: s_('PrometheusService|The contents of the credentials.json file of your service account.'), required: false } ] diff --git a/spec/serializers/merge_request_user_entity_spec.rb b/spec/serializers/merge_request_user_entity_spec.rb index dcd4ef6acfb..697fa3001e3 100644 --- a/spec/serializers/merge_request_user_entity_spec.rb +++ b/spec/serializers/merge_request_user_entity_spec.rb @@ -3,19 +3,22 @@ require 'spec_helper' RSpec.describe MergeRequestUserEntity do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:request) { EntityRequest.new(project: project, current_user: user) } + let_it_be(:user) { create(:user) } + let_it_be(:merge_request) { create(:merge_request) } + let(:request) { EntityRequest.new(project: merge_request.target_project, current_user: user) } let(:entity) do - described_class.new(user, request: request) + described_class.new(user, request: request, merge_request: merge_request) end - context 'as json' do + describe '#as_json' do subject { entity.as_json } it 'exposes needed attributes' do - expect(subject).to include(:id, :name, :username, :state, :avatar_url, :web_url, :can_merge) + is_expected.to include( + :id, :name, :username, :state, :avatar_url, :web_url, + :can_merge, :can_update_merge_request, :reviewed, :approved + ) end context 'when `status` is not preloaded' do @@ -24,6 +27,22 @@ RSpec.describe MergeRequestUserEntity do end end + context 'when the user has not approved the merge-request' do + it 'exposes that the user has not approved the MR' do + expect(subject).to include(approved: false) + end + end + + context 'when the user has approved the merge-request' do + before do + merge_request.approvals.create!(user: user) + end + + it 'exposes that the user has approved the MR' do + expect(subject).to include(approved: true) + end + end + context 'when `status` is preloaded' do before do user.create_status!(availability: :busy) @@ -35,5 +54,27 @@ RSpec.describe MergeRequestUserEntity do expect(subject[:availability]).to eq('busy') end end + + describe 'performance' do + let_it_be(:user_a) { create(:user) } + let_it_be(:user_b) { create(:user) } + let_it_be(:merge_request_b) { create(:merge_request) } + + it 'is linear in the number of merge requests' do + pending "See: https://gitlab.com/gitlab-org/gitlab/-/issues/322549" + baseline = ActiveRecord::QueryRecorder.new do + ent = described_class.new(user_a, request: request, merge_request: merge_request) + ent.as_json + end + + expect do + a = described_class.new(user_a, request: request, merge_request: merge_request_b) + b = described_class.new(user_b, request: request, merge_request: merge_request_b) + + a.as_json + b.as_json + end.not_to exceed_query_limit(baseline) + end + end end end diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb index 22b3456708f..8adf6d69f73 100644 --- a/spec/services/merge_requests/build_service_spec.rb +++ b/spec/services/merge_requests/build_service_spec.rb @@ -19,8 +19,21 @@ RSpec.describe MergeRequests::BuildService do let(:label_ids) { [] } let(:merge_request) { service.execute } let(:compare) { double(:compare, commits: commits) } - let(:commit_1) { double(:commit_1, sha: 'f00ba7', safe_message: "Initial commit\n\nCreate the app") } - let(:commit_2) { double(:commit_2, sha: 'f00ba7', safe_message: 'This is a bad commit message!') } + let(:commit_1) do + double(:commit_1, sha: 'f00ba6', safe_message: 'Initial commit', + gitaly_commit?: false, id: 'f00ba6', parent_ids: ['f00ba5']) + end + + let(:commit_2) do + double(:commit_2, sha: 'f00ba7', safe_message: "Closes #1234 Second commit\n\nCreate the app", + gitaly_commit?: false, id: 'f00ba7', parent_ids: ['f00ba6']) + end + + let(:commit_3) do + double(:commit_3, sha: 'f00ba8', safe_message: 'This is a bad commit message!', + gitaly_commit?: false, id: 'f00ba8', parent_ids: ['f00ba7']) + end + let(:commits) { nil } let(:params) do @@ -47,6 +60,7 @@ RSpec.describe MergeRequests::BuildService do allow(CompareService).to receive_message_chain(:new, :execute).and_return(compare) allow(project).to receive(:commit).and_return(commit_1) allow(project).to receive(:commit).and_return(commit_2) + allow(project).to receive(:commit).and_return(commit_3) end shared_examples 'allows the merge request to be created' do @@ -137,7 +151,7 @@ RSpec.describe MergeRequests::BuildService do context 'when target branch is missing' do let(:target_branch) { nil } - let(:commits) { Commit.decorate([commit_1], project) } + let(:commits) { Commit.decorate([commit_2], project) } before do stub_compare @@ -199,8 +213,8 @@ RSpec.describe MergeRequests::BuildService do end context 'one commit in the diff' do - let(:commits) { Commit.decorate([commit_1], project) } - let(:commit_description) { commit_1.safe_message.split(/\n+/, 2).last } + let(:commits) { Commit.decorate([commit_2], project) } + let(:commit_description) { commit_2.safe_message.split(/\n+/, 2).last } before do stub_compare @@ -209,7 +223,7 @@ RSpec.describe MergeRequests::BuildService do it_behaves_like 'allows the merge request to be created' it 'uses the title of the commit as the title of the merge request' do - expect(merge_request.title).to eq(commit_1.safe_message.split("\n").first) + expect(merge_request.title).to eq(commit_2.safe_message.split("\n").first) end it 'uses the description of the commit as the description of the merge request' do @@ -225,10 +239,10 @@ RSpec.describe MergeRequests::BuildService do end context 'commit has no description' do - let(:commits) { Commit.decorate([commit_2], project) } + let(:commits) { Commit.decorate([commit_3], project) } it 'uses the title of the commit as the title of the merge request' do - expect(merge_request.title).to eq(commit_2.safe_message) + expect(merge_request.title).to eq(commit_3.safe_message) end it 'sets the description to nil' do @@ -257,7 +271,7 @@ RSpec.describe MergeRequests::BuildService do end it 'uses the title of the commit as the title of the merge request' do - expect(merge_request.title).to eq('Initial commit') + expect(merge_request.title).to eq('Closes #1234 Second commit') end it 'appends the closing description' do @@ -310,8 +324,8 @@ RSpec.describe MergeRequests::BuildService do end end - context 'more than one commit in the diff' do - let(:commits) { Commit.decorate([commit_1, commit_2], project) } + context 'no multi-line commit messages in the diff' do + let(:commits) { Commit.decorate([commit_1, commit_3], project) } before do stub_compare @@ -365,6 +379,55 @@ RSpec.describe MergeRequests::BuildService do end end end + end + + context 'a multi-line commit message in the diff' do + let(:commits) { Commit.decorate([commit_1, commit_2, commit_3], project) } + + before do + stub_compare + end + + it_behaves_like 'allows the merge request to be created' + + it 'uses the first line of the first multi-line commit message as the title' do + expect(merge_request.title).to eq('Closes #1234 Second commit') + end + + it 'adds the remaining lines of the first multi-line commit message as the description' do + expect(merge_request.description).to eq('Create the app') + end + + context 'when the source branch matches an issue' do + where(:issue_tracker, :source_branch, :title, :closing_message) do + :jira | 'FOO-123-fix-issue' | 'Resolve FOO-123 "Fix issue"' | 'Closes FOO-123' + :jira | 'fix-issue' | 'Fix issue' | nil + :custom_issue_tracker | '123-fix-issue' | 'Resolve #123 "Fix issue"' | 'Closes #123' + :custom_issue_tracker | 'fix-issue' | 'Fix issue' | nil + :internal | '123-fix-issue' | 'Resolve "A bug"' | 'Closes #123' + :internal | 'fix-issue' | 'Fix issue' | nil + :internal | '124-fix-issue' | '124 fix issue' | nil + end + + with_them do + before do + if issue_tracker == :internal + issue.update!(iid: 123) + else + create(:"#{issue_tracker}_service", project: project) + project.reload + end + end + + it 'sets the correct title' do + expect(merge_request.title).to eq('Closes #1234 Second commit') + end + + it 'sets the closing description' do + expect(merge_request.description).to eq("Create the app#{closing_message ? "\n\n" + closing_message : ''}") + end + end + end context 'when the issue is not accessible to user' do let(:source_branch) { "#{issue.iid}-fix-issue" } @@ -373,12 +436,12 @@ RSpec.describe MergeRequests::BuildService do project.team.truncate end - it 'uses branch title as the merge request title' do - expect(merge_request.title).to eq("#{issue.iid} fix issue") + it 'uses the first line of the first multi-line commit message as the title' do + expect(merge_request.title).to eq('Closes #1234 Second commit') end - it 'does not set a description' do - expect(merge_request.description).to be_nil + it 'adds the remaining lines of the first multi-line commit message as the description' do + expect(merge_request.description).to eq('Create the app') end end @@ -386,12 +449,12 @@ RSpec.describe MergeRequests::BuildService do let(:source_branch) { "#{issue.iid}-fix-issue" } let(:issue_confidential) { true } - it 'uses the title of the branch as the merge request title' do - expect(merge_request.title).to eq("#{issue.iid} fix issue") + it 'uses the first line of the first multi-line commit message as the title' do + expect(merge_request.title).to eq('Closes #1234 Second commit') end - it 'does not set a description' do - expect(merge_request.description).to be_nil + it 'adds the remaining lines of the first multi-line commit message as the description' do + expect(merge_request.description).to eq('Create the app') end end end @@ -399,7 +462,7 @@ RSpec.describe MergeRequests::BuildService do context 'source branch does not exist' do before do allow(project).to receive(:commit).with(source_branch).and_return(nil) - allow(project).to receive(:commit).with(target_branch).and_return(commit_1) + allow(project).to receive(:commit).with(target_branch).and_return(commit_2) end it_behaves_like 'forbids the merge request from being created' do @@ -409,7 +472,7 @@ RSpec.describe MergeRequests::BuildService do context 'target branch does not exist' do before do - allow(project).to receive(:commit).with(source_branch).and_return(commit_1) + allow(project).to receive(:commit).with(source_branch).and_return(commit_2) allow(project).to receive(:commit).with(target_branch).and_return(nil) end @@ -433,7 +496,7 @@ RSpec.describe MergeRequests::BuildService do context 'upstream project has disabled merge requests' do let(:upstream_project) { create(:project, :merge_requests_disabled) } let(:project) { create(:project, forked_from_project: upstream_project) } - let(:commits) { Commit.decorate([commit_1], project) } + let(:commits) { Commit.decorate([commit_2], project) } it 'sets target project correctly' do expect(merge_request.target_project).to eq(project) @@ -441,8 +504,8 @@ RSpec.describe MergeRequests::BuildService do end context 'target_project is set and accessible by current_user' do - let(:target_project) { create(:project, :public, :repository)} - let(:commits) { Commit.decorate([commit_1], project) } + let(:target_project) { create(:project, :public, :repository) } + let(:commits) { Commit.decorate([commit_2], project) } it 'sets target project correctly' do expect(merge_request.target_project).to eq(target_project) @@ -450,8 +513,8 @@ RSpec.describe MergeRequests::BuildService do end context 'target_project is set but not accessible by current_user' do - let(:target_project) { create(:project, :private, :repository)} - let(:commits) { Commit.decorate([commit_1], project) } + let(:target_project) { create(:project, :private, :repository) } + let(:commits) { Commit.decorate([commit_2], project) } it 'sets target project correctly' do expect(merge_request.target_project).to eq(project) @@ -469,8 +532,8 @@ RSpec.describe MergeRequests::BuildService do end context 'source_project is set and accessible by current_user' do - let(:source_project) { create(:project, :public, :repository)} - let(:commits) { Commit.decorate([commit_1], project) } + let(:source_project) { create(:project, :public, :repository) } + let(:commits) { Commit.decorate([commit_2], project) } before do # To create merge requests _from_ a project the user needs at least @@ -484,8 +547,8 @@ RSpec.describe MergeRequests::BuildService do end context 'source_project is set but not accessible by current_user' do - let(:source_project) { create(:project, :private, :repository)} - let(:commits) { Commit.decorate([commit_1], project) } + let(:source_project) { create(:project, :private, :repository) } + let(:commits) { Commit.decorate([commit_2], project) } it 'sets source project correctly' do expect(merge_request.source_project).to eq(project) diff --git a/spec/tasks/admin_mode_spec.rb b/spec/tasks/admin_mode_spec.rb new file mode 100644 index 00000000000..9dd35650ab6 --- /dev/null +++ b/spec/tasks/admin_mode_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'rake_helper' + +RSpec.describe 'admin mode on tasks' do + before do + allow(::Gitlab::Runtime).to receive(:test_suite?).and_return(false) + allow(::Gitlab::Runtime).to receive(:rake?).and_return(true) + end + + shared_examples 'verify admin mode' do |state| + it 'matches the expected admin mode' do + Rake::Task.define_task :verify_admin_mode do + expect(Gitlab::Auth::CurrentUserMode.new(user).admin_mode?).to be(state) + end + + run_rake_task('verify_admin_mode') + end + end + + describe 'with a regular user' do + let(:user) { create(:user) } + + include_examples 'verify admin mode', false + end + + describe 'with an admin' do + let(:user) { create(:admin) } + + include_examples 'verify admin mode', true + end +end diff --git a/spec/views/projects/settings/operations/show.html.haml_spec.rb b/spec/views/projects/settings/operations/show.html.haml_spec.rb index a22853d40d8..b2dd3556098 100644 --- a/spec/views/projects/settings/operations/show.html.haml_spec.rb +++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb @@ -59,7 +59,7 @@ RSpec.describe 'projects/settings/operations/show' do expect(rendered).to have_content _('Prometheus') expect(rendered).to have_content _('Link Prometheus monitoring to GitLab.') - expect(rendered).to have_content _('To enable the installation of Prometheus on your clusters, deactivate the manual configuration below') + expect(rendered).to have_content _('To enable the installation of Prometheus on your clusters, deactivate the manual configuration.') end end @@ -71,7 +71,7 @@ RSpec.describe 'projects/settings/operations/show' do it 'renders the Operations Settings page' do render - expect(rendered).not_to have_content _('Select the Active checkbox to override the Auto Configuration with custom settings. If unchecked, Auto Configuration settings are used.') + expect(rendered).not_to have_content _('Auto configuration settings are used unless you override their values here.') end end end |