@@ -8,7 +8,7 @@ import PageModel, { Page } from "@/models/Page";
88import Course from "@/models/Course" ;
99import CommunityModel from "@/models/Community" ;
1010import constants from "@/config/constants" ;
11- import { deleteMedia } from "@/services/medialit" ;
11+ import { deleteMedia , sealMedia } from "@/services/medialit" ;
1212import GQLContext from "@/models/GQLContext" ;
1313import { responses } from "@/config/strings" ;
1414
@@ -844,6 +844,92 @@ describe("Media cleanup", () => {
844844 expect ( deleteMedia ) . not . toHaveBeenCalledWith ( media1 ) ;
845845 } ) ;
846846
847+ it ( "sets draftSocialImage to null when socialImage is null" , async ( ) => {
848+ const page = await PageModel . create ( {
849+ domain : ctx . subdomain . _id ,
850+ pageId : "update-clears-draft-social-image" ,
851+ type : constants . site ,
852+ creatorId : "creator-1" ,
853+ name : "Update Clears Draft Social Image" ,
854+ layout : [ ] ,
855+ draftLayout : [ ] ,
856+ draftSocialImage : mediaObj1 ,
857+ } ) ;
858+
859+ await updatePage ( {
860+ context : ctx ,
861+ pageId : page . pageId ,
862+ socialImage : null ,
863+ } ) ;
864+
865+ const refreshedPage = await PageModel . findOne ( {
866+ _id : page . _id ,
867+ } ) ;
868+
869+ expect ( refreshedPage ?. draftSocialImage ) . toBeNull ( ) ;
870+ expect ( deleteMedia ) . toHaveBeenCalledWith ( media1 ) ;
871+ } ) ;
872+
873+ it ( "does NOT delete the cleared draftSocialImage if published socialImage still uses it" , async ( ) => {
874+ const page = await PageModel . create ( {
875+ domain : ctx . subdomain . _id ,
876+ pageId : "update-clears-draft-but-protects-published-social" ,
877+ type : constants . site ,
878+ creatorId : "creator-1" ,
879+ name : "Update Clears Draft But Protects Published Social" ,
880+ layout : [ ] ,
881+ draftLayout : [ ] ,
882+ socialImage : mediaObj1 ,
883+ draftSocialImage : mediaObj1 ,
884+ } ) ;
885+
886+ await updatePage ( {
887+ context : ctx ,
888+ pageId : page . pageId ,
889+ socialImage : null ,
890+ } ) ;
891+
892+ const refreshedPage = await PageModel . findOne ( {
893+ _id : page . _id ,
894+ } ) ;
895+
896+ expect ( refreshedPage ?. draftSocialImage ) . toBeNull ( ) ;
897+ expect ( deleteMedia ) . not . toHaveBeenCalledWith ( media1 ) ;
898+ } ) ;
899+
900+ it ( "does not delete the existing draftSocialImage when sealing the new social image fails" , async ( ) => {
901+ const page = await PageModel . create ( {
902+ domain : ctx . subdomain . _id ,
903+ pageId : "update-social-image-seal-failure" ,
904+ type : constants . site ,
905+ creatorId : "creator-1" ,
906+ name : "Update Social Image Seal Failure" ,
907+ layout : [ ] ,
908+ draftLayout : [ ] ,
909+ draftSocialImage : mediaObj1 ,
910+ } ) ;
911+
912+ ( sealMedia as jest . Mock ) . mockRejectedValueOnce (
913+ new Error ( "seal failed" ) ,
914+ ) ;
915+
916+ await expect (
917+ updatePage ( {
918+ context : ctx ,
919+ pageId : page . pageId ,
920+ socialImage : mediaObj2 as any ,
921+ } ) ,
922+ ) . rejects . toThrow ( "seal failed" ) ;
923+
924+ expect ( deleteMedia ) . not . toHaveBeenCalledWith ( media1 ) ;
925+
926+ const refreshedPage = await PageModel . findOne ( {
927+ _id : page . _id ,
928+ } ) ;
929+
930+ expect ( refreshedPage ?. draftSocialImage ?. mediaId ) . toBe ( media1 ) ;
931+ } ) ;
932+
847933 it ( "handles multiple media in a single widget" , async ( ) => {
848934 const page = await PageModel . create ( {
849935 domain : ctx . subdomain . _id ,
@@ -1091,6 +1177,29 @@ describe("Media cleanup", () => {
10911177 expect ( deleteMedia ) . not . toHaveBeenCalledWith ( media1 ) ;
10921178 } ) ;
10931179
1180+ it ( "clears published socialImage when draftSocialImage is null" , async ( ) => {
1181+ const page = await PageModel . create ( {
1182+ domain : ctx . subdomain . _id ,
1183+ pageId : "publish-clears-social-image" ,
1184+ type : constants . site ,
1185+ creatorId : "creator-1" ,
1186+ name : "Publish Clears Social Image" ,
1187+ layout : [ ] ,
1188+ draftLayout : [ ] ,
1189+ socialImage : mediaObj1 ,
1190+ draftSocialImage : null ,
1191+ } ) ;
1192+
1193+ await publish ( page . pageId , ctx ) ;
1194+
1195+ const refreshedPage = await PageModel . findOne ( {
1196+ _id : page . _id ,
1197+ } ) ;
1198+
1199+ expect ( refreshedPage ?. socialImage ) . toBeUndefined ( ) ;
1200+ expect ( deleteMedia ) . toHaveBeenCalledWith ( media1 ) ;
1201+ } ) ;
1202+
10941203 it ( "handles publishing with empty draftLayout - media is deleted" , async ( ) => {
10951204 // Note: When draftLayout is empty, the layout is NOT copied (checked via `if (page.draftLayout.length)`)
10961205 // However, the media diff computation still happens: currentPublished - nextPublished
0 commit comments