mirror of
https://github.com/typicode/json-server.git
synced 2025-07-30 05:31:41 +08:00
305 lines
6.9 KiB
TypeScript
305 lines
6.9 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
|
|
import { Low, Memory } from 'lowdb'
|
|
import { ParsedUrlQuery } from 'querystring'
|
|
|
|
import { Data, Item, PaginatedItems, Service } from './service.js'
|
|
|
|
const defaultData = { posts: [] }
|
|
const adapter = new Memory<Data>()
|
|
const db = new Low<Data>(adapter, defaultData)
|
|
const service = new Service(db)
|
|
|
|
const POSTS = 'posts'
|
|
const COMMENTS = 'comments'
|
|
const UNKNOWN_RESOURCE = 'xxx'
|
|
const UNKNOWN_ID = 'xxx'
|
|
|
|
const post1 = {
|
|
id: '1',
|
|
title: 'a',
|
|
views: 100,
|
|
author: { name: 'foo' },
|
|
tags: ['foo', 'bar'],
|
|
}
|
|
const post2 = {
|
|
id: '2',
|
|
title: 'b',
|
|
views: 200,
|
|
author: { name: 'bar' },
|
|
tags: ['bar'],
|
|
}
|
|
const post3 = {
|
|
id: '3',
|
|
title: 'c',
|
|
views: 300,
|
|
author: { name: 'baz' },
|
|
tags: ['foo'],
|
|
}
|
|
const comment1 = { id: '1', title: 'a', postId: '1' }
|
|
const items = 3
|
|
|
|
function reset() {
|
|
db.data = structuredClone({
|
|
posts: [post1, post2, post3],
|
|
comments: [comment1],
|
|
})
|
|
}
|
|
|
|
type Test = {
|
|
data?: Data
|
|
name: string
|
|
params?: ParsedUrlQuery
|
|
res: Item | Item[] | PaginatedItems | undefined
|
|
error?: Error
|
|
}
|
|
|
|
await test('findById', () => {
|
|
reset()
|
|
assert.deepEqual(service.findById(POSTS, '1', {}), db.data?.[POSTS]?.[0])
|
|
assert.equal(service.findById(POSTS, UNKNOWN_ID, {}), undefined)
|
|
assert.deepEqual(service.findById(POSTS, '1', { _include: ['comments'] }), {
|
|
...post1,
|
|
comments: [comment1],
|
|
})
|
|
assert.deepEqual(service.findById(COMMENTS, '1', { _include: ['post'] }), {
|
|
...comment1,
|
|
post: post1,
|
|
})
|
|
assert.equal(service.findById(UNKNOWN_RESOURCE, '1', {}), undefined)
|
|
})
|
|
|
|
await test('find', async (t) => {
|
|
const arr: Test[] = [
|
|
{
|
|
name: POSTS,
|
|
res: [post1, post2, post3],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { id: post1.id },
|
|
res: [post1],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { id: UNKNOWN_ID },
|
|
res: [],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views: post1.views.toString() },
|
|
res: [post1],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { 'author.name': post1.author.name },
|
|
res: [post1],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { 'tags[0]': 'foo' },
|
|
res: [post1, post3],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { id: UNKNOWN_ID, views: post1.views.toString() },
|
|
res: [],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views_ne: post1.views.toString() },
|
|
res: [post2, post3],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views_lt: (post1.views + 1).toString() },
|
|
res: [post1],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views_lt: post1.views.toString() },
|
|
res: [],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views_lte: post1.views.toString() },
|
|
res: [post1],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views_gt: post1.views.toString() },
|
|
res: [post2, post3],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views_gt: (post1.views - 1).toString() },
|
|
res: [post1, post2, post3],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { views_gte: post1.views.toString() },
|
|
res: [post1, post2, post3],
|
|
},
|
|
{
|
|
data: { posts: [post3, post1, post2] },
|
|
name: POSTS,
|
|
params: { _sort: 'views' },
|
|
res: [post1, post2, post3],
|
|
},
|
|
{
|
|
data: { posts: [post3, post1, post2] },
|
|
name: POSTS,
|
|
params: { _sort: '-views' },
|
|
res: [post3, post2, post1],
|
|
},
|
|
{
|
|
data: { posts: [post3, post1, post2] },
|
|
name: POSTS,
|
|
params: { _sort: '-views,id' },
|
|
res: [post3, post2, post1],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _start: '0', _end: '2' },
|
|
res: [post1, post2],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _start: '1', _end: '3' },
|
|
res: [post2, post3],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _start: '0', _limit: '2' },
|
|
res: [post1, post2],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _start: '1', _limit: '2' },
|
|
res: [post2, post3],
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _page: '1', _per_page: '2' },
|
|
res: {
|
|
first: 1,
|
|
last: 2,
|
|
prev: null,
|
|
next: 2,
|
|
pages: 2,
|
|
items,
|
|
data: [post1, post2],
|
|
},
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _page: '2', _per_page: '2' },
|
|
res: {
|
|
first: 1,
|
|
last: 2,
|
|
prev: 1,
|
|
next: null,
|
|
pages: 2,
|
|
items,
|
|
data: [post3],
|
|
},
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _page: '3', _per_page: '2' },
|
|
res: {
|
|
first: 1,
|
|
last: 2,
|
|
prev: 1,
|
|
next: null,
|
|
pages: 2,
|
|
items,
|
|
data: [post3],
|
|
},
|
|
},
|
|
{
|
|
name: POSTS,
|
|
params: { _include: ['comments'] },
|
|
res: [
|
|
{ ...post1, comments: [comment1] },
|
|
{ ...post2, comments: [] },
|
|
{ ...post3, comments: [] },
|
|
],
|
|
},
|
|
{
|
|
name: COMMENTS,
|
|
params: { _include: ['post'] },
|
|
res: [{ ...comment1, post: post1 }],
|
|
},
|
|
{
|
|
name: UNKNOWN_RESOURCE,
|
|
res: undefined,
|
|
},
|
|
]
|
|
for (const tc of arr) {
|
|
await t.test(`${tc.name} ${JSON.stringify(tc.params)}`, () => {
|
|
if (tc.data) {
|
|
db.data = tc.data
|
|
} else {
|
|
reset()
|
|
}
|
|
|
|
assert.deepEqual(service.find(tc.name, tc.params), tc.res)
|
|
})
|
|
}
|
|
})
|
|
|
|
await test('create', async () => {
|
|
reset()
|
|
const post = { title: 'new post' }
|
|
const res = await service.create(POSTS, post)
|
|
assert.equal(res?.['title'], post.title)
|
|
assert.equal(typeof res?.['id'], 'string', 'id should be a string')
|
|
|
|
assert.equal(await service.create(UNKNOWN_RESOURCE, post), undefined)
|
|
})
|
|
|
|
await test('update', async () => {
|
|
reset()
|
|
const post = { id: 'xxx', title: 'updated post' }
|
|
const res = await service.update(POSTS, post1.id, post)
|
|
assert.equal(res?.['id'], post1.id, 'id should not change')
|
|
assert.equal(res?.['title'], post.title)
|
|
|
|
assert.equal(
|
|
await service.update(UNKNOWN_RESOURCE, post1.id, post),
|
|
undefined,
|
|
)
|
|
assert.equal(await service.update(POSTS, UNKNOWN_ID, post), undefined)
|
|
})
|
|
|
|
await test('patch', async () => {
|
|
reset()
|
|
const post = { id: 'xxx', title: 'updated post' }
|
|
const res = await service.patch(POSTS, post1.id, post)
|
|
assert.notEqual(res, undefined)
|
|
assert.equal(res?.['id'], post1.id)
|
|
assert.equal(res?.['title'], post.title)
|
|
|
|
assert.equal(await service.patch(UNKNOWN_RESOURCE, post1.id, post), undefined)
|
|
assert.equal(await service.patch(POSTS, UNKNOWN_ID, post), undefined)
|
|
})
|
|
|
|
await test('destroy', async () => {
|
|
reset()
|
|
let prevLength = db.data?.[POSTS]?.length || 0
|
|
await service.destroy(POSTS, post1.id)
|
|
assert.equal(db.data?.[POSTS]?.length, prevLength - 1)
|
|
assert.deepEqual(db.data?.[COMMENTS], [{ ...comment1, postId: null }])
|
|
|
|
reset()
|
|
prevLength = db.data?.[POSTS]?.length || 0
|
|
await service.destroy(POSTS, post1.id, [COMMENTS])
|
|
assert.equal(db.data[POSTS].length, prevLength - 1)
|
|
assert.equal(db.data[COMMENTS].length, 0)
|
|
|
|
assert.equal(await service.destroy(UNKNOWN_RESOURCE, post1.id), undefined)
|
|
assert.equal(await service.destroy(POSTS, UNKNOWN_ID), undefined)
|
|
})
|