summaryrefslogtreecommitdiff
path: root/spec/frontend
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-09-15 18:11:29 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-09-15 18:11:29 +0000
commit27d1ed4ddff6c2649544a968c2842140272d9c9d (patch)
tree93a68b94ece233b47284a9c7ad8cabf31465212c /spec/frontend
parent6e2dde590e694c13efdd441e058a925dcff17258 (diff)
downloadgitlab-ce-27d1ed4ddff6c2649544a968c2842140272d9c9d.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js2
-rw-r--r--spec/frontend/deprecated_jquery_dropdown_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap4
-rw-r--r--spec/frontend/header_search/components/app_spec.js76
-rw-r--r--spec/frontend/header_search/components/header_search_scoped_items_spec.js61
-rw-r--r--spec/frontend/header_search/mock_data.js40
-rw-r--r--spec/frontend/header_search/store/actions_spec.js28
-rw-r--r--spec/frontend/header_search/store/getters_spec.js119
-rw-r--r--spec/frontend/header_search/store/mutations_spec.js20
-rw-r--r--spec/frontend/header_spec.js4
-rw-r--r--spec/frontend/invite_members/components/invite_members_trigger_spec.js4
-rw-r--r--spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js2
-rw-r--r--spec/frontend/sidebar/track_invite_members_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/merge_checks_failed_spec.js49
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',
+ );
+ });
+ });
+});