import { jest, expect, describe, beforeEach, it } from '@jest/globals' import { Commenter, COMMENT_TAG, PRIX_BRANDING, COMMENT_GREETING } from '../commenter' // Mock dependencies jest.mock('../octokit', () => ({ octokit: { rest: { issues: { createComment: jest.fn(), updateComment: jest.fn(), listComments: jest.fn(), }, pulls: { listReviewComments: jest.fn(), createReview: jest.fn(), submitReview: jest.fn(), deletePendingReview: jest.fn(), deleteReviewComment: jest.fn(), createReviewComment: jest.fn(), createReplyForReviewComment: jest.fn(), updateReviewComment: jest.fn(), listReviews: jest.fn(), get: jest.fn(), update: jest.fn(), }, }, }, setOctokit: jest.fn(), })) jest.mock('../context', () => ({ als: { getStore: jest.fn(), }, })) describe('Commenter', () => { let commenter: Commenter const mockOctokit = { rest: { issues: { createComment: jest.fn(), updateComment: jest.fn(), listComments: jest.fn().mockResolvedValue({ data: [] }), }, pulls: { listReviewComments: jest.fn().mockResolvedValue({ data: [] }), createReview: jest.fn().mockResolvedValue({ data: { id: 1 } }), submitReview: jest.fn(), deletePendingReview: jest.fn(), listReviews: jest.fn().mockResolvedValue({ data: [] }), }, }, } beforeEach(() => { jest.clearAllMocks() commenter = new Commenter() const { als } = require('../context') als.getStore.mockReturnValue({ probotContext: { payload: { pull_request: { number: 123 } }, }, octokit: mockOctokit, repo: { owner: 'test-org', repo: 'test-repo' }, }) }) describe('constants', () => { it('should have proper branding constants', () => { expect(COMMENT_TAG).toContain('auto-generated') expect(PRIX_BRANDING).toContain('prixai.xyz') expect(COMMENT_GREETING).toContain('PRIX AI Code Review') }) }) describe('comment', () => { it('should create comment with branding', async () => { const { octokit } = require('../octokit') await commenter.comment('Test message', COMMENT_TAG, 'create') expect(octokit.rest.issues.createComment).toHaveBeenCalledWith( expect.objectContaining({ owner: 'test-org', repo: 'test-repo', body: expect.stringContaining('Test message'), }) ) }) it('should include branding in comment body', async () => { const { octokit } = require('../octokit') await commenter.comment('Test message', COMMENT_TAG, 'create') const callArg = octokit.rest.issues.createComment.mock.calls[0][0] expect(callArg.body).toContain(PRIX_BRANDING) expect(callArg.body).toContain(COMMENT_GREETING) }) }) describe('bufferReviewComment', () => { it('should buffer review comments with proper formatting', async () => { await commenter.bufferReviewComment( 'test.ts', 10, 15, 'CRITICAL | Bug: Something wrong', true ) // Should be stored in buffer for later submission expect(commenter).toBeInstanceOf(Commenter) }) it('should add verification badge for verified comments', async () => { await commenter.bufferReviewComment( 'test.ts', 10, 15, 'Test message', true, undefined ) }) }) describe('submitReview', () => { it('should submit review with comments', async () => { const { octokit } = require('../octokit') await commenter.bufferReviewComment('test.ts', 1, 5, 'Test issue', false) await commenter.submitReview(123, 'abc123', 'Status message') expect(octokit.rest.pulls.createReview).toHaveBeenCalled() }) it('should include branding in review body', async () => { const { octokit } = require('../octokit') await commenter.submitReview(123, 'abc123', 'Status message') const callArg = octokit.rest.pulls.createReview.mock.calls[0][0] expect(callArg.body).toContain(PRIX_BRANDING) }) }) })