Add basic working unit tests

This commit is contained in:
Brandon Presley 2022-10-30 12:56:58 +13:00
parent cc97c760bb
commit 6e75614d10
19 changed files with 10926 additions and 76 deletions

View File

@ -8,7 +8,7 @@ import {useColorScheme} from 'react-native';
import {
DarkTheme as PaperDarkTheme,
DefaultTheme as PaperDefaultTheme,
Provider,
Provider as PaperProvider,
} from 'react-native-paper';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import {Color} from './color';
@ -75,7 +75,7 @@ const App = () => {
return (
<Color.Provider value={{color, setColor}}>
<Provider
<PaperProvider
theme={theme}
settings={{icon: props => <MaterialIcon {...props} />}}>
<NavigationContainer theme={theme}>
@ -87,7 +87,7 @@ const App = () => {
)}
</MassiveSnack>
</NavigationContainer>
</Provider>
</PaperProvider>
</Color.Provider>
);
};

View File

@ -12,7 +12,6 @@ import Page from './Page';
import Set from './set';
import {defaultSet, getSets, getToday} from './set.service';
import SetItem from './SetItem';
import {useSettings} from './use-settings';
const limit = 15;
@ -22,27 +21,22 @@ export default function SetList() {
const [offset, setOffset] = useState(0);
const [term, setTerm] = useState('');
const [end, setEnd] = useState(false);
const {settings} = useSettings();
const navigation = useNavigation<NavigationProp<HomePageParams>>();
const refresh = useCallback(
async (value: string) => {
const todaysSet = await getToday();
if (todaysSet) setSet({...todaysSet});
const newSets = await getSets({
term: `%${value}%`,
limit,
offset: 0,
format: settings.date || '%Y-%m-%d %H:%M',
});
console.log(`${SetList.name}.refresh:`, {first: newSets[0]});
if (newSets.length === 0) return setSets([]);
setSets(newSets);
setOffset(0);
setEnd(false);
},
[settings.date],
);
const refresh = useCallback(async (value: string) => {
const todaysSet = await getToday();
if (todaysSet) setSet({...todaysSet});
const newSets = await getSets({
term: `%${value}%`,
limit,
offset: 0,
});
console.log(`${SetList.name}.refresh:`, {first: newSets[0]});
if (newSets.length === 0) return setSets([]);
setSets(newSets);
setOffset(0);
setEnd(false);
}, []);
useFocusEffect(
useCallback(() => {

View File

@ -47,7 +47,7 @@ export default function StartPlan() {
setCounts(newCounts);
console.log(`${StartPlan.name}.focus:`, {newCounts});
});
}, [params]),
}, [workouts]),
);
const handleSubmit = async () => {
@ -101,7 +101,7 @@ export default function StartPlan() {
setUnit(newBest.unit);
setBest(newBest);
},
[name, workouts],
[name, counts],
);
return (

View File

@ -10,10 +10,10 @@ import {WorkoutsPageParams} from './WorkoutsPage';
export default function WorkoutItem({
item,
onRemoved,
onRemove,
}: {
item: Set;
onRemoved: () => void;
onRemove: () => void;
}) {
const [showMenu, setShowMenu] = useState(false);
const [anchor, setAnchor] = useState({x: 0, y: 0});
@ -24,8 +24,8 @@ export default function WorkoutItem({
const remove = useCallback(async () => {
await deleteSetsBy(item.name);
setShowMenu(false);
onRemoved();
}, [setShowMenu, onRemoved, item.name]);
onRemove();
}, [setShowMenu, onRemove, item.name]);
const longPress = useCallback(
(e: GestureResponderEvent) => {

View File

@ -43,11 +43,7 @@ export default function WorkoutList() {
const renderItem = useCallback(
({item}: {item: Set}) => (
<WorkoutItem
item={item}
key={item.name}
onRemoved={() => refresh(term)}
/>
<WorkoutItem item={item} key={item.name} onRemove={() => refresh(term)} />
),
[refresh, term],
);

View File

@ -1,14 +0,0 @@
/**
* @format
*/
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
renderer.create(<App />);
});

View File

@ -0,0 +1,15 @@
import {render, screen} from '@testing-library/react-native';
import React from 'react';
import 'react-native';
import BestList from '../BestList';
import {MockProviders} from '../mock-providers';
it('renders correctly', () => {
render(
<MockProviders>
<BestList />
</MockProviders>,
);
expect(screen.getByText('Best')).toBeDefined();
expect(screen.getByPlaceholderText('Search')).toBeDefined();
});

View File

@ -0,0 +1,26 @@
import {render, screen} from '@testing-library/react-native';
import React from 'react';
import 'react-native';
import {MockProviders} from '../mock-providers';
import {Plan} from '../plan';
import PlanItem from '../PlanItem';
const plan: Plan = {
days: 'Monday,Tuesday,Wednesday',
workouts: 'Bench press,Bicep curls,Overhead press',
};
it('renders correctly', () => {
const onRemove = jest.fn();
render(
<MockProviders>
<PlanItem item={plan} onRemove={onRemove} />
</MockProviders>,
);
expect(screen.getByText(/Monday/i)).toBeDefined();
expect(screen.getByText(/Tuesday/i)).toBeDefined();
expect(screen.getByText(/Wednesday/i)).toBeDefined();
expect(screen.getByText(/Bench press/i)).toBeDefined();
expect(screen.getByText(/Bicep curls/i)).toBeDefined();
expect(screen.getByText(/Overhead press/i)).toBeDefined();
});

View File

@ -0,0 +1,15 @@
import {render, screen} from '@testing-library/react-native';
import React from 'react';
import 'react-native';
import {MockProviders} from '../mock-providers';
import PlanList from '../PlanList';
it('renders correctly', () => {
render(
<MockProviders>
<PlanList />
</MockProviders>,
);
expect(screen.getByText('Plans')).toBeDefined();
expect(screen.getByPlaceholderText('Search')).toBeDefined();
});

View File

@ -0,0 +1,26 @@
import {render, screen} from '@testing-library/react-native';
import React from 'react';
import 'react-native';
import {MockProviders} from '../mock-providers';
import Set from '../set';
import SetItem from '../SetItem';
const set: Set = {
name: 'Bench press',
reps: 6,
weight: 20,
};
it('renders correctly', () => {
const onRemove = jest.fn();
render(
<MockProviders>
<SetItem item={set} onRemove={onRemove} />
</MockProviders>,
);
expect(screen.getByText(set.name)).toBeDefined();
const reps = RegExp(set.reps.toString());
expect(screen.getByText(reps)).toBeDefined();
const weight = RegExp(set.weight.toString());
expect(screen.getByText(weight)).toBeDefined();
});

View File

@ -0,0 +1,15 @@
import {render, screen} from '@testing-library/react-native';
import React from 'react';
import 'react-native';
import {MockProviders} from '../mock-providers';
import SetList from '../SetList';
it('renders correctly', () => {
render(
<MockProviders>
<SetList />
</MockProviders>,
);
expect(screen.getByText('Home')).toBeDefined();
expect(screen.getByPlaceholderText('Search')).toBeDefined();
});

View File

@ -0,0 +1,27 @@
import {render, screen} from '@testing-library/react-native';
import React from 'react';
import 'react-native';
import {MockProviders} from '../mock-providers';
import Set from '../set';
import WorkoutItem from '../WorkoutItem';
const set: Set = {
name: 'Bench press',
reps: 6,
weight: 20,
seconds: 40,
minutes: 3,
sets: 5,
};
it('renders correctly', () => {
const onRemove = jest.fn();
render(
<MockProviders>
<WorkoutItem item={set} onRemove={onRemove} />
</MockProviders>,
);
expect(screen.getByText(set.name)).toBeDefined();
const sets = RegExp(set.sets?.toString() || '');
expect(screen.getByText(sets)).toBeDefined();
});

View File

@ -0,0 +1,15 @@
import {render, screen} from '@testing-library/react-native';
import React from 'react';
import 'react-native';
import {MockProviders} from '../mock-providers';
import WorkoutList from '../WorkoutList';
it('renders correctly', () => {
render(
<MockProviders>
<WorkoutList />
</MockProviders>,
);
expect(screen.getByText('Workouts')).toBeDefined();
expect(screen.getByPlaceholderText('Search')).toBeDefined();
});

View File

@ -1,6 +1,9 @@
#!/bin/sh
set -ex
yarn tsc
yarn lint
yarn test
git push origin HEAD > /dev/null &
cd android || exit 1
build=app/build.gradle

View File

@ -7,5 +7,8 @@ module.exports = {
transformIgnorePatterns: [
'node_modules/(?!(jest-)?@?react-native|@react-native-community|@react-navigation)',
],
setupFiles: ['./jestSetup.ts'],
setupFiles: [
'./node_modules/react-native-gesture-handler/jestSetup',
'./jestSetup.ts',
],
};

View File

@ -1,21 +1,29 @@
import 'react-native-gesture-handler/jestSetup';
import {NativeModules as RNNativeModules} from 'react-native';
RNNativeModules.UIManager = RNNativeModules.UIManager || {};
RNNativeModules.UIManager.RCTView = RNNativeModules.UIManager.RCTView || {};
RNNativeModules.RNGestureHandlerModule =
RNNativeModules.RNGestureHandlerModule || {
State: {BEGAN: 'BEGAN', FAILED: 'FAILED', ACTIVE: 'ACTIVE', END: 'END'},
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
};
RNNativeModules.PlatformConstants = RNNativeModules.PlatformConstants || {
forceTouchAvailable: false,
};
//RNNativeModules.UIManager = RNNativeModules.UIManager || {};
//RNNativeModules.UIManager.RCTView = RNNativeModules.UIManager.RCTView || {};
//RNNativeModules.RNGestureHandlerModule =
// RNNativeModules.RNGestureHandlerModule || {
// State: {BEGAN: 'BEGAN', FAILED: 'FAILED', ACTIVE: 'ACTIVE', END: 'END'},
// attachGestureHandler: jest.fn(),
// createGestureHandler: jest.fn(),
// dropGestureHandler: jest.fn(),
// updateGestureHandler: jest.fn(),
// };
//RNNativeModules.PlatformConstants = RNNativeModules.PlatformConstants || {
// forceTouchAvailable: false,
//};
RNNativeModules.RNViewShot = RNNativeModules.RNViewShot || {
captureScreen: jest.fn(),
};
jest.mock('react-native-file-access', () => jest.fn());
jest.mock('react-native-share', () => jest.fn());
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
jest.useFakeTimers();
jest.mock('react-native-reanimated', () => {
const Reanimated = require('react-native-reanimated/mock');
Reanimated.default.call = () => {};
return Reanimated;
});

29
mock-providers.tsx Normal file
View File

@ -0,0 +1,29 @@
import {NavigationContainer} from '@react-navigation/native';
import React from 'react';
import {Provider as PaperProvider} from 'react-native-paper';
import {Color} from './color';
import {lightColors} from './colors';
import MassiveSnack from './MassiveSnack';
import {defaultSettings, SettingsContext} from './use-settings';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
const color = lightColors[0].hex;
export const setColor = jest.fn();
const settings = defaultSettings;
export const setSettings = jest.fn();
export const MockProviders = ({
children,
}: {
children: JSX.Element | JSX.Element[];
}) => (
<Color.Provider value={{color, setColor}}>
<PaperProvider settings={{icon: props => <MaterialIcon {...props} />}}>
<SettingsContext.Provider value={{settings, setSettings}}>
<MassiveSnack>
<NavigationContainer>{children}</NavigationContainer>
</MassiveSnack>
</SettingsContext.Provider>
</PaperProvider>
</Color.Provider>
);

View File

@ -1,24 +1,27 @@
import React, {useContext} from 'react';
import Settings from './settings';
export const defaultSettings: Settings = {
alarm: 0,
color: '',
date: '',
images: 1,
notify: 0,
showDate: 0,
showSets: 1,
showUnit: 1,
sound: '',
steps: 0,
theme: 'system',
vibrate: 1,
noSound: 0,
};
export const SettingsContext = React.createContext<{
settings: Settings;
setSettings: (value: Settings) => void;
}>({
settings: {
alarm: 0,
color: '',
date: '',
images: 1,
notify: 0,
showDate: 0,
showSets: 1,
showUnit: 1,
sound: '',
steps: 0,
theme: 'system',
vibrate: 1,
},
settings: defaultSettings,
setSettings: () => null,
});

10689
yarn.lock Normal file

File diff suppressed because it is too large Load Diff