mirror of https://gitlab.com/m3f_usm/SmartStopAPK
feat: rework remote config call + some code improvements
parent
9664a5bb2d
commit
a7a565ceb6
|
@ -5,14 +5,11 @@ import DevicesRepositoryImpl from '../../repositories/DevicesRepositoryImpl';
|
|||
import mockResponse from '../__mocks__/mockResponse.json';
|
||||
import {getNumber} from '../../../../__mocks__/@react-native-firebase/remote-config';
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
describe('useDevices tests', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
|
@ -24,7 +21,7 @@ describe('useDevices tests', () => {
|
|||
{
|
||||
lineNumber: '803010',
|
||||
description: 'Tucapel',
|
||||
locomotionType: 1,
|
||||
locomotionType: '1',
|
||||
backgroundColor: 'Hexadecimal',
|
||||
letterColor: 'Hexadecimal',
|
||||
lineMessage: '',
|
||||
|
@ -52,7 +49,7 @@ describe('useDevices tests', () => {
|
|||
{
|
||||
lineNumber: '5487',
|
||||
description: 'Centauro',
|
||||
locomotionType: 1,
|
||||
locomotionType: '1',
|
||||
backgroundColor: 'Hexadecimal',
|
||||
letterColor: 'Hexadecimal',
|
||||
lineMessage: 'Sin info. GPS, la informacion es estimada',
|
||||
|
@ -84,8 +81,6 @@ describe('useDevices tests', () => {
|
|||
stopNumber: '37477',
|
||||
stopName: "O'Higgins - entre Angol y Salas",
|
||||
});
|
||||
|
||||
getNumber.mockReturnValue(20000).mockReturnValue(60000);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
|
@ -139,7 +134,7 @@ describe('useDevices tests', () => {
|
|||
letterColor: 'Hexadecimal',
|
||||
lineMessage: '',
|
||||
lineNumber: '803010',
|
||||
locomotionType: 1,
|
||||
locomotionType: '1',
|
||||
},
|
||||
{
|
||||
arrivals: [
|
||||
|
@ -167,7 +162,7 @@ describe('useDevices tests', () => {
|
|||
letterColor: 'Hexadecimal',
|
||||
lineMessage: 'Sin info. GPS, la informacion es estimada',
|
||||
lineNumber: '5487',
|
||||
locomotionType: 1,
|
||||
locomotionType: '1',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
@ -176,6 +171,7 @@ describe('useDevices tests', () => {
|
|||
});
|
||||
|
||||
it('should refresh devices list after 20000 miliseconds', async () => {
|
||||
getNumber.mockReturnValue(20000);
|
||||
const mockDate = new Date('2023-01-01T00:01:00Z');
|
||||
const spy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
|
||||
jest
|
||||
|
@ -188,7 +184,9 @@ describe('useDevices tests', () => {
|
|||
expect(result.current.state.currentIndex).toBe(0);
|
||||
});
|
||||
|
||||
act(() => {
|
||||
jest.advanceTimersByTime(20000);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.state.currentIndex).toBe(22);
|
||||
|
@ -198,6 +196,7 @@ describe('useDevices tests', () => {
|
|||
});
|
||||
|
||||
it('should refresh devices list after 60000 miliseconds', async () => {
|
||||
getNumber.mockReturnValue(60000);
|
||||
const mockDate = new Date('2023-01-01T00:01:00Z');
|
||||
const spy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
|
||||
const spp = jest.spyOn(DevicesRepositoryImpl.prototype, 'getDeviceInfo');
|
||||
|
|
|
@ -48,20 +48,4 @@ describe('useRemoteconfig tests', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('get string', () => {
|
||||
it('should be defined', async () => {
|
||||
const {result} = renderHook(() => useRemoteConfig());
|
||||
|
||||
expect(result.current.getString).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return a value', async () => {
|
||||
getString.mockReturnValueOnce('someValue');
|
||||
|
||||
const {result} = renderHook(() => useRemoteConfig());
|
||||
|
||||
expect(result.current.getString('someKey')).toStrictEqual('someValue');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -30,7 +30,7 @@ const useDevices = () => {
|
|||
stopMessage: '',
|
||||
displayedLines: [],
|
||||
lines: [],
|
||||
stopName: 'Sin información - Sin información',
|
||||
stopName: '',
|
||||
});
|
||||
|
||||
const baseURL = remoteConfig().getString(RemoteConfigKeys.BASE_URL);
|
||||
|
@ -180,7 +180,7 @@ const useDevices = () => {
|
|||
status: Status.SUCCESS,
|
||||
},
|
||||
}));
|
||||
} catch (error) {
|
||||
} catch (error: unknown) {
|
||||
setState((prevState: State) => ({
|
||||
...prevState,
|
||||
status: Status.ERROR,
|
||||
|
@ -199,8 +199,8 @@ const useDevices = () => {
|
|||
authRepository,
|
||||
devicesRepository,
|
||||
password,
|
||||
username,
|
||||
updateBusesListInterval,
|
||||
username,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -212,8 +212,9 @@ const useDevices = () => {
|
|||
|
||||
const init = () => {
|
||||
setState(prevState => {
|
||||
const currentIndex = prevState.currentIndex || 1;
|
||||
const isGreatherThanLinesLength =
|
||||
(prevState.currentIndex || 1) + BUSES_BY_PAGE >= state.lines.length;
|
||||
currentIndex + BUSES_BY_PAGE >= state.lines.length;
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
|
@ -224,7 +225,7 @@ const useDevices = () => {
|
|||
};
|
||||
});
|
||||
|
||||
setTimeout(init, changePageInterval);
|
||||
timeout = setTimeout(init, changePageInterval);
|
||||
};
|
||||
|
||||
init();
|
||||
|
@ -232,7 +233,7 @@ const useDevices = () => {
|
|||
return () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}, [state.lines, state.status, changePageInterval]);
|
||||
}, [changePageInterval, state.lines.length]);
|
||||
|
||||
return {state};
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {useCallback, useEffect, useState} from 'react';
|
||||
import {useEffect, useState} from 'react';
|
||||
import remoteConfig from '@react-native-firebase/remote-config';
|
||||
import Status from '../../utils/Status';
|
||||
|
||||
|
@ -7,11 +7,6 @@ const ONE_HOUR = 3600000;
|
|||
const useRemoteConfig = () => {
|
||||
const [status, setStatus] = useState(Status.LOADING);
|
||||
|
||||
const getString = useCallback(
|
||||
(key: string) => remoteConfig().getString(key),
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
try {
|
||||
|
@ -29,11 +24,9 @@ const useRemoteConfig = () => {
|
|||
UPDATE_BUSES_LIST_INTERVAL: 0, // in miliseconds
|
||||
});
|
||||
|
||||
const isActivated = await remoteConfig().fetchAndActivate();
|
||||
await remoteConfig().fetchAndActivate();
|
||||
|
||||
if (isActivated) {
|
||||
setStatus(Status.SUCCESS);
|
||||
}
|
||||
} catch (error) {
|
||||
setStatus(Status.ERROR);
|
||||
}
|
||||
|
@ -42,7 +35,7 @@ const useRemoteConfig = () => {
|
|||
init();
|
||||
}, []);
|
||||
|
||||
return {status, getString};
|
||||
return {status};
|
||||
};
|
||||
|
||||
export default useRemoteConfig;
|
||||
|
|
|
@ -19,17 +19,33 @@ const ERROR_MESSAGE = 'Ha ocurrido un error';
|
|||
const EMPTY_MESSAGE = 'No buses available';
|
||||
|
||||
const BusList = ({buses, status, style}: BusListProps) => {
|
||||
if (status === Status.LOADING) {
|
||||
return (
|
||||
<View style={style}>
|
||||
<ActivityIndicator testID="LOADING" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (status === Status.ERROR) {
|
||||
return (
|
||||
<View style={style}>
|
||||
{status === Status.LOADING && <ActivityIndicator testID="LOADING" />}
|
||||
{status === Status.ERROR && (
|
||||
<Text style={styles.text}>{ERROR_MESSAGE}</Text>
|
||||
)}
|
||||
{status === Status.SUCCESS && buses.length === 0 ? (
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (status === Status.SUCCESS && buses.length === 0) {
|
||||
return (
|
||||
<View style={style}>
|
||||
<Text style={styles.text}>{EMPTY_MESSAGE}</Text>
|
||||
) : (
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={style}>
|
||||
<Table data={buses} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -36,8 +36,8 @@ const Header = ({title, subTitle, style, image}: HeaderProps) => {
|
|||
};
|
||||
|
||||
const defaultProps = {
|
||||
title: 'Sin información',
|
||||
subTitle: 'Sin información',
|
||||
title: '',
|
||||
subTitle: '',
|
||||
};
|
||||
|
||||
Header.defaultProps = defaultProps;
|
||||
|
|
|
@ -5,288 +5,6 @@ exports[`BusList tests should render correctly with status LOADING 1`] = `
|
|||
<ActivityIndicator
|
||||
testID="LOADING"
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "white",
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"borderColor": "grey",
|
||||
"borderWidth": 1,
|
||||
"flex": 1,
|
||||
"flexDirection": "column",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
|
|
|
@ -1,7 +1,28 @@
|
|||
import {SafeAreaView, StyleSheet} from 'react-native';
|
||||
import {ActivityIndicator, SafeAreaView, StyleSheet, Text} from 'react-native';
|
||||
import BusStopInfoScreen from './BusStopInfoScreen';
|
||||
import useRemoteConfig from '../../infraestructure/hooks/useRemoteConfig';
|
||||
import Status from '../../utils/Status';
|
||||
|
||||
const ERROR_MESSAGE = 'Ha ocurrido un error';
|
||||
|
||||
const App = () => {
|
||||
const {status} = useRemoteConfig();
|
||||
|
||||
if (status === Status.LOADING) {
|
||||
return (
|
||||
<SafeAreaView style={styles.centeredContainer}>
|
||||
<ActivityIndicator testID="LOADING" />
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
if (status === Status.ERROR) {
|
||||
return (
|
||||
<SafeAreaView style={styles.centeredContainer}>
|
||||
<Text>{ERROR_MESSAGE}</Text>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<BusStopInfoScreen />
|
||||
|
@ -13,6 +34,11 @@ const styles = StyleSheet.create({
|
|||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
centeredContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default App;
|
||||
|
|
|
@ -1,43 +1,25 @@
|
|||
import {ActivityIndicator, Image, StyleSheet, Text, View} from 'react-native';
|
||||
import {Image, StyleSheet, View} from 'react-native';
|
||||
import remoteConfig from '@react-native-firebase/remote-config';
|
||||
import Container from '../components/Container';
|
||||
import Header from '../components/Header';
|
||||
import useDevices from '../../infraestructure/hooks/useDevices';
|
||||
import Banner from '../components/Banner';
|
||||
import RemoteConfigKeys from '../../utils/RemoteConfigKeys';
|
||||
import BusList from '../components/BusList';
|
||||
import useRemoteConfig from '../../infraestructure/hooks/useRemoteConfig';
|
||||
import Status from '../../utils/Status';
|
||||
|
||||
const BANNER_TEXT = 'Buses que se detienen en esta parada';
|
||||
const ERROR_MESSAGE = 'Ha ocurrido un error';
|
||||
|
||||
const BusStopInfoScreen = () => {
|
||||
const {
|
||||
state: {status, displayedLines, stopName},
|
||||
} = useDevices();
|
||||
const {status: remoteConfigStatus, getString} = useRemoteConfig();
|
||||
|
||||
const image = getString(RemoteConfigKeys.HEADER_IMAGE_URL);
|
||||
const image = remoteConfig().getString(RemoteConfigKeys.HEADER_IMAGE_URL);
|
||||
|
||||
const [first, second] = stopName.split('-');
|
||||
const title = first ? first.trim() : '';
|
||||
const subTitle = second ? second.trim() : '';
|
||||
|
||||
if (remoteConfigStatus === Status.LOADING) {
|
||||
return (
|
||||
<Container style={styles.containerCenter}>
|
||||
<ActivityIndicator />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
if (remoteConfigStatus === Status.ERROR) {
|
||||
return (
|
||||
<Container style={styles.containerCenter}>
|
||||
<Text>{ERROR_MESSAGE}</Text>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container style={styles.container}>
|
||||
<Header
|
||||
|
@ -89,7 +71,7 @@ const styles = StyleSheet.create({
|
|||
flex: 1,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
resizeMode: 'contain',
|
||||
resizeMode: 'stretch',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import {render} from '@testing-library/react-native';
|
|||
import BusStopInfoScreen from '../BusStopInfoScreen';
|
||||
import * as useDevices from '../../../infraestructure/hooks/useDevices';
|
||||
import * as useRemoteConfig from '../../../infraestructure/hooks/useRemoteConfig';
|
||||
import {getString} from '../../../../__mocks__/@react-native-firebase/remote-config';
|
||||
|
||||
const mockState: useDevices.State = {
|
||||
status: 1,
|
||||
|
@ -576,6 +577,7 @@ describe('BusStopInfoScreen tests', () => {
|
|||
jest.spyOn(useDevices, 'default').mockReturnValue({
|
||||
state: mockState,
|
||||
});
|
||||
getString.mockReturnValue('https://www.google.com');
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
|
@ -585,7 +587,6 @@ describe('BusStopInfoScreen tests', () => {
|
|||
it('should render the screen with status loading', () => {
|
||||
jest.spyOn(useRemoteConfig, 'default').mockReturnValue({
|
||||
status: 0,
|
||||
getString: () => 'https://www.google.com',
|
||||
});
|
||||
const {toJSON} = render(<BusStopInfoScreen />);
|
||||
|
||||
|
@ -595,7 +596,6 @@ describe('BusStopInfoScreen tests', () => {
|
|||
it('should render the screen with status error', () => {
|
||||
jest.spyOn(useRemoteConfig, 'default').mockReturnValue({
|
||||
status: 2,
|
||||
getString: () => 'https://www.google.com',
|
||||
});
|
||||
|
||||
const {toJSON} = render(<BusStopInfoScreen />);
|
||||
|
@ -606,7 +606,6 @@ describe('BusStopInfoScreen tests', () => {
|
|||
it('should render the screen with status success', () => {
|
||||
jest.spyOn(useRemoteConfig, 'default').mockReturnValue({
|
||||
status: 1,
|
||||
getString: () => 'https://www.google.com',
|
||||
});
|
||||
const {toJSON} = render(<BusStopInfoScreen />);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue