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
55 changes: 37 additions & 18 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,13 @@ GET /v1/users/me

```json
{
"status": "success",
"data": {
"id": "usr_123",
"email": "user@example.com",
"name": "John Doe",
"walletAddress": "GABC...123",
"createdAt": "2024-01-01T00:00:00Z",
"stats": {
"modulesCompleted": 15,
"totalEarned": "25.50",
"currentStreak": 7
}
}
"id": "usr_123",
"email": "user@example.com",
"username": "john_doe",
"role": "LEARNER",
"walletAddress": "GABC...123",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-02T00:00:00Z"
}
```

Expand All @@ -83,11 +77,36 @@ PATCH /v1/users/me

```json
{
"name": "John Updated",
"preferences": {
"language": "fr",
"notifications": true
}
"username": "john_updated"
}
```

#### Change Password

```txt
PATCH /v1/users/password
```

**Request:**

```json
{
"currentPassword": "OldPassword123!",
"newPassword": "NewPassword123!"
}
```

#### Update Wallet Address

```txt
PATCH /v1/users/wallet
```

**Request:**

```json
{
"walletAddress": "GABC...123"
}
```

Expand Down
73 changes: 12 additions & 61 deletions integrations/unit/validation.middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,7 @@ describe('validate', () => {

describe('validateProfileUpdate', () => {
it('calls next() for a valid update payload', () => {
const { req, res, next } = makeMocks({
username: 'valid_user',
firstName: 'John',
lastName: 'Doe',
bio: 'Hello world',
avatar: 'https://example.com/avatar.jpg',
})
const { req, res, next } = makeMocks({ username: 'valid_user' })

validateProfileUpdate(req as Request, res as Response, next)

Expand Down Expand Up @@ -259,65 +253,22 @@ describe('validateProfileUpdate', () => {
})
})

it('returns 400 when firstName exceeds 50 characters', () => {
const { req, res, next } = makeMocks({ firstName: 'A'.repeat(51) })

validateProfileUpdate(req as Request, res as Response, next)

expect(res.status).toHaveBeenCalledWith(400)
expect(res.json).toHaveBeenCalledWith({
message: 'Validation failed',
errors: { body: ['First name must be less than 50 characters'] }
})
})

it('returns 400 when lastName exceeds 50 characters', () => {
const { req, res, next } = makeMocks({ lastName: 'B'.repeat(51) })

validateProfileUpdate(req as Request, res as Response, next)

expect(res.status).toHaveBeenCalledWith(400)
expect(res.json).toHaveBeenCalledWith({
message: 'Validation failed',
errors: { body: ['Last name must be less than 50 characters'] }
})
})

it('returns 400 when bio exceeds 500 characters', () => {
const { req, res, next } = makeMocks({ bio: 'x'.repeat(501) })

validateProfileUpdate(req as Request, res as Response, next)

expect(res.status).toHaveBeenCalledWith(400)
expect(res.json).toHaveBeenCalledWith({
message: 'Validation failed',
errors: { body: ['Bio must be less than 500 characters'] }
})
})

it('returns 400 when avatar is not a valid URL', () => {
const { req, res, next } = makeMocks({ avatar: 'not-a-url' })

validateProfileUpdate(req as Request, res as Response, next)

expect(res.status).toHaveBeenCalledWith(400)
expect(res.json).toHaveBeenCalledWith({
message: 'Validation failed',
errors: { body: ['Invalid URL format'] }
})
})

it('returns multiple errors when multiple fields are invalid', () => {
it('ignores unsupported fields (firstName, lastName, bio, avatar)', () => {
const { req, res, next } = makeMocks({
username: 'ab',
bio: 'x'.repeat(501),
username: 'valid_user',
firstName: 'John',
lastName: 'Doe',
bio: 'Hello world',
avatar: 'https://example.com/avatar.jpg',
})

validateProfileUpdate(req as Request, res as Response, next)

expect(res.status).toHaveBeenCalledWith(400)
const response = (res.json as ReturnType<typeof vi.fn>).mock.calls[0][0]
expect(response.errors.body.length).toBeGreaterThanOrEqual(2)
expect(next).toHaveBeenCalledOnce()
expect((req as any).body.firstName).toBeUndefined()
expect((req as any).body.lastName).toBeUndefined()
expect((req as any).body.bio).toBeUndefined()
expect((req as any).body.avatar).toBeUndefined()
})
})

Expand Down
Loading
Loading