@@ -840,6 +840,49 @@ describe.each([
840840 } ) ;
841841 } ) ;
842842
843+ test ( 'saveProvenance with null/undefined deletes existing provenance asset' , async ( ) => {
844+ storageEngine = new LocalStorageEngine ( true ) ;
845+ await storageEngine . connect ( ) ;
846+ await storageEngine . initializeStudyDb ( studyId ) ;
847+ sequenceArray = await generateSequenceArray ( configSimple ) ;
848+ const participantSession = await storageEngine . initializeParticipantSession ( { } , configSimple , participantMetadata ) ;
849+ const identifier = 'intro_0' ;
850+
851+ // First, save a provenance asset
852+ const provenanceGraph = {
853+ root : 'root' ,
854+ nodes : {
855+ root : {
856+ id : 'root' ,
857+ createdOn : 10 ,
858+ children : [ ] ,
859+ } ,
860+ } ,
861+ } ;
862+ await storageEngine . saveProvenance ( {
863+ aboveStimulus : undefined ,
864+ belowStimulus : undefined ,
865+ sidebar : undefined ,
866+ stimulus : provenanceGraph ,
867+ } , identifier ) ;
868+
869+ // Verify it was saved
870+ let storedProvenance = await storageEngine . getProvenance ( identifier , participantSession . participantId ) ;
871+ expect ( storedProvenance ) . toEqual ( {
872+ aboveStimulus : undefined ,
873+ belowStimulus : undefined ,
874+ sidebar : undefined ,
875+ stimulus : provenanceGraph ,
876+ } ) ;
877+
878+ // Now save with null — should delete the existing asset
879+ await storageEngine . saveProvenance ( null , identifier ) ;
880+
881+ // Verify it was deleted
882+ storedProvenance = await storageEngine . getProvenance ( identifier , participantSession . participantId ) ;
883+ expect ( storedProvenance ) . toBeNull ( ) ;
884+ } ) ;
885+
843886 test ( 'saveAnswers coalesces to the latest answer and finalizeParticipant persists completion after delayed writes' , async ( ) => {
844887 storageEngine = new DelayedLocalStorageEngine ( true ) ;
845888 await storageEngine . connect ( ) ;
0 commit comments