Skip to content

Commit

Permalink
Merge branch 'main' into feat/auction-demo
Browse files Browse the repository at this point in the history
  • Loading branch information
VariableVic committed Mar 26, 2024
2 parents b5c5514 + 8bdad11 commit f49c139
Show file tree
Hide file tree
Showing 104 changed files with 2,251 additions and 156 deletions.
136 changes: 136 additions & 0 deletions .github/workflows/test-e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
name: Medusa NextJS Template Tests

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

env:
PGHOST: localhost
PGPORT: 5432
PGUSER: postgres
PGPASSWORD: password
PGDATABASE: postgres

TEST_POSTGRES_USER: test_medusa_user
TEST_POSTGRES_PASSWORD: password
TEST_POSTGRES_DATABASE: test_medusa_db
TEST_POSTGRES_DATABASE_TEMPLATE: test_medusa_db_template
TEST_POSTGRES_HOST: localhost
TEST_POSTGREST_PORT: 5432
PRODUCTION_POSTGRES_DATABASE: medusa_db
CLIENT_SERVER: http://localhost:9000

JWT_SECRET: something
COOKIE_SECRET: something

DATABASE_TYPE: "postgres"
REDIS_URL: redis://localhost:6379
DATABASE_URL: postgres://test_medusa_user:password@localhost/test_medusa_db
NEXT_PUBLIC_BASE_URL: http://localhost:8000

jobs:
e2e-test-runner:
timeout-minutes: 20
runs-on:
- ubuntu-latest
services:
postgres:
image: postgres:latest
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
meilisearch:
image: getmeili/meilisearch:v1.7
ports:
- 7700:7700
options: >-
--health-cmd "curl --fail http://localhost:7700/health"
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:latest
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18"

- name: Initialize PostgreSQL
run: |
echo "Initializing Databases"
psql -h localhost -U postgres -d test -c "CREATE USER ${{ env.TEST_POSTGRES_USER }} WITH PASSWORD '${{ env.TEST_POSTGRES_PASSWORD }}';"
psql -h localhost -U postgres -d test -c "CREATE DATABASE ${{ env.TEST_POSTGRES_DATABASE }} OWNER ${{ env.TEST_POSTGRES_USER }};"
- name: Install Medusa CLI
run: npm install @medusajs/medusa-cli -g
- name: Setup medusa backend server
working-directory: ../
# https://docs.medusajs.com/cli/reference#options
run: |
medusa new backend \
-y \
--skip-db \
--skip-migrations \
--skip-env \
--db-user ${{ env.TEST_POSTGRES_USER }} \
--db-pass ${{ env.TEST_POSTGRES_PASSWORD }} \
--db-database ${{ env.TEST_POSTGRES_DATABASE }} \
--db-host ${{ env.TEST_POSTGRES_HOST }} \
--db-port ${{ env.TEST_POSTGREST_PORT }}
- name: Build the backend
working-directory: ../backend
run: yarn build:admin

- name: Seed data from default seed file
working-directory: ../backend
run: medusa seed --seed-file=data/seed.json

- name: Run backend server
working-directory: ../backend
run: medusa develop &

- name: Install packages
run: yarn install -y

- name: Install playwright
run: yarn playwright install --with-deps

- name: Copy environment
run: cp .env.template .env

- name: Setup frontend
run: yarn build

- name: Run Tests
run: yarn test-e2e

- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: test-results
retention-days: 30
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,12 @@ node_modules
.yarn
.swc
dump.rdb
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth
17 changes: 17 additions & 0 deletions e2e/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Need a superuser to reset database
PGHOST=localhost
PGPORT=5432
PGUSER=postgres
PGPASSWORD=password
PGDATABASE=postgres

# Test database config
TEST_POSTGRES_USER=test_medusa_user
TEST_POSTGRES_DATABASE=test_medusa_db
TEST_POSTGRES_DATABASE_TEMPLATE=test_medusa_db_template
TEST_POSTGRES_HOST=localhost
TEST_POSTGREST_PORT=5432
PRODUCTION_POSTGRES_DATABASE=medusa_db

# Backend server API
CLIENT_SERVER=http://localhost:9000
89 changes: 89 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# About

This folder contains an end to end testing suite written with playwright checking all of the main functionality provided by this template. Note it assumes you are using a postgres database on the backend and have configured a test database. This is required because the tests will **drop and recreate the test database** in order to ensure replicability between test runs.

