@@ -156,6 +156,174 @@ export const testCases: TestCase[] = [
156156 } ,
157157 } ,
158158 } ,
159+ // Escape a single quote in a value
160+ {
161+ testCase : 100 ,
162+ soql : "SELECT Name FROM Account WHERE Industry = 'med\\'ia' LIMIT 125" ,
163+ input : {
164+ fields : [ { type : 'Field' , field : 'Name' } ] ,
165+ sObject : 'Account' ,
166+ where : {
167+ left : { field : 'Industry' , operator : '=' , value : "med'ia" , literalType : 'STRING' } ,
168+ } ,
169+ limit : 125 ,
170+ } ,
171+ } ,
172+ // Pre-escaped single quote is left unchanged
173+ {
174+ testCase : 101 ,
175+ soql : "SELECT Name FROM Account WHERE Name = 'mr\\'s'" ,
176+ input : {
177+ fields : [ { type : 'Field' , field : 'Name' } ] ,
178+ sObject : 'Account' ,
179+ where : {
180+ left : { field : 'Name' , operator : '=' , value : "mr\\'s" , literalType : 'STRING' } ,
181+ } ,
182+ } ,
183+ } ,
184+ // Lone backslash gets escaped
185+ {
186+ testCase : 102 ,
187+ soql : "SELECT Name FROM Account WHERE Name = 'back\\\\slash'" ,
188+ input : {
189+ fields : [ { type : 'Field' , field : 'Name' } ] ,
190+ sObject : 'Account' ,
191+ where : {
192+ left : { field : 'Name' , operator : '=' , value : 'back\\slash' , literalType : 'STRING' } ,
193+ } ,
194+ } ,
195+ } ,
196+ // Multiple lone backslashes (using chars not in the SOQL escape set)
197+ {
198+ testCase : 103 ,
199+ soql : "SELECT Name FROM Account WHERE Name = 'a\\\\xb\\\\yc'" ,
200+ input : {
201+ fields : [ { type : 'Field' , field : 'Name' } ] ,
202+ sObject : 'Account' ,
203+ where : {
204+ left : { field : 'Name' , operator : '=' , value : 'a\\xb\\yc' , literalType : 'STRING' } ,
205+ } ,
206+ } ,
207+ } ,
208+ // Pre-escaped backslash (\\) left unchanged
209+ {
210+ testCase : 104 ,
211+ soql : "SELECT Name FROM Account WHERE Name = 'a\\\\b'" ,
212+ input : {
213+ fields : [ { type : 'Field' , field : 'Name' } ] ,
214+ sObject : 'Account' ,
215+ where : {
216+ left : { field : 'Name' , operator : '=' , value : 'a\\\\b' , literalType : 'STRING' } ,
217+ } ,
218+ } ,
219+ } ,
220+ // LIKE wildcard escapes (\% and \_) left unchanged
221+ {
222+ testCase : 105 ,
223+ soql : "SELECT Name FROM Account WHERE Name LIKE 'like\\%pct'" ,
224+ input : {
225+ fields : [ { type : 'Field' , field : 'Name' } ] ,
226+ sObject : 'Account' ,
227+ where : {
228+ left : { field : 'Name' , operator : 'LIKE' , value : 'like\\%pct' , literalType : 'STRING' } ,
229+ } ,
230+ } ,
231+ } ,
232+ {
233+ testCase : 106 ,
234+ soql : "SELECT Name FROM Account WHERE Name LIKE 'a\\_b'" ,
235+ input : {
236+ fields : [ { type : 'Field' , field : 'Name' } ] ,
237+ sObject : 'Account' ,
238+ where : {
239+ left : { field : 'Name' , operator : 'LIKE' , value : 'a\\_b' , literalType : 'STRING' } ,
240+ } ,
241+ } ,
242+ } ,
243+ // Unicode escape (\uXXXX) left unchanged
244+ {
245+ testCase : 107 ,
246+ soql : "SELECT Name FROM Account WHERE Name = 'caf\\u00e9'" ,
247+ input : {
248+ fields : [ { type : 'Field' , field : 'Name' } ] ,
249+ sObject : 'Account' ,
250+ where : {
251+ left : { field : 'Name' , operator : '=' , value : 'caf\\u00e9' , literalType : 'STRING' } ,
252+ } ,
253+ } ,
254+ } ,
255+ // Invalid unicode escape (not 4 hex digits) — backslash escaped, body preserved
256+ {
257+ testCase : 108 ,
258+ soql : "SELECT Name FROM Account WHERE Name = '\\\\uZZZZ'" ,
259+ input : {
260+ fields : [ { type : 'Field' , field : 'Name' } ] ,
261+ sObject : 'Account' ,
262+ where : {
263+ left : { field : 'Name' , operator : '=' , value : '\\uZZZZ' , literalType : 'STRING' } ,
264+ } ,
265+ } ,
266+ } ,
267+ // Other valid backslash escapes (\n, \t, \r, \", \b, \f) preserved
268+ {
269+ testCase : 109 ,
270+ soql : "SELECT Name FROM Account WHERE Name = 'line1\\nline2\\ttab\\rret'" ,
271+ input : {
272+ fields : [ { type : 'Field' , field : 'Name' } ] ,
273+ sObject : 'Account' ,
274+ where : {
275+ left : { field : 'Name' , operator : '=' , value : 'line1\\nline2\\ttab\\rret' , literalType : 'STRING' } ,
276+ } ,
277+ } ,
278+ } ,
279+ // Mixed: unescaped quote alongside pre-escaped sequences
280+ {
281+ testCase : 110 ,
282+ soql : "SELECT Name FROM Account WHERE Name = 'it\\'s\\na test'" ,
283+ input : {
284+ fields : [ { type : 'Field' , field : 'Name' } ] ,
285+ sObject : 'Account' ,
286+ where : {
287+ left : { field : 'Name' , operator : '=' , value : "it's\\na test" , literalType : 'STRING' } ,
288+ } ,
289+ } ,
290+ } ,
291+ // IN array with mixed escape needs
292+ {
293+ testCase : 111 ,
294+ soql : "SELECT Id FROM Account WHERE Name IN ('a\\'b', 'c\\\\d', 'e\\nf')" ,
295+ input : {
296+ fields : [ { type : 'Field' , field : 'Id' } ] ,
297+ sObject : 'Account' ,
298+ where : {
299+ left : { field : 'Name' , operator : 'IN' , value : [ "a'b" , 'c\\d' , 'e\\nf' ] , literalType : 'STRING' } ,
300+ } ,
301+ } ,
302+ } ,
303+ // Trailing backslash with nothing after it gets escaped
304+ {
305+ testCase : 112 ,
306+ soql : "SELECT Name FROM Account WHERE Name = 'trailing\\\\'" ,
307+ input : {
308+ fields : [ { type : 'Field' , field : 'Name' } ] ,
309+ sObject : 'Account' ,
310+ where : {
311+ left : { field : 'Name' , operator : '=' , value : 'trailing\\' , literalType : 'STRING' } ,
312+ } ,
313+ } ,
314+ } ,
315+ // Round-trip: value already wrapped in quotes (as parseQuery produces) passes through unchanged
316+ {
317+ testCase : 113 ,
318+ soql : "SELECT Name FROM Account WHERE Name = 'already\\'quoted'" ,
319+ input : {
320+ fields : [ { type : 'Field' , field : 'Name' } ] ,
321+ sObject : 'Account' ,
322+ where : {
323+ left : { field : 'Name' , operator : '=' , value : "'already\\'quoted'" , literalType : 'STRING' } ,
324+ } ,
325+ } ,
326+ } ,
159327] ;
160328
161329export default testCases ;
0 commit comments