diff options
Diffstat (limited to 'spec/frontend/import_projects/components/import_projects_table_spec.js')
-rw-r--r-- | spec/frontend/import_projects/components/import_projects_table_spec.js | 114 |
1 files changed, 68 insertions, 46 deletions
diff --git a/spec/frontend/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_projects/components/import_projects_table_spec.js index b217242968a..1dbad588ec4 100644 --- a/spec/frontend/import_projects/components/import_projects_table_spec.js +++ b/spec/frontend/import_projects/components/import_projects_table_spec.js @@ -1,15 +1,12 @@ import { nextTick } from 'vue'; import Vuex from 'vuex'; import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { GlLoadingIcon, GlButton } from '@gitlab/ui'; +import { GlLoadingIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui'; import state from '~/import_projects/store/state'; import * as getters from '~/import_projects/store/getters'; import { STATUSES } from '~/import_projects/constants'; import ImportProjectsTable from '~/import_projects/components/import_projects_table.vue'; -import ImportedProjectTableRow from '~/import_projects/components/imported_project_table_row.vue'; import ProviderRepoTableRow from '~/import_projects/components/provider_repo_table_row.vue'; -import IncompatibleRepoTableRow from '~/import_projects/components/incompatible_repo_table_row.vue'; -import PageQueryParamSync from '~/import_projects/components/page_query_param_sync.vue'; describe('ImportProjectsTable', () => { let wrapper; @@ -18,16 +15,26 @@ describe('ImportProjectsTable', () => { wrapper.find('input[data-qa-selector="githubish_import_filter_field"]'); const providerTitle = 'THE PROVIDER'; - const providerRepo = { id: 10, sanitizedName: 'sanitizedName', fullName: 'fullName' }; + const providerRepo = { + importSource: { + id: 10, + sanitizedName: 'sanitizedName', + fullName: 'fullName', + }, + importedProject: null, + }; const findImportAllButton = () => wrapper .findAll(GlButton) .filter(w => w.props().variant === 'success') .at(0); + const findImportAllModal = () => wrapper.find({ ref: 'importAllModal' }); const importAllFn = jest.fn(); + const importAllModalShowFn = jest.fn(); const setPageFn = jest.fn(); + const fetchReposFn = jest.fn(); function createComponent({ state: initialState, @@ -46,7 +53,7 @@ describe('ImportProjectsTable', () => { ...customGetters, }, actions: { - fetchRepos: jest.fn(), + fetchRepos: fetchReposFn, fetchJobs: jest.fn(), fetchNamespaces: jest.fn(), importAll: importAllFn, @@ -66,6 +73,9 @@ describe('ImportProjectsTable', () => { paginatable, }, slots, + stubs: { + GlModal: { template: '<div>Modal!</div>', methods: { show: importAllModalShowFn } }, + }, }); } @@ -79,58 +89,54 @@ describe('ImportProjectsTable', () => { it('renders a loading icon while repos are loading', () => { createComponent({ state: { isLoadingRepos: true } }); - expect(wrapper.contains(GlLoadingIcon)).toBe(true); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); it('renders a loading icon while namespaces are loading', () => { createComponent({ state: { isLoadingNamespaces: true } }); - expect(wrapper.contains(GlLoadingIcon)).toBe(true); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); - it('renders a table with imported projects and provider repos', () => { + it('renders a table with provider repos', () => { + const repositories = [ + { importSource: { id: 1 }, importedProject: null }, + { importSource: { id: 2 }, importedProject: { importStatus: STATUSES.FINISHED } }, + { importSource: { id: 3, incompatible: true }, importedProject: {} }, + ]; + createComponent({ - state: { - namespaces: [{ fullPath: 'path' }], - repositories: [ - { importSource: { id: 1 }, importedProject: null, importStatus: STATUSES.NONE }, - { importSource: { id: 2 }, importedProject: {}, importStatus: STATUSES.FINISHED }, - { - importSource: { id: 3, incompatible: true }, - importedProject: {}, - importStatus: STATUSES.NONE, - }, - ], - }, + state: { namespaces: [{ fullPath: 'path' }], repositories }, }); - expect(wrapper.contains(GlLoadingIcon)).toBe(false); - expect(wrapper.contains('table')).toBe(true); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); + expect(wrapper.find('table').exists()).toBe(true); expect( wrapper .findAll('th') .filter(w => w.text() === `From ${providerTitle}`) - .isEmpty(), - ).toBe(false); + .exists(), + ).toBe(true); - expect(wrapper.contains(ProviderRepoTableRow)).toBe(true); - expect(wrapper.contains(ImportedProjectTableRow)).toBe(true); - expect(wrapper.contains(IncompatibleRepoTableRow)).toBe(true); + expect(wrapper.findAll(ProviderRepoTableRow)).toHaveLength(repositories.length); }); it.each` - hasIncompatibleRepos | buttonText - ${false} | ${'Import all repositories'} - ${true} | ${'Import all compatible repositories'} + hasIncompatibleRepos | count | buttonText + ${false} | ${1} | ${'Import 1 repository'} + ${true} | ${1} | ${'Import 1 compatible repository'} + ${false} | ${5} | ${'Import 5 repositories'} + ${true} | ${5} | ${'Import 5 compatible repositories'} `( - 'import all button has "$buttonText" text when hasIncompatibleRepos is $hasIncompatibleRepos', - ({ hasIncompatibleRepos, buttonText }) => { + 'import all button has "$buttonText" text when hasIncompatibleRepos is $hasIncompatibleRepos and repos count is $count', + ({ hasIncompatibleRepos, buttonText, count }) => { createComponent({ state: { providerRepos: [providerRepo], }, getters: { hasIncompatibleRepos: () => hasIncompatibleRepos, + importAllCount: () => count, }, }); @@ -138,20 +144,28 @@ describe('ImportProjectsTable', () => { }, ); - it('renders an empty state if there are no projects available', () => { + it('renders an empty state if there are no repositories available', () => { createComponent({ state: { repositories: [] } }); - expect(wrapper.contains(ProviderRepoTableRow)).toBe(false); - expect(wrapper.contains(ImportedProjectTableRow)).toBe(false); + expect(wrapper.find(ProviderRepoTableRow).exists()).toBe(false); expect(wrapper.text()).toContain(`No ${providerTitle} repositories found`); }); - it('sends importAll event when import button is clicked', async () => { - createComponent({ state: { providerRepos: [providerRepo] } }); + it('opens confirmation modal when import all button is clicked', async () => { + createComponent({ state: { repositories: [providerRepo] } }); findImportAllButton().vm.$emit('click'); await nextTick(); + expect(importAllModalShowFn).toHaveBeenCalled(); + }); + + it('triggers importAll action when modal is confirmed', async () => { + createComponent({ state: { providerRepos: [providerRepo] } }); + + findImportAllModal().vm.$emit('ok'); + await nextTick(); + expect(importAllFn).toHaveBeenCalled(); }); @@ -189,21 +203,29 @@ describe('ImportProjectsTable', () => { }); }); - it('passes current page to page-query-param-sync component', () => { - expect(wrapper.find(PageQueryParamSync).props().page).toBe(pageInfo.page); + it('does not call fetchRepos on mount', () => { + expect(fetchReposFn).not.toHaveBeenCalled(); + }); + + it('renders intersection observer component', () => { + expect(wrapper.find(GlIntersectionObserver).exists()).toBe(true); }); - it('dispatches setPage when page-query-param-sync emits popstate', () => { - const NEW_PAGE = 2; - wrapper.find(PageQueryParamSync).vm.$emit('popstate', NEW_PAGE); + it('calls fetchRepos when intersection observer appears', async () => { + wrapper.find(GlIntersectionObserver).vm.$emit('appear'); - const { calls } = setPageFn.mock; + await nextTick(); - expect(calls).toHaveLength(1); - expect(calls[0][1]).toBe(NEW_PAGE); + expect(fetchReposFn).toHaveBeenCalled(); }); }); + it('calls fetchRepos on mount', () => { + createComponent(); + + expect(fetchReposFn).toHaveBeenCalled(); + }); + it.each` hasIncompatibleRepos | shouldRenderSlot | action ${false} | ${false} | ${'does not render'} |