Skip to content

Commit 4c197c0

Browse files
ABCrimsonclaude
andcommitted
fix: align API test mocks with security audit changes
- unshareWorksheet: include worksheetId in delete where clause (IDOR fix) - incrementWorksheetViews: add findUnique mock for existence check - forumPost: mock atomic update instead of findUnique (view counter fix) - forumPost not-found/soft-deleted: mock update rejection All 161 API tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8eec362 commit 4c197c0

1 file changed

Lines changed: 11 additions & 8 deletions

File tree

apps/api/src/__tests__/resolvers.test.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -875,13 +875,16 @@ describe('Worksheet Resolvers', () => {
875875
ctx,
876876
);
877877
expect(result).toBe(true);
878-
expect(prisma.worksheetShare.delete).toHaveBeenCalledWith({ where: { id: 'share1' } });
878+
expect(prisma.worksheetShare.delete).toHaveBeenCalledWith({
879+
where: { id: 'share1', worksheetId: 'ws1' },
880+
});
879881
});
880882
});
881883

882884
describe('Mutation.incrementWorksheetViews', () => {
883885
it('increments views and returns true', async () => {
884886
const prisma = createMockPrisma();
887+
prisma.worksheet.findUnique.mockResolvedValue(mockWorksheet);
885888
prisma.worksheet.update.mockResolvedValue({ ...mockWorksheet, views: 1 });
886889
const ctx = userContext(prisma);
887890

@@ -1464,26 +1467,26 @@ describe('Calculation Resolvers', () => {
14641467

14651468
describe('Forum Resolvers', () => {
14661469
describe('Query.forumPost', () => {
1467-
it('returns a post and increments view count', async () => {
1470+
it('returns a post and increments view count atomically', async () => {
14681471
const prisma = createMockPrisma();
1469-
prisma.forumPost.findUnique.mockResolvedValue(mockForumPost);
1470-
prisma.forumPost.update.mockResolvedValue({ ...mockForumPost, views: 1 });
1472+
const updatedPost = { ...mockForumPost, views: 1 };
1473+
prisma.forumPost.update.mockResolvedValue(updatedPost);
14711474
const ctx = makeContext({
14721475
user: null,
14731476
prisma: prisma as unknown as GraphQLContext['prisma'],
14741477
});
14751478

14761479
const result = await forumResolvers.Query.forumPost(null, { id: 'post1' }, ctx);
1477-
expect(result).toEqual(mockForumPost);
1480+
expect(result).toEqual(updatedPost);
14781481
expect(prisma.forumPost.update).toHaveBeenCalledWith({
1479-
where: { id: 'post1' },
1482+
where: { id: 'post1', deletedAt: null },
14801483
data: { views: { increment: 1 } },
14811484
});
14821485
});
14831486

14841487
it('throws NotFoundError when post does not exist', async () => {
14851488
const prisma = createMockPrisma();
1486-
prisma.forumPost.findUnique.mockResolvedValue(null);
1489+
prisma.forumPost.update.mockRejectedValue(new Error('Record not found'));
14871490
const ctx = makeContext({
14881491
user: null,
14891492
prisma: prisma as unknown as GraphQLContext['prisma'],
@@ -1496,7 +1499,7 @@ describe('Forum Resolvers', () => {
14961499

14971500
it('throws NotFoundError for soft-deleted posts', async () => {
14981501
const prisma = createMockPrisma();
1499-
prisma.forumPost.findUnique.mockResolvedValue({ ...mockForumPost, deletedAt: NOW });
1502+
prisma.forumPost.update.mockRejectedValue(new Error('Record not found'));
15001503
const ctx = makeContext({
15011504
user: null,
15021505
prisma: prisma as unknown as GraphQLContext['prisma'],

0 commit comments

Comments
 (0)