This test suite was built off of using the [medusa-starter-default](https://github.com/medusajs/medusa-starter-default) repository with the seed data from `data/seed.json`.

# Setup

## .env

These tests have a number of dependent environment variables, with an example found in `.env.example`. You can setup your local environment by copying the example environment file

```sh
cat e2e/.env.example >> .env
```

and configuring the `.env` file from there. There are more details below about what the test values correspond to and how to set them. But we mention that

* `CLIENT_SERVER` - is the server the next server is listening on

## Playwright

In order to run these tests, make sure playwright and a playwright-enabled browser is installed. You can do this by running

```sh
npx playwright install
```

## Database

Note that **these tests drop and reset the database** after each test run. This means you will need to configure a separate test database based on your development or production database. We give some instructions for doing so, and enforce a rule which requires the test database to have the prefix `test_` in its name.

### Environment variables

- `TEST_POSTGRES_USER` - user for connecting to the test database, for example, `medusa`
- `TEST_POSTGRES_PASSWORD` - password for connecting to the test database, for example `my_secret_password`
- `TEST_POSTGRES_DATABASE` - name of the test database, must start with the prefix `test*`, for example `test_medusa_db`
- `TEST_POSTGRES_HOST` - optional - host for the postgres database, defaults to `localhost`
- `TEST_POSTGREST_PORT` - optional - host for the postgres
- `PRODUCTION_POSTGRES_DATABASE` - name of the production database, for example `medusa_db`

in addition, there are environment variables for connecting to the database as a superuser, so we can efficiently reset the database.

* `PGHOST` - host for the postgres instance
* `PGPORT` - port for the postgres instance
* `PGUSER` - superuser for the postgres instance
* `PGPASSWORD` - superuser password for the postgres instance
* `PGDATABASE` - database we connect to while updating the other databases

### Test Database Failsafes

There are a few failsafes to ensure the test and production databases don't get mixed up. This includes:

- Ensuring the production database doesn't have the same name as the test database
- Ensuring the test database starts with the prefix `test_`

Note running the test suite will trigger database drops and recreations of the test database.

### Using a separate database

If you need to run your project with a separate database, such as sqlite, MySQL, or something else, please refer to `seed/reset.ts` and implement your own `resetDatabase` function which can be run between test runs.

# Running the test suite

## Test environment

Before running the test suite, make sure to start the backend server the medusa client is using. In addition, make sure to run in the nextjs template directory

```sh
yarn build
```

so the project is built.

## Calling the tests

You can run the test suite in the base directory of the project with either

```sh
yarn test-e2e
```

or

```sh
npm run test-e2e
```

While the test suite is running, it is configured to automatically run the nextjs template during test execution.
106 changes: 106 additions & 0 deletions e2e/data/reset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Client } from "pg"

async function getDatabaseClient() {
testEnvChecks()
const env = getEnv()
const client = new Client(env.superuser)
await client.connect()
return client
}

function getEnv() {
return {
host: process.env.TEST_POSTGRES_HOST || "localhost",
port: process.env.TEST_POSTGRES_HOST
? Number(process.env.TEST_POSTGRES_HOST)
: 5432,
user: process.env.TEST_POSTGRES_USER || "test_medusa_user",
testDatabase: process.env.TEST_POSTGRES_DATABASE || "test_medusa_db",
testDatabaseTemplate:
process.env.TEST_POSTGRES_DATABASE_TEMPLATE || "test_medusa_db_template",
productionDatabase: process.env.PRODUCTION_POSTGRES_DATABASE || "medusa_db",
superuser: {
host: process.env.PGHOST || "localhost",
port: process.env.PGPORT ? Number(process.env.PGPORT) : 5432,
user: process.env.PGUSER || "postgres",
password: process.env.PGPASSWORD || "password",
database: process.env.PGDATABASE || "postgres",
},
}
}

async function testEnvChecks() {
const env = getEnv()
if (!env.testDatabase.startsWith("test_")) {
const msg =
"Please make sure your test environment database name starts with test_"
console.error(msg)
throw new Error(msg)
}
if (env.testDatabase === env.productionDatabase) {
const msg =
"Please make sure your test environment database and production environment database names are not equal"
console.error(msg)
throw new Error(msg)
}
}

async function createTemplateDatabase(client: Client) {
const { user, testDatabase, testDatabaseTemplate } = getEnv()
try {
// close current connections
await client.query(`
ALTER DATABASE ${testDatabase} WITH ALLOW_CONNECTIONS false;
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE datname='${testDatabase}';
`)
await client.query(`
CREATE DATABASE ${testDatabaseTemplate} WITH
OWNER=${user}
TEMPLATE=${testDatabase}
IS_TEMPLATE=true;
`)
} catch (e: any) {
// duplicate database code
if (e.code === "42P04") {
return
}
throw e
}
}

async function createTestDatabase(client: Client) {
const { user, testDatabase, testDatabaseTemplate } = getEnv()
const deleteDatabase = `${testDatabase}_del`
// drop connections and alter database name
await client.query(`
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname='${testDatabase}';
ALTER DATABASE ${testDatabase}
RENAME TO ${deleteDatabase};
`)
await client.query(`
CREATE DATABASE ${testDatabase}
WITH OWNER ${user}
TEMPLATE=${testDatabaseTemplate};
`)
await client.query(`DROP DATABASE ${deleteDatabase}`)
}

export async function resetDatabase() {
const client = await getDatabaseClient()
await createTemplateDatabase(client)
await createTestDatabase(client)
await client.end()
}

export async function dropTemplate() {
const client = await getDatabaseClient()
const env = getEnv()
await client.query(
`ALTER DATABASE ${env.testDatabaseTemplate} is_template false`
)
await client.query(`DROP DATABASE ${env.testDatabaseTemplate}`)
await client.end()
}
Loading

0 comments on commit f49c139

Please sign in to comment.