Add basic working unit tests
This commit is contained in:
parent
cc97c760bb
commit
6e75614d10
6
App.tsx
6
App.tsx
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
34
SetList.tsx
34
SetList.tsx
|
@ -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(() => {
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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],
|
||||
);
|
||||
|
|
|
@ -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 />);
|
||||
});
|
15
__tests__/BestList-test.tsx
Normal file
15
__tests__/BestList-test.tsx
Normal 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();
|
||||
});
|
26
__tests__/PlanItem-test.tsx
Normal file
26
__tests__/PlanItem-test.tsx
Normal 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();
|
||||
});
|
15
__tests__/PlanList-test.tsx
Normal file
15
__tests__/PlanList-test.tsx
Normal 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();
|
||||
});
|
26
__tests__/SetItem-test.tsx
Normal file
26
__tests__/SetItem-test.tsx
Normal 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();
|
||||
});
|
15
__tests__/SetList-test.tsx
Normal file
15
__tests__/SetList-test.tsx
Normal 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();
|
||||
});
|
27
__tests__/WorkoutItem-test.tsx
Normal file
27
__tests__/WorkoutItem-test.tsx
Normal 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();
|
||||
});
|
15
__tests__/WorkoutList-test.tsx
Normal file
15
__tests__/WorkoutList-test.tsx
Normal 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();
|
||||
});
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
],
|
||||
};
|
||||
|
|
34
jestSetup.ts
34
jestSetup.ts
|
@ -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
29
mock-providers.tsx
Normal 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>
|
||||
);
|
|
@ -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,
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user