@@ -624,5 +624,137 @@ void main() {
624624 // assert
625625 expect (() => getRelation (), throwsA (isA <ParseRelationException >()));
626626 });
627+
628+ test ('addRelation() should work with custom ParseObject subclasses' , () {
629+ // arrange
630+ // Create custom ParseObject subclasses similar to the issue report
631+ final contact1 = Contact ()..objectId = 'contact1' ;
632+ final contact2 = Contact ()..objectId = 'contact2' ;
633+
634+ final order = Order ();
635+
636+ // act & assert
637+ // This should not throw a TypeError
638+ expect (
639+ () => order.addRelation ('receivers' , [contact1, contact2]),
640+ returnsNormally,
641+ );
642+
643+ final toJsonAfterAddRelation = order.toJson (forApiRQ: true );
644+
645+ const expectedToJson = {
646+ "receivers" : {
647+ "__op" : "AddRelation" ,
648+ "objects" : [
649+ {
650+ "__type" : "Pointer" ,
651+ "className" : "Contact" ,
652+ "objectId" : "contact1" ,
653+ },
654+ {
655+ "__type" : "Pointer" ,
656+ "className" : "Contact" ,
657+ "objectId" : "contact2" ,
658+ },
659+ ],
660+ },
661+ };
662+
663+ expect (
664+ DeepCollectionEquality ().equals (expectedToJson, toJsonAfterAddRelation),
665+ isTrue,
666+ );
667+ });
668+
669+ test (
670+ 'addRelation() should work when getRelation<T>() was called first with typed generic' ,
671+ () {
672+ // This test reproduces issue #999
673+ // The issue occurs when:
674+ // 1. getRelation<Contact>() is called first (creating _ParseRelation<Contact>)
675+ // 2. Then addRelation() is called with Contact objects
676+ // 3. The merge operation creates a Set<ParseObject>
677+ // 4. Trying to cast Set<ParseObject> to Set<Contact> throws TypeError
678+
679+ // arrange
680+ final contact1 = Contact ()..objectId = 'contact1' ;
681+ final contact2 = Contact ()..objectId = 'contact2' ;
682+
683+ final order = Order ();
684+
685+ // First, get the relation with typed generic (this creates _ParseRelation<Contact>)
686+ order.getRelation <Contact >('receivers' );
687+
688+ // act & assert
689+ // This should NOT throw: _TypeError (type '_Set<ParseObject>' is not a subtype of type 'Set<Contact>' in type cast)
690+ expect (
691+ () => order.addRelation ('receivers' , [contact1, contact2]),
692+ returnsNormally,
693+ );
694+ },
695+ );
696+
697+ test (
698+ 'calling addRelation() multiple times with custom subclasses should work' ,
699+ () {
700+ // arrange
701+ final contact1 = Contact ()..objectId = 'contact1' ;
702+ final contact2 = Contact ()..objectId = 'contact2' ;
703+ final contact3 = Contact ()..objectId = 'contact3' ;
704+
705+ final order = Order ();
706+
707+ // act & assert
708+ // First addRelation call
709+ expect (
710+ () => order.addRelation ('receivers' , [contact1]),
711+ returnsNormally,
712+ );
713+
714+ // Second addRelation call - this should also not throw
715+ expect (
716+ () => order.addRelation ('receivers' , [contact2, contact3]),
717+ returnsNormally,
718+ );
719+ },
720+ );
721+
722+ test ('removeRelation() should work with custom ParseObject subclasses' , () {
723+ // arrange
724+ final contact1 = Contact ()..objectId = 'contact1' ;
725+ final contact2 = Contact ()..objectId = 'contact2' ;
726+
727+ final order = Order ();
728+
729+ // act & assert
730+ expect (
731+ () => order.removeRelation ('receivers' , [contact1, contact2]),
732+ returnsNormally,
733+ );
734+ });
627735 });
628736}
737+
738+ /// Custom ParseObject subclass for testing (similar to the issue report)
739+ class Contact extends ParseObject implements ParseCloneable {
740+ Contact () : super (_keyTableName);
741+ Contact .clone () : this ();
742+
743+ @override
744+ clone (Map <String , dynamic > map) =>
745+ Contact .clone ()..fromJson (Map <String , dynamic >.from (map));
746+
747+ static const String _keyTableName = 'Contact' ;
748+ }
749+
750+ /// Custom ParseObject subclass for testing (similar to the issue report)
751+ class Order extends ParseObject implements ParseCloneable {
752+ Order () : super (_keyTableName);
753+ Order .clone () : this ();
754+
755+ @override
756+ clone (Map <String , dynamic > map) =>
757+ Order .clone ()..fromJson (Map <String , dynamic >.from (map));
758+
759+ static const String _keyTableName = 'Order' ;
760+ }
0 commit comments