diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-15 18:11:29 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-15 18:11:29 +0000 |
commit | 27d1ed4ddff6c2649544a968c2842140272d9c9d (patch) | |
tree | 93a68b94ece233b47284a9c7ad8cabf31465212c /spec/frontend | |
parent | 6e2dde590e694c13efdd441e058a925dcff17258 (diff) | |
download | gitlab-ce-27d1ed4ddff6c2649544a968c2842140272d9c9d.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
14 files changed, 399 insertions, 14 deletions
diff --git a/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js b/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js index b77def195b6..2dcc537809f 100644 --- a/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js +++ b/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js @@ -78,7 +78,7 @@ describe('RecoveryCodes', () => { it('fires Snowplow event', () => { expect(findProceedButton().attributes()).toMatchObject({ - 'data-track-event': 'click_button', + 'data-track-action': 'click_button', 'data-track-label': '2fa_recovery_codes_proceed_button', }); }); diff --git a/spec/frontend/deprecated_jquery_dropdown_spec.js b/spec/frontend/deprecated_jquery_dropdown_spec.js index 7858f88f8c3..4a6dee31cd5 100644 --- a/spec/frontend/deprecated_jquery_dropdown_spec.js +++ b/spec/frontend/deprecated_jquery_dropdown_spec.js @@ -323,7 +323,7 @@ describe('deprecatedJQueryDropdown', () => { const li = dropdown.renderItem(item, null, 3); const link = li.querySelector('a'); - expect(link).toHaveAttr('data-track-event', 'click_text'); + expect(link).toHaveAttr('data-track-action', 'click_text'); expect(link).toHaveAttr('data-track-label', 'some_value_for_label'); expect(link).toHaveAttr('data-track-value', '3'); expect(link).toHaveAttr('data-track-property', 'suggestion-category'); diff --git a/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap b/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap index d9f5ba0bade..4dc8eaea174 100644 --- a/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap +++ b/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Design reply form component renders button text as "Comment" when creating a comment 1`] = ` -"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn gl-mr-3 gl-w-auto! btn-confirm btn-md disabled gl-button\\"> +"<button data-track-action=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn gl-mr-3 gl-w-auto! btn-confirm btn-md disabled gl-button\\"> <!----> <!----> <span class=\\"gl-button-text\\"> Comment @@ -9,7 +9,7 @@ exports[`Design reply form component renders button text as "Comment" when creat `; exports[`Design reply form component renders button text as "Save comment" when creating a comment 1`] = ` -"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn gl-mr-3 gl-w-auto! btn-confirm btn-md disabled gl-button\\"> +"<button data-track-action=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn gl-mr-3 gl-w-auto! btn-confirm btn-md disabled gl-button\\"> <!----> <!----> <span class=\\"gl-button-text\\"> Save comment diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js index 523d3bd7b23..2cbcb73ce5b 100644 --- a/spec/frontend/header_search/components/app_spec.js +++ b/spec/frontend/header_search/components/app_spec.js @@ -1,14 +1,41 @@ import { GlSearchBoxByType } from '@gitlab/ui'; +import Vue from 'vue'; +import Vuex from 'vuex'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import HeaderSearchApp from '~/header_search/components/app.vue'; -import { ESC_KEY } from '~/lib/utils/keys'; -import { MOCK_USERNAME } from '../mock_data'; +import HeaderSearchDefaultItems from '~/header_search/components/header_search_default_items.vue'; +import HeaderSearchScopedItems from '~/header_search/components/header_search_scoped_items.vue'; +import { ENTER_KEY, ESC_KEY } from '~/lib/utils/keys'; +import { visitUrl } from '~/lib/utils/url_utility'; +import { MOCK_SEARCH, MOCK_SEARCH_QUERY, MOCK_USERNAME } from '../mock_data'; + +Vue.use(Vuex); + +jest.mock('~/lib/utils/url_utility', () => ({ + visitUrl: jest.fn(), +})); describe('HeaderSearchApp', () => { let wrapper; - const createComponent = () => { - wrapper = shallowMountExtended(HeaderSearchApp); + const actionSpies = { + setSearch: jest.fn(), + }; + + const createComponent = (initialState) => { + const store = new Vuex.Store({ + state: { + ...initialState, + }, + actions: actionSpies, + getters: { + searchQuery: () => MOCK_SEARCH_QUERY, + }, + }); + + wrapper = shallowMountExtended(HeaderSearchApp, { + store, + }); }; afterEach(() => { @@ -17,6 +44,8 @@ describe('HeaderSearchApp', () => { const findHeaderSearchInput = () => wrapper.findComponent(GlSearchBoxByType); const findHeaderSearchDropdown = () => wrapper.findByTestId('header-search-dropdown-menu'); + const findHeaderSearchDefaultItems = () => wrapper.findComponent(HeaderSearchDefaultItems); + const findHeaderSearchScopedItems = () => wrapper.findComponent(HeaderSearchScopedItems); describe('template', () => { it('always renders Header Search Input', () => { @@ -43,6 +72,29 @@ describe('HeaderSearchApp', () => { }); }); }); + + describe.each` + search | showDefault | showScoped + ${null} | ${true} | ${false} + ${''} | ${true} | ${false} + ${MOCK_SEARCH} | ${false} | ${true} + `('Header Search Dropdown Items', ({ search, showDefault, showScoped }) => { + describe(`when search is ${search}`, () => { + beforeEach(() => { + createComponent({ search }); + window.gon.current_username = MOCK_USERNAME; + wrapper.setData({ showDropdown: true }); + }); + + it(`should${showDefault ? '' : ' not'} render the Default Dropdown Items`, () => { + expect(findHeaderSearchDefaultItems().exists()).toBe(showDefault); + }); + + it(`should${showScoped ? '' : ' not'} render the Scoped Dropdown Items`, () => { + expect(findHeaderSearchScopedItems().exists()).toBe(showScoped); + }); + }); + }); }); describe('events', () => { @@ -86,6 +138,22 @@ describe('HeaderSearchApp', () => { expect(findHeaderSearchDropdown().exists()).toBe(false); }); }); + + it('calls setSearch when search input event is fired', async () => { + findHeaderSearchInput().vm.$emit('input', MOCK_SEARCH); + + await wrapper.vm.$nextTick(); + + expect(actionSpies.setSearch).toHaveBeenCalledWith(expect.any(Object), MOCK_SEARCH); + }); + + it('submits a search onKey-Enter', async () => { + findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY })); + + await wrapper.vm.$nextTick(); + + expect(visitUrl).toHaveBeenCalledWith(MOCK_SEARCH_QUERY); + }); }); }); }); diff --git a/spec/frontend/header_search/components/header_search_scoped_items_spec.js b/spec/frontend/header_search/components/header_search_scoped_items_spec.js new file mode 100644 index 00000000000..f0e5e182ec4 --- /dev/null +++ b/spec/frontend/header_search/components/header_search_scoped_items_spec.js @@ -0,0 +1,61 @@ +import { GlDropdownItem } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +import Vuex from 'vuex'; +import { trimText } from 'helpers/text_helper'; +import HeaderSearchScopedItems from '~/header_search/components/header_search_scoped_items.vue'; +import { MOCK_SEARCH, MOCK_SCOPED_SEARCH_OPTIONS } from '../mock_data'; + +Vue.use(Vuex); + +describe('HeaderSearchScopedItems', () => { + let wrapper; + + const createComponent = (initialState) => { + const store = new Vuex.Store({ + state: { + search: MOCK_SEARCH, + ...initialState, + }, + getters: { + scopedSearchOptions: () => MOCK_SCOPED_SEARCH_OPTIONS, + }, + }); + + wrapper = shallowMount(HeaderSearchScopedItems, { + store, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); + const findDropdownItemTitles = () => findDropdownItems().wrappers.map((w) => trimText(w.text())); + const findDropdownItemLinks = () => findDropdownItems().wrappers.map((w) => w.attributes('href')); + + describe('template', () => { + describe('Dropdown items', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders item for each option in scopedSearchOptions', () => { + expect(findDropdownItems()).toHaveLength(MOCK_SCOPED_SEARCH_OPTIONS.length); + }); + + it('renders titles correctly', () => { + const expectedTitles = MOCK_SCOPED_SEARCH_OPTIONS.map((o) => + trimText(`"${MOCK_SEARCH}" ${o.description} ${o.scope || ''}`), + ); + expect(findDropdownItemTitles()).toStrictEqual(expectedTitles); + }); + + it('renders links correctly', () => { + const expectedLinks = MOCK_SCOPED_SEARCH_OPTIONS.map((o) => o.url); + expect(findDropdownItemLinks()).toStrictEqual(expectedLinks); + }); + }); + }); +}); diff --git a/spec/frontend/header_search/mock_data.js b/spec/frontend/header_search/mock_data.js index 680b6522d98..5963ad9c279 100644 --- a/spec/frontend/header_search/mock_data.js +++ b/spec/frontend/header_search/mock_data.js @@ -4,14 +4,37 @@ import { MSG_MR_ASSIGNED_TO_ME, MSG_MR_IM_REVIEWER, MSG_MR_IVE_CREATED, + MSG_IN_PROJECT, + MSG_IN_GROUP, + MSG_IN_ALL_GITLAB, } from '~/header_search/constants'; export const MOCK_USERNAME = 'anyone'; +export const MOCK_SEARCH_PATH = '/search'; + export const MOCK_ISSUE_PATH = '/dashboard/issues'; export const MOCK_MR_PATH = '/dashboard/merge_requests'; +export const MOCK_ALL_PATH = '/'; + +export const MOCK_PROJECT = { + id: 123, + name: 'MockProject', + path: '/mock-project', +}; + +export const MOCK_GROUP = { + id: 321, + name: 'MockGroup', + path: '/mock-group', +}; + +export const MOCK_SEARCH_QUERY = 'http://gitlab.com/search?search=test'; + +export const MOCK_SEARCH = 'test'; + export const MOCK_SEARCH_CONTEXT = { project: null, project_metadata: {}, @@ -41,3 +64,20 @@ export const MOCK_DEFAULT_SEARCH_OPTIONS = [ url: `${MOCK_MR_PATH}/?author_username=${MOCK_USERNAME}`, }, ]; + +export const MOCK_SCOPED_SEARCH_OPTIONS = [ + { + scope: MOCK_PROJECT.name, + description: MSG_IN_PROJECT, + url: MOCK_PROJECT.path, + }, + { + scope: MOCK_GROUP.name, + description: MSG_IN_GROUP, + url: MOCK_GROUP.path, + }, + { + description: MSG_IN_ALL_GITLAB, + url: MOCK_ALL_PATH, + }, +]; diff --git a/spec/frontend/header_search/store/actions_spec.js b/spec/frontend/header_search/store/actions_spec.js new file mode 100644 index 00000000000..4530df0d91c --- /dev/null +++ b/spec/frontend/header_search/store/actions_spec.js @@ -0,0 +1,28 @@ +import testAction from 'helpers/vuex_action_helper'; +import * as actions from '~/header_search/store/actions'; +import * as types from '~/header_search/store/mutation_types'; +import createState from '~/header_search/store/state'; +import { MOCK_SEARCH } from '../mock_data'; + +describe('Header Search Store Actions', () => { + let state; + + beforeEach(() => { + state = createState({}); + }); + + afterEach(() => { + state = null; + }); + + describe('setSearch', () => { + it('calls the SET_SEARCH mutation', () => { + return testAction({ + action: actions.setSearch, + payload: MOCK_SEARCH, + state, + expectedMutations: [{ type: types.SET_SEARCH, payload: MOCK_SEARCH }], + }); + }); + }); +}); diff --git a/spec/frontend/header_search/store/getters_spec.js b/spec/frontend/header_search/store/getters_spec.js index f87a58a0560..2ad0a082f6a 100644 --- a/spec/frontend/header_search/store/getters_spec.js +++ b/spec/frontend/header_search/store/getters_spec.js @@ -2,10 +2,16 @@ import * as getters from '~/header_search/store/getters'; import initState from '~/header_search/store/state'; import { MOCK_USERNAME, + MOCK_SEARCH_PATH, MOCK_ISSUE_PATH, MOCK_MR_PATH, MOCK_SEARCH_CONTEXT, MOCK_DEFAULT_SEARCH_OPTIONS, + MOCK_SCOPED_SEARCH_OPTIONS, + MOCK_PROJECT, + MOCK_GROUP, + MOCK_ALL_PATH, + MOCK_SEARCH, } from '../mock_data'; describe('Header Search Store Getters', () => { @@ -13,6 +19,7 @@ describe('Header Search Store Getters', () => { const createState = (initialState) => { state = initState({ + searchPath: MOCK_SEARCH_PATH, issuesPath: MOCK_ISSUE_PATH, mrPath: MOCK_MR_PATH, searchContext: MOCK_SEARCH_CONTEXT, @@ -25,6 +32,30 @@ describe('Header Search Store Getters', () => { }); describe.each` + group | project | expectedPath + ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=undefined&group_id=undefined&scope=issues`} + ${MOCK_GROUP} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=undefined&group_id=${MOCK_GROUP.id}&scope=issues`} + ${MOCK_GROUP} | ${MOCK_PROJECT} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}&scope=issues`} + `('searchQuery', ({ group, project, expectedPath }) => { + describe(`when group is ${group?.name} and project is ${project?.name}`, () => { + beforeEach(() => { + createState({ + searchContext: { + group, + project, + scope: 'issues', + }, + }); + state.search = MOCK_SEARCH; + }); + + it(`should return ${expectedPath}`, () => { + expect(getters.searchQuery(state)).toBe(expectedPath); + }); + }); + }); + + describe.each` group | group_metadata | project | project_metadata | expectedPath ${null} | ${null} | ${null} | ${null} | ${MOCK_ISSUE_PATH} ${{ name: 'Test Group' }} | ${{ issues_path: 'group/path' }} | ${null} | ${null} | ${'group/path'} @@ -72,6 +103,71 @@ describe('Header Search Store Getters', () => { }); }); + describe.each` + group | project | expectedPath + ${null} | ${null} | ${null} + ${MOCK_GROUP} | ${null} | ${null} + ${MOCK_GROUP} | ${MOCK_PROJECT} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}&scope=issues`} + `('projectUrl', ({ group, project, expectedPath }) => { + describe(`when group is ${group?.name} and project is ${project?.name}`, () => { + beforeEach(() => { + createState({ + searchContext: { + group, + project, + scope: 'issues', + }, + }); + state.search = MOCK_SEARCH; + }); + + it(`should return ${expectedPath}`, () => { + expect(getters.projectUrl(state)).toBe(expectedPath); + }); + }); + }); + + describe.each` + group | project | expectedPath + ${null} | ${null} | ${null} + ${MOCK_GROUP} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}&scope=issues`} + ${MOCK_GROUP} | ${MOCK_PROJECT} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}&scope=issues`} + `('groupUrl', ({ group, project, expectedPath }) => { + describe(`when group is ${group?.name} and project is ${project?.name}`, () => { + beforeEach(() => { + createState({ + searchContext: { + group, + project, + scope: 'issues', + }, + }); + state.search = MOCK_SEARCH; + }); + + it(`should return ${expectedPath}`, () => { + expect(getters.groupUrl(state)).toBe(expectedPath); + }); + }); + }); + + describe('allUrl', () => { + const expectedPath = `${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&scope=issues`; + + beforeEach(() => { + createState({ + searchContext: { + scope: 'issues', + }, + }); + state.search = MOCK_SEARCH; + }); + + it(`should return ${expectedPath}`, () => { + expect(getters.allUrl(state)).toBe(expectedPath); + }); + }); + describe('defaultSearchOptions', () => { const mockGetters = { scopedIssuesPath: MOCK_ISSUE_PATH, @@ -89,4 +185,27 @@ describe('Header Search Store Getters', () => { ); }); }); + + describe('scopedSearchOptions', () => { + const mockGetters = { + projectUrl: MOCK_PROJECT.path, + groupUrl: MOCK_GROUP.path, + allUrl: MOCK_ALL_PATH, + }; + + beforeEach(() => { + createState({ + searchContext: { + project: MOCK_PROJECT, + group: MOCK_GROUP, + }, + }); + }); + + it('returns the correct array', () => { + expect(getters.scopedSearchOptions(state, mockGetters)).toStrictEqual( + MOCK_SCOPED_SEARCH_OPTIONS, + ); + }); + }); }); diff --git a/spec/frontend/header_search/store/mutations_spec.js b/spec/frontend/header_search/store/mutations_spec.js new file mode 100644 index 00000000000..8196c06099d --- /dev/null +++ b/spec/frontend/header_search/store/mutations_spec.js @@ -0,0 +1,20 @@ +import * as types from '~/header_search/store/mutation_types'; +import mutations from '~/header_search/store/mutations'; +import createState from '~/header_search/store/state'; +import { MOCK_SEARCH } from '../mock_data'; + +describe('Header Search Store Mutations', () => { + let state; + + beforeEach(() => { + state = createState({}); + }); + + describe('SET_SEARCH', () => { + it('sets search to value', () => { + mutations[types.SET_SEARCH](state, MOCK_SEARCH); + + expect(state.search).toBe(MOCK_SEARCH); + }); + }); +}); diff --git a/spec/frontend/header_spec.js b/spec/frontend/header_spec.js index 4ca6d7259bd..0d43accb7e5 100644 --- a/spec/frontend/header_spec.js +++ b/spec/frontend/header_spec.js @@ -59,8 +59,8 @@ describe('Header', () => { beforeEach(() => { setFixtures(` <li class="js-nav-user-dropdown"> - <a class="js-buy-pipeline-minutes-link" data-track-event="click_buy_ci_minutes" data-track-label="free" data-track-property="user_dropdown">Buy Pipeline minutes</a> - <a class="js-upgrade-plan-link" data-track-event="click_upgrade_link" data-track-label="free" data-track-property="user_dropdown">Upgrade</a> + <a class="js-buy-pipeline-minutes-link" data-track-action="click_buy_ci_minutes" data-track-label="free" data-track-property="user_dropdown">Buy Pipeline minutes</a> + <a class="js-upgrade-plan-link" data-track-action="click_upgrade_link" data-track-label="free" data-track-property="user_dropdown">Upgrade</a> </li>`); trackingSpy = mockTracking('_category_', $('.js-nav-user-dropdown').element, jest.spyOn); diff --git a/spec/frontend/invite_members/components/invite_members_trigger_spec.js b/spec/frontend/invite_members/components/invite_members_trigger_spec.js index f57af61ad5b..b2ebb9e4a47 100644 --- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js +++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js @@ -79,14 +79,14 @@ describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement it('does not add tracking attributes', () => { createComponent(); - expect(findButton().attributes('data-track-event')).toBeUndefined(); + expect(findButton().attributes('data-track-action')).toBeUndefined(); expect(findButton().attributes('data-track-label')).toBeUndefined(); }); it('adds tracking attributes', () => { createComponent({ label: '_label_', event: '_event_' }); - expect(findButton().attributes('data-track-event')).toBe('_event_'); + expect(findButton().attributes('data-track-action')).toBe('_event_'); expect(findButton().attributes('data-track-label')).toBe('_label_'); }); }); diff --git a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js index 63c1260560b..f84800d8266 100644 --- a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js +++ b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js @@ -65,7 +65,7 @@ describe('CustomizeHomepageBanner', () => { await wrapper.vm.$nextTick(); const button = wrapper.find(`[href='${wrapper.vm.preferencesBehaviorPath}']`); - expect(button.attributes('data-track-event')).toEqual(preferencesTrackingEvent); + expect(button.attributes('data-track-action')).toEqual(preferencesTrackingEvent); expect(button.attributes('data-track-label')).toEqual(provide.trackLabel); }); diff --git a/spec/frontend/sidebar/track_invite_members_spec.js b/spec/frontend/sidebar/track_invite_members_spec.js index 6c96e4cfc76..5946e3320c4 100644 --- a/spec/frontend/sidebar/track_invite_members_spec.js +++ b/spec/frontend/sidebar/track_invite_members_spec.js @@ -10,7 +10,7 @@ describe('Track user dropdown open', () => { document.body.innerHTML = ` <div id="dummy-wrapper-element"> <div class="js-sidebar-assignee-dropdown"> - <div class="js-invite-members-track" data-track-event="_track_event_" data-track-label="_track_label_"> + <div class="js-invite-members-track" data-track-action="_track_event_" data-track-label="_track_label_"> </div> </div> </div> diff --git a/spec/frontend/vue_mr_widget/components/states/merge_checks_failed_spec.js b/spec/frontend/vue_mr_widget/components/states/merge_checks_failed_spec.js new file mode 100644 index 00000000000..bdad0bada5f --- /dev/null +++ b/spec/frontend/vue_mr_widget/components/states/merge_checks_failed_spec.js @@ -0,0 +1,49 @@ +import { shallowMount } from '@vue/test-utils'; +import MergeChecksFailed from '~/vue_merge_request_widget/components/states/merge_checks_failed.vue'; + +let wrapper; + +function factory(propsData = {}) { + wrapper = shallowMount(MergeChecksFailed, { + propsData, + }); +} + +describe('Merge request widget merge checks failed state component', () => { + afterEach(() => { + wrapper.destroy(); + }); + + it.each` + mrState | displayText + ${{ isPipelineFailed: true }} | ${'pipelineFailed'} + ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'} + ${{ hasMergeableDiscussionsState: true }} | ${'unresolvedDiscussions'} + `('display $displayText text for $mrState', ({ mrState, displayText }) => { + factory({ mr: mrState }); + + expect(wrapper.text()).toContain(MergeChecksFailed.i18n[displayText]); + }); + + describe('unresolved discussions', () => { + it('renders jump to button', () => { + factory({ mr: { hasMergeableDiscussionsState: true } }); + + expect(wrapper.find('[data-testid="jumpToUnresolved"]').exists()).toBe(true); + }); + + it('renders resolve thread button', () => { + factory({ + mr: { + hasMergeableDiscussionsState: true, + createIssueToResolveDiscussionsPath: 'https://gitlab.com', + }, + }); + + expect(wrapper.find('[data-testid="resolveIssue"]').exists()).toBe(true); + expect(wrapper.find('[data-testid="resolveIssue"]').attributes('href')).toBe( + 'https://gitlab.com', + ); + }); + }); +}); |