2020-03-09 13:42:32 +05:30
|
|
|
import { shallowMount } from '@vue/test-utils';
|
2020-05-24 23:13:21 +05:30
|
|
|
import { GlDropdownItem, GlModal, GlLoadingIcon, GlAlert, GlIcon } from '@gitlab/ui';
|
2020-03-09 13:42:32 +05:30
|
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
|
|
|
|
|
|
|
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
|
|
|
|
import DuplicateDashboardForm from '~/monitoring/components/duplicate_dashboard_form.vue';
|
|
|
|
|
|
|
|
import { dashboardGitResponse } from '../mock_data';
|
|
|
|
|
|
|
|
const defaultBranch = 'master';
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
const starredDashboards = dashboardGitResponse.filter(({ starred }) => starred);
|
|
|
|
const notStarredDashboards = dashboardGitResponse.filter(({ starred }) => !starred);
|
2020-03-09 13:42:32 +05:30
|
|
|
|
|
|
|
describe('DashboardsDropdown', () => {
|
|
|
|
let wrapper;
|
2020-05-24 23:13:21 +05:30
|
|
|
let mockDashboards;
|
|
|
|
let mockSelectedDashboard;
|
|
|
|
|
|
|
|
function createComponent(props, opts = {}) {
|
|
|
|
const storeOpts = {
|
|
|
|
methods: {
|
|
|
|
duplicateSystemDashboard: jest.fn(),
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
allDashboards: () => mockDashboards,
|
|
|
|
selectedDashboard: () => mockSelectedDashboard,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return shallowMount(DashboardsDropdown, {
|
|
|
|
propsData: {
|
|
|
|
...props,
|
|
|
|
defaultBranch,
|
|
|
|
},
|
|
|
|
sync: false,
|
|
|
|
...storeOpts,
|
|
|
|
...opts,
|
|
|
|
});
|
|
|
|
}
|
2020-03-09 13:42:32 +05:30
|
|
|
|
|
|
|
const findItems = () => wrapper.findAll(GlDropdownItem);
|
|
|
|
const findItemAt = i => wrapper.findAll(GlDropdownItem).at(i);
|
|
|
|
const findSearchInput = () => wrapper.find({ ref: 'monitorDashboardsDropdownSearch' });
|
|
|
|
const findNoItemsMsg = () => wrapper.find({ ref: 'monitorDashboardsDropdownMsg' });
|
2020-05-24 23:13:21 +05:30
|
|
|
const findStarredListDivider = () => wrapper.find({ ref: 'starredListDivider' });
|
2020-03-09 13:42:32 +05:30
|
|
|
const setSearchTerm = searchTerm => wrapper.setData({ searchTerm });
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
beforeEach(() => {
|
|
|
|
mockDashboards = dashboardGitResponse;
|
|
|
|
mockSelectedDashboard = null;
|
|
|
|
});
|
|
|
|
|
2020-03-09 13:42:32 +05:30
|
|
|
describe('when it receives dashboards data', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
wrapper = createComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays an item for each dashboard', () => {
|
|
|
|
expect(findItems().length).toEqual(dashboardGitResponse.length);
|
|
|
|
});
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
it('displays items with the dashboard display name, with starred dashboards first', () => {
|
|
|
|
expect(findItemAt(0).text()).toBe(starredDashboards[0].display_name);
|
|
|
|
expect(findItemAt(1).text()).toBe(notStarredDashboards[0].display_name);
|
|
|
|
expect(findItemAt(2).text()).toBe(notStarredDashboards[1].display_name);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays separator between starred and not starred dashboards', () => {
|
|
|
|
expect(findStarredListDivider().exists()).toBe(true);
|
2020-03-09 13:42:32 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a search input', () => {
|
|
|
|
expect(findSearchInput().isVisible()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('hides no message text by default', () => {
|
|
|
|
expect(findNoItemsMsg().isVisible()).toBe(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('filters dropdown items when searched for item exists in the list', () => {
|
|
|
|
const searchTerm = 'Default';
|
|
|
|
setSearchTerm(searchTerm);
|
|
|
|
|
|
|
|
return wrapper.vm.$nextTick(() => {
|
|
|
|
expect(findItems()).toHaveLength(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('shows no items found message when searched for item does not exists in the list', () => {
|
|
|
|
const searchTerm = 'does-not-exist';
|
|
|
|
setSearchTerm(searchTerm);
|
|
|
|
|
|
|
|
return wrapper.vm.$nextTick(() => {
|
|
|
|
expect(findNoItemsMsg().isVisible()).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
describe('when the dashboard is missing a display name', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mockDashboards = dashboardGitResponse.map(d => ({ ...d, display_name: undefined }));
|
|
|
|
wrapper = createComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays items with the dashboard path, with starred dashboards first', () => {
|
|
|
|
expect(findItemAt(0).text()).toBe(starredDashboards[0].path);
|
|
|
|
expect(findItemAt(1).text()).toBe(notStarredDashboards[0].path);
|
|
|
|
expect(findItemAt(2).text()).toBe(notStarredDashboards[1].path);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when it receives starred dashboards', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mockDashboards = starredDashboards;
|
|
|
|
wrapper = createComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays an item for each dashboard', () => {
|
|
|
|
expect(findItems().length).toEqual(starredDashboards.length);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a star icon', () => {
|
|
|
|
const star = findItemAt(0).find(GlIcon);
|
|
|
|
expect(star.exists()).toBe(true);
|
|
|
|
expect(star.attributes('name')).toBe('star');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays no separator between starred and not starred dashboards', () => {
|
|
|
|
expect(findStarredListDivider().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when it receives only not-starred dashboards', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
mockDashboards = notStarredDashboards;
|
|
|
|
wrapper = createComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays an item for each dashboard', () => {
|
|
|
|
expect(findItems().length).toEqual(notStarredDashboards.length);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays no star icon', () => {
|
|
|
|
const star = findItemAt(0).find(GlIcon);
|
|
|
|
expect(star.exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays no separator between starred and not starred dashboards', () => {
|
|
|
|
expect(findStarredListDivider().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-03-09 13:42:32 +05:30
|
|
|
describe('when a system dashboard is selected', () => {
|
|
|
|
let duplicateDashboardAction;
|
|
|
|
let modalDirective;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
2020-05-24 23:13:21 +05:30
|
|
|
[mockSelectedDashboard] = dashboardGitResponse;
|
2020-03-09 13:42:32 +05:30
|
|
|
modalDirective = jest.fn();
|
|
|
|
duplicateDashboardAction = jest.fn().mockResolvedValue();
|
|
|
|
|
|
|
|
wrapper = createComponent(
|
2020-05-24 23:13:21 +05:30
|
|
|
{},
|
2020-03-09 13:42:32 +05:30
|
|
|
{
|
|
|
|
directives: {
|
|
|
|
GlModal: modalDirective,
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
// Mock vuex actions
|
|
|
|
duplicateSystemDashboard: duplicateDashboardAction,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
wrapper.vm.$refs.duplicateDashboardModal.hide = jest.fn();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays an item for each dashboard plus a "duplicate dashboard" item', () => {
|
|
|
|
const item = wrapper.findAll({ ref: 'duplicateDashboardItem' });
|
|
|
|
|
|
|
|
expect(findItems().length).toEqual(dashboardGitResponse.length + 1);
|
|
|
|
expect(item.length).toBe(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('modal form', () => {
|
|
|
|
let okEvent;
|
|
|
|
|
|
|
|
const findModal = () => wrapper.find(GlModal);
|
|
|
|
const findAlert = () => wrapper.find(GlAlert);
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
okEvent = {
|
|
|
|
preventDefault: jest.fn(),
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
it('exists and contains a form to duplicate a dashboard', () => {
|
|
|
|
expect(findModal().exists()).toBe(true);
|
|
|
|
expect(findModal().contains(DuplicateDashboardForm)).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('saves a new dashboard', () => {
|
|
|
|
findModal().vm.$emit('ok', okEvent);
|
|
|
|
|
|
|
|
return waitForPromises().then(() => {
|
|
|
|
expect(okEvent.preventDefault).toHaveBeenCalled();
|
|
|
|
|
|
|
|
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
|
|
|
expect(wrapper.vm.$refs.duplicateDashboardModal.hide).toHaveBeenCalled();
|
|
|
|
expect(wrapper.emitted().selectDashboard).toBeTruthy();
|
|
|
|
expect(findAlert().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when a new dashboard is saved succesfully', () => {
|
|
|
|
const newDashboard = {
|
|
|
|
can_edit: true,
|
|
|
|
default: false,
|
|
|
|
display_name: 'A new dashboard',
|
|
|
|
system_dashboard: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
const submitForm = formVals => {
|
|
|
|
duplicateDashboardAction.mockResolvedValueOnce(newDashboard);
|
|
|
|
findModal()
|
|
|
|
.find(DuplicateDashboardForm)
|
|
|
|
.vm.$emit('change', {
|
|
|
|
dashboard: 'common_metrics.yml',
|
|
|
|
commitMessage: 'A commit message',
|
|
|
|
...formVals,
|
|
|
|
});
|
|
|
|
findModal().vm.$emit('ok', okEvent);
|
|
|
|
};
|
|
|
|
|
|
|
|
it('to the default branch, redirects to the new dashboard', () => {
|
|
|
|
submitForm({
|
|
|
|
branch: defaultBranch,
|
|
|
|
});
|
|
|
|
|
|
|
|
return waitForPromises().then(() => {
|
|
|
|
expect(wrapper.emitted().selectDashboard[0][0]).toEqual(newDashboard);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('to a new branch refreshes in the current dashboard', () => {
|
|
|
|
submitForm({
|
|
|
|
branch: 'another-branch',
|
|
|
|
});
|
|
|
|
|
|
|
|
return waitForPromises().then(() => {
|
|
|
|
expect(wrapper.emitted().selectDashboard[0][0]).toEqual(dashboardGitResponse[0]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('handles error when a new dashboard is not saved', () => {
|
|
|
|
const errMsg = 'An error occurred';
|
|
|
|
|
|
|
|
duplicateDashboardAction.mockRejectedValueOnce(errMsg);
|
|
|
|
findModal().vm.$emit('ok', okEvent);
|
|
|
|
|
|
|
|
return waitForPromises().then(() => {
|
|
|
|
expect(okEvent.preventDefault).toHaveBeenCalled();
|
|
|
|
|
|
|
|
expect(findAlert().exists()).toBe(true);
|
|
|
|
expect(findAlert().text()).toBe(errMsg);
|
|
|
|
|
|
|
|
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
|
|
|
expect(wrapper.vm.$refs.duplicateDashboardModal.hide).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('id is correct, as the value of modal directive binding matches modal id', () => {
|
|
|
|
expect(modalDirective).toHaveBeenCalledTimes(1);
|
|
|
|
|
|
|
|
// Binding's second argument contains the modal id
|
|
|
|
expect(modalDirective.mock.calls[0][1]).toEqual(
|
|
|
|
expect.objectContaining({
|
|
|
|
value: findModal().props('modalId'),
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('updates the form on changes', () => {
|
|
|
|
const formVals = {
|
|
|
|
dashboard: 'common_metrics.yml',
|
|
|
|
commitMessage: 'A commit message',
|
|
|
|
};
|
|
|
|
|
|
|
|
findModal()
|
|
|
|
.find(DuplicateDashboardForm)
|
|
|
|
.vm.$emit('change', formVals);
|
|
|
|
|
|
|
|
// Binding's second argument contains the modal id
|
|
|
|
expect(wrapper.vm.form).toEqual(formVals);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when a custom dashboard is selected', () => {
|
|
|
|
const findModal = () => wrapper.find(GlModal);
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
wrapper = createComponent({
|
|
|
|
selectedDashboard: dashboardGitResponse[1],
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays an item for each dashboard', () => {
|
|
|
|
const item = wrapper.findAll({ ref: 'duplicateDashboardItem' });
|
|
|
|
|
|
|
|
expect(findItems()).toHaveLength(dashboardGitResponse.length);
|
|
|
|
expect(item.length).toBe(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('modal form does not exist and contains a form to duplicate a dashboard', () => {
|
|
|
|
expect(findModal().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when a dashboard gets selected by the user', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
wrapper = createComponent();
|
|
|
|
findItemAt(1).vm.$emit('click');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('emits a "selectDashboard" event', () => {
|
|
|
|
expect(wrapper.emitted().selectDashboard).toBeTruthy();
|
|
|
|
});
|
|
|
|
it('emits a "selectDashboard" event with dashboard information', () => {
|
2020-05-24 23:13:21 +05:30
|
|
|
expect(wrapper.emitted().selectDashboard[0]).toEqual([dashboardGitResponse[0]]);
|
2020-03-09 13:42:32 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|