@aaronshaf/ger 0.2.4 → 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.
@@ -1,26 +1,48 @@
1
- import { describe, test, expect, beforeEach } from 'bun:test'
1
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, mock, test } from 'bun:test'
2
2
  import { Effect, Layer } from 'effect'
3
+ import { HttpResponse, http } from 'msw'
4
+ import { setupServer } from 'msw/node'
5
+ import { GerritApiServiceLive } from '@/api/gerrit'
3
6
  import { mineCommand } from '@/cli/commands/mine'
4
- import { GerritApiService, type ApiError } from '@/api/gerrit'
7
+ import { ConfigService } from '@/services/config'
5
8
  import { generateMockChange } from '@/test-utils/mock-generator'
6
9
  import type { ChangeInfo } from '@/schemas/gerrit'
10
+ import { createMockConfigService } from './helpers/config-mock'
7
11
 
8
- // Mock console.log to capture output
9
- const mockConsole = {
10
- logs: [] as string[],
11
- log: function (message: string) {
12
- this.logs.push(message)
13
- },
14
- clear: function () {
15
- this.logs = []
16
- },
17
- }
12
+ // Create MSW server
13
+ const server = setupServer(
14
+ // Default handler for auth check
15
+ http.get('*/a/accounts/self', ({ request }) => {
16
+ const auth = request.headers.get('Authorization')
17
+ if (!auth || !auth.startsWith('Basic ')) {
18
+ return HttpResponse.text('Unauthorized', { status: 401 })
19
+ }
20
+ return HttpResponse.json({
21
+ _account_id: 1000,
22
+ name: 'Test User',
23
+ email: 'test@example.com',
24
+ })
25
+ }),
26
+ )
18
27
 
