diff options
Diffstat (limited to 'spec/frontend/environments/graphql/resolvers_spec.js')
-rw-r--r-- | spec/frontend/environments/graphql/resolvers_spec.js | 503 |
1 files changed, 0 insertions, 503 deletions
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js deleted file mode 100644 index be210ed619e..00000000000 --- a/spec/frontend/environments/graphql/resolvers_spec.js +++ /dev/null @@ -1,503 +0,0 @@ -import MockAdapter from 'axios-mock-adapter'; -import { CoreV1Api, AppsV1Api, BatchV1Api } from '@gitlab/cluster-client'; -import { s__ } from '~/locale'; -import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; -import { resolvers } from '~/environments/graphql/resolvers'; -import environmentToRollback from '~/environments/graphql/queries/environment_to_rollback.query.graphql'; -import environmentToDelete from '~/environments/graphql/queries/environment_to_delete.query.graphql'; -import environmentToStopQuery from '~/environments/graphql/queries/environment_to_stop.query.graphql'; -import createMockApollo from 'helpers/mock_apollo_helper'; -import pollIntervalQuery from '~/environments/graphql/queries/poll_interval.query.graphql'; -import isEnvironmentStoppingQuery from '~/environments/graphql/queries/is_environment_stopping.query.graphql'; -import pageInfoQuery from '~/environments/graphql/queries/page_info.query.graphql'; -import { TEST_HOST } from 'helpers/test_constants'; -import { CLUSTER_AGENT_ERROR_MESSAGES } from '~/environments/constants'; -import { - environmentsApp, - resolvedEnvironmentsApp, - resolvedEnvironment, - folder, - resolvedFolder, - k8sPodsMock, - k8sServicesMock, - k8sNamespacesMock, -} from './mock_data'; - -const ENDPOINT = `${TEST_HOST}/environments`; - -describe('~/frontend/environments/graphql/resolvers', () => { - let mockResolvers; - let mock; - let mockApollo; - let localState; - - const configuration = { - basePath: 'kas-proxy/', - baseOptions: { - headers: { 'GitLab-Agent-Id': '1' }, - }, - }; - const namespace = 'default'; - - beforeEach(() => { - mockResolvers = resolvers(ENDPOINT); - mock = new MockAdapter(axios); - mockApollo = createMockApollo(); - localState = mockApollo.defaultClient.localState; - }); - - afterEach(() => { - mock.reset(); - }); - - describe('environmentApp', () => { - it('should fetch environments and map them to frontend data', async () => { - const cache = { writeQuery: jest.fn() }; - const scope = 'available'; - const search = ''; - mock - .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search } }) - .reply(HTTP_STATUS_OK, environmentsApp, {}); - - const app = await mockResolvers.Query.environmentApp( - null, - { scope, page: 1, search }, - { cache }, - ); - expect(app).toEqual(resolvedEnvironmentsApp); - expect(cache.writeQuery).toHaveBeenCalledWith({ - query: pollIntervalQuery, - data: { interval: undefined }, - }); - }); - it('should set the poll interval when there is one', async () => { - const cache = { writeQuery: jest.fn() }; - const scope = 'stopped'; - const interval = 3000; - mock - .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } }) - .reply(HTTP_STATUS_OK, environmentsApp, { - 'poll-interval': interval, - }); - - await mockResolvers.Query.environmentApp(null, { scope, page: 1, search: '' }, { cache }); - expect(cache.writeQuery).toHaveBeenCalledWith({ - query: pollIntervalQuery, - data: { interval }, - }); - }); - it('should set page info if there is any', async () => { - const cache = { writeQuery: jest.fn() }; - const scope = 'stopped'; - mock - .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } }) - .reply(HTTP_STATUS_OK, environmentsApp, { - 'x-next-page': '2', - 'x-page': '1', - 'X-Per-Page': '2', - 'X-Prev-Page': '', - 'X-TOTAL': '37', - 'X-Total-Pages': '5', - }); - - await mockResolvers.Query.environmentApp(null, { scope, page: 1, search: '' }, { cache }); - expect(cache.writeQuery).toHaveBeenCalledWith({ - query: pageInfoQuery, - data: { - pageInfo: { - total: 37, - perPage: 2, - previousPage: NaN, - totalPages: 5, - nextPage: 2, - page: 1, - __typename: 'LocalPageInfo', - }, - }, - }); - }); - it('should not set page info if there is none', async () => { - const cache = { writeQuery: jest.fn() }; - const scope = 'stopped'; - mock - .onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } }) - .reply(HTTP_STATUS_OK, environmentsApp, {}); - - await mockResolvers.Query.environmentApp(null, { scope, page: 1, search: '' }, { cache }); - expect(cache.writeQuery).toHaveBeenCalledWith({ - query: pageInfoQuery, - data: { - pageInfo: { - __typename: 'LocalPageInfo', - nextPage: NaN, - page: NaN, - perPage: NaN, - previousPage: NaN, - total: NaN, - totalPages: NaN, - }, - }, - }); - }); - }); - describe('folder', () => { - it('should fetch the folder url passed to it', async () => { - mock - .onGet(ENDPOINT, { params: { per_page: 3, scope: 'available', search: '' } }) - .reply(HTTP_STATUS_OK, folder); - - const environmentFolder = await mockResolvers.Query.folder(null, { - environment: { folderPath: ENDPOINT }, - scope: 'available', - search: '', - }); - - expect(environmentFolder).toEqual(resolvedFolder); - }); - }); - describe('k8sPods', () => { - const mockPodsListFn = jest.fn().mockImplementation(() => { - return Promise.resolve({ - data: { - items: k8sPodsMock, - }, - }); - }); - - const mockNamespacedPodsListFn = jest.fn().mockImplementation(mockPodsListFn); - const mockAllPodsListFn = jest.fn().mockImplementation(mockPodsListFn); - - beforeEach(() => { - jest - .spyOn(CoreV1Api.prototype, 'listCoreV1NamespacedPod') - .mockImplementation(mockNamespacedPodsListFn); - jest - .spyOn(CoreV1Api.prototype, 'listCoreV1PodForAllNamespaces') - .mockImplementation(mockAllPodsListFn); - }); - - it('should request namespaced pods from the cluster_client library if namespace is specified', async () => { - const pods = await mockResolvers.Query.k8sPods(null, { configuration, namespace }); - - expect(mockNamespacedPodsListFn).toHaveBeenCalledWith(namespace); - expect(mockAllPodsListFn).not.toHaveBeenCalled(); - - expect(pods).toEqual(k8sPodsMock); - }); - it('should request all pods from the cluster_client library if namespace is not specified', async () => { - const pods = await mockResolvers.Query.k8sPods(null, { configuration, namespace: '' }); - - expect(mockAllPodsListFn).toHaveBeenCalled(); - expect(mockNamespacedPodsListFn).not.toHaveBeenCalled(); - - expect(pods).toEqual(k8sPodsMock); - }); - it('should throw an error if the API call fails', async () => { - jest - .spyOn(CoreV1Api.prototype, 'listCoreV1PodForAllNamespaces') - .mockRejectedValue(new Error('API error')); - - await expect(mockResolvers.Query.k8sPods(null, { configuration })).rejects.toThrow( - 'API error', - ); - }); - }); - describe('k8sServices', () => { - const mockServicesListFn = jest.fn().mockImplementation(() => { - return Promise.resolve({ - data: { - items: k8sServicesMock, - }, - }); - }); - - beforeEach(() => { - jest - .spyOn(CoreV1Api.prototype, 'listCoreV1ServiceForAllNamespaces') - .mockImplementation(mockServicesListFn); - }); - - it('should request services from the cluster_client library', async () => { - const services = await mockResolvers.Query.k8sServices(null, { configuration }); - - expect(mockServicesListFn).toHaveBeenCalled(); - - expect(services).toEqual(k8sServicesMock); - }); - it('should throw an error if the API call fails', async () => { - jest - .spyOn(CoreV1Api.prototype, 'listCoreV1ServiceForAllNamespaces') - .mockRejectedValue(new Error('API error')); - - await expect(mockResolvers.Query.k8sServices(null, { configuration })).rejects.toThrow( - 'API error', - ); - }); - }); - describe('k8sWorkloads', () => { - const emptyImplementation = jest.fn().mockImplementation(() => { - return Promise.resolve({ - data: { - items: [], - }, - }); - }); - - const [ - mockNamespacedDeployment, - mockNamespacedDaemonSet, - mockNamespacedStatefulSet, - mockNamespacedReplicaSet, - mockNamespacedJob, - mockNamespacedCronJob, - mockAllDeployment, - mockAllDaemonSet, - mockAllStatefulSet, - mockAllReplicaSet, - mockAllJob, - mockAllCronJob, - ] = Array(12).fill(emptyImplementation); - - const namespacedMocks = [ - { method: 'listAppsV1NamespacedDeployment', api: AppsV1Api, spy: mockNamespacedDeployment }, - { method: 'listAppsV1NamespacedDaemonSet', api: AppsV1Api, spy: mockNamespacedDaemonSet }, - { method: 'listAppsV1NamespacedStatefulSet', api: AppsV1Api, spy: mockNamespacedStatefulSet }, - { method: 'listAppsV1NamespacedReplicaSet', api: AppsV1Api, spy: mockNamespacedReplicaSet }, - { method: 'listBatchV1NamespacedJob', api: BatchV1Api, spy: mockNamespacedJob }, - { method: 'listBatchV1NamespacedCronJob', api: BatchV1Api, spy: mockNamespacedCronJob }, - ]; - - const allMocks = [ - { method: 'listAppsV1DeploymentForAllNamespaces', api: AppsV1Api, spy: mockAllDeployment }, - { method: 'listAppsV1DaemonSetForAllNamespaces', api: AppsV1Api, spy: mockAllDaemonSet }, - { method: 'listAppsV1StatefulSetForAllNamespaces', api: AppsV1Api, spy: mockAllStatefulSet }, - { method: 'listAppsV1ReplicaSetForAllNamespaces', api: AppsV1Api, spy: mockAllReplicaSet }, - { method: 'listBatchV1JobForAllNamespaces', api: BatchV1Api, spy: mockAllJob }, - { method: 'listBatchV1CronJobForAllNamespaces', api: BatchV1Api, spy: mockAllCronJob }, - ]; - - beforeEach(() => { - [...namespacedMocks, ...allMocks].forEach((workloadMock) => { - jest - .spyOn(workloadMock.api.prototype, workloadMock.method) - .mockImplementation(workloadMock.spy); - }); - }); - - it('should request namespaced workload types from the cluster_client library if namespace is specified', async () => { - await mockResolvers.Query.k8sWorkloads(null, { configuration, namespace }); - - namespacedMocks.forEach((workloadMock) => { - expect(workloadMock.spy).toHaveBeenCalledWith(namespace); - }); - }); - - it('should request all workload types from the cluster_client library if namespace is not specified', async () => { - await mockResolvers.Query.k8sWorkloads(null, { configuration, namespace: '' }); - - allMocks.forEach((workloadMock) => { - expect(workloadMock.spy).toHaveBeenCalled(); - }); - }); - it('should pass fulfilled calls data if one of the API calls fail', async () => { - jest - .spyOn(AppsV1Api.prototype, 'listAppsV1DeploymentForAllNamespaces') - .mockRejectedValue(new Error('API error')); - - await expect( - mockResolvers.Query.k8sWorkloads(null, { configuration }), - ).resolves.toBeDefined(); - }); - it('should throw an error if all the API calls fail', async () => { - [...allMocks].forEach((workloadMock) => { - jest - .spyOn(workloadMock.api.prototype, workloadMock.method) - .mockRejectedValue(new Error('API error')); - }); - - await expect(mockResolvers.Query.k8sWorkloads(null, { configuration })).rejects.toThrow( - 'API error', - ); - }); - }); - describe('k8sNamespaces', () => { - const mockNamespacesListFn = jest.fn().mockImplementation(() => { - return Promise.resolve({ - data: { - items: k8sNamespacesMock, - }, - }); - }); - - beforeEach(() => { - jest - .spyOn(CoreV1Api.prototype, 'listCoreV1Namespace') - .mockImplementation(mockNamespacesListFn); - }); - - it('should request all namespaces from the cluster_client library', async () => { - const namespaces = await mockResolvers.Query.k8sNamespaces(null, { configuration }); - - expect(mockNamespacesListFn).toHaveBeenCalled(); - - expect(namespaces).toEqual(k8sNamespacesMock); - }); - it.each([ - ['Unauthorized', CLUSTER_AGENT_ERROR_MESSAGES.unauthorized], - ['Forbidden', CLUSTER_AGENT_ERROR_MESSAGES.forbidden], - ['Not found', CLUSTER_AGENT_ERROR_MESSAGES['not found']], - ['Unknown', CLUSTER_AGENT_ERROR_MESSAGES.other], - ])( - 'should throw an error if the API call fails with the reason "%s"', - async (reason, message) => { - jest.spyOn(CoreV1Api.prototype, 'listCoreV1Namespace').mockRejectedValue({ - response: { - data: { - reason, - }, - }, - }); - - await expect(mockResolvers.Query.k8sNamespaces(null, { configuration })).rejects.toThrow( - message, - ); - }, - ); - }); - describe('stopEnvironmentREST', () => { - it('should post to the stop environment path', async () => { - mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK); - - const client = { writeQuery: jest.fn() }; - const environment = { stopPath: ENDPOINT }; - await mockResolvers.Mutation.stopEnvironmentREST(null, { environment }, { client }); - - expect(mock.history.post).toContainEqual( - expect.objectContaining({ url: ENDPOINT, method: 'post' }), - ); - - expect(client.writeQuery).toHaveBeenCalledWith({ - query: isEnvironmentStoppingQuery, - variables: { environment }, - data: { isEnvironmentStopping: true }, - }); - }); - it('should set is stopping to false if stop fails', async () => { - mock.onPost(ENDPOINT).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); - - const client = { writeQuery: jest.fn() }; - const environment = { stopPath: ENDPOINT }; - await mockResolvers.Mutation.stopEnvironmentREST(null, { environment }, { client }); - - expect(mock.history.post).toContainEqual( - expect.objectContaining({ url: ENDPOINT, method: 'post' }), - ); - - expect(client.writeQuery).toHaveBeenCalledWith({ - query: isEnvironmentStoppingQuery, - variables: { environment }, - data: { isEnvironmentStopping: false }, - }); - }); - }); - describe('rollbackEnvironment', () => { - it('should post to the retry environment path', async () => { - mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK); - - await mockResolvers.Mutation.rollbackEnvironment(null, { - environment: { retryUrl: ENDPOINT }, - }); - - expect(mock.history.post).toContainEqual( - expect.objectContaining({ url: ENDPOINT, method: 'post' }), - ); - }); - }); - describe('deleteEnvironment', () => { - it('should DELETE to the delete environment path', async () => { - mock.onDelete(ENDPOINT).reply(HTTP_STATUS_OK); - - await mockResolvers.Mutation.deleteEnvironment(null, { - environment: { deletePath: ENDPOINT }, - }); - - expect(mock.history.delete).toContainEqual( - expect.objectContaining({ url: ENDPOINT, method: 'delete' }), - ); - }); - }); - describe('cancelAutoStop', () => { - it('should post to the auto stop path', async () => { - mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK); - - await mockResolvers.Mutation.cancelAutoStop(null, { autoStopUrl: ENDPOINT }); - - expect(mock.history.post).toContainEqual( - expect.objectContaining({ url: ENDPOINT, method: 'post' }), - ); - }); - }); - describe('setEnvironmentToRollback', () => { - it('should write the given environment to the cache', () => { - localState.client.writeQuery = jest.fn(); - mockResolvers.Mutation.setEnvironmentToRollback( - null, - { environment: resolvedEnvironment }, - localState, - ); - - expect(localState.client.writeQuery).toHaveBeenCalledWith({ - query: environmentToRollback, - data: { environmentToRollback: resolvedEnvironment }, - }); - }); - }); - describe('setEnvironmentToDelete', () => { - it('should write the given environment to the cache', () => { - localState.client.writeQuery = jest.fn(); - mockResolvers.Mutation.setEnvironmentToDelete( - null, - { environment: resolvedEnvironment }, - localState, - ); - - expect(localState.client.writeQuery).toHaveBeenCalledWith({ - query: environmentToDelete, - data: { environmentToDelete: resolvedEnvironment }, - }); - }); - }); - describe('setEnvironmentToStop', () => { - it('should write the given environment to the cache', () => { - localState.client.writeQuery = jest.fn(); - mockResolvers.Mutation.setEnvironmentToStop( - null, - { environment: resolvedEnvironment }, - localState, - ); - - expect(localState.client.writeQuery).toHaveBeenCalledWith({ - query: environmentToStopQuery, - data: { environmentToStop: resolvedEnvironment }, - }); - }); - }); - describe('action', () => { - it('should POST to the given path', async () => { - mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK); - const errors = await mockResolvers.Mutation.action(null, { action: { playPath: ENDPOINT } }); - - expect(errors).toEqual({ __typename: 'LocalEnvironmentErrors', errors: [] }); - }); - it('should return a nice error message on fail', async () => { - mock.onPost(ENDPOINT).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); - const errors = await mockResolvers.Mutation.action(null, { action: { playPath: ENDPOINT } }); - - expect(errors).toEqual({ - __typename: 'LocalEnvironmentErrors', - errors: [s__('Environments|An error occurred while making the request.')], - }); - }); - }); -}); |