Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(e2e): intégration detox, tests pour l'onboarding #111

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .detoxrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"testRunner": "jest",
"runnerConfig": "e2e/config.json",
"skipLegacyWorkersInjection": true,
"apps": {
"ios": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/monsuivipsy.app",
"build": "xcodebuild -workspace ios/monsuivipsy.xcworkspace -configuration Release -sdk iphonesimulator -scheme monsuivipsy -derivedDataPath ios/build",
"bundleId": "org.reactjs.native.example.monsuivipsy"
},
"android": {
"type": "android.apk",
"binaryPath": "SPECIFY_PATH_TO_YOUR_APP_BINARY"
}
},
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 13"
}
},
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "Pixel_3a_API_30_x86"
}
}
},
"configurations": {
"ios": {
"device": "simulator",
"app": "ios"
},
"android": {
"device": "emulator",
"app": "android"
}
}
}
2 changes: 2 additions & 0 deletions App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import {DiaryNotesProvider} from './src/context/diaryNotes';
import NPS from './src/services/NPS/NPS';
import VersionChecker from './src/services/versionChecker';
import {Sentry} from 'react-native-sentry';
import { LogBox } from 'react-native';

if (!__DEV__) {
LogBox.ignoreAllLogs();
Sentry.config(
'https://9f0bd8f8af8444eea9f470d00a1bb411@sentry.fabrique.social.gouv.fr/54',
).install();
Expand Down
9 changes: 9 additions & 0 deletions e2e/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"maxWorkers": 1,
"testEnvironment": "./environment",
"testRunner": "jest-circus/runner",
"testTimeout": 120000,
"testRegex": "\\.e2e\\.js$",
"reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true
}
23 changes: 23 additions & 0 deletions e2e/environment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const {
DetoxCircusEnvironment,
SpecReporter,
WorkerAssignReporter,
} = require('detox/runners/jest-circus');

class CustomDetoxEnvironment extends DetoxCircusEnvironment {
constructor(config, context) {
super(config, context);

// Can be safely removed, if you are content with the default value (=300000ms)
this.initTimeout = 300000;

// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
// This is strictly optional.
this.registerListeners({
SpecReporter,
WorkerAssignReporter,
});
}
}

