diff options
Diffstat (limited to 'spec/frontend/ci/runner')
7 files changed, 117 insertions, 35 deletions
diff --git a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js index 4f5f9c43cb4..798cef252c9 100644 --- a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js +++ b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js @@ -50,11 +50,13 @@ import { } from '~/ci/runner/constants'; import allRunnersQuery from 'ee_else_ce/ci/runner/graphql/list/all_runners.query.graphql'; import allRunnersCountQuery from 'ee_else_ce/ci/runner/graphql/list/all_runners_count.query.graphql'; +import runnerJobCountQuery from '~/ci/runner/graphql/list/runner_job_count.query.graphql'; import { captureException } from '~/ci/runner/sentry_utils'; import { allRunnersData, runnersCountData, + runnerJobCountData, allRunnersDataPaginated, onlineContactTimeoutSecs, staleTimeoutSecs, @@ -68,6 +70,7 @@ const mockRunnersCount = runnersCountData.data.runners.count; const mockRunnersHandler = jest.fn(); const mockRunnersCountHandler = jest.fn(); +const mockRunnerJobCountHandler = jest.fn(); jest.mock('~/alert'); jest.mock('~/ci/runner/sentry_utils'); @@ -108,6 +111,7 @@ describe('AdminRunnersApp', () => { const handlers = [ [allRunnersQuery, mockRunnersHandler], [allRunnersCountQuery, mockRunnersCountHandler], + [runnerJobCountQuery, mockRunnerJobCountHandler], ]; wrapper = mountFn(AdminRunnersApp, { @@ -137,11 +141,13 @@ describe('AdminRunnersApp', () => { beforeEach(() => { mockRunnersHandler.mockResolvedValue(allRunnersData); mockRunnersCountHandler.mockResolvedValue(runnersCountData); + mockRunnerJobCountHandler.mockResolvedValue(runnerJobCountData); }); afterEach(() => { mockRunnersHandler.mockReset(); mockRunnersCountHandler.mockReset(); + mockRunnerJobCountHandler.mockReset(); showToast.mockReset(); }); diff --git a/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js b/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js index 27fb288c462..2504458efff 100644 --- a/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js +++ b/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js @@ -4,6 +4,7 @@ import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_help import RunnerSummaryCell from '~/ci/runner/components/cells/runner_summary_cell.vue'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import RunnerCreatedAt from '~/ci/runner/components/runner_created_at.vue'; +import RunnerJobCount from '~/ci/runner/components/runner_job_count.vue'; import RunnerManagersBadge from '~/ci/runner/components/runner_managers_badge.vue'; import RunnerTags from '~/ci/runner/components/runner_tags.vue'; import RunnerSummaryField from '~/ci/runner/components/cells/runner_summary_field.vue'; @@ -157,23 +158,9 @@ describe('RunnerTypeCell', () => { }); it('Displays job count', () => { - expect(findRunnerSummaryField('pipeline').text()).toContain(`${mockRunner.jobCount}`); - }); - - it('Formats large job counts', () => { - createComponent({ - runner: { jobCount: 1000 }, - }); - - expect(findRunnerSummaryField('pipeline').text()).toContain('1,000'); - }); - - it('Formats large job counts with a plus symbol', () => { - createComponent({ - runner: { jobCount: 1001 }, - }); - - expect(findRunnerSummaryField('pipeline').text()).toContain('1,000+'); + expect( + findRunnerSummaryField('pipeline').findComponent(RunnerJobCount).props('runner'), + ).toEqual(mockRunner); }); it('Displays creation info', () => { diff --git a/spec/frontend/ci/runner/components/runner_filtered_search_bar_spec.js b/spec/frontend/ci/runner/components/runner_filtered_search_bar_spec.js index ffc19d66cac..62ab40b2ebb 100644 --- a/spec/frontend/ci/runner/components/runner_filtered_search_bar_spec.js +++ b/spec/frontend/ci/runner/components/runner_filtered_search_bar_spec.js @@ -1,4 +1,4 @@ -import { GlFilteredSearch, GlDropdown, GlDropdownItem } from '@gitlab/ui'; +import { GlFilteredSearch, GlSorting } from '@gitlab/ui'; import { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { assertProps } from 'helpers/assert_props'; @@ -32,7 +32,12 @@ describe('RunnerList', () => { const findFilteredSearch = () => wrapper.findComponent(FilteredSearch); const findGlFilteredSearch = () => wrapper.findComponent(GlFilteredSearch); - const findSortOptions = () => wrapper.findAllComponents(GlDropdownItem); + const findGlSorting = () => wrapper.findComponent(GlSorting); + const getSortOptions = () => findGlSorting().props('sortOptions'); + const getSelectedSortOption = () => { + const sortBy = findGlSorting().props('sortBy'); + return getSortOptions().find(({ value }) => sortBy === value)?.text; + }; const mockOtherSort = CONTACTED_DESC; const mockFilters = [ @@ -56,8 +61,6 @@ describe('RunnerList', () => { stubs: { FilteredSearch, GlFilteredSearch, - GlDropdown, - GlDropdownItem, }, ...options, }); @@ -74,9 +77,10 @@ describe('RunnerList', () => { it('sets sorting options', () => { const SORT_OPTIONS_COUNT = 2; - expect(findSortOptions()).toHaveLength(SORT_OPTIONS_COUNT); - expect(findSortOptions().at(0).text()).toBe('Created date'); - expect(findSortOptions().at(1).text()).toBe('Last contact'); + const sortOptionsProp = getSortOptions(); + expect(sortOptionsProp).toHaveLength(SORT_OPTIONS_COUNT); + expect(sortOptionsProp[0].text).toBe('Created date'); + expect(sortOptionsProp[1].text).toBe('Last contact'); }); it('sets tokens to the filtered search', () => { @@ -141,12 +145,7 @@ describe('RunnerList', () => { }); it('sort option is selected', () => { - expect( - findSortOptions() - .filter((w) => w.props('isChecked')) - .at(0) - .text(), - ).toEqual('Last contact'); + expect(getSelectedSortOption()).toBe('Last contact'); }); it('when the user sets a filter, the "search" preserves the other filters', async () => { @@ -181,7 +180,7 @@ describe('RunnerList', () => { }); it('when the user sets a sorting method, the "search" is emitted with the sort', () => { - findSortOptions().at(1).vm.$emit('click'); + findGlSorting().vm.$emit('sortByChange', 2); expectToHaveLastEmittedInput({ runnerType: null, diff --git a/spec/frontend/ci/runner/components/runner_job_count_spec.js b/spec/frontend/ci/runner/components/runner_job_count_spec.js new file mode 100644 index 00000000000..01b5ca5332e --- /dev/null +++ b/spec/frontend/ci/runner/components/runner_job_count_spec.js @@ -0,0 +1,74 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import runnerJobCountQuery from '~/ci/runner/graphql/list/runner_job_count.query.graphql'; + +import RunnerJobCount from '~/ci/runner/components/runner_job_count.vue'; + +import { runnerJobCountData } from '../mock_data'; + +const mockRunner = runnerJobCountData.data.runner; + +Vue.use(VueApollo); + +describe('RunnerJobCount', () => { + let wrapper; + let runnerJobCountHandler; + + const createComponent = ({ props = {}, ...options } = {}, mountFn = shallowMountExtended) => { + wrapper = mountFn(RunnerJobCount, { + apolloProvider: createMockApollo([[runnerJobCountQuery, runnerJobCountHandler]]), + propsData: { + runner: mockRunner, + ...props, + }, + ...options, + }); + }; + + beforeEach(() => { + runnerJobCountHandler = jest.fn().mockReturnValue(new Promise(() => {})); + }); + + it('Loads data while it displays empty content', () => { + createComponent(); + + expect(runnerJobCountHandler).toHaveBeenCalledWith({ id: mockRunner.id }); + expect(wrapper.text()).toBe('-'); + }); + + it('Sets a batch key for the "jobCount" query', () => { + createComponent(); + + expect(wrapper.vm.$apollo.queries.jobCount.options.context.batchKey).toBe('RunnerJobCount'); + }); + + it('Displays job count', async () => { + runnerJobCountHandler.mockResolvedValue(runnerJobCountData); + + createComponent(); + + await waitForPromises(); + + expect(wrapper.text()).toBe('999'); + }); + + it('Displays formatted job count', async () => { + runnerJobCountHandler.mockResolvedValue({ + data: { + runner: { + ...mockRunner, + jobCount: 1001, + }, + }, + }); + + createComponent(); + + await waitForPromises(); + + expect(wrapper.text()).toBe('1,000+'); + }); +}); diff --git a/spec/frontend/ci/runner/components/runner_managers_detail_spec.js b/spec/frontend/ci/runner/components/runner_managers_detail_spec.js index 3435292394f..6db9bb1d091 100644 --- a/spec/frontend/ci/runner/components/runner_managers_detail_spec.js +++ b/spec/frontend/ci/runner/components/runner_managers_detail_spec.js @@ -85,7 +85,7 @@ describe('RunnerJobs', () => { }); it('is collapsed', () => { - expect(findCollapse().attributes('visible')).toBeUndefined(); + expect(findCollapse().props('visible')).toBe(false); }); describe('when expanded', () => { @@ -99,7 +99,7 @@ describe('RunnerJobs', () => { }); it('shows loading state', () => { - expect(findCollapse().attributes('visible')).toBe('true'); + expect(findCollapse().props('visible')).toBe(true); expect(findSkeletonLoader().exists()).toBe(true); }); @@ -156,14 +156,14 @@ describe('RunnerJobs', () => { }); it('shows rows', () => { - expect(findCollapse().attributes('visible')).toBe('true'); + expect(findCollapse().props('visible')).toBe(true); expect(findRunnerManagersTable().props('items')).toEqual(mockRunnerManagers); }); it('collapses when clicked', async () => { await findHideDetails().trigger('click'); - expect(findCollapse().attributes('visible')).toBeUndefined(); + expect(findCollapse().props('visible')).toBe(false); }); }); }); diff --git a/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js b/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js index f3d7ae85e0d..3e4cdecb07b 100644 --- a/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js +++ b/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js @@ -50,12 +50,14 @@ import { } from '~/ci/runner/constants'; import groupRunnersQuery from 'ee_else_ce/ci/runner/graphql/list/group_runners.query.graphql'; import groupRunnersCountQuery from 'ee_else_ce/ci/runner/graphql/list/group_runners_count.query.graphql'; +import runnerJobCountQuery from '~/ci/runner/graphql/list/runner_job_count.query.graphql'; import GroupRunnersApp from '~/ci/runner/group_runners/group_runners_app.vue'; import { captureException } from '~/ci/runner/sentry_utils'; import { groupRunnersData, groupRunnersDataPaginated, groupRunnersCountData, + runnerJobCountData, onlineContactTimeoutSecs, staleTimeoutSecs, mockRegistrationToken, @@ -72,6 +74,7 @@ const mockGroupRunnersCount = mockGroupRunnersEdges.length; const mockGroupRunnersHandler = jest.fn(); const mockGroupRunnersCountHandler = jest.fn(); +const mockRunnerJobCountHandler = jest.fn(); jest.mock('~/alert'); jest.mock('~/ci/runner/sentry_utils'); @@ -108,6 +111,7 @@ describe('GroupRunnersApp', () => { const handlers = [ [groupRunnersQuery, mockGroupRunnersHandler], [groupRunnersCountQuery, mockGroupRunnersCountHandler], + [runnerJobCountQuery, mockRunnerJobCountHandler], ]; wrapper = mountFn(GroupRunnersApp, { @@ -138,11 +142,13 @@ describe('GroupRunnersApp', () => { beforeEach(() => { mockGroupRunnersHandler.mockResolvedValue(groupRunnersData); mockGroupRunnersCountHandler.mockResolvedValue(groupRunnersCountData); + mockRunnerJobCountHandler.mockResolvedValue(runnerJobCountData); }); afterEach(() => { mockGroupRunnersHandler.mockReset(); mockGroupRunnersCountHandler.mockReset(); + mockRunnerJobCountHandler.mockReset(); }); it('shows the runner tabs with a runner count for each type', async () => { diff --git a/spec/frontend/ci/runner/mock_data.js b/spec/frontend/ci/runner/mock_data.js index 51556650c32..58d8e0ee74a 100644 --- a/spec/frontend/ci/runner/mock_data.js +++ b/spec/frontend/ci/runner/mock_data.js @@ -43,6 +43,15 @@ const emptyPageInfo = { endCursor: '', }; +const runnerJobCountData = { + data: { + runner: { + id: 'gid://gitlab/Ci::Runner/99', + jobCount: 999, + }, + }, +}; + // Other mock data // Mock searches and their corresponding urls @@ -348,6 +357,7 @@ export { groupRunnersCountData, emptyPageInfo, runnerData, + runnerJobCountData, runnerWithGroupData, runnerProjectsData, runnerJobsData, |