diff options
Diffstat (limited to 'spec/frontend/pages')
8 files changed, 216 insertions, 22 deletions
diff --git a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js index 542eb2f3ab8..85ed94b748d 100644 --- a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js +++ b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js @@ -23,17 +23,17 @@ describe('AccountAndLimits', () => { describe('Changing of userInternalRegex when userDefaultExternal', () => { it('is unchecked', () => { - expect($userDefaultExternal.prop('checked')).toBeFalsy(); + expect($userDefaultExternal.prop('checked')).toBe(false); expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE); - expect($userInternalRegex.readOnly).toBeTruthy(); + expect($userInternalRegex.readOnly).toBe(true); }); it('is checked', () => { if (!$userDefaultExternal.prop('checked')) $userDefaultExternal.click(); - expect($userDefaultExternal.prop('checked')).toBeTruthy(); + expect($userDefaultExternal.prop('checked')).toBe(true); expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE); - expect($userInternalRegex.readOnly).toBeFalsy(); + expect($userInternalRegex.readOnly).toBe(false); }); }); }); diff --git a/spec/frontend/pages/groups/new/components/app_spec.js b/spec/frontend/pages/groups/new/components/app_spec.js new file mode 100644 index 00000000000..ab483316086 --- /dev/null +++ b/spec/frontend/pages/groups/new/components/app_spec.js @@ -0,0 +1,39 @@ +import { shallowMount } from '@vue/test-utils'; +import App from '~/pages/groups/new/components/app.vue'; +import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue'; + +describe('App component', () => { + let wrapper; + + const createComponent = (propsData = {}) => { + wrapper = shallowMount(App, { propsData }); + }; + + const findNewNamespacePage = () => wrapper.findComponent(NewNamespacePage); + + const findCreateGroupPanel = () => + findNewNamespacePage() + .props('panels') + .find((panel) => panel.name === 'create-group-pane'); + + afterEach(() => { + wrapper.destroy(); + }); + + it('creates correct component for group creation', () => { + createComponent(); + + expect(findNewNamespacePage().props('initialBreadcrumb')).toBe('New group'); + expect(findCreateGroupPanel().title).toBe('Create group'); + }); + + it('creates correct component for subgroup creation', () => { + const props = { parentGroupName: 'parent', importExistingGroupPath: '/path' }; + + createComponent(props); + + expect(findNewNamespacePage().props('initialBreadcrumb')).toBe('parent'); + expect(findCreateGroupPanel().title).toBe('Create subgroup'); + expect(findCreateGroupPanel().detailProps).toEqual(props); + }); +}); diff --git a/spec/frontend/pages/groups/new/components/create_group_description_details_spec.js b/spec/frontend/pages/groups/new/components/create_group_description_details_spec.js new file mode 100644 index 00000000000..56a1fd03f71 --- /dev/null +++ b/spec/frontend/pages/groups/new/components/create_group_description_details_spec.js @@ -0,0 +1,57 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlSprintf, GlLink } from '@gitlab/ui'; +import CreateGroupDescriptionDetails from '~/pages/groups/new/components/create_group_description_details.vue'; +import { helpPagePath } from '~/helpers/help_page_helper'; + +describe('CreateGroupDescriptionDetails component', () => { + let wrapper; + + const createComponent = (propsData = {}) => { + wrapper = shallowMount(CreateGroupDescriptionDetails, { + propsData, + stubs: { GlSprintf, GlLink }, + }); + }; + + const findLinkHref = (at) => wrapper.findAllComponents(GlLink).at(at); + + afterEach(() => { + wrapper.destroy(); + }); + + it('creates correct component for group creation', () => { + createComponent(); + + const groupsLink = findLinkHref(0); + expect(groupsLink.attributes('href')).toBe(helpPagePath('user/group/index')); + expect(groupsLink.text()).toBe('Groups'); + + const subgroupsLink = findLinkHref(1); + expect(subgroupsLink.text()).toBe('subgroups'); + expect(subgroupsLink.attributes('href')).toBe(helpPagePath('user/group/subgroups/index')); + + expect(wrapper.text()).toBe( + 'Groups allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups.', + ); + }); + + it('creates correct component for subgroup creation', () => { + createComponent({ parentGroupName: 'parent', importExistingGroupPath: '/path' }); + + const groupsLink = findLinkHref(0); + expect(groupsLink.attributes('href')).toBe(helpPagePath('user/group/index')); + expect(groupsLink.text()).toBe('Groups'); + + const subgroupsLink = findLinkHref(1); + expect(subgroupsLink.text()).toBe('subgroups'); + expect(subgroupsLink.attributes('href')).toBe(helpPagePath('user/group/subgroups/index')); + + const importGroupLink = findLinkHref(2); + expect(importGroupLink.text()).toBe('import an existing group'); + expect(importGroupLink.attributes('href')).toBe('/path'); + + expect(wrapper.text()).toBe( + 'Groups and subgroups allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. You can also import an existing group.', + ); + }); +}); 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 43361bb6f24..21a38f066d9 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 @@ -3,6 +3,33 @@ exports[`Code Coverage when fetching data is successful matches the snapshot 1`] = ` <div> <div + class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-t gl-pt-4 gl-mb-3" + > + <h4 + class="gl-m-0" + sub-header="" + > + <gl-sprintf-stub + message="Code coverage statistics for %{ref} %{start_date} - %{end_date}" + /> + </h4> + + <gl-button-stub + buttontextclasses="" + category="primary" + data-testid="download-button" + href="url/" + icon="" + size="small" + variant="default" + > + + Download raw data (.csv) + + </gl-button-stub> + </div> + + <div class="gl-mt-3 gl-mb-3" > <!----> @@ -79,6 +106,7 @@ exports[`Code Coverage when fetching data is successful matches the snapshot 1`] legendmaxtext="Max" legendmintext="Min" option="[object Object]" + responsive="" thresholds="" /> </div> diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js index 0f763e3220a..f272891919d 100644 --- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js +++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js @@ -15,17 +15,26 @@ describe('Code Coverage', () => { let mockAxios; const graphEndpoint = '/graph'; + const graphStartDate = '13 February'; + const graphEndDate = '12 May'; + const graphRef = 'master'; + const graphCsvPath = 'url/'; const findAlert = () => wrapper.find(GlAlert); const findAreaChart = () => wrapper.find(GlAreaChart); const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem); const findFirstDropdownItem = () => findAllDropdownItems().at(0); const findSecondDropdownItem = () => findAllDropdownItems().at(1); + const findDownloadButton = () => wrapper.find('[data-testid="download-button"]'); const createComponent = () => { wrapper = shallowMount(CodeCoverage, { propsData: { graphEndpoint, + graphStartDate, + graphEndDate, + graphRef, + graphCsvPath, }, }); }; @@ -64,6 +73,10 @@ describe('Code Coverage', () => { it('shows no error messages', () => { expect(findAlert().exists()).toBe(false); }); + + it('does not render download button', () => { + expect(findDownloadButton().exists()).toBe(true); + }); }); describe('when fetching data fails', () => { @@ -112,6 +125,10 @@ describe('Code Coverage', () => { it('still renders an empty graph', () => { expect(findAreaChart().exists()).toBe(true); }); + + it('does not render download button', () => { + expect(findDownloadButton().exists()).toBe(false); + }); }); describe('dropdown options', () => { @@ -146,8 +163,8 @@ describe('Code Coverage', () => { await nextTick(); - expect(findFirstDropdownItem().attributes('ischecked')).toBeFalsy(); - expect(findSecondDropdownItem().attributes('ischecked')).toBeTruthy(); + expect(findFirstDropdownItem().attributes('ischecked')).toBe(undefined); + expect(findSecondDropdownItem().attributes('ischecked')).toBe('true'); }); it('updates the graph data when selecting a different option in dropdown', async () => { 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 42eeff89bf4..5b9c48f0d9b 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 @@ -226,7 +226,6 @@ describe('Timezone Dropdown', () => { it('returns the correct object if the identifier exists', () => { const res = findTimezoneByIdentifier(tzList, identifier); - expect(res).toBeTruthy(); expect(res).toBe(tzList[2]); }); diff --git a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js index 85660d09baa..f908508c4b5 100644 --- a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js +++ b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js @@ -127,6 +127,7 @@ describe('Settings Panel', () => { const findOperationsVisibilityInput = () => findOperationsSettings().findComponent(ProjectFeatureSetting); const findConfirmDangerButton = () => wrapper.findComponent(ConfirmDanger); + const findEnvironmentsSettings = () => wrapper.findComponent({ ref: 'environments-settings' }); afterEach(() => { wrapper.destroy(); @@ -786,4 +787,23 @@ describe('Settings Panel', () => { expect(findOperationsSettings().exists()).toBe(true); }); }); + + describe('Environments', () => { + describe('with feature flag', () => { + it('should show the environments toggle', () => { + wrapper = mountComponent({ + glFeatures: { splitOperationsVisibilityPermissions: true }, + }); + + expect(findEnvironmentsSettings().exists()).toBe(true); + }); + }); + describe('without feature flag', () => { + it('should not show the environments toggle', () => { + wrapper = mountComponent({}); + + expect(findEnvironmentsSettings().exists()).toBe(false); + }); + }); + }); }); diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js index a5db10d106d..204c48f8de1 100644 --- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js +++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js @@ -1,5 +1,5 @@ import { nextTick } from 'vue'; -import { GlAlert, GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui'; +import { GlAlert, GlButton, GlFormInput, GlFormGroup, GlSegmentedControl } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; @@ -106,6 +106,7 @@ describe('WikiForm', () => { MarkdownField, GlAlert, GlButton, + GlSegmentedControl, LocalStorageSync: stubComponent(LocalStorageSync), GlFormInput, GlFormGroup, @@ -317,20 +318,20 @@ describe('WikiForm', () => { }); describe('when content editor is not active', () => { - it('displays "Edit rich text" label in the toggle editing mode button', () => { - expect(findToggleEditingModeButton().text()).toBe('Edit rich text'); + it('displays "Source" label in the toggle editing mode button', () => { + expect(findToggleEditingModeButton().props().checked).toBe('source'); }); describe('when clicking the toggle editing mode button', () => { beforeEach(async () => { - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'richText'); }); it('hides the classic editor', () => { expect(findClassicEditor().exists()).toBe(false); }); - it('hides the content editor', () => { + it('shows the content editor', () => { expect(findContentEditor().exists()).toBe(true); }); }); @@ -342,7 +343,7 @@ describe('WikiForm', () => { expect(findContentEditor().exists()).toBe(false); // enable content editor - await findLocalStorageSync().vm.$emit('input', true); + await findLocalStorageSync().vm.$emit('input', 'richText'); expect(findContentEditor().exists()).toBe(true); expect(findClassicEditor().exists()).toBe(false); @@ -352,17 +353,18 @@ describe('WikiForm', () => { describe('when content editor is active', () => { let mockContentEditor; - beforeEach(async () => { + beforeEach(() => { + createWrapper(); mockContentEditor = { getSerializedContent: jest.fn(), setSerializedContent: jest.fn(), }; - await findToggleEditingModeButton().trigger('click'); + findToggleEditingModeButton().vm.$emit('input', 'richText'); }); - it('displays "Edit source" label in the toggle editing mode button', () => { - expect(findToggleEditingModeButton().text()).toBe('Edit source'); + it('displays "Edit Rich" label in the toggle editing mode button', () => { + expect(findToggleEditingModeButton().props().checked).toBe('richText'); }); describe('when clicking the toggle editing mode button', () => { @@ -374,7 +376,8 @@ describe('WikiForm', () => { ); findContentEditor().vm.$emit('initialized', mockContentEditor); - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'source'); + await nextTick(); }); it('hides the content editor', () => { @@ -389,6 +392,38 @@ describe('WikiForm', () => { expect(findContent().element.value).toBe(contentEditorFakeSerializedContent); }); }); + + describe('when content editor is loading', () => { + beforeEach(async () => { + findContentEditor().vm.$emit('loading'); + + await nextTick(); + }); + + it('disables toggle editing mode button', () => { + expect(findToggleEditingModeButton().attributes().disabled).toBe('true'); + }); + + describe('when content editor loads successfully', () => { + it('enables toggle editing mode button', async () => { + findContentEditor().vm.$emit('loadingSuccess'); + + await nextTick(); + + expect(findToggleEditingModeButton().attributes().disabled).not.toBeDefined(); + }); + }); + + describe('when content editor fails to load', () => { + it('enables toggle editing mode button', async () => { + findContentEditor().vm.$emit('loadingError'); + + await nextTick(); + + expect(findToggleEditingModeButton().attributes().disabled).not.toBeDefined(); + }); + }); + }); }); }); @@ -398,7 +433,7 @@ describe('WikiForm', () => { createWrapper({ mountFn: mount }); mock.onPost(/preview-markdown/).reply(400); - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'richText'); // try waiting for content editor to load (but it will never actually load) await waitForPromises(); @@ -410,7 +445,7 @@ describe('WikiForm', () => { describe('toggling editing modes to the classic editor', () => { beforeEach(() => { - return findToggleEditingModeButton().trigger('click'); + return findToggleEditingModeButton().vm.$emit('input', 'source'); }); it('switches to classic editor', () => { @@ -426,7 +461,7 @@ describe('WikiForm', () => { mock.onPost(/preview-markdown/).reply(200, { body: '<p>hello <strong>world</strong></p>' }); - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'richText'); await waitForPromises(); }); @@ -463,7 +498,6 @@ describe('WikiForm', () => { it('triggers tracking events on form submit', async () => { await triggerFormSubmit(); - expect(trackingSpy).toHaveBeenCalledWith(undefined, SAVED_USING_CONTENT_EDITOR_ACTION, { label: WIKI_CONTENT_EDITOR_TRACKING_LABEL, }); |