- NestJS
- Supabase
- React
- TailwindCSS
- Authentication via Supabase
- User can view the countries of the world, including where it is in the world, details of the country, current weather and more.
- Option to filter countries via region or search
- Dark/Light mode for user preference
- Authenticated user has the option to favorite, unfavorite and view favorites.
This project has given me the opportunity to learn about state management using Redux.
The idea behind state management in react remains the same among most state management libraries:
- Creating the context
- Connecting the context
- Providing the context
- Listening for change
Something I've been curious about for a while and I finally got to try it.
Basically you're able to add styling via classes and the class names are very self-explanatory.
Pros:
- I don't have to dig through a long CSS file or multiple CSS files to edit the styling
- Syntax is easy with a very nice Cheat Sheet to look through
Cons:
- Components can become cluttered
I never thought I would enjoy testing as much as I do. But when seeing E2E testing in action using Cypress I was pleasantly surprised. It's a great tool I will definitely bring with me in my future projects.
What I had to do:
- Create a .yml file
// .github/workflows/main.yml
name: Run Cypress Tests
on:
push:
branches-ignore:
- starter
Here I have:
- Defined a name for the workflow ("Run Cypress Tests")
- Defined what events trigger the workflow ("on: push")
- Defined which branches the workflow will run (All branches except "starter")
After a lot of trial and error I figured out how to set up the jobs
// cont..
jobs:
cypress:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Build project
run: npm run build
- name: Run Cypress tests
run: npm run e2e:dev
env:
VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
VITE_WEATHER_API_KEY: ${{ secrets.VITE_WEATHER_API_KEY }}
VITE_GOOGLE_MAPS_API_KEY: ${{ secrets.VITE_GOOGLE_MAPS_API_KEY }}You can have multiple jobs in a workflow but for this one we only need one.
In defaults I define default settings for the workflow. In this case, I only want the testing to run in the frontend directory, since that's what we'll be testing.
The different steps of that specific job that will be run.
For this job, these are the steps that the job is performing:
Each step has a name, and a corresponding command (run)
-
Checking out repository (Still need to research this one)
-
Setting up Node
-
Installing dependencies
-
Build the project
-
Running the tests
Setting up the environment variables for github actions is actually really simple.
Before adding them to the .yml file, I had to add the variables to my repository settings on github.
Navigate to:
https://github.com/USER_NAME/REPOSITORY_NAME/settings/secrets/actions
Here you can add the secrets (aka env variables) the project uses. It's important these are named the same as in the code. Then, you add them to the workflow using the following syntax:
- name: Run Cypress tests
run: npm run e2e:dev
env:
VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
VITE_WEATHER_API_KEY: ${{ secrets.VITE_WEATHER_API_KEY }}
VITE_GOOGLE_MAPS_API_KEY: ${{ secrets.VITE_GOOGLE_MAPS_API_KEY }}- Creating
There are multiple ways of creating the cypress environment variables.
I chose to do this in a cypress.env.json file
{
"TEST_USER_EMAIL": "[email protected]",
"TEST_USER_PW": "password_here"
}- Access in test
cy.get('#email').type(Cypress.env('TEST_USER_EMAIL'));- Access in .yml
- name: Run Cypress tests
run: npm run e2e:dev
env:
VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
VITE_WEATHER_API_KEY: ${{ secrets.VITE_WEATHER_API_KEY }}
VITE_GOOGLE_MAPS_API_KEY: ${{ secrets.VITE_GOOGLE_MAPS_API_KEY }}
CYPRESS_TEST_USER_EMAIL: ${{ secrets.CYPRESS_TEST_USER_EMAIL }}
CYPRESS_TEST_USER_PW: ${{ secrets.CYPRESS_TEST_USER_PW }}When creating some of my test, I had to make sure the requests had finished before navigating to another site. At first I used .wait(ms), but it seemed time-inefficient to do so. That's when I found out about the built in method .intercept. This method allows you to spy on requests.
cy.intercept(
'POST',
`${Cypress.env('SUPABASE_URL')}/rest/v1/country_favorites*`
).as('favoriteRequest');
cy.get('button[data-test-id="favorite-button"]').first().click();
cy.wait('@favoriteRequest');Some cool things about this snippet:
- The request is intercepted using the METHOD and URL.
- The interception is given an alias "favoriteRequest"
- After the request is made, Cypress spies on it and waits for it to complete.
The problem:
When deploying an app that uses react-router-dom with netlify the routes don't work, as in directly going to a route like /home or /login would result in a "Page not found" error, although these routes do exist in the project.
The solution:
Super simple, add a \_redirects file in the projects public folder.
In this file, add /* /index.html 200. Now any request goes through index.html which is where we have our script + routes.