Skip to content

Commit

Permalink
fix tests, update doc
Browse files Browse the repository at this point in the history
  • Loading branch information
foyarash committed Mar 22, 2024
1 parent edf46a5 commit 37ae669
Show file tree
Hide file tree
Showing 11 changed files with 2,427 additions and 2,639 deletions.
35 changes: 18 additions & 17 deletions __tests__/adapters/prisma/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const createMocks = (options: RequestOptions) => {
res: {
...res,
send: jest.spyOn(res, 'send'),
json: jest.spyOn(res, 'json'),
} as unknown as NextApiResponse,
}
}
Expand Down Expand Up @@ -56,7 +57,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should get a page based paginated users list', async () => {
Expand All @@ -72,7 +73,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith({
expect(res.json).toHaveBeenCalledWith({
data: expectedResult,
pagination: {
total: 4,
Expand All @@ -92,7 +93,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(user)
expect(res.json).toHaveBeenCalledWith(user)
})

it('should get the list of users with only their email', async () => {
Expand All @@ -109,7 +110,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should get the list of users with only their email and posts', async () => {
Expand All @@ -127,7 +128,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should get the list of users with only their email and posts ids', async () => {
Expand All @@ -149,7 +150,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should get the list of users with only their email, posts ids, comments and comments users', async () => {
Expand All @@ -176,7 +177,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should return the first 2 users', async () => {
Expand All @@ -191,7 +192,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should return 2 users after the first 2 ones', async () => {
Expand All @@ -207,7 +208,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should return 2 users based on a cursor', async () => {
Expand All @@ -227,7 +228,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should filter user by its email', async () => {
Expand All @@ -246,7 +247,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should filter users where email does not match', async () => {
Expand All @@ -265,7 +266,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should filter users where email starts with john and ends with .com', async () => {
Expand All @@ -285,7 +286,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should create a user', async () => {
Expand All @@ -305,7 +306,7 @@ describe('Prisma interraction', () => {
},
})

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should update a user', async () => {
Expand All @@ -330,7 +331,7 @@ describe('Prisma interraction', () => {
},
})

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should update a user and respond with only its email', async () => {
Expand Down Expand Up @@ -358,7 +359,7 @@ describe('Prisma interraction', () => {
},
})

expect(res.send).toHaveBeenCalledWith(expectedResult)
expect(res.json).toHaveBeenCalledWith(expectedResult)
})

it('should delete the previously created user', async () => {
Expand All @@ -374,7 +375,7 @@ describe('Prisma interraction', () => {

await handler(req, res)

expect(res.send).toHaveBeenCalledWith(user)
expect(res.json).toHaveBeenCalledWith(user)
})

afterAll(async () => {
Expand Down
42 changes: 24 additions & 18 deletions __tests__/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import HttpError from '../src/httpError'
import { ApiError } from 'next/dist/server/api-utils'
import { RequestOptions, createMocks as createHttpMocks } from 'node-mocks-http'
import { NextApiRequest, NextApiResponse } from 'next'
import { toRequest } from '../src/utils'

const createMocks = (options: RequestOptions) => {
const { req, res } = createHttpMocks(options)
Expand All @@ -15,6 +16,7 @@ const createMocks = (options: RequestOptions) => {
...res,
send: jest.spyOn(res, 'send'),
status: jest.spyOn(res, 'status'),
json: jest.spyOn(res, 'json'),
} as unknown as NextApiResponse,
}
}
Expand Down Expand Up @@ -93,7 +95,7 @@ describe('Handler', () => {
})

await handler(req, res)
expect(res.send).toHaveBeenCalled()
expect(res.status).toHaveBeenCalled()
})

it('should throw an error with an invalid adapter', async () => {
Expand Down Expand Up @@ -131,7 +133,7 @@ describe('Handler', () => {
})

await handler(req, res)
expect(onRequest).toHaveBeenCalledWith(req, res, {
expect(onRequest).toHaveBeenCalledWith(await toRequest(req), {
routeType: RouteType.READ_ALL,
resourceName: 'foo',
})
Expand All @@ -150,7 +152,7 @@ describe('Handler', () => {
})

await handler(req, res)
expect(onSuccess).toHaveBeenCalledWith(req, res)
expect(onSuccess).toHaveBeenCalledWith(await toRequest(req))
})

it('should trigger a simple Error', async () => {
Expand All @@ -172,7 +174,7 @@ describe('Handler', () => {
})

await handler(req, res)
expect(onError).toHaveBeenCalledWith(req, res, error)
expect(onError).toHaveBeenCalledWith(await toRequest(req), error)
expect(res.status).toHaveBeenCalledWith(500)
})

Expand All @@ -195,9 +197,11 @@ describe('Handler', () => {
})

await handler(req, res)
expect(onError).toHaveBeenCalledWith(req, res, error)
expect(onError).toHaveBeenCalledWith(await toRequest(req), error)
expect(res.status).toHaveBeenCalledWith(400)
expect(res.send).toHaveBeenCalledWith(`${http.STATUS_CODES[400]}: Error`)
expect(res.json).toHaveBeenCalledWith({
message: `${http.STATUS_CODES[400]}: Error`,
})
})

it('should trigger an 400 HttpError using the default NextJS ApiError', async () => {
Expand All @@ -219,17 +223,19 @@ describe('Handler', () => {
})

await handler(req, res)
expect(onError).toHaveBeenCalledWith(req, res, error)
expect(onError).toHaveBeenCalledWith(await toRequest(req), error)
expect(res.status).toHaveBeenCalledWith(400)
expect(res.send).toHaveBeenCalledWith(`Error`)
expect(res.json).toHaveBeenCalledWith({ message: `Error` })
})

it('should run adapter handleError upon Error', async () => {
const error = new Error()
const getOne = jest.fn(() => {
throw error
})
const handleError = jest.fn()
const handleError = jest.fn((e) => {
throw e
})
const adapter = generateNoopAdapter(
{
getOne,
Expand Down Expand Up @@ -374,7 +380,7 @@ describe('Handler', () => {
method: 'GET',
})
await handler(req, res)
expect(res.send).toHaveBeenCalledWith(data)
expect(res.json).toHaveBeenCalledWith(data)
})

it('should throw a 404 for a non existing resource', async () => {
Expand All @@ -390,9 +396,9 @@ describe('Handler', () => {
})
await handler(req, res)
expect(res.status).toHaveBeenCalledWith(404)
expect(res.send).toHaveBeenCalledWith(
`${http.STATUS_CODES[404]}: foo bar not found`
)
expect(res.json).toHaveBeenCalledWith({
message: `${http.STATUS_CODES[404]}: foo bar not found`,
})
})
})

Expand All @@ -410,7 +416,7 @@ describe('Handler', () => {
method: 'GET',
})
await handler(req, res)
expect(res.send).toHaveBeenCalledWith(collection)
expect(res.json).toHaveBeenCalledWith(collection)
})
})

