Mirror of https://github.com/roostorg/coop github.com/roostorg/coop
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 557ff54b2b435e5f1e789c6a8a4e1bebf2d7deb6 195 lines 6.3 kB view raw
1import { type Dependencies } from '../../iocContainer/index.js'; 2import { type MockedFn } from '../../test/mockHelpers/jestMocks.js'; 3import makeGetRuleAnomalyDetectionStatistics from './getRuleAnomalyDetectionStatistics.js'; 4 5/** 6 * @fileoverview The testing strategy here is to just snapshot the queries 7 * that our service function is generating, and run those manually to verify 8 * that they work. If we update the warehouse structure, we can update the 9 * snapshots and manually re-run the new queries. But having these snapshots at 10 * least makes sure we can't change inadvertently change the generated queries. 11 */ 12describe('getRuleAnomalyDetectionStatistics', () => { 13 let queryMock: MockedFn<(query: string, tracer: any, binds?: readonly unknown[]) => Promise<unknown[]>>; 14 let getRulePassStatistics: Dependencies['getRuleAnomalyDetectionStatistics']; 15 16 beforeAll(() => { 17 const queryResult = [ 18 { 19 RULE_ID: 'a', 20 NUM_PASSES: 2, 21 NUM_DISTINCT_USERS: 1, 22 NUM_RUNS: 4, 23 TS_START_INCLUSIVE: '2022-05-07 23:00:00.00', 24 RULE_VERSION: '2022-05-01T12:10:00.00305Z', 25 }, 26 ]; 27 28 // Scope of this is just the test suite, so mutation should be ok. 29 // eslint-disable-next-line better-mutation/no-mutation 30 queryMock = jest.fn() as any; 31 queryMock.mockResolvedValue(queryResult); 32 33 const dataWarehouseMock = { 34 query: queryMock, 35 transaction: jest.fn(), 36 start: jest.fn(), 37 close: jest.fn(), 38 getProvider: () => 'clickhouse' as const, 39 }; 40 41 // Scope of this is just the test suite, so mutation should be ok. 42 // eslint-disable-next-line better-mutation/no-mutation 43 getRulePassStatistics = makeGetRuleAnomalyDetectionStatistics( 44 dataWarehouseMock, 45 {} as any, 46 ); 47 }); 48 49 beforeEach(() => { 50 // This is only safe while we're not running tests concurrently. 51 // Consider using the `makeTestWithFixture` helper instead to make 52 // a local copy of this state for each test. 53 queryMock.mockClear(); 54 }); 55 56 test('should return the result from the warehouse, properly formatted', async () => { 57 const result = await getRulePassStatistics(); 58 expect(result).toEqual([ 59 { 60 ruleId: 'a', 61 passCount: 2, 62 runsCount: 4, 63 passingUsersCount: 1, 64 windowStart: new Date('2022-05-07 23:00:00.00'), 65 approxRuleVersion: new Date('2022-05-01T12:10:00.00305Z'), 66 }, 67 ]); 68 }); 69 70 test('should generate the proper query when given no filters', async () => { 71 await getRulePassStatistics(); 72 73 expect(queryMock).toHaveBeenCalledTimes(1); 74 expect(queryMock.mock.calls[0]).toMatchInlineSnapshot(` 75 [ 76 " 77 SELECT 78 rule_id, 79 rule_version, 80 num_passes, 81 num_runs, 82 array_size(passes_distinct_user_ids) as num_distinct_users, 83 ts_start_inclusive 84 FROM RULE_ANOMALY_DETECTION_SERVICE.RULE_EXECUTION_STATISTICS 85 WHERE ts_end_exclusive <= SYSDATE() 86 ORDER BY ts_start_inclusive DESC;", 87 {}, 88 [], 89 ] 90 `); 91 }); 92 93 test('should generate the proper query when given a start time filter', async () => { 94 await getRulePassStatistics({ startTime: new Date('2022-05-02') }); 95 96 expect(queryMock).toHaveBeenCalledTimes(1); 97 expect(queryMock.mock.calls[0]).toMatchInlineSnapshot(` 98 [ 99 " 100 SELECT 101 rule_id, 102 rule_version, 103 num_passes, 104 num_runs, 105 array_size(passes_distinct_user_ids) as num_distinct_users, 106 ts_start_inclusive 107 FROM RULE_ANOMALY_DETECTION_SERVICE.RULE_EXECUTION_STATISTICS 108 WHERE ts_end_exclusive <= SYSDATE() AND ts_start_inclusive >= ? 109 ORDER BY ts_start_inclusive DESC;", 110 {}, 111 [ 112 2022-05-02T00:00:00.000Z, 113 ], 114 ] 115 `); 116 }); 117 118 test('should generate the proper query when given a ruleIds filter', async () => { 119 await getRulePassStatistics({ ruleIds: ['1', '2'] }); 120 121 expect(queryMock).toHaveBeenCalledTimes(1); 122 expect(queryMock.mock.calls[0]).toMatchInlineSnapshot(` 123 [ 124 " 125 SELECT 126 rule_id, 127 rule_version, 128 num_passes, 129 num_runs, 130 array_size(passes_distinct_user_ids) as num_distinct_users, 131 ts_start_inclusive 132 FROM RULE_ANOMALY_DETECTION_SERVICE.RULE_EXECUTION_STATISTICS 133 WHERE ts_end_exclusive <= SYSDATE() AND rule_id IN (?,?) 134 ORDER BY ts_start_inclusive DESC;", 135 {}, 136 [ 137 "1", 138 "2", 139 ], 140 ] 141 `); 142 await getRulePassStatistics({ ruleIds: ['1'] }); 143 144 expect(queryMock).toHaveBeenCalledTimes(2); 145 expect(queryMock.mock.calls[1]).toMatchInlineSnapshot(` 146 [ 147 " 148 SELECT 149 rule_id, 150 rule_version, 151 num_passes, 152 num_runs, 153 array_size(passes_distinct_user_ids) as num_distinct_users, 154 ts_start_inclusive 155 FROM RULE_ANOMALY_DETECTION_SERVICE.RULE_EXECUTION_STATISTICS 156 WHERE ts_end_exclusive <= SYSDATE() AND rule_id IN (?) 157 ORDER BY ts_start_inclusive DESC;", 158 {}, 159 [ 160 "1", 161 ], 162 ] 163 `); 164 }); 165 166 test('should generate the proper query when given both filters', async () => { 167 await getRulePassStatistics({ 168 ruleIds: ['1', '2'], 169 startTime: new Date('2022-05-02 23:00:00.00-04'), 170 }); 171 172 expect(queryMock).toHaveBeenCalledTimes(1); 173 expect(queryMock.mock.calls[0]).toMatchInlineSnapshot(` 174 [ 175 " 176 SELECT 177 rule_id, 178 rule_version, 179 num_passes, 180 num_runs, 181 array_size(passes_distinct_user_ids) as num_distinct_users, 182 ts_start_inclusive 183 FROM RULE_ANOMALY_DETECTION_SERVICE.RULE_EXECUTION_STATISTICS 184 WHERE ts_end_exclusive <= SYSDATE() AND ts_start_inclusive >= ? AND rule_id IN (?,?) 185 ORDER BY ts_start_inclusive DESC;", 186 {}, 187 [ 188 2022-05-03T03:00:00.000Z, 189 "1", 190 "2", 191 ], 192 ] 193 `); 194 }); 195});