diff --git a/.eslint_todo/vue-no-unused-properties.mjs b/.eslint_todo/vue-no-unused-properties.mjs index 8d3a91eb40385db160ab1a0a602c3adf3286cf4f..f93163ced0353eebacce9f2183ab5f5806b51657 100644 --- a/.eslint_todo/vue-no-unused-properties.mjs +++ b/.eslint_todo/vue-no-unused-properties.mjs @@ -393,7 +393,6 @@ export default { 'app/assets/javascripts/work_items/components/work_item_detail.vue', 'app/assets/javascripts/work_items/components/work_item_detail_modal.vue', 'app/assets/javascripts/work_items/components/work_item_development/work_item_create_branch_merge_request_modal.vue', - 'app/assets/javascripts/work_items/components/work_item_development/work_item_development.vue', 'app/assets/javascripts/work_items/components/work_item_development/work_item_development_mr_item.vue', 'app/assets/javascripts/work_items/components/work_item_due_date.vue', 'app/assets/javascripts/work_items/components/work_item_labels.vue', diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue index d77b71eaec49357fd89ba175674b8f5ef7bc14ef..4221033f145e032683fd8f0e5ea1040b3afb256c 100644 --- a/app/assets/javascripts/work_items/components/work_item_detail.vue +++ b/app/assets/javascripts/work_items/components/work_item_detail.vue @@ -1101,7 +1101,6 @@ export default { :work-item-id="workItem.id" :work-item-iid="iid" :work-item-full-path="workItemFullPath" - :work-item-type="workItem.workItemType.name" /> <work-item-notes v-if="workItemNotes" diff --git a/app/assets/javascripts/work_items/components/work_item_development/work_item_development.vue b/app/assets/javascripts/work_items/components/work_item_development/work_item_development.vue index 7791b0c3193eecb0f3ebaac34d637a961fe65845..d025a772ddc89cecb3feceb0f633c89899a6e059 100644 --- a/app/assets/javascripts/work_items/components/work_item_development/work_item_development.vue +++ b/app/assets/javascripts/work_items/components/work_item_development/work_item_development.vue @@ -1,5 +1,6 @@ <script> -import { GlIcon, GlAlert, GlTooltipDirective, GlModalDirective } from '@gitlab/ui'; +import { GlIcon, GlAlert, GlTooltipDirective } from '@gitlab/ui'; +import * as Sentry from '~/sentry/sentry_browser_wrapper'; import { s__, __ } from '~/locale'; import { findWidget } from '~/issues/list/utils'; @@ -20,24 +21,6 @@ import WorkItemDevelopmentRelationshipList from './work_item_development_relatio import WorkItemCreateBranchMergeRequestModal from './work_item_create_branch_merge_request_modal.vue'; export default { - i18n: { - development: s__('WorkItem|Development'), - fetchError: s__('WorkItem|Something went wrong when fetching items. Please refresh this page.'), - createMergeRequest: __('Create merge request'), - createBranch: __('Create branch'), - branchLabel: __('Branch'), - mergeRequestLabel: __('Merge request'), - addTooltipLabel: __('Add development item'), - openStateWithOneMergeRequestText: s__( - 'WorkItem|This %{workItemType} will be closed when the following is merged.', - ), - openStateText: s__( - 'WorkItem|This %{workItemType} will be closed when any of the following is merged.', - ), - closedStateText: s__( - 'WorkItem|The %{workItemType} was closed automatically when a branch was merged.', - ), - }, components: { GlIcon, GlAlert, @@ -48,17 +31,12 @@ export default { }, directives: { GlTooltip: GlTooltipDirective, - GlModalDirective, }, props: { workItemFullPath: { type: String, required: true, }, - workItemType: { - type: String, - required: true, - }, workItemId: { type: String, required: true, @@ -82,7 +60,6 @@ export default { showCreateBranchAndMrModal: false, showBranchFlow: true, showMergeRequestFlow: false, - isLoadingPermissionsQuery: false, showCreateOptions: true, }; }, @@ -117,11 +94,10 @@ export default { return this.workItemDevelopment?.relatedBranches?.nodes || []; }, shouldShowDevWidget() { - return this.workItemDevelopment && !this.isRelatedDevelopmentListEmpty; + return this.error || !this.isRelatedDevelopmentListEmpty; }, isRelatedDevelopmentListEmpty() { return ( - !this.error && this.relatedMergeRequests.length === 0 && this.closingMergeRequests.length === 0 && this.featureFlags.length === 0 && @@ -135,14 +111,22 @@ export default { }, openStateText() { return this.closingMergeRequests.length > 1 - ? sprintfWorkItem(this.$options.i18n.openStateText, this.workItemTypeName) + ? sprintfWorkItem( + s__( + 'WorkItem|This %{workItemType} will be closed when any of the following is merged.', + ), + this.workItemTypeName, + ) : sprintfWorkItem( - this.$options.i18n.openStateWithOneMergeRequestText, + s__('WorkItem|This %{workItemType} will be closed when the following is merged.'), this.workItemTypeName, ); }, closedStateText() { - return sprintfWorkItem(this.$options.i18n.closedStateText, this.workItemTypeName); + return sprintfWorkItem( + s__('WorkItem|The %{workItemType} was closed automatically when a branch was merged.'), + this.workItemTypeName, + ); }, tooltipText() { return this.workItemState === STATE_OPEN ? this.openStateText : this.closedStateText; @@ -159,10 +143,10 @@ export default { addItemsActions() { return [ { - name: this.$options.i18n.mergeRequestLabel, + name: __('Merge request'), items: [ { - text: this.$options.i18n.createMergeRequest, + text: __('Create merge request'), action: this.openModal.bind(this, false, true), extraAttrs: { 'data-testid': 'create-mr-dropdown-button', @@ -171,10 +155,10 @@ export default { ], }, { - name: this.$options.i18n.branchLabel, + name: __('Branch'), items: [ { - text: this.$options.i18n.createBranch, + text: __('Create branch'), action: this.openModal.bind(this, true, false), extraAttrs: { 'data-testid': 'create-branch-dropdown-button', @@ -200,9 +184,11 @@ export default { skip() { return !this.workItemIid; }, - error(e) { - this.$emit('error', this.$options.i18n.fetchError); - this.error = e.message || this.$options.i18n.fetchError; + error(error) { + this.error = s__( + 'WorkItem|Something went wrong when fetching items. Please refresh this page.', + ); + Sentry.captureException(error); }, }, workItemDevelopment: { @@ -218,9 +204,11 @@ export default { skip() { return !this.workItemIid; }, - error(e) { - this.$emit('error', this.$options.i18n.fetchError); - this.error = e.message || this.$options.i18n.fetchError; + error(error) { + this.error = s__( + "WorkItem|One or more items cannot be shown. If you're using SAML authentication, this could mean your session has expired.", + ); + Sentry.captureException(error); }, subscribeToMore: { document: workItemDevelopmentUpdatedSubscription, @@ -257,9 +245,9 @@ export default { <crud-component v-if="shouldShowDevWidget" ref="workItemDevelopment" - :title="$options.i18n.development" + :title="s__('WorkItem|Development')" :anchor-id="$options.DEVELOPMENT_ITEMS_ANCHOR" - :is-loading="isLoading || isLoadingPermissionsQuery" + :is-loading="isLoading" is-collapsible persist-collapsed-state data-testid="work-item-development" @@ -283,16 +271,16 @@ export default { v-if="showAddButton" data-testid="create-options-dropdown" :actions="addItemsActions" - :tooltip-text="$options.i18n.addTooltipLabel" + :tooltip-text="__('Add development item')" /> </template> - <template v-if="isRelatedDevelopmentListEmpty" #empty> + <template v-if="isRelatedDevelopmentListEmpty && !error" #empty> {{ __('None') }} </template> <template #default> - <gl-alert v-if="error" variant="danger" @dismiss="error = undefined"> + <gl-alert v-if="error" :dismissible="false" variant="danger"> {{ error }} </gl-alert> <work-item-development-relationship-list diff --git a/ee/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js b/ee/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js index 3277e206058a1d4b342633674a3add00b0b555db..f21603c51922876e33e119f7b548ea7ffbd6fa13 100644 --- a/ee/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js +++ b/ee/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js @@ -3,7 +3,6 @@ import VueApollo from 'vue-apollo'; import { map } from 'lodash'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; -import { createMockDirective } from 'helpers/vue_mock_directive'; import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql'; import workItemDevelopmentQuery from '~/work_items/graphql/work_item_development.query.graphql'; import workItemDevelopmentUpdatedSubscription from '~/work_items/graphql/work_item_development.subscription.graphql'; @@ -21,71 +20,68 @@ import { import WorkItemDevelopment from '~/work_items/components/work_item_development/work_item_development.vue'; import WorkItemDevelopmentRelationshipList from '~/work_items/components/work_item_development/work_item_development_relationship_list.vue'; -/* - MR list is available for CE and EE - Related feature flags is only available for EE -*/ +/** + * MR list is available for CE and EE + * Related feature flags is only available for EE + */ describe('WorkItemDevelopment EE', () => { Vue.use(VueApollo); let wrapper; - let mockApollo; - const workItemSuccessQueryHandler = jest - .fn() - .mockResolvedValue(workItemByIidResponseFactory({ canUpdate: true })); - - const devWidgetWithMRListOnly = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: workItemDevelopmentMRNodes, - willAutoCloseByMergeRequest: true, - featureFlagNodes: [], - branchNodes: [], - relatedMergeRequests: [], - }), + const workItemResponse = workItemByIidResponseFactory({ canUpdate: true }); + + const workItemSuccessQueryHandler = jest.fn().mockResolvedValue(workItemResponse); + + const createWorkItemDevelopmentResponse = (config) => + workItemDevelopmentResponse({ + widgets: [ + ...workItemResponse.data.workspace.workItem.widgets, + workItemDevelopmentFragmentResponse(config), + ], + }); + + const devWidgetWithMRListOnly = createWorkItemDevelopmentResponse({ + mrNodes: workItemDevelopmentMRNodes, + willAutoCloseByMergeRequest: true, + featureFlagNodes: [], + branchNodes: [], + relatedMergeRequests: [], }); - const devWidgetWithFlagListOnly = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: [], - willAutoCloseByMergeRequest: false, - featureFlagNodes: workItemDevelopmentFeatureFlagNodes, - branchNodes: [], - relatedMergeRequests: [], - }), + const devWidgetWithFlagListOnly = createWorkItemDevelopmentResponse({ + mrNodes: [], + willAutoCloseByMergeRequest: false, + featureFlagNodes: workItemDevelopmentFeatureFlagNodes, + branchNodes: [], + relatedMergeRequests: [], }); - const devWidgetWithBranchListOnly = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: [], - willAutoCloseByMergeRequest: false, - featureFlagNodes: [], - branchNodes: workItemRelatedBranchNodes, - relatedMergeRequests: [], - }), + const devWidgetWithBranchListOnly = createWorkItemDevelopmentResponse({ + mrNodes: [], + willAutoCloseByMergeRequest: false, + featureFlagNodes: [], + branchNodes: workItemRelatedBranchNodes, + relatedMergeRequests: [], }); - const devWidgetWithRelatedMRListOnly = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: [], - willAutoCloseByMergeRequest: false, - featureFlagNodes: [], - branchNodes: [], - relatedMergeRequests: map(workItemDevelopmentMRNodes, 'mergeRequest'), - }), + const devWidgetWithRelatedMRListOnly = createWorkItemDevelopmentResponse({ + mrNodes: [], + willAutoCloseByMergeRequest: false, + featureFlagNodes: [], + branchNodes: [], + relatedMergeRequests: map(workItemDevelopmentMRNodes, 'mergeRequest'), }); - const devWidgetWithNoDevItems = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: [], - willAutoCloseByMergeRequest: false, - featureFlagNodes: [], - branchNodes: [], - relatedMergeRequests: [], - }), + const devWidgetWithNoDevItems = createWorkItemDevelopmentResponse({ + mrNodes: [], + willAutoCloseByMergeRequest: false, + featureFlagNodes: [], + branchNodes: [], + relatedMergeRequests: [], }); - const devWidgetsuccessQueryHandler = jest.fn().mockResolvedValue(devWidgetWithMRListOnly); + const devWidgetSuccessQueryHandler = jest.fn().mockResolvedValue(devWidgetWithMRListOnly); const devWidgetSuccessQueryHandlerWithOnlyMRList = jest .fn() @@ -112,33 +108,19 @@ describe('WorkItemDevelopment EE', () => { .mockResolvedValue({ data: { workItemUpdated: null } }); const createComponent = ({ - workItemId = 'gid://gitlab/WorkItem/1', - workItemIid = '1', - workItemFullPath = 'full-path', - workItemType = 'Issue', workItemQueryHandler = workItemSuccessQueryHandler, - workItemDevelopmentQueryHandler = devWidgetsuccessQueryHandler, + workItemDevelopmentQueryHandler = devWidgetSuccessQueryHandler, } = {}) => { - mockApollo = createMockApollo([ - [workItemByIidQuery, workItemQueryHandler], - [workItemDevelopmentQuery, workItemDevelopmentQueryHandler], - [workItemDevelopmentUpdatedSubscription, workItemDevelopmentUpdatedSubscriptionHandler], - ]); - wrapper = shallowMountExtended(WorkItemDevelopment, { - apolloProvider: mockApollo, - directives: { - GlModal: createMockDirective('gl-modal'), - GlTooltip: createMockDirective('gl-tooltip'), - }, + apolloProvider: createMockApollo([ + [workItemByIidQuery, workItemQueryHandler], + [workItemDevelopmentQuery, workItemDevelopmentQueryHandler], + [workItemDevelopmentUpdatedSubscription, workItemDevelopmentUpdatedSubscriptionHandler], + ]), propsData: { - workItemId, - workItemIid, - workItemFullPath, - workItemType, - }, - stubs: { - WorkItemCreateBranchMergeRequestModal: true, + workItemId: 'gid://gitlab/WorkItem/1', + workItemIid: '1', + workItemFullPath: 'full-path', }, }); }; @@ -154,9 +136,7 @@ describe('WorkItemDevelopment EE', () => { `( 'should show the relationship list when there is only a list of $description', async ({ successQueryResolveHandler }) => { - createComponent({ - workItemDevelopmentQueryHandler: successQueryResolveHandler, - }); + createComponent({ workItemDevelopmentQueryHandler: successQueryResolveHandler }); await waitForPromises(); expect(findRelationshipList().exists()).toBe(true); @@ -164,9 +144,7 @@ describe('WorkItemDevelopment EE', () => { ); it('should not show the widget when any of the dev item is not available', async () => { - createComponent({ - workItemDevelopmentQueryHandler: devWidgetSuccessQueryHandlerWithNoDevItem, - }); + createComponent({ workItemDevelopmentQueryHandler: devWidgetSuccessQueryHandlerWithNoDevItem }); await waitForPromises(); expect(findRelationshipList().exists()).toBe(false); diff --git a/locale/gitlab.pot b/locale/gitlab.pot index fe24325e6d19be768555639df6086d6b1fbb3c59..03ab807bdf77bbc472518ae537f913a6a0194a90 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -66091,6 +66091,9 @@ msgstr "" msgid "WorkItem|Objective" msgstr "" +msgid "WorkItem|One or more items cannot be shown. If you're using SAML authentication, this could mean your session has expired." +msgstr "" + msgid "WorkItem|Only %{MAX_WORK_ITEMS} items can be added at a time." msgstr "" diff --git a/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js b/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js index 988b87239fe3e5e01950b249c19fa95b764f2110..7d14e836ad3b6cc142799b9a15bcd04b1e4e2761 100644 --- a/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js +++ b/spec/frontend/work_items/components/work_item_development/work_item_development_spec.js @@ -1,13 +1,9 @@ import Vue from 'vue'; -import { - GlDisclosureDropdownGroup, - GlDisclosureDropdownItem, - GlDisclosureDropdown, -} from '@gitlab/ui'; +import { GlAlert, GlDisclosureDropdownGroup } from '@gitlab/ui'; import VueApollo from 'vue-apollo'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; -import { createMockDirective } from 'helpers/vue_mock_directive'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql'; import workItemDevelopmentQuery from '~/work_items/graphql/work_item_development.query.graphql'; import workItemDevelopmentUpdatedSubscription from '~/work_items/graphql/work_item_development.subscription.graphql'; @@ -31,47 +27,48 @@ describe('WorkItemDevelopment CE', () => { Vue.use(VueApollo); let wrapper; - let mockApollo; - const workItemSucessQueryHandler = ({ state = STATE_OPEN } = {}) => { - return jest.fn().mockResolvedValue(workItemByIidResponseFactory({ canUpdate: true, state })); - }; + const workItemResponse = workItemByIidResponseFactory({ canUpdate: true }); - const devWidgetWithOneMR = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: [workItemDevelopmentMRNodes[0]], - willAutoCloseByMergeRequest: true, - featureFlagNodes: null, - branchNodes: [], - relatedMergeRequests: [], - }), + const workItemSuccessQueryHandler = jest.fn().mockResolvedValue(workItemResponse); + + const createWorkItemDevelopmentResponse = (config) => + workItemDevelopmentResponse({ + widgets: [ + ...workItemResponse.data.workspace.workItem.widgets, + workItemDevelopmentFragmentResponse(config), + ], + }); + + const devWidgetWithOneMR = createWorkItemDevelopmentResponse({ + mrNodes: [workItemDevelopmentMRNodes[0]], + willAutoCloseByMergeRequest: true, + featureFlagNodes: null, + branchNodes: [], + relatedMergeRequests: [], }); - const devWidgetWithMoreThanOneMR = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: workItemDevelopmentMRNodes, - willAutoCloseByMergeRequest: true, - featureFlagNodes: null, - branchNodes: [], - relatedMergeRequests: [], - }), + const devWidgetWithMoreThanOneMR = createWorkItemDevelopmentResponse({ + mrNodes: workItemDevelopmentMRNodes, + willAutoCloseByMergeRequest: true, + featureFlagNodes: null, + branchNodes: [], + relatedMergeRequests: [], }); - const devWidgetWithAutoCloseDisabled = workItemDevelopmentResponse({ - developmentItems: workItemDevelopmentFragmentResponse({ - mrNodes: workItemDevelopmentMRNodes, - willAutoCloseByMergeRequest: false, - featureFlagNodes: null, - branchNodes: [], - relatedMergeRequests: [], - }), + const devWidgetWithAutoCloseDisabled = createWorkItemDevelopmentResponse({ + mrNodes: workItemDevelopmentMRNodes, + willAutoCloseByMergeRequest: false, + featureFlagNodes: null, + branchNodes: [], + relatedMergeRequests: [], }); const devWidgetSuccessHandlerWithAutoCloseDisabled = jest .fn() .mockResolvedValue(devWidgetWithAutoCloseDisabled); const devWidgetSuccessQueryHandlerWithOneMR = jest.fn().mockResolvedValue(devWidgetWithOneMR); - const devWidgeSuccessQueryHandlerWithMRList = jest + const devWidgetSuccessQueryHandlerWithMRList = jest .fn() .mockResolvedValue(devWidgetWithMoreThanOneMR); const workItemDevelopmentUpdatedSubscriptionHandler = jest @@ -80,40 +77,30 @@ describe('WorkItemDevelopment CE', () => { const createComponent = ({ mountFn = shallowMountExtended, - workItemId = 'gid://gitlab/WorkItem/1', - workItemIid = '1', - workItemFullPath = 'full-path', - workItemType = 'Issue', - workItemQueryHandler = workItemSucessQueryHandler(), + workItemQueryHandler = workItemSuccessQueryHandler, workItemDevelopmentQueryHandler = devWidgetSuccessQueryHandlerWithOneMR, } = {}) => { - mockApollo = createMockApollo([ - [workItemByIidQuery, workItemQueryHandler], - [workItemDevelopmentQuery, workItemDevelopmentQueryHandler], - [workItemDevelopmentUpdatedSubscription, workItemDevelopmentUpdatedSubscriptionHandler], - ]); - wrapper = mountFn(WorkItemDevelopment, { - apolloProvider: mockApollo, + apolloProvider: createMockApollo([ + [workItemByIidQuery, workItemQueryHandler], + [workItemDevelopmentQuery, workItemDevelopmentQueryHandler], + [workItemDevelopmentUpdatedSubscription, workItemDevelopmentUpdatedSubscriptionHandler], + ]), directives: { - GlModal: createMockDirective('gl-modal'), GlTooltip: createMockDirective('gl-tooltip'), }, propsData: { - workItemId, - workItemIid, - workItemFullPath, - workItemType, + workItemId: 'gid://gitlab/WorkItem/1', + workItemIid: '1', + workItemFullPath: 'full-path', }, stubs: { WorkItemCreateBranchMergeRequestModal: true, - GlDisclosureDropdown, - GlDisclosureDropdownItem, - GlDisclosureDropdownGroup, }, }); }; + const findAlert = () => wrapper.findComponent(GlAlert); const findCrudComponent = () => wrapper.findComponent(CrudComponent); const findAddButton = () => wrapper.findComponent(WorkItemActionsSplitButton); const findMoreInformation = () => wrapper.findByTestId('more-information'); @@ -180,32 +167,47 @@ describe('WorkItemDevelopment CE', () => { createComponent({ workItemDevelopmentQueryHandler: devWidgetSuccessQueryHandlerWithOneMR, }); - await waitForPromises(); expect(findMoreInformation().exists()).toBe(true); }); it.each` - developmentWidgetQueryHandler | message | workItemState | linkedMRsNumber - ${devWidgetSuccessQueryHandlerWithOneMR} | ${'This task will be closed when the following is merged.'} | ${STATE_OPEN} | ${1} - ${devWidgeSuccessQueryHandlerWithMRList} | ${'This task will be closed when any of the following is merged.'} | ${STATE_OPEN} | ${workItemDevelopmentMRNodes.length} - ${devWidgeSuccessQueryHandlerWithMRList} | ${'The task was closed automatically when a branch was merged.'} | ${STATE_CLOSED} | ${workItemDevelopmentMRNodes.length} + developmentWidgetQueryHandler | message | workItemState | linkedMRsNumber + ${devWidgetSuccessQueryHandlerWithOneMR} | ${'This task will be closed when the following is merged.'} | ${STATE_OPEN} | ${1} + ${devWidgetSuccessQueryHandlerWithMRList} | ${'This task will be closed when any of the following is merged.'} | ${STATE_OPEN} | ${workItemDevelopmentMRNodes.length} + ${devWidgetSuccessQueryHandlerWithMRList} | ${'The task was closed automatically when a branch was merged.'} | ${STATE_CLOSED} | ${workItemDevelopmentMRNodes.length} `( 'when the workItemState is `$workItemState` and number of linked MRs is `$linkedMRsNumber` shows message `$message`', async ({ developmentWidgetQueryHandler, message, workItemState }) => { + const workItemQueryResponse = workItemByIidResponseFactory({ + canUpdate: true, + state: workItemState, + }); createComponent({ - workItemQueryHandler: workItemSucessQueryHandler({ state: workItemState }), + workItemQueryHandler: jest.fn().mockResolvedValue(workItemQueryResponse), workItemDevelopmentQueryHandler: developmentWidgetQueryHandler, }); - await waitForPromises(); + const tooltip = getBinding(findMoreInformation().element, 'gl-tooltip'); expect(findMoreInformation().attributes('aria-label')).toBe(message); + expect(tooltip).toBeDefined(); }, ); }); + describe('when the response is unsuccessful', () => { + it('shows an alert with an error message', async () => { + createComponent({ workItemDevelopmentQueryHandler: jest.fn().mockRejectedValue({}) }); + await waitForPromises(); + + expect(findAlert().text()).toBe( + "One or more items cannot be shown. If you're using SAML authentication, this could mean your session has expired.", + ); + }); + }); + describe('Create branch/merge request flow', () => { beforeEach(() => { createComponent({ mountFn: mountExtended }); diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js index 195118b7c90a8693a34ef4bba584e60a11e262a3..aed69a0252e6137fabb0c095fd8dbe65a667681b 100644 --- a/spec/frontend/work_items/mock_data.js +++ b/spec/frontend/work_items/mock_data.js @@ -1248,7 +1248,7 @@ export const workItemDevelopmentFragmentResponse = ({ export const workItemDevelopmentResponse = ({ iid = '1', id = 'gid://gitlab/WorkItem/1', - developmentItems, + widgets, } = {}) => ({ data: { workItem: { @@ -1259,35 +1259,7 @@ export const workItemDevelopmentResponse = ({ __typename: 'Project', id: '1', }, - widgets: [ - { - __typename: 'WorkItemWidgetIteration', - }, - { - __typename: 'WorkItemWidgetWeight', - }, - { - __typename: 'WorkItemWidgetAssignees', - }, - { - __typename: 'WorkItemWidgetLabels', - }, - { - __typename: 'WorkItemWidgetDescription', - }, - { - __typename: 'WorkItemWidgetHierarchy', - }, - { - __typename: 'WorkItemWidgetStartAndDueDate', - }, - { - __typename: 'WorkItemWidgetMilestone', - }, - { - ...developmentItems, - }, - ], + widgets, }, }, });