@@ -713,3 +713,144 @@ where
713713 . map ( |key| AtKeyed :: new ( self . inner . clone ( ) , key) )
714714 }
715715}
716+
717+ #[ cfg( test) ]
718+ mod tests {
719+ use crate :: { self as reactive_stores, tests:: tick, AtKeyed , Store } ;
720+ use reactive_graph:: {
721+ effect:: Effect ,
722+ traits:: { GetUntracked , ReadUntracked , Set , Track , Write } ,
723+ } ;
724+ use std:: sync:: {
725+ atomic:: { AtomicUsize , Ordering } ,
726+ Arc ,
727+ } ;
728+
729+ #[ derive( Debug , Store , Default ) ]
730+ struct Todos {
731+ #[ store( key: usize = |todo| todo. id) ]
732+ todos : Vec < Todo > ,
733+ }
734+
735+ #[ derive( Debug , Store , Default , Clone , PartialEq , Eq ) ]
736+ struct Todo {
737+ id : usize ,
738+ label : String ,
739+ }
740+
741+ impl Todo {
742+ pub fn new ( id : usize , label : impl ToString ) -> Self {
743+ Self {
744+ id,
745+ label : label. to_string ( ) ,
746+ }
747+ }
748+ }
749+
750+ fn data ( ) -> Todos {
751+ Todos {
752+ todos : vec ! [
753+ Todo {
754+ id: 10 ,
755+ label: "A" . to_string( ) ,
756+ } ,
757+ Todo {
758+ id: 11 ,
759+ label: "B" . to_string( ) ,
760+ } ,
761+ Todo {
762+ id: 12 ,
763+ label: "C" . to_string( ) ,
764+ } ,
765+ ] ,
766+ }
767+ }
768+ #[ tokio:: test]
769+ async fn keyed_fields_can_be_moved ( ) {
770+ _ = any_spawner:: Executor :: init_tokio ( ) ;
771+
772+ let store = Store :: new ( data ( ) ) ;
773+ assert_eq ! ( store. read_untracked( ) . todos. len( ) , 3 ) ;
774+
775+ // create an effect to read from each keyed field
776+ let a_count = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
777+ let b_count = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
778+ let c_count = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
779+
780+ let a = AtKeyed :: new ( store. todos ( ) , 10 ) ;
781+ let b = AtKeyed :: new ( store. todos ( ) , 11 ) ;
782+ let c = AtKeyed :: new ( store. todos ( ) , 12 ) ;
783+
784+ Effect :: new_sync ( {
785+ let a_count = Arc :: clone ( & a_count) ;
786+ move || {
787+ a. track ( ) ;
788+ a_count. fetch_add ( 1 , Ordering :: Relaxed ) ;
789+ }
790+ } ) ;
791+ Effect :: new_sync ( {
792+ let b_count = Arc :: clone ( & b_count) ;
793+ move || {
794+ b. track ( ) ;
795+ b_count. fetch_add ( 1 , Ordering :: Relaxed ) ;
796+ }
797+ } ) ;
798+ Effect :: new_sync ( {
799+ let c_count = Arc :: clone ( & c_count) ;
800+ move || {
801+ c. track ( ) ;
802+ c_count. fetch_add ( 1 , Ordering :: Relaxed ) ;
803+ }
804+ } ) ;
805+
806+ tick ( ) . await ;
807+ assert_eq ! ( a_count. load( Ordering :: Relaxed ) , 1 ) ;
808+ assert_eq ! ( b_count. load( Ordering :: Relaxed ) , 1 ) ;
809+ assert_eq ! ( c_count. load( Ordering :: Relaxed ) , 1 ) ;
810+
811+ // writing at a key doesn't notify siblings
812+ * a. label ( ) . write ( ) = "Foo" . into ( ) ;
813+ tick ( ) . await ;
814+ assert_eq ! ( a_count. load( Ordering :: Relaxed ) , 2 ) ;
815+ assert_eq ! ( b_count. load( Ordering :: Relaxed ) , 1 ) ;
816+ assert_eq ! ( c_count. load( Ordering :: Relaxed ) , 1 ) ;
817+
818+ // the keys can be reorganized
819+ store. todos ( ) . write ( ) . swap ( 0 , 2 ) ;
820+ let after = store. todos ( ) . get_untracked ( ) ;
821+ assert_eq ! (
822+ after,
823+ vec![ Todo :: new( 12 , "C" ) , Todo :: new( 11 , "B" ) , Todo :: new( 10 , "Foo" ) ]
824+ ) ;
825+
826+ tick ( ) . await ;
827+ assert_eq ! ( a_count. load( Ordering :: Relaxed ) , 2 ) ;
828+ assert_eq ! ( b_count. load( Ordering :: Relaxed ) , 1 ) ;
829+ assert_eq ! ( c_count. load( Ordering :: Relaxed ) , 1 ) ;
830+
831+ // and after we move the keys around, they still update the moved items
832+ a. label ( ) . set ( "Bar" . into ( ) ) ;
833+ let after = store. todos ( ) . get_untracked ( ) ;
834+ assert_eq ! (
835+ after,
836+ vec![ Todo :: new( 12 , "C" ) , Todo :: new( 11 , "B" ) , Todo :: new( 10 , "Bar" ) ]
837+ ) ;
838+ tick ( ) . await ;
839+ assert_eq ! ( a_count. load( Ordering :: Relaxed ) , 3 ) ;
840+ assert_eq ! ( b_count. load( Ordering :: Relaxed ) , 1 ) ;
841+ assert_eq ! ( c_count. load( Ordering :: Relaxed ) , 1 ) ;
842+
843+ // we can remove a key and add a new one
844+ store. todos ( ) . write ( ) . pop ( ) ;
845+ store. todos ( ) . write ( ) . push ( Todo :: new ( 13 , "New" ) ) ;
846+ let after = store. todos ( ) . get_untracked ( ) ;
847+ assert_eq ! (
848+ after,
849+ vec![ Todo :: new( 12 , "C" ) , Todo :: new( 11 , "B" ) , Todo :: new( 13 , "New" ) ]
850+ ) ;
851+ tick ( ) . await ;
852+ assert_eq ! ( a_count. load( Ordering :: Relaxed ) , 3 ) ;
853+ assert_eq ! ( b_count. load( Ordering :: Relaxed ) , 1 ) ;
854+ assert_eq ! ( c_count. load( Ordering :: Relaxed ) , 1 ) ;
855+ }
856+ }
0 commit comments