diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-24 21:11:44 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-24 21:11:44 +0300 |
commit | fd247970cfe1e98276c780fbdcca026b7960e42a (patch) | |
tree | ab7963eb9b30fd73283c526cb6ae4ca1ef61c06f /spec/frontend | |
parent | df9890e9a702e2f12bbc8f022b916ca72820a292 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
10 files changed, 302 insertions, 19 deletions
diff --git a/spec/frontend/authentication/u2f/register_spec.js b/spec/frontend/authentication/u2f/register_spec.js index 7ae3a2734cb..23d1e5c7dee 100644 --- a/spec/frontend/authentication/u2f/register_spec.js +++ b/spec/frontend/authentication/u2f/register_spec.js @@ -1,5 +1,6 @@ import $ from 'jquery'; import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import { trimText } from 'helpers/text_helper'; import U2FRegister from '~/authentication/u2f/register'; import 'vendor/u2f'; import MockU2FDevice from './mock_u2f_device'; @@ -24,7 +25,7 @@ describe('U2FRegister', () => { it('allows registering a U2F device', () => { const setupButton = container.find('#js-setup-token-2fa-device'); - expect(setupButton.text()).toBe('Set up new device'); + expect(trimText(setupButton.text())).toBe('Set up new device'); setupButton.trigger('click'); const inProgressMessage = container.children('p'); diff --git a/spec/frontend/authentication/webauthn/register_spec.js b/spec/frontend/authentication/webauthn/register_spec.js index 95cb993fc70..773481346fc 100644 --- a/spec/frontend/authentication/webauthn/register_spec.js +++ b/spec/frontend/authentication/webauthn/register_spec.js @@ -1,5 +1,6 @@ import $ from 'jquery'; import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import { trimText } from 'helpers/text_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; import waitForPromises from 'helpers/wait_for_promises'; import WebAuthnRegister from '~/authentication/webauthn/register'; @@ -52,7 +53,7 @@ describe('WebAuthnRegister', () => { const findRetryButton = () => container.find('#js-token-2fa-try-again'); it('shows setup button', () => { - expect(findSetupButton().text()).toBe('Set up new device'); + expect(trimText(findSetupButton().text())).toBe('Set up new device'); }); describe('when unsupported', () => { diff --git a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap index 3f812d3cf4e..50cbef21fd5 100644 --- a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap +++ b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap @@ -1,9 +1,48 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Contributors charts should render charts when loading completed and there is chart data 1`] = ` +exports[`Contributors charts should render charts and a RefSelector when loading completed and there is chart data 1`] = ` <div> <div - class="contributors-charts" + class="gl-border-b gl-border-gray-100 gl-mb-6 gl-bg-gray-10 gl-p-5" + > + <div + class="gl-display-flex" + > + <div + class="gl-mr-3" + > + <refselector-stub + enabledreftypes="REF_TYPE_BRANCHES,REF_TYPE_TAGS" + name="" + projectid="23" + state="true" + togglebuttonclass="gl-max-w-26" + translations="[object Object]" + value="main" + /> + </div> + + <a + class="btn btn-default btn-md gl-button" + data-testid="history-button" + href="some/path" + > + <!----> + + <!----> + + <span + class="gl-button-text" + > + History + + </span> + </a> + </div> + </div> + + <div + data-testid="contributors-charts" > <h4 class="gl-mb-2 gl-mt-5" @@ -49,8 +88,8 @@ exports[`Contributors charts should render charts when loading completed and the class="gl-mb-3" > - 2 commits (jawnnypoo@gmail.com) - + 2 commits (jawnnypoo@gmail.com) + </p> <div> diff --git a/spec/frontend/contributors/component/contributors_spec.js b/spec/frontend/contributors/component/contributors_spec.js index 2f0b5719326..c14bbc2f9f9 100644 --- a/spec/frontend/contributors/component/contributors_spec.js +++ b/spec/frontend/contributors/component/contributors_spec.js @@ -1,21 +1,29 @@ -import { mount } from '@vue/test-utils'; -import { GlLoadingIcon } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import Vue, { nextTick } from 'vue'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import ContributorsCharts from '~/contributors/components/contributors.vue'; import { createStore } from '~/contributors/stores'; import axios from '~/lib/utils/axios_utils'; +import { visitUrl } from '~/lib/utils/url_utility'; +import RefSelector from '~/ref/components/ref_selector.vue'; +import { REF_TYPE_BRANCHES, REF_TYPE_TAGS } from '~/ref/constants'; + +jest.mock('~/lib/utils/url_utility', () => ({ + visitUrl: jest.fn(), +})); let wrapper; let mock; let store; const Component = Vue.extend(ContributorsCharts); -const endpoint = 'contributors'; +const endpoint = 'contributors/-/graphs'; const branch = 'main'; const chartData = [ { author_name: 'John', author_email: 'jawnnypoo@gmail.com', date: '2019-05-05' }, { author_name: 'John', author_email: 'jawnnypoo@gmail.com', date: '2019-03-03' }, ]; +const projectId = '23'; +const commitsPath = 'some/path'; function factory() { mock = new MockAdapter(axios); @@ -23,19 +31,27 @@ function factory() { mock.onGet().reply(200, chartData); store = createStore(); - wrapper = mount(Component, { + wrapper = mountExtended(Component, { propsData: { endpoint, branch, + projectId, + commitsPath, }, stubs: { GlLoadingIcon: true, GlAreaChart: true, + RefSelector: true, }, store, }); } +const findLoadingIcon = () => wrapper.findByTestId('loading-app-icon'); +const findRefSelector = () => wrapper.findComponent(RefSelector); +const findHistoryButton = () => wrapper.findByTestId('history-button'); +const findContributorsCharts = () => wrapper.findByTestId('contributors-charts'); + describe('Contributors charts', () => { beforeEach(() => { factory(); @@ -53,15 +69,46 @@ describe('Contributors charts', () => { it('should display loader whiled loading data', async () => { wrapper.vm.$store.state.loading = true; await nextTick(); - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true); + expect(findLoadingIcon().exists()).toBe(true); }); - it('should render charts when loading completed and there is chart data', async () => { + it('should render charts and a RefSelector when loading completed and there is chart data', async () => { wrapper.vm.$store.state.loading = false; wrapper.vm.$store.state.chartData = chartData; await nextTick(); - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false); - expect(wrapper.find('.contributors-charts').exists()).toBe(true); + + expect(findLoadingIcon().exists()).toBe(false); + expect(findRefSelector().exists()).toBe(true); + expect(findRefSelector().props()).toMatchObject({ + enabledRefTypes: [REF_TYPE_BRANCHES, REF_TYPE_TAGS], + value: branch, + projectId, + translations: { dropdownHeader: 'Switch branch/tag' }, + useSymbolicRefNames: false, + state: true, + name: '', + }); + expect(findContributorsCharts().exists()).toBe(true); expect(wrapper.element).toMatchSnapshot(); }); + + it('should have a history button with a set href attribute', async () => { + wrapper.vm.$store.state.loading = false; + wrapper.vm.$store.state.chartData = chartData; + await nextTick(); + + const historyButton = findHistoryButton(); + expect(historyButton.exists()).toBe(true); + expect(historyButton.attributes('href')).toBe(commitsPath); + }); + + it('visits a URL when clicking on a branch/tag', async () => { + wrapper.vm.$store.state.loading = false; + wrapper.vm.$store.state.chartData = chartData; + await nextTick(); + + findRefSelector().vm.$emit('input', branch); + + expect(visitUrl).toHaveBeenCalledWith(`${endpoint}/${branch}`); + }); }); diff --git a/spec/frontend/projects/settings/components/default_branch_selector_spec.js b/spec/frontend/projects/settings/components/default_branch_selector_spec.js index bfbf3e234f4..ca9a72663d2 100644 --- a/spec/frontend/projects/settings/components/default_branch_selector_spec.js +++ b/spec/frontend/projects/settings/components/default_branch_selector_spec.js @@ -34,6 +34,7 @@ describe('projects/settings/components/default_branch_selector', () => { projectId, refType: null, state: true, + toggleButtonClass: null, translations: { dropdownHeader: expect.any(String), searchPlaceholder: expect.any(String), diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js index e12659a0eff..ec14d8bacb2 100644 --- a/spec/frontend/ref/components/ref_selector_spec.js +++ b/spec/frontend/ref/components/ref_selector_spec.js @@ -715,7 +715,7 @@ describe('Ref selector component', () => { describe('validation state', () => { const invalidClass = 'gl-inset-border-1-red-500!'; const isInvalidClassApplied = () => - wrapper.findComponent(GlDropdown).props('toggleClass')[invalidClass]; + wrapper.findComponent(GlDropdown).props('toggleClass')[0][invalidClass]; describe('valid state', () => { describe('when the state prop is not provided', () => { diff --git a/spec/frontend/usage_quotas/components/usage_quotas_app_spec.js b/spec/frontend/usage_quotas/components/usage_quotas_app_spec.js new file mode 100644 index 00000000000..cb70ea4e72d --- /dev/null +++ b/spec/frontend/usage_quotas/components/usage_quotas_app_spec.js @@ -0,0 +1,39 @@ +import { GlSprintf } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import UsageQuotasApp from '~/usage_quotas/components/usage_quotas_app.vue'; +import { USAGE_QUOTAS_TITLE } from '~/usage_quotas/constants'; +import { defaultProvide } from '../mock_data'; + +describe('UsageQuotasApp', () => { + let wrapper; + + const createComponent = ({ provide = {} } = {}) => { + wrapper = shallowMountExtended(UsageQuotasApp, { + provide: { + ...defaultProvide, + ...provide, + }, + stubs: { + GlSprintf, + }, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + const findSubTitle = () => wrapper.findByTestId('usage-quotas-page-subtitle'); + + it('renders the view title', () => { + expect(wrapper.text()).toContain(USAGE_QUOTAS_TITLE); + }); + + it('renders the view subtitle', () => { + expect(findSubTitle().text()).toContain(defaultProvide.namespaceName); + }); +}); diff --git a/spec/frontend/usage_quotas/mock_data.js b/spec/frontend/usage_quotas/mock_data.js new file mode 100644 index 00000000000..a9d2a7ad1db --- /dev/null +++ b/spec/frontend/usage_quotas/mock_data.js @@ -0,0 +1,3 @@ +export const defaultProvide = { + namespaceName: 'Group 1', +}; diff --git a/spec/frontend/vue_shared/components/entity_select/group_select_spec.js b/spec/frontend/vue_shared/components/entity_select/group_select_spec.js index 2c94b34971d..b9479b0d51d 100644 --- a/spec/frontend/vue_shared/components/entity_select/group_select_spec.js +++ b/spec/frontend/vue_shared/components/entity_select/group_select_spec.js @@ -6,8 +6,8 @@ import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import GroupSelect from '~/vue_shared/components/entity_select/group_select.vue'; import EntitySelect from '~/vue_shared/components/entity_select/entity_select.vue'; import { - TOGGLE_TEXT, - HEADER_TEXT, + GROUP_TOGGLE_TEXT, + GROUP_HEADER_TEXT, FETCH_GROUPS_ERROR, FETCH_GROUP_ERROR, } from '~/vue_shared/components/entity_select/constants'; @@ -74,8 +74,8 @@ describe('GroupSelect', () => { ${'label'} | ${label} ${'inputName'} | ${inputName} ${'inputId'} | ${inputId} - ${'defaultToggleText'} | ${TOGGLE_TEXT} - ${'headerText'} | ${HEADER_TEXT} + ${'defaultToggleText'} | ${GROUP_TOGGLE_TEXT} + ${'headerText'} | ${GROUP_HEADER_TEXT} `('passes the $prop prop to entity-select', ({ prop, expectedValue }) => { expect(findEntitySelect().props(prop)).toBe(expectedValue); }); diff --git a/spec/frontend/vue_shared/components/entity_select/project_select_spec.js b/spec/frontend/vue_shared/components/entity_select/project_select_spec.js new file mode 100644 index 00000000000..ef5fa78f5cc --- /dev/null +++ b/spec/frontend/vue_shared/components/entity_select/project_select_spec.js @@ -0,0 +1,152 @@ +import { GlCollapsibleListbox } from '@gitlab/ui'; +import MockAdapter from 'axios-mock-adapter'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_OK, HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; +import ProjectSelect from '~/vue_shared/components/entity_select/project_select.vue'; +import EntitySelect from '~/vue_shared/components/entity_select/entity_select.vue'; +import { + PROJECT_TOGGLE_TEXT, + PROJECT_HEADER_TEXT, + FETCH_PROJECTS_ERROR, + FETCH_PROJECT_ERROR, +} from '~/vue_shared/components/entity_select/constants'; +import waitForPromises from 'helpers/wait_for_promises'; + +describe('ProjectSelect', () => { + let wrapper; + let mock; + + // Stubs + const GlAlert = { + template: '<div><slot /></div>', + }; + + // Props + const label = 'label'; + const inputName = 'inputName'; + const inputId = 'inputId'; + const groupId = '22'; + + // Mocks + const apiVersion = 'v4'; + const projectMock = { + name_with_namespace: 'selectedProject', + id: '1', + }; + const groupProjectEndpoint = `/api/${apiVersion}/groups/${groupId}/projects.json`; + const projectEndpoint = `/api/${apiVersion}/projects/${projectMock.id}`; + + // Finders + const findListbox = () => wrapper.findComponent(GlCollapsibleListbox); + const findEntitySelect = () => wrapper.findComponent(EntitySelect); + const findAlert = () => wrapper.findComponent(GlAlert); + + // Helpers + const createComponent = ({ props = {} } = {}) => { + wrapper = mountExtended(ProjectSelect, { + propsData: { + label, + inputName, + inputId, + groupId, + ...props, + }, + stubs: { + GlAlert, + EntitySelect, + }, + }); + }; + const openListbox = () => findListbox().vm.$emit('shown'); + + beforeAll(() => { + gon.api_version = apiVersion; + }); + + beforeEach(() => { + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + + describe('entity_select props', () => { + beforeEach(() => { + createComponent(); + }); + + it.each` + prop | expectedValue + ${'label'} | ${label} + ${'inputName'} | ${inputName} + ${'inputId'} | ${inputId} + ${'defaultToggleText'} | ${PROJECT_TOGGLE_TEXT} + ${'headerText'} | ${PROJECT_HEADER_TEXT} + `('passes the $prop prop to entity-select', ({ prop, expectedValue }) => { + expect(findEntitySelect().props(prop)).toBe(expectedValue); + }); + }); + + describe('on mount', () => { + it('fetches projects when the listbox is opened', async () => { + createComponent(); + await waitForPromises(); + + expect(mock.history.get).toHaveLength(0); + + openListbox(); + await waitForPromises(); + + expect(mock.history.get).toHaveLength(1); + expect(mock.history.get[0].url).toBe(groupProjectEndpoint); + expect(mock.history.get[0].params).toEqual({ + include_subgroups: false, + order_by: 'similarity', + per_page: 20, + search: '', + simple: true, + with_shared: true, + }); + }); + + describe('with an initial selection', () => { + it("fetches the initially selected value's name", async () => { + mock.onGet(projectEndpoint).reply(HTTP_STATUS_OK, projectMock); + createComponent({ props: { initialSelection: projectMock.id } }); + await waitForPromises(); + + expect(mock.history.get).toHaveLength(1); + expect(findListbox().props('toggleText')).toBe(projectMock.name_with_namespace); + }); + + it('show an error if fetching the individual project fails', async () => { + mock + .onGet(groupProjectEndpoint) + .reply(200, [{ full_name: 'notTheSelectedProject', id: '2' }]); + mock.onGet(projectEndpoint).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + createComponent({ props: { initialSelection: projectMock.id } }); + + expect(findAlert().exists()).toBe(false); + + await waitForPromises(); + + expect(findAlert().exists()).toBe(true); + expect(findAlert().text()).toBe(FETCH_PROJECT_ERROR); + }); + }); + }); + + it('shows an error when fetching projects fails', async () => { + mock.onGet(groupProjectEndpoint).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + createComponent(); + openListbox(); + expect(findAlert().exists()).toBe(false); + + await waitForPromises(); + + expect(findAlert().exists()).toBe(true); + expect(findAlert().text()).toBe(FETCH_PROJECTS_ERROR); + }); +}); |