module.exports = CustomDetoxEnvironment;
98 changes: 98 additions & 0 deletions e2e/onboarding.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
describe('Onboarding', () => {
beforeAll(async () => {
await device.launchApp({ permissions: { notifications: 'YES' } });
});

beforeEach(async () => {
await device.reloadReactNative();
});

it('Presentation', async () => {
await expect(element(by.id('screen-0'))).toBeVisible();

await expect(element(by.id('scroll-view'))).toBeVisible();

await element(by.id('scroll-view')).swipe('left', 'fast');
await expect(element(by.id('screen-1'))).toBeVisible();
await element(by.id('scroll-view')).swipe('left', 'fast');
await expect(element(by.id('screen-2'))).toBeVisible();
await element(by.id('scroll-view')).swipe('left', 'fast');
await expect(element(by.id('screen-3'))).toBeVisible();

await element(by.id('scroll-view')).swipe('right', 'fast');
await expect(element(by.id('screen-2'))).toBeVisible();
await element(by.id('scroll-view')).swipe('right', 'fast');
await expect(element(by.id('screen-1'))).toBeVisible();

await element(by.id('next-button')).tap();
await expect(element(by.id('screen-2'))).toBeVisible();
await element(by.id('next-button')).tap();
await expect(element(by.id('screen-3'))).toBeVisible();

try { // check button disabled
await element(by.id('start-button')).tap();
await expect(element(by.id('__unknown'))).toBeVisible();
} catch(e) {}

await element(by.id('check-box')).tap();

await element(by.id('start-button')).tap();
});

it('Supported', async () => {
await element(by.id('not-followed-button')).tap();
});

it('Symptoms', async () => {
await element(by.id('scroll-view')).scrollTo('bottom');

try { // check button disabled
await element(by.id('validate-button')).tap();
await expect(element(by.id('__unknown'))).toBeVisible();
} catch(e) {}

await element(by.id('scroll-view')).scrollTo('top');

await element(by.id('check-box-mood')).tap();
await element(by.id('check-box-anxiety')).tap();

await element(by.id('custom-input')).typeText('Custom');
await element(by.id('custom-add-button')).tap();
await expect(element(by.text('Custom'))).toBeVisible();

await element(by.id('scroll-view')).scrollTo('bottom');

await element(by.id('validate-button')).tap();
});

it('Drugs', async () => {
await element(by.id('add-drugs-button')).tap();

await waitFor(element(by.text('Champix'))).toBeVisible().whileElement(by.id('scroll-view')).scroll(300, 'down', 0.5, 0.7);

await element(by.id('check-box-champix')).tap();

await waitFor(element(by.text('Deroxat'))).toBeVisible().whileElement(by.id('scroll-view')).scroll(300, 'down', 0.5, 0.7);

await element(by.id('check-box-deroxat')).tap();

await element(by.id('validate-button')).tap();

await expect(element(by.id('drug-item-deroxat'))).toBeVisible();
await expect(element(by.id('drug-item-champix'))).toBeVisible();

await element(by.id('continue-button')).tap();
});

it('Reminder', async () => {
await element(by.id('later-button')).tap();
});

it('Final check', async () => {
await element(by.id('main-button')).tap();
await element(by.id('day-button-0')).tap();
await expect(element(by.text('Humeur'))).toBeVisible();
await expect(element(by.text('Anxiété'))).toBeVisible();
await expect(element(by.text('Custom'))).toBeVisible();
});
});
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"ios:12promax": "react-native run-ios --simulator=\"iPhone 12 Pro Max\"",
"start": "react-native start --reset-cache",
"test": "jest",
"detox:ios": "detox build --configuration ios && detox test --configuration ios",
"lint": "eslint .",
"android:build-aab": "cd android && ./gradlew clean && ./gradlew bundleRelease && cd ../",
"postinstall": "pod install --project-directory=ios/ --repo-update && npx jetify -r",
Expand Down Expand Up @@ -63,8 +64,10 @@
"@babel/runtime": "^7.12.5",
"@react-native-community/eslint-config": "^2.0.0",
"babel-jest": "^26.6.3",
"detox": "^19.4.2",
"eslint": "7.32.0",
"jest": "^26.6.3",
"jest-circus": "^27.4.6",
"metro-react-native-babel-preset": "^0.66.0",
"react-native-codegen": "^0.0.12",
"react-native-svg-transformer": "^0.14.3",
Expand Down
5 changes: 4 additions & 1 deletion src/components/AddElemToList.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default ({
placeholder = 'Ajouter...',
styleContainer,
onChangeText = console.log,
testID
}) => {
const [value, setValue] = useState();

Expand All @@ -29,6 +30,7 @@ export default ({
placeholder={placeholder}
placeholderTextColor="lightgrey"
style={styles.text}
testID={testID ? testID+'-input' : undefined}
/>
</View>
<View style={styles.iconContainer}>
Expand All @@ -39,7 +41,8 @@ export default ({
onChange(value);
setValue('');
onChangeText('');
}}>
}}
testID={testID ? testID+'-add-button' : undefined}>
<CircledIcon
icon="PlusSvg"
color={colors.LIGHT_BLUE}
Expand Down
4 changes: 3 additions & 1 deletion src/components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const Button = ({
disabled = false,
buttonStyle,
textStyle,
testID,
}) => {
const color = disabled ? 'lightgrey' : buttonColor;
return (
Expand All @@ -53,7 +54,8 @@ const Button = ({
buttonStyle,
]}
onPress={onPress}
disabled={disabled}>
disabled={disabled}
testID={testID}>
<Text style={[{...styles.text, color: textColor || 'white'}, textStyle]}>
{title}
</Text>
Expand Down
9 changes: 7 additions & 2 deletions src/scenes/diary/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@ const Diary = ({navigation}) => {
else {
const isFirstAppLaunch = await localStorage.getIsFirstAppLaunch();
if (isFirstAppLaunch !== 'false') {
navigation.navigate('onboarding', {
screen: onboardingStep || 'OnboardingPresentation',
navigation.reset({
routes: [
{
name: 'onboarding',
params: {screen: onboardingStep || 'OnboardingPresentation'},
},
],
});
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/scenes/onboarding/onboarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const Onboarding = ({navigation}) => {
<Text style={styles.title}>
Mon Suivi Psy m'accompagne entre mes consultations
</Text>
<ScrollView contentContainerStyle={styles.scrollContainer}>
<ScrollView contentContainerStyle={styles.scrollContainer} testID="scroll-view">
<Swiper
onIndexChanged={(page) => {
// dirty hack because of this issue
Expand Down Expand Up @@ -84,6 +84,7 @@ const Onboarding = ({navigation}) => {
style={styles.checkbox}
value={isCguChecked}
onValueChange={(newValue) => setIsCguChecked(newValue)}
testID='check-box'
/>
<Text style={styles.textCgu}>
En cochant cette case, vous acceptez nos{' '}
Expand All @@ -106,18 +107,19 @@ const Onboarding = ({navigation}) => {
<Button
onPress={validateOnboarding}
title="Commencer"
testID="start-button"
disabled={!isCguChecked && firstTime}
/>
</View>
</>
) : (
<View style={styles.buttonWrapper}>
<Button title="Terminer" onPress={navigation.goBack} />
<Button title="Terminer" testID="done-button" onPress={navigation.goBack} />
</View>
)
) : (
<View style={styles.buttonWrapper}>
<Button title="Suivant" onPress={onPressNext} />
<Button title="Suivant" testID="next-button" onPress={onPressNext} />
</View>
)}
</View>
Expand Down
4 changes: 2 additions & 2 deletions src/scenes/onboarding/onboardingDrugs/drug-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {colors} from '../../../utils/colors';
import RNPickerSelect from 'react-native-picker-select';
import Icon from '../../../components/Icon';

export default ({drug, onChange, showPosology, onClose}) => {
export default ({drug, onChange, showPosology, onClose, testID}) => {
const [showFreeText, setShowFreeText] = useState(false);
const [freeText, setFreeText] = useState('');

Expand All @@ -28,7 +28,7 @@ export default ({drug, onChange, showPosology, onClose}) => {

const render = () => {
return (
<View style={styles.posologyItem}>
<View style={styles.posologyItem} testID={testID}>
<View style={styles.left}>
<TouchableOpacity style={styles.delete} onPress={onClose}>
<Icon icon="CrossSvg" width={8} height={8} color={colors.BLUE} />
Expand Down
4 changes: 3 additions & 1 deletion src/scenes/onboarding/onboardingDrugs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const Drugs = ({navigation, route}) => {
onChange={handleDrugChange}
showPosology={false}
onClose={() => handleDelete(e)}
testID={e.name1 ? 'drug-item-'+e.name1.trim().toLowerCase() : undefined}
/>
))}
<Text style={styles.addButton} onPress={handleAdd}>
Expand All @@ -143,7 +144,8 @@ const Drugs = ({navigation, route}) => {
<View style={styles.buttonWrapper}>
<TouchableOpacity
onPress={() => navigation.navigate('reminder', {onboarding: true})}
style={styles.setupButton}>
style={styles.setupButton}
testID='continue-button'>
<Text style={styles.setupButtonText}>Continuer</Text>
</TouchableOpacity>
</View>
Expand Down
8 changes: 6 additions & 2 deletions src/scenes/onboarding/onboardingDrugs/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ const Drugs = ({navigation, route}) => {
ref={scrollRef}
style={styles.container}
contentContainerStyle={styles.scrollContainer}
keyboardShouldPersistTaps="handled">
keyboardShouldPersistTaps="handled"
testID="scroll-view">
{!filteredList ? (
<Text>Chargement</Text>
) : (
Expand Down Expand Up @@ -198,14 +199,17 @@ const Drugs = ({navigation, route}) => {
style={styles.checkbox}
value={!!treatment.find((x) => x.id === e.id)}
onValueChange={(newValue) => setToogleCheckbox(e, newValue)}
testID={e.name1 ? "check-box-"+e.name1.trim().toLowerCase() : undefined}
/>
</View>
))}
</>
)}
</ScrollView>
<View style={styles.buttonWrapper}>
<Button onPress={handleSubmit} title="Valider" />
<Button onPress={handleSubmit} title="Valider"
testID='validate-button'
/>
</View>
</SafeAreaView>
);
Expand Down
1 change: 1 addition & 0 deletions src/scenes/onboarding/onboardingDrugs/no-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default ({navigation}) => {
title="Ajouter un traitement"
buttonStyle={styles.button}
textStyle={{fontSize: 14, fontWeight: 'bold'}}
testID='add-drugs-button'
/>
<TouchableOpacity onPress={handleDrugInformation}>
<Text style={styles.link}>Informations sur les traitements</Text>
Expand Down
Loading