@@ -1012,7 +1012,9 @@ describe(`On-Demand Sync Mode`, () => {
10121012 const productA = electronicsQuery . toArray . find (
10131013 ( p ) => p . name === `Product A` ,
10141014 )
1015- await db . execute ( `DELETE FROM products WHERE id = ?` , [ productA ! . id ] )
1015+
1016+ const tx = collection . delete ( productA ! . id )
1017+ await tx . isPersisted . promise
10161018
10171019 await vi . waitFor (
10181020 ( ) => {
@@ -1023,6 +1025,351 @@ describe(`On-Demand Sync Mode`, () => {
10231025
10241026 const names = electronicsQuery . toArray . map ( ( p ) => p . name ) . sort ( )
10251027 expect ( names ) . toEqual ( [ `Product B` , `Product D` ] )
1028+
1029+ // Verify the delete operation was recorded in the ps_crud table
1030+ const crud = await db . getAll < { id : number ; data : string ; tx_id : number } > (
1031+ `SELECT * FROM ps_crud` ,
1032+ )
1033+
1034+ const lastEntry = crud [ crud . length - 1 ] !
1035+ const parsed = JSON . parse ( lastEntry . data )
1036+ expect ( parsed . op ) . toBe ( `DELETE` )
1037+ expect ( parsed . id ) . toBe ( productA ! . id )
1038+ } )
1039+
1040+ it ( `should handle INSERT of a matching row` , async ( ) => {
1041+ const db = await createDatabase ( )
1042+ await createTestProducts ( db )
1043+
1044+ const collection = createCollection (
1045+ powerSyncCollectionOptions ( {
1046+ database : db ,
1047+ table : APP_SCHEMA . props . products ,
1048+ syncMode : `on-demand` ,
1049+ } ) ,
1050+ )
1051+ onTestFinished ( ( ) => collection . cleanup ( ) )
1052+ await collection . stateWhenReady ( )
1053+
1054+ const electronicsQuery = createLiveQueryCollection ( {
1055+ query : ( q ) =>
1056+ q
1057+ . from ( { product : collection } )
1058+ . where ( ( { product } ) => eq ( product . category , `electronics` ) )
1059+ . select ( ( { product } ) => ( {
1060+ id : product . id ,
1061+ name : product . name ,
1062+ price : product . price ,
1063+ category : product . category ,
1064+ } ) ) ,
1065+ } )
1066+ onTestFinished ( ( ) => electronicsQuery . cleanup ( ) )
1067+
1068+ await electronicsQuery . preload ( )
1069+
1070+ await vi . waitFor (
1071+ ( ) => {
1072+ expect ( electronicsQuery . size ) . toBe ( 3 )
1073+ } ,
1074+ { timeout : 2000 } ,
1075+ )
1076+
1077+ // Insert a new electronics product via the collection
1078+ const newId = randomUUID ( )
1079+ const tx = collection . insert ( {
1080+ id : newId ,
1081+ name : `New Gadget` ,
1082+ price : 99 ,
1083+ category : `electronics` ,
1084+ } )
1085+ await tx . isPersisted . promise
1086+
1087+ await vi . waitFor (
1088+ ( ) => {
1089+ expect ( electronicsQuery . size ) . toBe ( 4 )
1090+ } ,
1091+ { timeout : 2000 } ,
1092+ )
1093+
1094+ const names = electronicsQuery . toArray . map ( ( p ) => p . name ) . sort ( )
1095+ expect ( names ) . toContain ( `New Gadget` )
1096+
1097+ // Verify the insert operation was recorded in the ps_crud table
1098+ const crud = await db . getAll < { id : number ; data : string ; tx_id : number } > (
1099+ `SELECT * FROM ps_crud` ,
1100+ )
1101+
1102+ const lastEntry = crud [ crud . length - 1 ] !
1103+ const parsed = JSON . parse ( lastEntry . data )
1104+ expect ( parsed . op ) . toBe ( `PUT` )
1105+ expect ( parsed . id ) . toBe ( newId )
1106+ } )
1107+
1108+ it ( `should handle UPDATE of a matching row` , async ( ) => {
1109+ const db = await createDatabase ( )
1110+ await createTestProducts ( db )
1111+
1112+ const collection = createCollection (
1113+ powerSyncCollectionOptions ( {
1114+ database : db ,
1115+ table : APP_SCHEMA . props . products ,
1116+ syncMode : `on-demand` ,
1117+ } ) ,
1118+ )
1119+ onTestFinished ( ( ) => collection . cleanup ( ) )
1120+ await collection . stateWhenReady ( )
1121+
1122+ const electronicsQuery = createLiveQueryCollection ( {
1123+ query : ( q ) =>
1124+ q
1125+ . from ( { product : collection } )
1126+ . where ( ( { product } ) => eq ( product . category , `electronics` ) )
1127+ . select ( ( { product } ) => ( {
1128+ id : product . id ,
1129+ name : product . name ,
1130+ price : product . price ,
1131+ category : product . category ,
1132+ } ) ) ,
1133+ } )
1134+ onTestFinished ( ( ) => electronicsQuery . cleanup ( ) )
1135+
1136+ await electronicsQuery . preload ( )
1137+
1138+ await vi . waitFor (
1139+ ( ) => {
1140+ expect ( electronicsQuery . size ) . toBe ( 3 )
1141+ } ,
1142+ { timeout : 2000 } ,
1143+ )
1144+
1145+ // Update Product A via the collection
1146+ const productA = electronicsQuery . toArray . find (
1147+ ( p ) => p . name === `Product A` ,
1148+ )
1149+
1150+ const tx = collection . update ( productA ! . id , ( d ) => {
1151+ d . price = 999
1152+ } )
1153+ await tx . isPersisted . promise
1154+
1155+ await vi . waitFor (
1156+ ( ) => {
1157+ const product = electronicsQuery . toArray . find (
1158+ ( p ) => p . name === `Product A` ,
1159+ )
1160+ expect ( product ) . toBeDefined ( )
1161+ expect ( product ! . price ) . toBe ( 999 )
1162+ } ,
1163+ { timeout : 2000 } ,
1164+ )
1165+
1166+ // Verify the update operation was recorded in the ps_crud table
1167+ const crud = await db . getAll < { id : number ; data : string ; tx_id : number } > (
1168+ `SELECT * FROM ps_crud` ,
1169+ )
1170+
1171+ const lastEntry = crud [ crud . length - 1 ] !
1172+ const parsed = JSON . parse ( lastEntry . data )
1173+ expect ( parsed . op ) . toBe ( `PATCH` )
1174+ expect ( parsed . id ) . toBe ( productA ! . id )
1175+ } )
1176+
1177+ it ( `should handle DELETE when read from collection by id` , async ( ) => {
1178+ const db = await createDatabase ( )
1179+ await createTestProducts ( db )
1180+
1181+ const collection = createCollection (
1182+ powerSyncCollectionOptions ( {
1183+ database : db ,
1184+ table : APP_SCHEMA . props . products ,
1185+ syncMode : `on-demand` ,
1186+ } ) ,
1187+ )
1188+ onTestFinished ( ( ) => collection . cleanup ( ) )
1189+ await collection . stateWhenReady ( )
1190+
1191+ const productA = await db . get < { id : string } > (
1192+ `SELECT id FROM products WHERE name = 'Product A'` ,
1193+ )
1194+
1195+ const electronicsQuery = createLiveQueryCollection ( {
1196+ query : ( q ) =>
1197+ q
1198+ . from ( { product : collection } )
1199+ . where ( ( { product } ) => eq ( product . id , productA . id ) )
1200+ . select ( ( { product } ) => ( {
1201+ id : product . id ,
1202+ name : product . name ,
1203+ price : product . price ,
1204+ category : product . category ,
1205+ } ) ) ,
1206+ } )
1207+ onTestFinished ( ( ) => electronicsQuery . cleanup ( ) )
1208+
1209+ await electronicsQuery . preload ( )
1210+
1211+ await vi . waitFor (
1212+ ( ) => {
1213+ expect ( electronicsQuery . size ) . toBe ( 1 )
1214+ } ,
1215+ { timeout : 2000 } ,
1216+ )
1217+
1218+ // Delete Product A
1219+ const tx = collection . delete ( productA . id )
1220+ await tx . isPersisted . promise
1221+
1222+ await vi . waitFor (
1223+ ( ) => {
1224+ expect ( electronicsQuery . size ) . toBe ( 0 )
1225+ } ,
1226+ { timeout : 2000 } ,
1227+ )
1228+
1229+ const names = electronicsQuery . toArray . map ( ( p ) => p . name ) . sort ( )
1230+ expect ( names ) . toEqual ( [ ] )
1231+
1232+ // Verify the delete operation was recorded in the ps_crud table
1233+ const crud = await db . getAll < { id : number ; data : string ; tx_id : number } > (
1234+ `SELECT * FROM ps_crud` ,
1235+ )
1236+
1237+ const lastEntry = crud [ crud . length - 1 ] !
1238+ const parsed = JSON . parse ( lastEntry . data )
1239+ expect ( parsed . op ) . toBe ( `DELETE` )
1240+ expect ( parsed . id ) . toBe ( productA . id )
1241+ } )
1242+
1243+ it ( `should handle INSERT when loaded by id` , async ( ) => {
1244+ const db = await createDatabase ( )
1245+
1246+ const collection = createCollection (
1247+ powerSyncCollectionOptions ( {
1248+ database : db ,
1249+ table : APP_SCHEMA . props . products ,
1250+ syncMode : `on-demand` ,
1251+ } ) ,
1252+ )
1253+ onTestFinished ( ( ) => collection . cleanup ( ) )
1254+ await collection . stateWhenReady ( )
1255+
1256+ const newId = randomUUID ( )
1257+
1258+ const idQuery = createLiveQueryCollection ( {
1259+ query : ( q ) =>
1260+ q
1261+ . from ( { product : collection } )
1262+ . where ( ( { product } ) => eq ( product . id , newId ) )
1263+ . select ( ( { product } ) => ( {
1264+ id : product . id ,
1265+ name : product . name ,
1266+ price : product . price ,
1267+ category : product . category ,
1268+ } ) ) ,
1269+ } )
1270+ onTestFinished ( ( ) => idQuery . cleanup ( ) )
1271+
1272+ await idQuery . preload ( )
1273+
1274+ await vi . waitFor (
1275+ ( ) => {
1276+ expect ( idQuery . size ) . toBe ( 0 )
1277+ } ,
1278+ { timeout : 2000 } ,
1279+ )
1280+
1281+ // Insert a new product via the collection
1282+ const tx = collection . insert ( {
1283+ id : newId ,
1284+ name : `New Product` ,
1285+ price : 99 ,
1286+ category : `electronics` ,
1287+ } )
1288+ await tx . isPersisted . promise
1289+
1290+ await vi . waitFor (
1291+ ( ) => {
1292+ expect ( idQuery . size ) . toBe ( 1 )
1293+ } ,
1294+ { timeout : 2000 } ,
1295+ )
1296+
1297+ // Verify the insert operation was recorded in the ps_crud table
1298+ const crud = await db . getAll < { id : number ; data : string ; tx_id : number } > (
1299+ `SELECT * FROM ps_crud` ,
1300+ )
1301+
1302+ const lastEntry = crud [ crud . length - 1 ] !
1303+ const parsed = JSON . parse ( lastEntry . data )
1304+ expect ( parsed . op ) . toBe ( `PUT` )
1305+ expect ( parsed . id ) . toBe ( newId )
1306+ } )
1307+
1308+ it ( `should handle UPDATE when read from collection by id` , async ( ) => {
1309+ const db = await createDatabase ( )
1310+ await createTestProducts ( db )
1311+
1312+ const collection = createCollection (
1313+ powerSyncCollectionOptions ( {
1314+ database : db ,
1315+ table : APP_SCHEMA . props . products ,
1316+ syncMode : `on-demand` ,
1317+ } ) ,
1318+ )
1319+ onTestFinished ( ( ) => collection . cleanup ( ) )
1320+ await collection . stateWhenReady ( )
1321+
1322+ const productA = await db . get < { id : string } > (
1323+ `SELECT id FROM products WHERE name = 'Product A'` ,
1324+ )
1325+
1326+ const idQuery = createLiveQueryCollection ( {
1327+ query : ( q ) =>
1328+ q
1329+ . from ( { product : collection } )
1330+ . where ( ( { product } ) => eq ( product . id , productA . id ) )
1331+ . select ( ( { product } ) => ( {
1332+ id : product . id ,
1333+ name : product . name ,
1334+ price : product . price ,
1335+ category : product . category ,
1336+ } ) ) ,
1337+ } )
1338+ onTestFinished ( ( ) => idQuery . cleanup ( ) )
1339+
1340+ await idQuery . preload ( )
1341+
1342+ await vi . waitFor (
1343+ ( ) => {
1344+ expect ( idQuery . size ) . toBe ( 1 )
1345+ } ,
1346+ { timeout : 2000 } ,
1347+ )
1348+
1349+ // Update Product A via the collection
1350+ const tx = collection . update ( productA . id , ( d ) => {
1351+ d . price = 999
1352+ } )
1353+ await tx . isPersisted . promise
1354+
1355+ await vi . waitFor (
1356+ ( ) => {
1357+ const product = idQuery . toArray [ 0 ]
1358+ expect ( product ) . toBeDefined ( )
1359+ expect ( product ! . price ) . toBe ( 999 )
1360+ } ,
1361+ { timeout : 2000 } ,
1362+ )
1363+
1364+ // Verify the update operation was recorded in the ps_crud table
1365+ const crud = await db . getAll < { id : number ; data : string ; tx_id : number } > (
1366+ `SELECT * FROM ps_crud` ,
1367+ )
1368+
1369+ const lastEntry = crud [ crud . length - 1 ] !
1370+ const parsed = JSON . parse ( lastEntry . data )
1371+ expect ( parsed . op ) . toBe ( `PATCH` )
1372+ expect ( parsed . id ) . toBe ( productA . id )
10261373 } )
10271374 } )
10281375
0 commit comments