Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ jobs:
APPT_LOGIN_PWORD: ${{ secrets.E2E_APPT_PROD_LOGIN_PASSWORD }}
APPT_DISPLAY_NAME: ${{ secrets.E2E_APPT_PROD_DISPLAY_NAME }}
APPT_MY_SHARE_LINK: ${{ secrets.E2E_APPT_PROD_MY_SHARE_LINK }}
APPT_BOOKING_REQUESTER_EMAIL: ${{ secrets.E2E_APPT_PROD_BOOKING_REQUESTER_EMAIL }}
APPT_BOOKEE_EMAIL: ${{ secrets.E2E_APPT_PROD_BOOKEE_EMAIL }}
steps:
- uses: actions/checkout@v4

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
APPT_LOGIN_PWORD: ${{ secrets.E2E_APPT_PROD_LOGIN_PASSWORD }}
APPT_DISPLAY_NAME: ${{ secrets.E2E_APPT_PROD_DISPLAY_NAME }}
APPT_MY_SHARE_LINK: ${{ secrets.E2E_APPT_PROD_MY_SHARE_LINK }}
APPT_BOOKING_REQUESTER_EMAIL: ${{ secrets.E2E_APPT_PROD_BOOKING_REQUESTER_EMAIL }}
APPT_BOOKEE_EMAIL: ${{ secrets.E2E_APPT_PROD_BOOKEE_EMAIL }}
steps:
- uses: actions/checkout@v4

Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,43 @@ jobs:
- name: Test with vitest
run: |
cd ./frontend && npm run test -- --run

e2e-tests-browserstack:
name: e2e-tests-browserstack
needs: detect-changes
if: needs.detect-changes.outputs.validate-frontend == 'true' || needs.detect-changes.outputs.validate-backend == 'true'
runs-on: ubuntu-latest
environment: staging
env:
APPT_LOGIN_EMAIL: ${{ secrets.E2E_APPT_STAGE_LOGIN_EMAIL }}
APPT_LOGIN_PWORD: ${{ secrets.E2E_APPT_STAGE_LOGIN_PASSWORD }}
APPT_DISPLAY_NAME: ${{ secrets.E2E_APPT_STAGE_DISPLAY_NAME }}
APPT_MY_SHARE_LINK: ${{ secrets.E2E_APPT_STAGE_MY_SHARE_LINK }}
APPT_BOOKEE_EMAIL: ${{ secrets.E2E_APPT_STAGE_BOOKEE_EMAIL }}
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
cache-dependency-path: 'test/e2e/package-lock.json'

- name: Install dependencies
run: |
cd ./test/e2e
npm install

- name: BrowserStack Env Setup
uses: browserstack/github-actions/setup-env@master
with:
username: ${{ secrets.BROWSERSTACK_USERNAME }}
access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
project-name: 'Thunderbird Appointment'
build-name: 'E2E Tests: BUILD_INFO'

- name: Run E2E Tests on Browserstack
run: |
cd ./test/e2e
cp .env.stage.example .env
npm run e2e-test-browserstack-gha
3 changes: 1 addition & 2 deletions frontend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# -- Frontend --
VITE_BASE_URL=localhost:8080
VITE_SHORT_BASE_URL=http://localhost:8080/user
# Set true to activate polling for dev server
# Set true to activate polling for dev server
VITE_SERVER_WATCH_POLLING=
VITE_SERVER_WATCH_INTERVAL=
VITE_SERVER_WATCH_BINARY_INTERVAL=
Expand Down Expand Up @@ -34,4 +34,3 @@ VITE_DEFAULT_HOUR_FORMAT=12

# You could use a url or a mailto: email address.
VITE_SUPPORT_URL=

3 changes: 1 addition & 2 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ const apiUrl = inject(apiUrlKey);
const route = useRoute();
const routeName = typeof route.name === 'string' ? route.name : '';
const router = useRouter();
const lang = defaultLocale();

const siteNotificationStore = useSiteNotificationStore();
const {
Expand Down Expand Up @@ -166,7 +165,7 @@ const onPageLoad = async () => {
resolution: deviceRes,
effective_resolution: effectiveDeviceRes,
user_agent: navigator.userAgent,
locale: lang,
locale: defaultLocale(),
}).json();

