1+ import {
2+ buildFilterClickHouse ,
3+ } from '../../filters/filters' ;
4+ import {
5+ FilterLeaf ,
6+ } from '../../filters/filterDefs' ;
7+
8+ describe ( 'Target URL Filter' , ( ) => {
9+ describe ( 'buildFilterClickHouse with target_url' , ( ) => {
10+ test ( 'should build target_url equals filter correctly' , ( ) => {
11+ const filter : FilterLeaf = {
12+ request_response_rmt : {
13+ target_url : { equals : 'https://api.openai.com/v1/chat/completions' }
14+ }
15+ } ;
16+
17+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
18+
19+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_0 : String}' ) ;
20+ expect ( result . argsAcc ) . toEqual ( [ 'https://api.openai.com/v1/chat/completions' ] ) ;
21+ } ) ;
22+
23+ test ( 'should build target_url like filter correctly' , ( ) => {
24+ const filter : FilterLeaf = {
25+ request_response_rmt : {
26+ target_url : { like : '%openai.com%' }
27+ }
28+ } ;
29+
30+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
31+
32+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url LIKE {val_0 : String}' ) ;
33+ expect ( result . argsAcc ) . toEqual ( [ '%openai.com%' ] ) ;
34+ } ) ;
35+
36+ test ( 'should build target_url ilike filter correctly' , ( ) => {
37+ const filter : FilterLeaf = {
38+ request_response_rmt : {
39+ target_url : { ilike : '%OPENAI.COM%' }
40+ }
41+ } ;
42+
43+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
44+
45+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url ILIKE {val_0 : String}' ) ;
46+ expect ( result . argsAcc ) . toEqual ( [ '%OPENAI.COM%' ] ) ;
47+ } ) ;
48+
49+ test ( 'should build target_url contains filter correctly' , ( ) => {
50+ const filter : FilterLeaf = {
51+ request_response_rmt : {
52+ target_url : { contains : 'anthropic' }
53+ }
54+ } ;
55+
56+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
57+
58+ expect ( result . filter ) . toBe ( "request_response_rmt.target_url ILIKE '%' || {val_0 : String}::text || '%'" ) ;
59+ expect ( result . argsAcc ) . toEqual ( [ 'anthropic' ] ) ;
60+ } ) ;
61+
62+ test ( 'should build target_url not-equals filter correctly' , ( ) => {
63+ const filter : FilterLeaf = {
64+ request_response_rmt : {
65+ target_url : { 'not-equals' : 'https://api.openai.com/v1/embeddings' }
66+ }
67+ } ;
68+
69+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
70+
71+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url != {val_0 : String}' ) ;
72+ expect ( result . argsAcc ) . toEqual ( [ 'https://api.openai.com/v1/embeddings' ] ) ;
73+ } ) ;
74+
75+ test ( 'should handle target_url with null value' , ( ) => {
76+ const filter : FilterLeaf = {
77+ request_response_rmt : {
78+ target_url : { equals : 'null' }
79+ }
80+ } ;
81+
82+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
83+
84+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url is null' ) ;
85+ expect ( result . argsAcc ) . toEqual ( [ ] ) ;
86+ } ) ;
87+
88+ test ( 'should work with target_url alongside other basic fields' , ( ) => {
89+ // Test that target_url doesn't break when used with a simple status filter
90+ const simpleFilter : FilterLeaf = {
91+ request_response_rmt : {
92+ target_url : { equals : 'https://api.openai.com/v1/chat/completions' }
93+ }
94+ } ;
95+
96+ const result = buildFilterClickHouse ( { filter : simpleFilter , argsAcc : [ ] } ) ;
97+
98+ // Should successfully build target_url filter
99+ expect ( result . argsAcc ) . toEqual ( [ 'https://api.openai.com/v1/chat/completions' ] ) ;
100+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_0 : String}' ) ;
101+ } ) ;
102+ } ) ;
103+
104+ describe ( 'Target URL Filter Mapping Verification' , ( ) => {
105+ test ( 'should verify target_url mapping exists in request_response_rmt' , ( ) => {
106+ // This test verifies that our fix is working by checking that target_url
107+ // filters can be built without throwing errors
108+ const filter : FilterLeaf = {
109+ request_response_rmt : {
110+ target_url : { equals : 'https://api.anthropic.com/v1/messages' }
111+ }
112+ } ;
113+
114+ // This should not throw an error now that target_url mapping is added
115+ expect ( ( ) => {
116+ buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
117+ } ) . not . toThrow ( ) ;
118+ } ) ;
119+
120+ test ( 'should handle target_url with different URL formats' , ( ) => {
121+ const testCases = [
122+ 'https://api.openai.com/v1/chat/completions' ,
123+ 'https://api.anthropic.com/v1/messages' ,
124+ 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent' ,
125+ 'https://api.cohere.ai/v1/generate' ,
126+ 'http://localhost:3000/api/proxy' ,
127+ 'https://api.mistral.ai/v1/chat/completions' ,
128+ 'wss://api.openai.com/v1/realtime' ,
129+ ] ;
130+
131+ testCases . forEach ( ( url ) => {
132+ const filter : FilterLeaf = {
133+ request_response_rmt : {
134+ target_url : { equals : url }
135+ }
136+ } ;
137+
138+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
139+
140+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_0 : String}' ) ;
141+ expect ( result . argsAcc ) . toEqual ( [ url ] ) ;
142+ } ) ;
143+ } ) ;
144+
145+ test ( 'should handle target_url with special characters in URL' , ( ) => {
146+ const urlWithSpecialChars = 'https://api.example.com/v1/test?param=value&other=test%20string' ;
147+ const filter : FilterLeaf = {
148+ request_response_rmt : {
149+ target_url : { equals : urlWithSpecialChars }
150+ }
151+ } ;
152+
153+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
154+
155+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_0 : String}' ) ;
156+ expect ( result . argsAcc ) . toEqual ( [ urlWithSpecialChars ] ) ;
157+ } ) ;
158+ } ) ;
159+
160+ describe ( 'Target URL Filter Edge Cases' , ( ) => {
161+ test ( 'should handle empty target_url value' , ( ) => {
162+ const filter : FilterLeaf = {
163+ request_response_rmt : {
164+ target_url : { equals : '' }
165+ }
166+ } ;
167+
168+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
169+
170+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_0 : String}' ) ;
171+ expect ( result . argsAcc ) . toEqual ( [ '' ] ) ;
172+ } ) ;
173+
174+ test ( 'should handle very long target_url values' , ( ) => {
175+ const longUrl = 'https://api.example.com/v1/very/long/path/that/goes/on/and/on/' + 'segment/' . repeat ( 50 ) + '?param=value' ;
176+ const filter : FilterLeaf = {
177+ request_response_rmt : {
178+ target_url : { equals : longUrl }
179+ }
180+ } ;
181+
182+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
183+
184+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_0 : String}' ) ;
185+ expect ( result . argsAcc ) . toEqual ( [ longUrl ] ) ;
186+ } ) ;
187+
188+ test ( 'should handle target_url with unicode characters' , ( ) => {
189+ const unicodeUrl = 'https://api.example.com/v1/测试/пример/🚀?param=тест' ;
190+ const filter : FilterLeaf = {
191+ request_response_rmt : {
192+ target_url : { equals : unicodeUrl }
193+ }
194+ } ;
195+
196+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
197+
198+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_0 : String}' ) ;
199+ expect ( result . argsAcc ) . toEqual ( [ unicodeUrl ] ) ;
200+ } ) ;
201+ } ) ;
202+
203+ describe ( 'Target URL Filter Integration' , ( ) => {
204+ test ( 'should work with existing argument arrays' , ( ) => {
205+ const filter : FilterLeaf = {
206+ request_response_rmt : {
207+ target_url : { equals : 'https://api.openai.com/v1/chat/completions' }
208+ }
209+ } ;
210+
211+ const existingArgs = [ 'existing_value_1' , 'existing_value_2' ] ;
212+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ...existingArgs ] } ) ;
213+
214+ expect ( result . filter ) . toBe ( 'request_response_rmt.target_url = {val_2 : String}' ) ;
215+ expect ( result . argsAcc ) . toEqual ( [ ...existingArgs , 'https://api.openai.com/v1/chat/completions' ] ) ;
216+ } ) ;
217+
218+ test ( 'should demonstrate the fix prevents previous error' , ( ) => {
219+ // Before the fix, this would cause an error because target_url was not mapped
220+ const filter : FilterLeaf = {
221+ request_response_rmt : {
222+ target_url : { contains : 'anthropic' }
223+ }
224+ } ;
225+
226+ // This should not throw an error now that target_url mapping is fixed
227+ expect ( ( ) => {
228+ const result = buildFilterClickHouse ( { filter, argsAcc : [ ] } ) ;
229+ expect ( result . filter ) . toContain ( "request_response_rmt.target_url ILIKE '%' || {val_0 : String}::text || '%'" ) ;
230+ expect ( result . argsAcc ) . toEqual ( [ 'anthropic' ] ) ;
231+ } ) . not . toThrow ( ) ;
232+ } ) ;
233+ } ) ;
234+ } ) ;
0 commit comments