@atlassian-dc-mcp/bitbucket 0.29.0 → 0.31.0

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +56 -2
  3. package/build/__tests__/bitbucket-service.test.js +60 -2
  4. package/build/__tests__/bitbucket-service.test.js.map +1 -1
  5. package/build/__tests__/bitbucket-token-optimization.test.js +11 -0
  6. package/build/__tests__/bitbucket-token-optimization.test.js.map +1 -1
  7. package/build/__tests__/merge-gateway.test.d.ts +2 -0
  8. package/build/__tests__/merge-gateway.test.d.ts.map +1 -0
  9. package/build/__tests__/merge-gateway.test.js +98 -0
  10. package/build/__tests__/merge-gateway.test.js.map +1 -0
  11. package/build/__tests__/pr-comment-mapper.test.js +91 -11
  12. package/build/__tests__/pr-comment-mapper.test.js.map +1 -1
  13. package/build/__tests__/pr-merge.test.d.ts +2 -0
  14. package/build/__tests__/pr-merge.test.d.ts.map +1 -0
  15. package/build/__tests__/pr-merge.test.js +166 -0
  16. package/build/__tests__/pr-merge.test.js.map +1 -0
  17. package/build/bitbucket-response-mapper.d.ts +10 -0
  18. package/build/bitbucket-response-mapper.d.ts.map +1 -1
  19. package/build/bitbucket-response-mapper.js +16 -0
  20. package/build/bitbucket-response-mapper.js.map +1 -1
  21. package/build/bitbucket-service.d.ts +68 -9
  22. package/build/bitbucket-service.d.ts.map +1 -1
  23. package/build/bitbucket-service.js +91 -15
  24. package/build/bitbucket-service.js.map +1 -1
  25. package/build/index.js +34 -4
  26. package/build/index.js.map +1 -1
  27. package/build/merge-gateway.d.ts +34 -0
  28. package/build/merge-gateway.d.ts.map +1 -0
  29. package/build/merge-gateway.js +86 -0
  30. package/build/merge-gateway.js.map +1 -0
  31. package/build/pr-comment-mapper.d.ts +3 -0
  32. package/build/pr-comment-mapper.d.ts.map +1 -1
  33. package/build/pr-comment-mapper.js +8 -3
  34. package/build/pr-comment-mapper.js.map +1 -1
  35. package/build/pr-merge.d.ts +23 -0
  36. package/build/pr-merge.d.ts.map +1 -0
  37. package/build/pr-merge.js +59 -0
  38. package/build/pr-merge.js.map +1 -0
  39. package/package.json +3 -3
  40. package/src/__tests__/bitbucket-service.test.ts +154 -2
  41. package/src/__tests__/bitbucket-token-optimization.test.ts +11 -0
  42. package/src/__tests__/merge-gateway.test.ts +119 -0
  43. package/src/__tests__/pr-comment-mapper.test.ts +95 -11
  44. package/src/__tests__/pr-merge.test.ts +206 -0
  45. package/src/bitbucket-response-mapper.ts +27 -0
  46. package/src/bitbucket-service.ts +100 -14
  47. package/src/index.ts +55 -6
  48. package/src/merge-gateway.ts +132 -0
  49. package/src/pr-comment-mapper.ts +11 -3
  50. package/src/pr-merge.ts +94 -0
  51. package/tsconfig.tsbuildinfo +1 -1
@@ -3,7 +3,7 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { initializeRuntimeConfig } from '@atlassian-dc-mcp/common';
5
5
  import { BitbucketService } from '../bitbucket-service.js';
6
- import { PullRequestsService } from '../bitbucket-client/index.js';
6
+ import { PullRequestsService, RepositoryService } from '../bitbucket-client/index.js';
7
7
  import { request as mockRequest } from '../bitbucket-client/core/request.js';
8
8
 
9
9
  // Mock the request function
