Skip to content

Add E2E test coverage for users, courses, quizzes, and credentials modules #2

Description

@DeFiVC

Description

The API currently has E2E tests for only 2 of 6 modules:

  • tests/e2e/auth.test.ts — 4 tests
  • tests/e2e/rewards.test.ts — 4 tests

The remaining 4 modules have zero test coverage:

  • users — profile CRUD, progress aggregation
  • courses — listing, filtering, enrollment, detail
  • quizzes — generation, submission, scoring
  • credentials — listing, minting

Test pattern to follow

Use the existing structure from tests/e2e/auth.test.ts:

import{describe,it,expect,beforeAll,afterAll}from"vitest";importtype{FastifyInstance}from"fastify";import{buildApp}from"../../src/server.js";describe("ModuleName API",()=>{letapp: FastifyInstance;beforeAll(async()=>{app=awaitbuildApp();awaitapp.ready();});afterAll(async()=>{awaitapp.close();});// Use app.inject() for HTTP requests// Use app.jwt.sign() to create test tokens});

Files to create

tests/e2e/users.test.ts

Tests for GET /api/users/me, PUT /api/users/me, GET /api/users/me/progress:

describe("Users API")
describe("GET /api/users/me")
- should reject unauthenticated requests (401)
- should return user profile when authenticated (200)
- should return correct stellarAddress in profile
describe("PUT /api/users/me")
- should reject unauthenticated requests (401)
- should update displayName
- should update background and learningGoal
- should reject invalid background values (400)
describe("GET /api/users/me/progress")
- should reject unauthenticated requests (401)
- should return progress aggregate for enrolled user

Auth pattern for authenticated requests:

consttoken=app.jwt.sign({sub: "00000000-0000-0000-0000-000000000001",stellarAddress: "GALICE0000000000000000000000000000000000000000000000000000000",});constresponse=awaitapp.inject({method: "GET",url: "/api/users/me",headers: {authorization: `Bearer ${token}`},});

tests/e2e/courses.test.ts

Tests for GET /api/courses, GET /api/courses/:id, POST /api/courses/:id/enroll:

describe("Courses API")
describe("GET /api/courses")
- should return paginated course list (200)
- should filter by difficulty query param
- should return enrolledCount for each course
- should include isEnrolled when authenticated
describe("GET /api/courses/:id")
- should return course detail with modules (200)
- should return 404 for non-existent course
- should include enrollment status when authenticated
describe("POST /api/courses/:id/enroll")
- should reject unauthenticated requests (401)
- should enroll user in course (201)
- should reject duplicate enrollment (409)
- should return 404 for non-existent course

tests/e2e/quizzes.test.ts

Tests for POST /api/quizzes/generate, POST /api/quizzes/:id/submit:

describe("Quizzes API")
describe("POST /api/quizzes/generate")
- should reject unauthenticated requests (401)
- should reject if not enrolled in course (403)
- should return generated quiz questions (200)
- should return same quiz on repeat generation (idempotent)
describe("POST /api/quizzes/:id/submit")
- should reject unauthenticated requests (401)
- should submit answers and return score (200)
- should include feedback in response
- should set rewardAvailable when score >= 70%
- should reject duplicate submission (409)

tests/e2e/credentials.test.ts

Tests for GET /api/credentials, POST /api/credentials/mint:

describe("Credentials API")
describe("GET /api/credentials")
- should reject unauthenticated requests (401)
- should return user's credentials list (200)
describe("POST /api/credentials/mint")
- should reject unauthenticated requests (401)
- should mint credential for completed course (201)
- should reject if course not completed
- should reject duplicate credential (409)

Important notes

  • Some tests may fail without a running PostgreSQL + Redis. Use beforeAll/afterAll for cleanup, or consider mocking the database layer.
  • The app.inject() method does NOT require a running server — it uses Fastify's test injection.
  • Use realistic UUIDs for user IDs and Stellar addresses that match the DB schema constraints.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26good first issueGood for newcomerstestsTest additions or improvementstypescriptTypeScript language

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions