debian-mirror-gitlab/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js

277 lines
8 KiB
JavaScript
Raw Normal View History

2021-03-11 19:13:27 +05:30
import { GlLoadingIcon, GlButton, GlIntersectionObserver, GlFormInput } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
2020-06-23 00:09:42 +05:30
import { nextTick } from 'vue';
2019-07-31 22:56:46 +05:30
import Vuex from 'vuex';
2021-02-22 17:27:13 +05:30
import { STATUSES } from '~/import_entities/constants';
import ImportProjectsTable from '~/import_entities/import_projects/components/import_projects_table.vue';
import ProviderRepoTableRow from '~/import_entities/import_projects/components/provider_repo_table_row.vue';
2021-03-11 19:13:27 +05:30
import * as getters from '~/import_entities/import_projects/store/getters';
import state from '~/import_entities/import_projects/store/state';
2019-07-31 22:56:46 +05:30
describe('ImportProjectsTable', () => {
2020-06-23 00:09:42 +05:30
let wrapper;
2021-09-30 23:02:18 +05:30
const USER_NAMESPACE = 'root';
2020-06-23 00:09:42 +05:30
const findFilterField = () =>
2021-03-11 19:13:27 +05:30
wrapper
.findAllComponents(GlFormInput)
.wrappers.find((w) => w.attributes('placeholder') === 'Filter your repositories by name');
2020-06-23 00:09:42 +05:30
2019-07-31 22:56:46 +05:30
const providerTitle = 'THE PROVIDER';
2020-11-24 15:15:51 +05:30
const providerRepo = {
importSource: {
id: 10,
sanitizedName: 'sanitizedName',
fullName: 'fullName',
},
importedProject: null,
};
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
const findImportAllButton = () =>
wrapper
.findAll(GlButton)
2021-03-08 18:12:59 +05:30
.filter((w) => w.props().variant === 'success')
2020-06-23 00:09:42 +05:30
.at(0);
2020-11-24 15:15:51 +05:30
const findImportAllModal = () => wrapper.find({ ref: 'importAllModal' });
2020-06-23 00:09:42 +05:30
2020-10-24 23:57:45 +05:30
const importAllFn = jest.fn();
2020-11-24 15:15:51 +05:30
const importAllModalShowFn = jest.fn();
const fetchReposFn = jest.fn();
2020-10-24 23:57:45 +05:30
2020-06-23 00:09:42 +05:30
function createComponent({
state: initialState,
getters: customGetters,
slots,
filterable,
2020-10-24 23:57:45 +05:30
paginatable,
2020-06-23 00:09:42 +05:30
} = {}) {
2019-07-31 22:56:46 +05:30
const localVue = createLocalVue();
localVue.use(Vuex);
2020-06-23 00:09:42 +05:30
const store = new Vuex.Store({
2021-09-30 23:02:18 +05:30
state: { ...state(), defaultTargetNamespace: USER_NAMESPACE, ...initialState },
2020-06-23 00:09:42 +05:30
getters: {
...getters,
...customGetters,
},
actions: {
2020-11-24 15:15:51 +05:30
fetchRepos: fetchReposFn,
2020-06-23 00:09:42 +05:30
fetchJobs: jest.fn(),
2020-10-24 23:57:45 +05:30
fetchNamespaces: jest.fn(),
importAll: importAllFn,
2020-06-23 00:09:42 +05:30
stopJobsPolling: jest.fn(),
clearJobsEtagPoll: jest.fn(),
setFilter: jest.fn(),
},
});
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
wrapper = shallowMount(ImportProjectsTable, {
2019-07-31 22:56:46 +05:30
localVue,
store,
propsData: {
providerTitle,
2020-06-23 00:09:42 +05:30
filterable,
2020-10-24 23:57:45 +05:30
paginatable,
2019-07-31 22:56:46 +05:30
},
2020-06-23 00:09:42 +05:30
slots,
2020-11-24 15:15:51 +05:30
stubs: {
GlModal: { template: '<div>Modal!</div>', methods: { show: importAllModalShowFn } },
},
2019-07-31 22:56:46 +05:30
});
}
afterEach(() => {
2020-06-23 00:09:42 +05:30
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
2019-07-31 22:56:46 +05:30
});
2020-06-23 00:09:42 +05:30
it('renders a loading icon while repos are loading', () => {
2020-10-24 23:57:45 +05:30
createComponent({ state: { isLoadingRepos: true } });
2020-11-24 15:15:51 +05:30
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
2020-10-24 23:57:45 +05:30
});
it('renders a loading icon while namespaces are loading', () => {
createComponent({ state: { isLoadingNamespaces: true } });
2019-07-31 22:56:46 +05:30
2020-11-24 15:15:51 +05:30
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
2019-07-31 22:56:46 +05:30
});
2020-11-24 15:15:51 +05:30
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: {} },
];
2020-06-23 00:09:42 +05:30
createComponent({
2020-11-24 15:15:51 +05:30
state: { namespaces: [{ fullPath: 'path' }], repositories },
2019-07-31 22:56:46 +05:30
});
2020-11-24 15:15:51 +05:30
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find('table').exists()).toBe(true);
2020-06-23 00:09:42 +05:30
expect(
wrapper
.findAll('th')
2021-03-08 18:12:59 +05:30
.filter((w) => w.text() === `From ${providerTitle}`)
2020-11-24 15:15:51 +05:30
.exists(),
).toBe(true);
2020-06-23 00:09:42 +05:30
2020-11-24 15:15:51 +05:30
expect(wrapper.findAll(ProviderRepoTableRow)).toHaveLength(repositories.length);
2019-07-31 22:56:46 +05:30
});
2020-06-23 00:09:42 +05:30
it.each`
2020-11-24 15:15:51 +05:30
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'}
2020-06-23 00:09:42 +05:30
`(
2020-11-24 15:15:51 +05:30
'import all button has "$buttonText" text when hasIncompatibleRepos is $hasIncompatibleRepos and repos count is $count',
({ hasIncompatibleRepos, buttonText, count }) => {
2020-06-23 00:09:42 +05:30
createComponent({
state: {
providerRepos: [providerRepo],
},
getters: {
hasIncompatibleRepos: () => hasIncompatibleRepos,
2020-11-24 15:15:51 +05:30
importAllCount: () => count,
2020-06-23 00:09:42 +05:30
},
2019-07-31 22:56:46 +05:30
});
2020-06-23 00:09:42 +05:30
expect(findImportAllButton().text()).toBe(buttonText);
},
);
2019-07-31 22:56:46 +05:30
2021-03-08 18:12:59 +05:30
it.each`
importingRepoCount | buttonMessage
${1} | ${'Importing 1 repository'}
${5} | ${'Importing 5 repositories'}
`(
'sets the button text to "$buttonMessage" when importing repos',
({ importingRepoCount, buttonMessage }) => {
createComponent({
state: {
providerRepos: [providerRepo],
},
getters: {
hasIncompatibleRepos: () => false,
importAllCount: () => 10,
isImportingAnyRepo: () => true,
importingRepoCount: () => importingRepoCount,
},
});
expect(findImportAllButton().text()).toBe(buttonMessage);
},
);
2020-11-24 15:15:51 +05:30
it('renders an empty state if there are no repositories available', () => {
2020-10-24 23:57:45 +05:30
createComponent({ state: { repositories: [] } });
2019-07-31 22:56:46 +05:30
2020-11-24 15:15:51 +05:30
expect(wrapper.find(ProviderRepoTableRow).exists()).toBe(false);
2020-06-23 00:09:42 +05:30
expect(wrapper.text()).toContain(`No ${providerTitle} repositories found`);
2019-07-31 22:56:46 +05:30
});
2020-11-24 15:15:51 +05:30
it('opens confirmation modal when import all button is clicked', async () => {
createComponent({ state: { repositories: [providerRepo] } });
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
findImportAllButton().vm.$emit('click');
await nextTick();
2020-10-24 23:57:45 +05:30
2020-11-24 15:15:51 +05:30
expect(importAllModalShowFn).toHaveBeenCalled();
});
it('triggers importAll action when modal is confirmed', async () => {
createComponent({ state: { providerRepos: [providerRepo] } });
findImportAllModal().vm.$emit('ok');
await nextTick();
2020-10-24 23:57:45 +05:30
expect(importAllFn).toHaveBeenCalled();
2020-06-23 00:09:42 +05:30
});
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
it('shows loading spinner when import is in progress', () => {
2021-03-08 18:12:59 +05:30
createComponent({ getters: { isImportingAnyRepo: () => true, importallCount: () => 1 } });
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
expect(findImportAllButton().props().loading).toBe(true);
});
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
it('renders filtering input field by default', () => {
createComponent();
2020-10-24 23:57:45 +05:30
2020-06-23 00:09:42 +05:30
expect(findFilterField().exists()).toBe(true);
});
2019-07-31 22:56:46 +05:30
2020-06-23 00:09:42 +05:30
it('does not render filtering input field when filterable is false', () => {
createComponent({ filterable: false });
2020-10-24 23:57:45 +05:30
2021-03-11 19:13:27 +05:30
expect(findFilterField()).toBeUndefined();
2020-06-23 00:09:42 +05:30
});
2019-07-31 22:56:46 +05:30
2020-10-24 23:57:45 +05:30
describe('when paginatable is set to true', () => {
const pageInfo = { page: 1 };
beforeEach(() => {
createComponent({
state: {
namespaces: [{ fullPath: 'path' }],
pageInfo,
repositories: [
{ importSource: { id: 1 }, importedProject: null, importStatus: STATUSES.NONE },
],
},
paginatable: true,
});
});
2020-11-24 15:15:51 +05:30
it('does not call fetchRepos on mount', () => {
expect(fetchReposFn).not.toHaveBeenCalled();
});
it('renders intersection observer component', () => {
expect(wrapper.find(GlIntersectionObserver).exists()).toBe(true);
2020-10-24 23:57:45 +05:30
});
2020-11-24 15:15:51 +05:30
it('calls fetchRepos when intersection observer appears', async () => {
wrapper.find(GlIntersectionObserver).vm.$emit('appear');
2020-10-24 23:57:45 +05:30
2020-11-24 15:15:51 +05:30
await nextTick();
2020-10-24 23:57:45 +05:30
2020-11-24 15:15:51 +05:30
expect(fetchReposFn).toHaveBeenCalled();
2020-10-24 23:57:45 +05:30
});
});
2020-11-24 15:15:51 +05:30
it('calls fetchRepos on mount', () => {
createComponent();
expect(fetchReposFn).toHaveBeenCalled();
});
2020-06-23 00:09:42 +05:30
it.each`
hasIncompatibleRepos | shouldRenderSlot | action
${false} | ${false} | ${'does not render'}
${true} | ${true} | ${'render'}
`(
'$action incompatible-repos-warning slot if hasIncompatibleRepos is $hasIncompatibleRepos',
({ hasIncompatibleRepos, shouldRenderSlot }) => {
const INCOMPATIBLE_TEXT = 'INCOMPATIBLE!';
createComponent({
getters: {
hasIncompatibleRepos: () => hasIncompatibleRepos,
},
slots: {
'incompatible-repos-warning': INCOMPATIBLE_TEXT,
},
2019-07-31 22:56:46 +05:30
});
2019-12-21 20:55:43 +05:30
2020-06-23 00:09:42 +05:30
expect(wrapper.text().includes(INCOMPATIBLE_TEXT)).toBe(shouldRenderSlot);
},
);
2019-07-31 22:56:46 +05:30
});