This is the final project for the 2nd part of the Frontend Engineering Advanced course, offered by the University Ost in Rapperswil.
We had to develop a Chat App based on NextJS in a given Mumble Design according to the specification of Mumble-Figma-Design. We had the requirement to use our previously developed Component Library for our Chat App.
- Introduction
- Getting started
- Add Credentials
- Add .env vars
- Installation
- Start the App
- Testing
- Features
- Live Demo
- Resources
- Project Status
- Design System Component Library Version
- Contributors
In the next steps you will setup the chat app.
Please use node version 16.19.1. If you use nvm you can use the following command.
nvm use 16.19.1
We need a github token and a .npmrc to get access to the mumble npm package at smartive education on github.
Create github token and add to .npmrc
To authenticate by adding your personal access token (classic) to your ~/.npmrc file, edit the ~/.npmrc file for your project to include the following line, replacing TOKEN with your personal access token. Create a new ~/.npmrc file if one doesn’t exist.
//npm.pkg.github.com/:_authToken=TOKEN
Create .npmrc in the project folder, where you wanna add your npm package and add following line
@smartive-education:registry=https://npm.pkg.github.com
Create a new .env file in the root directory. I have sent you an email with the .env vars. Please copy them into the newly created .env file.
Now, you should be able to start the application.
git clone https://github.com/smartive-education/app-yeahyeahyeah.git
cd app-yeahyeahyeah
npm install
npm run dev
npm run build
npm start
The application is equipped with the following features.
- Almost real-time feeling, thanks to SWR. :)
- Write messages (mumble) with text and an image (optional).
- Search detail page, where you can navigate through #hashtags.
- Rate messages with a like.
- Comment on existing messages.
- Delete your own messages as needed.
You can view a live demo at www.mumble-yeahyeahyeah.ch. Please note that you must have a valid and active account on Zitadel.
You can view a live demo at Google Cloud. Please note that you must have a valid and active account on Zitadel.
Run tests in watch mode
npm run test
Run tests once
npm run test:ci
Run tests in silent mode (without warnings)
npm run test:ci-silent
Run tests once with coverage report
npm run test:ci-coverage
Run tests in debug mode
npm run test:debug
Before the first run, you have to install the default browsers for playwright.
npx playwright install
Now you can run the tests.
Run all tests in headless mode:
npm run test:e2e
Run tests in headful mode
npm run test:e2e:headful
All end-to-end tests can be initiated locally in isolation. Each test run generates a test message (globalSetup) which is deleted after the run (globalTeardown). To run further tests individually, execute the following command:
npx playwright test
If you want to run the test run with chromium only, use:
npx playwright test --project=chromium
Alternatively, the debug mode can be used. After each command the --debug option is applied for this purpose. Here are a few examples to run tests.
npx playwright test -g 'should comment an article' --project=chromium
npx playwright test -g 'should like it or not' --project=chromium
npx playwright test -g 'should click on hashtag' --project=chromium
npx playwright test -g 'should post no message' --project=chromium
npx playwright test -g 'should list created message and liked article' --project=chromium
- Chromium
- Firefox
- Webkit
- Mobile Chrome
- Mobile Safari
- Microsoft Edge
- Google Chrome
Apply this command to switch the browser. Here is an example for the Edge browser:
npx playwright test --project='Microsoft Edge'
Monkey testing can help identify issues such as:
- Application crashes
- Unexpected behavior or responses
- Memory leaks
- Performance issues
Monkey testing can be performed manually or automated using various tools and libraries, such as gremlins.js for web applications, which simulates random user interactions on a web page.
While monkey testing can uncover issues that might not be found through structured testing, it is not a substitute for other testing techniques, such as unit testing, integration testing, or end-to-end testing. Monkey testing should be used as a complementary approach to more targeted and structured testing methods.
At the moment, the monkey tests are not very stable. Therefore, the tests are not executed in the CI pipeline. However, you can run the tests locally. If the test fails, it will be repeated until it succeeds (up to 20 times).
Run monkey tests in headless mode:
npm run test:monkeytest
Run monkey tests in headful mode:
npm run test:monkeytest:headful
We perform 6 hourly testing with Playwright to check endpoints for availability. The app that is installed on Google Cloud is checked. Additionally, the Qwacker API posts are tested for availability. The availability test can be executed directly with this command:
npx playwright test --project=chromium -g '@healthcheck' --config=./playwright.checks.config.ts
User testing was performed for this application. The testing was done by a 15 year old girl with basic computer skills. As a result, it was concluded that the image upload needs to be improved. The user test can be viewed here: Mumble App - User Testing.
Test the docker image locally.
docker build -t app-yeahyeahyeah . --build-arg NPM_TOKEN=$NPM_TOKEN
docker run -p 3000:3000 --env-file .env --rm --name app-yeahyeahyeah app-yeahyeahyeah
Hint: If you build the image on a mac with an M1 chip and you wanna use the image for example on a linux/amd64 machine,
you should use the --platform=linux/amd64
flag in your Dockerfile to build the image for this specific platform.
docker build -t europe-west6-docker.pkg.dev/casfea22/app-yeahyeahyeah-docker/app-yeahyeahyeah . --build-arg NPM_TOKEN=$NPM_TOKEN
docker run -p 3000:3000 --env-file .env --rm --name app-yeahyeahyeah europe-west6-docker.pkg.dev/casfea22/app-yeahyeahyeah-docker/app-yeahyeahyeah:latest
docker push europe-west6-docker.pkg.dev/casfea22/app-yeahyeahyeah-docker/app-yeahyeahyeah
Here are a few steps, if you want to deploy the application on Google Cloud.
First of all you have to create a new project.
gcloud projects create PROJECT_ID --name=PROJECT_NAME --set-as-default
Next you have to enable billing for your project, otherwise you can't use any services.
gcloud beta billing projects link PROJECT_ID --billing-account=BILLING_ACCOUNT_ID
You will have to enable a few APIs for your project. Below are some of them listed. Maybe there are more APIs that you have to enable.
gcloud services enable artifactregistry.googleapis.com
gcloud services enable cloudapis.googleapis.com
gcloud services enable cloudbuild.googleapis.com
gcloud services enable clouddeploy.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable containerregistry.googleapis.com
gcloud services enable datastore.googleapis.com
gcloud services enable iam.googleapis.com
gcloud services enable iamcredentials.googleapis.com
gcloud services enable run.googleapis.com
gcloud services enable secretmanager.googleapis.com
gcloud services enable servicemanagement.googleapis.com
gcloud services enable storage-api.googleapis.com
gcloud services enable storage-component.googleapis.com
gcloud services enable storage.googleapis.com
The storage bucket is in our case used for the terraform state.
gsutil mb -p PROJECT_ID -c STANDARD -l europe-west6 -b on gs://BUCKET_NAME
With the Secret Manager you can store your secrets in a secure way. Below is an example how you can create a secret. You can also use the UI to create a secret. In the Terraform section you can see how to read these secrets.
echo -n "SUPERSECRET" | gcloud secrets create "nextauth_secret" \
--data-file - \
--replication-policy "automatic"
With our terraform configuration, we can create a new project on Google Cloud and deploy our application. First you have to install terraform on your machine.
terraform init
You can use this command to check whether the proposed changes match what you expected before you apply the changes or share your changes with your team for broader review.
terraform plan
-out=FILENAME
- Writes the generated plan to the given filename in an opaque file format that you can later pass to terraform apply to execute the planned changes, and to some other Terraform commands that can work with saved plan files.
terraform plan -out=FILENAME
When you run terraform apply without passing a saved plan file, Terraform automatically creates a new execution plan as if you had run terraform plan, prompts you to approve that plan, and takes the indicated actions.
You can pass the -auto-approve option to instruct Terraform to apply the plan without asking for confirmation.
terraform apply -auto-approve
With the Secret Manager you can store your secrets in a secure way. Below is an example how you can create a secret. You can also use the UI to create a secret.
echo -n "SUPERSECRET" | gcloud secrets create "nextauth_secret" \
--data-file - \
--replication-policy "automatic"
Permission "roles/secretmanager.secretAccessor" is needed to access the secret manager. Add this role to "google_project_iam_member" "cloud-runner". Following code snippet shows how to add the role.
resource "google_project_iam_member" "cloud-runner" {
for_each = toset([
"roles/run.serviceAgent",
"roles/viewer",
"roles/storage.objectViewer",
"roles/run.admin",
"roles/cloudsql.client",
"roles/secretmanager.secretAccessor",
])
role = each.key
member = "serviceAccount:${google_service_account.cloud-runner.email}"
project = data.google_project.project.id
}
To access a secret from Google Secret Manager, use the google_secret_manager_secret_version data
source:
data "google_secret_manager_secret_version" "nextauth_secret" {
provider = google
secret = "nextauth_secret"
version = "1"
}
output "secret" {
value = data.google_secret_manager_secret_version.my-secret.secret_data
}
If you rename the name of the service or delete the service and create a new one, you will have to delete the actual state value ("casfea22-tf-state") in the bucket. Following code snippet shows the name of the service, that has to be changed.
locals {
name = "app-yeahyeahyeah"
gcp_region = "europe-west6"
}
You will also have to delete the service account, because the service account will be created during the first terraform run and will not be deleted if you rename the service.
If you deleted the service account, or you want to create a new one with terraform, you will have to add the following roles to the service account.
Necessary permissions for the service account that is used for terraform deployment.
gcloud projects add-iam-policy-binding casfea22 \
--member='serviceAccount:[email protected]' \
--role='roles/resourcemanager.projectIamAdmin'
gcloud projects add-iam-policy-binding casfea22 \
--member='serviceAccount:[email protected]' \
--role='roles/iam.serviceAccountAdmin'
We use the Github Action auth with Workload Identity Federation to authenticate with Google Cloud.
Workload Identity Federation is recommended over Service Account Keys as it obviates the need to export a long-lived credential and establishes a trust delegation relationship between a particular GitHub Actions workflow invocation and permissions on Google Cloud.
You will find a lot of examples at their [google-github-actions repo]](https://github.com/google-github-actions/auth#setup).
- Create a Google Cloud service account and grant IAM permissions
- Create and configure a Workload Identity Provider for GitHub
- Exchange the GitHub Actions OIDC token for a short-lived Google Cloud access token
-
For authenticating via Workload Identity Federation, you must create and configure a Google Cloud Workload Identity Provider. See setup for instructions.
-
You must run the
actions/checkout@v3
step before this action. Omitting the checkout step or putting it afterauth
will cause future steps to be unable to authenticate. -
If you plan to create binaries, containers, pull requests, or other releases, add the following to your
.gitignore
to prevent accidentially committing credentials to your release artifact:# Ignore generated credentials from google-github-actions/auth gha-creds-*.json
-
This action runs using Node 16. If you are using self-hosted GitHub Actions runners, you must use runner version 2.285.0 or newer.
jobs:
release:
name: Create Release
runs-on: ubuntu-latest
# Add intended permissions.
permissions: write-all
steps:
# actions/checkout MUST come before auth
- uses: actions/checkout@v3
- id: 'auth'
name: 'Authenticate to Google Cloud'
uses: 'google-github-actions/auth@v1'
with:
workload_identity_provider: 'projects/655814648425/locations/global/workloadIdentityPools/casfea22-pool/providers/casfea22-provider'
service_account: '[email protected]'
token_format: 'access_token'
# login to Artifact Registry
- name: Login to Google Artifact Registry
uses: docker/login-action@v2
with:
registry: europe-west6-docker.pkg.dev
username: 'oauth2accesstoken'
# Use the access token from the auth step
password: '${{ steps.auth.outputs.access_token }}'
Note that changing the permissions
block may remove some default permissions.
See the [permissions documentation][github-perms] for more information.
See Examples for more examples. For help debugging common errors, see Troubleshooting