@@ -25,6 +25,9 @@ jest.mock('../bitbucket-client/index.js', () => ({
25
25
  getReviewers: jest.fn(),
26
26
  get3: jest.fn()
27
27
  },
28
+ RepositoryService: {
29
+ streamRaw: jest.fn()
30
+ },
28
31
  OpenAPI: {
29
32
  BASE: '',
30
33
  TOKEN: '',
@@ -1209,6 +1212,78 @@ describe('BitbucketService', () => {
1209
1212
  });
1210
1213
  });
1211
1214
 
1215
+ describe('getFileContent', () => {
1216
+ const mockFileContent = 'FROM node:20-alpine\n\nWORKDIR /app\n';
1217
+
1218
+ it('should fetch a file at the repository default branch when at is omitted', async () => {
1219
+ (RepositoryService.streamRaw as jest.Mock).mockResolvedValue(mockFileContent);
1220
+
1221
+ const result = await bitbucketService.getFileContent(mockProjectKey, mockRepositorySlug, 'Dockerfile');
1222
+
1223
+ expect(result.success).toBe(true);
1224
+ expect(result.data).toBe(mockFileContent);
1225
+ expect(RepositoryService.streamRaw).toHaveBeenCalledWith(
1226
+ 'Dockerfile',
1227
+ mockProjectKey,
1228
+ mockRepositorySlug,
1229
+ undefined
1230
+ );
1231
+ });
1232
+
1233
+ it('should pass the ref through and keep nested paths intact', async () => {
1234
+ (RepositoryService.streamRaw as jest.Mock).mockResolvedValue(mockFileContent);
1235
+
1236
+ await bitbucketService.getFileContent(
1237
+ mockProjectKey,
1238
+ mockRepositorySlug,
1239
+ 'deploy/base/configmap.yaml',
1240
+ 'refs/heads/main'
1241
+ );
1242
+
1243
+ expect(RepositoryService.streamRaw).toHaveBeenCalledWith(
1244
+ 'deploy/base/configmap.yaml',
1245
+ mockProjectKey,
1246
+ mockRepositorySlug,
1247
+ 'refs/heads/main'
1248
+ );
1249
+ });
1250
+
1251
+ it('should strip a leading slash from the path', async () => {
1252
+ (RepositoryService.streamRaw as jest.Mock).mockResolvedValue(mockFileContent);
1253
+
1254
+ await bitbucketService.getFileContent(mockProjectKey, mockRepositorySlug, '/src/index.ts');
1255
+
1256
+ expect(RepositoryService.streamRaw).toHaveBeenCalledWith(
1257
+ 'src/index.ts',
1258
+ mockProjectKey,
1259
+ mockRepositorySlug,
1260
+ undefined
1261
+ );
1262
+ });
1263
+
1264
+ it('should normalize project key and repository slug casing', async () => {
1265
+ (RepositoryService.streamRaw as jest.Mock).mockResolvedValue(mockFileContent);
1266
+
1267
+ await bitbucketService.getFileContent('test', 'TEST-REPO', 'Dockerfile');
1268
+
1269
+ expect(RepositoryService.streamRaw).toHaveBeenCalledWith(
1270
+ 'Dockerfile',
1271
+ 'TEST',
1272
+ 'test-repo',
1273
+ undefined
1274
+ );
1275
+ });
1276
+
1277
+ it('should handle API errors gracefully', async () => {
1278
+ (RepositoryService.streamRaw as jest.Mock).mockRejectedValue(new Error('API Error'));
1279
+
1280
+ const result = await bitbucketService.getFileContent(mockProjectKey, mockRepositorySlug, 'missing.txt');
1281
+
1282
+ expect(result.success).toBe(false);
1283
+ expect(result.error).toBe('API Error');
1284
+ });
1285
+ });
1286
+
1212
1287
  describe('createPullRequest', () => {
1213
1288
  it('should successfully create a PR with minimal parameters', async () => {
1214
1289
  const mockPullRequest = {
@@ -2166,7 +2241,7 @@ describe('BitbucketService', () => {
2166
2241
  const mockComment = { id: 502, version: 4, text: 'New body', state: 'RESOLVED', severity: 'BLOCKER' };
2167
2242
  (PullRequestsService.updateComment2 as jest.Mock).mockResolvedValue(mockComment);
2168
2243
 
2169
- await bitbucketService.updatePullRequestComment(
2244
+ const result = await bitbucketService.updatePullRequestComment(
2170
2245
  mockProjectKey,
2171
2246
  mockRepositorySlug,
2172
2247
  mockPullRequestId,
@@ -2184,6 +2259,83 @@ describe('BitbucketService', () => {
2184
2259
  mockRepositorySlug,
2185
2260
  { version: 3, text: 'New body', state: 'RESOLVED', severity: 'BLOCKER' }
2186
2261
  );
2262
+ expect(result.data).toMatchObject({ state: 'RESOLVED', severity: 'BLOCKER' });
2263
+ });
2264
+
2265
+ it('should resolve a comment thread by sending threadResolved true', async () => {
2266
+ const mockComment = { id: 504, version: 3, state: 'OPEN', threadResolved: true };
2267
+ (PullRequestsService.updateComment2 as jest.Mock).mockResolvedValue(mockComment);
2268
+
2269
+ const result = await bitbucketService.updatePullRequestComment(
2270
+ mockProjectKey,
2271
+ mockRepositorySlug,
2272
+ mockPullRequestId,
2273
+ '504',
2274
+ 2,
2275
+ undefined, // text
2276
+ undefined, // state
2277
+ undefined, // severity
2278
+ true // threadResolved
2279
+ );
2280
+
2281
+ expect(PullRequestsService.updateComment2).toHaveBeenCalledWith(
2282
+ mockProjectKey,
2283
+ '504',
2284
+ mockPullRequestId,
2285
+ mockRepositorySlug,
2286
+ { version: 2, threadResolved: true }
2287
+ );
2288
+ expect(result.data).toMatchObject({ state: 'OPEN', threadResolved: true });
2289
+ });
2290
+
2291
+ it('should reopen a comment thread by sending threadResolved false', async () => {
2292
+ const mockComment = { id: 505, version: 4, threadResolved: false };
2293
+ (PullRequestsService.updateComment2 as jest.Mock).mockResolvedValue(mockComment);
2294
+
2295
+ await bitbucketService.updatePullRequestComment(
2296
+ mockProjectKey,
2297
+ mockRepositorySlug,
2298
+ mockPullRequestId,
2299
+ '505',
2300
+ 3,
2301
+ undefined,
2302
+ undefined,
2303
+ undefined,
2304
+ false
2305
+ );
2306
+
2307
+ expect(PullRequestsService.updateComment2).toHaveBeenCalledWith(
2308
+ mockProjectKey,
2309
+ '505',
2310
+ mockPullRequestId,
2311
+ mockRepositorySlug,
2312
+ { version: 3, threadResolved: false }
2313
+ );
2314
+ });
2315
+
2316
+ it('should set task state and thread resolution independently in one update', async () => {
2317
+ const mockComment = { id: 506, version: 5, state: 'OPEN', threadResolved: true };
2318
+ (PullRequestsService.updateComment2 as jest.Mock).mockResolvedValue(mockComment);
2319
+
2320
+ await bitbucketService.updatePullRequestComment(
2321
+ mockProjectKey,
2322
+ mockRepositorySlug,
2323
+ mockPullRequestId,
2324
+ '506',
2325
+ 4,
2326
+ undefined,
2327
+ 'OPEN',
2328
+ undefined,
2329
+ true
2330
+ );
2331
+
2332
+ expect(PullRequestsService.updateComment2).toHaveBeenCalledWith(
2333
+ mockProjectKey,
2334
+ '506',
2335
+ mockPullRequestId,
2336
+ mockRepositorySlug,
2337
+ { version: 4, state: 'OPEN', threadResolved: true }
2338
+ );
2187
2339
  });
2188
2340
 
2189
2341
  it('should propagate API errors', async () => {
@@ -143,6 +143,7 @@ describe('BitbucketService token optimization paths', () => {
143
143
  comments: [],
144
144
  threadResolved: false,
145
145
  state: 'OPEN',
146
+ severity: 'NORMAL',
146
147
  },
147
148
  },
148
149
  ],
@@ -151,6 +152,8 @@ describe('BitbucketService token optimization paths', () => {
151
152
  prAuthor: { name: 'author', displayName: 'Author' },
152
153
  commentCount: 1,
153
154
  unresolvedCount: 1,
155
+ blockerCount: 0,
156
+ unresolvedBlockerCount: 0,
154
157
  },
155
158
  });
156
159
  expect(PullRequestsService.getActivities).toHaveBeenCalledWith('TEST', '123', 'repo', undefined, undefined, undefined, 25);
@@ -202,6 +205,8 @@ describe('BitbucketService token optimization paths', () => {
202
205
  prAuthor: { name: 'author', displayName: 'Author' },
203
206
  commentCount: 0,
204
207
  unresolvedCount: 0,
208
+ blockerCount: 0,
209
+ unresolvedBlockerCount: 0,
205
210
  },
206
211
  });
207
212
  expect(includeResolvedResult.success).toBe(true);
@@ -238,10 +243,12 @@ describe('BitbucketService token optimization paths', () => {
238
243
  comments: [],
239
244
  threadResolved: true,
240
245
  state: 'OPEN',
246
+ severity: 'NORMAL',
241
247
  },
242
248
  ],
243
249
  threadResolved: true,
244
250
  state: 'OPEN',
251
+ severity: 'NORMAL',
245
252
  },
246
253
  },
247
254
  ],
@@ -250,6 +257,8 @@ describe('BitbucketService token optimization paths', () => {
250
257
  prAuthor: { name: 'author', displayName: 'Author' },
251
258
  commentCount: 1,
252
259
  unresolvedCount: 0,
260
+ blockerCount: 0,
261
+ unresolvedBlockerCount: 0,
253
262
  },
254
263
  });
255
264
  });
@@ -267,6 +276,8 @@ describe('BitbucketService token optimization paths', () => {
267
276
  prAuthor: { name: 'author', displayName: 'Author' },
268
277
  commentCount: 1,
269
278
  unresolvedCount: 1,
279
+ blockerCount: 0,
280
+ unresolvedBlockerCount: 0,
270
281
  },
271
282
  items: ['Reviewer on src/app.ts:10: Looks good'],
272
283
  });
@@ -0,0 +1,119 @@
1
+ import {
2
+ assertRepoMergeAllowed,
3
+ assertTargetRefMergeAllowed,
4
+ resolveMergeGateway,
5
+ } from '../merge-gateway.js';
6
+
7
+ const silentWarn = () => undefined;
8
+
9
+ describe('resolveMergeGateway', () => {
10
+ it('is disabled by default', () => {
11
+ const gateway = resolveMergeGateway({ env: {}, warn: silentWarn });
12
+ expect(gateway.enabled).toBe(false);
13
+ expect(gateway.repos).toEqual([]);
14
+ });
15
+
16
+ it('stays disabled when enabled without any repository', () => {
17
+ const gateway = resolveMergeGateway({ env: { BITBUCKET_MERGE_ENABLED: 'true' }, warn: silentWarn });
18
+ expect(gateway.enabled).toBe(false);
19
+ });
20
+
21
+ it('stays disabled when every configured repository entry is malformed', () => {
22
+ const gateway = resolveMergeGateway({
23
+ env: { BITBUCKET_MERGE_ENABLED: 'true', BITBUCKET_MERGE_ALLOWED_REPOS: 'demo, PROJ/a/b, */*' },
24
+ warn: silentWarn,
25
+ });
26
+ expect(gateway.enabled).toBe(false);
27
+ });
28
+
29
+ it('normalizes repository entries and de-duplicates them', () => {
30
+ const gateway = resolveMergeGateway({
31
+ env: {
32
+ BITBUCKET_MERGE_ENABLED: 'yes',
33
+ BITBUCKET_MERGE_ALLOWED_REPOS: 'proj/Demo, PROJ/demo; OTHER/*',
34
+ },
35
+ warn: silentWarn,
36
+ });
37
+ expect(gateway.enabled).toBe(true);
38
+ expect(gateway.repos).toEqual(['PROJ/demo', 'OTHER/*']);
39
+ expect(gateway.targetRefs).toEqual([]);
40
+ });
41
+
42
+ it('expands bare branch names into fully-qualified target refs', () => {
43
+ const gateway = resolveMergeGateway({
44
+ env: {
45
+ BITBUCKET_MERGE_ENABLED: '1',
46
+ BITBUCKET_MERGE_ALLOWED_REPOS: 'PROJ/demo',
47
+ BITBUCKET_MERGE_ALLOWED_TARGET_REFS: 'develop, refs/heads/release/*',
48
+ },
49
+ warn: silentWarn,
50
+ });
51
+ expect(gateway.targetRefs).toEqual(['refs/heads/develop', 'refs/heads/release/*']);
52
+ });
53
+
54
+ it('warns about ignored entries and about being enabled with no valid repository', () => {
55
+ const warnings: string[] = [];
56
+ resolveMergeGateway({
57
+ env: { BITBUCKET_MERGE_ENABLED: 'true', BITBUCKET_MERGE_ALLOWED_REPOS: 'demo' },
58
+ warn: message => warnings.push(message),
59
+ });
60
+ expect(warnings).toHaveLength(2);
61
+ expect(warnings[0]).toContain('"demo"');
62
+ expect(warnings[1]).toContain('stay disabled');
63
+ });
64
+ });
65
+
66
+ describe('assertRepoMergeAllowed', () => {
67
+ const gateway = resolveMergeGateway({
68
+ env: { BITBUCKET_MERGE_ENABLED: 'true', BITBUCKET_MERGE_ALLOWED_REPOS: 'PROJ/demo, OTHER/*' },
69
+ warn: silentWarn,
70
+ });
71
+
72
+ it('refuses everything when merging is disabled', () => {
73
+ expect(() => assertRepoMergeAllowed({ enabled: false, repos: [], targetRefs: [] }, 'PROJ', 'demo'))
74
+ .toThrow(/disabled on this server/);
75
+ });
76
+
77
+ it('allows an exact repository regardless of the casing used by the caller', () => {
78
+ expect(() => assertRepoMergeAllowed(gateway, 'proj', 'DEMO')).not.toThrow();
79
+ });
80
+
81
+ it('allows any repository in a wildcard project', () => {
82
+ expect(() => assertRepoMergeAllowed(gateway, 'OTHER', 'anything')).not.toThrow();
83
+ });
84
+
85
+ it('refuses a repository outside the allowed list', () => {
86
+ expect(() => assertRepoMergeAllowed(gateway, 'PROJ', 'other-repo')).toThrow(/not allowed in PROJ\/other-repo/);
87
+ });
88
+
89
+ it('does not treat a wildcard project as a prefix of another project', () => {
90
+ expect(() => assertRepoMergeAllowed(gateway, 'OTHERS', 'demo')).toThrow(/not allowed/);
91
+ });
92
+ });
93
+
94
+ describe('assertTargetRefMergeAllowed', () => {
95
+ const unrestricted = { enabled: true, repos: ['PROJ/demo'], targetRefs: [] };
96
+ const restricted = {
97
+ enabled: true,
98
+ repos: ['PROJ/demo'],
99
+ targetRefs: ['refs/heads/develop', 'refs/heads/release/*'],
100
+ };
101
+
102
+ it('allows any ref when no target-ref restriction is configured', () => {
103
+ expect(() => assertTargetRefMergeAllowed(unrestricted, 'refs/heads/master')).not.toThrow();
104
+ expect(() => assertTargetRefMergeAllowed(unrestricted, undefined)).not.toThrow();
105
+ });
106
+
107
+ it('allows an exact and a wildcard target ref', () => {
108
+ expect(() => assertTargetRefMergeAllowed(restricted, 'refs/heads/develop')).not.toThrow();
109
+ expect(() => assertTargetRefMergeAllowed(restricted, 'refs/heads/release/1.2')).not.toThrow();
110
+ });
111
+
112
+ it('refuses a target ref outside the allowed list', () => {
113
+ expect(() => assertTargetRefMergeAllowed(restricted, 'refs/heads/master')).toThrow(/refs\/heads\/master is not allowed/);
114
+ });
115
+
116
+ it('refuses when the target ref is unknown but restrictions apply', () => {
117
+ expect(() => assertTargetRefMergeAllowed(restricted, undefined)).toThrow(/Could not determine the target branch/);
118
+ });
119
+ });
@@ -140,7 +140,8 @@ describe('PR Comment Mapper', () => {
140
140
  },
141
141
  comments: [],
142
142
  threadResolved: false,
143
- state: "OPEN"
143
+ state: "OPEN",
144
+ severity: "NORMAL"
144
145
  }
145
146
  },
