@@ -234,6 +234,192 @@ describe("parseRows", () => {
234234 } ,
235235 ] ) ;
236236 } ) ;
237+
238+ it ( "handles FieldMask fields like changed_fields" , ( ) => {
239+ const fields = [
240+ "change_event.resource_name" ,
241+ "change_event.changed_fields" ,
242+ ] ;
243+ const rows : services . IGoogleAdsRow [ ] = [
244+ {
245+ change_event : {
246+ resource_name :
247+ "customers/4517895542/changeEvents/1750751693628134~0~0" ,
248+ change_date_time : "2025-06-24 08:54:53.628134" ,
249+ change_resource_name : "customers/4517895542/campaigns/21930728598" ,
250+ changed_fields : {
251+ paths : [ "campaign.target_roas.target_roas" ] ,
252+ } ,
253+ old_resource : { campaign : { target_roas : { target_roas : 3 } } } ,
254+ new_resource : { campaign : { target_roas : { target_roas : 3.25 } } } ,
255+ } ,
256+ } ,
257+ ] ;
258+ const result = parseRows ( rows , fields ) ;
259+ expect ( result ) . toHaveLength ( 1 ) ;
260+ expect ( result [ 0 ] . change_event ?. resource_name ) . toBe (
261+ "customers/4517895542/changeEvents/1750751693628134~0~0"
262+ ) ;
263+ expect ( result [ 0 ] . change_event ?. changed_fields ) . toEqual ( {
264+ paths : [ "campaign.target_roas.target_roas" ] ,
265+ } ) ;
266+ } ) ;
267+
268+ it ( "handles old_resource and new_resource fields in change events" , ( ) => {
269+ const fields = [
270+ "change_event.resource_name" ,
271+ "change_event.old_resource" ,
272+ "change_event.new_resource" ,
273+ ] ;
274+ const rows : services . IGoogleAdsRow [ ] = [
275+ {
276+ change_event : {
277+ resource_name :
278+ "customers/4517895542/changeEvents/1750751693628134~0~0" ,
279+ change_date_time : "2025-06-24 08:54:53.628134" ,
280+ change_resource_name : "customers/4517895542/campaigns/21930728598" ,
281+ changed_fields : {
282+ paths : [ "campaign.target_roas.target_roas" ] ,
283+ } ,
284+ old_resource : { campaign : { target_roas : { target_roas : 3 } } } ,
285+ new_resource : { campaign : { target_roas : { target_roas : 3.25 } } } ,
286+ } ,
287+ } ,
288+ ] ;
289+ const result = parseRows ( rows , fields ) ;
290+ expect ( result ) . toHaveLength ( 1 ) ;
291+ expect ( result [ 0 ] . change_event ?. resource_name ) . toBe (
292+ "customers/4517895542/changeEvents/1750751693628134~0~0"
293+ ) ;
294+ expect (
295+ result [ 0 ] . change_event ?. old_resource ?. campaign ?. target_roas ?. target_roas
296+ ) . toBe ( 3 ) ;
297+ expect (
298+ result [ 0 ] . change_event ?. new_resource ?. campaign ?. target_roas ?. target_roas
299+ ) . toBe ( 3.25 ) ;
300+ } ) ;
301+
302+ it ( "handles complex nested structures in old_resource and new_resource" , ( ) => {
303+ const fields = [
304+ "change_event.resource_name" ,
305+ "change_event.old_resource" ,
306+ "change_event.new_resource" ,
307+ ] ;
308+ const rows : services . IGoogleAdsRow [ ] = [
309+ {
310+ change_event : {
311+ resource_name :
312+ "customers/4517895542/changeEvents/1750751666945610~0~0" ,
313+ change_date_time : "2025-06-24 08:54:26.94561" ,
314+ change_resource_name : "customers/4517895542/campaigns/17049405489" ,
315+ changed_fields : {
316+ paths : [ "maximize_conversion_value.target_roas" ] ,
317+ } ,
318+ old_resource : {
319+ campaign : {
320+ maximize_conversion_value : {
321+ target_roas : 8 ,
322+ } ,
323+ } ,
324+ } ,
325+ new_resource : {
326+ campaign : {
327+ maximize_conversion_value : {
328+ target_roas : 8.5 ,
329+ } ,
330+ } ,
331+ } ,
332+ } ,
333+ } ,
334+ ] ;
335+ const result = parseRows ( rows , fields ) ;
336+ expect ( result ) . toHaveLength ( 1 ) ;
337+ expect (
338+ result [ 0 ] . change_event ?. old_resource ?. campaign ?. maximize_conversion_value
339+ ?. target_roas
340+ ) . toBe ( 8 ) ;
341+ expect (
342+ result [ 0 ] . change_event ?. new_resource ?. campaign ?. maximize_conversion_value
343+ ?. target_roas
344+ ) . toBe ( 8.5 ) ;
345+ } ) ;
346+
347+ it ( "handles campaign criterion deletion in old_resource and new_resource" , ( ) => {
348+ const fields = [
349+ "change_event.resource_name" ,
350+ "change_event.old_resource" ,
351+ "change_event.new_resource" ,
352+ ] ;
353+ const rows : services . IGoogleAdsRow [ ] = [
354+ {
355+ change_event : {
356+ resource_name :
357+ "customers/4517895542/changeEvents/1750693690782591~0~0" ,
358+ change_date_time : "2025-06-23 16:48:10.782591" ,
359+ change_resource_name :
360+ "customers/4517895542/campaignCriteria/21890334919~23340370" ,
361+ changed_fields : {
362+ paths : [
363+ "campaign" ,
364+ "criterion_id" ,
365+ "keyword.match_type" ,
366+ "keyword.text" ,
367+ "negative" ,
368+ "resource_name" ,
369+ "status" ,
370+ ] ,
371+ } ,
372+ old_resource : {
373+ campaign_criterion : {
374+ resource_name :
375+ "customers/4517895542/campaignCriteria/21890334919~23340370" ,
376+ keyword : {
377+ match_type : "BROAD" ,
378+ text : "crackle" ,
379+ } ,
380+ status : "ENABLED" ,
381+ campaign : "customers/4517895542/campaigns/21890334919" ,
382+ criterion_id : 23340370 ,
383+ negative : true ,
384+ } ,
385+ } ,
386+ new_resource : {
387+ campaign_criterion : { } ,
388+ } ,
389+ } ,
390+ } ,
391+ ] ;
392+ const result = parseRows ( rows , fields ) ;
393+ expect ( result ) . toHaveLength ( 1 ) ;
394+ expect (
395+ result [ 0 ] . change_event ?. old_resource ?. campaign_criterion ?. resource_name
396+ ) . toBe ( "customers/4517895542/campaignCriteria/21890334919~23340370" ) ;
397+ expect (
398+ result [ 0 ] . change_event ?. old_resource ?. campaign_criterion ?. keyword
399+ ?. match_type
400+ ) . toBe ( 4 ) ;
401+ expect (
402+ result [ 0 ] . change_event ?. old_resource ?. campaign_criterion ?. keyword ?. text
403+ ) . toBe ( "crackle" ) ;
404+ expect (
405+ result [ 0 ] . change_event ?. old_resource ?. campaign_criterion ?. status
406+ ) . toBe ( 2 ) ;
407+ expect (
408+ result [ 0 ] . change_event ?. old_resource ?. campaign_criterion ?. campaign
409+ ) . toBe ( "customers/4517895542/campaigns/21890334919" ) ;
410+ expect (
411+ (
412+ result [ 0 ] . change_event ?. old_resource ?. campaign_criterion
413+ ?. criterion_id as any
414+ ) ?. low
415+ ) . toBe ( 23340370 ) ;
416+ expect (
417+ result [ 0 ] . change_event ?. old_resource ?. campaign_criterion ?. negative
418+ ) . toBe ( true ) ;
419+ expect (
420+ result [ 0 ] . change_event ?. new_resource ?. campaign_criterion
421+ ) . toBeDefined ( ) ;
422+ } ) ;
237423} ) ;
238424
239425describe ( "getGAQLFields" , ( ) => {
0 commit comments