UNPKG

@prisma-extensions/soft-delete

Version:

Soft Delete can be used to hide records instead of deleting them, making them recoverable later.

448 lines (359 loc) 11.7 kB
import { faker } from '@faker-js/faker' import { PrismaClient, type Post, type User } from '@prisma/client' import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest' import { applyExtension } from './soft-delete' const prisma = new PrismaClient() describe('Soft Delete', () => { afterAll(async () => { await prisma.post.deleteMany() await prisma.user.deleteMany() await prisma.$disconnect() }) describe('All Models', () => { const xprisma = prisma.$extends(applyExtension()) afterEach(async () => { await xprisma.post.deleteMany() await xprisma.user.deleteMany() }) describe('Mutations', () => { test('.softDelete', async () => { const user = await xprisma.user.create({ data: { firstName: faker.name.firstName(), lastName: faker.name.lastName(), }, }) const deleteOp = await xprisma.user.softDelete({ where: { id: user.id }, }) expect(deleteOp).toEqual( expect.objectContaining({ ...user, deletedAt: expect.any(Date), updatedAt: expect.any(Date), }), ) }) test('.softDeleteMany', async () => { const ids: number[] = [] const createUser = async () => { const post = await xprisma.user.create({ data: { firstName: faker.name.firstName(), lastName: faker.name.lastName(), }, }) ids.push(post.id) } await Promise.allSettled([createUser(), createUser(), createUser()]) const deleteOp = await xprisma.user.softDeleteMany() expect(deleteOp.count).toEqual(3) const findOp = await xprisma.user.findMany({ where: { id: { in: ids } }, }) expect(findOp.length).toEqual(0) }) test('.restore', async () => { const user = await xprisma.user.create({ data: { firstName: faker.name.firstName(), lastName: faker.name.lastName(), deletedAt: new Date(), }, }) const restoredUser = await xprisma.user.softRestore({ where: { id: user.id }, }) expect(restoredUser.deletedAt).toBeNull() }) test('.restoreMany', async () => { const deletedAt = new Date() const ids: number[] = [] const createUser = async () => { const user = await xprisma.user.create({ data: { firstName: faker.name.firstName(), lastName: faker.name.lastName(), deletedAt, }, }) ids.push(user.id) } await Promise.allSettled([createUser(), createUser(), createUser()]) const deleteOp = await xprisma.user.softRestoreMany() expect(deleteOp.count).toEqual(3) const findOp = await xprisma.user.findMany({ where: { id: { in: ids } }, }) expect(findOp.map((p) => p.id).sort()).toEqual(ids.sort()) }) }) describe('Queries', () => { let post: Post beforeAll(async () => { const author = await prisma.user.create({ data: { firstName: faker.name.firstName(), lastName: faker.name.lastName(), }, }) post = await xprisma.post.create({ data: { authorId: author.id, content: faker.lorem.paragraphs(3), title: faker.lorem.sentence(), deletedAt: new Date(), commentCount: 5, }, }) }) test('.aggregate', async () => { const { _avg } = await xprisma.post.aggregate({ _avg: { commentCount: true, }, }) expect(_avg.commentCount).toBeNull() }) test('.count', async () => { const count = await xprisma.post.count() expect(count).toBe(0) }) test('.findFirst', async () => { const res = await xprisma.post.findFirst({ where: { id: post.id } }) expect(res).toBeNull() }) test.todo('.findFirstOrThrow', async () => { // Prisma Client does not invoke the extended functions await expect( prisma.post.findFirstOrThrow({ where: { id: post.id }, }), ).rejects.toThrowError() }) test.todo('.findMany', async () => { // Prisma Client does not invoke the extended functions const res = await prisma.post.findMany({ where: { id: { in: post.id } }, }) expect(res).toStrictEqual([]) }) test('.groupBy', async () => { const res = await xprisma.post.groupBy({ by: ['authorId'], _count: { authorId: true, }, }) expect(res).toStrictEqual([]) }) }) }) describe('Selected Models', () => { let author: User const xprisma = prisma.$extends(applyExtension({ models: ['post'] })) beforeAll(async () => { author = await prisma.user.create({ data: { firstName: faker.name.firstName(), lastName: faker.name.lastName(), }, }) }) describe('Mutations', () => { afterEach(async () => { await xprisma.post.deleteMany() }) describe('Enabled', () => { test('.softDelete', async () => { const post = await xprisma.post.create({ data: { authorId: author.id, content: faker.lorem.paragraphs(3), title: faker.lorem.sentence(), }, }) const deleteOp = await xprisma.post.softDelete({ where: { id: post.id }, }) expect(deleteOp).toEqual( expect.objectContaining({ ...post, deletedAt: expect.any(Date), updatedAt: expect.any(Date), }), ) const findOp = await xprisma.post.findFirst({ where: { id: post.id }, }) expect(findOp).toBeNull() }) test('.softDeleteMany', async () => { const ids: number[] = [] const createPost = async () => { const post = await xprisma.post.create({ data: { authorId: author.id, content: faker.lorem.paragraphs(3), title: faker.lorem.sentence(), }, }) ids.push(post.id) } await Promise.allSettled([createPost(), createPost(), createPost()]) const deleteOp = await xprisma.post.softDeleteMany() expect(deleteOp.count).toEqual(3) const findOp = await xprisma.post.findMany({ where: { id: { in: ids } }, }) expect(findOp.length).toEqual(0) }) test('.restore', async () => { const post = await xprisma.post.create({ data: { authorId: author.id, content: faker.lorem.paragraphs(3), deletedAt: new Date(), title: faker.lorem.sentence(), }, }) const restoredPost = await xprisma.post.softRestore({ where: { id: post.id }, }) expect(restoredPost.deletedAt).toBeNull() }) test('.restoreMany', async () => { const deletedAt = new Date() const ids: number[] = [] const createPost = async () => { const post = await xprisma.post.create({ data: { authorId: author.id, content: faker.lorem.paragraphs(3), deletedAt, title: faker.lorem.sentence(), }, }) ids.push(post.id) } await Promise.allSettled([createPost(), createPost(), createPost()]) const deleteOp = await xprisma.post.softRestoreMany() expect(deleteOp.count).toEqual(3) const findOp = await xprisma.post.findMany({ where: { id: { in: ids } }, }) expect(findOp.map((p) => p.id).sort()).toEqual(ids.sort()) }) }) }) describe('Queries', () => { describe('Modified ', () => { let post: Post beforeAll(async () => { post = await xprisma.post.create({ data: { authorId: author.id, content: faker.lorem.paragraphs(3), title: faker.lorem.sentence(), deletedAt: new Date(), commentCount: 5, }, }) }) test('.aggregate', async () => { const { _avg } = await xprisma.post.aggregate({ _avg: { commentCount: true, }, }) expect(_avg.commentCount).toBeNull() }) test('.count', async () => { const count = await xprisma.post.count() expect(count).toBe(0) }) test('.findFirst', async () => { const res = await xprisma.post.findFirst({ where: { id: post.id } }) expect(res).toBeNull() }) test.todo('.findFirstOrThrow', async () => { // Prisma Client does not invoke the extended functions await expect( prisma.post.findFirstOrThrow({ where: { id: post.id }, }), ).rejects.toThrowError() }) test.todo('.findMany', async () => { // Prisma Client does not invoke the extended functions const res = await prisma.post.findMany({ where: { id: { in: post.id } }, }) expect(res).toStrictEqual([]) }) test('.groupBy', async () => { const res = await xprisma.post.groupBy({ by: ['authorId'], _count: { authorId: true, }, }) expect(res).toStrictEqual([]) }) }) describe('Unmodified', () => { test('.aggregate', async () => { const { _avg } = await xprisma.user.aggregate({ _avg: { id: true, }, }) expect(_avg.id).toEqual(author.id) }) test('.count', async () => { const count = await xprisma.user.count() expect(count).toBe(1) }) test('.findFirst', async () => { const res = await xprisma.user.findFirst({ where: { id: author.id } }) expect(res).toStrictEqual(author) }) test('.findFirstOrThrow - resolves', async () => { const res = await prisma.user.findFirstOrThrow({ where: { id: author.id }, }) expect(res).toStrictEqual(author) }) test('.findFirstOrThrow - throws', async () => { await expect( prisma.user.findFirstOrThrow({ where: { firstName: 'no-name' }, }), ).rejects.toThrowError() }) test('.findMany', async () => { const res = await prisma.user.findMany({ where: { id: { in: author.id } }, }) expect(res).toStrictEqual([author]) }) test('.groupBy', async () => { const res = await xprisma.user.groupBy({ by: ['id'], _count: { id: true, }, }) expect(res).toStrictEqual([ { _count: { id: 1, }, id: author.id, }, ]) }) }) }) }) })