import { shallowMount } from '@vue/test-utils'; import { GlDropdownItem, GlIcon } from '@gitlab/ui'; import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue'; import { dashboardGitResponse, selfMonitoringDashboardGitResponse } from '../mock_data'; const defaultBranch = 'master'; const modalId = 'duplicateDashboardModalId'; const starredDashboards = dashboardGitResponse.filter(({ starred }) => starred); const notStarredDashboards = dashboardGitResponse.filter(({ starred }) => !starred); describe('DashboardsDropdown', () => { let wrapper; 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, modalId, }, sync: false, ...storeOpts, ...opts, }); } 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' }); const findStarredListDivider = () => wrapper.find({ ref: 'starredListDivider' }); const setSearchTerm = searchTerm => wrapper.setData({ searchTerm }); beforeEach(() => { mockDashboards = dashboardGitResponse; mockSelectedDashboard = null; }); describe('when it receives dashboards data', () => { beforeEach(() => { wrapper = createComponent(); }); it('displays an item for each dashboard', () => { expect(findItems().length).toEqual(dashboardGitResponse.length); }); 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); }); 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().then(() => { 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().then(() => { expect(findNoItemsMsg().isVisible()).toBe(true); }); }); }); 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); }); }); const duplicableCases = [ dashboardGitResponse[0], dashboardGitResponse[2], selfMonitoringDashboardGitResponse[0], ]; describe.each(duplicableCases)('when the selected dashboard can be duplicated', dashboard => { let duplicateDashboardAction; let modalDirective; beforeEach(() => { mockSelectedDashboard = dashboard; modalDirective = jest.fn(); duplicateDashboardAction = jest.fn().mockResolvedValue(); wrapper = createComponent( {}, { directives: { GlModal: modalDirective, }, methods: { // Mock vuex actions duplicateSystemDashboard: duplicateDashboardAction, }, }, ); }); it('displays a dropdown item for each dashboard', () => { expect(findItems().length).toEqual(dashboardGitResponse.length + 1); }); it('displays one "duplicate dashboard" dropdown item with a directive attached', () => { const item = wrapper.findAll('[data-testid="duplicateDashboardItem"]'); expect(item.length).toBe(1); }); it('"duplicate dashboard" dropdown item directive works', () => { const item = wrapper.find('[data-testid="duplicateDashboardItem"]'); item.trigger('click'); return wrapper.vm.$nextTick().then(() => { expect(modalDirective).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: modalId, }), ); }); }); const nonDuplicableCases = [dashboardGitResponse[1], selfMonitoringDashboardGitResponse[1]]; describe.each(nonDuplicableCases)( 'when the selected dashboard can not be duplicated', dashboard => { beforeEach(() => { mockSelectedDashboard = dashboard; wrapper = createComponent(); }); it('displays a dropdown list item for each dashboard, but no list item for "duplicate dashboard"', () => { const item = wrapper.findAll('[data-testid="duplicateDashboardItem"]'); expect(findItems()).toHaveLength(dashboardGitResponse.length); expect(item.length).toBe(0); }); }, ); 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', () => { expect(wrapper.emitted().selectDashboard[0]).toEqual([dashboardGitResponse[0]]); }); }); });