19
28
  describe('mine command', () => {
29
+ let mockConsoleLog: ReturnType<typeof mock>
30
+
31
+ beforeAll(() => {
32
+ server.listen({ onUnhandledRequest: 'bypass' })
33
+ })
34
+
35
+ afterAll(() => {
36
+ server.close()
37
+ })
38
+
20
39
  beforeEach(() => {
21
- mockConsole.clear()
22
- // Replace console.log for tests
23
- global.console.log = mockConsole.log.bind(mockConsole)
40
+ mockConsoleLog = mock(() => {})
41
+ console.log = mockConsoleLog
42
+ })
43
+
44
+ afterEach(() => {
45
+ server.resetHandlers()
24
46
  })
25
47
 
26
48
  test('should fetch and display my changes in pretty format', async () => {
@@ -41,32 +63,26 @@ describe('mine command', () => {
41
63
  }),
42
64
  ]
43
65
 
44
- const mockApi = GerritApiService.of({
45
- listChanges: (query?: string) => {
46
- expect(query).toBe('owner:self status:open')
47
- return Effect.succeed(mockChanges)
48
- },
49
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
50
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
51
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
52
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
53
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
54
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
55
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
56
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
57
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
58
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
59
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
60
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
61
- })
66
+ server.use(
67
+ http.get('*/a/changes/', ({ request }) => {
68
+ const url = new URL(request.url)
69
+ expect(url.searchParams.get('q')).toBe('owner:self status:open')
70
+ return HttpResponse.text(`)]}'\n${JSON.stringify(mockChanges)}`)
71
+ }),
72
+ )
62
73
 
74
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
63
75
  await Effect.runPromise(
64
- mineCommand({ xml: false }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
76
+ mineCommand({ xml: false }).pipe(
77
+ Effect.provide(GerritApiServiceLive),
78
+ Effect.provide(mockConfigLayer),
79
+ ),
65
80
  )
66
81
 
67
- expect(mockConsole.logs.length).toBeGreaterThan(0)
68
- expect(mockConsole.logs.some((log) => log.includes('My test change'))).toBe(true)
69
- expect(mockConsole.logs.some((log) => log.includes('Another change'))).toBe(true)
82
+ const output = mockConsoleLog.mock.calls.map((call) => call[0]).join('\n')
83
+ expect(output.length).toBeGreaterThan(0)
84
+ expect(output).toContain('My test change')
85
+ expect(output).toContain('Another change')
70
86
  })
71
87
 
72
88
  test('should output XML format when --xml flag is used', async () => {
@@ -80,30 +96,23 @@ describe('mine command', () => {
80
96
  }),
81
97
  ]
82
98
 
83
- const mockApi = GerritApiService.of({
84
- listChanges: (query?: string) => {
85
- expect(query).toBe('owner:self status:open')
86
- return Effect.succeed(mockChanges)
87
- },
88
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
89
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
90
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
91
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
92
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
93
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
94
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
95
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
96
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
97
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
98
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
99
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
100
- })
99
+ server.use(
100
+ http.get('*/a/changes/', ({ request }) => {
101
+ const url = new URL(request.url)
102
+ expect(url.searchParams.get('q')).toBe('owner:self status:open')
103
+ return HttpResponse.text(`)]}'\n${JSON.stringify(mockChanges)}`)
104
+ }),
105
+ )
101
106
 
107
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
102
108
  await Effect.runPromise(
103
- mineCommand({ xml: true }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
109
+ mineCommand({ xml: true }).pipe(
110
+ Effect.provide(GerritApiServiceLive),
111
+ Effect.provide(mockConfigLayer),
112
+ ),
104
113
  )
105
114
 
106
- const output = mockConsole.logs.join('\n')
115
+ const output = mockConsoleLog.mock.calls.map((call) => call[0]).join('\n')
107
116
  expect(output).toContain('<?xml version="1.0" encoding="UTF-8"?>')
108
117
  expect(output).toContain('<changes count="1">')
109
118
  expect(output).toContain('<change>')
@@ -117,113 +126,83 @@ describe('mine command', () => {
117
126
  })
118
127
 
119
128
  test('should handle no changes gracefully', async () => {
120
- const mockApi = GerritApiService.of({
121
- listChanges: () => Effect.succeed([]),
122
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
123
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
124
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
125
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
126
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
127
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
128
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
129
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
130
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
131
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
132
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
133
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
134
- })
129
+ server.use(
130
+ http.get('*/a/changes/', () => {
131
+ return HttpResponse.text(")]}'\n[]")
132
+ }),
133
+ )
135
134
 
135
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
136
136
  await Effect.runPromise(
137
- mineCommand({ xml: false }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
137
+ mineCommand({ xml: false }).pipe(
138
+ Effect.provide(GerritApiServiceLive),
139
+ Effect.provide(mockConfigLayer),
140
+ ),
138
141
  )
139
142
 
140
143
  // Mine command returns early for empty results, so no output is expected
141
- expect(mockConsole.logs).toEqual([])
144
+ expect(mockConsoleLog.mock.calls).toEqual([])
142
145
  })
143
146
 
144
147
  test('should handle no changes gracefully in XML format', async () => {
145
- const mockApi = GerritApiService.of({
146
- listChanges: () => Effect.succeed([]),
147
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
148
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
149
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
150
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
151
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
152
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
153
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
154
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
155
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
156
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
157
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
158
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
159
- })
148
+ server.use(
149
+ http.get('*/a/changes/', () => {
150
+ return HttpResponse.text(")]}'\n[]")
151
+ }),
152
+ )
160
153
 
154
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
161
155
  await Effect.runPromise(
162
- mineCommand({ xml: true }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
156
+ mineCommand({ xml: true }).pipe(
157
+ Effect.provide(GerritApiServiceLive),
158
+ Effect.provide(mockConfigLayer),
159
+ ),
163
160
  )
164
161
 
165
- const output = mockConsole.logs.join('\n')
162
+ const output = mockConsoleLog.mock.calls.map((call) => call[0]).join('\n')
166
163
  expect(output).toContain('<?xml version="1.0" encoding="UTF-8"?>')
167
164
  expect(output).toContain('<changes count="0">')
168
165
  expect(output).toContain('</changes>')
169
166
  })
170
167
 
171
168
  test('should handle network failures gracefully', async () => {
172
- const mockApi = GerritApiService.of({
173
- listChanges: () => Effect.fail(new Error('Network error') as ApiError),
174
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
175
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
176
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
177
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
178
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
179
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
180
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
181
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
182
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
183
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
184
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
185
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
186
- })
169
+ server.use(
170
+ http.get('*/a/changes/', () => {
171
+ return HttpResponse.text('Network error', { status: 500 })
172
+ }),
173
+ )
187
174
 
175
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
188
176
  const result = await Effect.runPromise(
189
177
  Effect.either(
190
- mineCommand({ xml: false }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
178
+ mineCommand({ xml: false }).pipe(
179
+ Effect.provide(GerritApiServiceLive),
180
+ Effect.provide(mockConfigLayer),
181
+ ),
191
182
  ),
192
183
  )
193
184
 
194
185
  expect(result._tag).toBe('Left')
195
- if (result._tag === 'Left') {
196
- expect(result.left.message).toBe('Network error')
197
- }
198
186
  })
199
187
 
200
188
  test('should handle network failures gracefully in XML format', async () => {
201
- const mockApi = GerritApiService.of({
202
- listChanges: () => Effect.fail(new Error('API error') as ApiError),
203
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
204
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
205
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
206
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
207
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
208
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
209
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
210
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
211
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
212
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
213
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
214
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
215
- })
189
+ server.use(
190
+ http.get('*/a/changes/', () => {
191
+ return HttpResponse.text('API error', { status: 500 })
192
+ }),
193
+ )
216
194
 
195
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
217
196
  const result = await Effect.runPromise(
218
197
  Effect.either(
219
- mineCommand({ xml: true }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
198
+ mineCommand({ xml: true }).pipe(
199
+ Effect.provide(GerritApiServiceLive),
200
+ Effect.provide(mockConfigLayer),
201
+ ),
220
202
  ),
221
203
  )
222
204
 
223
205
  expect(result._tag).toBe('Left')
224
- if (result._tag === 'Left') {
225
- expect(result.left.message).toBe('API error')
226
- }
227
206
  })
228
207
 
229
208
  test('should properly escape XML special characters', async () => {
@@ -237,27 +216,21 @@ describe('mine command', () => {
237
216
  }),
238
217
  ]
239
218
 
240
- const mockApi = GerritApiService.of({
241
- listChanges: () => Effect.succeed(mockChanges),
242
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
243
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
244
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
245
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
246
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
247
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
248
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
249
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
250
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
251
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
252
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
253
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
254
- })
219
+ server.use(
220
+ http.get('*/a/changes/', () => {
221
+ return HttpResponse.text(`)]}'\n${JSON.stringify(mockChanges)}`)
222
+ }),
223
+ )
255
224
 
225
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
256
226
  await Effect.runPromise(
257
- mineCommand({ xml: true }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
227
+ mineCommand({ xml: true }).pipe(
228
+ Effect.provide(GerritApiServiceLive),
229
+ Effect.provide(mockConfigLayer),
230
+ ),
258
231
  )
259
232
 
260
- const output = mockConsole.logs.join('\n')
233
+ const output = mockConsoleLog.mock.calls.map((call) => call[0]).join('\n')
261
234
  // CDATA sections should preserve special characters
262
235
  expect(output).toContain('<![CDATA[Test with <special> & "characters"]]>')
263
236
  expect(output).toContain('<branch>feature/test&update</branch>')
@@ -288,27 +261,21 @@ describe('mine command', () => {
288
261
  }),
289
262
  ]
290
263
 
291
- const mockApi = GerritApiService.of({
292
- listChanges: () => Effect.succeed(mockChanges),
293
- getChange: () => Effect.fail(new Error('Not implemented') as ApiError),
294
- postReview: () => Effect.fail(new Error('Not implemented') as ApiError),
295
- abandonChange: () => Effect.fail(new Error('Not implemented') as ApiError),
296
- testConnection: Effect.fail(new Error('Not implemented') as ApiError),
297
- getRevision: () => Effect.fail(new Error('Not implemented') as ApiError),
298
- getFiles: () => Effect.fail(new Error('Not implemented') as ApiError),
299
- getFileDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
300
- getFileContent: () => Effect.fail(new Error('Not implemented') as ApiError),
301
- getPatch: () => Effect.fail(new Error('Not implemented') as ApiError),
302
- getDiff: () => Effect.fail(new Error('Not implemented') as ApiError),
303
- getComments: () => Effect.fail(new Error('Not implemented') as ApiError),
304
- getMessages: () => Effect.fail(new Error('Not implemented') as ApiError),
305
- })
264
+ server.use(
265
+ http.get('*/a/changes/', () => {
266
+ return HttpResponse.text(`)]}'\n${JSON.stringify(mockChanges)}`)
267
+ }),
268
+ )
306
269
 
270
+ const mockConfigLayer = Layer.succeed(ConfigService, createMockConfigService())
307
271
  await Effect.runPromise(
308
- mineCommand({ xml: false }).pipe(Effect.provide(Layer.succeed(GerritApiService, mockApi))),
272
+ mineCommand({ xml: false }).pipe(
273
+ Effect.provide(GerritApiServiceLive),
274
+ Effect.provide(mockConfigLayer),
275
+ ),
309
276
  )
310
277
 
311
- const output = mockConsole.logs.join('\n')
278
+ const output = mockConsoleLog.mock.calls.map((call) => call[0]).join('\n')
312
279
  expect(output).toContain('Change in project A')
313
280
  expect(output).toContain('Change in project B')
314
281
  expect(output).toContain('Another change in project A')
@@ -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
- })