@@ -3,6 +3,7 @@ import mitt from "mitt"
33import { Collection } from "../../src/collection.js"
44import { queryBuilder } from "../../src/query/query-builder.js"
55import { compileQuery } from "../../src/query/compiled-query.js"
6+ import { createTransaction } from "../../src/transactions.js"
67import type { PendingMutation } from "../../src/types.js"
78
89type Person = {
@@ -562,6 +563,139 @@ describe(`Query Collections`, () => {
562563 { id : `1` , name : `John Doe` , age : 40 , _orderByIndex : 2 } ,
563564 ] )
564565 } )
566+
567+ it ( `optimistic state is dropped after commit` , async ( ) => {
568+ const emitter = mitt ( )
569+
570+ // Create person collection
571+ const personCollection = new Collection < Person > ( {
572+ id : `person-collection-test-bug` ,
573+ sync : {
574+ sync : ( { begin, write, commit } ) => {
575+ // @ts -expect-error Mitt typing doesn't match our usage
576+ emitter . on ( `sync-person` , ( changes : Array < PendingMutation > ) => {
577+ begin ( )
578+ changes . forEach ( ( change ) => {
579+ write ( {
580+ key : change . key ,
581+ type : change . type ,
582+ value : change . changes as Person ,
583+ } )
584+ } )
585+ commit ( )
586+ } )
587+ } ,
588+ } ,
589+ } )
590+
591+ // Create issue collection
592+ const issueCollection = new Collection < Issue > ( {
593+ id : `issue-collection-test-bug` ,
594+ sync : {
595+ sync : ( { begin, write, commit } ) => {
596+ // @ts -expect-error Mitt typing doesn't match our usage
597+ emitter . on ( `sync-issue` , ( changes : Array < PendingMutation > ) => {
598+ begin ( )
599+ changes . forEach ( ( change ) => {
600+ write ( {
601+ key : change . key ,
602+ type : change . type ,
603+ value : change . changes as Issue ,
604+ } )
605+ } )
606+ commit ( )
607+ } )
608+ } ,
609+ } ,
610+ } )
611+
612+ // Sync initial person data
613+ emitter . emit (
614+ `sync-person` ,
615+ initialPersons . map ( ( person ) => ( {
616+ key : person . id ,
617+ type : `insert` ,
618+ changes : person ,
619+ } ) )
620+ )
621+
622+ // Sync initial issue data
623+ emitter . emit (
624+ `sync-issue` ,
625+ initialIssues . map ( ( issue ) => ( {
626+ key : issue . id ,
627+ type : `insert` ,
628+ changes : issue ,
629+ } ) )
630+ )
631+
632+ // Create a query with a join between persons and issues
633+ const query = queryBuilder ( )
634+ . from ( { issues : issueCollection } )
635+ . join ( {
636+ type : `inner` ,
637+ from : { persons : personCollection } ,
638+ on : [ `@persons.id` , `=` , `@issues.userId` ] ,
639+ } )
640+ . select ( `@issues.id` , `@issues.title` , `@persons.name` )
641+ . keyBy ( `@id` )
642+
643+ const compiledQuery = compileQuery ( query )
644+ compiledQuery . start ( )
645+
646+ const result = compiledQuery . results
647+
648+ await waitForChanges ( )
649+
650+ // Verify initial state
651+ expect ( result . state . size ) . toBe ( 3 )
652+
653+ // Create a transaction to perform an optimistic mutation
654+ const tx = createTransaction ( {
655+ mutationFn : async ( ) => {
656+ emitter . emit ( `sync-issue` , [
657+ {
658+ key : `4` ,
659+ type : `insert` ,
660+ changes : {
661+ id : `4` ,
662+ title : `New Issue` ,
663+ description : `New Issue Description` ,
664+ userId : `1` ,
665+ } ,
666+ } ,
667+ ] )
668+ return Promise . resolve ( )
669+ } ,
670+ } )
671+
672+ // Perform optimistic insert of a new issue
673+ tx . mutate ( ( ) =>
674+ issueCollection . insert (
675+ {
676+ id : `temp-key` ,
677+ title : `New Issue` ,
678+ description : `New Issue Description` ,
679+ userId : `1` ,
680+ } ,
681+ { key : `temp-key` }
682+ )
683+ )
684+
685+ // Verify optimistic state is immediately reflected
686+ expect ( result . state . size ) . toBe ( 4 )
687+ expect ( result . state . get ( `temp-key` ) ) . toEqual ( {
688+ id : `temp-key` ,
689+ name : `John Doe` ,
690+ title : `New Issue` ,
691+ } )
692+
693+ // Wait for the transaction to be committed
694+ await tx . isPersisted . promise
695+
696+ expect ( result . state . size ) . toBe ( 4 )
697+ expect ( result . state . get ( `4` ) ) . toBeDefined ( )
698+ } )
565699} )
566700
567701async function waitForChanges ( ms = 0 ) {
0 commit comments