Detox your React Native AWS Amplify Authentication.

Frikan Erwee
6 min readJun 14, 2018

--

We have all heard about testing our code. About unit-tests, integration-tests and smoke-tests (when first I heard about this type, I figured it was when you mash buttons so fast your device literally catches fire).

Testing, who has the time?

We try and try to make time to write them, but for most of us writing tests seems an impossible task as we do not know where to start. After a while we believe that writing tests are like exercise and eating healthy; it happens mostly to other people. We go on and hope one day we will reach that point where we can write a test or two.

But what if I told you writing tests was like learning a new framework or implementing a new package. It is slow at first then before you know it you have testing in place for production code with all the advantages it brings. This can save you from those embarrassing calls from a client about your app not behaving as it should.

To help you get started I chose one of our most recent tech stacks namely aws-amplify and react-native to write a test for its authentication flow. The gatekeepers to most apps are sign up, sign in and sign out, we all have to write code for an authentication flow some time or an other. We all want to know that the first code our user uses is stable and working, being the first impression of our app.

Your welcome here dear user. [image by Lisa Walton on Unsplash]

Requirements

You will need to have the following in place:

  1. A working authentication flow using the aws-amplify in your react-native app.
  2. aws-cli installed on your system
  3. Your aws enviromental varaible set for example :

export AWSKEY=”A123456342A”

export AWSSECRET=”v12341234fd9+g234/fo81234+jpnojK”

4.awsmobile-cli installed and configured.

5. aws-cli-js package [ This will make your test fully automated ]

If you need help setting it all up, the follow links will get you started:

I will explain the following code using an example app hooked up to a standing AWS app instance at this repo: https://github.com/FrikanRw/Amplify---Detox

The authentication flow is very simple and I will be using react-native-router flux for the navigation. I will not go to deep into it, but if you require some more details on the code, please don’t hesitate to contact me directly.

Now to the reason we are here…

There are a lot of tutorials on testing, and thus I will not go into the philosophy of it all. I will suggest though that you use the ‘get-started’ section from Detox to get started.

In my repo there are two test files, namely signupTest.spec.js and signinTest.spec.js. Below you will find a quick view of both these files and an explanation of the flow thereof.

signupTest.spec.js

In this file the test:

  • reloads the app
  • looks for a landing page [ a view with the testID →landingPage]
  • goes to the sign up page
  • fills in the form with details that are valid
  • and taps the sign up button
  • goes to the email verification page
  • taps the verify email button
  • waits for the verification to take place
  • and the taps check for the verification
  • lastly it needs to look for the welcome page

signinTest.spec.js

In this file the test:

  • reloads the app
  • looks for a landing page
  • goes to the sign in page
  • fills in the form with details that are valid
  • lastly it needs to look for the welcome page

We also have a helper.js-file that contains all of our helper functions. The first of these functions are used to take screenshots after each test and is called takeScreenshot. It uses xcrun simctl which is a command line control for ios simulators.The deleteTestUser() function deletes the test user account we create when signing up. This keeps our initial state of the user as non-existing before signing up, and for extra bonus points we have a confirmTestUser() which confirms the user after the sign-up call. Both of these use aws-cli-js to run the required commands.

Some general notes:

We always want to have the app at a known state for the test to start at; In the code this is achieved with:

await device.reloadReactNative();

Helper functions are great for mimicking user actions. In our most recent project we dived more deeply into the following:

  • sent coordinates to test different locations.
  • recorded parts of the test using the simulator screen.
  • used some helper to trigger the react-native debugger to start remote debugging which allowed us some more insight into the code while the tests were running.

There are however some obscure drawbacks:

The confirmUser triggers the cognito event on AWS, but sends a false on the email confirmation. Luckily it was not a breaking situation for most of our testing, but keep this in mind if something is not functioning as expected.

when you run:

 detox test

You will be greeted by a whirrrr of code from you command line:

detox-server info 11:23:35: server listening on localhost:58962…
detox info 2: Searching for device matching iPhone 6…
detox info 4: Uninstalling org.reactjs.native.example.AWSDetox…
detox info 4: org.reactjs.native.example.AWSDetox uninstalled
detox info 5: Installing /Users/frikanerwee/repos/Amplify_Detox/ios/build/Build/Products/Debug-iphonesimulator/AWSDetox.app…
detox info 5: /Users/frikanerwee/repos/Amplify_Detox/ios/build/Build/Products/Debug-iphonesimulator/AWSDetox.app installed
detox info 6: Terminating org.reactjs.native.example.AWSDetox…
detox info 6: org.reactjs.native.example.AWSDetox terminated
detox info 7: Launching org.reactjs.native.example.AWSDetox…
detox info 7: org.reactjs.native.example.AWSDetox launched. The stdout and stderr logs were recreated, you can watch them with:
tail -F $HOME/Library/Developer/CoreSimulator/Devices/0C30D23E-3E90–4AED-A920–29AF26734696/data/tmp/detox.last_launch_app_log.{out,err}
Sign in Flow — Actions
✓ should have landing screen & tap SIGN IN (1845ms)
Wrote screenshot to: /tmp/screenshots/screenshot-0.png
✓ should have sign in screen & sign in button (5110ms)
Wrote screenshot to: /tmp/screenshots/screenshot-1.png
✓ should have welcome page (3670ms)
Wrote screenshot to: /tmp/screenshots/screenshot-2.png
Sign up Flow — Actions
✓ should have landing screen & tap SIGN UP (2205ms)
Wrote screenshot to: /tmp/screenshots/screenshot-3.png
Test User deleted
✓ should have sign up screen & able to fill in required details (12821ms)
Wrote screenshot to: /tmp/screenshots/screenshot-4.png
✓ should have email verification screen and tap on required buttons and proceed to homepage (4575ms)
Wrote screenshot to: /tmp/screenshots/screenshot-5.png
✓ should have welcome page (1828ms)
Wrote screenshot to: /tmp/screenshots/screenshot-6.png
Test User confirmed
7 passing (41s)

A short summary of your tests awaits you, with the sweet sign that your code has passed.

Below are some of the screen shots from the testing:

start of the test
after sign in
after sign in

I hope that this article inspires you to write tests.

I hope that this article inspires you to write tests. This not only tested the application but the whole system. In the heat of a looming deadline, we had to integrate a last feature and could test the whole codebase knowing that we will did not break any of our original features.. Running tests in this manner had the added benefit of not just testing the app, but the system as a whole..

Thank you to the following people:

Carlo; his article that got me onto helpers and writing some of my own (His code was used in the screenshot helper): https://medium.com/async-la/e2e-testing-react-native-with-detox-screenshots-595146073863

George; my colleague and friend that keeps me humble and hammered me to write this article.

Fabio; my recent front-end partner for also enjoying to hear the clicks of the ios-sim when our test runs. Giving the back-end a run for their money.

Elri and Lily; my wife and daughter for their support on all my side-projects.

--

--