const { data } = response;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@
"recipientsCanScheduleBetween": "Recipients can schedule a {duration} appointment between {earliest} and {farthest} ahead of time.",
"redirectedNotice": "You are being redirected to {url}.",
"refreshLinkNotice": "This refreshes your link. Your old links will no longer work.",
"requestInformationSentToOwner": "An information about this booking request has been emailed to the owner.",
"requestInformationSentToOwner": "Information about this booking request has been emailed to the owner.",
"scheduleSettings": {
"clickHereToConnect": "Click here to connect a calendar!",
"create": "Select a calendar under Scheduling details and click save to get started!",
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/views/ProfileView.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { inject } from 'vue';
import { inject, onMounted } from 'vue';
import { keyByValue } from '@/utils';
import { callKey, isFxaAuthKey, fxaEditProfileUrlKey } from '@/keys';
import { useI18n } from 'vue-i18n';
Expand Down Expand Up @@ -41,6 +41,12 @@ const logout = async () => {
const editProfile = async () => {
window.location.href = fxaEditProfileUrl;
};

// Load calendar and bookings information
onMounted(() => {
calendarStore.fetch(call);
appointmentStore.fetch(call);
});
</script>

<template>
Expand Down
20 changes: 20 additions & 0 deletions test/e2e/.env.dev.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Appointment E2E Test Configuration
APPT_TARGET_ENV=dev

# URLs
APPT_URL=http://localhost:8080/

# Local sign-in credentials
APPT_LOGIN_EMAIL=
APPT_LOGIN_PWORD=

# Local Appointment user display name (settings => account => display name) for above user
APPT_DISPLAY_NAME=

# Booking share link for the existing local user above (settings => account => my link)
APPT_MY_SHARE_LINK=

# Booking requester's name and email address (used when a booking slot is requested via the
# share link). Important: real appointment booking emails will be sent to the provided email.
APPT_BOOKEE_NAME='Automated-Test-Bot-Dev'
APPT_BOOKEE_EMAIL=
5 changes: 3 additions & 2 deletions test/e2e/.env.prod.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Appointment E2E Test Configuration
APPT_TARGET_ENV=prod

# URLs
APPT_URL=https://appointment.day/
Expand All @@ -17,5 +18,5 @@ APPT_MY_SHARE_LINK=

# Booking requester's name and email address (used when a booking slot is requested via the
# share link). Important: real appointment booking emails will be sent to the provided email.
APPT_BOOKING_REQUESTER_NAME='Automated-Test-Bot'
APPT_BOOKING_REQUESTER_EMAIL=
APPT_BOOKEE_NAME='Automated-Test-Bot-Prod'
APPT_BOOKEE_EMAIL=
22 changes: 22 additions & 0 deletions test/e2e/.env.stage.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Appointment E2E Test Configuration
APPT_TARGET_ENV=stage

# URLs
APPT_URL=https://stage.appointment.day/
APPT_SHORT_SHARE_LINK_PREFIX=https://stage.apmt.day/
APPT_LONG_SHARE_LINK_PREFIX=https://stage.appointment.day/user/

# Sign-in (FxA) credentials
APPT_LOGIN_EMAIL=
APPT_LOGIN_PWORD=

# Appointment user display name (settings => account => display name) for above user
APPT_DISPLAY_NAME=

# Booking share link for the existing user above (settings => account => my link)
APPT_MY_SHARE_LINK=

# Booking requester's name and email address (used when a booking slot is requested via the
# share link). Important: real appointment booking emails will be sent to the provided email.
APPT_BOOKEE_NAME='Automated-Test-Bot-Stage'
APPT_BOOKEE_EMAIL=
120 changes: 101 additions & 19 deletions test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@

Guide for running the Thunderbird Appointment E2E tests.

## Prerequisite

You must have a pre-existing Appointment user test account (using FxA credentials) on the platform where you are running the tests. ie. For the production sanity test you must have an Appointment test account on production (using production FxA credentials) already set up.

The tests expect that default Appointment application settings exist for the provided test user; for example the user scheduling availability hasn't been changed from the default settings; and the default calendar view is the current month view. This is important so that the tests can find an available booking slot, etc.

## Installation

First install the E2E suite (includes Playwright):
Expand All @@ -23,13 +17,95 @@ Next install the Playwright browsers (Playwright uses it's own bundled browers)
npx playwright install
```

## Running Locally
## E2E Test Prerequisites
The E2E tests require an existing Appointment (and corresponding FxA account) and associated data, and reads this from your local .env file. This includes:
- Credentials for an existing Appointment (FxA) account (email address, password)
- The account user's display name and share link:
- The display name is found in Appointment => Settings => Account => Display name.
- The share link is found in Appointment => Settings => Account => My Link.
- The tests also require an email address to be used as the appointment bookee's email address when actually requesting bookings. This is the email address entered on the `Book selection` dialog (after an appointment slot was selected on the booking share link page). Note that real Appointment emails will be sent to this email address.

The tests expect that the default Appointment application settings haven't been changed for the provided test user:
- The user scheduling availability hasn't been changed from the default settings;
- In the dashboard the default calendar view is the current month view; this is important so that the tests can find an available booking slot, etc.
- In `Booking Settings`, the `Booking Confirmation` option is enabled, so that requested appointments generate HOLD appointments that need to be confirmed

## Running the E2E tests against your local dev environment

First ensure that you have a local Appointment account created and you can sign in to Appointment at http://localhost:8080/.

Then copy over the provided `.env.dev.example` to a local `.env`:

```bash
cd test/e2e
cp .env.dev.example .env
```

Then edit your local `.env` file and provide the following values:
```dotenv
APPT_LOGIN_EMAIL=<existing-dev-FxA-user-email>
APPT_LOGIN_PWORD=<exisiting-dev-FxA-user-password>
APPT_DISPLAY_NAME=<appointment-dev-user-display-name>
APPT_MY_SHARE_LINK=<apointment-dev-user-share-link>
APPT_BOOKEE_EMAIL=<booking-requesters-email>
```

To run the E2E tests headless (still in `test/e2e`):

```bash
npm run e2e-test
```

To run the E2E tests with a UI so you can watch the tests run (still in `test/e2e`):

```bash
npm run e2e-test-headed
```

To run the E2E tests in debug mode (still in `test/e2e`):

```bash
npm run e2e-test-debug
```

## Running the E2E tests against the staging environmnent

First copy over the provided `.env.stage.example` to a local `.env`:

```bash
cd test/e2e
cp .env.stage.example .env
```

Then edit your local `.env` file and provide the following values:
```dotenv
APPT_LOGIN_EMAIL=<existing-stage-FxA-user-email>
APPT_LOGIN_PWORD=<exisiting-stage-FxA-user-password>
APPT_DISPLAY_NAME=<appointment-stage-user-display-name>
APPT_MY_SHARE_LINK=<apointment-stage-user-share-link>
APPT_BOOKEE_EMAIL=<booking-requesters-email>
```

To run the E2E tests headless (still in `test/e2e`):

```bash
npm run e2e-test
```

To run the E2E tests with a UI so you can watch the tests run (still in `test/e2e`):

```bash
npm run e2e-test-headed
```

To run the E2E tests in debug mode (still in `test/e2e`):

```bash
npm run e2e-test-debug
```

## Running the production sanity test

The E2E tests require credentials for an existing Appointment (FxA) account and reads these from your local env vars.
This includes the existing Appointment account's email address, password, user's display name and share link.
The display name is found in Appointment => Settings => Account => Display name.
The share link is found in Appointment => Settings => Account => My Link.
The tests also require an email address to be used when actually requesting bookings. This is the email address entered on the `Book selection` dialog (after an appoitment slot was selected on the booking share link page). Note that real Appointment emails will be sent to this email address.
First copy over the provided `.env.prod.example` to a local `.env`:

```bash
Expand All @@ -39,11 +115,11 @@ cp .env.prod.example .env

Then edit your local `.env` file and provide the following values:
```dotenv
APPT_LOGIN_EMAIL=<existing-test-FxA-user-email>
APPT_LOGIN_PWORD=<exisiting-test-FxA-user-password>
APPT_DISPLAY_NAME=<appointment-user-display-name>
APPT_MY_SHARE_LINK=<apointment-user-share-link>
APPT_BOOKING_REQUESTER_EMAIL=<booking-requesters-email>
APPT_LOGIN_EMAIL=<existing-prod-FxA-user-email>
APPT_LOGIN_PWORD=<exisiting-prod-FxA-user-password>
APPT_DISPLAY_NAME=<appointment-prod-user-display-name>
APPT_MY_SHARE_LINK=<apointment-prod-user-share-link>
APPT_BOOKEE_EMAIL=<booking-requesters-email>
```

To run the production sanity test headless (still in `test/e2e`):
Expand All @@ -55,7 +131,7 @@ npm run prod-sanity-test
To run the production sanity test with a UI so you can watch the tests run (still in `test/e2e`):

```bash
npm run prod-sanity-test-ui
npm run prod-sanity-test-headed
```

To run the production sanity test in debug mode (still in `test/e2e`):
Expand All @@ -77,7 +153,7 @@ APPT_LOGIN_EMAIL=<existing-test-FxA-user-email>
APPT_LOGIN_PWORD=<exisiting-test-FxA-user-password>
APPT_DISPLAY_NAME=<appointment-user-display-name>
APPT_MY_SHARE_LINK=<apointment-user-share-link>
APPT_BOOKING_REQUESTER_EMAIL=<booking-requesters-email>
APPT_BOOKEE_EMAIL=<booking-requesters-email>
```

Also in order to run on BrowserStack you need to provide your BrowserStack credentials. Sign into your BrowserStack account and navigate to your `User Profile` and find your auth username and access key. In your local terminal export the following env vars to set the BrowserStack credentials that the tests will use:
Expand All @@ -90,6 +166,12 @@ export BROWSERSTACK_USERNAME=<your-browserstack-user-name>
export BROWSERSTACK_ACCESS_KEY=<your-browserstack-access-key>
```

To run the E2E tests on BrowserStack (still in `test/e2e`):

```bash
npm run e2e-test-browserstack
```

To run the production sanity test on BrowserStack (still in `test/e2e`):

```bash
Expand Down
22 changes: 15 additions & 7 deletions test/e2e/const/constants.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
// environment where the tests will run
export const APPT_TARGET_ENV = String(process.env.APPT_TARGET_ENV);

// appointment urls
export const APPT_URL = String(process.env.APPT_URL);
export const APPT_MY_SHARE_LINK = String(process.env.APPT_MY_SHARE_LINK);
export const APPT_SHORT_SHARE_LINK_PREFIX = String(process.env.APPT_SHORT_SHARE_LINK_PREFIX);
export const APPT_LONG_SHARE_LINK_PREFIX = String(process.env.APPT_LONG_SHARE_LINK_PREFIX);
export const APPT_PROD_PENDING_BOOKINGS_PAGE = `${process.env.APPT_URL}bookings/pending`;
export const APPT_PENDING_BOOKINGS_PAGE = `${process.env.APPT_URL}bookings/pending`;
export const APPT_BOOKED_BOOKINGS_PAGE = `${process.env.APPT_URL}bookings/booked`;

// page titles
export const APPT_PAGE_TITLE = 'Thunderbird Appointment';
export const FXA_PAGE_TITLE = 'Mozilla accounts';

// production sign-in credentials and corresponding account display name
export const PROD_LOGIN_EMAIL = String(process.env.APPT_LOGIN_EMAIL);
export const PROD_LOGIN_PWORD = String(process.env.APPT_LOGIN_PWORD);
// sign-in credentials and corresponding account display name
export const APPT_LOGIN_EMAIL = String(process.env.APPT_LOGIN_EMAIL);
export const APPT_LOGIN_PWORD = String(process.env.APPT_LOGIN_PWORD);

// appointment user display name (settings => account) for above user
export const PROD_DISPLAY_NAME = String(process.env.APPT_DISPLAY_NAME);
export const APPT_DISPLAY_NAME = String(process.env.APPT_DISPLAY_NAME);

// appointment requester's name and email address
export const APPT_BOOKING_REQUESTER_NAME = String(process.env.APPT_BOOKING_REQUESTER_NAME);
export const APPT_BOOKING_REQUESTER_EMAIL = String(process.env.APPT_BOOKING_REQUESTER_EMAIL);
export const APPT_BOOKEE_NAME = String(process.env.APPT_BOOKEE_NAME);
export const APPT_BOOKEE_EMAIL = String(process.env.APPT_BOOKEE_EMAIL);

// playwright test tags
export const PLAYWRIGHT_TAG_PROD_SANITY = '@prod-sanity';
export const PLAYWRIGHT_TAG_E2E_SUITE = '@e2e-suite';
7 changes: 6 additions & 1 deletion test/e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
"version": "1.0.0",
"main": "index.js",
"scripts": {
"e2e-test": "npx playwright test --grep e2e-suite --project=firefox",
"e2e-test-headed": "npx playwright test --grep e2e-suite --project=firefox --headed",
"e2e-test-debug": "npx playwright test --grep e2e-suite --project=firefox --headed --ui",
"e2e-test-browserstack": "npx browserstack-node-sdk playwright test --grep e2e-suite --browserstack.buildName 'Appointment E2E Tests'",
"e2e-test-browserstack-gha": "npx browserstack-node-sdk playwright test --grep e2e-suite",
"prod-sanity-test": "npx playwright test --grep prod-sanity --project=firefox",
"prod-sanity-test-ui": "npx playwright test --grep prod-sanity --project=firefox --headed",
"prod-sanity-test-headed": "npx playwright test --grep prod-sanity --project=firefox --headed",
"prod-sanity-test-debug": "npx playwright test --grep prod-sanity --project=firefox --headed --ui",
"prod-sanity-test-browserstack": "npx browserstack-node-sdk playwright test --grep prod-sanity --browserstack.buildName 'Production Sanity Test'",
"prod-sanity-test-browserstack-gha": "npx browserstack-node-sdk playwright test --grep prod-sanity",
Expand Down
Loading