import { screen } from "@testing-library/react-native";
import SimpleUploadBannerContainer from "components/MyObservations/SimpleUploadBannerContainer";
import React from "react";
import {
MANUAL_SYNC_IN_PROGRESS,
SYNC_PENDING
} from "stores/createSyncObservationsSlice.ts";
import {
UPLOAD_COMPLETE,
UPLOAD_IN_PROGRESS,
UPLOAD_PENDING
} from "stores/createUploadObservationsSlice.ts";
import useStore, { zustandStorage } from "stores/useStore";
import { renderComponent } from "tests/helpers/render";
import setStoreStateLayout from "tests/helpers/setStoreStateLayout";
const mockUser = {};
const deletionStore = {
currentDeleteCount: 1,
deleteQueue: [{}],
deleteError: null,
syncingStatus: SYNC_PENDING
};
beforeAll( ( ) => {
jest.useFakeTimers( );
} );
describe( "SimpleUploadBannerContainer", () => {
it( "displays syncing text before beginning uploads when sync button tapped", ( ) => {
useStore.setState( {
numUnuploadedObservations: 1,
uploadStatus: UPLOAD_PENDING,
syncingStatus: MANUAL_SYNC_IN_PROGRESS
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const statusText = screen.getByText( /Syncing.../ );
expect( statusText ).toBeVisible( );
} );
it( "displays a pending upload", ( ) => {
useStore.setState( {
uploadStatus: UPLOAD_PENDING,
syncingStatus: SYNC_PENDING
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent(
);
const statusText = screen.getByText( /Upload 1 observation/ );
expect( statusText ).toBeVisible( );
} );
it( "displays an upload in progress", ( ) => {
useStore.setState( {
initialNumObservationsInQueue: 1,
numUploadsAttempted: 1,
uploadStatus: UPLOAD_IN_PROGRESS,
syncingStatus: SYNC_PENDING
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const statusText = screen.getByText( /Uploading 1 observation/ );
expect( statusText ).toBeVisible( );
} );
it( "displays a completed upload", () => {
const numUploadsAttempted = 1;
useStore.setState( {
numUploadsAttempted,
uploadStatus: UPLOAD_COMPLETE,
syncingStatus: SYNC_PENDING,
initialNumObservationsInQueue: numUploadsAttempted
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const statusText = screen.getByText( /1 observation uploaded/ );
expect( statusText ).toBeVisible( );
} );
it( "displays multiple pending uploads", () => {
useStore.setState( {
uploadStatus: UPLOAD_PENDING,
syncingStatus: SYNC_PENDING
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent(
);
const statusText = screen.getByText( /Upload 4 observations/ );
expect( statusText ).toBeVisible( );
} );
it( "displays multiple uploads in progress", () => {
useStore.setState( {
uploadStatus: UPLOAD_IN_PROGRESS,
numUploadsAttempted: 2,
syncingStatus: SYNC_PENDING,
initialNumObservationsInQueue: 5
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const statusText = screen.getByText( /Uploading 2 of 5 observations/ );
expect( statusText ).toBeVisible( );
} );
it( "displays multiple completed uploads", () => {
const numUploadsAttempted = 7;
useStore.setState( {
numUploadsAttempted,
uploadStatus: UPLOAD_COMPLETE,
syncingStatus: SYNC_PENDING,
initialNumObservationsInQueue: numUploadsAttempted
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const statusText = screen.getByText( /7 observations uploaded/ );
expect( statusText ).toBeVisible( );
} );
it( "displays 1 upload completed and 4 failed", () => {
useStore.setState( {
numUploadsAttempted: 5,
uploadStatus: UPLOAD_COMPLETE,
syncingStatus: SYNC_PENDING,
initialNumObservationsInQueue: 5,
errorsByUuid: {
1: true,
2: true,
3: true,
4: true
}
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const successText = screen.getByText( /1 observation uploaded/ );
const errorText = screen.getByText( /4 uploads failed/ );
expect( successText ).toBeVisible( );
expect( errorText ).toBeVisible( );
} );
it( "displays only error when all 5 uploads failed", () => {
useStore.setState( {
uploadStatus: UPLOAD_COMPLETE,
syncingStatus: SYNC_PENDING,
initialNumObservationsInQueue: 5,
numUploadsAttempted: 5,
errorsByUuid: {
1: true,
2: true,
3: true,
4: true,
5: true
}
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const errorText = screen.getByText( /5 uploads failed/ );
expect( errorText ).toBeVisible();
const successText = screen.queryByText( /1 observation uploaded/ );
expect( successText ).toBeFalsy();
} );
it( "displays 4 uploads completed and 1 failed", () => {
useStore.setState( {
uploadStatus: UPLOAD_COMPLETE,
syncingStatus: SYNC_PENDING,
initialNumObservationsInQueue: 5,
numUploadsAttempted: 5,
errorsByUuid: { 1: true }
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const successText = screen.getByText( /4 observations uploaded/ );
const errorText = screen.getByText( /1 upload failed/ );
expect( successText ).toBeVisible();
expect( errorText ).toBeVisible();
} );
// 20240611 amanda - removing this test for now, since I believe the new intended UI
// is that the user will only ever see "Syncing..." followed by
// "1 observation deleted" UI after deleting a local observation. feel free to reinstate this
// test if I'm misunderstanding the UI
// it( "displays deletions in progress", async () => {
// useStore.setState( {
// ...deletionStore,
// syncingStatus: HANDLING_LOCAL_DELETIONS
// } );
// renderComponent( );
// const statusText = screen.getByText( /Deleting 1 of 1 observation/ );
// expect( statusText ).toBeVisible( );
// } );
it( "displays deletions completed", () => {
useStore.setState( {
...deletionStore,
currentDeleteCount: 1,
deleteQueue: [{}],
initialNumDeletionsInQueue: 1
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const statusText = screen.getByText( /1 observation deleted/ );
expect( statusText ).toBeVisible( );
} );
it( "displays deletion error", ( ) => {
const deleteError = "Unknown problem deleting observations";
useStore.setState( {
...deletionStore,
deleteError,
initialNumDeletionsInQueue: 2
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent( );
const deletingText = screen.getByText( /Deleting/ );
expect( deletingText ).toBeVisible( );
const statusText = screen.getByText( deleteError );
expect( statusText ).toBeVisible( );
} );
it( "should hide banner if logged out and only one observation", ( ) => {
zustandStorage.setItem( "numOfUserObservations", 1 );
useStore.setState( {
uploadStatus: UPLOAD_PENDING,
syncingStatus: SYNC_PENDING,
numOfUserObservations: 1
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent(
);
const statusText = screen.queryByText( /Upload 1 observation/ );
expect( statusText ).toBeFalsy( );
} );
it( "should show banner if logged out with more than one observation", ( ) => {
zustandStorage.setItem( "numOfUserObservations", 2 );
useStore.setState( {
uploadStatus: UPLOAD_PENDING,
syncingStatus: SYNC_PENDING
} );
setStoreStateLayout( {
isDefaultMode: false
} );
renderComponent(
);
const statusText = screen.getByText( /Upload 1 observation/ );
expect( statusText ).toBeVisible( );
} );
} );