Skip to content

Commit

Permalink
feat: add app router support (#67)
Browse files Browse the repository at this point in the history
* feat: add app router support

* fix tests, update doc
  • Loading branch information
foyarash authored Apr 3, 2024
1 parent 27837de commit b48d461
Show file tree
Hide file tree
Showing 24 changed files with 2,872 additions and 3,000 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
86 changes: 33 additions & 53 deletions __tests__/handler.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import * as http from 'http'
import NextCrud from '../src/handler'
import {
IAdapter,
IParsedQueryParams,
RouteType,
TPaginationData,
} from '../src/types'
import { IAdapter, RouteType, TPaginationData } from '../src/types'
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 @@ -20,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 All @@ -31,50 +28,29 @@ class NoopAdapter implements IAdapter<unknown, unknown, string> {
this.models = models
}

async getPaginationData(
resourceName: string,
query: unknown,
lastElement?: unknown
): Promise<TPaginationData> {
async getPaginationData(): Promise<TPaginationData> {
return {
total: 1,
pageCount: 1,
page: 1,
}
}
parseQuery(resourceName: string, query?: IParsedQueryParams): unknown {
parseQuery(): unknown {
return {}
}
async getAll(resourceName: string, query?: unknown): Promise<unknown[]> {
async getAll(): Promise<unknown[]> {
return []
}
async getOne(
resourceName: string,
resourceId: string | number,
query?: unknown
): Promise<unknown> {
async getOne(): Promise<unknown> {
return {}
}
async create(
resourceName: string,
data: any,
query?: unknown
): Promise<unknown> {
async create(): Promise<unknown> {
return {}
}
async update(
resourceName: string,
resourceId: string | number,
data: any,
query?: unknown
): Promise<unknown> {
async update(): Promise<unknown> {
return {}
}
async delete(
resourceName: string,
resourceId: string | number,
query?: unknown
): Promise<unknown> {
async delete(): Promise<unknown> {
return {}
}

Expand All @@ -91,7 +67,7 @@ class InvalidAdapter {}

const generateNoopAdapter = (
methods: {
[name in keyof IAdapter<unknown, unknown>]?: (...args: any[]) => any
[name in keyof IAdapter<unknown, unknown>]?: (...args: unknown[]) => unknown
},
models: string[] = []
) => {
Expand Down Expand Up @@ -119,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 @@ -157,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 @@ -176,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 @@ -198,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 @@ -221,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 @@ -245,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 @@ -400,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 @@ -416,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 @@ -436,7 +416,7 @@ describe('Handler', () => {
method: 'GET',
})
await handler(req, res)
expect(res.send).toHaveBeenCalledWith(collection)
expect(res.json).toHaveBeenCalledWith(collection)
})
})

Expand All @@ -454,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 @@ -476,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 @@ -513,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 @@ -622,7 +602,7 @@ describe('Handler', () => {
})

await handler(req, res)
expect(res.send).toHaveBeenCalledWith({
expect(res.json).toHaveBeenCalledWith({
data: mockResources,
pagination: {
total: 1,
Expand Down
1 change: 1 addition & 0 deletions __tests__/queryParser.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { parseQuery } from '../src/queryParser'
import { IParsedQueryParams } from '../src/types'

Expand Down
Loading

0 comments on commit b48d461

Please sign in to comment.