mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-06-18 20:50:54 -04:00
* Rename for consistency with obs photos * Refactor to be similar to obs photos * Include Sound as type * Revert "Include Sound as type" This reverts commit3db88ae031. * Revert "Refactor to be similar to obs photos" This reverts commit8ed7454be0. * Revert "Rename for consistency with obs photos" This reverts commit674b921bab. * Git mv without changes * Add types * Type api sound param * Type fields s const * Type fields as const * Type api param * Type new param * The only call site of this function passes in only defined strings * Adapted from Photo check for local path before deleting * Type fct params * Refactor constructor to only have a uri as param * Refactor Sound constructor to have string as param * Update Sound.ts * Remove unused param * Type fct params * Type realm * Also collect unsyncedSounds * Create operations for sound uploads based on Sound only * Add Evidence type * Change a sound upload operation to work with a RealmSound * Update realmSync to also just pass through Sounds * Use server ID for attaching obs_sound to obs * Also split photo pipeline for clarity This is not a functional change. Also previously, only RealmPhoto s are uploaded, only RealmObservationPhoto s are attached or modified. Same as for sounds now. * Update realmSync.ts * Remove log * Update realmSync.test.js * Update mocks * Update Sound map test * Update prepareMediaForUpload.test.js * Update prepareMediaForUpload.test.js * Update mediaUploader.test.js
149 lines
5.1 KiB
JavaScript
149 lines
5.1 KiB
JavaScript
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 );
|
|
} );
|
|
} );
|