Skip to content

Commit

Permalink
Merge pull request #193 from UoaWDCC/UABC-onboard
Browse files Browse the repository at this point in the history
Onboarding flow
  • Loading branch information
dyzhuu authored May 26, 2024
2 parents aee37d1 + a32c619 commit b077f2b
Show file tree
Hide file tree
Showing 16 changed files with 364 additions and 8 deletions.
File renamed without changes.
51 changes: 51 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: E2E Playwright Tests

on:
pull_request:
branches:
- main
push:
branches: [main]

jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v3
name: Setup pnpm
with:
version: 8

- name: Set up Node.js version
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"

- name: Install dependencies
run: pnpm install

- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps

- name: Create env file
run: echo ${{ secrets.UABC_DEV_BACKEND_ENVFILE }} | base64 --decode > .env

- name: Build Next app
env:
CI: true
run: |
pnpm build
- name: Run Playwright tests
run: pnpm test:e2e

- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: Run Tests
name: Tests

on:
pull_request:
branches:
- main

jobs:
build:
test:
runs-on: ubuntu-latest
environment: development
steps:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ next-env.d.ts

# env files
.env
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const config: Config = {
preset: "ts-jest",
coverageProvider: "v8",
testEnvironment: "<rootDir>/src/tests/jsdom-extended.js",
testPathIgnorePatterns: ["<rootDir>/playwright"],
setupFilesAfterEnv: ["<rootDir>/src/tests/setup-jest.ts"],
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"start": "next start",
"preview": "next build && next start",
"test": "jest",
"test:e2e": "playwright test",
"test:watch": "jest --watch",
"lint": "next lint",
"db:push": "drizzle-kit push",
Expand Down Expand Up @@ -48,6 +49,7 @@
},
"devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@playwright/test": "^1.44.0",
"@storybook/addon-essentials": "^8.0.5",
"@storybook/blocks": "^8.0.5",
"@storybook/nextjs": "^8.0.5",
Expand Down
77 changes: 77 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { defineConfig, devices } from "@playwright/test";

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./playwright",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:3000",

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},

/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},

// {
// name: "firefox",
// use: { ...devices["Desktop Firefox"] },
// },

// {
// name: "webkit",
// use: { ...devices["Desktop Safari"] },
// },

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
webServer: {
command: "npm run start",
url: "http://127.0.0.1:3000",
reuseExistingServer: !process.env.CI,
},
});
58 changes: 58 additions & 0 deletions playwright/onboarding.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { expect, test } from "@playwright/test";

import { signUpAndLogin } from "./utils/helper";
import { generateMockOnboardingUser } from "./utils/mock";

test.beforeEach(async ({ page }) => {
const user = generateMockOnboardingUser();
await signUpAndLogin(page, user.email, user.password);
});

test.afterEach(async ({ page }) => {
// await is necessary so test context is not disposed before the request is completed
await page.request
.get(`/api/auth/session`)
.then((res) => res.json())
.then(async ({ user }) => {
await page.request.delete(`/api/users/${user.id}`);
});
});

test.describe("Onboarding flow", () => {
test("should navigate to the name page", async ({ page }) => {
await expect(page).toHaveURL("/onboarding/name");
});

test("should navigate to the member page", async ({ page }) => {
await page.goto("/onboard/name");
await page.getByRole("textbox").nth(0).fill("John");
await page.getByRole("textbox").nth(1).fill("Doe");
await page.click("text=Continue");
await expect(page).toHaveURL("onboarding/member");
});
test("should navigate to the session page", async ({ page }) => {
await page.goto("/onboard/name");
await page.getByRole("textbox").nth(0).fill("John");
await page.getByRole("textbox").nth(1).fill("Doe");
await page.click("text=Continue");
await page.click("text=Prepaid Member");
await page.click("text=Next");
await expect(page).toHaveURL("sessions");
});
test("should fill in first name and last name before continuing", async ({
page,
}) => {
await page.goto("/onboard/name");
const continueButton = await page.locator("text=Continue");
await expect(continueButton).toBeDisabled();
});

test("should select membership type before continuing", async ({ page }) => {
await page.goto("/onboard/name");
await page.getByRole("textbox").nth(0).fill("John");
await page.getByRole("textbox").nth(1).fill("Doe");
await page.click("text=Continue");
const nextButton = await page.locator("text=Next");
await expect(nextButton).toBeDisabled();
});
});
30 changes: 30 additions & 0 deletions playwright/utils/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Page } from "@playwright/test";

export const signUpAndLogin = async (
page: Page,
email: string,
password: string,
): Promise<void> => {
await page.request.post(`/api/auth/register`, {
data: {
email,
password,
},
});

const res = await page.request.get(`/api/auth/csrf`);
const { csrfToken } = await res.json();

await page.goto("/");

// page.request stores cookies between requests
await page.request.post(`/api/auth/callback/credentials`, {
data: {
email,
password,
csrfToken,
},
});

await page.reload();
};
4 changes: 4 additions & 0 deletions playwright/utils/mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const generateMockOnboardingUser = () => ({
email: crypto.randomUUID() + "@onboarding.com",
password: "231Xh7D&dM8u75EjIYV",
});
35 changes: 35 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions src/app/api/users/[userId]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";

import { db } from "@/lib/db";
import { users } from "@/lib/db/schema";
import { getCurrentUser } from "@/lib/session";

/**
* Get user by id
Expand Down Expand Up @@ -37,3 +38,32 @@ export async function GET(
return new Response("Internal Server Error", { status: 500 });
}
}

export async function DELETE(
_req: NextRequest,
{ params }: { params: { userId: string } },
) {
try {
const { userId } = params;

const currentUser = await getCurrentUser();

if (!currentUser) {
return new Response("ERROR: Unauthorized request", { status: 401 });
}

if (currentUser.id !== userId) {
return new Response("ERROR: Invalid permissions", { status: 403 });
}

const user = await db.delete(users).where(eq(users.id, userId));

if (!user) {
return new Response(`No User found for id: ${userId}`, { status: 404 });
}

return new Response(null, { status: 204 });
} catch {
return new Response("Internal Server Error", { status: 500 });
}
}
Loading

0 comments on commit b077f2b

Please sign in to comment.