summaryrefslogtreecommitdiff
path: root/spec/frontend/pages
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/pages')
-rw-r--r--spec/frontend/pages/admin/projects/components/namespace_select_spec.js93
-rw-r--r--spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js175
-rw-r--r--spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js92
-rw-r--r--spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap2
-rw-r--r--spec/frontend/pages/projects/new/components/app_spec.js44
-rw-r--r--spec/frontend/pages/projects/new/components/new_project_push_tip_popover_spec.js75
-rw-r--r--spec/frontend/pages/projects/new/components/new_project_url_select_spec.js122
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js78
-rw-r--r--spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js2
9 files changed, 406 insertions, 277 deletions
diff --git a/spec/frontend/pages/admin/projects/components/namespace_select_spec.js b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
new file mode 100644
index 00000000000..c579aa2f2da
--- /dev/null
+++ b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js
@@ -0,0 +1,93 @@
+import { mount } from '@vue/test-utils';
+import Api from '~/api';
+import NamespaceSelect from '~/pages/admin/projects/components/namespace_select.vue';
+
+describe('Dropdown select component', () => {
+ let wrapper;
+
+ const mountDropdown = (propsData) => {
+ wrapper = mount(NamespaceSelect, { propsData });
+ };
+
+ const findDropdownToggle = () => wrapper.find('button.dropdown-toggle');
+ const findNamespaceInput = () => wrapper.find('[data-testid="hidden-input"]');
+ const findFilterInput = () => wrapper.find('.namespace-search-box input');
+ const findDropdownOption = (match) => {
+ const buttons = wrapper
+ .findAll('button.dropdown-item')
+ .filter((node) => node.text().match(match));
+ return buttons.length ? buttons.at(0) : buttons;
+ };
+
+ const setFieldValue = async (field, value) => {
+ await field.setValue(value);
+ field.trigger('blur');
+ };
+
+ beforeEach(() => {
+ setFixtures('<div class="test-container"></div>');
+
+ jest.spyOn(Api, 'namespaces').mockImplementation((_, callback) =>
+ callback([
+ { id: 10, kind: 'user', full_path: 'Administrator' },
+ { id: 20, kind: 'group', full_path: 'GitLab Org' },
+ ]),
+ );
+ });
+
+ it('creates a hidden input if fieldName is provided', () => {
+ mountDropdown({ fieldName: 'namespace-input' });
+
+ expect(findNamespaceInput()).toExist();
+ expect(findNamespaceInput().attributes('name')).toBe('namespace-input');
+ });
+
+ describe('clicking dropdown options', () => {
+ it('retrieves namespaces based on filter query', async () => {
+ mountDropdown();
+
+ await setFieldValue(findFilterInput(), 'test');
+
+ expect(Api.namespaces).toHaveBeenCalledWith('test', expect.anything());
+ });
+
+ it('updates the dropdown value based upon selection', async () => {
+ mountDropdown({ fieldName: 'namespace-input' });
+
+ // wait for dropdown options to populate
+ await wrapper.vm.$nextTick();
+
+ expect(findDropdownOption('user: Administrator')).toExist();
+ expect(findDropdownOption('group: GitLab Org')).toExist();
+ expect(findDropdownOption('group: Foobar')).not.toExist();
+
+ findDropdownOption('user: Administrator').trigger('click');
+ await wrapper.vm.$nextTick();
+
+ expect(findNamespaceInput().attributes('value')).toBe('10');
+ expect(findDropdownToggle().text()).toBe('user: Administrator');
+ });
+
+ it('triggers a setNamespace event upon selection', async () => {
+ mountDropdown();
+
+ // wait for dropdown options to populate
+ await wrapper.vm.$nextTick();
+
+ findDropdownOption('group: GitLab Org').trigger('click');
+
+ expect(wrapper.emitted('setNamespace')).toHaveLength(1);
+ expect(wrapper.emitted('setNamespace')[0][0]).toBe(20);
+ });
+
+ it('displays "Any Namespace" option when showAny prop provided', () => {
+ mountDropdown({ showAny: true });
+ expect(wrapper.text()).toContain('Any namespace');
+ });
+
+ it('does not display "Any Namespace" option when showAny prop not provided', () => {
+ mountDropdown();
+ expect(wrapper.text()).not.toContain('Any namespace');
+ });
+ });
+});
diff --git a/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js b/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js
new file mode 100644
index 00000000000..d6b394a42c6
--- /dev/null
+++ b/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js
@@ -0,0 +1,175 @@
+import { GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import PaginationBar from '~/import_entities/components/pagination_bar.vue';
+import BulkImportsHistoryApp from '~/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+
+describe('BulkImportsHistoryApp', () => {
+ const API_URL = '/api/v4/bulk_imports/entities';
+
+ const DEFAULT_HEADERS = {
+ 'x-page': 1,
+ 'x-per-page': 20,
+ 'x-next-page': 2,
+ 'x-total': 22,
+ 'x-total-pages': 2,
+ 'x-prev-page': null,
+ };
+ const DUMMY_RESPONSE = [
+ {
+ id: 1,
+ bulk_import_id: 1,
+ status: 'finished',
+ source_full_path: 'top-level-group-12',
+ destination_name: 'top-level-group-12',
+ destination_namespace: 'h5bp',
+ created_at: '2021-07-08T10:03:44.743Z',
+ failures: [],
+ },
+ {
+ id: 2,
+ bulk_import_id: 2,
+ status: 'failed',
+ source_full_path: 'autodevops-demo',
+ destination_name: 'autodevops-demo',
+ destination_namespace: 'flightjs',
+ parent_id: null,
+ namespace_id: null,
+ project_id: null,
+ created_at: '2021-07-13T12:52:26.664Z',
+ updated_at: '2021-07-13T13:34:49.403Z',
+ failures: [
+ {
+ pipeline_class: 'BulkImports::Groups::Pipelines::GroupPipeline',
+ pipeline_step: 'loader',
+ exception_class: 'ActiveRecord::RecordNotUnique',
+ correlation_id_value: '01FAFYSYZ7XPF3P9NSMTS693SZ',
+ created_at: '2021-07-13T13:34:49.344Z',
+ },
+ ],
+ },
+ ];
+
+ let wrapper;
+ let mock;
+
+ function createComponent({ shallow = true } = {}) {
+ const mountFn = shallow ? shallowMount : mount;
+ wrapper = mountFn(BulkImportsHistoryApp);
+ }
+
+ const originalApiVersion = gon.api_version;
+ beforeAll(() => {
+ gon.api_version = 'v4';
+ });
+
+ afterAll(() => {
+ gon.api_version = originalApiVersion;
+ });
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+ });
+
+ describe('general behavior', () => {
+ it('renders loading state when loading', () => {
+ createComponent();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('renders empty state when no data is available', async () => {
+ mock.onGet(API_URL).reply(200, [], DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(GlEmptyState).exists()).toBe(true);
+ });
+
+ it('renders table with data when history is available', async () => {
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+
+ const table = wrapper.find(GlTable);
+ expect(table.exists()).toBe(true);
+ // can't use .props() or .attributes() here
+ expect(table.vm.$attrs.items).toHaveLength(DUMMY_RESPONSE.length);
+ });
+
+ it('changes page when requested by pagination bar', async () => {
+ const NEW_PAGE = 4;
+
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+ mock.resetHistory();
+
+ wrapper.findComponent(PaginationBar).vm.$emit('set-page', NEW_PAGE);
+ await axios.waitForAll();
+
+ expect(mock.history.get.length).toBe(1);
+ expect(mock.history.get[0].params).toStrictEqual(expect.objectContaining({ page: NEW_PAGE }));
+ });
+ });
+
+ it('changes page size when requested by pagination bar', async () => {
+ const NEW_PAGE_SIZE = 4;
+
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+ mock.resetHistory();
+
+ wrapper.findComponent(PaginationBar).vm.$emit('set-page-size', NEW_PAGE_SIZE);
+ await axios.waitForAll();
+
+ expect(mock.history.get.length).toBe(1);
+ expect(mock.history.get[0].params).toStrictEqual(
+ expect.objectContaining({ per_page: NEW_PAGE_SIZE }),
+ );
+ });
+
+ describe('details button', () => {
+ beforeEach(() => {
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent({ shallow: false });
+ return axios.waitForAll();
+ });
+
+ it('renders details button if relevant item has failures', async () => {
+ expect(
+ extendedWrapper(wrapper.find('tbody').findAll('tr').at(1)).findByText('Details').exists(),
+ ).toBe(true);
+ });
+
+ it('does not render details button if relevant item has no failures', () => {
+ expect(
+ extendedWrapper(wrapper.find('tbody').findAll('tr').at(0)).findByText('Details').exists(),
+ ).toBe(false);
+ });
+
+ it('expands details when details button is clicked', async () => {
+ const ORIGINAL_ROW_INDEX = 1;
+ await extendedWrapper(wrapper.find('tbody').findAll('tr').at(ORIGINAL_ROW_INDEX))
+ .findByText('Details')
+ .trigger('click');
+
+ const detailsRowContent = wrapper
+ .find('tbody')
+ .findAll('tr')
+ .at(ORIGINAL_ROW_INDEX + 1)
+ .find('pre');
+
+ expect(detailsRowContent.exists()).toBe(true);
+ expect(JSON.parse(detailsRowContent.text())).toStrictEqual(DUMMY_RESPONSE[1].failures);
+ });
+ });
+});
diff --git a/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js b/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js
new file mode 100644
index 00000000000..b722ac1e97b
--- /dev/null
+++ b/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js
@@ -0,0 +1,92 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import {
+ I18N_PASSWORD_PROMPT_CANCEL_BUTTON,
+ I18N_PASSWORD_PROMPT_CONFIRM_BUTTON,
+} from '~/pages/profiles/password_prompt/constants';
+import PasswordPromptModal from '~/pages/profiles/password_prompt/password_prompt_modal.vue';
+
+const createComponent = ({ props }) => {
+ return shallowMountExtended(PasswordPromptModal, {
+ propsData: {
+ ...props,
+ },
+ });
+};
+
+describe('Password prompt modal', () => {
+ let wrapper;
+
+ const mockPassword = 'not+fake+shady+password';
+ const mockEvent = { preventDefault: jest.fn() };
+ const handleConfirmPasswordSpy = jest.fn();
+
+ const findField = () => wrapper.findByTestId('password-prompt-field');
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findConfirmBtn = () => findModal().props('actionPrimary');
+ const findConfirmBtnDisabledState = () =>
+ findModal().props('actionPrimary').attributes[2].disabled;
+
+ const findCancelBtn = () => findModal().props('actionCancel');
+
+ const submitModal = () => findModal().vm.$emit('primary', mockEvent);
+ const setPassword = (newPw) => findField().vm.$emit('input', newPw);
+
+ beforeEach(() => {
+ wrapper = createComponent({
+ props: {
+ handleConfirmPassword: handleConfirmPasswordSpy,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the password field', () => {
+ expect(findField().exists()).toBe(true);
+ });
+
+ it('renders the confirm button', () => {
+ expect(findConfirmBtn().text).toEqual(I18N_PASSWORD_PROMPT_CONFIRM_BUTTON);
+ });
+
+ it('renders the cancel button', () => {
+ expect(findCancelBtn().text).toEqual(I18N_PASSWORD_PROMPT_CANCEL_BUTTON);
+ });
+
+ describe('confirm button', () => {
+ describe('with a valid password', () => {
+ it('calls the `handleConfirmPassword` method when clicked', async () => {
+ setPassword(mockPassword);
+ submitModal();
+
+ await wrapper.vm.$nextTick();
+
+ expect(handleConfirmPasswordSpy).toHaveBeenCalledTimes(1);
+ expect(handleConfirmPasswordSpy).toHaveBeenCalledWith(mockPassword);
+ });
+
+ it('enables the confirm button', async () => {
+ setPassword(mockPassword);
+
+ expect(findConfirmBtnDisabledState()).toBe(true);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findConfirmBtnDisabledState()).toBe(false);
+ });
+ });
+
+ it('without a valid password is disabled', async () => {
+ setPassword('');
+
+ expect(findConfirmBtnDisabledState()).toBe(true);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findConfirmBtnDisabledState()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
index 417567c9f4c..43361bb6f24 100644
--- a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
+++ b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
@@ -12,11 +12,11 @@ exports[`Code Coverage when fetching data is successful matches the snapshot 1`]
<gl-dropdown-stub
category="primary"
clearalltext="Clear all"
+ clearalltextclass="gl-px-5"
headertext=""
hideheaderborder="true"
highlighteditemstitle="Selected"
highlighteditemstitleclass="gl-px-5"
- showhighlighteditemstitle="true"
size="medium"
text="rspec"
variant="default"
diff --git a/spec/frontend/pages/projects/new/components/app_spec.js b/spec/frontend/pages/projects/new/components/app_spec.js
deleted file mode 100644
index ab8c6d529a8..00000000000
--- a/spec/frontend/pages/projects/new/components/app_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import App from '~/pages/projects/new/components/app.vue';
-import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
-
-describe('Experimental new project creation app', () => {
- let wrapper;
-
- const createComponent = (propsData) => {
- wrapper = shallowMount(App, { propsData });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('passes custom new project guideline text to underlying component', () => {
- const DEMO_GUIDELINES = 'Demo guidelines';
- const guidelineSelector = '#new-project-guideline';
- createComponent({
- newProjectGuidelines: DEMO_GUIDELINES,
- });
-
- expect(wrapper.find(guidelineSelector).text()).toBe(DEMO_GUIDELINES);
- });
-
- it.each`
- isCiCdAvailable | outcome
- ${false} | ${'do not show CI/CD panel'}
- ${true} | ${'show CI/CD panel'}
- `('$outcome when isCiCdAvailable is $isCiCdAvailable', ({ isCiCdAvailable }) => {
- createComponent({
- isCiCdAvailable,
- });
-
- expect(
- Boolean(
- wrapper
- .findComponent(NewNamespacePage)
- .props()
- .panels.find((p) => p.name === 'cicd_for_external_repo'),
- ),
- ).toBe(isCiCdAvailable);
- });
-});
diff --git a/spec/frontend/pages/projects/new/components/new_project_push_tip_popover_spec.js b/spec/frontend/pages/projects/new/components/new_project_push_tip_popover_spec.js
deleted file mode 100644
index d4cf8c78600..00000000000
--- a/spec/frontend/pages/projects/new/components/new_project_push_tip_popover_spec.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import { GlPopover, GlFormInputGroup } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import NewProjectPushTipPopover from '~/pages/projects/new/components/new_project_push_tip_popover.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-
-describe('New project push tip popover', () => {
- let wrapper;
- const targetId = 'target';
- const pushToCreateProjectCommand = 'command';
- const workingWithProjectsHelpPath = 'path';
-
- const findPopover = () => wrapper.findComponent(GlPopover);
- const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
- const findFormInput = () => wrapper.findComponent(GlFormInputGroup);
- const findHelpLink = () => wrapper.find('a');
- const findTarget = () => document.getElementById(targetId);
-
- const buildWrapper = () => {
- wrapper = shallowMount(NewProjectPushTipPopover, {
- propsData: {
- target: findTarget(),
- },
- stubs: {
- GlFormInputGroup,
- },
- provide: {
- pushToCreateProjectCommand,
- workingWithProjectsHelpPath,
- },
- });
- };
-
- beforeEach(() => {
- setFixtures(`<a id="${targetId}"></a>`);
- buildWrapper();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders popover that targets the specified target', () => {
- expect(findPopover().props()).toMatchObject({
- target: findTarget(),
- triggers: 'click blur',
- placement: 'top',
- title: 'Push to create a project',
- });
- });
-
- it('renders a readonly form input with the push to create command', () => {
- expect(findFormInput().props()).toMatchObject({
- value: pushToCreateProjectCommand,
- selectOnClick: true,
- });
- expect(findFormInput().attributes()).toMatchObject({
- 'aria-label': 'Push project from command line',
- readonly: 'readonly',
- });
- });
-
- it('allows copying the push command using the clipboard button', () => {
- expect(findClipboardButton().props()).toMatchObject({
- text: pushToCreateProjectCommand,
- tooltipPlacement: 'right',
- title: 'Copy command',
- });
- });
-
- it('displays a link to open the push command help page reference', () => {
- expect(findHelpLink().attributes().href).toBe(
- `${workingWithProjectsHelpPath}#push-to-create-a-new-project`,
- );
- });
-});
diff --git a/spec/frontend/pages/projects/new/components/new_project_url_select_spec.js b/spec/frontend/pages/projects/new/components/new_project_url_select_spec.js
deleted file mode 100644
index 8a7f9229503..00000000000
--- a/spec/frontend/pages/projects/new/components/new_project_url_select_spec.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import { GlButton, GlDropdown, GlDropdownItem, GlDropdownSectionHeader } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import NewProjectUrlSelect from '~/pages/projects/new/components/new_project_url_select.vue';
-import searchQuery from '~/pages/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql';
-
-describe('NewProjectUrlSelect component', () => {
- let wrapper;
-
- const data = {
- currentUser: {
- groups: {
- nodes: [
- {
- id: 'gid://gitlab/Group/26',
- fullPath: 'flightjs',
- },
- {
- id: 'gid://gitlab/Group/28',
- fullPath: 'h5bp',
- },
- ],
- },
- namespace: {
- id: 'gid://gitlab/Namespace/1',
- fullPath: 'root',
- },
- },
- };
-
- const localVue = createLocalVue();
- localVue.use(VueApollo);
-
- const requestHandlers = [[searchQuery, jest.fn().mockResolvedValue({ data })]];
- const apolloProvider = createMockApollo(requestHandlers);
-
- const provide = {
- namespaceFullPath: 'h5bp',
- namespaceId: '28',
- rootUrl: 'https://gitlab.com/',
- trackLabel: 'blank_project',
- };
-
- const mountComponent = ({ mountFn = shallowMount } = {}) =>
- mountFn(NewProjectUrlSelect, { localVue, apolloProvider, provide });
-
- const findButtonLabel = () => wrapper.findComponent(GlButton);
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findHiddenInput = () => wrapper.find('input');
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders the root url as a label', () => {
- wrapper = mountComponent();
-
- expect(findButtonLabel().text()).toBe(provide.rootUrl);
- expect(findButtonLabel().props('label')).toBe(true);
- });
-
- it('renders a dropdown with the initial namespace full path as the text', () => {
- wrapper = mountComponent();
-
- expect(findDropdown().props('text')).toBe(provide.namespaceFullPath);
- });
-
- it('renders a dropdown with the initial namespace id in the hidden input', () => {
- wrapper = mountComponent();
-
- expect(findHiddenInput().attributes('value')).toBe(provide.namespaceId);
- });
-
- it('renders expected dropdown items', async () => {
- wrapper = mountComponent({ mountFn: mount });
-
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
-
- const listItems = wrapper.findAll('li');
-
- expect(listItems.at(0).findComponent(GlDropdownSectionHeader).text()).toBe('Groups');
- expect(listItems.at(1).text()).toBe(data.currentUser.groups.nodes[0].fullPath);
- expect(listItems.at(2).text()).toBe(data.currentUser.groups.nodes[1].fullPath);
- expect(listItems.at(3).findComponent(GlDropdownSectionHeader).text()).toBe('Users');
- expect(listItems.at(4).text()).toBe(data.currentUser.namespace.fullPath);
- });
-
- it('updates hidden input with selected namespace', async () => {
- wrapper = mountComponent();
-
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
-
- wrapper.findComponent(GlDropdownItem).vm.$emit('click');
-
- await wrapper.vm.$nextTick();
-
- expect(findHiddenInput().attributes()).toMatchObject({
- name: 'project[namespace_id]',
- value: getIdFromGraphQLId(data.currentUser.groups.nodes[0].id).toString(),
- });
- });
-
- it('tracks clicking on the dropdown', () => {
- wrapper = mountComponent();
-
- const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
-
- findDropdown().vm.$emit('show');
-
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'activate_form_input', {
- label: provide.trackLabel,
- property: 'project_path',
- });
-
- unmockTracking();
- });
-});
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
index 2a3b07f95f2..53c1733eab9 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
@@ -10,7 +10,17 @@ describe('Timezone Dropdown', () => {
let $dropdownEl = null;
let $wrapper = null;
const tzListSel = '.dropdown-content ul li a.is-active';
- const tzDropdownToggleText = '.dropdown-toggle-text';
+
+ const initTimezoneDropdown = (options = {}) => {
+ // eslint-disable-next-line no-new
+ new TimezoneDropdown({
+ $inputEl,
+ $dropdownEl,
+ ...options,
+ });
+ };
+
+ const findDropdownToggleText = () => $wrapper.find('.dropdown-toggle-text');
describe('Initialize', () => {
describe('with dropdown already loaded', () => {
@@ -18,16 +28,13 @@ describe('Timezone Dropdown', () => {
loadFixtures('pipeline_schedules/edit.html');
$wrapper = $('.dropdown');
$inputEl = $('#schedule_cron_timezone');
+ $inputEl.val('');
$dropdownEl = $('.js-timezone-dropdown');
-
- // eslint-disable-next-line no-new
- new TimezoneDropdown({
- $inputEl,
- $dropdownEl,
- });
});
it('can take an $inputEl in the constructor', () => {
+ initTimezoneDropdown();
+
const tzStr = '[UTC + 5.5] Sri Jayawardenepura';
const tzValue = 'Asia/Colombo';
@@ -42,6 +49,8 @@ describe('Timezone Dropdown', () => {
});
it('will format data array of timezones into a list of offsets', () => {
+ initTimezoneDropdown();
+
const data = $dropdownEl.data('data');
const formatted = $wrapper.find(tzListSel).text();
@@ -50,10 +59,28 @@ describe('Timezone Dropdown', () => {
});
});
- it('will default the timezone to UTC', () => {
- const tz = $inputEl.val();
+ describe('when `allowEmpty` property is `false`', () => {
+ beforeEach(() => {
+ initTimezoneDropdown();
+ });
+
+ it('will default the timezone to UTC', () => {
+ const tz = $inputEl.val();
- expect(tz).toBe('UTC');
+ expect(tz).toBe('UTC');
+ });
+ });
+
+ describe('when `allowEmpty` property is `true`', () => {
+ beforeEach(() => {
+ initTimezoneDropdown({
+ allowEmpty: true,
+ });
+ });
+
+ it('will default the value of the input to an empty string', () => {
+ expect($inputEl.val()).toBe('');
+ });
});
});
@@ -68,23 +95,15 @@ describe('Timezone Dropdown', () => {
it('will populate the list of UTC offsets after the dropdown is loaded', () => {
expect($wrapper.find(tzListSel).length).toEqual(0);
- // eslint-disable-next-line no-new
- new TimezoneDropdown({
- $inputEl,
- $dropdownEl,
- });
+ initTimezoneDropdown();
expect($wrapper.find(tzListSel).length).toEqual($($dropdownEl).data('data').length);
});
it('will call a provided handler when a new timezone is selected', () => {
const onSelectTimezone = jest.fn();
- // eslint-disable-next-line no-new
- new TimezoneDropdown({
- $inputEl,
- $dropdownEl,
- onSelectTimezone,
- });
+
+ initTimezoneDropdown({ onSelectTimezone });
$wrapper.find(tzListSel).first().trigger('click');
@@ -94,24 +113,15 @@ describe('Timezone Dropdown', () => {
it('will correctly set the dropdown label if a timezone identifier is set on the inputEl', () => {
$inputEl.val('America/St_Johns');
- // eslint-disable-next-line no-new
- new TimezoneDropdown({
- $inputEl,
- $dropdownEl,
- displayFormat: (selectedItem) => formatTimezone(selectedItem),
- });
+ initTimezoneDropdown({ displayFormat: (selectedItem) => formatTimezone(selectedItem) });
- expect($wrapper.find(tzDropdownToggleText).html()).toEqual('[UTC - 2.5] Newfoundland');
+ expect(findDropdownToggleText().html()).toEqual('[UTC - 2.5] Newfoundland');
});
it('will call a provided `displayFormat` handler to format the dropdown value', () => {
const displayFormat = jest.fn();
- // eslint-disable-next-line no-new
- new TimezoneDropdown({
- $inputEl,
- $dropdownEl,
- displayFormat,
- });
+
+ initTimezoneDropdown({ displayFormat });
$wrapper.find(tzListSel).first().trigger('click');
diff --git a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
index e39a3904613..a29db961452 100644
--- a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
+++ b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
@@ -44,7 +44,7 @@ describe('preserve_url_fragment', () => {
});
it('when "remember-me" is present', () => {
- $('.omniauth-btn')
+ $('.js-oauth-login')
.parent('form')
.attr('action', (i, href) => `${href}?remember_me=1`);