@@ -534,7 +534,127 @@ void main() {
534534 );
535535
536536 // assert
537- expect (result.query.contains ("%22object2%22,%22%22include%22" ), true );
537+ expect (result.query.contains ("%22object2%22,%22include%22" ), true );
538+ });
539+
540+ test ('whereMatchesQuery generates valid JSON' , () async {
541+ // arrange - This test specifically checks for the bug where
542+ // whereMatchesQuery generated invalid JSON with trailing commas
543+ // See: https://github.com/parse-community/Parse-SDK-Flutter/issues/932
544+ ParseObject deliveryArea = ParseObject ("DeliveryArea" );
545+ final deliveryAreasQuery = QueryBuilder <ParseObject >(deliveryArea)
546+ ..whereArrayContainsAll ('postalCodes' , [21075 ]);
547+
548+ ParseObject farmer = ParseObject ("Farmer" , client: client);
549+ final query = QueryBuilder <ParseObject >(farmer)
550+ ..whereMatchesQuery ('deliveryAreas' , deliveryAreasQuery)
551+ ..whereEqualTo ('isActive' , true );
552+
553+ var desiredOutput = {"results" : []};
554+
555+ when (
556+ client.get (
557+ any,
558+ options: anyNamed ("options" ),
559+ onReceiveProgress: anyNamed ("onReceiveProgress" ),
560+ ),
561+ ).thenAnswer (
562+ (_) async => ParseNetworkResponse (
563+ statusCode: 200 ,
564+ data: jsonEncode (desiredOutput),
565+ ),
566+ );
567+
568+ // act
569+ await query.query ();
570+
571+ final String capturedUrl = verify (
572+ client.get (
573+ captureAny,
574+ options: anyNamed ("options" ),
575+ onReceiveProgress: anyNamed ("onReceiveProgress" ),
576+ ),
577+ ).captured.single;
578+
579+ // Extract the 'where' parameter from the URL
580+ final Uri uri = Uri .parse (capturedUrl);
581+ final String ? whereParam = uri.queryParameters['where' ];
582+
583+ // assert - The JSON should be valid (no trailing commas)
584+ expect (whereParam, isNotNull);
585+
586+ // This should not throw if JSON is valid
587+ final decoded = jsonDecode (whereParam! );
588+ expect (decoded, isA <Map >());
589+
590+ // Verify the structure is correct
591+ expect (decoded['deliveryAreas' ], isNotNull);
592+ expect (decoded['deliveryAreas' ]['\$ inQuery' ], isNotNull);
593+ expect (
594+ decoded['deliveryAreas' ]['\$ inQuery' ]['className' ],
595+ 'DeliveryArea' ,
596+ );
597+ expect (decoded['deliveryAreas' ]['\$ inQuery' ]['where' ], isNotNull);
598+ });
599+
600+ test ('whereMatchesQuery with limiters should not have extra quotes' , () async {
601+ // arrange - This test specifically checks for the bug where limiters
602+ // were incorrectly wrapped with extra quotes like ',"$lim"' instead of ',$lim'
603+ // which produced patterns like ""include" (double quotes before limiter key)
604+ // See: https://github.com/parse-community/Parse-SDK-Flutter/issues/932
605+ ParseObject innerObject = ParseObject ("InnerClass" );
606+ final innerQuery = QueryBuilder <ParseObject >(innerObject)
607+ ..includeObject (["relatedField" ])
608+ ..whereEqualTo ("status" , "active" );
609+
610+ ParseObject outerObject = ParseObject ("OuterClass" , client: client);
611+ final outerQuery = QueryBuilder <ParseObject >(outerObject)
612+ ..whereMatchesQuery ('innerRef' , innerQuery);
613+
614+ var desiredOutput = {"results" : []};
615+
616+ when (
617+ client.get (
618+ any,
619+ options: anyNamed ("options" ),
620+ onReceiveProgress: anyNamed ("onReceiveProgress" ),
621+ ),
622+ ).thenAnswer (
623+ (_) async => ParseNetworkResponse (
624+ statusCode: 200 ,
625+ data: jsonEncode (desiredOutput),
626+ ),
627+ );
628+
629+ // act
630+ await outerQuery.query ();
631+
632+ final String capturedUrl = verify (
633+ client.get (
634+ captureAny,
635+ options: anyNamed ("options" ),
636+ onReceiveProgress: anyNamed ("onReceiveProgress" ),
637+ ),
638+ ).captured.single;
639+
640+ // assert - Check that the URL does NOT contain the buggy pattern ""include"
641+ // (double quotes before 'include' which was caused by extra quotes around limiters)
642+ // %22%22 is the URL-encoded form of "" (two consecutive double quotes)
643+ expect (
644+ capturedUrl.contains ('%22%22include' ),
645+ isFalse,
646+ reason: 'URL should not contain double quotes before limiter keys' ,
647+ );
648+
649+ // Also verify the correct pattern exists: className followed by comma and include
650+ // without extra quotes between them
651+ // The pattern should be: "className":"InnerClass","include" not "className":"InnerClass",""include"
652+ expect (
653+ capturedUrl.contains ('%22InnerClass%22,%22include%22' ),
654+ isTrue,
655+ reason:
656+ 'URL should contain properly formatted className followed by include' ,
657+ );
538658 });
539659
540660 test ('the result query should contains encoded special characters values' , () {
0 commit comments