Files
iNaturalistReactNative/tests/unit/helpers/uploadObservation.test.js
Ken-ichi a7a2e1c10f Show up-to-date metadata for observations immediately after upload (#1497)
This fetches a remote copy of each observation after upload to make sure the
client has the freshest copy of the data immediately.
2024-05-06 17:50:46 -07:00

119 lines
4.6 KiB
JavaScript

import inatjs from "inaturalistjs";
import uploadObservation from "sharedHelpers/uploadObservation";
import factory, { makeResponse } from "tests/factory";
// Mock JWT so uploadObservation will act like it's authenticated
jest.mock( "components/LoginSignUp/AuthenticationService", ( ) => ( {
getJWT: jest.fn( ( ) => "test-json-web-token" )
} ) );
// Mock safeRealmWrite b/c this function writes to realm
jest.mock( "sharedHelpers/safeRealmWrite", ( ) => jest.fn( ) );
// Mock fetches, since this helper will try to fetch the most up-to-date copy
// of the obs after POSTing
inatjs.observations.fetch.mockImplementation(
uuid => makeResponse( [factory( "RemoteObservation", { uuid } )] )
);
// Mock upsert, but only upsert. It should happen but we don't care if it
// works in a unit test
jest.mock( "realmModels/Observation", () => {
const actual = jest.requireActual( "realmModels/Observation" );
actual.default.upsertRemoteObservations = jest.fn( );
return actual;
} );
// This function also tries to retrieve records from Realm. If your test needs
// this to fetch a specific record, you'll need to change the mock
// implementation here
const realm = {
objectForPrimaryKey: jest.fn( ( _modelName, _primaryKey ) => factory( "LocalObservation" ) )
};
function makeObservationWithPhotos( ) {
const mockObservationPhoto = factory( "LocalObservationPhoto" );
const mockObservation = factory( "LocalObservation", {
observationPhotos: [mockObservationPhoto]
} );
return mockObservation;
}
function makeObservationWithSounds( ) {
const mockObservationSound = factory( "LocalObservationSound" );
const mockObservation = factory( "LocalObservation", {
observationSounds: [mockObservationSound]
} );
return mockObservation;
}
describe( "uploadObservation", ( ) => {
beforeEach( ( ) => {
inatjs.observations.create.mockReset( );
inatjs.observation_photos.create.mockReset( );
inatjs.observation_sounds.create.mockReset( );
inatjs.photos.create.mockReset( );
inatjs.sounds.create.mockReset( );
} );
it( "should call inatjs.observations.create", async ( ) => {
const mockObservation = factory( "LocalObservation" );
await uploadObservation( mockObservation );
expect( inatjs.observations.create ).toHaveBeenCalledTimes( 1 );
} );
it( "should call inatjs.photos.create for an obs w/ photos", async ( ) => {
await uploadObservation( makeObservationWithPhotos( ) );
expect( inatjs.photos.create ).toHaveBeenCalledTimes( 1 );
} );
it( "should call inatjs.observation_photos.create for an obs w/ photos", async ( ) => {
inatjs.observations.create.mockResolvedValue(
makeResponse( [factory( "RemoteObservation" )] )
);
await uploadObservation( makeObservationWithPhotos( ), realm );
expect( inatjs.observation_photos.create ).toHaveBeenCalledTimes( 1 );
} );
it( "should not call inatjs.photos.create for an obs w/o photos", async ( ) => {
await uploadObservation( factory( "LocalObservation" ) );
expect( inatjs.photos.create ).not.toHaveBeenCalled( );
} );
it( "should call inatjs.sounds.create for an obs w/ sounds", async ( ) => {
await uploadObservation( makeObservationWithSounds( ) );
expect( inatjs.sounds.create ).toHaveBeenCalledTimes( 1 );
} );
it( "should call inatjs.observation_sounds.create for an obs w/ sounds", async ( ) => {
inatjs.observations.create.mockResolvedValue(
makeResponse( [factory( "RemoteObservation" )] )
);
await uploadObservation( makeObservationWithSounds( ), realm );
expect( inatjs.observation_sounds.create ).toHaveBeenCalledTimes( 1 );
} );
it( "should not call inatjs.sounds.create for an obs w/o sounds", async ( ) => {
await uploadObservation( factory( "LocalObservation" ) );
expect( inatjs.sounds.create ).not.toHaveBeenCalled( );
} );
describe( "for an observation with updated photos", ( ) => {
it( "should call inatjs.observation_photos.update", async ( ) => {
const mockObservationPhoto = factory.states( "uploaded" )( "LocalObservationPhoto" );
mockObservationPhoto.needsSync.mockImplementation( ( ) => true );
const mockObservation = factory.states( "uploaded" )( "LocalObservation", {
observationPhotos: [mockObservationPhoto]
} );
const mockRemoteObservation = factory( "RemoteObservation" );
inatjs.observations.update.mockResolvedValue(
makeResponse( [mockRemoteObservation] )
);
inatjs.observations.fetch.mockResolvedValue(
makeResponse( [mockRemoteObservation] )
);
await uploadObservation( mockObservation, realm );
expect( inatjs.observation_photos.update ).toHaveBeenCalledTimes( 1 );
} );
} );
} );