vitess.io/vitess@v0.16.2/web/vtadmin/src/errors/errorHandler.test.ts (about) 1 /** 2 * Copyright 2021 The Vitess Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import { ErrorHandler, HttpResponseNotOkError } from './errorTypes'; 18 import * as errorHandler from './errorHandler'; 19 import * as errorHandlers from './errorHandlers'; 20 21 // Since vtadmin uses process.env variables quite a bit, we need to 22 // do a bit of a dance to clear them out between test runs. 23 const ORIGINAL_PROCESS_ENV = process.env; 24 const TEST_PROCESS_ENV = { 25 ...process.env, 26 REACT_APP_VTADMIN_API_ADDRESS: '', 27 }; 28 29 beforeAll(() => { 30 // TypeScript can get a little cranky with the automatic 31 // string/boolean type conversions, hence this cast. 32 process.env = { ...TEST_PROCESS_ENV } as NodeJS.ProcessEnv; 33 }); 34 35 afterEach(() => { 36 // Reset the process.env to clear out any changes made in the tests. 37 process.env = { ...TEST_PROCESS_ENV } as NodeJS.ProcessEnv; 38 39 jest.restoreAllMocks(); 40 }); 41 42 afterAll(() => { 43 process.env = { ...ORIGINAL_PROCESS_ENV }; 44 }); 45 46 describe('errorHandler', () => { 47 let mockErrorHandler: ErrorHandler; 48 let mockEnv: NodeJS.ProcessEnv; 49 50 beforeEach(() => { 51 mockErrorHandler = { 52 initialize: jest.fn(), 53 isEnabled: () => true, 54 notify: jest.fn(), 55 }; 56 57 jest.spyOn(errorHandlers, 'getHandlers').mockReturnValue([mockErrorHandler]); 58 59 mockEnv = { 60 REACT_APP_VTADMIN_API_ADDRESS: 'http://example.com', 61 } as NodeJS.ProcessEnv; 62 process.env = mockEnv; 63 }); 64 65 describe('initialize', () => { 66 it('initializes enabled handlers', () => { 67 errorHandler.initialize(); 68 expect(mockErrorHandler.initialize).toHaveBeenCalledTimes(1); 69 }); 70 }); 71 72 describe('notify', () => { 73 it('notifies enabled ErrorHandlers', () => { 74 const err = new Error('testing'); 75 errorHandler.notify(err); 76 77 expect(mockErrorHandler.notify).toHaveBeenCalledTimes(1); 78 expect(mockErrorHandler.notify).toHaveBeenCalledWith(err, mockEnv, { 79 errorMetadata: {}, 80 }); 81 }); 82 83 it("appends metadata from the Error's instance properties", () => { 84 const response = new Response('', { status: 500 }); 85 const err = new HttpResponseNotOkError('/api/test', { ok: false }, response); 86 errorHandler.notify(err, { goodbye: 'moon' }); 87 88 expect(mockErrorHandler.notify).toHaveBeenCalledTimes(1); 89 expect(mockErrorHandler.notify).toHaveBeenCalledWith(err, mockEnv, { 90 errorMetadata: { 91 fetchResponse: { 92 ok: false, 93 status: 500, 94 statusText: '', 95 type: 'default', 96 url: '', 97 }, 98 name: 'HttpResponseNotOkError', 99 response: { ok: false }, 100 }, 101 goodbye: 'moon', 102 }); 103 }); 104 105 it('only includes santizied environment variables', () => { 106 process.env = { 107 REACT_APP_VTADMIN_API_ADDRESS: 'http://not-secret.example.com', 108 REACT_APP_BUGSNAG_API_KEY: 'secret', 109 } as NodeJS.ProcessEnv; 110 111 const err = new Error('testing'); 112 errorHandler.notify(err); 113 114 expect(mockErrorHandler.notify).toHaveBeenCalledTimes(1); 115 expect(mockErrorHandler.notify).toHaveBeenCalledWith( 116 err, 117 { 118 REACT_APP_VTADMIN_API_ADDRESS: 'http://not-secret.example.com', 119 }, 120 { 121 errorMetadata: {}, 122 } 123 ); 124 }); 125 }); 126 });