Fakultas Ilmu Komputer UI

Commit e784aca0 authored by Jahns's avatar Jahns
Browse files

Merge branch 'pbi-11-lupa-password' into 'staging'

Pbi 11 lupa password

See merge request !4
parents 377ed196 adc44145
Pipeline #80994 passed with stage
in 34 minutes and 44 seconds
......@@ -28,6 +28,7 @@ import initialCacheState, {
} from 'contexts/AppContext/cache';
import { useMainService } from 'services'
import { Box, Text, Button, Gap } from 'components';
import ForgetPasswordPage from 'scenes/ForgetPasswordPage';
const StyledApp = styled.SafeAreaView`
height: 100%;
......@@ -284,6 +285,7 @@ const App = () => {
}}>
<Stack.Screen name="splash" component={Splash} />
<Stack.Screen name="login" component={LoginPage} />
<Stack.Screen name="forget-password" component={ForgetPasswordPage} />
<Stack.Screen name="home" component={Home} />
<Stack.Screen
name="contact-investigation-form/1"
......
......@@ -163,7 +163,7 @@ exports[`DatePicker tests renders correctly 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......
import 'react-native';
import axios from 'axios';
import React from 'react';
import { useMainService, LocalStorage } from 'services';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import ReactTestRenderer, { act } from 'react-test-renderer';
import ForgetPasswordPage from '.';
import { AppContext } from 'contexts';
const Stack = createStackNavigator();
const testProps = {
services: {
main: useMainService('dummyToken'),
},
alert: {
illustration: "",
message: "",
},
setAlert: (alert: string) => testProps.alert = alert,
shouldLoading: false,
setShouldLoading: (shouldLoading: boolean) => testProps.shouldLoading = shouldLoading,
cache: {},
}
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
it('renders correctly', () => {
const instance = ReactTestRenderer.create(
<NavigationContainer>
<Stack.Navigator
screenOptions={{
header: () => <></>,
}}>
<Stack.Screen name="forget-password" component={ForgetPasswordPage} />
</Stack.Navigator>
</NavigationContainer>,
);
expect(instance.toJSON()).toMatchSnapshot();
});
it('insert email correctly', async () => {
LocalStorage.setSecretKey("sssttt");
const instance = ReactTestRenderer.create(
<AppContext.Provider value={testProps}>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
header: () => <></>,
}}>
<Stack.Screen name="forget-password" component={ForgetPasswordPage} />
</Stack.Navigator>
</NavigationContainer>
</AppContext.Provider>,
);
expect(instance.toJSON()).toMatchSnapshot();
const emailField = instance.root.find(elem => elem.props.id === "email");
act(() => {
if (emailField) {
emailField.props.updateValue("email@email.com");
}
})
expect(instance).toBeTruthy();
mockedAxios.request.mockImplementationOnce(
() => new Promise(resolve => {
resolve({
status: 200,
data: [
"Password successfully changed"
],
});
})
);
const submit = instance.root.find(elem => elem.props.id === "submit");
await act(async () => {
submit.props.onPress();
})
expect(testProps.alert.message).toBe("Password berhasil diubah, silakan cek email anda.");
});
it('insert invalid email', async () => {
LocalStorage.setSecretKey("sssttt");
const instance = ReactTestRenderer.create(
<AppContext.Provider value={testProps}>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
header: () => <></>,
}}>
<Stack.Screen name="forget-password" component={ForgetPasswordPage} />
</Stack.Navigator>
</NavigationContainer>
</AppContext.Provider>,
);
expect(instance.toJSON()).toMatchSnapshot();
const emailField = instance.root.find(elem => elem.props.id === "email");
act(() => {
if (emailField) {
emailField.props.updateValue("beneranemail.com");
}
})
expect(instance).toBeTruthy();
const submit = instance.root.find(elem => elem.props.id === "submit");
await act(async () => {
submit.props.onPress();
})
expect(emailField.props.information).toBe("Masukkan email yang valid.");
});
it('insert email that does\'t exists in database', async () => {
LocalStorage.setSecretKey("sssttt");
const instance = ReactTestRenderer.create(
<AppContext.Provider value={testProps}>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
header: () => <></>,
}}>
<Stack.Screen name="forget-password" component={ForgetPasswordPage} />
</Stack.Navigator>
</NavigationContainer>
</AppContext.Provider>,
);
expect(instance.toJSON()).toMatchSnapshot();
const emailField = instance.root.find(elem => elem.props.id === "email");
act(() => {
if (emailField) {
emailField.props.updateValue("email@email.com");
}
})
expect(instance).toBeTruthy();
mockedAxios.request.mockImplementationOnce(
() => new Promise(resolve => {
resolve({
status: 400,
data: {
"error": "Account matching query does not exist."
},
});
})
);
const submit = instance.root.find(elem => elem.props.id === "submit");
await act(async () => {
submit.props.onPress();
})
expect(testProps.alert.message).toBe("Terjadi kesalahan, periksa kembali email anda.");
});
\ No newline at end of file
import { Box, Button, Cloud, Field, Gap, Text } from "components";
import styled from 'styled-components/native';
import React, { useContext, useState } from "react";
import { Image } from "react-native";
import WaveBackground from 'assets/arts/background-wave.png';
import WonderingIllustration from 'assets/illustrations/wondering.png';
import DoctorTeamIllustration from 'assets/illustrations/doctor-team.png';
import { useFormState } from "helpers";
import { AppContext } from "contexts";
enum ForgetPasswordResponse {
Success = 'Password berhasil diubah, silakan cek email anda.',
BadRequest = 'Terjadi kesalahan, periksa kembali email anda.',
UnknownServerError = 'Terjadi kesalahan pada server.',
NoInternetConn = 'Cek Konektivitas Internet',
}
const ForgetPasswordPage = () => {
const [isFirstTime, setIsFirstTime] = useState(true);
const { services, setAlert, shouldLoading, setShouldLoading } = useContext(AppContext);
const [form, setField] = useFormState({
email: {
type: 'EMAIL'
}
})
return (
<Box
axis={Box.Axis.Vertical}
height="100%"
width="100%"
background="transparent"
>
<Cloud
top="0px"
left="0px"
height="100%"
width="100%"
>
<Image
style={{
height: "100%",
width: "100%",
}}
source={WaveBackground}
/>
</Cloud>
<Container>
<FieldControl>
<Text isBold={true} fontSize='48px'>Lupa Password</Text>
</FieldControl>
<Gap gap={24} axis={Gap.Axis.Vertical} />
<FieldControl>
<Field
id="email"
name="Email"
placeholder="Masukkan email Anda."
information={
isFirstTime || form.fields.email.isValid
? ''
: 'Masukkan email yang valid.'
}
updateValue={val => setField('email', val)}>
</Field>
</FieldControl>
</Container>
<Action>
<Box>
<Button
id="submit"
type={Button.Type.Filled}
clickable={!shouldLoading}
onPress={async () => {
if (isFirstTime) {
setIsFirstTime(false);
}
if (form.isValid) {
setShouldLoading(true)
const forgetPassRes = await services.main.forgetPassword({
email: form.fields.email.value,
})
setShouldLoading(false)
if (forgetPassRes === undefined) {
setAlert({
illustration: WonderingIllustration,
message: ForgetPasswordResponse.NoInternetConn,
})
} else {
if (forgetPassRes.status === 200) {
setAlert({
illustration: DoctorTeamIllustration,
message: ForgetPasswordResponse.Success,
})
} else if (forgetPassRes.status === 400) {
setAlert({
illustration: WonderingIllustration,
message: ForgetPasswordResponse.BadRequest,
})
} else {
setAlert({
illustration: WonderingIllustration,
message: ForgetPasswordResponse.UnknownServerError,
})
}
}
}
}}
>Kirim Email Verifikasi</Button>
</Box>
</Action>
</Box>
)
}
const Container = styled.View`
width: 100%;
height: 55%;
padding: 0 32px;
justify-content: flex-end;
`;
const FieldControl = styled.View`
margin-bottom: 5%;
`;
const Action = styled.View`
position: relative;
display: flex;
flex-flow: column nowrap;
width: 100%;
padding: 0 32px;
flex-grow: 1;
`;
export default ForgetPasswordPage;
\ No newline at end of file
import React, {useContext, useState} from 'react';
import {AppContext} from 'contexts';
import React, { useContext, useState } from 'react';
import { AppContext } from 'contexts';
import styled from 'styled-components/native';
import {Image} from 'react-native';
import { Image } from 'react-native';
import {Box, Button, Text, Field, Cloud, Gap} from 'components';
import {useFormState} from 'helpers';
import {LocalStorage} from 'services';
import {useNavigation} from '@react-navigation/native';
import { Box, Button, Text, Field, Cloud, Gap } from 'components';
import { useFormState } from 'helpers';
import { LocalStorage } from 'services';
import { useNavigation } from '@react-navigation/native';
import WaveBackground from 'assets/arts/background-wave.png';
import WonderingIllustration from 'assets/illustrations/wondering.png';
......@@ -20,7 +20,7 @@ enum LoginResponse {
const LoginPage = () => {
const navigation = useNavigation();
const [isFirstTime, setIsFirstTime] = useState(true);
const {setToken, services, setAlert, shouldLoading, setShouldLoading} = useContext(AppContext);
const { setToken, services, setAlert, shouldLoading, setShouldLoading } = useContext(AppContext);
const [form, setField] = useFormState({
username: {
type: 'text',
......@@ -96,15 +96,15 @@ const LoginPage = () => {
setIsFirstTime(false);
}
if (form.isValid) {
setShouldLoading(true)
const loginRes = await services.main.login({
username: form.fields.username.value,
password: form.fields.password.value,
});
setShouldLoading(false)
if (loginRes === undefined) {
......@@ -133,6 +133,16 @@ const LoginPage = () => {
Masuk
</Button>
</Box>
<Gap axis={Gap.Axis.Vertical} gap={14}></Gap>
<Box>
<Button
id="forgetpass"
clickable={!shouldLoading}
type={Button.Type.Outline}
onPress={() => navigation.navigate('forget-password')}>
Lupa Password
</Button>
</Box>
<Line />
<Box>
<Button
......
......@@ -909,7 +909,7 @@ exports[`can press previous button 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -2365,7 +2365,7 @@ exports[`renders correctly 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -3821,7 +3821,7 @@ exports[`renders form with correct fields 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -5277,7 +5277,7 @@ exports[`submit data succesfully 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......
......@@ -663,7 +663,7 @@ exports[`can press previous button 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -881,7 +881,7 @@ exports[`can press previous button 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -2070,7 +2070,7 @@ exports[`renders correctly 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -2288,7 +2288,7 @@ exports[`renders correctly 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -3477,7 +3477,7 @@ exports[`renders form with correct fields 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -3695,7 +3695,7 @@ exports[`renders form with correct fields 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -4884,7 +4884,7 @@ exports[`submit data succesfully 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......@@ -5102,7 +5102,7 @@ exports[`submit data succesfully 1`] = `
]
}
>
10/5/2021
17/5/2021
</Text>
</View>
<View
......
......@@ -32,6 +32,25 @@ describe('Test API that needs token', () => {
expect(result.data).toMatchObject({token});
})
test('Forget Password', async () => {
const body = {
"email": "admin@admin.com"
}
mockedAxios.request.mockImplementationOnce(
() => new Promise(resolve => {
resolve({
status: 200,
data: "Password successfully changed"
});
})
);
const result = await withAuth.forgetPassword(body)
expect(result.status).toBe(200);
expect(result.data).toEqual("Password successfully changed");
})
test('Get current user profile', async () => {
const userProfile = {
"id": "d207657e-f0e6-4f9b-828e-af94fc654ca3",
......
......@@ -11,6 +11,7 @@ const END_POINTS = {
MONITORING_CASES: createEndpoint(["cases", "monitoring-cases"]),
LOGS: createEndpoint(["logs"]),
LOGIN: '/auth/token/',
FORGET_PASSWORD: '/accounts/set_random_password/',
};
enum Method {
......@@ -64,6 +65,10 @@ export default function useMainService(token: string) {
return fetchWithoutAuthentication(END_POINTS.LOGIN, Method.POST, body);
}
async function forgetPassword(body: object) {
return fetchWithoutAuthentication(END_POINTS.FORGET_PASSWORD, Method.POST, body);
}
async function me() {
const endPoint = END_POINTS.ACCOUNTS([
"me",
......@@ -259,6 +264,7 @@ export default function useMainService(token: string) {
return {
// Authentication
login,
forgetPassword,
createUser,
me,
// Contact Investigation Form
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment