Online Food Ordering App (7)
Bertrand Masabo
Posted on March 5, 2021
Hi, Welcome to part 7 of this series.
Today, we are going to implement authentication on our front-end apps.
We are going to start with the admin web app then proceed with the mobile app.
Let us begin with the admin web app (gourmet-admin)
.
Make sure the main branch is up to date with the remote main branch
Create a new
ft-authentication
branch off the main branchIn your terminal, run the following command to install the packages we are going to be using:
yarn add @material-ui/core @material-ui/icons @material-ui/lab axios cross-env history parcel parcel-bundler react-hook-form react-router-dom
- Install dev-dependencies:
yarn add -D axios-mock-adapter @babel/core @babel/preset-env @babel/preset-react
Inside
src
directory create the following directories:components, context, navigation, pages, and utils
.Inside
src/components
directory create the following directories:CustomDrawer, FormButton, FormInput, Loader, Title, and ToastNotification
.
I have seen a lot of people who like to put their test files in a separate __tests__
directory in the project root and it is totally fine. For me though, I like it when a test file is right next to the component it is supposed to test. I think it makes more sense this way.
That being said, we are going to be creating a component with its test file in the same directory.
Let's start with a title component that we will use throughout our app to display page titles or headings.
Inside
src/components/Title
create two files:Title.js
andTitle.test.js
Do not pay attention to that import of render and screen on the second line for now. We will implement src/customRender.js
before running our tests.
Cool!
- Implement the remaining components like here
Let us now create a reducer that we will use to update our authentication state.
Create a
src/context/reducers/authReducer.js
and paste the following inside:
Create a
src/contenxt/AuthState.js
and paste the following inside:
Create a
src/utils/history.js
and paste the following inside:
Create a
src/context/theme.js
file and paste the following inside:
Before creating the navigation of our app, let us create the three pages we will need for the authentication feature namely LoginPage
, Dashboard
, and NotFound
.
Inside
src/pages
create the following directories:Dashboard
,LoginPage
, andNotFound
Create a
src/pages/NotFound/NotFound.js
file and paste the following inside:
Create a
src/pages/Dashboard/index.js
file and paste the following inside:
Create a
src/pages/LoginPage/LoginPage.js
file and paste the following inside:
Create a
src/utils/validations.js
file and paste the following inside:
Create a
src/utils/api.js
file and paste the following inside:
Now we can create our routes and app navigation.
What we want to achieve is when a user (admin) visits our web app, he will land on our login page then when he logs in, he will be redirected to the dashboard.
Let us implement a wrapper route that we will use to render protected routes like the dashboard.
Create a
src/navigation/ProtectedRoute.js
file and paste the following inside:
Create a
src/navigation/Routes.js
file and paste the following inside:
Now we need to wrap our routes with our AuthProvider so that our components can have access to our state and ThemeProvider to be able to use Material UI components.
- Create a
src/navigation/index.js
file and paste the following inside:
Now we just need to hook this Providers component in our main App and we are good to go.
- Update
src/App.js
to look like the following:
Let us now update our scripts in package.json
and launch our app.
Now run
yarn start --open
to tell Parcel to build our app and launch it athttp://localhost:1234
.
When the app launches it should look like the image below:
Great!
Let us now take care of our tests.
Learn more about how this file is useful here.
- Create a
src/pages/LoginPage.test.js
and paste the following inside:
In this file we are testing if the page renders correctly, validation errors then we mock HTTP requests to our API to test scenarios such as when there is a network issue, when the user trying to login does not exist or when the user exists but he/she is not an admin and finally we test a successful login.
- Run
yarn test
to run the unit and integration tests with Jest. When the test runner finishes you should see each test file's status and the test coverage.
At the moment I have 96% coverage which is not bad. You could use the coverage table to investigate the uncovered lines and write either unit tests or integration tests to cover them and increase coverage.
Now we can commit our changes to GitHub and open a PR to trigger a build on CircleCI.
If all goes well, go ahead and merge the PR and we can proceed with the mobile app.
For reference, check out this branch
For our mobile app we need to implement sign up on top of login and logout.
Let's do it.
Switch to the
Gourmet
project directory that we created in the previous post and make sure the main branch is up to date with its remoteCreate a new
ft-authentication
branch off the main branchInstall dependencies by running:
yarn add @react-native-async-storage/async-storage @react-navigation/native @react-navigation/stack @react-native-community/masked-view react-native-gesture-handler react-native-reanimated react-native-safe-area-context react-native-screens react-native-paper react-native-vector-icons react-hook-form axios prop-types
- Install additional dev-dependencies:
yarn add -D axios-mock-adapter
Inside
src
create the following directories:components, context, navigation, screens, and utils
and in each directory create a component file and its test file like hereCreate a new
src/utils/storage.js
file and paste the following inside:
This code will help us to interact with the storage by using the AsyncStorage package to create, fetch, and delete data.
Create a new
src/utils/validations.js
and paste the following inside:
Create a new
src/utils/api.js
file and paste the following code inside:
Let us now create our context providers and consumers.
Create a new directory
reducers
insrc/context/
Create a new
src/context/reducers/AuthReducer.js
file and paste the following code inside:
Create a new
src/context/reducers/AlertReducer.js
file and paste the following code inside:
Create a new
src/context/AuthProvider.js
file and paste the following code inside:
Create a new
src/context/AlertProvider.js
file and paste the following code inside:
Create a new
src/context/theme.js
file and paste the following code inside:
Now we can create the first screens of our app. We are going to create a signup screen, verify screen, login screen, and home screen
. The home screen
will only be visible to logged in users. Let us first create the screens then we can separate them in AustStack
and HomeStack
.
Inside
src/screens
create the following directories:HomeScreen
,LoginScreen
,SignupScreen
, andVerifyScreen
Inside
src/screens/SignupScreen
create two files:SignupScreen.js
andSignupScreen.test.js
Inside
src/screens/SignupScreen/SignupScreen.js
paste the following code:
Inside
src/screens/SignupScreen/SignupScreen.test.js
paste the following code:
Inside
src/screens/VerifyScreen
create two files:VerifyScreen.js
andVerifyScreen.test.js
Inside
src/screens/VerifyScreen/VerifyScreen.js
paste the following code:
Inside
src/screens/VerifyScreen/VerifyScreen.test.js
paste the following code:
Inside
src/screens/LoginScreen
create two files:LoginScreen.js
andLoginScreen.test.js
Inside
src/screens/LoginScreen/LoginScreen.js
paste the following code:
Inside
src/screens/LoginScreen/LoginScreen.test.js
paste the following code:
Inside
src/screens/HomeScreen
create two files:HomeScreen.js
andHomeScreen.test.js
Inside
src/screens/HomeScreen/HomeScreen.js
paste the following code:
Inside
src/screens/HomeScreen/HomeScreen.test.js
paste the following code:
Create a new
src/navigation/AuthStack.js
file and paste the following code inside:
Create a new
src/navigation/HomeStack.js
file and paste the following code inside:
Create a new
src/navigation/Routes.js
file and paste the following code inside:
Create a new
src/navigation/__tests__
directory and inside create aRoutes.test.js
file with the following content:
Now let us wrap our routes with the providers we created earlier and the React-Native-Paper provider.
- Update
src/App.js
file to look like the following:
If we were to run our tests they would fail because we haven't yet wrapped our providers around components and screens in the test environment. To do so, update test-utils.js
to look like the following:
Now run the tests again and they should pass.
If you get errors make sure jest.config.js, jest.setup.js, and setupFiles.js
look like below and run tests again:
Alternatively, you can run the app on your emulator or physical device to test that everything works as it should.
That's it for today! Push the authentication branch to GitHub, open a PR, wait for the Continuous Integration
workflow to succeed then merge the PR.
For reference, check out this branch.
In the next post, we will wrap up this series with the following features:
- Place order (mobile app)
- View orders list (mobile app and admin web app)
- View single order details (mobile app and admin web app)
Thank you for your time. See you in the next post!
Posted on March 5, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.