Fakultas Ilmu Komputer UI
Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ppl-fasilkom-ui
2021
Kelas D
PT Gizi Sehat - Dietela
Dietela Mobile
Commits
48cdfb25
Commit
48cdfb25
authored
Apr 25, 2021
by
Wulan Mantiri
Committed by
Muzaki Azami
Apr 25, 2021
Browse files
Implement Checkout page layout and integrate with API
parent
16ed516f
Changes
26
Hide whitespace changes
Inline
Side-by-side
src/constants/cacheKeys.ts
View file @
48cdfb25
...
@@ -3,4 +3,5 @@ export default {
...
@@ -3,4 +3,5 @@ export default {
cartId
:
'
CART_ID
'
,
cartId
:
'
CART_ID
'
,
authToken
:
'
AUTH_TOKEN
'
,
authToken
:
'
AUTH_TOKEN
'
,
refreshToken
:
'
REFRESH_TOKEN
'
,
refreshToken
:
'
REFRESH_TOKEN
'
,
programRecommendations
:
'
PROGRAM_RECOMMENDATIONS
'
,
};
};
src/constants/navigation.ts
View file @
48cdfb25
import
*
as
ROUTES
from
'
constants/routes
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
{
import
{
AllAccessQuestionnaire
,
AllAccessQuestionnaire
,
Checkout
,
ChoosePlan
,
ChoosePlan
,
ComingSoonPage
,
ComingSoonPage
,
DietelaQuizResult
,
DietelaQuizResult
,
...
@@ -38,9 +39,9 @@ export const navigation: NavRoute[] = [
...
@@ -38,9 +39,9 @@ export const navigation: NavRoute[] = [
header
:
'
Choose Plan
'
,
header
:
'
Choose Plan
'
,
},
},
{
{
name
:
ROUTES
.
c
ar
t
,
name
:
ROUTES
.
c
heckou
t
,
component
:
C
omingSoonPage
,
component
:
C
heckout
,
header
:
'
C
ar
t
'
,
header
:
'
C
heckou
t
'
,
},
},
{
{
name
:
ROUTES
.
programDetail
,
name
:
ROUTES
.
programDetail
,
...
...
src/constants/routes.ts
View file @
48cdfb25
...
@@ -5,10 +5,10 @@ const questionnaire = 'questionnaire';
...
@@ -5,10 +5,10 @@ const questionnaire = 'questionnaire';
export
const
allAccessQuestionnaire
=
`
${
questionnaire
}
/all-access`
;
export
const
allAccessQuestionnaire
=
`
${
questionnaire
}
/all-access`
;
export
const
dietelaQuizResult
=
`
${
questionnaire
}
/dietela-quiz-result`
;
export
const
dietelaQuizResult
=
`
${
questionnaire
}
/dietela-quiz-result`
;
export
const
c
art
=
'
car
t
'
;
export
const
c
heckout
=
'
checkou
t
'
;
export
const
choosePlan
=
`
${
c
ar
t
}
/choose-plan`
;
export
const
choosePlan
=
`
${
c
heckou
t
}
/choose-plan`
;
export
const
programDetail
=
'
dietela-program
'
;
export
const
programDetail
=
`
${
checkout
}
/
dietela-program
`
;
export
const
nutritionistDetail
=
'
nutritionist
'
;
export
const
nutritionistDetail
=
`
${
checkout
}
/
nutritionist
`
;
export
const
registration
=
'
registration
'
;
export
const
registration
=
'
registration
'
;
export
const
login
=
'
login
'
;
export
const
login
=
'
login
'
;
...
...
src/hooks/index.ts
View file @
48cdfb25
export
{
default
as
useApi
}
from
'
./useApi
'
;
export
{
default
as
useApi
}
from
'
./useApi
'
;
export
{
default
as
useAuthEffect
}
from
'
./useAuthEffect
'
;
export
{
default
as
useAuthEffect
}
from
'
./useAuthEffect
'
;
export
{
default
as
useAuthGuardEffect
}
from
'
./useAuthGuardEffect
'
;
export
{
default
as
useForm
}
from
'
./useForm
'
;
export
{
default
as
useForm
}
from
'
./useForm
'
;
src/hooks/useAuthGuardEffect/index.ts
0 → 100644
View file @
48cdfb25
import
{
useContext
,
useEffect
}
from
'
react
'
;
import
{
useNavigation
}
from
'
@react-navigation/native
'
;
import
{
UserContext
}
from
'
provider
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
const
useAuthGuardEffect
=
()
=>
{
const
{
isAuthenticated
}
=
useContext
(
UserContext
);
const
navigation
=
useNavigation
();
useEffect
(()
=>
{
if
(
!
isAuthenticated
)
{
navigation
.
navigate
(
ROUTES
.
login
);
}
},
[
isAuthenticated
,
navigation
]);
};
export
default
useAuthGuardEffect
;
src/scenes/cart/Checkout/components/CheckoutCard/index.test.tsx
0 → 100644
View file @
48cdfb25
import
React
from
'
react
'
;
import
{
render
}
from
'
@testing-library/react-native
'
;
import
CheckoutCard
from
'
.
'
;
describe
(
'
CheckoutCard component
'
,
()
=>
{
it
(
'
for program renders correctly
'
,
()
=>
{
render
(
<
CheckoutCard
type
=
"program"
content
=
"yes"
onReadMore
=
{
jest
.
fn
()
}
/>,
);
});
it
(
'
for nutritionist renders correctly
'
,
()
=>
{
render
(
<
CheckoutCard
type
=
"nutritionist"
content
=
"yes"
onReadMore
=
{
jest
.
fn
()
}
/>,
);
});
});
src/scenes/cart/Checkout/components/CheckoutCard/index.tsx
0 → 100644
View file @
48cdfb25
import
React
,
{
FC
}
from
'
react
'
;
import
{
View
}
from
'
react-native
'
;
import
{
Text
,
Button
}
from
'
react-native-elements
'
;
import
{
Props
}
from
'
./types
'
;
import
{
styles
}
from
'
./styles
'
;
import
{
typographyStyles
,
colors
}
from
'
styles
'
;
const
CheckoutCard
:
FC
<
Props
>
=
({
content
,
type
,
onReadMore
})
=>
(
<
View
style
=
{
styles
.
container
}
>
<
Text
style
=
{
typographyStyles
.
overlineBig
}
>
Pilihan
{
type
===
'
program
'
?
'
Program
'
:
'
Nutrisionis
'
}
Anda
</
Text
>
<
Text
style
=
{
styles
.
title
}
>
{
type
===
'
program
'
?
'
📝
'
:
'
👩🏻⚕️
'
}
{
content
}
</
Text
>
<
Button
title
=
"Baca selengkapnya"
type
=
"clear"
icon
=
{
{
name
:
'
arrow-forward
'
,
size
:
22
,
color
:
colors
.
primary
,
}
}
onPress
=
{
onReadMore
}
iconRight
titleStyle
=
{
styles
.
readMore
}
buttonStyle
=
{
styles
.
buttonStyle
}
/>
</
View
>
);
export
default
CheckoutCard
;
src/scenes/cart/Checkout/components/CheckoutCard/styles.ts
0 → 100644
View file @
48cdfb25
import
{
StyleSheet
}
from
'
react-native
'
;
import
{
colors
,
typography
}
from
'
styles
'
;
export
const
styles
=
StyleSheet
.
create
({
container
:
{
borderWidth
:
2
,
borderRadius
:
6
,
padding
:
20
,
paddingBottom
:
15
,
marginTop
:
20
,
backgroundColor
:
colors
.
primaryYellow
,
borderColor
:
colors
.
primaryVariant
,
},
title
:
{
...
typography
.
headingMedium
,
marginVertical
:
15
,
},
readMore
:
{
color
:
colors
.
primary
,
},
buttonStyle
:
{
margin
:
0
,
padding
:
0
,
},
});
src/scenes/cart/Checkout/components/CheckoutCard/types.ts
0 → 100644
View file @
48cdfb25
export
interface
Props
{
type
:
'
program
'
|
'
nutritionist
'
;
content
:
string
;
onReadMore
:
()
=>
void
;
}
src/scenes/cart/Checkout/components/index.ts
0 → 100644
View file @
48cdfb25
export
{
default
as
CheckoutCard
}
from
'
./CheckoutCard
'
;
src/scenes/cart/Checkout/index.test.tsx
0 → 100644
View file @
48cdfb25
import
React
from
'
react
'
;
import
{
withAuthRender
,
waitFor
,
fireEvent
}
from
'
utils/testing
'
;
import
axios
from
'
axios
'
;
import
Checkout
from
'
.
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
CACHE_KEYS
from
'
constants/cacheKeys
'
;
import
{
DietelaProgram
}
from
'
services/dietelaQuiz/quizResult
'
;
import
{
setCache
}
from
'
utils/cache
'
;
import
{
mockProgramRecommendations
}
from
'
__mocks__/quizResult
'
;
jest
.
mock
(
'
axios
'
);
const
mockAxios
=
axios
as
jest
.
Mocked
<
typeof
axios
>
;
describe
(
'
Checkout
'
,
()
=>
{
const
nutritionist
=
{
id
:
1
,
full_name_and_degree
:
'
Wendy
'
,
registration_certificate_no
:
'
123
'
,
university
:
'
UI
'
,
mastered_nutritional_problems
:
'
diet
'
,
handled_age_group
:
'
18
'
,
another_practice_place
:
'
-
'
,
languages
:
'
English
'
,
};
const
retrieveCartApi
=
()
=>
Promise
.
resolve
({
status
:
200
,
data
:
{
id
:
1
,
program
:
{
id
:
1
,
unique_code
:
DietelaProgram
.
TRIAL
,
},
nutritionist
,
},
});
it
(
'
redirects to program detail page when user clicks Baca selengkapnya button for program
'
,
async
()
=>
{
await
setCache
(
CACHE_KEYS
.
cartId
,
1
);
mockAxios
.
request
.
mockImplementationOnce
(
retrieveCartApi
);
const
{
getAllByText
,
getByText
}
=
withAuthRender
(
<
Checkout
/>,
ROUTES
.
checkout
,
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
const
chosenProgram
=
getByText
(
/One Week Trial/i
);
expect
(
chosenProgram
).
toBeTruthy
();
const
readMoreButton
=
getAllByText
(
/Baca selengkapnya/i
)[
0
];
expect
(
readMoreButton
).
toBeTruthy
();
fireEvent
.
press
(
readMoreButton
);
const
programDetailPage
=
getByText
(
/Program Dietela/i
);
expect
(
programDetailPage
).
toBeTruthy
();
});
it
(
'
redirects to nutritionist detail page when user clicks Baca selengkapnya button for nutritionist
'
,
async
()
=>
{
mockAxios
.
request
.
mockImplementationOnce
(
retrieveCartApi
);
const
{
getAllByText
,
getByText
}
=
withAuthRender
(
<
Checkout
/>,
ROUTES
.
checkout
,
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
const
chosenNutritionist
=
getByText
(
/Wendy/i
);
expect
(
chosenNutritionist
).
toBeTruthy
();
const
readMoreButton
=
getAllByText
(
/Baca selengkapnya/i
)[
1
];
expect
(
readMoreButton
).
toBeTruthy
();
fireEvent
.
press
(
readMoreButton
);
const
nutritionistDetailPage
=
getByText
(
/Coming Soon/i
);
expect
(
nutritionistDetailPage
).
toBeTruthy
();
});
it
(
'
redirects to choose plan page when user clicks Ganti Pilihan button
'
,
async
()
=>
{
await
setCache
(
CACHE_KEYS
.
programRecommendations
,
JSON
.
stringify
(
mockProgramRecommendations
),
);
mockAxios
.
request
.
mockImplementationOnce
(
retrieveCartApi
);
const
{
getByText
}
=
withAuthRender
(<
Checkout
/>,
ROUTES
.
checkout
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
const
changePlanButton
=
getByText
(
/ganti pilihan/i
);
expect
(
changePlanButton
).
toBeTruthy
();
await
waitFor
(()
=>
fireEvent
.
press
(
changePlanButton
));
const
choosePlanPage
=
getByText
(
/Choose Plan/i
);
expect
(
choosePlanPage
).
toBeTruthy
();
});
afterAll
(()
=>
{
jest
.
clearAllMocks
();
});
});
src/scenes/cart/Checkout/index.tsx
0 → 100644
View file @
48cdfb25
import
React
,
{
FC
,
useCallback
}
from
'
react
'
;
import
{
View
}
from
'
react-native
'
;
import
{
Text
,
Button
}
from
'
react-native-elements
'
;
import
{
useNavigation
}
from
'
@react-navigation/native
'
;
import
{
Loader
,
BigButton
}
from
'
components/core
'
;
import
{
Section
}
from
'
components/layout
'
;
import
CACHE_KEYS
from
'
constants/cacheKeys
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
{
dietPrograms
}
from
'
constants/dietelaProgram
'
;
import
{
useApi
,
useAuthGuardEffect
}
from
'
hooks
'
;
import
{
retrieveCartApi
}
from
'
services/payment
'
;
import
{
getCache
}
from
'
utils/cache
'
;
import
{
typographyStyles
}
from
'
styles
'
;
import
{
styles
}
from
'
./styles
'
;
import
{
CheckoutCard
}
from
'
./components
'
;
const
Checkout
:
FC
=
()
=>
{
const
navigation
=
useNavigation
();
const
fetchCart
=
useCallback
(
async
()
=>
{
const
cartId
=
await
getCache
(
CACHE_KEYS
.
cartId
);
return
await
retrieveCartApi
(
cartId
);
},
[]);
const
{
isLoading
,
data
}
=
useApi
(
fetchCart
);
useAuthGuardEffect
();
if
(
isLoading
)
{
return
<
Loader
/>;
}
return
(
<
View
style
=
{
styles
.
container
}
>
<
View
>
<
CheckoutCard
content
=
{
data
?
dietPrograms
[
data
.
program
.
unique_code
].
title
:
'
-
'
}
type
=
"program"
onReadMore
=
{
()
=>
navigation
.
navigate
(
ROUTES
.
programDetail
,
{
id
:
data
?.
program
.
unique_code
,
})
}
/>
<
CheckoutCard
content
=
{
data
?
data
.
nutritionist
.
full_name_and_degree
:
'
-
'
}
type
=
"nutritionist"
onReadMore
=
{
()
=>
navigation
.
navigate
(
ROUTES
.
nutritionistDetail
,
{
id
:
data
?.
nutritionist
.
id
,
})
}
/>
</
View
>
<
View
style
=
{
styles
.
priceContainer
}
>
<
Text
style
=
{
typographyStyles
.
headingMedium
}
>
Harga:
</
Text
>
{
data
?
(
<
View
style
=
{
styles
.
currencyContainer
}
>
<
Text
style
=
{
styles
.
currency
}
>
Rp
</
Text
>
<
Text
style
=
{
styles
.
basePrice
}
>
{
dietPrograms
[
data
.
program
.
unique_code
].
price
}
</
Text
>
</
View
>
)
:
(
<
Text
>
-
</
Text
>
)
}
</
View
>
<
View
>
<
Button
title
=
"ganti pilihan"
type
=
"outline"
onPress
=
{
()
=>
navigation
.
navigate
(
ROUTES
.
choosePlan
)
}
buttonStyle
=
{
styles
.
buttonStyle
}
titleStyle
=
{
[
typographyStyles
.
overlineBig
,
styles
.
titleStyle
]
}
/>
<
Section
>
<
BigButton
title
=
"bayar dengan midtrans"
onPress
=
{
console
.
log
}
/>
</
Section
>
</
View
>
</
View
>
);
};
export
default
Checkout
;
src/scenes/cart/Checkout/styles.ts
0 → 100644
View file @
48cdfb25
import
{
StyleSheet
}
from
'
react-native
'
;
import
{
layoutStyles
,
typography
,
colors
}
from
'
styles
'
;
export
const
styles
=
StyleSheet
.
create
({
container
:
{
display
:
'
flex
'
,
flexDirection
:
'
column
'
,
justifyContent
:
'
space-between
'
,
flexGrow
:
1
,
...
layoutStyles
,
marginBottom
:
10
,
},
topContainer
:
{
display
:
'
flex
'
,
flexDirection
:
'
column
'
,
justifyContent
:
'
space-between
'
,
},
priceContainer
:
{
display
:
'
flex
'
,
flexDirection
:
'
row
'
,
justifyContent
:
'
space-between
'
,
alignItems
:
'
center
'
,
},
currencyContainer
:
{
display
:
'
flex
'
,
flexDirection
:
'
row
'
,
},
currency
:
{
...
typography
.
bodyMedium
,
color
:
colors
.
formLabel
,
marginRight
:
8
,
marginTop
:
8
,
},
basePrice
:
{
...
typography
.
displayMediumMontserrat
,
color
:
colors
.
primary
,
},
buttonStyle
:
{
borderColor
:
colors
.
buttonYellow
,
borderWidth
:
1
,
},
titleStyle
:
{
color
:
colors
.
textBlack
,
},
});
src/scenes/cart/ChoosePlan/components/PricingCard/index.tsx
View file @
48cdfb25
...
@@ -59,7 +59,7 @@ const PricingCard: FC<Props> = ({
...
@@ -59,7 +59,7 @@ const PricingCard: FC<Props> = ({
title
=
"Baca selengkapnya"
title
=
"Baca selengkapnya"
type
=
"clear"
type
=
"clear"
icon
=
{
{
icon
=
{
{
name
:
'
keyboard-arrow-right
'
,
name
:
'
arrow-forward
'
,
size
:
25
,
size
:
25
,
color
:
colors
.
primaryVariant
,
color
:
colors
.
primaryVariant
,
}
}
}
}
...
...
src/scenes/cart/ChoosePlan/index.test.tsx
View file @
48cdfb25
...
@@ -2,11 +2,13 @@ import React from 'react';
...
@@ -2,11 +2,13 @@ import React from 'react';
import
{
render
,
fireEvent
,
waitFor
}
from
'
utils/testing
'
;
import
{
render
,
fireEvent
,
waitFor
}
from
'
utils/testing
'
;
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
ChoosePlan
from
'
.
'
;
import
ChoosePlan
from
'
.
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
CACHE_KEYS
from
'
constants/cacheKeys
'
;
import
{
mockProgramRecommendations
}
from
'
__mocks__/quizResult
'
;
import
{
mockProgramRecommendations
}
from
'
__mocks__/quizResult
'
;
import
{
dietPrograms
}
from
'
constants/dietelaProgram
'
;
import
{
dietPrograms
}
from
'
constants/dietelaProgram
'
;
import
{
defaultProgramRecommendations
}
from
'
constants/dietelaProgram
'
;
import
{
setCache
}
from
'
utils/cache
'
;
jest
.
mock
(
'
axios
'
);
jest
.
mock
(
'
axios
'
);
const
mockAxios
=
axios
as
jest
.
Mocked
<
typeof
axios
>
;
const
mockAxios
=
axios
as
jest
.
Mocked
<
typeof
axios
>
;
...
@@ -30,7 +32,7 @@ describe('ChoosePlan', () => {
...
@@ -30,7 +32,7 @@ describe('ChoosePlan', () => {
data
:
nutritionists
,
data
:
nutritionists
,
});
});
it
(
'
provides default program recommendations if not
passed
'
,
async
()
=>
{
it
(
'
provides default program recommendations if not
in cache
'
,
async
()
=>
{
mockAxios
.
request
.
mockImplementationOnce
(
retrieveNutritionistsApi
);
mockAxios
.
request
.
mockImplementationOnce
(
retrieveNutritionistsApi
);
const
{
getAllByText
}
=
render
(<
ChoosePlan
/>,
ROUTES
.
choosePlan
);
const
{
getAllByText
}
=
render
(<
ChoosePlan
/>,
ROUTES
.
choosePlan
);
...
@@ -41,6 +43,10 @@ describe('ChoosePlan', () => {
...
@@ -41,6 +43,10 @@ describe('ChoosePlan', () => {
});
});
it
(
'
redirects to cart page when user clicks Bayar button
'
,
async
()
=>
{
it
(
'
redirects to cart page when user clicks Bayar button
'
,
async
()
=>
{
await
setCache
(
CACHE_KEYS
.
programRecommendations
,
JSON
.
stringify
(
mockProgramRecommendations
),
);
const
createCartApi
=
()
=>
const
createCartApi
=
()
=>
Promise
.
resolve
({
Promise
.
resolve
({
status
:
200
,
status
:
200
,
...
@@ -53,10 +59,9 @@ describe('ChoosePlan', () => {
...
@@ -53,10 +59,9 @@ describe('ChoosePlan', () => {
mockAxios
.
request
.
mockImplementationOnce
(
retrieveNutritionistsApi
);
mockAxios
.
request
.
mockImplementationOnce
(
retrieveNutritionistsApi
);
const
{
getByText
,
queryByText
}
=
render
(
const
{
getByText
,
query
All
ByText
}
=
render
(
<
ChoosePlan
/>,
<
ChoosePlan
/>,
ROUTES
.
choosePlan
,
ROUTES
.
choosePlan
,
defaultProgramRecommendations
,
);
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
...
@@ -78,15 +83,17 @@ describe('ChoosePlan', () => {
...
@@ -78,15 +83,17 @@ describe('ChoosePlan', () => {
expect
(
payButton
).
toBeTruthy
();
expect
(
payButton
).
toBeTruthy
();
await
waitFor
(()
=>
fireEvent
.
press
(
payButton
));
await
waitFor
(()
=>
fireEvent
.
press
(
payButton
));
const
c
ar
tPage
=
queryByText
(
/C
oming Soon
/i
);
const
c
heckou
tPage
=
query
All
ByText
(
/C
heckout
/i
);
expect
(
c
ar
tPage
).
toBeTruthy
();
expect
(
c
heckou
tPage
).
toBeTruthy
();
});
});
it
(
'
does not redirect to cart page when submit fails
'
,
async
()
=>
{
it
(
'
does not redirect to cart page when submit fails
'
,
async
()
=>
{
const
createCartApi
=
()
=>
const
createCartApi
=
()
=>
Promise
.
reject
({
Promise
.
reject
({
status
:
400
,
status
:
400
,
data
:
'
error
'
,
response
:
{
data
:
'
error
'
,
},
});
});
mockAxios
.
request
.
mockImplementationOnce
(
retrieveNutritionistsApi
);
mockAxios
.
request
.
mockImplementationOnce
(
retrieveNutritionistsApi
);
...
@@ -94,7 +101,6 @@ describe('ChoosePlan', () => {
...
@@ -94,7 +101,6 @@ describe('ChoosePlan', () => {
const
{
getByText
,
queryByText
}
=
render
(
const
{
getByText
,
queryByText
}
=
render
(
<
ChoosePlan
/>,
<
ChoosePlan
/>,
ROUTES
.
choosePlan
,
ROUTES
.
choosePlan
,
defaultProgramRecommendations
,
);
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
...
@@ -116,8 +122,8 @@ describe('ChoosePlan', () => {
...
@@ -116,8 +122,8 @@ describe('ChoosePlan', () => {
expect
(
payButton
).
toBeTruthy
();
expect
(
payButton
).
toBeTruthy
();
await
waitFor
(()
=>
fireEvent
.
press
(
payButton
));
await
waitFor
(()
=>
fireEvent
.
press
(
payButton
));
const
c
ar
tPage
=
queryByText
(
/C
oming Soon
/i
);
const
c
heckou
tPage
=
queryByText
(
/C
heckout
/i
);
expect
(
c
ar
tPage
).
toBeFalsy
();
expect
(
c
heckou
tPage
).
toBeFalsy
();
});
});
it
(
'
redirects to program detail page when user clicks Baca selengkapnya button for program
'
,
async
()
=>
{
it
(
'
redirects to program detail page when user clicks Baca selengkapnya button for program
'
,
async
()
=>
{
...
@@ -126,7 +132,6 @@ describe('ChoosePlan', () => {
...
@@ -126,7 +132,6 @@ describe('ChoosePlan', () => {
const
{
getAllByText
,
getByText
}
=
render
(
const
{
getAllByText
,
getByText
}
=
render
(
<
ChoosePlan
/>,
<
ChoosePlan
/>,
ROUTES
.
choosePlan
,
ROUTES
.
choosePlan
,
defaultProgramRecommendations
,
);
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
...
@@ -147,7 +152,6 @@ describe('ChoosePlan', () => {
...
@@ -147,7 +152,6 @@ describe('ChoosePlan', () => {
const
{
getAllByText
,
getByText
}
=
render
(
const
{
getAllByText
,
getByText
}
=
render
(
<
ChoosePlan
/>,
<
ChoosePlan
/>,
ROUTES
.
choosePlan
,
ROUTES
.
choosePlan
,
defaultProgramRecommendations
,
);
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
...
...
src/scenes/cart/ChoosePlan/index.tsx
View file @
48cdfb25
import
React
,
{
FC
,
useState
}
from
'
react
'
;
import
React
,
{
FC
,
useState
,
useCallback
,
useEffect
}
from
'
react
'
;
import
{
ScrollView
}
from
'
react-native
'
;
import
{
ScrollView
}
from
'
react-native
'
;
import
{
useNavigation
,
useRoute
}
from
'
@react-navigation/native
'
;
import
{
useNavigation
}
from
'
@react-navigation/native
'
;