146
147
  {
@@ -160,13 +161,85 @@ describe('PR Comment Mapper', () => {
160
161
  displayName: "User B"
161
162
  },
162
163
  commentCount: 1,
163
- unresolvedCount: 1
164
+ unresolvedCount: 1,
165
+ blockerCount: 0,
166
+ unresolvedBlockerCount: 0
164
167
  }
165
168
  };
166
169
 
167
170
  expect(result).toEqual(expectedResult);
168
171
  });
169
172
 
173
+ it('should expose BLOCKER severity so tasks are distinguishable from normal comments', () => {
174
+ const blockerResponse: BitbucketPRApiResponse = {
175
+ ...validPRResponse,
176
+ values: [
177
+ {
178
+ id: 1001,
179
+ createdDate: 1600000000000,
180
+ user: createUser('reviewer1', 106, 'Reviewer One'),
181
+ action: 'COMMENTED',
182
+ commentAction: 'ADDED',
183
+ comment: createComment({
184
+ id: 2010,
185
+ text: 'Blocking: fix this',
186
+ severity: 'BLOCKER',
187
+ comments: [
188
+ createComment({
189
+ id: 2011,
190
+ text: 'Reply keeps its own severity',
191
+ anchor: undefined,
192
+ severity: 'NORMAL'
193
+ })
194
+ ]
195
+ })
196
+ }
197
+ ]
198
+ };
199
+
200
+ const result = simplifyBitbucketPRComments(blockerResponse) as SimplifiedPRResponse;
201
+ expect(result.activities[0].comment?.severity).toBe('BLOCKER');
202
+ expect(result.activities[0].comment?.comments[0].severity).toBe('NORMAL');
203
+ });
204
+
205
+ it('should count blockers and unresolved blockers by task state in the summary', () => {
206
+ const blockerResponse: BitbucketPRApiResponse = {
207
+ ...validPRResponse,
208
+ values: [
209
+ openedActivity!,
210
+ {
211
+ id: 1010,
212
+ createdDate: 1600000003000,
213
+ user: createUser('reviewer1', 106, 'Reviewer One'),
214
+ action: 'COMMENTED',
215
+ commentAction: 'ADDED',
216
+ comment: createComment({ id: 2020, text: 'Unresolved task', severity: 'BLOCKER', state: 'OPEN' })
217
+ },
218
+ {
219
+ id: 1011,
220
+ createdDate: 1600000004000,
221
+ user: createUser('reviewer1', 106, 'Reviewer One'),
222
+ action: 'COMMENTED',
223
+ commentAction: 'ADDED',
224
+ comment: createComment({ id: 2021, text: 'Ticked task', severity: 'BLOCKER', state: 'RESOLVED' })
225
+ },
226
+ {
227
+ id: 1012,
228
+ createdDate: 1600000005000,
229
+ user: createUser('reviewer1', 106, 'Reviewer One'),
230
+ action: 'COMMENTED',
231
+ commentAction: 'ADDED',
232
+ comment: createComment({ id: 2022, text: 'Just a note', severity: 'NORMAL', state: 'OPEN' })
233
+ }
234
+ ]
235
+ };
236
+
237
+ const result = simplifyBitbucketPRComments(blockerResponse) as SimplifiedPRResponse;
238
+ expect(result.summary.commentCount).toBe(3);
239
+ expect(result.summary.blockerCount).toBe(2);
240
+ expect(result.summary.unresolvedBlockerCount).toBe(1);
241
+ });
242
+
170
243
  it('should preserve nested replies recursively', () => {
171
244
  const threadedResponse: BitbucketPRApiResponse = {
172
245
  ...validPRResponse,
@@ -220,11 +293,13 @@ describe('PR Comment Mapper', () => {
220
293
  createdDate: 1600000000000,
221
294
  comments: [],
222
295
  threadResolved: false,
223
- state: "OPEN"
296
+ state: "OPEN",
297
+ severity: "NORMAL"
224
298
  }
225
299
  ],
226
300
  threadResolved: false,
227
- state: "OPEN"
301
+ state: "OPEN",
302
+ severity: "NORMAL"
228
303
  }
229
304
  ]);
