@aaronshaf/ger 0.2.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +3 -3
- package/README.md +49 -0
- package/package.json +1 -1
- package/src/cli/commands/build-status.ts +116 -0
- package/src/cli/commands/show.ts +138 -64
- package/src/cli/index.ts +58 -0
- package/tests/abandon.test.ts +178 -111
- package/tests/build-status.test.ts +691 -0
- package/tests/mine.test.ts +130 -163
- package/tests/show-auto-detect.test.ts +20 -2
- package/tests/show.test.ts +226 -8
- package/tests/mocks/fetch-mock.ts +0 -142
- package/tests/setup.ts +0 -13
package/tests/show.test.ts
CHANGED
|
@@ -27,6 +27,7 @@ const server = setupServer(
|
|
|
27
27
|
// Store captured output
|
|
28
28
|
let capturedLogs: string[] = []
|
|
29
29
|
let capturedErrors: string[] = []
|
|
30
|
+
let capturedStdout: string[] = []
|
|
30
31
|
|
|
31
32
|
// Mock console.log and console.error
|
|
32
33
|
const mockConsoleLog = mock((...args: any[]) => {
|
|
@@ -36,9 +37,20 @@ const mockConsoleError = mock((...args: any[]) => {
|
|
|
36
37
|
capturedErrors.push(args.join(' '))
|
|
37
38
|
})
|
|
38
39
|
|
|
39
|
-
//
|
|
40
|
+
// Mock process.stdout.write to capture JSON output and handle callbacks
|
|
41
|
+
const mockStdoutWrite = mock((chunk: any, callback?: any) => {
|
|
42
|
+
capturedStdout.push(String(chunk))
|
|
43
|
+
// Call the callback synchronously if provided
|
|
44
|
+
if (typeof callback === 'function') {
|
|
45
|
+
callback()
|
|
46
|
+
}
|
|
47
|
+
return true
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// Store original methods
|
|
40
51
|
const originalConsoleLog = console.log
|
|
41
52
|
const originalConsoleError = console.error
|
|
53
|
+
const originalStdoutWrite = process.stdout.write
|
|
42
54
|
|
|
43
55
|
beforeAll(() => {
|
|
44
56
|
server.listen({ onUnhandledRequest: 'bypass' })
|
|
@@ -46,20 +58,26 @@ beforeAll(() => {
|
|
|
46
58
|
console.log = mockConsoleLog
|
|
47
59
|
// @ts-ignore
|
|
48
60
|
console.error = mockConsoleError
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
process.stdout.write = mockStdoutWrite
|
|
49
63
|
})
|
|
50
64
|
|
|
51
65
|
afterAll(() => {
|
|
52
66
|
server.close()
|
|
53
67
|
console.log = originalConsoleLog
|
|
54
68
|
console.error = originalConsoleError
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
process.stdout.write = originalStdoutWrite
|
|
55
71
|
})
|
|
56
72
|
|
|
57
73
|
afterEach(() => {
|
|
58
74
|
server.resetHandlers()
|
|
59
75
|
mockConsoleLog.mockClear()
|
|
60
76
|
mockConsoleError.mockClear()
|
|
77
|
+
mockStdoutWrite.mockClear()
|
|
61
78
|
capturedLogs = []
|
|
62
79
|
capturedErrors = []
|
|
80
|
+
capturedStdout = []
|
|
63
81
|
})
|
|
64
82
|
|
|
65
83
|
describe('show command', () => {
|
|
@@ -201,7 +219,7 @@ describe('show command', () => {
|
|
|
201
219
|
|
|
202
220
|
await Effect.runPromise(program)
|
|
203
221
|
|
|
204
|
-
const output =
|
|
222
|
+
const output = capturedStdout.join('')
|
|
205
223
|
|
|
206
224
|
expect(output).toContain('<?xml version="1.0" encoding="UTF-8"?>')
|
|
207
225
|
expect(output).toContain('<show_result>')
|
|
@@ -258,7 +276,7 @@ describe('show command', () => {
|
|
|
258
276
|
|
|
259
277
|
await Effect.runPromise(program)
|
|
260
278
|
|
|
261
|
-
const output =
|
|
279
|
+
const output = capturedStdout.join('')
|
|
262
280
|
|
|
263
281
|
expect(output).toContain('<?xml version="1.0" encoding="UTF-8"?>')
|
|
264
282
|
expect(output).toContain('<show_result>')
|
|
@@ -301,7 +319,7 @@ describe('show command', () => {
|
|
|
301
319
|
|
|
302
320
|
await Effect.runPromise(program)
|
|
303
321
|
|
|
304
|
-
const output =
|
|
322
|
+
const output = capturedStdout.join('')
|
|
305
323
|
|
|
306
324
|
expect(output).toContain('<subject><![CDATA[Fix "quotes" & <tags> in auth]]></subject>')
|
|
307
325
|
expect(output).toContain('<branch>feature/fix&improve</branch>')
|
|
@@ -450,7 +468,7 @@ describe('show command', () => {
|
|
|
450
468
|
|
|
451
469
|
await Effect.runPromise(program)
|
|
452
470
|
|
|
453
|
-
const output =
|
|
471
|
+
const output = capturedStdout.join('')
|
|
454
472
|
|
|
455
473
|
// Parse JSON to verify it's valid
|
|
456
474
|
const parsed = JSON.parse(output)
|
|
@@ -495,7 +513,7 @@ describe('show command', () => {
|
|
|
495
513
|
|
|
496
514
|
await Effect.runPromise(program)
|
|
497
515
|
|
|
498
|
-
const output =
|
|
516
|
+
const output = capturedStdout.join('')
|
|
499
517
|
|
|
500
518
|
// Parse JSON to verify it's valid
|
|
501
519
|
const parsed = JSON.parse(output)
|
|
@@ -516,7 +534,7 @@ describe('show command', () => {
|
|
|
516
534
|
|
|
517
535
|
await Effect.runPromise(program)
|
|
518
536
|
|
|
519
|
-
const output =
|
|
537
|
+
const output = capturedStdout.join('')
|
|
520
538
|
|
|
521
539
|
// Extract comment sections to verify order
|
|
522
540
|
const commentMatches = output.matchAll(
|
|
@@ -581,7 +599,7 @@ describe('show command', () => {
|
|
|
581
599
|
|
|
582
600
|
await Effect.runPromise(program)
|
|
583
601
|
|
|
584
|
-
const output =
|
|
602
|
+
const output = capturedStdout.join('')
|
|
585
603
|
const parsed = JSON.parse(output)
|
|
586
604
|
|
|
587
605
|
expect(parsed.messages).toBeDefined()
|
|
@@ -592,4 +610,204 @@ describe('show command', () => {
|
|
|
592
610
|
expect(parsed.messages[0].author.name).toBe('Jenkins Bot')
|
|
593
611
|
expect(parsed.messages[0].revision).toBe(2)
|
|
594
612
|
})
|
|
613
|
+
|
|
614
|
+
test('should handle large JSON output without truncation', async () => {
|
|
615
|
+
// Create a large diff to simulate output > 64KB
|
|
616
|
+
const largeDiff = '--- a/large-file.js\n+++ b/large-file.js\n' + 'x'.repeat(100000)
|
|
617
|
+
|
|
618
|
+
const mockChange = generateMockChange({
|
|
619
|
+
_number: 12345,
|
|
620
|
+
subject: 'Large change with extensive diff',
|
|
621
|
+
})
|
|
622
|
+
|
|
623
|
+
// Create many comments to increase JSON size
|
|
624
|
+
const manyComments: Record<string, any[]> = {
|
|
625
|
+
'src/file.js': Array.from({ length: 100 }, (_, i) => ({
|
|
626
|
+
id: `comment${i}`,
|
|
627
|
+
path: 'src/file.js',
|
|
628
|
+
line: i + 1,
|
|
629
|
+
message: `Comment ${i}: ${'a'.repeat(500)}`, // Make comments substantial
|
|
630
|
+
author: {
|
|
631
|
+
name: 'Reviewer',
|
|
632
|
+
email: 'reviewer@example.com',
|
|
633
|
+
},
|
|
634
|
+
updated: '2024-01-15 11:30:00.000000000',
|
|
635
|
+
unresolved: false,
|
|
636
|
+
})),
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
server.use(
|
|
640
|
+
http.get('*/a/changes/:changeId', () => {
|
|
641
|
+
return HttpResponse.text(`)]}'\n${JSON.stringify(mockChange)}`)
|
|
642
|
+
}),
|
|
643
|
+
http.get('*/a/changes/:changeId/revisions/current/patch', () => {
|
|
644
|
+
return HttpResponse.text(btoa(largeDiff))
|
|
645
|
+
}),
|
|
646
|
+
http.get('*/a/changes/:changeId/revisions/current/comments', () => {
|
|
647
|
+
return HttpResponse.text(`)]}'\n${JSON.stringify(manyComments)}`)
|
|
648
|
+
}),
|
|
649
|
+
http.get('*/a/changes/:changeId/revisions/current/files/:fileName/diff', () => {
|
|
650
|
+
return HttpResponse.text('context')
|
|
651
|
+
}),
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
const mockConfigLayer = createMockConfigLayer()
|
|
655
|
+
const program = showCommand('12345', { json: true }).pipe(
|
|
656
|
+
Effect.provide(GerritApiServiceLive),
|
|
657
|
+
Effect.provide(mockConfigLayer),
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
await Effect.runPromise(program)
|
|
661
|
+
|
|
662
|
+
const output = capturedStdout.join('')
|
|
663
|
+
|
|
664
|
+
// Verify output is larger than 64KB (the previous truncation point)
|
|
665
|
+
expect(output.length).toBeGreaterThan(65536)
|
|
666
|
+
|
|
667
|
+
// Verify JSON is valid and complete
|
|
668
|
+
const parsed = JSON.parse(output)
|
|
669
|
+
expect(parsed.status).toBe('success')
|
|
670
|
+
expect(parsed.diff).toContain('x'.repeat(100000))
|
|
671
|
+
expect(parsed.comments.length).toBe(100)
|
|
672
|
+
|
|
673
|
+
// Verify last comment is present (proves no truncation)
|
|
674
|
+
const lastComment = parsed.comments[parsed.comments.length - 1]
|
|
675
|
+
expect(lastComment.message).toContain('Comment 99')
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
test('should handle stdout drain event when buffer is full', async () => {
|
|
679
|
+
setupMockHandlers()
|
|
680
|
+
|
|
681
|
+
// Store original stdout.write
|
|
682
|
+
const originalStdoutWrite = process.stdout.write
|
|
683
|
+
|
|
684
|
+
let drainCallback: (() => void) | null = null
|
|
685
|
+
let errorCallback: ((err: Error) => void) | null = null
|
|
686
|
+
let writeCallbackFn: ((err?: Error) => void) | null = null
|
|
687
|
+
|
|
688
|
+
// Mock stdout.write to simulate full buffer
|
|
689
|
+
const mockWrite = mock((chunk: any, callback?: any) => {
|
|
690
|
+
capturedStdout.push(String(chunk))
|
|
691
|
+
writeCallbackFn = callback
|
|
692
|
+
// Return false to simulate full buffer
|
|
693
|
+
return false
|
|
694
|
+
})
|
|
695
|
+
|
|
696
|
+
// Mock stdout.once to capture drain and error listeners
|
|
697
|
+
const mockOnce = mock((event: string, callback: any) => {
|
|
698
|
+
if (event === 'drain') {
|
|
699
|
+
drainCallback = callback
|
|
700
|
+
// Simulate drain event after a short delay
|
|
701
|
+
setTimeout(() => {
|
|
702
|
+
if (drainCallback) {
|
|
703
|
+
drainCallback()
|
|
704
|
+
if (writeCallbackFn) {
|
|
705
|
+
writeCallbackFn()
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}, 10)
|
|
709
|
+
} else if (event === 'error') {
|
|
710
|
+
errorCallback = callback
|
|
711
|
+
}
|
|
712
|
+
return process.stdout
|
|
713
|
+
})
|
|
714
|
+
|
|
715
|
+
// Apply mocks
|
|
716
|
+
// @ts-ignore
|
|
717
|
+
process.stdout.write = mockWrite
|
|
718
|
+
// @ts-ignore
|
|
719
|
+
process.stdout.once = mockOnce
|
|
720
|
+
|
|
721
|
+
const mockConfigLayer = createMockConfigLayer()
|
|
722
|
+
const program = showCommand('12345', { json: true }).pipe(
|
|
723
|
+
Effect.provide(GerritApiServiceLive),
|
|
724
|
+
Effect.provide(mockConfigLayer),
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
await Effect.runPromise(program)
|
|
728
|
+
|
|
729
|
+
// Restore original stdout.write
|
|
730
|
+
// @ts-ignore
|
|
731
|
+
process.stdout.write = originalStdoutWrite
|
|
732
|
+
|
|
733
|
+
// Verify that write returned false (buffer full)
|
|
734
|
+
expect(mockWrite).toHaveBeenCalled()
|
|
735
|
+
|
|
736
|
+
// Verify that drain listener was registered
|
|
737
|
+
expect(mockOnce).toHaveBeenCalledWith('drain', expect.any(Function))
|
|
738
|
+
|
|
739
|
+
// Verify that error listener was registered for robustness
|
|
740
|
+
expect(mockOnce).toHaveBeenCalledWith('error', expect.any(Function))
|
|
741
|
+
|
|
742
|
+
// Verify output is still valid JSON despite drain handling
|
|
743
|
+
const output = capturedStdout.join('')
|
|
744
|
+
const parsed = JSON.parse(output)
|
|
745
|
+
expect(parsed.status).toBe('success')
|
|
746
|
+
expect(parsed.change.id).toBe('I123abc456def')
|
|
747
|
+
})
|
|
748
|
+
|
|
749
|
+
test('should handle large XML output without truncation', async () => {
|
|
750
|
+
// Create a large diff to simulate output > 64KB
|
|
751
|
+
const largeDiff = '--- a/large-file.js\n+++ b/large-file.js\n' + 'x'.repeat(100000)
|
|
752
|
+
|
|
753
|
+
const mockChange = generateMockChange({
|
|
754
|
+
_number: 12345,
|
|
755
|
+
subject: 'Large change with extensive diff',
|
|
756
|
+
})
|
|
757
|
+
|
|
758
|
+
// Create many comments to increase XML size
|
|
759
|
+
const manyComments: Record<string, any[]> = {
|
|
760
|
+
'src/file.js': Array.from({ length: 100 }, (_, i) => ({
|
|
761
|
+
id: `comment${i}`,
|
|
762
|
+
path: 'src/file.js',
|
|
763
|
+
line: i + 1,
|
|
764
|
+
message: `Comment ${i}: ${'a'.repeat(500)}`,
|
|
765
|
+
author: {
|
|
766
|
+
name: 'Reviewer',
|
|
767
|
+
email: 'reviewer@example.com',
|
|
768
|
+
},
|
|
769
|
+
updated: '2024-01-15 11:30:00.000000000',
|
|
770
|
+
unresolved: false,
|
|
771
|
+
})),
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
server.use(
|
|
775
|
+
http.get('*/a/changes/:changeId', () => {
|
|
776
|
+
return HttpResponse.text(`)]}'\n${JSON.stringify(mockChange)}`)
|
|
777
|
+
}),
|
|
778
|
+
http.get('*/a/changes/:changeId/revisions/current/patch', () => {
|
|
779
|
+
return HttpResponse.text(btoa(largeDiff))
|
|
780
|
+
}),
|
|
781
|
+
http.get('*/a/changes/:changeId/revisions/current/comments', () => {
|
|
782
|
+
return HttpResponse.text(`)]}'\n${JSON.stringify(manyComments)}`)
|
|
783
|
+
}),
|
|
784
|
+
http.get('*/a/changes/:changeId/revisions/current/files/:fileName/diff', () => {
|
|
785
|
+
return HttpResponse.text('context')
|
|
786
|
+
}),
|
|
787
|
+
)
|
|
788
|
+
|
|
789
|
+
const mockConfigLayer = createMockConfigLayer()
|
|
790
|
+
const program = showCommand('12345', { xml: true }).pipe(
|
|
791
|
+
Effect.provide(GerritApiServiceLive),
|
|
792
|
+
Effect.provide(mockConfigLayer),
|
|
793
|
+
)
|
|
794
|
+
|
|
795
|
+
await Effect.runPromise(program)
|
|
796
|
+
|
|
797
|
+
const output = capturedStdout.join('')
|
|
798
|
+
|
|
799
|
+
// Verify output is larger than 64KB
|
|
800
|
+
expect(output.length).toBeGreaterThan(65536)
|
|
801
|
+
|
|
802
|
+
// Verify XML is valid and complete
|
|
803
|
+
expect(output).toContain('<?xml version="1.0" encoding="UTF-8"?>')
|
|
804
|
+
expect(output).toContain('<show_result>')
|
|
805
|
+
expect(output).toContain('<status>success</status>')
|
|
806
|
+
expect(output).toContain('x'.repeat(100000))
|
|
807
|
+
expect(output).toContain('<count>100</count>')
|
|
808
|
+
expect(output).toContain('</show_result>')
|
|
809
|
+
|
|
810
|
+
// Verify last comment is present (proves no truncation)
|
|
811
|
+
expect(output).toContain('Comment 99')
|
|
812
|
+
})
|
|
595
813
|
})
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { mock } from 'bun:test'
|
|
2
|
-
import { Schema } from '@effect/schema'
|
|
3
|
-
import { ChangeInfo } from '@/schemas/gerrit'
|
|
4
|
-
import {
|
|
5
|
-
generateMockAccount,
|
|
6
|
-
generateMockChange,
|
|
7
|
-
generateMockFileDiff,
|
|
8
|
-
generateMockFiles,
|
|
9
|
-
} from '@/test-utils/mock-generator'
|
|
10
|
-
|
|
11
|
-
// Generate consistent mock data using Effect Schema
|
|
12
|
-
const mockChange = generateMockChange()
|
|
13
|
-
const mockFiles = generateMockFiles()
|
|
14
|
-
const mockDiff = generateMockFileDiff()
|
|
15
|
-
const mockAccount = generateMockAccount()
|
|
16
|
-
|
|
17
|
-
// Keep the old mockChange definition for now as backup (disabled to fix unused variable)
|
|
18
|
-
// const _mockChange: Schema.Schema.Type<typeof ChangeInfo> = {
|
|
19
|
-
// id: 'myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940',
|
|
20
|
-
// project: 'myProject',
|
|
21
|
-
// branch: 'master',
|
|
22
|
-
// change_id: 'I8473b95934b5732ac55d26311a706c9c2bde9940',
|
|
23
|
-
// subject: 'Implementing new feature',
|
|
24
|
-
// status: 'NEW',
|
|
25
|
-
// created: '2023-12-01 10:00:00.000000000',
|
|
26
|
-
// updated: '2023-12-01 12:00:00.000000000',
|
|
27
|
-
// _number: 123456,
|
|
28
|
-
// owner: {
|
|
29
|
-
// _account_id: 1000000,
|
|
30
|
-
// name: 'John Doe',
|
|
31
|
-
// email: 'john.doe@example.com',
|
|
32
|
-
// },
|
|
33
|
-
// labels: {},
|
|
34
|
-
// permitted_labels: {},
|
|
35
|
-
// removable_reviewers: [],
|
|
36
|
-
// reviewers: {},
|
|
37
|
-
// requirements: [],
|
|
38
|
-
// }
|
|
39
|
-
|
|
40
|
-
export const setupFetchMock = (): ((
|
|
41
|
-
url: string | URL,
|
|
42
|
-
options?: RequestInit,
|
|
43
|
-
) => Promise<Response>) => {
|
|
44
|
-
return mock(async (url: string | URL, options?: RequestInit): Promise<Response> => {
|
|
45
|
-
const urlStr = url.toString()
|
|
46
|
-
const method = options?.method || 'GET'
|
|
47
|
-
|
|
48
|
-
// Check authentication
|
|
49
|
-
const authHeader =
|
|
50
|
-
options?.headers && 'Authorization' in options.headers
|
|
51
|
-
? (options.headers as Record<string, string>).Authorization
|
|
52
|
-
: undefined
|
|
53
|
-
|
|
54
|
-
if (!authHeader || !authHeader.startsWith('Basic ')) {
|
|
55
|
-
return new Response(`)]}'\n${JSON.stringify({ message: 'Unauthorized' })}`, { status: 401 })
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Authentication endpoint
|
|
59
|
-
if (urlStr.includes('/a/accounts/self')) {
|
|
60
|
-
return new Response(`)]}'\n${JSON.stringify(mockAccount)}`, { status: 200 })
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// List changes endpoint (must come before get change endpoint)
|
|
64
|
-
if (urlStr.includes('/a/changes/?q=')) {
|
|
65
|
-
return new Response(`)]}'\n${JSON.stringify([mockChange])}`, { status: 200 })
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Get change endpoint
|
|
69
|
-
if (
|
|
70
|
-
urlStr.includes('/a/changes/') &&
|
|
71
|
-
method === 'GET' &&
|
|
72
|
-
!urlStr.includes('/files') &&
|
|
73
|
-
!urlStr.includes('/diff') &&
|
|
74
|
-
!urlStr.includes('/patch') &&
|
|
75
|
-
!urlStr.includes('/review')
|
|
76
|
-
) {
|
|
77
|
-
if (urlStr.includes('notfound')) {
|
|
78
|
-
return new Response(`)]}'\n${JSON.stringify({ message: 'Not found' })}`, { status: 404 })
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Validate response against schema
|
|
82
|
-
const validated = Schema.decodeUnknownSync(ChangeInfo)(mockChange)
|
|
83
|
-
return new Response(`)]}'\n${JSON.stringify(validated)}`, { status: 200 })
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Get file diff endpoint - must be checked BEFORE other file endpoints
|
|
87
|
-
if (urlStr.includes('/files/') && urlStr.includes('/diff') && method === 'GET') {
|
|
88
|
-
return new Response(`)]}'\n${JSON.stringify(mockDiff)}`, { status: 200 })
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Get files endpoint (list of files)
|
|
92
|
-
if (
|
|
93
|
-
urlStr.includes('/files') &&
|
|
94
|
-
method === 'GET' &&
|
|
95
|
-
!urlStr.includes('/diff') &&
|
|
96
|
-
!urlStr.includes('/content')
|
|
97
|
-
) {
|
|
98
|
-
return new Response(`)]}'\n${JSON.stringify(mockFiles)}`, { status: 200 })
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Get file content endpoint
|
|
102
|
-
if (urlStr.includes('/content') && method === 'GET' && !urlStr.includes('/diff')) {
|
|
103
|
-
const content =
|
|
104
|
-
'function main() {\n console.log("Hello, world!")\n return process.exit(0)\n}'
|
|
105
|
-
const base64Content = btoa(content)
|
|
106
|
-
return new Response(base64Content, { status: 200 })
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Get patch endpoint
|
|
110
|
-
if (urlStr.includes('/patch') && method === 'GET') {
|
|
111
|
-
const patch = `--- a/src/main.ts
|
|
112
|
-
+++ b/src/main.ts
|
|
113
|
-
@@ -1,3 +1,3 @@
|
|
114
|
-
function main() {
|
|
115
|
-
console.log("Hello, world!")
|
|
116
|
-
- return 0
|
|
117
|
-
+ return process.exit(0)
|
|
118
|
-
}`
|
|
119
|
-
const base64Patch = btoa(patch)
|
|
120
|
-
return new Response(base64Patch, { status: 200 })
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Post review endpoint
|
|
124
|
-
if (urlStr.includes('/review') && method === 'POST') {
|
|
125
|
-
return new Response(
|
|
126
|
-
")]}'\n" +
|
|
127
|
-
JSON.stringify({
|
|
128
|
-
labels: {},
|
|
129
|
-
ready: true,
|
|
130
|
-
}),
|
|
131
|
-
{ status: 200 },
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Default 404 for unhandled requests
|
|
136
|
-
return new Response(`)]}'\n${JSON.stringify({ message: 'Not found' })}`, { status: 404 })
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export const restoreFetch: () => void = () => {
|
|
141
|
-
// Restore original fetch (Bun handles this automatically after tests)
|
|
142
|
-
}
|
package/tests/setup.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeAll } from 'bun:test'
|
|
2
|
-
import { setupFetchMock } from './mocks/fetch-mock'
|
|
3
|
-
|
|
4
|
-
// Setup Bun's native fetch mocking before all tests
|
|
5
|
-
beforeAll(() => {
|
|
6
|
-
setupFetchMock()
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
// Clean up after each test (Bun automatically restores mocks)
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
// Bun automatically handles mock cleanup
|
|
12
|
-
// But we can reset if needed
|
|
13
|
-
})
|