Fakultas Ilmu Komputer UI

Commit 094388fd authored by Wulan Mantiri's avatar Wulan Mantiri
Browse files

Merge branch 'PBI-13-improve_test_weekly_report' into 'staging'

Improve tests for client weekly report

See merge request !73
parents 59d47491 0e3b5036
Pipeline #81655 passed with stages
in 48 minutes and 58 seconds
...@@ -46,7 +46,6 @@ const LikertScale: FC<Props> = ({ ...@@ -46,7 +46,6 @@ const LikertScale: FC<Props> = ({
style={{ flex: 1 / choices.length }} style={{ flex: 1 / choices.length }}
key={`button${choice.value}`}> key={`button${choice.value}`}>
<RadioButton <RadioButton
testID={`${label}-${value}`}
key={choice.value} key={choice.value}
checked={value === choice.value} checked={value === choice.value}
onPress={() => onChange(choice.value)} onPress={() => onChange(choice.value)}
......
...@@ -17,10 +17,10 @@ import { ...@@ -17,10 +17,10 @@ import {
Questionnaire4, Questionnaire4,
Questionnaire5, Questionnaire5,
} from 'scenes/questionnaire/ExtendedQuestionnaire/components'; } from 'scenes/questionnaire/ExtendedQuestionnaire/components';
import ReadOnlyWeeklyReport from 'scenes/report/ReadOnlyWeeklyReport';
import { screenOptions } from 'app/styles'; import { screenOptions } from 'app/styles';
import { styles } from './styles'; import { styles } from './styles';
import { ReadOnlyWeeklyReport } from 'scenes';
interface NavRoute<T = any> { interface NavRoute<T = any> {
name: string; name: string;
......
...@@ -9,7 +9,7 @@ import { generateValidationSchema } from 'utils/form'; ...@@ -9,7 +9,7 @@ import { generateValidationSchema } from 'utils/form';
import { DietReportPage } from './components'; import { DietReportPage } from './components';
import { useRoute, useNavigation } from '@react-navigation/native'; import { useRoute, useNavigation } from '@react-navigation/native';
import { import {
retrieveUserReportById, retrieveUserReportByIdApi,
createNutritionistCommentApi, createNutritionistCommentApi,
} from 'services/progress'; } from 'services/progress';
import { NutritionistCommentRequest } from 'services/progress/models'; import { NutritionistCommentRequest } from 'services/progress/models';
...@@ -28,7 +28,7 @@ const DietReportForNutritionist: FC = () => { ...@@ -28,7 +28,7 @@ const DietReportForNutritionist: FC = () => {
const route = useRoute(); const route = useRoute();
const { id } = route.params as ParamsDietReport; const { id } = route.params as ParamsDietReport;
const { isLoading, data: userReports = [] } = useApi(() => const { isLoading, data: userReports = [] } = useApi(() =>
retrieveUserReportById(id), retrieveUserReportByIdApi(id),
); );
const [activeSlide, setActiveSlide] = useState(1); const [activeSlide, setActiveSlide] = useState(1);
......
...@@ -14,7 +14,10 @@ const Report2: FC<ReportProps> = ({ getTextInputProps, getFormFieldProps }) => ( ...@@ -14,7 +14,10 @@ const Report2: FC<ReportProps> = ({ getTextInputProps, getFormFieldProps }) => (
{dietReportSelectFields.dietReportPage2.map((props, i) => { {dietReportSelectFields.dietReportPage2.map((props, i) => {
const FormField = props.scaleDescription ? LikertScale : RadioButtonGroup; const FormField = props.scaleDescription ? LikertScale : RadioButtonGroup;
return ( return (
<View key={`report2-select${i}`} style={styles.spacing}> <View
key={`report2-select${i}`}
style={styles.spacing}
testID={props.name}>
<FormField <FormField
{...props} {...props}
choices={props.choiceList.map((label: string, id: number) => ({ choices={props.choiceList.map((label: string, id: number) => ({
......
...@@ -14,7 +14,10 @@ const Report3: FC<ReportProps> = ({ getFormFieldProps }) => ( ...@@ -14,7 +14,10 @@ const Report3: FC<ReportProps> = ({ getFormFieldProps }) => (
atau minuman dibawah ini selama seharian: atau minuman dibawah ini selama seharian:
</Text> </Text>
{dietReportSelectFields.dietReportPage3.map((props, i) => ( {dietReportSelectFields.dietReportPage3.map((props, i) => (
<View key={`report3-scale${i}`} style={styles.spacing}> <View
key={`report3-scale${i}`}
style={styles.spacing}
testID={props.name}>
<LikertScale <LikertScale
{...props} {...props}
{...getFormFieldProps(props.name)} {...getFormFieldProps(props.name)}
......
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import axios from 'axios';
import WeeklyReport from '.';
import {
dietReportTextFields,
dietReportSelectFields,
} from 'constants/weeklyReport';
import { RadioButton } from 'components/form';
jest.mock('react-native-toast-message');
jest.mock('axios');
const mockAxios = axios as jest.Mocked<typeof axios>;
const mockedNavigate = jest.fn();
jest.mock('@react-navigation/native', () => {
return {
useNavigation: () => ({
reset: mockedNavigate,
}),
};
});
describe('WeeklyReport', () => {
const validFormValues: { [_: string]: any } = {
weight: '52',
height: '90',
waist_size: '190',
changes_felt: 1,
hunger_level: 1,
fullness_level: 1,
heavy_meal: 1,
snacks: 1,
sweet_beverages: 1,
sugary_ingredients: 1,
fried_snacks: 1,
umami_snacks: 1,
sweet_snacks: 1,
fruits_portion: 1,
vegetables_portion: 1,
water_consumption: '80',
physical_activity: [1],
physical_activity_other: '',
time_for_activity: 1,
feeling_rating: 1,
lesson_learned: 'hai',
problem_faced_and_feedbacks: 'feedback',
};
it('initially has disabled next button', () => {
const { getByText, queryByText } = render(<WeeklyReport />);
const weightTextField = queryByText(/Berat Badan/i);
expect(weightTextField).toBeTruthy();
const nextButton = getByText(/Lanjut/i);
expect(nextButton).toBeTruthy();
fireEvent.press(nextButton);
expect(queryByText(/Berat Badan/i)).toBeTruthy();
});
it('redirects to choose week for report if all form values are valid and submit success', async () => {
const createUserReportApi = () =>
Promise.resolve({
status: 201,
data: validFormValues,
});
mockAxios.request.mockImplementationOnce(createUserReportApi);
const { getByText, getByPlaceholderText, getByTestId } = render(
<WeeklyReport />,
);
dietReportTextFields.dietReportPage1.forEach(({ name, placeholder }) => {
const formField = getByPlaceholderText(placeholder as string);
fireEvent.changeText(formField, validFormValues[name]);
});
fireEvent.press(getByText(/Lanjut/i));
dietReportTextFields.dietReportPage2.forEach(({ name, placeholder }) => {
const formField = getByPlaceholderText(placeholder as string);
fireEvent.changeText(formField, validFormValues[name]);
});
dietReportSelectFields.dietReportPage2.forEach(({ name }) => {
const formField = getByTestId(name);
const firstChoice = formField.findAllByType(RadioButton)[0];
fireEvent.press(firstChoice);
});
fireEvent.press(getByText(/Lanjut/i));
dietReportSelectFields.dietReportPage3.forEach(({ name }) => {
const formField = getByTestId(name);
const firstChoice = formField.findAllByType(RadioButton)[0];
fireEvent.press(firstChoice);
});
fireEvent.press(getByText(/Lanjut/i));
dietReportSelectFields.dietReportPage4.forEach(({ choiceList }) => {
const firstChoice = getByText(choiceList[0]);
fireEvent.press(firstChoice);
});
dietReportTextFields.dietReportPage4.forEach(({ name, placeholder }) => {
const formField = getByPlaceholderText(placeholder as string);
fireEvent.changeText(formField, validFormValues[name]);
});
const submitButton = getByText('Selesai');
await waitFor(() => fireEvent.press(submitButton));
expect(mockedNavigate).toHaveBeenCalledTimes(1);
});
it('does not redirect to choose week for report if all form values are valid but submit fails', async () => {
const createUserReportApi = () =>
Promise.reject({
status: 400,
response: {
data: 'error',
},
});
mockAxios.request.mockImplementationOnce(createUserReportApi);
const { getByText, getByPlaceholderText, getByTestId } = render(
<WeeklyReport />,
);
dietReportTextFields.dietReportPage1.forEach(({ name, placeholder }) => {
const formField = getByPlaceholderText(placeholder as string);
fireEvent.changeText(formField, validFormValues[name]);
});
fireEvent.press(getByText(/Lanjut/i));
dietReportTextFields.dietReportPage2.forEach(({ name, placeholder }) => {
const formField = getByPlaceholderText(placeholder as string);
fireEvent.changeText(formField, validFormValues[name]);
});
dietReportSelectFields.dietReportPage2.forEach(({ name }) => {
const formField = getByTestId(name);
const firstChoice = formField.findAllByType(RadioButton)[0];
fireEvent.press(firstChoice);
});
fireEvent.press(getByText(/Lanjut/i));
dietReportSelectFields.dietReportPage3.forEach(({ name }) => {
const formField = getByTestId(name);
const firstChoice = formField.findAllByType(RadioButton)[0];
fireEvent.press(firstChoice);
});
fireEvent.press(getByText(/Lanjut/i));
dietReportSelectFields.dietReportPage4.forEach(({ choiceList }) => {
const firstChoice = getByText(choiceList[0]);
fireEvent.press(firstChoice);
});
dietReportTextFields.dietReportPage4.forEach(({ name, placeholder }) => {
const formField = getByPlaceholderText(placeholder as string);
fireEvent.changeText(formField, validFormValues[name]);
});
const submitButton = getByText('Selesai');
await waitFor(() => fireEvent.press(submitButton));
expect(mockedNavigate).toHaveBeenCalledTimes(1);
});
afterAll(() => {
jest.clearAllMocks();
});
});
import React, { FC, useContext, useState } from 'react'; import React, { FC, useState } from 'react';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import * as ROUTES from 'constants/routes'; import * as ROUTES from 'constants/routes';
import { WizardContainer, Toast, Loader } from 'components/core'; import { WizardContainer, Toast } from 'components/core';
import { import {
dietReportTextFields, dietReportTextFields,
dietReportSelectFields, dietReportSelectFields,
} from 'constants/weeklyReport'; } from 'constants/weeklyReport';
import { useApi, useForm } from 'hooks'; import { useForm } from 'hooks';
import { generateValidationSchema } from 'utils/form'; import { generateValidationSchema } from 'utils/form';
import { createUserReportApi, retrieveUserReportById } from 'services/progress'; import { createUserReportApi } from 'services/progress';
import { initialValues, fieldValidations, convertPayload } from './schema'; import { initialValues, fieldValidations, convertPayload } from './schema';
import { pages } from './components'; import { pages } from './components';
import { UserContext } from 'provider';
const WeeklyReport: FC = () => { const WeeklyReport: FC = () => {
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const { user } = useContext(UserContext);
const { isLoading, data } = useApi(() => retrieveUserReportById(user.id!));
const navigation = useNavigation(); const navigation = useNavigation();
const { const {
getTextInputProps, getTextInputProps,
getFormFieldProps, getFormFieldProps,
isFormUntouched,
isFieldError, isFieldError,
handleSubmit, handleSubmit,
isSubmitting, isSubmitting,
values: formValues,
} = useForm({ } = useForm({
initialValues, initialValues,
validationSchema: generateValidationSchema(fieldValidations), validationSchema: generateValidationSchema(fieldValidations),
...@@ -49,28 +46,23 @@ const WeeklyReport: FC = () => { ...@@ -49,28 +46,23 @@ const WeeklyReport: FC = () => {
}); });
const isCurrentPageError = (): boolean => { const isCurrentPageError = (): boolean => {
if (currentPage === 1) {
return [
formValues.height,
formValues.weight,
formValues.waist_size,
].reduce((acc: boolean, item) => acc || item === '', false);
}
const fields = [ const fields = [
...(dietReportTextFields[`dietReportPage${currentPage}`] || []), ...(dietReportTextFields[`dietReportPage${currentPage}`] || []),
...(dietReportSelectFields[`dietReportPage${currentPage}`] || []), ...dietReportSelectFields[`dietReportPage${currentPage}`],
]; ];
return ( return fields.reduce(
isFormUntouched() || (acc: boolean, item) => acc || isFieldError(item.name),
fields.reduce( false,
(acc: boolean, item) => acc || isFieldError(item.name),
false,
)
); );
}; };
console.log('diluar if');
if (isLoading) {
return <Loader />;
} else if (data?.length > 0) {
navigation.reset({
index: 0,
routes: [{ name: ROUTES.weeklyReportReadOnly, params: data }],
});
}
return ( return (
<WizardContainer <WizardContainer
......
...@@ -8,7 +8,7 @@ import { ...@@ -8,7 +8,7 @@ import {
NutritionistCommentResponse, NutritionistCommentResponse,
} from './models'; } from './models';
export const retrieveUserReportById = ( export const retrieveUserReportByIdApi = (
clientId: number, clientId: number,
): ApiResponse<UserReportResponse[]> => { ): ApiResponse<UserReportResponse[]> => {
return api(RequestMethod.GET, apiUrls.userReportByClientId(clientId)); return api(RequestMethod.GET, apiUrls.userReportByClientId(clientId));
......
Markdown is supported
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