From 5296b88d246fa66fd9e22dd519803154ad30bbc3 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 30 Mar 2022 13:37:26 +0200 Subject: [PATCH] [Ingest Pipelines] Remove `axios` dependency in tests (#128467) * Refactor main cits * commit using @elastic.co * Finish refactoring pipeline_editor cits * Carefully access prop * Fix hardcoded props * Fix ts issues * Add back missing attr * Address CR changes (cherry picked from commit d869a7fc8106dfa40ba158c57a7f7ebfc6f34b75) # Conflicts: # x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/http_requests.ts # x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_clone.helpers.ts # x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_create.helpers.ts # x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_create_from_csv.helpers.ts # x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts # x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create_from_csv.test.tsx --- .../helpers/http_requests.ts | 103 ++++++++++-------- .../helpers/pipelines_clone.helpers.ts | 9 +- .../helpers/pipelines_create.helpers.ts | 9 +- .../helpers/pipelines_edit.helpers.ts | 6 +- .../helpers/pipelines_list.helpers.ts | 6 +- .../helpers/setup_environment.tsx | 21 ++-- .../ingest_pipelines_clone.test.tsx | 30 +++-- .../ingest_pipelines_create.test.tsx | 38 +++---- .../ingest_pipelines_edit.test.tsx | 31 +++--- .../ingest_pipelines_list.test.ts | 31 ++---- .../__jest__/http_requests.helpers.ts | 78 +++++++------ .../pipeline_processors_editor.helpers.tsx | 2 +- .../__jest__/processors/processor.helpers.tsx | 5 +- .../__jest__/test_pipeline.helpers.tsx | 27 ++--- .../__jest__/test_pipeline.test.tsx | 54 +++++---- 15 files changed, 233 insertions(+), 217 deletions(-) diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/http_requests.ts index 67adb15f7cd85..08f3240ea10a5 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/http_requests.ts @@ -5,52 +5,70 @@ * 2.0. */ -import sinon, { SinonFakeServer } from 'sinon'; - +import { httpServiceMock } from '../../../../../../src/core/public/mocks'; import { API_BASE_PATH } from '../../../common/constants'; +type HttpMethod = 'GET' | 'PUT' | 'DELETE' | 'POST'; +export interface ResponseError { + statusCode: number; + message: string | Error; + attributes?: Record; +} + // Register helpers to mock HTTP Requests -const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { - const setLoadPipelinesResponse = (response?: any[], error?: any) => { - const status = error ? error.status || 400 : 200; - const body = error ? error.body : response; +const registerHttpRequestMockHelpers = ( + httpSetup: ReturnType +) => { + const mockResponses = new Map>>( + ['GET', 'PUT', 'DELETE', 'POST'].map( + (method) => [method, new Map()] as [HttpMethod, Map>] + ) + ); - server.respondWith('GET', API_BASE_PATH, [ - status, - { 'Content-Type': 'application/json' }, - JSON.stringify(body), - ]); - }; + const mockMethodImplementation = (method: HttpMethod, path: string) => + mockResponses.get(method)?.get(path) ?? Promise.resolve({}); - const setLoadPipelineResponse = (response?: {}, error?: any) => { - const status = error ? error.status || 400 : 200; - const body = error ? error.body : response; + httpSetup.get.mockImplementation((path) => + mockMethodImplementation('GET', path as unknown as string) + ); + httpSetup.delete.mockImplementation((path) => + mockMethodImplementation('DELETE', path as unknown as string) + ); + httpSetup.post.mockImplementation((path) => + mockMethodImplementation('POST', path as unknown as string) + ); + httpSetup.put.mockImplementation((path) => + mockMethodImplementation('PUT', path as unknown as string) + ); - server.respondWith('GET', `${API_BASE_PATH}/:name`, [ - status, - { 'Content-Type': 'application/json' }, - JSON.stringify(body), - ]); - }; + const mockResponse = (method: HttpMethod, path: string, response?: unknown, error?: unknown) => { + const defuse = (promise: Promise) => { + promise.catch(() => {}); + return promise; + }; - const setDeletePipelineResponse = (response?: object) => { - server.respondWith('DELETE', `${API_BASE_PATH}/:name`, [ - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify(response), - ]); + return mockResponses + .get(method)! + .set(path, error ? defuse(Promise.reject({ body: error })) : Promise.resolve(response)); }; - const setCreatePipelineResponse = (response?: object, error?: any) => { - const status = error ? error.status || 400 : 200; - const body = error ? JSON.stringify(error.body) : JSON.stringify(response); + const setLoadPipelinesResponse = (response?: object[], error?: ResponseError) => + mockResponse('GET', API_BASE_PATH, response, error); - server.respondWith('POST', API_BASE_PATH, [ - status, - { 'Content-Type': 'application/json' }, - body, - ]); - }; + const setLoadPipelineResponse = ( + pipelineName: string, + response?: object, + error?: ResponseError + ) => mockResponse('GET', `${API_BASE_PATH}/${pipelineName}`, response, error); + + const setDeletePipelineResponse = ( + pipelineName: string, + response?: object, + error?: ResponseError + ) => mockResponse('DELETE', `${API_BASE_PATH}/${pipelineName}`, response, error); + + const setCreatePipelineResponse = (response?: object, error?: ResponseError) => + mockResponse('POST', API_BASE_PATH, response, error); return { setLoadPipelinesResponse, @@ -61,18 +79,11 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { }; export const init = () => { - const server = sinon.fakeServer.create(); - server.respondImmediately = true; - - // Define default response for unhandled requests. - // We make requests to APIs which don't impact the component under test, e.g. UI metric telemetry, - // and we can mock them all with a 200 instead of mocking each one individually. - server.respondWith([200, {}, 'DefaultMockedResponse']); - - const httpRequestsMockHelpers = registerHttpRequestMockHelpers(server); + const httpSetup = httpServiceMock.createSetupContract(); + const httpRequestsMockHelpers = registerHttpRequestMockHelpers(httpSetup); return { - server, + httpSetup, httpRequestsMockHelpers, }; }; diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_clone.helpers.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_clone.helpers.ts index 51f6d9bd96bd6..079124ed612b6 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_clone.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_clone.helpers.ts @@ -6,6 +6,7 @@ */ import { registerTestBed, AsyncTestBedConfig, TestBed } from '@kbn/test/jest'; +import { HttpSetup } from 'src/core/public'; import { PipelinesClone } from '../../../public/application/sections/pipelines_clone'; import { getFormActions, PipelineFormTestSubjects } from './pipeline_form.helpers'; import { WithAppDependencies } from './setup_environment'; @@ -36,9 +37,11 @@ const testBedConfig: AsyncTestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(WithAppDependencies(PipelinesClone), testBedConfig); - -export const setup = async (): Promise => { +export const setup = async (httpSetup: HttpSetup): Promise => { + const initTestBed = registerTestBed( + WithAppDependencies(PipelinesClone, httpSetup), + testBedConfig + ); const testBed = await initTestBed(); return { diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_create.helpers.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_create.helpers.ts index faf1b42042ec1..22cd589ec1800 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_create.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_create.helpers.ts @@ -6,6 +6,7 @@ */ import { registerTestBed, AsyncTestBedConfig, TestBed } from '@kbn/test/jest'; +import { HttpSetup } from 'src/core/public'; import { PipelinesCreate } from '../../../public/application/sections/pipelines_create'; import { getFormActions, PipelineFormTestSubjects } from './pipeline_form.helpers'; import { WithAppDependencies } from './setup_environment'; @@ -23,9 +24,11 @@ const testBedConfig: AsyncTestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(WithAppDependencies(PipelinesCreate), testBedConfig); - -export const setup = async (): Promise => { +export const setup = async (httpSetup: HttpSetup): Promise => { + const initTestBed = registerTestBed( + WithAppDependencies(PipelinesCreate, httpSetup), + testBedConfig + ); const testBed = await initTestBed(); return { diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts index 9a3c41196653f..ab64656a4cfb2 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_edit.helpers.ts @@ -6,6 +6,7 @@ */ import { registerTestBed, AsyncTestBedConfig, TestBed } from '@kbn/test/jest'; +import { HttpSetup } from 'src/core/public'; import { PipelinesEdit } from '../../../public/application/sections/pipelines_edit'; import { getFormActions, PipelineFormTestSubjects } from './pipeline_form.helpers'; import { WithAppDependencies } from './setup_environment'; @@ -36,9 +37,8 @@ const testBedConfig: AsyncTestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(WithAppDependencies(PipelinesEdit), testBedConfig); - -export const setup = async (): Promise => { +export const setup = async (httpSetup: HttpSetup): Promise => { + const initTestBed = registerTestBed(WithAppDependencies(PipelinesEdit, httpSetup), testBedConfig); const testBed = await initTestBed(); return { diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_list.helpers.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_list.helpers.ts index 3cd768104203a..2acead6f6a51e 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_list.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipelines_list.helpers.ts @@ -6,6 +6,7 @@ */ import { act } from 'react-dom/test-utils'; +import { HttpSetup } from 'src/core/public'; import { registerTestBed, TestBed, AsyncTestBedConfig, findTestSubject } from '@kbn/test/jest'; import { PipelinesList } from '../../../public/application/sections/pipelines_list'; @@ -20,8 +21,6 @@ const testBedConfig: AsyncTestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(WithAppDependencies(PipelinesList), testBedConfig); - export type PipelineListTestBed = TestBed & { actions: ReturnType; }; @@ -84,7 +83,8 @@ const createActions = (testBed: TestBed) => { }; }; -export const setup = async (): Promise => { +export const setup = async (httpSetup: HttpSetup): Promise => { + const initTestBed = registerTestBed(WithAppDependencies(PipelinesList, httpSetup), testBedConfig); const testBed = await initTestBed(); return { diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx index 7ba5e44cddf61..fc9cf3f458c95 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/setup_environment.tsx @@ -6,8 +6,6 @@ */ import React from 'react'; -import axios from 'axios'; -import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { LocationDescriptorObject } from 'history'; import { HttpSetup } from 'kibana/public'; @@ -29,8 +27,6 @@ import { import { init as initHttpRequests } from './http_requests'; -const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); - const history = scopedHistoryMock.create(); history.createHref.mockImplementation((location: LocationDescriptorObject) => { return `${location.pathname}?${location.search}`; @@ -51,22 +47,19 @@ const appServices = { }; export const setupEnvironment = () => { - uiMetricService.setup(usageCollectionPluginMock.createSetupContract()); - apiService.setup(mockHttpClient as unknown as HttpSetup, uiMetricService); documentationService.setup(docLinksServiceMock.createStartContract()); breadcrumbService.setup(() => {}); - const { server, httpRequestsMockHelpers } = initHttpRequests(); - - return { - server, - httpRequestsMockHelpers, - }; + return initHttpRequests(); }; -export const WithAppDependencies = (Comp: any) => (props: any) => - ( +export const WithAppDependencies = (Comp: any, httpSetup: HttpSetup) => (props: any) => { + uiMetricService.setup(usageCollectionPluginMock.createSetupContract()); + apiService.setup(httpSetup, uiMetricService); + + return ( ); +}; diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_clone.test.tsx b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_clone.test.tsx index 556cea9eb5f80..8d7ed011b60cd 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_clone.test.tsx +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_clone.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers } from './helpers'; +import { API_BASE_PATH } from '../../common/constants'; import { PIPELINE_TO_CLONE, PipelinesCloneTestBed } from './helpers/pipelines_clone.helpers'; const { setup } = pageHelpers.pipelinesClone; @@ -33,17 +34,13 @@ jest.mock('@elastic/eui', () => { describe('', () => { let testBed: PipelinesCloneTestBed; - const { server, httpRequestsMockHelpers } = setupEnvironment(); - - afterAll(() => { - server.restore(); - }); - - httpRequestsMockHelpers.setLoadPipelineResponse(PIPELINE_TO_CLONE); + const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); beforeEach(async () => { + httpRequestsMockHelpers.setLoadPipelineResponse(PIPELINE_TO_CLONE.name, PIPELINE_TO_CLONE); + await act(async () => { - testBed = await setup(); + testBed = await setup(httpSetup); }); testBed.component.update(); @@ -67,14 +64,15 @@ describe('', () => { await actions.clickSubmitButton(); - const latestRequest = server.requests[server.requests.length - 1]; - - const expected = { - ...PIPELINE_TO_CLONE, - name: `${PIPELINE_TO_CLONE.name}-copy`, - }; - - expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual(expected); + expect(httpSetup.post).toHaveBeenLastCalledWith( + API_BASE_PATH, + expect.objectContaining({ + body: JSON.stringify({ + ...PIPELINE_TO_CLONE, + name: `${PIPELINE_TO_CLONE.name}-copy`, + }), + }) + ); }); }); }); diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx index bb1d3f2503f9b..c73a703bf0385 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers } from './helpers'; +import { API_BASE_PATH } from '../../common/constants'; import { PipelinesCreateTestBed } from './helpers/pipelines_create.helpers'; import { nestedProcessorsErrorFixture } from './fixtures'; @@ -35,16 +36,12 @@ jest.mock('@elastic/eui', () => { describe('', () => { let testBed: PipelinesCreateTestBed; - const { server, httpRequestsMockHelpers } = setupEnvironment(); - - afterAll(() => { - server.restore(); - }); + const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); describe('on component mount', () => { beforeEach(async () => { await act(async () => { - testBed = await setup(); + testBed = await setup(httpSetup); }); testBed.component.update(); @@ -106,7 +103,7 @@ describe('', () => { describe('form submission', () => { beforeEach(async () => { await act(async () => { - testBed = await setup(); + testBed = await setup(httpSetup); }); testBed.component.update(); @@ -129,27 +126,28 @@ describe('', () => { await actions.clickSubmitButton(); - const latestRequest = server.requests[server.requests.length - 1]; - - const expected = { - name: 'my_pipeline', - description: 'pipeline description', - processors: [], - }; - - expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual(expected); + expect(httpSetup.post).toHaveBeenLastCalledWith( + API_BASE_PATH, + expect.objectContaining({ + body: JSON.stringify({ + name: 'my_pipeline', + description: 'pipeline description', + processors: [], + }), + }) + ); }); test('should surface API errors from the request', async () => { const { actions, find, exists } = testBed; const error = { - status: 409, + statusCode: 409, error: 'Conflict', message: `There is already a pipeline with name 'my_pipeline'.`, }; - httpRequestsMockHelpers.setCreatePipelineResponse(undefined, { body: error }); + httpRequestsMockHelpers.setCreatePipelineResponse(undefined, error); await actions.clickSubmitButton(); @@ -160,7 +158,9 @@ describe('', () => { test('displays nested pipeline errors as a flat list', async () => { const { actions, find, exists, component } = testBed; httpRequestsMockHelpers.setCreatePipelineResponse(undefined, { - body: nestedProcessorsErrorFixture, + statusCode: 409, + message: 'Error', + ...nestedProcessorsErrorFixture, }); await actions.clickSubmitButton(); diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx index 8b44727b4a985..04ea1e5928a19 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_edit.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers } from './helpers'; +import { API_BASE_PATH } from '../../common/constants'; import { PIPELINE_TO_EDIT, PipelinesEditTestBed } from './helpers/pipelines_edit.helpers'; const { setup } = pageHelpers.pipelinesEdit; @@ -33,17 +34,13 @@ jest.mock('@elastic/eui', () => { describe('', () => { let testBed: PipelinesEditTestBed; - const { server, httpRequestsMockHelpers } = setupEnvironment(); - - afterAll(() => { - server.restore(); - }); - - httpRequestsMockHelpers.setLoadPipelineResponse(PIPELINE_TO_EDIT); + const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); beforeEach(async () => { + httpRequestsMockHelpers.setLoadPipelineResponse(PIPELINE_TO_EDIT.name, PIPELINE_TO_EDIT); + await act(async () => { - testBed = await setup(); + testBed = await setup(httpSetup); }); testBed.component.update(); @@ -78,16 +75,16 @@ describe('', () => { await actions.clickSubmitButton(); - const latestRequest = server.requests[server.requests.length - 1]; - const { name, ...pipelineDefinition } = PIPELINE_TO_EDIT; - - const expected = { - ...pipelineDefinition, - description: UPDATED_DESCRIPTION, - }; - - expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual(expected); + expect(httpSetup.put).toHaveBeenLastCalledWith( + `${API_BASE_PATH}/${name}`, + expect.objectContaining({ + body: JSON.stringify({ + ...pipelineDefinition, + description: UPDATED_DESCRIPTION, + }), + }) + ); }); }); }); diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts index 19a2abb5a5a52..97c6142811760 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_list.test.ts @@ -15,17 +15,13 @@ import { PipelineListTestBed } from './helpers/pipelines_list.helpers'; const { setup } = pageHelpers.pipelinesList; describe('', () => { - const { server, httpRequestsMockHelpers } = setupEnvironment(); + const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); let testBed: PipelineListTestBed; - afterAll(() => { - server.restore(); - }); - describe('With pipelines', () => { beforeEach(async () => { await act(async () => { - testBed = await setup(); + testBed = await setup(httpSetup); }); testBed.component.update(); @@ -72,12 +68,10 @@ describe('', () => { test('should reload the pipeline data', async () => { const { actions } = testBed; - const totalRequests = server.requests.length; await actions.clickReloadButton(); - expect(server.requests.length).toBe(totalRequests + 1); - expect(server.requests[server.requests.length - 1].url).toBe(API_BASE_PATH); + expect(httpSetup.get).toHaveBeenLastCalledWith(API_BASE_PATH, expect.anything()); }); test('should show the details of a pipeline', async () => { @@ -94,7 +88,7 @@ describe('', () => { const { actions, component } = testBed; const { name: pipelineName } = pipeline1; - httpRequestsMockHelpers.setDeletePipelineResponse({ + httpRequestsMockHelpers.setDeletePipelineResponse(pipelineName, { itemsDeleted: [pipelineName], errors: [], }); @@ -117,11 +111,10 @@ describe('', () => { component.update(); - const deleteRequest = server.requests[server.requests.length - 2]; - - expect(deleteRequest.method).toBe('DELETE'); - expect(deleteRequest.url).toBe(`${API_BASE_PATH}/${pipelineName}`); - expect(deleteRequest.status).toEqual(200); + expect(httpSetup.delete).toHaveBeenLastCalledWith( + `${API_BASE_PATH}/${pipelineName}`, + expect.anything() + ); }); }); @@ -130,7 +123,7 @@ describe('', () => { httpRequestsMockHelpers.setLoadPipelinesResponse([]); await act(async () => { - testBed = await setup(); + testBed = await setup(httpSetup); }); const { exists, component, find } = testBed; component.update(); @@ -144,15 +137,15 @@ describe('', () => { describe('Error handling', () => { beforeEach(async () => { const error = { - status: 500, + statusCode: 500, error: 'Internal server error', message: 'Internal server error', }; - httpRequestsMockHelpers.setLoadPipelinesResponse(undefined, { body: error }); + httpRequestsMockHelpers.setLoadPipelinesResponse(undefined, error); await act(async () => { - testBed = await setup(); + testBed = await setup(httpSetup); }); testBed.component.update(); diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/http_requests.helpers.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/http_requests.helpers.ts index 4bea242fb8656..516e104b37b3f 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/http_requests.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/http_requests.helpers.ts @@ -5,34 +5,58 @@ * 2.0. */ -import sinon, { SinonFakeServer } from 'sinon'; +import { httpServiceMock } from '../../../../../../../../src/core/public/mocks'; +import { API_BASE_PATH } from '../../../../../common/constants'; type HttpResponse = Record | any[]; +type HttpMethod = 'GET' | 'POST'; +export interface ResponseError { + statusCode: number; + message: string | Error; + attributes?: Record; +} // Register helpers to mock HTTP Requests -const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { - const setSimulatePipelineResponse = (response?: HttpResponse, error?: any) => { - const status = error ? error.status || 400 : 200; - const body = error ? JSON.stringify(error.body) : JSON.stringify(response); - - server.respondWith('POST', '/api/ingest_pipelines/simulate', [ - status, - { 'Content-Type': 'application/json' }, - body, - ]); - }; +const registerHttpRequestMockHelpers = ( + httpSetup: ReturnType +) => { + const mockResponses = new Map>>( + ['GET', 'POST'].map( + (method) => [method, new Map()] as [HttpMethod, Map>] + ) + ); + + const mockMethodImplementation = (method: HttpMethod, path: string) => + mockResponses.get(method)?.get(path) ?? Promise.resolve({}); - const setFetchDocumentsResponse = (response?: HttpResponse, error?: any) => { - const status = error ? error.status || 400 : 200; - const body = error ? JSON.stringify(error.body) : JSON.stringify(response); + httpSetup.get.mockImplementation((path) => + mockMethodImplementation('GET', path as unknown as string) + ); + httpSetup.post.mockImplementation((path) => + mockMethodImplementation('POST', path as unknown as string) + ); - server.respondWith('GET', '/api/ingest_pipelines/documents/:index/:id', [ - status, - { 'Content-Type': 'application/json' }, - body, - ]); + const mockResponse = (method: HttpMethod, path: string, response?: unknown, error?: unknown) => { + const defuse = (promise: Promise) => { + promise.catch(() => {}); + return promise; + }; + + return mockResponses + .get(method)! + .set(path, error ? defuse(Promise.reject({ body: error })) : Promise.resolve(response)); }; + const setSimulatePipelineResponse = (response?: HttpResponse, error?: ResponseError) => + mockResponse('POST', `${API_BASE_PATH}/simulate`, response, error); + + const setFetchDocumentsResponse = ( + index: string, + documentId: string, + response?: HttpResponse, + error?: ResponseError + ) => mockResponse('GET', `${API_BASE_PATH}/documents/${index}/${documentId}`, response, error); + return { setSimulatePipelineResponse, setFetchDocumentsResponse, @@ -40,19 +64,11 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { }; export const initHttpRequests = () => { - const server = sinon.fakeServer.create(); - - server.respondImmediately = true; - - // Define default response for unhandled requests. - // We make requests to APIs which don't impact the component under test, e.g. UI metric telemetry, - // and we can mock them all with a 200 instead of mocking each one individually. - server.respondWith([200, {}, 'DefaultSinonMockServerResponse']); - - const httpRequestsMockHelpers = registerHttpRequestMockHelpers(server); + const httpSetup = httpServiceMock.createSetupContract(); + const httpRequestsMockHelpers = registerHttpRequestMockHelpers(httpSetup); return { - server, + httpSetup, httpRequestsMockHelpers, }; }; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/pipeline_processors_editor.helpers.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/pipeline_processors_editor.helpers.tsx index 79ffd28c9e788..dec8c86256348 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/pipeline_processors_editor.helpers.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/pipeline_processors_editor.helpers.tsx @@ -178,7 +178,7 @@ const createActions = (testBed: TestBed) => { }; export const setup = async (props: Props): Promise => { - const testBed = await testBedSetup(props); + const testBed = testBedSetup(props); return { ...testBed, actions: createActions(testBed), diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx index 65d9b8f306058..56b58a7a182d0 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx @@ -104,7 +104,7 @@ const createActions = (testBed: TestBed) => { }; export const setup = async (props: Props): Promise => { - const testBed = await testBedSetup(props); + const testBed = testBedSetup(props); return { ...testBed, actions: createActions(testBed), @@ -119,10 +119,9 @@ export const setupEnvironment = () => { // @ts-ignore apiService.setup(mockHttpClient, uiMetricService); - const { server, httpRequestsMockHelpers } = initHttpRequests(); + const { httpRequestsMockHelpers } = initHttpRequests(); return { - server, httpRequestsMockHelpers, }; }; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.helpers.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.helpers.tsx index 263a40a605d2d..19f0cde5898f0 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.helpers.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.helpers.tsx @@ -7,11 +7,10 @@ import { act } from 'react-dom/test-utils'; import React from 'react'; -import axios from 'axios'; -import axiosXhrAdapter from 'axios/lib/adapters/xhr'; /* eslint-disable-next-line @kbn/eslint/no-restricted-paths */ import { usageCollectionPluginMock } from 'src/plugins/usage_collection/public/mocks'; +import { HttpSetup } from 'src/core/public'; import { registerTestBed, TestBed } from '@kbn/test/jest'; import { stubWebWorker } from '@kbn/test/jest'; @@ -62,6 +61,7 @@ const testBedSetup = registerTestBed( ); export interface SetupResult extends TestBed { + httpSetup: HttpSetup; actions: ReturnType; } @@ -189,30 +189,23 @@ const createActions = (testBed: TestBed) => { }; }; -export const setup = async (props: Props): Promise => { - const testBed = await testBedSetup(props); - return { - ...testBed, - actions: createActions(testBed), - }; -}; - -const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); - -export const setupEnvironment = () => { +export const setup = async (httpSetup: HttpSetup, props: Props): Promise => { // Initialize mock services uiMetricService.setup(usageCollectionPluginMock.createSetupContract()); // @ts-ignore - apiService.setup(mockHttpClient, uiMetricService); + apiService.setup(httpSetup, uiMetricService); - const { server, httpRequestsMockHelpers } = initHttpRequests(); + const testBed = testBedSetup(props); return { - server, - httpRequestsMockHelpers, + ...testBed, + httpSetup, + actions: createActions(testBed), }; }; +export const setupEnvironment = initHttpRequests; + type TestSubject = | 'addDocumentsButton' | 'testPipelineFlyout' diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.test.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.test.tsx index 607978512e203..6feb3464fae91 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.test.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/test_pipeline.test.tsx @@ -6,6 +6,7 @@ */ import { Pipeline } from '../../../../../common/types'; +import { API_BASE_PATH } from '../../../../../common/constants'; import { VerboseTestOutput, Document } from '../types'; import { setup, SetupResult, setupEnvironment } from './test_pipeline.helpers'; @@ -21,7 +22,7 @@ describe('Test pipeline', () => { let onUpdate: jest.Mock; let testBed: SetupResult; - const { server, httpRequestsMockHelpers } = setupEnvironment(); + const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); // This is a hack // We need to provide the processor id in the mocked output; @@ -49,13 +50,12 @@ describe('Test pipeline', () => { }); afterAll(() => { - server.restore(); jest.useRealTimers(); }); beforeEach(async () => { onUpdate = jest.fn(); - testBed = await setup({ + testBed = await setup(httpSetup, { value: { ...PROCESSORS, }, @@ -87,8 +87,9 @@ describe('Test pipeline', () => { await actions.clickRunPipelineButton(); // Verify request - const latestRequest = server.requests[server.requests.length - 1]; - const requestBody: ReqBody = JSON.parse(JSON.parse(latestRequest.requestBody).body); + const latestRequest: any = httpSetup.post.mock.calls.pop() || []; + const requestBody: ReqBody = JSON.parse(latestRequest[1]?.body); + const { documents: reqDocuments, verbose: reqVerbose, @@ -114,23 +115,26 @@ describe('Test pipeline', () => { expect(exists('outputTabContent')).toBe(true); // Click reload button and verify request - const totalRequests = server.requests.length; await actions.clickRefreshOutputButton(); // There will be two requests made to the simulate API // the second request will have verbose enabled to update the processor results - expect(server.requests.length).toBe(totalRequests + 2); - expect(server.requests[server.requests.length - 2].url).toBe( - '/api/ingest_pipelines/simulate' + expect(httpSetup.post).toHaveBeenNthCalledWith( + 1, + `${API_BASE_PATH}/simulate`, + expect.anything() ); - expect(server.requests[server.requests.length - 1].url).toBe( - '/api/ingest_pipelines/simulate' + expect(httpSetup.post).toHaveBeenNthCalledWith( + 2, + `${API_BASE_PATH}/simulate`, + expect.anything() ); // Click verbose toggle and verify request await actions.toggleVerboseSwitch(); - expect(server.requests.length).toBe(totalRequests + 3); - expect(server.requests[server.requests.length - 1].url).toBe( - '/api/ingest_pipelines/simulate' + // There will be one request made to the simulate API + expect(httpSetup.post).toHaveBeenLastCalledWith( + `${API_BASE_PATH}/simulate`, + expect.anything() ); }); @@ -163,12 +167,12 @@ describe('Test pipeline', () => { const { actions, find, exists } = testBed; const error = { - status: 500, + statusCode: 500, error: 'Internal server error', message: 'Internal server error', }; - httpRequestsMockHelpers.setSimulatePipelineResponse(undefined, { body: error }); + httpRequestsMockHelpers.setSimulatePipelineResponse(undefined, error); // Open flyout actions.clickAddDocumentsButton(); @@ -201,7 +205,7 @@ describe('Test pipeline', () => { const { _index: index, _id: documentId } = DOCUMENTS[0]; - httpRequestsMockHelpers.setFetchDocumentsResponse(DOCUMENTS[0]); + httpRequestsMockHelpers.setFetchDocumentsResponse(index, documentId, DOCUMENTS[0]); // Open flyout actions.clickAddDocumentsButton(); @@ -220,9 +224,10 @@ describe('Test pipeline', () => { await actions.clickAddDocumentButton(); // Verify request - const latestRequest = server.requests[server.requests.length - 1]; - expect(latestRequest.status).toEqual(200); - expect(latestRequest.url).toEqual(`/api/ingest_pipelines/documents/${index}/${documentId}`); + expect(httpSetup.get).toHaveBeenLastCalledWith( + `${API_BASE_PATH}/documents/${index}/${documentId}`, + expect.anything() + ); // Verify success callout expect(exists('addDocumentSuccess')).toBe(true); }); @@ -236,12 +241,17 @@ describe('Test pipeline', () => { }; const error = { - status: 404, + statusCode: 404, error: 'Not found', message: '[index_not_found_exception] no such index', }; - httpRequestsMockHelpers.setFetchDocumentsResponse(undefined, { body: error }); + httpRequestsMockHelpers.setFetchDocumentsResponse( + nonExistentDoc.index, + nonExistentDoc.id, + undefined, + error + ); // Open flyout actions.clickAddDocumentsButton();