From 2e6018c0394ee7a6719263b86594b6280302ca3b Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 13:56:02 +0800 Subject: [PATCH 01/13] [CHORES] Add config to allow passing route params to screens --- jestSetup.js | 7 +++++++ src/utils/testing.tsx | 11 +++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/jestSetup.js b/jestSetup.js index 53ba9b6..2aea538 100644 --- a/jestSetup.js +++ b/jestSetup.js @@ -1,5 +1,12 @@ +import 'react-native-gesture-handler/jestSetup'; import { jest } from '@jest/globals'; import mockAsyncStorage from '@react-native-community/async-storage/jest/async-storage-mock'; +jest.mock('react-native-reanimated', () => { + const Reanimated = require('react-native-reanimated/mock'); + Reanimated.default.call = () => {}; + return Reanimated; +}); + jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper'); jest.mock('@react-native-community/async-storage', () => mockAsyncStorage); diff --git a/src/utils/testing.tsx b/src/utils/testing.tsx index b9bc18f..e8ff377 100644 --- a/src/utils/testing.tsx +++ b/src/utils/testing.tsx @@ -9,10 +9,11 @@ const Stack = createStackNavigator(); interface TestProvider { route: string; + params?: any; children: ReactElement; } -const TestProvider: FC = ({ route, children }) => { +const TestProvider: FC = ({ route, params, children }) => { return ( @@ -21,6 +22,7 @@ const TestProvider: FC = ({ route, children }) => { key={`nav${i}`} name={nav.name} component={route === nav.name ? () => children : nav.component} + initialParams={params} options={{ title: nav.header, headerShown: Boolean(nav.header), @@ -35,10 +37,15 @@ const TestProvider: FC = ({ route, children }) => { const customRender = ( ui: ReactElement, route: string, + params?: any, options?: Omit, ) => render(ui, { - wrapper: () => {ui}, + wrapper: () => ( + + {ui} + + ), ...options, }); -- GitLab From 681443b6c01584c644eb1f2243211eaf1cdb130f Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 13:56:56 +0800 Subject: [PATCH 02/13] [REFACTOR] Extract mock quiz result and adjust with their corresponding enums --- src/mocks/quizResult.ts | 86 ++++++++++++++++++++++++++ src/services/dietelaQuiz/quizResult.ts | 70 --------------------- 2 files changed, 86 insertions(+), 70 deletions(-) create mode 100644 src/mocks/quizResult.ts diff --git a/src/mocks/quizResult.ts b/src/mocks/quizResult.ts new file mode 100644 index 0000000..5fb53de --- /dev/null +++ b/src/mocks/quizResult.ts @@ -0,0 +1,86 @@ +import { + DietProfileResponse, + DietProfileRequest, +} from 'services/dietelaQuiz/models'; +import { + BodyMassConstants, + VegetableAndFruitSufficiencyResponse, + SugarSaltFatProblemResponse, + LargeMealDietRecommendation, + SnacksDietRecommendation, + BreakfastReponse, + PhysicalActivityResponse, +} from 'services/dietelaQuiz/quizResult'; +import { DietelaProgram } from 'services/cart/models'; + +const validFormValues: DietProfileRequest = { + name: 'Dietela', + email: 'dietela@gmail.com', + age: 20, + weight: 60, + height: 172, + gender: 2, + special_condition: 1, + body_activity: 1, + vegetables_in_one_day: 1, + fruits_in_one_day: 1, + fried_food_in_one_day: 1, + sweet_snacks_in_one_day: 1, + sweet_drinks_in_one_day: 1, + packaged_food_in_one_day: 1, + large_meal_in_one_day: 1, + snacks_in_one_day: 1, + breakfast_type: 1, + current_condition: 1, + problem_to_solve: 1, + health_problem: [2, 3], +}; + +export const mockProgramRecommendations = { + priority_1: DietelaProgram.TRIAL, + priority_2: null, +}; + +export const mockQuizResult: DietProfileResponse = { + id: 1, + ...validFormValues, + quiz_result: { + diet_profile: 1, + age: 20, + weight: 60, + height: 172, + gender: 2, + body_mass_index: 20, + nutrition_status: BodyMassConstants.NORMAL, + ideal_weight_range: { + max: 68.0432, + min: 56.209599999999995, + }, + daily_energy_needs: 1696.8, + daily_nutrition_needs: { + fat_needs: 56.559999999999995, + fiber_needs: 25, + protein_needs: 55.146, + carbohydrate_needs: 241.79399999999998, + }, + vegetable_and_fruit_sufficiency: + VegetableAndFruitSufficiencyResponse.LACKING, + vegetable_and_fruit_diet_recommendation: + 'Yah.. asupan buah & sayur kamu masih kurang nih. Yuk, cari solusi agar kamu bisa konsumsi setidaknya 2 porsi sayur & 3 porsi buah atau sebaliknya per hari. Pokoknya kalau di total kamu perlu 5 porsi buah & sayur per hari.', + sugar_salt_fat_problem: SugarSaltFatProblemResponse.CONTROLLED, + sugar_salt_fat_diet_recommendation: + 'Selamat! Kamu sudah memenuhi salah satu langkah untuk menuju hidup sehat. Pertahankan pemilihan jenis makanan yang seperti ini ya. Upayakan agar jumlah gorengan, cemilan manis, makan manis, makanan kemasan, dan makanan cepat saji yang kamu makan bisa terkontrol jumlahnya.', + large_meal_diet_recommendation: LargeMealDietRecommendation.ONCE_A_DAY, + snacks_diet_recommendation: SnacksDietRecommendation.NO_SNACK, + breakfast_recommendation: BreakfastReponse.NO_BREAKFAST, + energy_needed_per_dine: { + lunch: 509.03999999999996, + dinner: 509.03999999999996, + breakfast: 169.68, + morning_snack: 254.51999999999998, + afternoon_snack: 254.51999999999998, + }, + physical_activity_recommendation: PhysicalActivityResponse.LEVEL1_ACTIVITY, + program_recommendation: mockProgramRecommendations, + }, +}; diff --git a/src/services/dietelaQuiz/quizResult.ts b/src/services/dietelaQuiz/quizResult.ts index 083d3ab..90411a6 100644 --- a/src/services/dietelaQuiz/quizResult.ts +++ b/src/services/dietelaQuiz/quizResult.ts @@ -1,4 +1,3 @@ -import { DietProfileResponse } from 'services/dietelaQuiz/models'; import { DietelaProgram } from 'services/cart/models'; export enum Status { @@ -174,72 +173,3 @@ export interface ProgramRecommendations { priority_1: DietelaProgram; priority_2: DietelaProgram | null; } - -export const exampleResult: DietProfileResponse = { - id: 1, - health_problem: [2, 3], - name: 'test2', - email: 'test2@test.com', - age: 20, - weight: 60, - height: 172, - gender: 2, - special_condition: 1, - body_activity: 1, - vegetables_in_one_day: 1, - fruits_in_one_day: 1, - fried_food_in_one_day: 1, - sweet_snacks_in_one_day: 1, - sweet_drinks_in_one_day: 1, - packaged_food_in_one_day: 1, - large_meal_in_one_day: 1, - snacks_in_one_day: 1, - breakfast_type: 1, - current_condition: 1, - problem_to_solve: 1, - quiz_result: { - diet_profile: 1, - age: 20, - weight: 60, - height: 172, - gender: 2, - body_mass_index: 20, - nutrition_status: 'Normal', - ideal_weight_range: { - max: 68.0432, - min: 56.209599999999995, - }, - daily_energy_needs: 1696.8, - daily_nutrition_needs: { - fat_needs: 56.559999999999995, - fiber_needs: 25, - protein_needs: 55.146, - carbohydrate_needs: 241.79399999999998, - }, - vegetable_and_fruit_sufficiency: 'Kurang makan sayur dan buah', - vegetable_and_fruit_diet_recommendation: - 'Yah.. asupan buah & sayur kamu masih kurang nih. Yuk, cari solusi agar kamu bisa konsumsi setidaknya 2 porsi sayur & 3 porsi buah atau sebaliknya per hari. Pokoknya kalau di total kamu perlu 5 porsi buah & sayur per hari.', - sugar_salt_fat_problem: 'Asupan gula, garam, dan lemak terkontrol', - sugar_salt_fat_diet_recommendation: - 'Selamat! Kamu sudah memenuhi salah satu langkah untuk menuju hidup sehat. Pertahankan pemilihan jenis makanan yang seperti ini ya. Upayakan agar jumlah gorengan, cemilan manis, makan manis, makanan kemasan, dan makanan cepat saji yang kamu makan bisa terkontrol jumlahnya.', - large_meal_diet_recommendation: - 'Hmmm.... Kenapa cuma makan besar 1 kali sehari? Makan besar cuma 1 kali dalam sehari berisiko membuat kamu makan berlebihan dan kekurangan zat gizi tertentu Lho! Yuk coba mulai diatur pola makannya, dengan merutinkan waktu makan agar metabolisme kamu lebih baik.', - snacks_diet_recommendation: - 'Yah kok gak ngemil? Makan cemilan itu penting untuk menjaga kadar gula darah kamu seharian, dengan ngemil gula darah seharian kamu bisa terkontrol sehingga mencegah lemas dan berkurangnya konsentrasi.', - breakfast_recommendation: - 'Perut kosong di pagi hari bisa mengarahkan kepada 2 keadaan, antara membuat makan berlebihan di siang hari atau kurang asupan zat gizi per hari. Makan pagi bisa disesuaikan dengan pola bangun tidur kamu lho, cari deh solusi terbaik agar kamu bisa beraktifitas tanpa perut kosong.', - energy_needed_per_dine: { - lunch: 509.03999999999996, - dinner: 509.03999999999996, - breakfast: 169.68, - morning_snack: 254.51999999999998, - afternoon_snack: 254.51999999999998, - }, - physical_activity_recommendation: - 'Hayooo kok duduk-duduk aja? Yuk ah mulai lakukan aktivitas fisik, dimulai dari aktivitas yang ringan seperti jalan kaki, jogging, senam, atau naik turun tangga 15 menit per hari. Tingkatkan perlahan hingga mencapai 30 menit per hari. Konsultasikan kebutuhan gizi harianmu kepada Dietela agar asupan makan kamu seimbang dengan energi yang kamu keluarkan setiap harinya', - program_recommendation: { - priority_1: 'TRIAL', - priority_2: null, - }, - }, -}; -- GitLab From b69a924313ac5d55b6c488a478be5b4439902b62 Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 13:58:28 +0800 Subject: [PATCH 03/13] [GREEN] Improve coverage by adding mock tests for choose plan page --- src/scenes/cart/ChoosePlan/index.test.tsx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/scenes/cart/ChoosePlan/index.test.tsx b/src/scenes/cart/ChoosePlan/index.test.tsx index e5cb9fe..78d48b4 100644 --- a/src/scenes/cart/ChoosePlan/index.test.tsx +++ b/src/scenes/cart/ChoosePlan/index.test.tsx @@ -4,6 +4,7 @@ import axios from 'axios'; import * as ROUTES from 'constants/routes'; import ChoosePlan from '.'; +import { mockProgramRecommendations } from 'mocks/quizResult'; jest.mock('axios'); @@ -46,21 +47,26 @@ describe('ChoosePlan', () => { }); it('redirects to program detail page when user clicks Baca selengkapnya button for program', async () => { - const { queryAllByText } = render(, ROUTES.choosePlan); + const { getAllByText, getByText } = render( + , + ROUTES.choosePlan, + mockProgramRecommendations, + ); await waitFor(() => expect(mockAxios.request).toBeCalled()); - const readMoreButton = queryAllByText(/Baca selengkapnya/i)[0]; - expect(readMoreButton).toBeFalsy(); - // fireEvent.press(readMoreButton); + const readMoreButton = getAllByText(/Baca selengkapnya/i)[0]; + expect(readMoreButton).toBeTruthy(); + fireEvent.press(readMoreButton); - // const programDetailPage = queryByText(/Coming Soon/i); - // expect(programDetailPage).toBeFalsy(); + const programDetailPage = getByText(/Coming Soon/i); + expect(programDetailPage).toBeTruthy(); }); it('redirects to nutritionist detail page when user clicks Baca selengkapnya button for nutritionist', async () => { const { getAllByText, getByText } = render( , ROUTES.choosePlan, + mockProgramRecommendations, ); await waitFor(() => expect(mockAxios.request).toBeCalled()); -- GitLab From 30209b0da2b610b8e6fe3586329863893f789694 Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 14:01:28 +0800 Subject: [PATCH 04/13] [REFACTOR] Handle error typings and unique key prop on quiz result page --- src/scenes/questionnaire/DietelaQuizResult/index.tsx | 9 +++++---- .../DietelaQuizResult/pages/ResultPage/index.tsx | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/scenes/questionnaire/DietelaQuizResult/index.tsx b/src/scenes/questionnaire/DietelaQuizResult/index.tsx index 3d114c8..8b2c264 100644 --- a/src/scenes/questionnaire/DietelaQuizResult/index.tsx +++ b/src/scenes/questionnaire/DietelaQuizResult/index.tsx @@ -5,13 +5,13 @@ import Carousel from 'react-native-snap-carousel'; import { CarouselPagination } from 'components/core'; import { ResultPage, pages } from './pages'; import { styles } from './styles'; -import { useRoute } from '@react-navigation/core'; +import { useRoute } from '@react-navigation/native'; import { DietProfileResponse } from 'services/dietelaQuiz/models'; const DietelaQuizResult: FC = () => { const [activeSlide, setActiveSlide] = useState(0); const route = useRoute(); - const resultData: DietProfileResponse = route.params; + const resultData = route.params as DietProfileResponse; return ( @@ -19,14 +19,15 @@ const DietelaQuizResult: FC = () => { data={pages.map((page, idx) => idx === 8 ? ( ) : ( - + ), )} - renderItem={({ item }) => item} + renderItem={({ item }: any) => item} sliderWidth={Dimensions.get('window').width} itemWidth={Dimensions.get('window').width} onSnapToItem={(index) => setActiveSlide(index)} diff --git a/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.tsx b/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.tsx index bdfabe6..f291607 100644 --- a/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.tsx +++ b/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.tsx @@ -33,11 +33,11 @@ const ResultPage: FC<{
{section.header} - {section.content.statistics?.map((statRow) => ( - + {section.content.statistics?.map((statRow, ii) => ( + - {statRow.map((stat) => ( - + {statRow.map((stat, iii) => ( + Date: Mon, 5 Apr 2021 14:07:34 +0800 Subject: [PATCH 05/13] [GRREN] Improve coverage of dietela quiz page by adding mock tests to redirect to quiz result --- .../AllAccessQuestionnaire/index.test.tsx | 82 +++++++++---------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/src/scenes/questionnaire/AllAccessQuestionnaire/index.test.tsx b/src/scenes/questionnaire/AllAccessQuestionnaire/index.test.tsx index e37b607..99e2e63 100644 --- a/src/scenes/questionnaire/AllAccessQuestionnaire/index.test.tsx +++ b/src/scenes/questionnaire/AllAccessQuestionnaire/index.test.tsx @@ -5,6 +5,7 @@ import axios from 'axios'; import AllAccessQuestionnaire from '.'; import { allAccessQuestions, textFields } from './schema'; +import { mockQuizResult } from 'mocks/quizResult'; jest.mock('react-native-toast-message'); jest.mock('axios'); @@ -14,9 +15,9 @@ describe('AllAccessQuestionnaire', () => { const validFormValues: { [_: string]: any } = { name: 'Dietela', email: 'dietela@gmail.com', - age: '29', - weight: '82', - height: '178', + age: '20', + weight: '60', + height: '172', gender: 1, special_condition: 1, body_activity: 1, @@ -31,7 +32,7 @@ describe('AllAccessQuestionnaire', () => { breakfast_type: 1, current_condition: 1, problem_to_solve: 1, - health_problem: [1], + health_problem: [2, 3], }; it('shows biodata form and all required errors after submit with empty form values', async () => { @@ -91,44 +92,41 @@ describe('AllAccessQuestionnaire', () => { expect(nextPage).toBeTruthy(); }); - // it('redirects to quiz result page if all form values are valid and submit success', async () => { - // const createDietProfileApi = () => - // Promise.resolve({ - // status: 201, - // data: { - // id: 1, - // ...validFormValues, - // }, - // }); - // mockAxios.request.mockImplementationOnce(createDietProfileApi); - - // const { getByText, getByPlaceholderText } = render( - // , - // ROUTES.allAccessQuestionnaire, - // ); - - // textFields.forEach(({ name, placeholder }) => { - // const formField = getByPlaceholderText(placeholder as string); - // fireEvent.changeText(formField, validFormValues[name]); - // }); - - // const maleChoice = getByText(/Pria/i); - // fireEvent.press(maleChoice); - - // allAccessQuestions.forEach(({ choiceList }) => { - // const nextButton = getByText(/Lanjut/i); - // fireEvent.press(nextButton); - - // const firstChoice = getByText(choiceList[0]); - // fireEvent.press(firstChoice); - // }); - - // const submitButton = getByText('Selesai'); - // await waitFor(() => fireEvent.press(submitButton)); - - // const quizResultPage = getByText(/Quiz Result/i); - // expect(quizResultPage).toBeTruthy(); - // }); + it('redirects to quiz result page if all form values are valid and submit success', async () => { + const createDietProfileApi = () => + Promise.resolve({ + status: 201, + data: mockQuizResult, + }); + mockAxios.request.mockImplementationOnce(createDietProfileApi); + + const { getByText, getByPlaceholderText } = render( + , + ROUTES.allAccessQuestionnaire, + ); + + textFields.forEach(({ name, placeholder }) => { + const formField = getByPlaceholderText(placeholder as string); + fireEvent.changeText(formField, validFormValues[name]); + }); + + const maleChoice = getByText(/Pria/i); + fireEvent.press(maleChoice); + + allAccessQuestions.forEach(({ choiceList }) => { + const nextButton = getByText(/Lanjut/i); + fireEvent.press(nextButton); + + const firstChoice = getByText(choiceList[0]); + fireEvent.press(firstChoice); + }); + + const submitButton = getByText('Selesai'); + await waitFor(() => fireEvent.press(submitButton)); + + const quizResultPage = getByText(/Quiz Result/i); + expect(quizResultPage).toBeTruthy(); + }); it('does not redirect to quiz result page if all form values are valid but submit fails', async () => { const createDietProfileApi = () => -- GitLab From cdc196a14f5cea3ca12ecbcf8055a370a28714e6 Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 14:12:05 +0800 Subject: [PATCH 06/13] [CHORES] Add .eslintcache to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5401465..ea6a1c2 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ buck-out/ coverage/ .husky +.eslintcache -- GitLab From c48c6378e6106a36ca2ad7d6b2609c8528572d1c Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 14:15:25 +0800 Subject: [PATCH 07/13] [CHORES] Separate pbi from main sonar scanner stage, lint from test ci stages --- .gitlab-ci.yml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dbd5a95..a5f982c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,20 +9,43 @@ cache: stages: - test + - lint + - pbi-sonar-scanner - sonar-scanner - build -lint-test: +test: stage: test before_script: - yarn install script: - - yarn lint - yarn test --coverage --watchAll=false --verbose --collectCoverageFrom="src/**/*.tsx" artifacts: paths: - coverage +lint: + stage: lint + script: + - yarn lint + - yarn prettify + +pbi-sonar-scanner: + image: + name: sonarsource/sonar-scanner-cli:latest + entrypoint: [''] + stage: pbi-sonar-scanner + script: + - sonar-scanner + -Dsonar.host.url=$SONARQUBE_URL + -Dsonar.login=$SONARQUBE_TOKEN + -Dsonar.branch.name=$CI_COMMIT_REF_NAME + -Dsonar.branch.target=staging + -Dsonar.projectKey=$SONARQUBE_PROJECT_KEY + except: + - staging + - master + sonar-scanner: image: name: sonarsource/sonar-scanner-cli:latest @@ -34,6 +57,9 @@ sonar-scanner: -Dsonar.login=$SONARQUBE_TOKEN -Dsonar.branch.name=$CI_COMMIT_REF_NAME -Dsonar.projectKey=$SONARQUBE_PROJECT_KEY + only: + - staging + - master android: stage: build @@ -42,7 +68,7 @@ android: - export ANDROID_SDK_ROOT=/usr/lib/android-sdk script: - cd android - - chmod +x gradlew && ./gradlew clean && ./gradlew assembleRelease + - chmod +x gradlew && ./gradlew assembleRelease - cd .. && cp android/app/build/outputs/apk/release/app-release.apk $CI_PROJECT_NAME-$CI_COMMIT_REF_NAME.apk artifacts: name: '$CI_PROJECT_NAME-$CI_COMMIT_REF_NAME' -- GitLab From b1eadf2e727b8cce47841a1a6c7246a88b94ae45 Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 14:15:55 +0800 Subject: [PATCH 08/13] [CHORES] Update lint staged commands --- package.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4aef8b8..9d64be2 100644 --- a/package.json +++ b/package.json @@ -59,10 +59,9 @@ "@types/react": "^16" }, "lint-staged": { - "./src/*.{ts,tsx}": [ - "yarn run lint", - "yarn run prettify" - ], - "*.{ts,tsx}": "eslint --cache --fix" + "*.{ts,tsx}": [ + "yarn lint", + "yarn prettify" + ] } } -- GitLab From d2214a91279f60d84f043f7253de80707999f8cd Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 15:05:51 +0800 Subject: [PATCH 09/13] [CHORES] Reduce coverage calculation time --- jestSetup.js | 7 ------- src/components/core/WizardContainer/index.test.tsx | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/jestSetup.js b/jestSetup.js index 2aea538..53ba9b6 100644 --- a/jestSetup.js +++ b/jestSetup.js @@ -1,12 +1,5 @@ -import 'react-native-gesture-handler/jestSetup'; import { jest } from '@jest/globals'; import mockAsyncStorage from '@react-native-community/async-storage/jest/async-storage-mock'; -jest.mock('react-native-reanimated', () => { - const Reanimated = require('react-native-reanimated/mock'); - Reanimated.default.call = () => {}; - return Reanimated; -}); - jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper'); jest.mock('@react-native-community/async-storage', () => mockAsyncStorage); diff --git a/src/components/core/WizardContainer/index.test.tsx b/src/components/core/WizardContainer/index.test.tsx index c9cd624..875af9e 100644 --- a/src/components/core/WizardContainer/index.test.tsx +++ b/src/components/core/WizardContainer/index.test.tsx @@ -39,10 +39,10 @@ describe('WizardContainer component', () => { }); it('shows finish button in the last component', () => { - const { findByText } = render( + const { queryByText } = render( , ); - const finishButton = findByText(/Selesai/i); + const finishButton = queryByText(/Selesai/i); expect(finishButton).toBeTruthy(); }); }); -- GitLab From 131d3fe37e8a587b0ce89d893e9f158f60257074 Mon Sep 17 00:00:00 2001 From: wulanmantiri Date: Mon, 5 Apr 2021 15:06:50 +0800 Subject: [PATCH 10/13] [CHORES] Setup different docker image for each stage --- .gitlab-ci.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a5f982c..3602d74 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,3 @@ -image: reactnativecommunity/react-native-android - cache: key: ${CI_COMMIT_REF_SLUG} paths: @@ -15,6 +13,7 @@ stages: - build test: + image: node:slim stage: test before_script: - yarn install @@ -25,10 +24,12 @@ test: - coverage lint: + image: node:slim stage: lint + before_script: + - yarn install script: - yarn lint - - yarn prettify pbi-sonar-scanner: image: @@ -62,6 +63,7 @@ sonar-scanner: - master android: + image: reactnativecommunity/react-native-android stage: build before_script: - yarn install -- GitLab From 8cace26d84f3c80aa52bbe523dcecdabf5dabf53 Mon Sep 17 00:00:00 2001 From: Doan Andreas Nathanael Date: Mon, 5 Apr 2021 20:09:38 +0700 Subject: [PATCH 11/13] [GREEN] integrate dietela quiz result test with new render utilities --- .../questionnaire/DietelaQuizResult/index.test.tsx | 12 ++++++++++++ src/scenes/questionnaire/DietelaQuizResult/kek.txt | 11 ----------- 2 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 src/scenes/questionnaire/DietelaQuizResult/index.test.tsx delete mode 100644 src/scenes/questionnaire/DietelaQuizResult/kek.txt diff --git a/src/scenes/questionnaire/DietelaQuizResult/index.test.tsx b/src/scenes/questionnaire/DietelaQuizResult/index.test.tsx new file mode 100644 index 0000000..8418da7 --- /dev/null +++ b/src/scenes/questionnaire/DietelaQuizResult/index.test.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { render } from 'utils/testing'; +import * as ROUTES from 'constants/routes'; + +import DietelaQuizResult from '.'; +import { mockQuizResult } from 'mocks/quizResult'; + +describe('DietelaQuizResult', () => { + it('renders correctly', () => { + render(, ROUTES.dietelaQuizResult, mockQuizResult); + }); +}); diff --git a/src/scenes/questionnaire/DietelaQuizResult/kek.txt b/src/scenes/questionnaire/DietelaQuizResult/kek.txt deleted file mode 100644 index 75fef9f..0000000 --- a/src/scenes/questionnaire/DietelaQuizResult/kek.txt +++ /dev/null @@ -1,11 +0,0 @@ -// import React from 'react'; -// import { render } from 'utils/testing'; -// import * as ROUTES from 'constants/routes'; - -// import DietelaQuizResult from '.'; - -// describe('DietelaQuizResult', () => { -// it('renders correctly', () => { -// render(, ROUTES.dietelaQuizResult); -// }); -// }); -- GitLab From 49daba1902062ca26fd3512283e4010988076388 Mon Sep 17 00:00:00 2001 From: Doan Andreas Nathanael Date: Mon, 5 Apr 2021 20:35:47 +0700 Subject: [PATCH 12/13] [GREEN] add test for result page content --- .../pages/ResultPage/index.test.tsx | 139 +++++++++++------- 1 file changed, 87 insertions(+), 52 deletions(-) diff --git a/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx b/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx index 315f0df..ff4cbd6 100644 --- a/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx +++ b/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx @@ -5,66 +5,101 @@ import * as ROUTES from 'constants/routes'; import ResultPage from '.'; describe('ResultPage', () => { + const infos = [ + { + label: 'Indeks massa tubuh', + content: '31.6', + }, + { + label: 'Status', + content: 'Obesitas 2', + }, + ]; + + const heightWeightData = { + header: 'Dihitung berdasarkan data:', + content: { + statistics: [ + [ + { + label: 'berat badan', + emote: '⚖️', + content: '77 kg', + }, + { + label: 'tinggi badan', + emote: '📐', + content: '156 cm', + }, + ], + ], + }, + }; + + const weightRecommendation = { + header: + 'Untuk orang dengan tinggi 156 cm, berikut rentang berat badan yang ideal:', + content: { + statistics: [ + [ + { + label: 'minimal', + emote: '◀️', + content: '46.2 kg', + }, + { + label: 'maksimal', + emote: '▶️', + content: '55.9 kg', + }, + ], + ], + textCard: ['Usahakan berat badan kamu masuk ke rentang ideal, ya!'], + }, + }; + const content = { title: 'Status Berat Badan', mainInfo: { - infos: [ - { - label: 'Indeks massa tubuh', - content: '31.6', - }, - { - label: 'Status', - content: 'Obesitas 2', - }, - ], + infos: infos, status: 'healthy', }, - sections: [ - { - header: 'Dihitung berdasarkan data:', - content: { - statistics: [ - [ - { - label: 'berat badan', - emote: '⚖️', - content: '77 kg', - }, - { - label: 'tinggi badan', - emote: '📐', - content: '156 cm', - }, - ], - ], - }, - }, - { - header: - 'Untuk orang dengan tinggi 156 cm, berikut rentang berat badan yang ideal:', - content: { - statistics: [ - [ - { - label: 'minimal', - emote: '◀️', - content: '46.2 kg', - }, - { - label: 'maksimal', - emote: '▶️', - content: '55.9 kg', - }, - ], - ], - textCard: ['Usahakan berat badan kamu masuk ke rentang ideal, ya!'], - }, - }, - ], + sections: [heightWeightData, weightRecommendation], }; it('renders correctly', () => { render(, ROUTES.dietelaQuizResult); }); + + it('shows the correct content', () => { + const { getByText } = render( + , + ROUTES.dietelaQuizResult, + ); + + // Check for result page title + expect(getByText(content.title)).toBeTruthy(); + + // Check for each info + infos.forEach((info) => { + expect(getByText(info.label)).toBeTruthy(); + expect(getByText(info.content)).toBeTruthy(); + }); + + // Check for height & weight data shows correct statistics + expect(getByText(heightWeightData.header)).toBeTruthy(); + heightWeightData.content.statistics[0].forEach((stats) => { + expect(getByText(stats.label)).toBeTruthy(); + expect(getByText(stats.emote)).toBeTruthy(); + expect(getByText(stats.content)).toBeTruthy(); + }); + + // Check for weight recommendation shows correct statistics + expect(getByText(weightRecommendation.header)).toBeTruthy(); + weightRecommendation.content.statistics[0].forEach((stats) => { + expect(getByText(stats.label)).toBeTruthy(); + expect(getByText(stats.emote)).toBeTruthy(); + expect(getByText(stats.content)).toBeTruthy(); + }); + }); }); -- GitLab From 84f1d827fc05a4c4d768f26cacbd62c5cada336e Mon Sep 17 00:00:00 2001 From: Doan Andreas Nathanael Date: Mon, 5 Apr 2021 20:40:36 +0700 Subject: [PATCH 13/13] [GREEN] add test for result page with CTA button --- .../DietelaQuizResult/pages/ResultPage/index.test.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx b/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx index ff4cbd6..e6a5af3 100644 --- a/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx +++ b/src/scenes/questionnaire/DietelaQuizResult/pages/ResultPage/index.test.tsx @@ -71,6 +71,16 @@ describe('ResultPage', () => { render(, ROUTES.dietelaQuizResult); }); + it('renders correctly when there is CTA button', () => { + render( + , + ROUTES.dietelaQuizResult, + ); + }); + it('shows the correct content', () => { const { getByText } = render( , -- GitLab