summaryrefslogtreecommitdiff
path: root/spec/frontend/runner/runner_list
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/runner/runner_list')
-rw-r--r--spec/frontend/runner/runner_list/runner_list_app_spec.js237
-rw-r--r--spec/frontend/runner/runner_list/runner_search_utils_spec.js272
2 files changed, 0 insertions, 509 deletions
diff --git a/spec/frontend/runner/runner_list/runner_list_app_spec.js b/spec/frontend/runner/runner_list/runner_list_app_spec.js
deleted file mode 100644
index 54b7d1f1bdb..00000000000
--- a/spec/frontend/runner/runner_list/runner_list_app_spec.js
+++ /dev/null
@@ -1,237 +0,0 @@
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { TEST_HOST } from 'helpers/test_constants';
-import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
-import { updateHistory } from '~/lib/utils/url_utility';
-
-import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
-import RunnerList from '~/runner/components/runner_list.vue';
-import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue';
-import RunnerPagination from '~/runner/components/runner_pagination.vue';
-import RunnerTypeHelp from '~/runner/components/runner_type_help.vue';
-
-import {
- CREATED_ASC,
- CREATED_DESC,
- DEFAULT_SORT,
- INSTANCE_TYPE,
- PARAM_KEY_STATUS,
- STATUS_ACTIVE,
- RUNNER_PAGE_SIZE,
-} from '~/runner/constants';
-import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
-import RunnerListApp from '~/runner/runner_list/runner_list_app.vue';
-import { captureException } from '~/runner/sentry_utils';
-
-import { runnersData, runnersDataPaginated } from '../mock_data';
-
-const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN';
-const mockActiveRunnersCount = 2;
-
-jest.mock('~/flash');
-jest.mock('~/runner/sentry_utils');
-jest.mock('~/lib/utils/url_utility', () => ({
- ...jest.requireActual('~/lib/utils/url_utility'),
- updateHistory: jest.fn(),
-}));
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-describe('RunnerListApp', () => {
- let wrapper;
- let mockRunnersQuery;
- let originalLocation;
-
- const findRunnerTypeHelp = () => wrapper.findComponent(RunnerTypeHelp);
- const findRunnerManualSetupHelp = () => wrapper.findComponent(RunnerManualSetupHelp);
- const findRunnerList = () => wrapper.findComponent(RunnerList);
- const findRunnerPagination = () => wrapper.findComponent(RunnerPagination);
- const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar);
-
- const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
- const handlers = [[getRunnersQuery, mockRunnersQuery]];
-
- wrapper = mountFn(RunnerListApp, {
- localVue,
- apolloProvider: createMockApollo(handlers),
- propsData: {
- activeRunnersCount: mockActiveRunnersCount,
- registrationToken: mockRegistrationToken,
- ...props,
- },
- });
- };
-
- const setQuery = (query) => {
- window.location.href = `${TEST_HOST}/admin/runners?${query}`;
- window.location.search = query;
- };
-
- beforeAll(() => {
- originalLocation = window.location;
- Object.defineProperty(window, 'location', { writable: true, value: { href: '', search: '' } });
- });
-
- afterAll(() => {
- window.location = originalLocation;
- });
-
- beforeEach(async () => {
- setQuery('');
-
- mockRunnersQuery = jest.fn().mockResolvedValue(runnersData);
- createComponentWithApollo();
- await waitForPromises();
- });
-
- afterEach(() => {
- mockRunnersQuery.mockReset();
- wrapper.destroy();
- });
-
- it('shows the runners list', () => {
- expect(runnersData.data.runners.nodes).toMatchObject(findRunnerList().props('runners'));
- });
-
- it('requests the runners with no filters', () => {
- expect(mockRunnersQuery).toHaveBeenLastCalledWith({
- status: undefined,
- type: undefined,
- sort: DEFAULT_SORT,
- first: RUNNER_PAGE_SIZE,
- });
- });
-
- it('shows the runner type help', () => {
- expect(findRunnerTypeHelp().exists()).toBe(true);
- });
-
- it('shows the runner setup instructions', () => {
- expect(findRunnerManualSetupHelp().exists()).toBe(true);
- expect(findRunnerManualSetupHelp().props('registrationToken')).toBe(mockRegistrationToken);
- });
-
- describe('when a filter is preselected', () => {
- beforeEach(async () => {
- setQuery(`?status[]=${STATUS_ACTIVE}&runner_type[]=${INSTANCE_TYPE}&tag[]=tag1`);
-
- createComponentWithApollo();
- await waitForPromises();
- });
-
- it('sets the filters in the search bar', () => {
- expect(findRunnerFilteredSearchBar().props('value')).toEqual({
- filters: [
- { type: 'status', value: { data: STATUS_ACTIVE, operator: '=' } },
- { type: 'runner_type', value: { data: INSTANCE_TYPE, operator: '=' } },
- { type: 'tag', value: { data: 'tag1', operator: '=' } },
- ],
- sort: 'CREATED_DESC',
- pagination: { page: 1 },
- });
- });
-
- it('requests the runners with filter parameters', () => {
- expect(mockRunnersQuery).toHaveBeenLastCalledWith({
- status: STATUS_ACTIVE,
- type: INSTANCE_TYPE,
- tagList: ['tag1'],
- sort: DEFAULT_SORT,
- first: RUNNER_PAGE_SIZE,
- });
- });
- });
-
- describe('when a filter is selected by the user', () => {
- beforeEach(() => {
- findRunnerFilteredSearchBar().vm.$emit('input', {
- filters: [{ type: PARAM_KEY_STATUS, value: { data: 'ACTIVE', operator: '=' } }],
- sort: CREATED_ASC,
- });
- });
-
- it('updates the browser url', () => {
- expect(updateHistory).toHaveBeenLastCalledWith({
- title: expect.any(String),
- url: 'http://test.host/admin/runners?status[]=ACTIVE&sort=CREATED_ASC',
- });
- });
-
- it('requests the runners with filters', () => {
- expect(mockRunnersQuery).toHaveBeenLastCalledWith({
- status: STATUS_ACTIVE,
- sort: CREATED_ASC,
- first: RUNNER_PAGE_SIZE,
- });
- });
- });
-
- describe('when no runners are found', () => {
- beforeEach(async () => {
- mockRunnersQuery = jest.fn().mockResolvedValue({ data: { runners: { nodes: [] } } });
- createComponentWithApollo();
- await waitForPromises();
- });
-
- it('shows a message for no results', async () => {
- expect(wrapper.text()).toContain('No runners found');
- });
- });
-
- it('when runners have not loaded, shows a loading state', () => {
- createComponentWithApollo();
- expect(findRunnerList().props('loading')).toBe(true);
- });
-
- describe('when runners query fails', () => {
- beforeEach(async () => {
- mockRunnersQuery = jest.fn().mockRejectedValue(new Error('Error!'));
- createComponentWithApollo();
-
- await waitForPromises();
- });
-
- it('error is reported to sentry', async () => {
- expect(captureException).toHaveBeenCalledWith({
- error: new Error('Network error: Error!'),
- component: 'RunnerListApp',
- });
- });
-
- it('error is shown to the user', async () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('Pagination', () => {
- beforeEach(() => {
- mockRunnersQuery = jest.fn().mockResolvedValue(runnersDataPaginated);
-
- createComponentWithApollo({ mountFn: mount });
- });
-
- it('more pages can be selected', () => {
- expect(findRunnerPagination().text()).toMatchInterpolatedText('Prev Next');
- });
-
- it('cannot navigate to the previous page', () => {
- expect(findRunnerPagination().find('[aria-disabled]').text()).toBe('Prev');
- });
-
- it('navigates to the next page', async () => {
- const nextPageBtn = findRunnerPagination().find('a');
- expect(nextPageBtn.text()).toBe('Next');
-
- await nextPageBtn.trigger('click');
-
- expect(mockRunnersQuery).toHaveBeenLastCalledWith({
- sort: CREATED_DESC,
- first: RUNNER_PAGE_SIZE,
- after: runnersDataPaginated.data.runners.pageInfo.endCursor,
- });
- });
- });
-});
diff --git a/spec/frontend/runner/runner_list/runner_search_utils_spec.js b/spec/frontend/runner/runner_list/runner_search_utils_spec.js
deleted file mode 100644
index e7969676549..00000000000
--- a/spec/frontend/runner/runner_list/runner_search_utils_spec.js
+++ /dev/null
@@ -1,272 +0,0 @@
-import { RUNNER_PAGE_SIZE } from '~/runner/constants';
-import {
- fromUrlQueryToSearch,
- fromSearchToUrl,
- fromSearchToVariables,
-} from '~/runner/runner_list/runner_search_utils';
-
-describe('search_params.js', () => {
- const examples = [
- {
- name: 'a default query',
- urlQuery: '',
- search: { filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' },
- graphqlVariables: { sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
- },
- {
- name: 'a single status',
- urlQuery: '?status[]=ACTIVE',
- search: {
- filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
- pagination: { page: 1 },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
- },
- {
- name: 'a single term text search',
- urlQuery: '?search=something',
- search: {
- filters: [
- {
- type: 'filtered-search-term',
- value: { data: 'something' },
- },
- ],
- pagination: { page: 1 },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: { search: 'something', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
- },
- {
- name: 'a two terms text search',
- urlQuery: '?search=something+else',
- search: {
- filters: [
- {
- type: 'filtered-search-term',
- value: { data: 'something' },
- },
- {
- type: 'filtered-search-term',
- value: { data: 'else' },
- },
- ],
- pagination: { page: 1 },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: { search: 'something else', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
- },
- {
- name: 'single instance type',
- urlQuery: '?runner_type[]=INSTANCE_TYPE',
- search: {
- filters: [{ type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } }],
- pagination: { page: 1 },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: { type: 'INSTANCE_TYPE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
- },
- {
- name: 'multiple runner status',
- urlQuery: '?status[]=ACTIVE&status[]=PAUSED',
- search: {
- filters: [
- { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
- { type: 'status', value: { data: 'PAUSED', operator: '=' } },
- ],
- pagination: { page: 1 },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
- },
- {
- name: 'multiple status, a single instance type and a non default sort',
- urlQuery: '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&sort=CREATED_ASC',
- search: {
- filters: [
- { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
- { type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } },
- ],
- pagination: { page: 1 },
- sort: 'CREATED_ASC',
- },
- graphqlVariables: {
- status: 'ACTIVE',
- type: 'INSTANCE_TYPE',
- sort: 'CREATED_ASC',
- first: RUNNER_PAGE_SIZE,
- },
- },
- {
- name: 'a tag',
- urlQuery: '?tag[]=tag-1',
- search: {
- filters: [{ type: 'tag', value: { data: 'tag-1', operator: '=' } }],
- pagination: { page: 1 },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: {
- tagList: ['tag-1'],
- first: 20,
- sort: 'CREATED_DESC',
- },
- },
- {
- name: 'two tags',
- urlQuery: '?tag[]=tag-1&tag[]=tag-2',
- search: {
- filters: [
- { type: 'tag', value: { data: 'tag-1', operator: '=' } },
- { type: 'tag', value: { data: 'tag-2', operator: '=' } },
- ],
- pagination: { page: 1 },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: {
- tagList: ['tag-1', 'tag-2'],
- first: 20,
- sort: 'CREATED_DESC',
- },
- },
- {
- name: 'the next page',
- urlQuery: '?page=2&after=AFTER_CURSOR',
- search: { filters: [], pagination: { page: 2, after: 'AFTER_CURSOR' }, sort: 'CREATED_DESC' },
- graphqlVariables: { sort: 'CREATED_DESC', after: 'AFTER_CURSOR', first: RUNNER_PAGE_SIZE },
- },
- {
- name: 'the previous page',
- urlQuery: '?page=2&before=BEFORE_CURSOR',
- search: {
- filters: [],
- pagination: { page: 2, before: 'BEFORE_CURSOR' },
- sort: 'CREATED_DESC',
- },
- graphqlVariables: { sort: 'CREATED_DESC', before: 'BEFORE_CURSOR', last: RUNNER_PAGE_SIZE },
- },
- {
- name: 'the next page filtered by a status, an instance type, tags and a non default sort',
- urlQuery:
- '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&tag[]=tag-1&tag[]=tag-2&sort=CREATED_ASC&page=2&after=AFTER_CURSOR',
- search: {
- filters: [
- { type: 'status', value: { data: 'ACTIVE', operator: '=' } },
- { type: 'runner_type', value: { data: 'INSTANCE_TYPE', operator: '=' } },
- { type: 'tag', value: { data: 'tag-1', operator: '=' } },
- { type: 'tag', value: { data: 'tag-2', operator: '=' } },
- ],
- pagination: { page: 2, after: 'AFTER_CURSOR' },
- sort: 'CREATED_ASC',
- },
- graphqlVariables: {
- status: 'ACTIVE',
- type: 'INSTANCE_TYPE',
- tagList: ['tag-1', 'tag-2'],
- sort: 'CREATED_ASC',
- after: 'AFTER_CURSOR',
- first: RUNNER_PAGE_SIZE,
- },
- },
- ];
-
- describe('fromUrlQueryToSearch', () => {
- examples.forEach(({ name, urlQuery, search }) => {
- it(`Converts ${name} to a search object`, () => {
- expect(fromUrlQueryToSearch(urlQuery)).toEqual(search);
- });
- });
-
- it('When search params appear as array, they are concatenated', () => {
- expect(fromUrlQueryToSearch('?search[]=my&search[]=text').filters).toEqual([
- { type: 'filtered-search-term', value: { data: 'my' } },
- { type: 'filtered-search-term', value: { data: 'text' } },
- ]);
- });
-
- it('When a page cannot be parsed as a number, it defaults to `1`', () => {
- expect(fromUrlQueryToSearch('?page=NONSENSE&after=AFTER_CURSOR').pagination).toEqual({
- page: 1,
- });
- });
-
- it('When a page is less than 1, it defaults to `1`', () => {
- expect(fromUrlQueryToSearch('?page=0&after=AFTER_CURSOR').pagination).toEqual({
- page: 1,
- });
- });
-
- it('When a page with no cursor is given, it defaults to `1`', () => {
- expect(fromUrlQueryToSearch('?page=2').pagination).toEqual({
- page: 1,
- });
- });
- });
-
- describe('fromSearchToUrl', () => {
- examples.forEach(({ name, urlQuery, search }) => {
- it(`Converts ${name} to a url`, () => {
- expect(fromSearchToUrl(search)).toEqual(`http://test.host/${urlQuery}`);
- });
- });
-
- it.each([
- 'http://test.host/?status[]=ACTIVE',
- 'http://test.host/?runner_type[]=INSTANCE_TYPE',
- 'http://test.host/?search=my_text',
- ])('When a filter is removed, it is removed from the URL', (initalUrl) => {
- const search = { filters: [], sort: 'CREATED_DESC' };
- const expectedUrl = `http://test.host/`;
-
- expect(fromSearchToUrl(search, initalUrl)).toEqual(expectedUrl);
- });
-
- it('When unrelated search parameter is present, it does not get removed', () => {
- const initialUrl = `http://test.host/?unrelated=UNRELATED&status[]=ACTIVE`;
- const search = { filters: [], sort: 'CREATED_DESC' };
- const expectedUrl = `http://test.host/?unrelated=UNRELATED`;
-
- expect(fromSearchToUrl(search, initialUrl)).toEqual(expectedUrl);
- });
- });
-
- describe('fromSearchToVariables', () => {
- examples.forEach(({ name, graphqlVariables, search }) => {
- it(`Converts ${name} to a GraphQL query variables object`, () => {
- expect(fromSearchToVariables(search)).toEqual(graphqlVariables);
- });
- });
-
- it('When a search param is empty, it gets removed', () => {
- expect(
- fromSearchToVariables({
- filters: [
- {
- type: 'filtered-search-term',
- value: { data: '' },
- },
- ],
- }),
- ).toMatchObject({
- search: '',
- });
-
- expect(
- fromSearchToVariables({
- filters: [
- {
- type: 'filtered-search-term',
- value: { data: 'something' },
- },
- {
- type: 'filtered-search-term',
- value: { data: '' },
- },
- ],
- }),
- ).toMatchObject({
- search: 'something',
- });
- });
- });
-});