import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import { shallowMount } from '@vue/test-utils'; import RunnerCount from '~/ci/runner/components/stat/runner_count.vue'; import { INSTANCE_TYPE, GROUP_TYPE } from '~/ci/runner/constants'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { captureException } from '~/ci/runner/sentry_utils'; import allRunnersCountQuery from 'ee_else_ce/ci/runner/graphql/list/all_runners_count.query.graphql'; import groupRunnersCountQuery from 'ee_else_ce/ci/runner/graphql/list/group_runners_count.query.graphql'; import { runnersCountData, groupRunnersCountData } from '../../mock_data'; jest.mock('~/ci/runner/sentry_utils'); Vue.use(VueApollo); describe('RunnerCount', () => { let wrapper; let mockRunnersCountHandler; let mockGroupRunnersCountHandler; const createComponent = ({ props = {}, ...options } = {}) => { const handlers = [ [allRunnersCountQuery, mockRunnersCountHandler], [groupRunnersCountQuery, mockGroupRunnersCountHandler], ]; wrapper = shallowMount(RunnerCount, { apolloProvider: createMockApollo(handlers), propsData: { ...props, }, scopedSlots: { default: '{{props.count}}', }, ...options, }); return waitForPromises(); }; beforeEach(() => { mockRunnersCountHandler = jest.fn().mockResolvedValue(runnersCountData); mockGroupRunnersCountHandler = jest.fn().mockResolvedValue(groupRunnersCountData); }); describe('in admin scope', () => { const mockVariables = { status: 'ONLINE' }; beforeEach(async () => { await createComponent({ props: { scope: INSTANCE_TYPE } }); }); it('fetches data from admin query', () => { expect(mockRunnersCountHandler).toHaveBeenCalledTimes(1); expect(mockRunnersCountHandler).toHaveBeenCalledWith({}); }); it('fetches data with filters', async () => { await createComponent({ props: { scope: INSTANCE_TYPE, variables: mockVariables } }); expect(mockRunnersCountHandler).toHaveBeenCalledTimes(2); expect(mockRunnersCountHandler).toHaveBeenCalledWith(mockVariables); expect(wrapper.html()).toBe(`${runnersCountData.data.runners.count}`); }); it('does not fetch from the group query', async () => { expect(mockGroupRunnersCountHandler).not.toHaveBeenCalled(); }); describe('when this query is skipped after data was loaded', () => { beforeEach(async () => { wrapper.setProps({ skip: true }); await nextTick(); }); it('clears current data', () => { expect(wrapper.html()).toBe(''); }); }); }); describe('when skipping query', () => { beforeEach(async () => { await createComponent({ props: { scope: INSTANCE_TYPE, skip: true } }); }); it('does not fetch data', async () => { expect(mockRunnersCountHandler).not.toHaveBeenCalled(); expect(mockGroupRunnersCountHandler).not.toHaveBeenCalled(); expect(wrapper.html()).toBe(''); }); }); describe('when runners query fails', () => { const mockError = new Error('error!'); beforeEach(async () => { mockRunnersCountHandler.mockRejectedValue(mockError); await createComponent({ props: { scope: INSTANCE_TYPE } }); }); it('data is not shown and error is reported', async () => { expect(wrapper.html()).toBe(''); expect(captureException).toHaveBeenCalledWith({ component: 'RunnerCount', error: mockError, }); }); }); describe('in group scope', () => { beforeEach(async () => { await createComponent({ props: { scope: GROUP_TYPE } }); }); it('fetches data from the group query', async () => { expect(mockGroupRunnersCountHandler).toHaveBeenCalledTimes(1); expect(mockGroupRunnersCountHandler).toHaveBeenCalledWith({}); expect(wrapper.html()).toBe( `${groupRunnersCountData.data.group.runners.count}`, ); }); it('does not fetch from the group query', () => { expect(mockRunnersCountHandler).not.toHaveBeenCalled(); }); }); describe('when .refetch() is called', () => { beforeEach(async () => { await createComponent({ props: { scope: INSTANCE_TYPE } }); wrapper.vm.refetch(); }); it('data is not shown and error is reported', async () => { expect(mockRunnersCountHandler).toHaveBeenCalledTimes(2); }); }); });