diff options
Diffstat (limited to 'spec/frontend')
10 files changed, 296 insertions, 15 deletions
diff --git a/spec/frontend/__mocks__/lodash/debounce.js b/spec/frontend/__mocks__/lodash/debounce.js new file mode 100644 index 00000000000..97fdb39097a --- /dev/null +++ b/spec/frontend/__mocks__/lodash/debounce.js @@ -0,0 +1,11 @@ +// `lodash/debounce` has a non-trivial implementation which can lead to +// [flaky spec errors][1]. This mock simply makes `debounce` calls synchronous. +// +// In the future we could enhance this by injecting some test values in +// the function passed to it. See [this issue][2] for more information. +// +// [1]: https://gitlab.com/gitlab-org/gitlab/-/issues/212532 +// [2]: https://gitlab.com/gitlab-org/gitlab/-/issues/213378 +// Further reference: https://github.com/facebook/jest/issues/3465 + +export default fn => fn; diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js index db5d5c84820..782e5215ad8 100644 --- a/spec/frontend/clusters/components/applications_spec.js +++ b/spec/frontend/clusters/components/applications_spec.js @@ -400,6 +400,10 @@ describe('Applications', () => { }); describe('Knative application', () => { + const availableDomain = { + id: 4, + domain: 'newhostname.com', + }; const propsData = { applications: { ...APPLICATIONS_MOCK_STATE, @@ -409,10 +413,11 @@ describe('Applications', () => { status: 'installed', externalIp: '1.1.1.1', installed: true, + availableDomains: [availableDomain], + pagesDomain: null, }, }, }; - const newHostname = 'newhostname.com'; let wrapper; let knativeDomainEditor; @@ -428,20 +433,44 @@ describe('Applications', () => { }); it('emits saveKnativeDomain event when knative domain editor emits save event', () => { - knativeDomainEditor.vm.$emit('save', newHostname); + propsData.applications.knative.hostname = availableDomain.domain; + propsData.applications.knative.pagesDomain = availableDomain; + knativeDomainEditor.vm.$emit('save'); + + expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', { + id: 'knative', + params: { + hostname: availableDomain.domain, + pages_domain_id: availableDomain.id, + }, + }); + }); + + it('emits saveKnativeDomain event when knative domain editor emits save event with custom domain', () => { + const newHostName = 'someothernewhostname.com'; + propsData.applications.knative.hostname = newHostName; + propsData.applications.knative.pagesDomain = null; + knativeDomainEditor.vm.$emit('save'); expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', { id: 'knative', - params: { hostname: newHostname }, + params: { + hostname: newHostName, + pages_domain_id: undefined, + }, }); }); it('emits setKnativeHostname event when knative domain editor emits change event', () => { - wrapper.find(KnativeDomainEditor).vm.$emit('set', newHostname); + wrapper.find(KnativeDomainEditor).vm.$emit('set', { + domain: availableDomain.domain, + domainId: availableDomain.id, + }); - expect(eventHub.$emit).toHaveBeenCalledWith('setKnativeHostname', { + expect(eventHub.$emit).toHaveBeenCalledWith('setKnativeDomain', { id: 'knative', - hostname: newHostname, + domain: availableDomain.domain, + domainId: availableDomain.id, }); }); }); diff --git a/spec/frontend/clusters/components/knative_domain_editor_spec.js b/spec/frontend/clusters/components/knative_domain_editor_spec.js index 6514d883c0d..2de04f7da1f 100644 --- a/spec/frontend/clusters/components/knative_domain_editor_spec.js +++ b/spec/frontend/clusters/components/knative_domain_editor_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { GlDropdownItem } from '@gitlab/ui'; import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue'; import LoadingButton from '~/vue_shared/components/loading_button.vue'; import { APPLICATION_STATUS } from '~/clusters/constants'; @@ -80,7 +81,7 @@ describe('KnativeDomainEditor', () => { it('triggers save event and pass current knative hostname', () => { wrapper.find(LoadingButton).vm.$emit('click'); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('save')[0]).toEqual([knative.hostname]); + expect(wrapper.emitted('save').length).toEqual(1); }); }); }); @@ -104,14 +105,43 @@ describe('KnativeDomainEditor', () => { describe('when knative domain name input changes', () => { it('emits "set" event with updated domain name', () => { - createComponent({ knative }); + const newDomain = { + id: 4, + domain: 'newhostname.com', + }; + + createComponent({ knative: { ...knative, availableDomains: [newDomain] } }); + jest.spyOn(wrapper.vm, 'selectDomain'); + + wrapper.find(GlDropdownItem).vm.$emit('click'); + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.vm.selectDomain).toHaveBeenCalledWith(newDomain); + expect(wrapper.emitted('set')[0]).toEqual([ + { + domain: newDomain.domain, + domainId: newDomain.id, + }, + ]); + }); + }); + + it('emits "set" event with updated custom domain name', () => { const newHostname = 'newhostname.com'; + createComponent({ knative }); + jest.spyOn(wrapper.vm, 'selectCustomDomain'); + wrapper.setData({ knativeHostname: newHostname }); return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('set')[0]).toEqual([newHostname]); + expect(wrapper.vm.selectCustomDomain).toHaveBeenCalledWith(newHostname); + expect(wrapper.emitted('set')[0]).toEqual([ + { + domain: newHostname, + domainId: null, + }, + ]); }); }); }); diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js index 0207fda84c4..9fafc688af9 100644 --- a/spec/frontend/clusters/stores/clusters_store_spec.js +++ b/spec/frontend/clusters/stores/clusters_store_spec.js @@ -140,7 +140,7 @@ describe('Clusters Store', () => { statusReason: mockResponseData.applications[5].status_reason, requestReason: null, hostname: null, - isEditingHostName: false, + isEditingDomain: false, externalIp: null, externalHostname: null, installed: false, diff --git a/spec/frontend/ide/components/branches/search_list_spec.js b/spec/frontend/ide/components/branches/search_list_spec.js index 826d51b24f1..fe142d70698 100644 --- a/spec/frontend/ide/components/branches/search_list_spec.js +++ b/spec/frontend/ide/components/branches/search_list_spec.js @@ -9,8 +9,6 @@ import { branches } from '../../mock_data'; const localVue = createLocalVue(); localVue.use(Vuex); -jest.mock('lodash/debounce', () => jest.fn); - describe('IDE branches search list', () => { let wrapper; const fetchBranchesMock = jest.fn(); diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js index ae94ee4efa7..e2c6ac49e07 100644 --- a/spec/frontend/ide/components/merge_requests/list_spec.js +++ b/spec/frontend/ide/components/merge_requests/list_spec.js @@ -134,9 +134,7 @@ describe('IDE merge requests list', () => { createComponent(defaultStateWithMergeRequests); const input = findTokenedInput(); input.vm.$emit('input', 'something'); - fetchMergeRequestsMock.mockClear(); - jest.runAllTimers(); return wrapper.vm.$nextTick().then(() => { expect(fetchMergeRequestsMock).toHaveBeenCalledWith( expect.any(Object), diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js index d0abf2c03a9..4960895890f 100644 --- a/spec/frontend/lib/utils/url_utility_spec.js +++ b/spec/frontend/lib/utils/url_utility_spec.js @@ -485,4 +485,30 @@ describe('URL utility', () => { ); }); }); + + describe('getHTTPProtocol', () => { + const httpProtocol = 'http:'; + const httpsProtocol = 'https:'; + + it.each([[httpProtocol], [httpsProtocol]])( + 'when no url passed, returns correct protocol for %i from window location', + protocol => { + setWindowLocation({ + protocol, + }); + expect(urlUtils.getHTTPProtocol()).toBe(protocol.slice(0, -1)); + }, + ); + + it.each` + url | expectation + ${'not-a-url'} | ${undefined} + ${'wss://example.com'} | ${'wss'} + ${'https://foo.bar'} | ${'https'} + ${'http://foo.bar'} | ${'http'} + ${'http://foo.bar:8080'} | ${'http'} + `('returns correct protocol for $url', ({ url, expectation }) => { + expect(urlUtils.getHTTPProtocol(url)).toBe(expectation); + }); + }); }); diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js index fff76f158dd..e216f49630f 100644 --- a/spec/frontend/test_setup.js +++ b/spec/frontend/test_setup.js @@ -20,7 +20,7 @@ afterEach(() => // give Promises a bit more time so they fail the right test new Promise(setImmediate).then(() => { // wait for pending setTimeout()s - jest.runAllTimers(); + jest.runOnlyPendingTimers(); }), ); diff --git a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap new file mode 100644 index 00000000000..d837c793784 --- /dev/null +++ b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap @@ -0,0 +1,115 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Clone Dropdown Button rendering matches the snapshot 1`] = ` +<gl-new-dropdown-stub + category="primary" + headertext="" + size="medium" + text="Clone" + variant="info" +> + <div + class="pb-2 mx-1" + > + <gl-new-dropdown-header-stub> + Clone with SSH + </gl-new-dropdown-header-stub> + + <div + class="mx-3" + > + <div + readonly="readonly" + > + <b-input-group-stub + tag="div" + > + <b-input-group-prepend-stub + tag="div" + > + + <!----> + </b-input-group-prepend-stub> + + <b-form-input-stub + class="gl-form-input" + debounce="0" + readonly="true" + type="text" + value="ssh://foo.bar" + /> + + <b-input-group-append-stub + tag="div" + > + <gl-new-button-stub + category="tertiary" + data-clipboard-text="ssh://foo.bar" + icon="" + size="medium" + title="Copy URL" + variant="default" + > + <gl-icon-stub + name="copy-to-clipboard" + size="16" + title="Copy URL" + /> + </gl-new-button-stub> + </b-input-group-append-stub> + </b-input-group-stub> + </div> + </div> + + <gl-new-dropdown-header-stub> + Clone with HTTP + </gl-new-dropdown-header-stub> + + <div + class="mx-3" + > + <div + readonly="readonly" + > + <b-input-group-stub + tag="div" + > + <b-input-group-prepend-stub + tag="div" + > + + <!----> + </b-input-group-prepend-stub> + + <b-form-input-stub + class="gl-form-input" + debounce="0" + readonly="true" + type="text" + value="http://foo.bar" + /> + + <b-input-group-append-stub + tag="div" + > + <gl-new-button-stub + category="tertiary" + data-clipboard-text="http://foo.bar" + icon="" + size="medium" + title="Copy URL" + variant="default" + > + <gl-icon-stub + name="copy-to-clipboard" + size="16" + title="Copy URL" + /> + </gl-new-button-stub> + </b-input-group-append-stub> + </b-input-group-stub> + </div> + </div> + </div> +</gl-new-dropdown-stub> +`; diff --git a/spec/frontend/vue_shared/components/clone_dropdown_spec.js b/spec/frontend/vue_shared/components/clone_dropdown_spec.js new file mode 100644 index 00000000000..38e0cadfe83 --- /dev/null +++ b/spec/frontend/vue_shared/components/clone_dropdown_spec.js @@ -0,0 +1,74 @@ +import CloneDropdown from '~/vue_shared/components/clone_dropdown.vue'; +import { shallowMount } from '@vue/test-utils'; +import { GlFormInputGroup, GlNewDropdownHeader } from '@gitlab/ui'; + +describe('Clone Dropdown Button', () => { + let wrapper; + const sshLink = 'ssh://foo.bar'; + const httpLink = 'http://foo.bar'; + const httpsLink = 'https://foo.bar'; + const defaultPropsData = { + sshLink, + httpLink, + }; + + const createComponent = (propsData = defaultPropsData) => { + wrapper = shallowMount(CloneDropdown, { + propsData, + stubs: { + 'gl-form-input-group': GlFormInputGroup, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('rendering', () => { + it('matches the snapshot', () => { + createComponent(); + expect(wrapper.element).toMatchSnapshot(); + }); + + it.each` + name | index | value + ${'SSH'} | ${0} | ${sshLink} + ${'HTTP'} | ${1} | ${httpLink} + `('renders correct link and a copy-button for $name', ({ index, value }) => { + createComponent(); + const group = wrapper.findAll(GlFormInputGroup).at(index); + expect(group.props('value')).toBe(value); + expect(group.contains(GlFormInputGroup)).toBe(true); + }); + + it.each` + name | value + ${'sshLink'} | ${sshLink} + ${'httpLink'} | ${httpLink} + `('does not fail if only $name is set', ({ name, value }) => { + createComponent({ [name]: value }); + + expect(wrapper.find(GlFormInputGroup).props('value')).toBe(value); + expect(wrapper.findAll(GlNewDropdownHeader).length).toBe(1); + }); + }); + + describe('functionality', () => { + it.each` + name | value + ${'sshLink'} | ${null} + ${'httpLink'} | ${null} + `('allows null values for the props', ({ name, value }) => { + createComponent({ ...defaultPropsData, [name]: value }); + + expect(wrapper.findAll(GlNewDropdownHeader).length).toBe(1); + }); + + it('correctly calculates httpLabel for HTTPS protocol', () => { + createComponent({ httpLink: httpsLink }); + expect(wrapper.find(GlNewDropdownHeader).text()).toContain('HTTPS'); + }); + }); +}); |