175 lines
5.3 KiB
JavaScript
175 lines
5.3 KiB
JavaScript
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 PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
|
|
import BulkImportsHistoryApp from '~/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue';
|
|
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
|
|
|
describe('BulkImportsHistoryApp', () => {
|
|
const API_URL = '/api/v4/bulk_imports/entities';
|
|
|
|
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,
|
|
bulk_import_id: 1,
|
|
status: 'finished',
|
|
source_full_path: 'top-level-group-12',
|
|
destination_name: 'top-level-group-12',
|
|
destination_namespace: 'h5bp',
|
|
created_at: '2021-07-08T10:03:44.743Z',
|
|
failures: [],
|
|
},
|
|
{
|
|
id: 2,
|
|
bulk_import_id: 2,
|
|
status: 'failed',
|
|
source_full_path: 'autodevops-demo',
|
|
destination_name: 'autodevops-demo',
|
|
destination_namespace: 'flightjs',
|
|
parent_id: null,
|
|
namespace_id: null,
|
|
project_id: null,
|
|
created_at: '2021-07-13T12:52:26.664Z',
|
|
updated_at: '2021-07-13T13:34:49.403Z',
|
|
failures: [
|
|
{
|
|
pipeline_class: 'BulkImports::Groups::Pipelines::GroupPipeline',
|
|
pipeline_step: 'loader',
|
|
exception_class: 'ActiveRecord::RecordNotUnique',
|
|
correlation_id_value: '01FAFYSYZ7XPF3P9NSMTS693SZ',
|
|
created_at: '2021-07-13T13:34:49.344Z',
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
let wrapper;
|
|
let mock;
|
|
|
|
function createComponent({ shallow = true } = {}) {
|
|
const mountFn = shallow ? shallowMount : mount;
|
|
wrapper = mountFn(BulkImportsHistoryApp);
|
|
}
|
|
|
|
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);
|
|
// can't use .props() or .attributes() here
|
|
expect(table.vm.$attrs.items).toHaveLength(DUMMY_RESPONSE.length);
|
|
});
|
|
|
|
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();
|
|
|
|
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 }));
|
|
});
|
|
});
|
|
|
|
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 }),
|
|
);
|
|
});
|
|
|
|
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 failures', async () => {
|
|
expect(
|
|
extendedWrapper(wrapper.find('tbody').findAll('tr').at(1)).findByText('Details').exists(),
|
|
).toBe(true);
|
|
});
|
|
|
|
it('does not render details button if relevant item has no failures', () => {
|
|
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)
|
|
.find('pre');
|
|
|
|
expect(detailsRowContent.exists()).toBe(true);
|
|
expect(JSON.parse(detailsRowContent.text())).toStrictEqual(DUMMY_RESPONSE[1].failures);
|
|
});
|
|
});
|
|
});
|