diff options
Diffstat (limited to 'spec/frontend/environments/graphql/resolvers_spec.js')
-rw-r--r-- | spec/frontend/environments/graphql/resolvers_spec.js | 182 |
1 files changed, 179 insertions, 3 deletions
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js index 2c223d3a1a7..edffc00e185 100644 --- a/spec/frontend/environments/graphql/resolvers_spec.js +++ b/spec/frontend/environments/graphql/resolvers_spec.js @@ -1,4 +1,5 @@ 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'; @@ -17,6 +18,8 @@ import { resolvedEnvironment, folder, resolvedFolder, + k8sPodsMock, + k8sServicesMock, } from './mock_data'; const ENDPOINT = `${TEST_HOST}/environments`; @@ -27,6 +30,14 @@ describe('~/frontend/environments/graphql/resolvers', () => { 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); @@ -143,13 +154,178 @@ describe('~/frontend/environments/graphql/resolvers', () => { expect(environmentFolder).toEqual(resolvedFolder); }); }); - describe('stopEnvironment', () => { + 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('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.stopEnvironment(null, { environment }, { client }); + await mockResolvers.Mutation.stopEnvironmentREST(null, { environment }, { client }); expect(mock.history.post).toContainEqual( expect.objectContaining({ url: ENDPOINT, method: 'post' }), @@ -166,7 +342,7 @@ describe('~/frontend/environments/graphql/resolvers', () => { const client = { writeQuery: jest.fn() }; const environment = { stopPath: ENDPOINT }; - await mockResolvers.Mutation.stopEnvironment(null, { environment }, { client }); + await mockResolvers.Mutation.stopEnvironmentREST(null, { environment }, { client }); expect(mock.history.post).toContainEqual( expect.objectContaining({ url: ENDPOINT, method: 'post' }), |