diff options
Diffstat (limited to 'spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js')
-rw-r--r-- | spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js | 146 |
1 files changed, 103 insertions, 43 deletions
diff --git a/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js b/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js index cf2dacb50d8..95658f66d09 100644 --- a/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js +++ b/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js @@ -1,58 +1,45 @@ -import { GlCollapsibleListbox } from '@gitlab/ui'; -import { mount, shallowMount } from '@vue/test-utils'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; +import { GlCollapsibleListbox } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; + import SourceBranchDropdown from '~/jira_connect/branches/components/source_branch_dropdown.vue'; import { BRANCHES_PER_PAGE } from '~/jira_connect/branches/constants'; import getProjectQuery from '~/jira_connect/branches/graphql/queries/get_project.query.graphql'; -import { mockProjects } from '../mock_data'; - -const mockProject = { - id: 'test', - repository: { - branchNames: ['main', 'f-test', 'release'], - rootRef: 'main', - }, -}; -const mockSelectedProject = mockProjects[0]; - -const mockProjectQueryResponse = { - data: { - project: mockProject, - }, -}; -const mockGetProjectQuery = jest.fn().mockResolvedValue(mockProjectQueryResponse); -const mockQueryLoading = jest.fn().mockReturnValue(new Promise(() => {})); +import { + mockBranchNames, + mockBranchNames2, + mockProjects, + mockProjectQueryResponse, +} from '../mock_data'; + +Vue.use(VueApollo); describe('SourceBranchDropdown', () => { let wrapper; + const mockSelectedProject = mockProjects[0]; + const querySuccessHandler = jest.fn().mockResolvedValue(mockProjectQueryResponse()); + const queryLoadingHandler = jest.fn().mockReturnValue(new Promise(() => {})); + const findListbox = () => wrapper.findComponent(GlCollapsibleListbox); - const assertListboxItems = () => { + const assertListboxItems = (branchNames = mockBranchNames) => { const listboxItems = findListbox().props('items'); - expect(listboxItems).toHaveLength(mockProject.repository.branchNames.length); - expect(listboxItems.map((item) => item.text)).toEqual(mockProject.repository.branchNames); + expect(listboxItems).toHaveLength(branchNames.length); + expect(listboxItems.map((item) => item.text)).toEqual(branchNames); }; - function createMockApolloProvider({ getProjectQueryLoading = false } = {}) { - Vue.use(VueApollo); - - const mockApollo = createMockApollo([ - [getProjectQuery, getProjectQueryLoading ? mockQueryLoading : mockGetProjectQuery], - ]); + const createComponent = ({ props, handler = querySuccessHandler } = {}) => { + const mockApollo = createMockApollo([[getProjectQuery, handler]]); - return mockApollo; - } - - function createComponent({ mockApollo, props, mountFn = shallowMount } = {}) { - wrapper = mountFn(SourceBranchDropdown, { - apolloProvider: mockApollo || createMockApolloProvider(), + wrapper = shallowMount(SourceBranchDropdown, { + apolloProvider: mockApollo, propsData: props, }); - } + }; describe('when `selectedProject` prop is not specified', () => { beforeEach(() => { @@ -78,6 +65,7 @@ describe('SourceBranchDropdown', () => { loading: false, searchable: true, searching: false, + selected: null, toggleText: 'Select a branch', }); }); @@ -92,23 +80,26 @@ describe('SourceBranchDropdown', () => { describe('when branches are loading', () => { it('sets loading prop to true', () => { createComponent({ - mockApollo: createMockApolloProvider({ getProjectQueryLoading: true }), props: { selectedProject: mockSelectedProject }, + handler: queryLoadingHandler, }); - expect(findListbox().props('loading')).toEqual(true); + expect(findListbox().props('loading')).toBe(true); }); }); describe('when branches have loaded', () => { describe('when searching branches', () => { it('triggers a refetch', async () => { - createComponent({ mountFn: mount, props: { selectedProject: mockSelectedProject } }); + createComponent({ props: { selectedProject: mockSelectedProject } }); await waitForPromises(); const mockSearchTerm = 'mai'; + expect(querySuccessHandler).toHaveBeenCalledTimes(1); + await findListbox().vm.$emit('search', mockSearchTerm); - expect(mockGetProjectQuery).toHaveBeenCalledWith({ + expect(querySuccessHandler).toHaveBeenCalledTimes(2); + expect(querySuccessHandler).toHaveBeenLastCalledWith({ branchNamesLimit: BRANCHES_PER_PAGE, branchNamesOffset: 0, branchNamesSearchPattern: `*${mockSearchTerm}*`, @@ -129,10 +120,15 @@ describe('SourceBranchDropdown', () => { loading: false, searchable: true, searching: false, + selected: null, toggleText: 'Select a branch', }); }); + it('disables infinite scroll', () => { + expect(findListbox().props('infiniteScroll')).toBe(false); + }); + it('omits monospace styling from listbox', () => { expect(findListbox().classes()).not.toContain('gl-font-monospace'); }); @@ -142,19 +138,19 @@ describe('SourceBranchDropdown', () => { }); it("emits `change` event with the repository's `rootRef` by default", () => { - expect(wrapper.emitted('change')[0]).toEqual([mockProject.repository.rootRef]); + expect(wrapper.emitted('change')[0]).toEqual([mockBranchNames[0]]); }); describe('when selecting a listbox item', () => { it('emits `change` event with the selected branch name', () => { - const mockBranchName = mockProject.repository.branchNames[1]; + const mockBranchName = mockBranchNames[1]; findListbox().vm.$emit('select', mockBranchName); expect(wrapper.emitted('change')[1]).toEqual([mockBranchName]); }); }); describe('when `selectedBranchName` prop is specified', () => { - const mockBranchName = mockProject.repository.branchNames[2]; + const mockBranchName = mockBranchNames[2]; beforeEach(() => { wrapper.setProps({ @@ -162,6 +158,10 @@ describe('SourceBranchDropdown', () => { }); }); + it('sets listbox selected to `selectedBranchName`', () => { + expect(findListbox().props('selected')).toBe(mockBranchName); + }); + it('sets listbox text to `selectedBranchName` value', () => { expect(findListbox().props('toggleText')).toBe(mockBranchName); }); @@ -170,6 +170,66 @@ describe('SourceBranchDropdown', () => { expect(findListbox().classes()).toContain('gl-font-monospace'); }); }); + + describe('when full page of branches returns', () => { + const fullPageBranchNames = Array(BRANCHES_PER_PAGE) + .fill(1) + .map((_, i) => mockBranchNames[i % mockBranchNames.length]); + + beforeEach(async () => { + createComponent({ + props: { selectedProject: mockSelectedProject }, + handler: () => Promise.resolve(mockProjectQueryResponse(fullPageBranchNames)), + }); + await waitForPromises(); + }); + + it('enables infinite scroll', () => { + expect(findListbox().props('infiniteScroll')).toBe(true); + }); + }); + }); + + describe('when loading more branches from infinite scroll', () => { + const queryLoadMoreHandler = jest.fn(); + + beforeEach(async () => { + queryLoadMoreHandler.mockResolvedValueOnce(mockProjectQueryResponse()); + queryLoadMoreHandler.mockResolvedValueOnce(mockProjectQueryResponse(mockBranchNames2)); + createComponent({ + props: { selectedProject: mockSelectedProject }, + handler: queryLoadMoreHandler, + }); + + await waitForPromises(); + + await findListbox().vm.$emit('bottom-reached'); + }); + + it('sets loading more prop to true', () => { + expect(findListbox().props('infiniteScrollLoading')).toBe(true); + }); + + it('triggers load more query', () => { + expect(queryLoadMoreHandler).toHaveBeenLastCalledWith({ + branchNamesLimit: BRANCHES_PER_PAGE, + branchNamesOffset: 3, + branchNamesSearchPattern: '*', + projectPath: 'test-path', + }); + }); + + it('renders available source branches as listbox items', async () => { + await waitForPromises(); + + assertListboxItems([...mockBranchNames, ...mockBranchNames2]); + }); + + it('sets loading more prop to false once done', async () => { + await waitForPromises(); + + expect(findListbox().props('infiniteScrollLoading')).toBe(false); + }); }); }); }); |