gitlab-org--gitlab-foss/spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js

178 lines
4.9 KiB
JavaScript

import {
GlButton,
GlDropdown,
GlDropdownItem,
GlDropdownSectionHeader,
GlSearchBoxByType,
GlTruncate,
} from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { createAlert } from '~/flash';
import searchQuery from '~/pages/projects/forks/new/queries/search_forkable_namespaces.query.graphql';
import ProjectNamespace from '~/pages/projects/forks/new/components/project_namespace.vue';
jest.mock('~/flash');
describe('ProjectNamespace component', () => {
let wrapper;
let originalGon;
const data = {
project: {
__typename: 'Project',
id: 'gid://gitlab/Project/1',
forkTargets: {
nodes: [
{
id: 'gid://gitlab/Group/21',
fullPath: 'flightjs',
name: 'Flight JS',
visibility: 'public',
},
{
id: 'gid://gitlab/Namespace/4',
fullPath: 'root',
name: 'Administrator',
visibility: 'public',
},
],
},
},
};
const mockQueryResponse = jest.fn().mockResolvedValue({ data });
const emptyQueryResponse = {
project: {
__typename: 'Project',
id: 'gid://gitlab/Project/1',
forkTargets: {
nodes: [],
},
},
};
const mockQueryError = jest.fn().mockRejectedValue(new Error('Network error'));
Vue.use(VueApollo);
const gitlabUrl = 'https://gitlab.com';
const defaultProvide = {
projectFullPath: 'gitlab-org/project',
};
const mountComponent = ({
provide = defaultProvide,
queryHandler = mockQueryResponse,
mountFn = shallowMount,
} = {}) => {
const requestHandlers = [[searchQuery, queryHandler]];
const apolloProvider = createMockApollo(requestHandlers);
wrapper = mountFn(ProjectNamespace, {
apolloProvider,
provide,
});
};
const findButtonLabel = () => wrapper.findComponent(GlButton);
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findDropdownText = () => wrapper.findComponent(GlTruncate);
const findInput = () => wrapper.findComponent(GlSearchBoxByType);
const clickDropdownItem = async () => {
wrapper.findComponent(GlDropdownItem).vm.$emit('click');
await nextTick();
};
const showDropdown = () => {
findDropdown().vm.$emit('shown');
};
beforeAll(() => {
originalGon = window.gon;
window.gon = { gitlab_url: gitlabUrl };
});
afterAll(() => {
window.gon = originalGon;
wrapper.destroy();
});
describe('Initial state', () => {
beforeEach(() => {
mountComponent({ mountFn: mount });
jest.runOnlyPendingTimers();
});
it('renders the root url as a label', () => {
expect(findButtonLabel().text()).toBe(`${gitlabUrl}/`);
expect(findButtonLabel().props('label')).toBe(true);
});
it('renders placeholder text', () => {
expect(findDropdownText().props('text')).toBe('Select a namespace');
});
});
describe('After user interactions', () => {
beforeEach(async () => {
mountComponent({ mountFn: mount });
jest.runOnlyPendingTimers();
await nextTick();
showDropdown();
});
it('focuses on the input when the dropdown is opened', () => {
const spy = jest.spyOn(findInput().vm, 'focusInput');
showDropdown();
expect(spy).toHaveBeenCalledTimes(1);
});
it('displays fetched namespaces', () => {
const listItems = wrapper.findAll('li');
expect(listItems).toHaveLength(3);
expect(listItems.at(0).findComponent(GlDropdownSectionHeader).text()).toBe('Namespaces');
expect(listItems.at(1).text()).toBe(data.project.forkTargets.nodes[0].fullPath);
expect(listItems.at(2).text()).toBe(data.project.forkTargets.nodes[1].fullPath);
});
it('sets the selected namespace', async () => {
const { fullPath } = data.project.forkTargets.nodes[0];
await clickDropdownItem();
expect(findDropdownText().props('text')).toBe(fullPath);
});
});
describe('With empty query response', () => {
beforeEach(() => {
mountComponent({ queryHandler: emptyQueryResponse, mountFn: mount });
jest.runOnlyPendingTimers();
});
it('renders `No matches found`', () => {
expect(wrapper.find('li').text()).toBe('No matches found');
});
});
describe('With error while fetching data', () => {
beforeEach(async () => {
mountComponent({ queryHandler: mockQueryError });
jest.runOnlyPendingTimers();
await nextTick();
});
it('creates a flash message and captures the error', () => {
expect(createAlert).toHaveBeenCalledWith({
message: 'Something went wrong while loading data. Please refresh the page to try again.',
captureError: true,
error: expect.any(Error),
});
});
});
});