diff options
Diffstat (limited to 'spec/frontend/service_desk/components')
4 files changed, 0 insertions, 617 deletions
diff --git a/spec/frontend/service_desk/components/empty_state_with_any_issues_spec.js b/spec/frontend/service_desk/components/empty_state_with_any_issues_spec.js deleted file mode 100644 index ce8a78767d4..00000000000 --- a/spec/frontend/service_desk/components/empty_state_with_any_issues_spec.js +++ /dev/null @@ -1,74 +0,0 @@ -import { GlEmptyState } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import EmptyStateWithAnyIssues from '~/service_desk/components/empty_state_with_any_issues.vue'; -import { - noSearchResultsTitle, - noSearchResultsDescription, - infoBannerUserNote, - noOpenIssuesTitle, - noClosedIssuesTitle, -} from '~/service_desk/constants'; - -describe('EmptyStateWithAnyIssues component', () => { - let wrapper; - - const defaultProvide = { - emptyStateSvgPath: 'empty/state/svg/path', - newIssuePath: 'new/issue/path', - showNewIssueLink: false, - }; - - const findGlEmptyState = () => wrapper.findComponent(GlEmptyState); - - const mountComponent = (props = {}) => { - wrapper = shallowMount(EmptyStateWithAnyIssues, { - propsData: { - hasSearch: true, - isOpenTab: true, - ...props, - }, - provide: defaultProvide, - }); - }; - - describe('when there is a search (with no results)', () => { - beforeEach(() => { - mountComponent(); - }); - - it('shows empty state', () => { - expect(findGlEmptyState().props()).toMatchObject({ - description: noSearchResultsDescription, - title: noSearchResultsTitle, - svgPath: defaultProvide.emptyStateSvgPath, - }); - }); - }); - - describe('when "Open" tab is active', () => { - beforeEach(() => { - mountComponent({ hasSearch: false }); - }); - - it('shows empty state', () => { - expect(findGlEmptyState().props()).toMatchObject({ - description: infoBannerUserNote, - title: noOpenIssuesTitle, - svgPath: defaultProvide.emptyStateSvgPath, - }); - }); - }); - - describe('when "Closed" tab is active', () => { - beforeEach(() => { - mountComponent({ hasSearch: false, isClosedTab: true, isOpenTab: false }); - }); - - it('shows empty state', () => { - expect(findGlEmptyState().props()).toMatchObject({ - title: noClosedIssuesTitle, - svgPath: defaultProvide.emptyStateSvgPath, - }); - }); - }); -}); diff --git a/spec/frontend/service_desk/components/empty_state_without_any_issues_spec.js b/spec/frontend/service_desk/components/empty_state_without_any_issues_spec.js deleted file mode 100644 index c67f9588ed4..00000000000 --- a/spec/frontend/service_desk/components/empty_state_without_any_issues_spec.js +++ /dev/null @@ -1,86 +0,0 @@ -import { GlEmptyState, GlLink } from '@gitlab/ui'; -import { mountExtended } from 'helpers/vue_test_utils_helper'; -import EmptyStateWithoutAnyIssues from '~/service_desk/components/empty_state_without_any_issues.vue'; -import { infoBannerTitle, noIssuesSignedOutButtonText, learnMore } from '~/service_desk/constants'; - -describe('EmptyStateWithoutAnyIssues component', () => { - let wrapper; - - const defaultProvide = { - emptyStateSvgPath: 'empty/state/svg/path', - isSignedIn: true, - signInPath: 'sign/in/path', - canAdminIssues: true, - isServiceDeskEnabled: true, - serviceDeskEmailAddress: 'email@address.com', - serviceDeskHelpPath: 'service/desk/help/path', - }; - - const findGlEmptyState = () => wrapper.findComponent(GlEmptyState); - const findGlLink = () => wrapper.findComponent(GlLink); - const findIssuesHelpPageLink = () => wrapper.findByRole('link', { name: learnMore }); - - const mountComponent = ({ provide = {} } = {}) => { - wrapper = mountExtended(EmptyStateWithoutAnyIssues, { - provide: { - ...defaultProvide, - ...provide, - }, - }); - }; - - describe('when signed in', () => { - beforeEach(() => { - mountComponent(); - }); - - it('renders empty state', () => { - expect(findGlEmptyState().props()).toMatchObject({ - title: infoBannerTitle, - svgPath: defaultProvide.emptyStateSvgPath, - contentClass: 'gl-max-w-80!', - }); - }); - - it('renders description with service desk docs link', () => { - expect(findIssuesHelpPageLink().attributes('href')).toBe(defaultProvide.serviceDeskHelpPath); - }); - - it('renders email address, when user can admin issues and service desk is enabled', () => { - expect(wrapper.text()).toContain(wrapper.vm.serviceDeskEmailAddress); - }); - - it('does not render email address, when user can not admin issues', () => { - mountComponent({ provide: { canAdminIssues: false } }); - - expect(wrapper.text()).not.toContain(wrapper.vm.serviceDeskEmailAddress); - }); - - it('does not render email address, when service desk is not setup', () => { - mountComponent({ provide: { isServiceDeskEnabled: false } }); - - expect(wrapper.text()).not.toContain(wrapper.vm.serviceDeskEmailAddress); - }); - }); - - describe('when signed out', () => { - beforeEach(() => { - mountComponent({ provide: { isSignedIn: false } }); - }); - - it('renders empty state', () => { - expect(findGlEmptyState().props()).toMatchObject({ - title: infoBannerTitle, - svgPath: defaultProvide.emptyStateSvgPath, - primaryButtonText: noIssuesSignedOutButtonText, - primaryButtonLink: defaultProvide.signInPath, - contentClass: 'gl-max-w-80!', - }); - }); - - it('renders service desk docs link', () => { - expect(findGlLink().attributes('href')).toBe(defaultProvide.serviceDeskHelpPath); - expect(findGlLink().text()).toBe(learnMore); - }); - }); -}); diff --git a/spec/frontend/service_desk/components/info_banner_spec.js b/spec/frontend/service_desk/components/info_banner_spec.js deleted file mode 100644 index 7487d5d8b64..00000000000 --- a/spec/frontend/service_desk/components/info_banner_spec.js +++ /dev/null @@ -1,81 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import { GlLink, GlButton } from '@gitlab/ui'; -import InfoBanner from '~/service_desk/components/info_banner.vue'; -import { infoBannerAdminNote, enableServiceDesk } from '~/service_desk/constants'; - -describe('InfoBanner', () => { - let wrapper; - - const defaultProvide = { - serviceDeskCalloutSvgPath: 'callout.svg', - serviceDeskEmailAddress: 'sd@gmail.com', - canAdminIssues: true, - canEditProjectSettings: true, - serviceDeskSettingsPath: 'path/to/project/settings', - serviceDeskHelpPath: 'path/to/documentation', - isServiceDeskEnabled: true, - }; - - const findEnableSDButton = () => wrapper.findComponent(GlButton); - - const mountComponent = (provide) => { - return shallowMount(InfoBanner, { - provide: { - ...defaultProvide, - ...provide, - }, - stubs: { - GlLink, - GlButton, - }, - }); - }; - - beforeEach(() => { - wrapper = mountComponent(); - }); - - describe('Service Desk email address', () => { - it('renders when user can admin issues and service desk is enabled', () => { - expect(wrapper.text()).toContain(infoBannerAdminNote); - expect(wrapper.text()).toContain(wrapper.vm.serviceDeskEmailAddress); - }); - - it('does not render, when user can not admin issues', () => { - wrapper = mountComponent({ canAdminIssues: false }); - - expect(wrapper.text()).not.toContain(infoBannerAdminNote); - expect(wrapper.text()).not.toContain(wrapper.vm.serviceDeskEmailAddress); - }); - - it('does not render, when service desk is not setup', () => { - wrapper = mountComponent({ isServiceDeskEnabled: false }); - - expect(wrapper.text()).not.toContain(infoBannerAdminNote); - expect(wrapper.text()).not.toContain(wrapper.vm.serviceDeskEmailAddress); - }); - }); - - describe('Link to Service Desk settings', () => { - it('renders when user can edit settings and service desk is not enabled', () => { - wrapper = mountComponent({ isServiceDeskEnabled: false }); - - expect(wrapper.text()).toContain(enableServiceDesk); - expect(findEnableSDButton().exists()).toBe(true); - }); - - it('does not render when service desk is enabled', () => { - wrapper = mountComponent(); - - expect(wrapper.text()).not.toContain(enableServiceDesk); - expect(findEnableSDButton().exists()).toBe(false); - }); - - it('does not render when user cannot edit settings', () => { - wrapper = mountComponent({ canEditProjectSettings: false }); - - expect(wrapper.text()).not.toContain(enableServiceDesk); - expect(findEnableSDButton().exists()).toBe(false); - }); - }); -}); diff --git a/spec/frontend/service_desk/components/service_desk_list_app_spec.js b/spec/frontend/service_desk/components/service_desk_list_app_spec.js deleted file mode 100644 index bdb6a48895e..00000000000 --- a/spec/frontend/service_desk/components/service_desk_list_app_spec.js +++ /dev/null @@ -1,376 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import Vue, { nextTick } from 'vue'; -import VueApollo from 'vue-apollo'; -import { cloneDeep } from 'lodash'; -import VueRouter from 'vue-router'; -import * as Sentry from '@sentry/browser'; -import createMockApollo from 'helpers/mock_apollo_helper'; -import setWindowLocation from 'helpers/set_window_location_helper'; -import { TEST_HOST } from 'helpers/test_constants'; -import waitForPromises from 'helpers/wait_for_promises'; -import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue'; -import { issuableListTabs } from '~/vue_shared/issuable/list/constants'; -import { TYPENAME_USER } from '~/graphql_shared/constants'; -import { convertToGraphQLId } from '~/graphql_shared/utils'; -import { STATUS_CLOSED, STATUS_OPEN, STATUS_ALL } from '~/service_desk/constants'; -import getServiceDeskIssuesQuery from 'ee_else_ce/service_desk/queries/get_service_desk_issues.query.graphql'; -import getServiceDeskIssuesCountsQuery from 'ee_else_ce/service_desk/queries/get_service_desk_issues_counts.query.graphql'; -import ServiceDeskListApp from '~/service_desk/components/service_desk_list_app.vue'; -import InfoBanner from '~/service_desk/components/info_banner.vue'; -import EmptyStateWithAnyIssues from '~/service_desk/components/empty_state_with_any_issues.vue'; -import EmptyStateWithoutAnyIssues from '~/service_desk/components/empty_state_without_any_issues.vue'; - -import { - TOKEN_TYPE_ASSIGNEE, - TOKEN_TYPE_AUTHOR, - TOKEN_TYPE_CONFIDENTIAL, - TOKEN_TYPE_LABEL, - TOKEN_TYPE_MILESTONE, - TOKEN_TYPE_MY_REACTION, - TOKEN_TYPE_RELEASE, - TOKEN_TYPE_SEARCH_WITHIN, -} from '~/vue_shared/components/filtered_search_bar/constants'; -import { - getServiceDeskIssuesQueryResponse, - getServiceDeskIssuesQueryEmptyResponse, - getServiceDeskIssuesCountsQueryResponse, - filteredTokens, - urlParams, - locationSearch, -} from '../mock_data'; - -jest.mock('@sentry/browser'); - -describe('CE ServiceDeskListApp', () => { - let wrapper; - let router; - - Vue.use(VueApollo); - Vue.use(VueRouter); - - const defaultProvide = { - releasesPath: 'releases/path', - autocompleteAwardEmojisPath: 'autocomplete/award/emojis/path', - hasIterationsFeature: true, - hasIssueWeightsFeature: true, - hasIssuableHealthStatusFeature: true, - groupPath: 'group/path', - emptyStateSvgPath: 'empty-state.svg', - isProject: true, - isSignedIn: true, - fullPath: 'path/to/project', - isServiceDeskSupported: true, - hasAnyIssues: true, - initialSort: '', - issuablesLoading: false, - }; - - let defaultQueryResponse = getServiceDeskIssuesQueryResponse; - if (IS_EE) { - defaultQueryResponse = cloneDeep(getServiceDeskIssuesQueryResponse); - defaultQueryResponse.data.project.issues.nodes[0].healthStatus = null; - defaultQueryResponse.data.project.issues.nodes[0].weight = 5; - } - - const mockServiceDeskIssuesQueryResponseHandler = jest - .fn() - .mockResolvedValue(defaultQueryResponse); - const mockServiceDeskIssuesQueryEmptyResponseHandler = jest - .fn() - .mockResolvedValue(getServiceDeskIssuesQueryEmptyResponse); - const mockServiceDeskIssuesCountsQueryResponseHandler = jest - .fn() - .mockResolvedValue(getServiceDeskIssuesCountsQueryResponse); - - const findIssuableList = () => wrapper.findComponent(IssuableList); - const findInfoBanner = () => wrapper.findComponent(InfoBanner); - const findLabelsToken = () => - findIssuableList() - .props('searchTokens') - .find((token) => token.type === TOKEN_TYPE_LABEL); - - const createComponent = ({ - provide = {}, - serviceDeskIssuesQueryResponseHandler = mockServiceDeskIssuesQueryResponseHandler, - serviceDeskIssuesCountsQueryResponseHandler = mockServiceDeskIssuesCountsQueryResponseHandler, - } = {}) => { - const requestHandlers = [ - [getServiceDeskIssuesQuery, serviceDeskIssuesQueryResponseHandler], - [getServiceDeskIssuesCountsQuery, serviceDeskIssuesCountsQueryResponseHandler], - ]; - - router = new VueRouter({ mode: 'history' }); - - return shallowMount(ServiceDeskListApp, { - apolloProvider: createMockApollo( - requestHandlers, - {}, - { - typePolicies: { - Query: { - fields: { - project: { - merge: true, - }, - }, - }, - }, - }, - ), - router, - provide: { - ...defaultProvide, - ...provide, - }, - }); - }; - - beforeEach(() => { - setWindowLocation(TEST_HOST); - wrapper = createComponent(); - return waitForPromises(); - }); - - it('renders the issuable list with skeletons while fetching service desk issues', async () => { - wrapper = createComponent(); - await nextTick(); - - expect(findIssuableList().props('issuablesLoading')).toBe(true); - - await waitForPromises(); - - expect(findIssuableList().props('issuablesLoading')).toBe(false); - }); - - it('fetches service desk issues and renders them in the issuable list', () => { - expect(findIssuableList().props()).toMatchObject({ - namespace: 'service-desk', - recentSearchesStorageKey: 'service-desk-issues', - issuables: defaultQueryResponse.data.project.issues.nodes, - tabs: issuableListTabs, - currentTab: STATUS_OPEN, - tabCounts: { - opened: 1, - closed: 1, - all: 1, - }, - }); - }); - - describe('InfoBanner', () => { - it('renders when Service Desk is supported and has any number of issues', () => { - expect(findInfoBanner().exists()).toBe(true); - }); - - it('does not render when Service Desk is not supported and has any number of issues', () => { - wrapper = createComponent({ provide: { isServiceDeskSupported: false } }); - - expect(findInfoBanner().exists()).toBe(false); - }); - - it('does not render, when there are no issues', () => { - wrapper = createComponent({ - serviceDeskIssuesQueryResponseHandler: mockServiceDeskIssuesQueryEmptyResponseHandler, - }); - - expect(findInfoBanner().exists()).toBe(false); - }); - }); - - describe('Empty states', () => { - describe('when there are issues', () => { - it('shows EmptyStateWithAnyIssues component', () => { - setWindowLocation(locationSearch); - wrapper = createComponent({ - serviceDeskIssuesQueryResponseHandler: mockServiceDeskIssuesQueryEmptyResponseHandler, - }); - - expect(wrapper.findComponent(EmptyStateWithAnyIssues).props()).toEqual({ - hasSearch: true, - isOpenTab: true, - }); - }); - }); - - describe('when there are no issues', () => { - it('shows EmptyStateWithoutAnyIssues component', () => { - wrapper = createComponent({ - provide: { hasAnyIssues: false }, - serviceDeskIssuesQueryResponseHandler: mockServiceDeskIssuesQueryEmptyResponseHandler, - }); - - expect(wrapper.findComponent(EmptyStateWithoutAnyIssues).exists()).toBe(true); - }); - }); - }); - - describe('Initial url params', () => { - describe('search', () => { - it('is set from the url params', () => { - setWindowLocation(locationSearch); - wrapper = createComponent(); - - expect(router.history.current.query).toMatchObject({ search: 'find issues' }); - }); - }); - - describe('state', () => { - it('is set from the url params', async () => { - const initialState = STATUS_ALL; - setWindowLocation(`?state=${initialState}`); - wrapper = createComponent(); - await waitForPromises(); - - expect(findIssuableList().props('currentTab')).toBe(initialState); - }); - }); - - describe('filter tokens', () => { - it('are set from the url params', () => { - setWindowLocation(locationSearch); - wrapper = createComponent(); - - expect(findIssuableList().props('initialFilterValue')).toEqual(filteredTokens); - }); - }); - }); - - describe('Tokens', () => { - const mockCurrentUser = { - id: 1, - name: 'Administrator', - username: 'root', - avatar_url: 'avatar/url', - }; - - describe('when user is signed out', () => { - beforeEach(() => { - wrapper = createComponent({ provide: { isSignedIn: false } }); - return waitForPromises(); - }); - - it('does not render My-Reaction or Confidential tokens', () => { - expect(findIssuableList().props('searchTokens')).not.toMatchObject([ - { type: TOKEN_TYPE_AUTHOR, preloadedUsers: [mockCurrentUser] }, - { type: TOKEN_TYPE_ASSIGNEE, preloadedUsers: [mockCurrentUser] }, - { type: TOKEN_TYPE_MY_REACTION }, - { type: TOKEN_TYPE_CONFIDENTIAL }, - ]); - }); - }); - - describe('when all tokens are available', () => { - beforeEach(() => { - window.gon = { - current_user_id: mockCurrentUser.id, - current_user_fullname: mockCurrentUser.name, - current_username: mockCurrentUser.username, - current_user_avatar_url: mockCurrentUser.avatar_url, - }; - - wrapper = createComponent(); - return waitForPromises(); - }); - - it('renders all tokens alphabetically', () => { - const preloadedUsers = [ - { ...mockCurrentUser, id: convertToGraphQLId(TYPENAME_USER, mockCurrentUser.id) }, - ]; - - expect(findIssuableList().props('searchTokens')).toMatchObject([ - { type: TOKEN_TYPE_ASSIGNEE, preloadedUsers }, - { type: TOKEN_TYPE_CONFIDENTIAL }, - { type: TOKEN_TYPE_LABEL }, - { type: TOKEN_TYPE_MILESTONE }, - { type: TOKEN_TYPE_MY_REACTION }, - { type: TOKEN_TYPE_RELEASE }, - { type: TOKEN_TYPE_SEARCH_WITHIN }, - ]); - }); - }); - }); - - describe('Events', () => { - describe('when "click-tab" event is emitted by IssuableList', () => { - beforeEach(async () => { - wrapper = createComponent(); - router.push = jest.fn(); - await waitForPromises(); - - findIssuableList().vm.$emit('click-tab', STATUS_CLOSED); - }); - - it('updates ui to the new tab', () => { - expect(findIssuableList().props('currentTab')).toBe(STATUS_CLOSED); - }); - - it('updates url to the new tab', () => { - expect(router.push).toHaveBeenCalledWith({ - query: expect.objectContaining({ state: STATUS_CLOSED }), - }); - }); - }); - - describe('when "filter" event is emitted by IssuableList', () => { - it('updates IssuableList with url params', async () => { - wrapper = createComponent(); - router.push = jest.fn(); - await waitForPromises(); - - findIssuableList().vm.$emit('filter', filteredTokens); - await nextTick(); - - expect(router.push).toHaveBeenCalledWith({ - query: expect.objectContaining(urlParams), - }); - }); - }); - }); - - describe('Errors', () => { - describe.each` - error | responseHandler - ${'fetching issues'} | ${'serviceDeskIssuesQueryResponseHandler'} - ${'fetching issue counts'} | ${'serviceDeskIssuesCountsQueryResponseHandler'} - `('when there is an error $error', ({ responseHandler }) => { - beforeEach(() => { - wrapper = createComponent({ - [responseHandler]: jest.fn().mockRejectedValue(new Error('ERROR')), - }); - return waitForPromises(); - }); - - it('shows an error message', () => { - expect(Sentry.captureException).toHaveBeenCalledWith(new Error('ERROR')); - }); - }); - }); - - describe('When providing token for labels', () => { - it('passes function to fetchLatestLabels property if frontend caching is enabled', async () => { - wrapper = createComponent({ - provide: { - glFeatures: { - frontendCaching: true, - }, - }, - }); - await waitForPromises(); - - expect(typeof findLabelsToken().fetchLatestLabels).toBe('function'); - }); - - it('passes null to fetchLatestLabels property if frontend caching is disabled', async () => { - wrapper = createComponent({ - provide: { - glFeatures: { - frontendCaching: false, - }, - }, - }); - await waitForPromises(); - - expect(findLabelsToken().fetchLatestLabels).toBe(null); - }); - }); -}); |