Skip to content

Commit

Permalink
✨ Add private, local only, API for usage in E2E tests (#1429)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <[email protected]>
  • Loading branch information
patrick91 and github-actions authored Dec 2, 2024
1 parent 414864d commit 14129f7
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 31 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/generate-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ jobs:
- run: uv run bash scripts/generate-client.sh
env:
VIRTUAL_ENV: backend/.venv
ENVIRONMENT: production
SECRET_KEY: just-for-generating-client
POSTGRES_PASSWORD: just-for-generating-client
FIRST_SUPERUSER_PASSWORD: just-for-generating-client
- name: Add changes to git
run: |
git config --local user.email "[email protected]"
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
with:
limit-access-to-actor: true
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "0.4.15"
enable-cache: true
- run: uv sync
working-directory: backend
- run: npm ci
working-directory: frontend
- run: uv run bash scripts/generate-client.sh
env:
VIRTUAL_ENV: backend/.venv
- run: docker compose build
- run: docker compose down -v --remove-orphans
- name: Run Playwright tests
Expand Down
7 changes: 6 additions & 1 deletion backend/app/api/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from fastapi import APIRouter

from app.api.routes import items, login, users, utils
from app.api.routes import items, login, private, users, utils
from app.core.config import settings

api_router = APIRouter()
api_router.include_router(login.router, tags=["login"])
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(utils.router, prefix="/utils", tags=["utils"])
api_router.include_router(items.router, prefix="/items", tags=["items"])


if settings.ENVIRONMENT == "local":
api_router.include_router(private.router)
38 changes: 38 additions & 0 deletions backend/app/api/routes/private.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import Any

from fastapi import APIRouter
from pydantic import BaseModel

from app.api.deps import SessionDep
from app.core.security import get_password_hash
from app.models import (
User,
UserPublic,
)

router = APIRouter(tags=["private"], prefix="/private")


class PrivateUserCreate(BaseModel):
email: str
password: str
full_name: str
is_verified: bool = False


@router.post("/users/", response_model=UserPublic)
def create_user(user_in: PrivateUserCreate, session: SessionDep) -> Any:
"""
Create a new user.
"""

user = User(
email=user_in.email,
full_name=user_in.full_name,
hashed_password=get_password_hash(user_in.password),
)

session.add(user)
session.commit()

return user
26 changes: 26 additions & 0 deletions backend/app/tests/api/routes/test_private.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from fastapi.testclient import TestClient
from sqlmodel import Session, select

from app.core.config import settings
from app.models import User


def test_create_user(client: TestClient, db: Session) -> None:
r = client.post(
f"{settings.API_V1_STR}/private/users/",
json={
"email": "[email protected]",
"password": "password123",
"full_name": "Pollo Listo",
},
)

assert r.status_code == 200

data = r.json()

user = db.exec(select(User).where(User.id == data["id"])).first()

assert user
assert user.email == "[email protected]"
assert user.full_name == "Pollo Listo"
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build": "tsc -p tsconfig.build.json && vite build",
"lint": "biome check --apply-unsafe --no-errors-on-unmatched --files-ignore-unknown=true ./",
"preview": "vite preview",
"generate-client": "openapi-ts"
Expand Down
43 changes: 14 additions & 29 deletions frontend/tests/user-settings.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { expect, test } from "@playwright/test"
import { firstSuperuser, firstSuperuserPassword } from "./config.ts"
import { randomEmail, randomPassword } from "./utils/random"
import { logInUser, logOutUser, signUpNewUser } from "./utils/user"
import { logInUser, logOutUser } from "./utils/user"
import { createUser } from "./utils/privateApi.ts"

const tabs = ["My profile", "Password", "Appearance"]

Expand All @@ -26,13 +27,11 @@ test.describe("Edit user full name and email successfully", () => {
test.use({ storageState: { cookies: [], origins: [] } })

test("Edit user name with a valid name", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const updatedName = "Test User 2"
const password = randomPassword()

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -50,13 +49,11 @@ test.describe("Edit user full name and email successfully", () => {
})

test("Edit user email with a valid email", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const updatedEmail = randomEmail()
const password = randomPassword()

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -77,13 +74,11 @@ test.describe("Edit user with invalid data", () => {
test.use({ storageState: { cookies: [], origins: [] } })

test("Edit user email with an invalid email", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const password = randomPassword()
const invalidEmail = ""

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -97,13 +92,11 @@ test.describe("Edit user with invalid data", () => {
})

test("Cancel edit action restores original name", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const password = randomPassword()
const updatedName = "Test User"

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
const user = await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -114,18 +107,18 @@ test.describe("Edit user with invalid data", () => {
await page.getByLabel("Full name").fill(updatedName)
await page.getByRole("button", { name: "Cancel" }).first().click()
await expect(
page.getByLabel("My profile").getByText(fullName, { exact: true }),
page
.getByLabel("My profile")
.getByText(user.full_name as string, { exact: true }),
).toBeVisible()
})

test("Cancel edit action restores original email", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const password = randomPassword()
const updatedEmail = randomEmail()

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -147,13 +140,11 @@ test.describe("Change password successfully", () => {
test.use({ storageState: { cookies: [], origins: [] } })

test("Update password successfully", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const password = randomPassword()
const NewPassword = randomPassword()

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -177,13 +168,11 @@ test.describe("Change password with invalid data", () => {
test.use({ storageState: { cookies: [], origins: [] } })

test("Update password with weak passwords", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const password = randomPassword()
const weakPassword = "weak"

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -201,14 +190,12 @@ test.describe("Change password with invalid data", () => {
test("New password and confirmation password do not match", async ({
page,
}) => {
const fullName = "Test User"
const email = randomEmail()
const password = randomPassword()
const newPassword = randomPassword()
const confirmPassword = randomPassword()

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand All @@ -223,12 +210,10 @@ test.describe("Change password with invalid data", () => {
})

test("Current password and new password are the same", async ({ page }) => {
const fullName = "Test User"
const email = randomEmail()
const password = randomPassword()

// Sign up a new user
await signUpNewUser(page, fullName, email, password)
await createUser({ email, password })

// Log in the user
await logInUser(page, email, password)
Expand Down
22 changes: 22 additions & 0 deletions frontend/tests/utils/privateApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Note: the `PrivateService` is only available when generating the client
// for local environments
import { OpenAPI, PrivateService } from "../../src/client"

OpenAPI.BASE = `${process.env.VITE_API_URL}`

export const createUser = async ({
email,
password,
}: {
email: string
password: string
}) => {
return await PrivateService.createUser({
requestBody: {
email,
password,
is_verified: true,
full_name: "Test User",
},
})
}
4 changes: 4 additions & 0 deletions frontend/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["tests/**/*.ts"]
}

0 comments on commit 14129f7

Please sign in to comment.