230
305
  });
@@ -294,7 +369,8 @@ describe('PR Comment Mapper', () => {
294
369
  },
295
370
  comments: [],
296
371
  threadResolved: false,
297
- state: 'OPEN'
372
+ state: 'OPEN',
373
+ severity: 'NORMAL'
298
374
  }
299
375
  }
300
376
  ]);
@@ -355,11 +431,13 @@ describe('PR Comment Mapper', () => {
355
431
  createdDate: 1600000000000,
356
432
  comments: [],
357
433
  threadResolved: true,
358
- state: 'OPEN'
434
+ state: 'OPEN',
435
+ severity: 'NORMAL'
359
436
  }
360
437
  ],
361
438
  threadResolved: true,
362
- state: 'OPEN'
439
+ state: 'OPEN',
440
+ severity: 'NORMAL'
363
441
  });
364
442
  expect(getCommentSummary(resolvedThreadResponse, { includeResolved: true })).toEqual([
365
443
  'User A on config.yml:6: Resolved thread root'
@@ -402,7 +480,8 @@ describe('PR Comment Mapper', () => {
402
480
  createdDate: 1600000000000,
403
481
  comments: [],
404
482
  threadResolved: false,
405
- state: "OPEN"
483
+ state: "OPEN",
484
+ severity: "NORMAL"
406
485
  }
407
486
  ]);
408
487
  });
@@ -447,7 +526,8 @@ describe('PR Comment Mapper', () => {
447
526
  createdDate: 1600000000000,
448
527
  comments: [],
449
528
  threadResolved: false,
450
- state: "OPEN"
529
+ state: "OPEN",
530
+ severity: "NORMAL"
451
531
  }
452
532
  ]);
453
533
 
@@ -465,7 +545,9 @@ describe('PR Comment Mapper', () => {
465
545
  summary: {
466
546
  totalActivities: 0,
467
547
  commentCount: 0,
468
- unresolvedCount: 0
548
+ unresolvedCount: 0,
549
+ blockerCount: 0,
550
+ unresolvedBlockerCount: 0
469
551
  }
470
552
  };
471
553
 
@@ -489,7 +571,9 @@ describe('PR Comment Mapper', () => {
489
571
  summary: {
490
572
  totalActivities: 0,
491
573
  commentCount: 0,
492
- unresolvedCount: 0
574
+ unresolvedCount: 0,
575
+ blockerCount: 0,
576
+ unresolvedBlockerCount: 0
493
577
  }
494
578
  };
495
579