import safeRealmWrite from "sharedHelpers/safeRealmWrite"; import { markRecordUploaded } from "uploaders"; jest.mock( "sharedHelpers/safeRealmWrite" ); describe( "markRecordUploaded", () => { let mockRealm; let mockObservation; let mockObsPhoto; let mockObsSound; let mockPhoto; let mockSound; let mockResponse; beforeEach( () => { jest.clearAllMocks(); mockObsPhoto = { uuid: "photo123", id: null, _synced_at: null }; mockObsSound = { uuid: "sound123", id: null, _synced_at: null }; mockPhoto = { id: null, _synced_at: null }; mockSound = { id: null, _synced_at: null }; mockObservation = { uuid: "obs123", id: null, _synced_at: null, needs_sync: true, observationPhotos: [mockObsPhoto], observationSounds: [mockObsSound], }; mockResponse = { results: [{ id: 12345 }], }; mockRealm = { isClosed: false, objectForPrimaryKey: jest.fn().mockReturnValue( mockObservation ), }; // Mock the safeRealmWrite implementation safeRealmWrite.mockImplementation( ( realm, callback ) => { callback(); } ); } ); test( "should do nothing if realm is closed", () => { mockRealm.isClosed = true; markRecordUploaded( mockObservation.uuid, null, "Observation", mockResponse, mockRealm ); expect( safeRealmWrite ).not.toHaveBeenCalled(); } ); test( "should update an Observation record correctly", () => { markRecordUploaded( "obs123", null, "Observation", mockResponse, mockRealm ); expect( mockRealm.objectForPrimaryKey ).toHaveBeenCalledWith( "Observation", "obs123" ); expect( safeRealmWrite ).toHaveBeenCalledTimes( 1 ); expect( mockObservation.id ).toBe( 12345 ); expect( mockObservation._synced_at ).toBeInstanceOf( Date ); expect( mockObservation.needs_sync ).toBe( false ); } ); test( "should update an ObservationPhoto record correctly", () => { markRecordUploaded( "obs123", "photo123", "ObservationPhoto", mockResponse, mockRealm ); expect( mockRealm.objectForPrimaryKey ).toHaveBeenCalledWith( "Observation", "obs123" ); expect( safeRealmWrite ).toHaveBeenCalledTimes( 1 ); expect( mockObsPhoto.id ).toBe( 12345 ); expect( mockObsPhoto._synced_at ).toBeInstanceOf( Date ); // needs_sync should not be modified for ObservationPhoto expect( mockObsPhoto.needs_sync ).toBeUndefined(); } ); test( "should update an ObservationSound record correctly", () => { markRecordUploaded( "obs123", "sound123", "ObservationSound", mockResponse, mockRealm ); expect( mockRealm.objectForPrimaryKey ).toHaveBeenCalledWith( "Observation", "obs123" ); expect( safeRealmWrite ).toHaveBeenCalledTimes( 1 ); expect( mockObsSound.id ).toBe( 12345 ); expect( mockObsSound._synced_at ).toBeInstanceOf( Date ); // needs_sync should not be modified for ObservationSound expect( mockObsSound.needs_sync ).toBeUndefined(); } ); test( "should update a Photo record correctly with options.record", () => { const options = { record: mockPhoto }; markRecordUploaded( "obs123", null, "Photo", mockResponse, mockRealm, options ); expect( safeRealmWrite ).toHaveBeenCalledTimes( 1 ); expect( mockPhoto.id ).toBe( 12345 ); expect( mockPhoto._synced_at ).toBeInstanceOf( Date ); } ); test( "should update a Sound record correctly with options.record", () => { const options = { record: mockSound }; markRecordUploaded( "obs123", null, "Sound", mockResponse, mockRealm, options ); expect( safeRealmWrite ).toHaveBeenCalledTimes( 1 ); expect( mockSound.id ).toBe( 12345 ); expect( mockSound._synced_at ).toBeInstanceOf( Date ); } ); test( "should throw error when record is not found", () => { expect( () => { markRecordUploaded( "obs123", "nonexistent", "ObservationPhoto", mockResponse, mockRealm ); } ).toThrow( "Cannot find local Realm object to mark as updated" ); } ); test( "should retry on invalidated object error", () => { safeRealmWrite.mockImplementationOnce( () => { throw new Error( "Object has been invalidated or deleted" ); } ); markRecordUploaded( "obs123", null, "Observation", mockResponse, mockRealm ); expect( mockRealm.objectForPrimaryKey ).toHaveBeenCalledTimes( 2 ); expect( safeRealmWrite ).toHaveBeenCalledTimes( 2 ); expect( mockObservation.id ).toBe( 12345 ); expect( mockObservation._synced_at ).toBeInstanceOf( Date ); expect( mockObservation.needs_sync ).toBe( false ); } ); test( "should attempt to retry on non-invalidation errors", () => { // Mock safeRealmWrite to throw a non-invalidation error safeRealmWrite.mockImplementationOnce( ( realm, callback, description ) => { const error = new Error( "Some other error" ); error.message = `${description}: ${error.message}`; throw error; } ); expect( () => { markRecordUploaded( "obs123", null, "Observation", mockResponse, mockRealm ); } ).toThrow( /Some other error/ ); // Only called once because error doesn't match invalidated pattern expect( safeRealmWrite ).toHaveBeenCalledTimes( 1 ); } ); } );