-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Synthetics] Increase unit test coverage (#193201)
## Summary I frequently find when I go to modify code in Synthetics there is a lack of good module-level coverage, which makes it challenging to confidently change things directly, or tangential to untested code. This commonly results in unintended regressions, or very high levels of manual investigation during code review. One way to get past this is to first introduce tests before modifying the code in question, but that requires a lot of burden on the developer trying to make the change. We should instead find time to add additional module-level testing where possible, and that is the spirit of this PR.
- Loading branch information
1 parent
5bb42e5
commit a178d52
Showing
2 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
166 changes: 166 additions & 0 deletions
166
x-pack/plugins/observability_solution/synthetics/server/common/pings/query_pings.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { queryPings } from './query_pings'; | ||
import { SyntheticsEsClient } from '../../lib'; | ||
|
||
jest.mock('../../lib'); // Mock the ES client module | ||
|
||
const mockEsClient: Partial<SyntheticsEsClient> = { | ||
search: jest.fn(), | ||
}; | ||
|
||
describe('queryPings', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); // Reset mocks before each test | ||
}); | ||
|
||
it.each([10, undefined])( | ||
'should return the correct result when fields are provided', | ||
async (sizeParam) => { | ||
const params = { | ||
syntheticsEsClient: mockEsClient as SyntheticsEsClient, | ||
dateRange: { from: '2023-01-01', to: '2023-01-02' }, | ||
index: 0, | ||
monitorId: 'test-monitor', | ||
status: 'up', | ||
sort: 'desc', | ||
size: sizeParam, | ||
pageIndex: 0, | ||
fields: [{ field: 'monitor.id' }], | ||
fieldsExtractorFn: (doc: any) => ({ fieldData: doc._source }), | ||
}; | ||
|
||
const mockResponse = { | ||
body: { | ||
hits: { | ||
hits: [{ _source: { 'monitor.id': 'test-monitor' } }], | ||
total: { value: 1 }, | ||
}, | ||
}, | ||
}; | ||
|
||
(mockEsClient.search as jest.Mock).mockResolvedValueOnce(mockResponse); | ||
|
||
const result = await queryPings(params); | ||
expect(result).toEqual({ | ||
total: 1, | ||
pings: [{ fieldData: { 'monitor.id': 'test-monitor' } }], | ||
}); | ||
|
||
expect(mockEsClient.search).toHaveBeenCalledTimes(1); | ||
const searchParams = (mockEsClient.search as jest.Mock).mock.calls[0][0]; | ||
expect(searchParams.body.size).toEqual(sizeParam ?? 25); | ||
} | ||
); | ||
|
||
it('should return the correct result when no fields are provided', async () => { | ||
const params = { | ||
syntheticsEsClient: mockEsClient as SyntheticsEsClient, | ||
dateRange: { from: '2023-01-01', to: '2023-01-02' }, | ||
index: 0, | ||
monitorId: 'test-monitor', | ||
status: 'up', | ||
sort: 'desc', | ||
size: 10, | ||
pageIndex: 0, | ||
}; | ||
|
||
const mockResponse = { | ||
body: { | ||
hits: { | ||
hits: [{ _source: { '@timestamp': '2023-01-01T00:00:00Z' }, _id: 'doc1' }], | ||
total: { value: 1 }, | ||
}, | ||
}, | ||
}; | ||
|
||
(mockEsClient.search as jest.Mock).mockResolvedValueOnce(mockResponse); | ||
|
||
const result = await queryPings(params); | ||
expect(result).toEqual({ | ||
total: 1, | ||
pings: [ | ||
{ '@timestamp': '2023-01-01T00:00:00Z', docId: 'doc1', timestamp: '2023-01-01T00:00:00Z' }, | ||
], | ||
}); | ||
|
||
expect(mockEsClient.search).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should handle excluded locations in the query', async () => { | ||
const params = { | ||
syntheticsEsClient: mockEsClient as SyntheticsEsClient, | ||
dateRange: { from: '2023-01-01', to: '2023-01-02' }, | ||
excludedLocations: JSON.stringify(['excluded-location']), | ||
size: 10, | ||
pageIndex: 0, | ||
}; | ||
|
||
const mockResponse = { | ||
body: { | ||
hits: { | ||
hits: [], | ||
total: { value: 0 }, | ||
}, | ||
}, | ||
}; | ||
|
||
(mockEsClient.search as jest.Mock).mockResolvedValueOnce(mockResponse); | ||
|
||
const result = await queryPings(params); | ||
|
||
expect(result).toEqual({ | ||
total: 0, | ||
pings: [], | ||
}); | ||
|
||
expect(mockEsClient.search).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should return an empty result when Elasticsearch returns no hits', async () => { | ||
const params = { | ||
syntheticsEsClient: mockEsClient as SyntheticsEsClient, | ||
dateRange: { from: '2023-01-01', to: '2023-01-02' }, | ||
size: 10, | ||
pageIndex: 0, | ||
}; | ||
|
||
const mockResponse = { | ||
body: { | ||
hits: { | ||
hits: [], | ||
total: { value: 0 }, | ||
}, | ||
}, | ||
}; | ||
|
||
(mockEsClient.search as jest.Mock).mockResolvedValueOnce(mockResponse); | ||
|
||
const result = await queryPings(params); | ||
expect(result).toEqual({ | ||
total: 0, | ||
pings: [], | ||
}); | ||
|
||
expect(mockEsClient.search).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should throw an error if query fails to execute', async () => { | ||
const params = { | ||
syntheticsEsClient: mockEsClient as SyntheticsEsClient, | ||
dateRange: { from: '2023-01-01', to: '2023-01-02' }, | ||
size: 10, | ||
pageIndex: 0, | ||
}; | ||
|
||
(mockEsClient.search as jest.Mock).mockRejectedValueOnce(new Error('Query failed')); | ||
|
||
await expect(queryPings(params)).rejects.toThrow('Query failed'); | ||
expect(mockEsClient.search).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
95 changes: 95 additions & 0 deletions
95
...ck/plugins/observability_solution/synthetics/server/routes/certs/get_certificates.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import * as getAllMonitors from '../../saved_objects/synthetics_monitor/get_all_monitors'; | ||
import * as getCerts from '../../queries/get_certs'; | ||
import { getSyntheticsCertsRoute } from './get_certificates'; | ||
|
||
describe('getSyntheticsCertsRoute', () => { | ||
let getMonitorsSpy: jest.SpyInstance; | ||
|
||
beforeEach(() => { | ||
getMonitorsSpy = jest.spyOn(getAllMonitors, 'getAllMonitors').mockReturnValue([] as any); | ||
}); | ||
|
||
afterEach(() => jest.clearAllMocks()); | ||
|
||
it('returns empty set when no monitors are found', async () => { | ||
const route = getSyntheticsCertsRoute(); | ||
expect( | ||
await route.handler({ | ||
// @ts-expect-error partial implementation for testing | ||
request: { query: {} }, | ||
// @ts-expect-error partial implementation for testing | ||
syntheticsEsClient: jest.fn(), | ||
savedObjectClient: jest.fn(), | ||
}) | ||
).toEqual({ | ||
data: { | ||
certs: [], | ||
total: 0, | ||
}, | ||
}); | ||
expect(getMonitorsSpy).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('returns cert data when monitors are found', async () => { | ||
const getMonitorsResult = [ | ||
{ | ||
id: 'test-id', | ||
monitor: { | ||
type: 'browser', | ||
name: 'test-monitor', | ||
enabled: true, | ||
schedule: { | ||
interval: 1, | ||
timezone: 'UTC', | ||
}, | ||
}, | ||
}, | ||
] as any; | ||
const processMonitorsSpy = jest.spyOn(getAllMonitors, 'processMonitors').mockReturnValue({ | ||
// @ts-expect-error partial implementation for testing | ||
enableMonitorQueryIds: ['test-id'], | ||
}); | ||
const getCertsResult = { | ||
total: 1, | ||
certs: [ | ||
{ | ||
monitors: [ | ||
{ | ||
name: 'test-monitor', | ||
id: 'test-id', | ||
configId: 'test-id', | ||
url: 'https://elastic.co', | ||
}, | ||
], | ||
sha256: 'some-hash', | ||
configId: 'test-id', | ||
}, | ||
], | ||
}; | ||
const getSyntheticsCertsSpy = jest | ||
.spyOn(getCerts, 'getSyntheticsCerts') | ||
// @ts-expect-error partial implementation for testing | ||
.mockReturnValue(getCertsResult); | ||
const route = getSyntheticsCertsRoute(); | ||
getMonitorsSpy.mockReturnValue(getMonitorsResult); | ||
const result = await route.handler({ | ||
// @ts-expect-error partial implementation for testing | ||
request: { query: {} }, | ||
// @ts-expect-error partial implementation for testing | ||
syntheticsEsClient: jest.fn(), | ||
savedObjectClient: jest.fn(), | ||
}); | ||
expect(getMonitorsSpy).toHaveBeenCalledTimes(1); | ||
expect(processMonitorsSpy).toHaveBeenCalledTimes(1); | ||
expect(processMonitorsSpy).toHaveBeenCalledWith(getMonitorsResult); | ||
expect(getSyntheticsCertsSpy).toHaveBeenCalledTimes(1); | ||
expect(result).toEqual({ data: { ...getCertsResult } }); | ||
}); | ||
}); |