diff options
Diffstat (limited to 'spec/frontend/ci/runner/graphql/local_state_spec.js')
-rw-r--r-- | spec/frontend/ci/runner/graphql/local_state_spec.js | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/spec/frontend/ci/runner/graphql/local_state_spec.js b/spec/frontend/ci/runner/graphql/local_state_spec.js new file mode 100644 index 00000000000..ce07a6a618d --- /dev/null +++ b/spec/frontend/ci/runner/graphql/local_state_spec.js @@ -0,0 +1,167 @@ +import { gql } from '@apollo/client/core'; +import createApolloClient from '~/lib/graphql'; +import { createLocalState } from '~/ci/runner/graphql/list/local_state'; +import getCheckedRunnerIdsQuery from '~/ci/runner/graphql/list/checked_runner_ids.query.graphql'; +import { RUNNER_TYPENAME } from '~/ci/runner/constants'; + +const makeRunner = (id, deleteRunner = true) => ({ + id, + userPermissions: { + deleteRunner, + }, +}); + +describe('~/ci/runner/graphql/list/local_state', () => { + let localState; + let apolloClient; + + const createSubject = () => { + if (apolloClient) { + throw new Error('test subject already exists!'); + } + + localState = createLocalState(); + + const { cacheConfig, typeDefs } = localState; + + apolloClient = createApolloClient({}, { cacheConfig, typeDefs }); + }; + + const addMockRunnerToCache = (id) => { + // mock some runners in the cache to prevent dangling references + apolloClient.writeFragment({ + id: `${RUNNER_TYPENAME}:${id}`, + fragment: gql` + fragment DummyRunner on CiRunner { + __typename + } + `, + data: { + __typename: RUNNER_TYPENAME, + }, + }); + }; + + const queryCheckedRunnerIds = () => { + const { checkedRunnerIds } = apolloClient.readQuery({ + query: getCheckedRunnerIdsQuery, + }); + return checkedRunnerIds; + }; + + beforeEach(() => { + createSubject(); + }); + + afterEach(() => { + localState = null; + apolloClient = null; + }); + + describe('queryCheckedRunnerIds', () => { + it('has empty checked list by default', () => { + expect(queryCheckedRunnerIds()).toEqual([]); + }); + + it('returns checked runners that have a reference in the cache', () => { + const id = 'a'; + + addMockRunnerToCache(id); + localState.localMutations.setRunnerChecked({ + runner: makeRunner(id), + isChecked: true, + }); + + expect(queryCheckedRunnerIds()).toEqual(['a']); + }); + + it('return checked runners that are not dangling references', () => { + addMockRunnerToCache('a'); // 'b' is missing from the cache, perhaps because it was deleted + localState.localMutations.setRunnerChecked({ runner: makeRunner('a'), isChecked: true }); + localState.localMutations.setRunnerChecked({ runner: makeRunner('b'), isChecked: true }); + + expect(queryCheckedRunnerIds()).toEqual(['a']); + }); + }); + + describe.each` + inputs | expected + ${[['a', true], ['b', true], ['b', true]]} | ${['a', 'b']} + ${[['a', true], ['b', true], ['a', false]]} | ${['b']} + ${[['c', true], ['b', true], ['a', true], ['d', false]]} | ${['c', 'b', 'a']} + `('setRunnerChecked', ({ inputs, expected }) => { + beforeEach(() => { + inputs.forEach(([id, isChecked]) => { + addMockRunnerToCache(id); + localState.localMutations.setRunnerChecked({ runner: makeRunner(id), isChecked }); + }); + }); + it(`for inputs="${inputs}" has a ids="[${expected}]"`, () => { + expect(queryCheckedRunnerIds()).toEqual(expected); + }); + }); + + describe.each` + inputs | expected + ${[[['a', 'b'], true]]} | ${['a', 'b']} + ${[[['a', 'b'], false]]} | ${[]} + ${[[['a', 'b'], true], [['c', 'd'], true]]} | ${['a', 'b', 'c', 'd']} + ${[[['a', 'b'], true], [['a', 'b'], false]]} | ${[]} + ${[[['a', 'b'], true], [['b'], false]]} | ${['a']} + `('setRunnersChecked', ({ inputs, expected }) => { + beforeEach(() => { + inputs.forEach(([ids, isChecked]) => { + ids.forEach(addMockRunnerToCache); + + localState.localMutations.setRunnersChecked({ + runners: ids.map((id) => makeRunner(id)), + isChecked, + }); + }); + }); + + it(`for inputs="${inputs}" has a ids="[${expected}]"`, () => { + expect(queryCheckedRunnerIds()).toEqual(expected); + }); + }); + + describe('clearChecked', () => { + it('clears all checked items', () => { + ['a', 'b', 'c'].forEach((id) => { + addMockRunnerToCache(id); + localState.localMutations.setRunnerChecked({ runner: makeRunner(id), isChecked: true }); + }); + + expect(queryCheckedRunnerIds()).toEqual(['a', 'b', 'c']); + + localState.localMutations.clearChecked(); + + expect(queryCheckedRunnerIds()).toEqual([]); + }); + }); + + describe('when some runners cannot be deleted', () => { + beforeEach(() => { + addMockRunnerToCache('a'); + addMockRunnerToCache('b'); + }); + + it('setRunnerChecked does not check runner that cannot be deleted', () => { + localState.localMutations.setRunnerChecked({ + runner: makeRunner('a', false), + isChecked: true, + }); + + expect(queryCheckedRunnerIds()).toEqual([]); + }); + + it('setRunnersChecked does not check runner that cannot be deleted', () => { + localState.localMutations.setRunnersChecked({ + runners: [makeRunner('a', false), makeRunner('b', false)], + isChecked: true, + }); + + expect(queryCheckedRunnerIds()).toEqual([]); + }); + }); +}); |