summaryrefslogtreecommitdiff
path: root/spec/frontend/pages/import/history/components/import_history_app_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/pages/import/history/components/import_history_app_spec.js')
-rw-r--r--spec/frontend/pages/import/history/components/import_history_app_spec.js205
1 files changed, 205 insertions, 0 deletions
diff --git a/spec/frontend/pages/import/history/components/import_history_app_spec.js b/spec/frontend/pages/import/history/components/import_history_app_spec.js
new file mode 100644
index 00000000000..0d821b114cf
--- /dev/null
+++ b/spec/frontend/pages/import/history/components/import_history_app_spec.js
@@ -0,0 +1,205 @@
+import { GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import ImportErrorDetails from '~/pages/import/history/components/import_error_details.vue';
+import ImportHistoryApp from '~/pages/import/history/components/import_history_app.vue';
+import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { stubComponent } from 'helpers/stub_component';
+
+describe('ImportHistoryApp', () => {
+ const API_URL = '/api/v4/projects.json';
+
+ const DEFAULT_HEADERS = {
+ 'x-page': 1,
+ 'x-per-page': 20,
+ 'x-next-page': 2,
+ 'x-total': 22,
+ 'x-total-pages': 2,
+ 'x-prev-page': null,
+ };
+ const DUMMY_RESPONSE = [
+ {
+ id: 1,
+ path_with_namespace: 'root/imported',
+ created_at: '2022-03-10T15:10:03.172Z',
+ import_url: null,
+ import_type: 'gitlab_project',
+ import_status: 'finished',
+ },
+ {
+ id: 2,
+ name_with_namespace: 'Administrator / Dummy',
+ path_with_namespace: 'root/dummy',
+ created_at: '2022-03-09T11:23:04.974Z',
+ import_url: 'https://dummy.github/url',
+ import_type: 'github',
+ import_status: 'failed',
+ },
+ {
+ id: 3,
+ name_with_namespace: 'Administrator / Dummy',
+ path_with_namespace: 'root/dummy2',
+ created_at: '2022-03-09T11:23:04.974Z',
+ import_url: 'git://non-http.url',
+ import_type: 'gi',
+ import_status: 'finished',
+ },
+ ];
+ let wrapper;
+ let mock;
+
+ function createComponent({ shallow = true } = {}) {
+ const mountFn = shallow ? shallowMount : mount;
+ wrapper = mountFn(ImportHistoryApp, {
+ provide: { assets: { gitlabLogo: 'http://dummy.host' } },
+ stubs: shallow ? { GlTable: { ...stubComponent(GlTable), props: ['items'] } } : {},
+ });
+ }
+
+ const originalApiVersion = gon.api_version;
+ beforeAll(() => {
+ gon.api_version = 'v4';
+ });
+
+ afterAll(() => {
+ gon.api_version = originalApiVersion;
+ });
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+ });
+
+ describe('general behavior', () => {
+ it('renders loading state when loading', () => {
+ createComponent();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('renders empty state when no data is available', async () => {
+ mock.onGet(API_URL).reply(200, [], DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(GlEmptyState).exists()).toBe(true);
+ });
+
+ it('renders table with data when history is available', async () => {
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+
+ const table = wrapper.find(GlTable);
+ expect(table.exists()).toBe(true);
+ expect(table.props().items).toStrictEqual(DUMMY_RESPONSE);
+ });
+
+ it('changes page when requested by pagination bar', async () => {
+ const NEW_PAGE = 4;
+
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+ mock.resetHistory();
+
+ const FAKE_NEXT_PAGE_REPLY = [
+ {
+ id: 4,
+ path_with_namespace: 'root/some_other_project',
+ created_at: '2022-03-10T15:10:03.172Z',
+ import_url: null,
+ import_type: 'gitlab_project',
+ import_status: 'finished',
+ },
+ ];
+
+ mock.onGet(API_URL).reply(200, FAKE_NEXT_PAGE_REPLY, DEFAULT_HEADERS);
+
+ wrapper.findComponent(PaginationBar).vm.$emit('set-page', NEW_PAGE);
+ await axios.waitForAll();
+
+ expect(mock.history.get.length).toBe(1);
+ expect(mock.history.get[0].params).toStrictEqual(expect.objectContaining({ page: NEW_PAGE }));
+ expect(wrapper.find(GlTable).props().items).toStrictEqual(FAKE_NEXT_PAGE_REPLY);
+ });
+ });
+
+ it('changes page size when requested by pagination bar', async () => {
+ const NEW_PAGE_SIZE = 4;
+
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+ mock.resetHistory();
+
+ wrapper.findComponent(PaginationBar).vm.$emit('set-page-size', NEW_PAGE_SIZE);
+ await axios.waitForAll();
+
+ expect(mock.history.get.length).toBe(1);
+ expect(mock.history.get[0].params).toStrictEqual(
+ expect.objectContaining({ per_page: NEW_PAGE_SIZE }),
+ );
+ });
+
+ it('resets page to 1 when page size is changed', async () => {
+ const NEW_PAGE_SIZE = 4;
+
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent();
+ await axios.waitForAll();
+ wrapper.findComponent(PaginationBar).vm.$emit('set-page', 2);
+ await axios.waitForAll();
+ mock.resetHistory();
+
+ wrapper.findComponent(PaginationBar).vm.$emit('set-page-size', NEW_PAGE_SIZE);
+ await axios.waitForAll();
+
+ expect(mock.history.get.length).toBe(1);
+ expect(mock.history.get[0].params).toStrictEqual(
+ expect.objectContaining({ per_page: NEW_PAGE_SIZE, page: 1 }),
+ );
+ });
+
+ describe('details button', () => {
+ beforeEach(() => {
+ mock.onGet(API_URL).reply(200, DUMMY_RESPONSE, DEFAULT_HEADERS);
+ createComponent({ shallow: false });
+ return axios.waitForAll();
+ });
+
+ it('renders details button if relevant item has failed', async () => {
+ expect(
+ extendedWrapper(wrapper.find('tbody').findAll('tr').at(1)).findByText('Details').exists(),
+ ).toBe(true);
+ });
+
+ it('does not render details button if relevant item does not failed', () => {
+ expect(
+ extendedWrapper(wrapper.find('tbody').findAll('tr').at(0)).findByText('Details').exists(),
+ ).toBe(false);
+ });
+
+ it('expands details when details button is clicked', async () => {
+ const ORIGINAL_ROW_INDEX = 1;
+ await extendedWrapper(wrapper.find('tbody').findAll('tr').at(ORIGINAL_ROW_INDEX))
+ .findByText('Details')
+ .trigger('click');
+
+ const detailsRowContent = wrapper
+ .find('tbody')
+ .findAll('tr')
+ .at(ORIGINAL_ROW_INDEX + 1)
+ .findComponent(ImportErrorDetails);
+
+ expect(detailsRowContent.exists()).toBe(true);
+ expect(detailsRowContent.props().id).toBe(DUMMY_RESPONSE[1].id);
+ });
+ });
+});