Expand All @@ -428,7 +434,7 @@ describe('Handler', () => {
method: 'POST',
})
await handler(req, res)
expect(res.send).toHaveBeenCalledWith(data)
expect(res.json).toHaveBeenCalledWith(data)
expect(res.status).toHaveBeenCalledWith(201)
})
})
Expand All @@ -450,7 +456,7 @@ describe('Handler', () => {
body,
})
await handler(req, res)
expect(res.send).toHaveBeenCalledWith({ ...data, ...body })
expect(res.json).toHaveBeenCalledWith({ ...data, ...body })
expect(update).toHaveBeenCalledWith('foo', 'bar', body, {})
})

Expand Down Expand Up @@ -487,7 +493,7 @@ describe('Handler', () => {
method: 'DELETE',
})
await handler(req, res)
expect(res.send).toHaveBeenCalledWith(data)
expect(res.json).toHaveBeenCalledWith(data)
expect(deleteFn).toHaveBeenCalledWith('foo', 'bar', {})
})

Expand Down Expand Up @@ -596,7 +602,7 @@ describe('Handler', () => {
})

await handler(req, res)
expect(res.send).toHaveBeenCalledWith({
expect(res.json).toHaveBeenCalledWith({
data: mockResources,
pagination: {
total: 1,
Expand Down
6 changes: 3 additions & 3 deletions docs/pages/api-docs/callbacks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ Callbacks are functions executed in 3 different situations:

#### onRequest

A request has arrived and the callback is executed right before any action on the database. It receives 4 arguments: the request, the response, an object containing the route type, the resource id and the resource name.
A request has arrived and the callback is executed right before any action on the database. It receives 3 arguments: the request, an object containing the route type, the resource id and the resource name.
You can use it to add some custom content to your query params for example, or to just do some debug.

#### onSuccess

The request is successful and the callback is executed right before ending the handler. It receives 2 arguments: the request and the response.
The request is successful and the callback is executed right before ending the handler. It receives the request as an argument.

#### onError

The request is unsuccessful and the callback is executed on the first error it meets. It receives 3 arguments: the request, the response and the thrown error.
The request is unsuccessful and the callback is executed on the first error it meets. It receives 2 arguments: the request and the thrown error.
A simple use case would be to notify some error monitoring system like Bugsnag.
10 changes: 1 addition & 9 deletions docs/pages/api-docs/middlewares.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,13 @@ Middlewares are executed right after your data has been retrieved from the datab

```typescript
export type TMiddlewareContext<T> = {
req: NextApiRequest
res: NextApiResponse
req: TInternalRequest
result: T | T[] // the data retrieved from the database
}
```
- a function as the second argument, which is used to execute the next middleware in the stack.
<Callout emoji="⚠️">
The request response is done by a middleware which is added by default at the
end of the middlewares stack. So it is mandatory that you call the function
received as your second argument, or your request will end up with no data
inside.
</Callout>
You can use middlewares to play with your data, for example if you want to wrap your data in a specific key you'd do the following:
```javascript
Expand Down
23 changes: 23 additions & 0 deletions docs/pages/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ npm install -S @premieroctet/next-crud

## Quick Start

### Page Router

```typescript
// pages/api/[...nextcrud].ts

Expand All @@ -50,6 +52,27 @@ const handler = async (req, res) => {
export default handler
```

### App Router

```typescript
// app/api/[...nextcrud]/route.ts
import { User, Post, Prisma } from '@prisma/client'
import NextCrud, { PrismaAdapter } from '@premieroctet/next-crud'
import { prisma } from '../../../../db'

const handler = async (req: Request) => {
const nextCrudHandler = await NextCrud({
adapter: new PrismaAdapter({
prismaClient: prisma,
}),
})

return nextCrudHandler(req)
}

export { handler as POST, handler as GET, handler as PUT, handler as DELETE }
```

## Usage

Here is an example to create CRUD routes for an `User` resource given the following Prisma schema:
Expand Down
Loading

0 comments on commit 37ae669

Please sign in to comment.