diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-07 06:07:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-07 06:07:43 +0300 |
commit | d0db90848503511d758f29c16a93a1e2b1c3da47 (patch) | |
tree | 58240f1bc91479c60d78114ecccaa97516e9245a /spec | |
parent | defeeba1a8d6fa8784db1c50ca4ff9e8b56f539c (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
30 files changed, 316 insertions, 194 deletions
diff --git a/spec/features/merge_request/user_sees_real_time_reviewers_spec.rb b/spec/features/merge_request/user_sees_real_time_reviewers_spec.rb new file mode 100644 index 00000000000..e967787d2c7 --- /dev/null +++ b/spec/features/merge_request/user_sees_real_time_reviewers_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Merge request > Real-time reviewers', feature_category: :code_review_workflow do + let_it_be(:project) { create(:project, :public, :repository) } + let(:user) { project.creator } + let(:merge_request) { create(:merge_request, :simple, source_project: project, author: user) } + + before do + sign_in(user) + visit project_merge_request_path(project, merge_request) + end + + it 'updates in real-time', :js do + wait_for_requests + + # Simulate a real-time update of reviewers + merge_request.update!(reviewer_ids: [user.id]) + GraphqlTriggers.merge_request_reviewers_updated(merge_request) + + expect(find('.reviewer')).to have_content(user.name) + end +end diff --git a/spec/frontend/access_tokens/components/new_access_token_app_spec.js b/spec/frontend/access_tokens/components/new_access_token_app_spec.js index e4313bdfa26..753e693cc85 100644 --- a/spec/frontend/access_tokens/components/new_access_token_app_spec.js +++ b/spec/frontend/access_tokens/components/new_access_token_app_spec.js @@ -4,12 +4,12 @@ import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import NewAccessTokenApp from '~/access_tokens/components/new_access_token_app.vue'; import { EVENT_ERROR, EVENT_SUCCESS, FORM_SELECTOR } from '~/access_tokens/components/constants'; -import { createAlert, VARIANT_INFO } from '~/flash'; +import { createAlert, VARIANT_INFO } from '~/alert'; import { __, sprintf } from '~/locale'; import DomElementListener from '~/vue_shared/components/dom_element_listener.vue'; import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('~/access_tokens/components/new_access_token_app', () => { let wrapper; diff --git a/spec/frontend/contributors/store/actions_spec.js b/spec/frontend/contributors/store/actions_spec.js index 72b22548aa2..a15b9ad2978 100644 --- a/spec/frontend/contributors/store/actions_spec.js +++ b/spec/frontend/contributors/store/actions_spec.js @@ -2,11 +2,11 @@ import MockAdapter from 'axios-mock-adapter'; import testAction from 'helpers/vuex_action_helper'; import * as actions from '~/contributors/stores/actions'; import * as types from '~/contributors/stores/mutation_types'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Contributors store actions', () => { describe('fetchChartData', () => { @@ -38,7 +38,7 @@ describe('Contributors store actions', () => { ); }); - it('should show flash on API error', async () => { + it('should show alert on API error', async () => { mock.onGet().reply(HTTP_STATUS_BAD_REQUEST, 'Not Found'); await testAction( diff --git a/spec/frontend/deploy_freeze/store/actions_spec.js b/spec/frontend/deploy_freeze/store/actions_spec.js index cd823e1fc28..d39577baa59 100644 --- a/spec/frontend/deploy_freeze/store/actions_spec.js +++ b/spec/frontend/deploy_freeze/store/actions_spec.js @@ -4,14 +4,14 @@ import Api from '~/api'; import * as actions from '~/deploy_freeze/store/actions'; import * as types from '~/deploy_freeze/store/mutation_types'; import getInitialState from '~/deploy_freeze/store/state'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import * as logger from '~/lib/logger'; import axios from '~/lib/utils/axios_utils'; import { freezePeriodsFixture } from '../helpers'; import { timezoneDataFixture } from '../../vue_shared/components/timezone_dropdown/helpers'; jest.mock('~/api.js'); -jest.mock('~/flash'); +jest.mock('~/alert'); describe('deploy freeze store actions', () => { const freezePeriodFixture = freezePeriodsFixture[0]; diff --git a/spec/frontend/filtered_search/filtered_search_manager_spec.js b/spec/frontend/filtered_search/filtered_search_manager_spec.js index 26af7af701b..8c16ff100eb 100644 --- a/spec/frontend/filtered_search/filtered_search_manager_spec.js +++ b/spec/frontend/filtered_search/filtered_search_manager_spec.js @@ -8,11 +8,11 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered import RecentSearchesRoot from '~/filtered_search/recent_searches_root'; import RecentSearchesService from '~/filtered_search/services/recent_searches_service'; import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from '~/lib/utils/keycodes'; import { visitUrl, getParameterByName } from '~/lib/utils/url_utility'; -jest.mock('~/flash'); +jest.mock('~/alert'); jest.mock('~/lib/utils/url_utility', () => ({ ...jest.requireActual('~/lib/utils/url_utility'), getParameterByName: jest.fn(), diff --git a/spec/frontend/filtered_search/visual_token_value_spec.js b/spec/frontend/filtered_search/visual_token_value_spec.js index d3fa8fae9ab..138a4e183a9 100644 --- a/spec/frontend/filtered_search/visual_token_value_spec.js +++ b/spec/frontend/filtered_search/visual_token_value_spec.js @@ -5,11 +5,11 @@ import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper'; import { TEST_HOST } from 'helpers/test_constants'; import DropdownUtils from '~/filtered_search/dropdown_utils'; import VisualTokenValue from '~/filtered_search/visual_token_value'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import AjaxCache from '~/lib/utils/ajax_cache'; import UsersCache from '~/lib/utils/users_cache'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Filtered Search Visual Tokens', () => { const findElements = (tokenElement) => { diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js index 4e6ddd89a55..ec397cc44f9 100644 --- a/spec/frontend/groups/components/app_spec.js +++ b/spec/frontend/groups/components/app_spec.js @@ -3,7 +3,7 @@ import AxiosMockAdapter from 'axios-mock-adapter'; import Vue, { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import appComponent from '~/groups/components/app.vue'; import groupFolderComponent from '~/groups/components/group_folder.vue'; import groupItemComponent from '~/groups/components/group_item.vue'; @@ -34,7 +34,7 @@ import { const $toast = { show: jest.fn(), }; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('AppComponent', () => { let wrapper; @@ -117,7 +117,7 @@ describe('AppComponent', () => { }); }); - it('should show flash error when request fails', () => { + it('should show alert error when request fails', () => { mock.onGet('/dashboard/groups.json').reply(HTTP_STATUS_BAD_REQUEST); jest.spyOn(window, 'scrollTo').mockImplementation(() => {}); @@ -325,7 +325,7 @@ describe('AppComponent', () => { }); }); - it('should show error flash message if request failed to leave group', () => { + it('should show error alert message if request failed to leave group', () => { const message = 'An error occurred. Please try again.'; jest .spyOn(vm.service, 'leaveGroup') @@ -342,7 +342,7 @@ describe('AppComponent', () => { }); }); - it('should show appropriate error flash message if request forbids to leave group', () => { + it('should show appropriate error alert message if request forbids to leave group', () => { const message = 'Failed to leave the group. Please make sure you are not the only owner.'; jest.spyOn(vm.service, 'leaveGroup').mockRejectedValue({ status: HTTP_STATUS_FORBIDDEN }); jest.spyOn(vm.store, 'removeGroup'); diff --git a/spec/frontend/groups/components/group_name_and_path_spec.js b/spec/frontend/groups/components/group_name_and_path_spec.js index 9965b608f27..0a18e657c94 100644 --- a/spec/frontend/groups/components/group_name_and_path_spec.js +++ b/spec/frontend/groups/components/group_name_and_path_spec.js @@ -7,11 +7,11 @@ import waitForPromises from 'helpers/wait_for_promises'; import createMockApollo from 'helpers/mock_apollo_helper'; import GroupNameAndPath from '~/groups/components/group_name_and_path.vue'; import { getGroupPathAvailability } from '~/rest_api'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { helpPagePath } from '~/helpers/help_page_helper'; import searchGroupsWhereUserCanCreateSubgroups from '~/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql'; -jest.mock('~/flash'); +jest.mock('~/alert'); jest.mock('~/rest_api', () => ({ getGroupPathAvailability: jest.fn(), })); diff --git a/spec/frontend/header_search/store/actions_spec.js b/spec/frontend/header_search/store/actions_spec.js index bd93b0edadf..95a619ebeca 100644 --- a/spec/frontend/header_search/store/actions_spec.js +++ b/spec/frontend/header_search/store/actions_spec.js @@ -16,7 +16,7 @@ import { MOCK_ISSUE_PATH, } from '../mock_data'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Header Search Store Actions', () => { let state; diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js index 96c0b87e2cb..337a7c9a175 100644 --- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js +++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js @@ -7,7 +7,7 @@ import { issuable1, issuable2, } from 'jest/issuable/components/related_issuable_mock_data'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_CONFLICT, @@ -19,7 +19,7 @@ import RelatedIssuesBlock from '~/related_issues/components/related_issues_block import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue'; import relatedIssuesService from '~/related_issues/services/related_issues_service'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('RelatedIssuesRoot', () => { let wrapper; diff --git a/spec/frontend/merge_request_spec.js b/spec/frontend/merge_request_spec.js index 579cee8c022..be16b5ebfd2 100644 --- a/spec/frontend/merge_request_spec.js +++ b/spec/frontend/merge_request_spec.js @@ -3,12 +3,12 @@ import $ from 'jquery'; import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import { TEST_HOST } from 'spec/test_constants'; import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_CONFLICT, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import MergeRequest from '~/merge_request'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('MergeRequest', () => { const test = {}; diff --git a/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js index d1da7cb3acf..24732e71d5d 100644 --- a/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js +++ b/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js @@ -4,7 +4,7 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import FailedJobsApp from '~/pipelines/components/jobs/failed_jobs_app.vue'; import FailedJobsTable from '~/pipelines/components/jobs/failed_jobs_table.vue'; import GetFailedJobsQuery from '~/pipelines/graphql/queries/get_failed_jobs.query.graphql'; @@ -12,7 +12,7 @@ import { mockFailedJobsQueryResponse, mockFailedJobsSummaryData } from '../../mo Vue.use(VueApollo); -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Failed Jobs App', () => { let wrapper; diff --git a/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js b/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js index 0df15afd70d..e2bb8906128 100644 --- a/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js +++ b/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js @@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { mountExtended } from 'helpers/vue_test_utils_helper'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { redirectTo } from '~/lib/utils/url_utility'; import FailedJobsTable from '~/pipelines/components/jobs/failed_jobs_table.vue'; import RetryFailedJobMutation from '~/pipelines/graphql/mutations/retry_failed_job.mutation.graphql'; @@ -15,7 +15,7 @@ import { mockPreparedFailedJobsDataNoPermission, } from '../../mock_data'; -jest.mock('~/flash'); +jest.mock('~/alert'); jest.mock('~/lib/utils/url_utility'); Vue.use(VueApollo); diff --git a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js index 9bc14266593..26dee132690 100644 --- a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js +++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js @@ -4,7 +4,7 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import JobsApp from '~/pipelines/components/jobs/jobs_app.vue'; import JobsTable from '~/jobs/components/table/jobs_table.vue'; import getPipelineJobsQuery from '~/pipelines/graphql/queries/get_pipeline_jobs.query.graphql'; @@ -12,7 +12,7 @@ import { mockPipelineJobsQueryResponse } from '../../mock_data'; Vue.use(VueApollo); -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Jobs app', () => { let wrapper; diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js index e034d52a33c..3b2a7c0a76d 100644 --- a/spec/frontend/pipelines/pipelines_actions_spec.js +++ b/spec/frontend/pipelines/pipelines_actions_spec.js @@ -5,7 +5,7 @@ import { nextTick } from 'vue'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { TEST_HOST } from 'spec/test_constants'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; @@ -13,7 +13,7 @@ import PipelinesManualActions from '~/pipelines/components/pipelines_list/pipeli import GlCountdown from '~/vue_shared/components/gl_countdown.vue'; import { TRACKING_CATEGORIES } from '~/pipelines/constants'; -jest.mock('~/flash'); +jest.mock('~/alert'); jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'); describe('Pipelines Actions dropdown', () => { diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index 2523b901506..67478f9307f 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -11,7 +11,7 @@ import { mockTracking } from 'helpers/tracking_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import Api from '~/api'; -import { createAlert, VARIANT_WARNING } from '~/flash'; +import { createAlert, VARIANT_WARNING } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue'; @@ -25,7 +25,7 @@ import TablePagination from '~/vue_shared/components/pagination/table_pagination import { stageReply, users, mockSearch, branches } from './mock_data'; -jest.mock('~/flash'); +jest.mock('~/alert'); const mockProjectPath = 'twitter/flight'; const mockProjectId = '21'; diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js index e813a63a53f..e05d2151f0a 100644 --- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js +++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js @@ -2,13 +2,13 @@ import MockAdapter from 'axios-mock-adapter'; import testReports from 'test_fixtures/pipelines/test_report.json'; import { TEST_HOST } from 'helpers/test_constants'; import testAction from 'helpers/vuex_action_helper'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import * as actions from '~/pipelines/stores/test_reports/actions'; import * as types from '~/pipelines/stores/test_reports/mutation_types'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Actions TestReports Store', () => { let mock; @@ -49,7 +49,7 @@ describe('Actions TestReports Store', () => { ); }); - it('should create flash on API error', async () => { + it('should create alert on API error', async () => { await testAction( actions.fetchSummary, null, diff --git a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js b/spec/frontend/pipelines/test_reports/stores/mutations_spec.js index 82c70c6db58..9c374ea817a 100644 --- a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js +++ b/spec/frontend/pipelines/test_reports/stores/mutations_spec.js @@ -1,9 +1,9 @@ import testReports from 'test_fixtures/pipelines/test_report.json'; import * as types from '~/pipelines/stores/test_reports/mutation_types'; import mutations from '~/pipelines/stores/test_reports/mutations'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Mutations TestReports Store', () => { let mockState; @@ -58,7 +58,7 @@ describe('Mutations TestReports Store', () => { expect(mockState.errorMessage).toBe(message); }); - it('should show a flash message otherwise', () => { + it('should show an alert message otherwise', () => { mutations[types.SET_SUITE_ERROR](mockState, {}); expect(createAlert).toHaveBeenCalled(); diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js index 0f270ff2491..cf0d4492305 100644 --- a/spec/frontend/search/store/actions_spec.js +++ b/spec/frontend/search/store/actions_spec.js @@ -1,7 +1,7 @@ import MockAdapter from 'axios-mock-adapter'; import testAction from 'helpers/vuex_action_helper'; import Api from '~/api'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import * as logger from '~/lib/logger'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; @@ -33,7 +33,7 @@ import { MOCK_AGGREGATIONS, } from '../mock_data'; -jest.mock('~/flash'); +jest.mock('~/alert'); jest.mock('~/lib/utils/url_utility', () => ({ setUrlParams: jest.fn(), joinPaths: jest.fn().mockReturnValue(''), @@ -47,7 +47,7 @@ describe('Global Search Store Actions', () => { let mock; let state; - const flashCallback = (callCount) => { + const alertCallback = (callCount) => { expect(createAlert).toHaveBeenCalledTimes(callCount); createAlert.mockClear(); }; @@ -63,12 +63,12 @@ describe('Global Search Store Actions', () => { }); describe.each` - action | axiosMock | type | expectedMutations | flashCallCount + action | axiosMock | type | expectedMutations | alertCallCount ${actions.fetchGroups} | ${{ method: 'onGet', code: HTTP_STATUS_OK, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${0} ${actions.fetchGroups} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${1} ${actions.fetchProjects} | ${{ method: 'onGet', code: HTTP_STATUS_OK, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${0} ${actions.fetchProjects} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${1} - `(`axios calls`, ({ action, axiosMock, type, expectedMutations, flashCallCount }) => { + `(`axios calls`, ({ action, axiosMock, type, expectedMutations, alertCallCount }) => { describe(action.name, () => { describe(`on ${type}`, () => { beforeEach(() => { @@ -76,7 +76,7 @@ describe('Global Search Store Actions', () => { }); it(`should dispatch the correct mutations`, () => { return testAction({ action, state, expectedMutations }).then(() => - flashCallback(flashCallCount), + alertCallback(alertCallCount), ); }); }); @@ -84,12 +84,12 @@ describe('Global Search Store Actions', () => { }); describe.each` - action | axiosMock | type | expectedMutations | flashCallCount + action | axiosMock | type | expectedMutations | alertCallCount ${actions.loadFrequentGroups} | ${{ method: 'onGet', code: HTTP_STATUS_OK }} | ${'success'} | ${[PROMISE_ALL_EXPECTED_MUTATIONS.resGroups]} | ${0} ${actions.loadFrequentGroups} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR }} | ${'error'} | ${[]} | ${1} ${actions.loadFrequentProjects} | ${{ method: 'onGet', code: HTTP_STATUS_OK }} | ${'success'} | ${[PROMISE_ALL_EXPECTED_MUTATIONS.resProjects]} | ${0} ${actions.loadFrequentProjects} | ${{ method: 'onGet', code: HTTP_STATUS_INTERNAL_SERVER_ERROR }} | ${'error'} | ${[]} | ${1} - `('Promise.all calls', ({ action, axiosMock, type, expectedMutations, flashCallCount }) => { + `('Promise.all calls', ({ action, axiosMock, type, expectedMutations, alertCallCount }) => { describe(action.name, () => { describe(`on ${type}`, () => { beforeEach(() => { @@ -103,7 +103,7 @@ describe('Global Search Store Actions', () => { it(`should dispatch the correct mutations`, () => { return testAction({ action, state, expectedMutations }).then(() => { - flashCallback(flashCallCount); + alertCallback(alertCallCount); }); }); }); diff --git a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js index 80a7565cbee..e78e1be7882 100644 --- a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js @@ -6,7 +6,7 @@ import approvedByCurrentUser from 'test_fixtures/graphql/merge_requests/approval import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import Approvals from '~/vue_merge_request_widget/components/approvals/approvals.vue'; import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue'; import ApprovalsSummaryOptional from '~/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue'; @@ -21,7 +21,7 @@ import { createCanApproveResponse } from 'jest/approvals/mock_data'; Vue.use(VueApollo); const mockAlertDismiss = jest.fn(); -jest.mock('~/flash', () => ({ +jest.mock('~/alert', () => ({ createAlert: jest.fn().mockImplementation(() => ({ dismiss: mockAlertDismiss, })), @@ -295,7 +295,7 @@ describe('MRWidget approvals', () => { return nextTick(); }); - it('flashes error message', () => { + it('alerts error message', () => { expect(createAlert).toHaveBeenCalledWith({ message: UNAPPROVE_ERROR }); }); }); diff --git a/spec/frontend/vue_merge_request_widget/components/states/work_in_progress_spec.js b/spec/frontend/vue_merge_request_widget/components/states/work_in_progress_spec.js index e610ceb2122..43ce1769ff3 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/work_in_progress_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/work_in_progress_spec.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import getStateQueryResponse from 'test_fixtures/graphql/merge_requests/get_state.query.graphql.json'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import WorkInProgress, { MSG_SOMETHING_WENT_WRONG, MSG_MARK_READY, @@ -22,7 +22,7 @@ const TEST_MR_IID = '23'; const TEST_MR_TITLE = 'Test MR Title'; const TEST_PROJECT_PATH = 'lorem/ipsum'; -jest.mock('~/flash'); +jest.mock('~/alert'); jest.mock('~/merge_request'); describe('~/vue_merge_request_widget/components/states/work_in_progress.vue', () => { diff --git a/spec/graphql/mutations/members/bulk_update_base_spec.rb b/spec/graphql/mutations/members/bulk_update_base_spec.rb new file mode 100644 index 00000000000..61a27984824 --- /dev/null +++ b/spec/graphql/mutations/members/bulk_update_base_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Members::BulkUpdateBase, feature_category: :subgroups do + include GraphqlHelpers + + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group).tap { |group| group.add_owner(user) } } + + it 'raises a NotImplementedError error if the source_type method is called on the base class' do + mutation = described_class.new(context: { current_user: user }, object: nil, field: nil) + + expect { mutation.resolve(group_id: group.to_gid.to_s) }.to raise_error(NotImplementedError) + end +end diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index a46f8c13f00..2318bbf861a 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -47,6 +47,12 @@ RSpec.describe DiffHelper do end describe 'diff_options' do + let(:large_notebooks_enabled) { false } + + before do + stub_feature_flags(large_ipynb_diffs: large_notebooks_enabled) + end + it 'returns no collapse false' do expect(diff_options).to include(expanded: false) end @@ -56,21 +62,48 @@ RSpec.describe DiffHelper do expect(diff_options).to include(expanded: true) end - it 'returns no collapse true if action name diff_for_path' do - allow(controller).to receive(:action_name) { 'diff_for_path' } - expect(diff_options).to include(expanded: true) - end + context 'when action name is diff_for_path' do + before do + allow(controller).to receive(:action_name) { 'diff_for_path' } + end - it 'returns paths if action name diff_for_path and param old path' do - allow(controller).to receive(:params) { { old_path: 'lib/wadus.rb' } } - allow(controller).to receive(:action_name) { 'diff_for_path' } - expect(diff_options[:paths]).to include('lib/wadus.rb') - end + it 'returns expanded true' do + expect(diff_options).to include(expanded: true) + end - it 'returns paths if action name diff_for_path and param new path' do - allow(controller).to receive(:params) { { new_path: 'lib/wadus.rb' } } - allow(controller).to receive(:action_name) { 'diff_for_path' } - expect(diff_options[:paths]).to include('lib/wadus.rb') + it 'returns paths if param old path' do + allow(controller).to receive(:params) { { old_path: 'lib/wadus.rb' } } + expect(diff_options[:paths]).to include('lib/wadus.rb') + end + + it 'returns paths if param new path' do + allow(controller).to receive(:params) { { new_path: 'lib/wadus.rb' } } + expect(diff_options[:paths]).to include('lib/wadus.rb') + end + + it 'does not set max_patch_bytes_for_file_extension' do + expect(diff_options[:max_patch_bytes_for_file_extension]).to be_nil + end + + context 'when file_identifier include .ipynb' do + before do + allow(controller).to receive(:params) { { file_identifier: 'something.ipynb' } } + end + + context 'when large_ipynb_diffs is disabled' do + it 'does not set max_patch_bytes_for_file_extension' do + expect(diff_options[:max_patch_bytes_for_file_extension]).to be_nil + end + end + + context 'when large_ipynb_diffs is enabled' do + let(:large_notebooks_enabled) { true } + + it 'sets max_patch_bytes_for_file_extension' do + expect(diff_options[:max_patch_bytes_for_file_extension]).to eq({ '.ipynb' => 1.megabyte }) + end + end + end end end diff --git a/spec/lib/gitlab/git/diff_collection_spec.rb b/spec/lib/gitlab/git/diff_collection_spec.rb index 7fa5bd8a92b..5fa0447091c 100644 --- a/spec/lib/gitlab/git/diff_collection_spec.rb +++ b/spec/lib/gitlab/git/diff_collection_spec.rb @@ -777,6 +777,26 @@ RSpec.describe Gitlab::Git::DiffCollection do end end + describe '.limits' do + let(:options) { {} } + + subject { described_class.limits(options) } + + context 'when options do not include max_patch_bytes_for_file_extension' do + it 'sets max_patch_bytes_for_file_extension as empty' do + expect(subject[:max_patch_bytes_for_file_extension]).to eq({}) + end + end + + context 'when options include max_patch_bytes_for_file_extension' do + let(:options) { { max_patch_bytes_for_file_extension: { '.file' => 1 } } } + + it 'sets value for max_patch_bytes_for_file_extension' do + expect(subject[:max_patch_bytes_for_file_extension]).to eq({ '.file' => 1 }) + end + end + end + def fake_diff(line_length, line_count) { 'diff' => "#{'a' * line_length}\n" * line_count } end diff --git a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb index 40ca2107698..b0631aacdb9 100644 --- a/spec/lib/sidebars/projects/menus/repository_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/repository_menu_spec.rb @@ -85,7 +85,7 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu, feature_category: :sou end end - describe 'Contributors' do + describe 'Contributor statistics' do let_it_be(:item_id) { :contributors } context 'when analytics is disabled' do diff --git a/spec/requests/api/graphql/mutations/members/groups/bulk_update_spec.rb b/spec/requests/api/graphql/mutations/members/groups/bulk_update_spec.rb index ad70129a7bc..f15b52f53a3 100644 --- a/spec/requests/api/graphql/mutations/members/groups/bulk_update_spec.rb +++ b/spec/requests/api/graphql/mutations/members/groups/bulk_update_spec.rb @@ -5,126 +5,14 @@ require 'spec_helper' RSpec.describe 'GroupMemberBulkUpdate', feature_category: :subgroups do include GraphqlHelpers - let_it_be(:current_user) { create(:user) } - let_it_be(:user1) { create(:user) } - let_it_be(:user2) { create(:user) } - let_it_be(:group) { create(:group) } - let_it_be(:group_member1) { create(:group_member, group: group, user: user1) } - let_it_be(:group_member2) { create(:group_member, group: group, user: user2) } + let_it_be(:parent_group) { create(:group) } + let_it_be(:parent_group_member) { create(:group_member, group: parent_group) } + let_it_be(:group) { create(:group, parent: parent_group) } + let_it_be(:source) { group } + let_it_be(:member_type) { :group_member } let_it_be(:mutation_name) { :group_member_bulk_update } + let_it_be(:source_id_key) { 'group_id' } + let_it_be(:response_member_field) { 'groupMembers' } - let(:input) do - { - 'group_id' => group.to_global_id.to_s, - 'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s], - 'access_level' => 'GUEST' - } - end - - let(:extra_params) { { expires_at: 10.days.from_now } } - let(:input_params) { input.merge(extra_params) } - let(:mutation) { graphql_mutation(mutation_name, input_params) } - let(:mutation_response) { graphql_mutation_response(mutation_name) } - - context 'when user is not logged-in' do - it_behaves_like 'a mutation that returns a top-level access error' - end - - context 'when user is not an owner' do - before do - group.add_maintainer(current_user) - end - - it_behaves_like 'a mutation that returns a top-level access error' - end - - context 'when user is an owner' do - before do - group.add_owner(current_user) - end - - shared_examples 'updates the user access role' do - specify do - post_graphql_mutation(mutation, current_user: current_user) - - new_access_levels = mutation_response['groupMembers'].map { |member| member['accessLevel']['integerValue'] } - expect(response).to have_gitlab_http_status(:success) - expect(mutation_response['errors']).to be_empty - expect(new_access_levels).to all(be Gitlab::Access::GUEST) - end - end - - it_behaves_like 'updates the user access role' - - context 'when inherited members are passed' do - let_it_be(:subgroup) { create(:group, parent: group) } - let_it_be(:subgroup_member) { create(:group_member, group: subgroup) } - - let(:input) do - { - 'group_id' => group.to_global_id.to_s, - 'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s, subgroup_member.user.to_global_id.to_s], - 'access_level' => 'GUEST' - } - end - - it 'does not update the members' do - post_graphql_mutation(mutation, current_user: current_user) - - error = Mutations::Members::Groups::BulkUpdate::INVALID_MEMBERS_ERROR - expect(json_response['errors'].first['message']).to include(error) - end - end - - context 'when members count is more than the allowed limit' do - let(:max_members_update_limit) { 1 } - - before do - stub_const('Mutations::Members::Groups::BulkUpdate::MAX_MEMBERS_UPDATE_LIMIT', max_members_update_limit) - end - - it 'does not update the members' do - post_graphql_mutation(mutation, current_user: current_user) - - error = Mutations::Members::Groups::BulkUpdate::MAX_MEMBERS_UPDATE_ERROR - expect(json_response['errors'].first['message']).to include(error) - end - end - - context 'when the update service raises access denied error' do - before do - allow_next_instance_of(Members::UpdateService) do |instance| - allow(instance).to receive(:execute).and_raise(Gitlab::Access::AccessDeniedError) - end - end - - it 'does not update the members' do - post_graphql_mutation(mutation, current_user: current_user) - - expect(mutation_response['groupMembers']).to be_nil - expect(mutation_response['errors']) - .to contain_exactly("Unable to update members, please check user permissions.") - end - end - - context 'when the update service returns an error message' do - before do - allow_next_instance_of(Members::UpdateService) do |instance| - error_result = { - message: 'Expires at cannot be a date in the past', - status: :error, - members: [group_member1] - } - allow(instance).to receive(:execute).and_return(error_result) - end - end - - it 'will pass through the error' do - post_graphql_mutation(mutation, current_user: current_user) - - expect(mutation_response['groupMembers'].first['id']).to eq(group_member1.to_global_id.to_s) - expect(mutation_response['errors']).to contain_exactly('Expires at cannot be a date in the past') - end - end - end + it_behaves_like 'members bulk update mutation' end diff --git a/spec/requests/api/graphql/mutations/members/projects/bulk_update_spec.rb b/spec/requests/api/graphql/mutations/members/projects/bulk_update_spec.rb new file mode 100644 index 00000000000..cbef9715cbe --- /dev/null +++ b/spec/requests/api/graphql/mutations/members/projects/bulk_update_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'ProjectMemberBulkUpdate', feature_category: :projects do + include GraphqlHelpers + + let_it_be(:parent_group) { create(:group) } + let_it_be(:parent_group_member) { create(:group_member, group: parent_group) } + let_it_be(:project) { create(:project, group: parent_group) } + let_it_be(:source) { project } + let_it_be(:member_type) { :project_member } + let_it_be(:mutation_name) { :project_member_bulk_update } + let_it_be(:source_id_key) { 'project_id' } + let_it_be(:response_member_field) { 'projectMembers' } + + it_behaves_like 'members bulk update mutation' +end diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb index e1ac0e3fd0a..3af0b30bca0 100644 --- a/spec/support/shared_contexts/navbar_structure_context.rb +++ b/spec/support/shared_contexts/navbar_structure_context.rb @@ -34,10 +34,10 @@ RSpec.shared_context 'project navbar structure' do _('Commits'), _('Branches'), _('Tags'), - _('Contributors'), + _('Contributor statistics'), _('Graph'), - _('Compare'), - (_('Locked Files') if Gitlab.ee?) + _('Compare revisions'), + (_('Locked files') if Gitlab.ee?) ] }, { diff --git a/spec/support/shared_examples/graphql/mutations/members/bulk_update_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/members/bulk_update_shared_examples.rb new file mode 100644 index 00000000000..e885b5d283e --- /dev/null +++ b/spec/support/shared_examples/graphql/mutations/members/bulk_update_shared_examples.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'members bulk update mutation' do + let_it_be(:current_user) { create(:user) } + let_it_be(:user1) { create(:user) } + let_it_be(:user2) { create(:user) } + let_it_be(:member1) { create(member_type, source: source, user: user1) } + let_it_be(:member2) { create(member_type, source: source, user: user2) } + + let(:extra_params) { { expires_at: 10.days.from_now } } + let(:input_params) { input.merge(extra_params) } + let(:mutation) { graphql_mutation(mutation_name, input_params) } + let(:mutation_response) { graphql_mutation_response(mutation_name) } + + let(:input) do + { + source_id_key => source.to_global_id.to_s, + 'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s], + 'access_level' => 'GUEST' + } + end + + context 'when user is not logged-in' do + it_behaves_like 'a mutation that returns a top-level access error' + end + + context 'when user is not an owner' do + before do + source.add_developer(current_user) + end + + it_behaves_like 'a mutation that returns a top-level access error' + end + + context 'when user is an owner' do + before do + source.add_owner(current_user) + end + + shared_examples 'updates the user access role' do + specify do + post_graphql_mutation(mutation, current_user: current_user) + + new_access_levels = mutation_response[response_member_field].map do |member| + member['accessLevel']['integerValue'] + end + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['errors']).to be_empty + expect(new_access_levels).to all(be Gitlab::Access::GUEST) + end + end + + it_behaves_like 'updates the user access role' + + context 'when inherited members are passed' do + let(:input) do + { + source_id_key => source.to_global_id.to_s, + 'user_ids' => [user1.to_global_id.to_s, user2.to_global_id.to_s, parent_group_member.user.to_global_id.to_s], + 'access_level' => 'GUEST' + } + end + + it 'does not update the members' do + post_graphql_mutation(mutation, current_user: current_user) + + error = Mutations::Members::BulkUpdateBase::INVALID_MEMBERS_ERROR + expect(json_response['errors'].first['message']).to include(error) + end + end + + context 'when members count is more than the allowed limit' do + let(:max_members_update_limit) { 1 } + + before do + stub_const('Mutations::Members::BulkUpdateBase::MAX_MEMBERS_UPDATE_LIMIT', max_members_update_limit) + end + + it 'does not update the members' do + post_graphql_mutation(mutation, current_user: current_user) + + error = Mutations::Members::BulkUpdateBase::MAX_MEMBERS_UPDATE_ERROR + expect(json_response['errors'].first['message']).to include(error) + end + end + + context 'when the update service raises access denied error' do + before do + allow_next_instance_of(Members::UpdateService) do |instance| + allow(instance).to receive(:execute).and_raise(Gitlab::Access::AccessDeniedError) + end + end + + it 'does not update the members' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response[response_member_field]).to be_nil + expect(mutation_response['errors']) + .to contain_exactly("Unable to update members, please check user permissions.") + end + end + + context 'when the update service returns an error message' do + before do + allow_next_instance_of(Members::UpdateService) do |instance| + error_result = { + message: 'Expires at cannot be a date in the past', + status: :error, + members: [member1] + } + allow(instance).to receive(:execute).and_return(error_result) + end + end + + it 'will pass through the error' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response[response_member_field].first['id']).to eq(member1.to_global_id.to_s) + expect(mutation_response['errors']).to contain_exactly('Expires at cannot be a date in the past') + end + end + end +end diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index dc9575dc767..0df490f9b41 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -106,11 +106,11 @@ RSpec.describe 'layouts/nav/sidebar/_project', feature_category: :navigation do end end - describe 'Contributors' do + describe 'Contributor statistics' do it 'has a link to the project contributors path' do render - expect(rendered).to have_link('Contributors', href: project_graph_path(project, current_ref, ref_type: 'heads')) + expect(rendered).to have_link('Contributor statistics', href: project_graph_path(project, current_ref, ref_type: 'heads')) end end @@ -122,11 +122,11 @@ RSpec.describe 'layouts/nav/sidebar/_project', feature_category: :navigation do end end - describe 'Compare' do + describe 'Compare revisions' do it 'has a link to the project compare path' do render - expect(rendered).to have_link('Compare', href: project_compare_index_path(project, from: project.repository.root_ref, to: current_ref)) + expect(rendered).to have_link('Compare revisions', href: project_compare_index_path(project, from: project.repository.root_ref, to: current_ref)) end end end |