| |
| |
| |
|
|
|
|
| import * as fs from 'fs'
|
| import * as path from 'path'
|
| import {ReviewComment, MockPRContext} from './types'
|
|
|
| export interface MockedCall {
|
| method: string
|
| endpoint: string
|
| payload: any
|
| timestamp: number
|
| }
|
|
|
| export class MockGitHubLayer {
|
| private calls: MockedCall[] = []
|
| private comments: ReviewComment[] = []
|
| private createdPRs: any[] = []
|
| private context: MockPRContext
|
| private logFile: string | null = null
|
|
|
| constructor(context: MockPRContext, options?: {logFile?: string}) {
|
| this.context = context
|
| if (options?.logFile) {
|
| this.logFile = options.logFile
|
| }
|
| }
|
|
|
| |
| |
|
|
| createMockOctokit(): any {
|
| return {
|
| issues: {
|
| createComment: async (params: any) => {
|
| this.recordCall('POST', 'issues.createComment', params)
|
| this.comments.push({
|
| path: params.path || 'general',
|
| line: params.line || 0,
|
| body: params.body,
|
| severity: 'info'
|
| })
|
| this.log(`💬 Comment created on ${params.path}:${params.line}`)
|
| return {data: {id: Date.now(), ...params}}
|
| }
|
| },
|
| pulls: {
|
| create: async (params: any) => {
|
| this.recordCall('POST', 'pulls.create', params)
|
| const pr = {
|
| number: Date.now(),
|
| html_url: `https://github.com/mock/repo/pull/${Date.now()}`,
|
| ...params
|
| }
|
| this.createdPRs.push(pr)
|
| this.log(`🔀 PR created: ${pr.title} (draft: ${params.draft})`)
|
| return {data: pr}
|
| },
|
| update: async (params: any) => {
|
| this.recordCall('PATCH', 'pulls.update', params)
|
| this.log(`📝 PR #${params.pull_number} updated`)
|
| return {data: {...params}}
|
| },
|
| list: async (params: any) => {
|
| this.recordCall('GET', 'pulls.list', params)
|
| return {data: this.createdPRs.filter(pr => pr.state === params.state)}
|
| }
|
| },
|
| repos: {
|
| getContent: async (params: any) => {
|
| this.recordCall('GET', 'repos.getContent', params)
|
|
|
| try {
|
| const filePath = path.join(this.context.head.ref, params.path)
|
| if (fs.existsSync(filePath)) {
|
| const content = fs.readFileSync(filePath, 'utf8')
|
| return {
|
| data: {
|
| content: Buffer.from(content).toString('base64'),
|
| encoding: 'base64'
|
| }
|
| }
|
| }
|
| } catch (e) {
|
|
|
| }
|
| return {data: null}
|
| }
|
| },
|
| rest: {
|
| pulls: {
|
| listFiles: async (params: any) => {
|
| this.recordCall('GET', 'pulls.listFiles', params)
|
| return {
|
| data: this.context.files.map(f => ({
|
| filename: f.filename,
|
| status: 'modified',
|
| changes: f.diff.split('\n').length,
|
| patch: f.diff
|
| }))
|
| }
|
| }
|
| }
|
| }
|
| }
|
| }
|
|
|
| |
| |
|
|
| createMockProbotContext(): any {
|
| const octokit = this.createMockOctokit()
|
| return {
|
| log: {
|
| info: (msg: string) => this.log(`ℹ️ ${msg}`),
|
| warn: (msg: string) => this.log(`⚠️ ${msg}`),
|
| error: (msg: string) => this.log(`❌ ${msg}`),
|
| debug: (msg: string) => this.log(`🐛 ${msg}`)
|
| },
|
| octokit,
|
| payload: {
|
| pull_request: this.context,
|
| repository: {
|
| owner: {login: 'mock-owner'},
|
| name: 'mock-repo'
|
| }
|
| },
|
| repo: () => ({
|
| owner: 'mock-owner',
|
| repo: 'mock-repo'
|
| })
|
| }
|
| }
|
|
|
| private recordCall(method: string, endpoint: string, payload: any): void {
|
| this.calls.push({
|
| method,
|
| endpoint,
|
| payload,
|
| timestamp: Date.now()
|
| })
|
| }
|
|
|
| private log(message: string): void {
|
| const timestamp = new Date().toISOString()
|
| const logLine = `[${timestamp}] ${message}`
|
| console.log(logLine)
|
|
|
| if (this.logFile) {
|
| fs.appendFileSync(this.logFile, logLine + '\n')
|
| }
|
| }
|
|
|
| getCalls(): MockedCall[] {
|
| return [...this.calls]
|
| }
|
|
|
| getComments(): ReviewComment[] {
|
| return [...this.comments]
|
| }
|
|
|
| getCreatedPRs(): any[] {
|
| return [...this.createdPRs]
|
| }
|
|
|
| clear(): void {
|
| this.calls = []
|
| this.comments = []
|
| this.createdPRs = []
|
| }
|
|
|
| generateReport(): string {
|
| const lines = [
|
| '=== Mock GitHub Activity Report ===',
|
| `Total API Calls: ${this.calls.length}`,
|
| `Comments Created: ${this.comments.length}`,
|
| `PRs Created: ${this.createdPRs.length}`,
|
| '',
|
| 'API Calls:',
|
| ...this.calls.map(c => ` ${c.method} ${c.endpoint}`),
|
| '',
|
| 'Comments:',
|
| ...this.comments.map(
|
| c => ` ${c.path}:${c.line} - ${c.body.substring(0, 50)}...`
|
| ),
|
| '',
|
| 'Created PRs:',
|
| ...this.createdPRs.map(pr => ` #${pr.number}: ${pr.title}`)
|
| ]
|
| return lines.join('\n')
|
| }
|
| }
|
|
|
| |
| |
|
|
| export function suppressGitHubCalls(): void {
|
|
|
| process.env.ENABLE_AUTO_PR = 'false'
|
| }
|
|
|
| |
| |
|
|
| export function restoreGitHubCalls(): void {
|
|
|
| }
|
|
|