Skip to content

Commit d223688

Browse files
authored
Merge branch 'main' into chore/2300-create-ChunkedTransaction
Signed-off-by: MontyPokemon <59332150+MonaaEid@users.noreply.github.com>
2 parents 16e3540 + 5e063df commit d223688

50 files changed

Lines changed: 1846 additions & 1358 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/scripts/__tests__/test-bot-pr-add-reviewers-as-assignees.test.js renamed to .github/scripts/__tests__/jest/bot-pr-add-reviewers-as-assignees.test.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
// SPDX-License-Identifier: Apache-2.0
2-
3-
/**
4-
* @fileoverview
5-
* Unit tests for the bot-pr-add-reviewers-as-assignees.js script using Jest.
6-
*/
1+
// __tests__/jest/bot-pr-add-reviewers-as-assignees.test.js
2+
//
3+
// Run from .github/scripts:
4+
// npm run test:js -- bot-pr-add-reviewers-as-assignees.test.js
75

86
describe('Bot: Add Reviewers as Assignees', () => {
97
let handler;
108

119
beforeAll(() => {
12-
handler = require('../bot-pr-add-reviewers-as-assignees.js');
10+
handler = require('../../bot-pr-add-reviewers-as-assignees.js');
1311
});
1412

1513
beforeEach(() => {
Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
// __tests__/jest/labels.test.js
2+
//
3+
// Run from .github/scripts:
4+
// npm run test:js -- labels.test.js
5+
6+
const { createMockGithub } = require('./test-utils');
7+
const {
8+
determineLabel,
9+
ensureLabel,
10+
syncLabel,
11+
} = require('../../review-sync/helpers/labels');
12+
const {
13+
QUEUE_LABELS,
14+
COMMUNITY_REVIEW,
15+
} = require('../../review-sync/helpers/constants');
16+
17+
describe('determineLabel', () => {
18+
test('0 approvals → queue:junior-committer', () => {
19+
const result = determineLabel({
20+
maintainerApprovals: 0,
21+
coreApprovals: 0,
22+
softApprovals: 0,
23+
anyApproval: 0,
24+
});
25+
26+
expect(result.name).toBe('queue:junior-committer');
27+
});
28+
29+
test('1 soft approval → queue:committers', () => {
30+
const result = determineLabel({
31+
maintainerApprovals: 0,
32+
coreApprovals: 0,
33+
softApprovals: 1,
34+
anyApproval: 1,
35+
});
36+
37+
expect(result.name).toBe('queue:committers');
38+
});
39+
40+
test('1 write approval → queue:maintainers', () => {
41+
const result = determineLabel({
42+
maintainerApprovals: 0,
43+
coreApprovals: 1,
44+
softApprovals: 0,
45+
anyApproval: 1,
46+
});
47+
48+
expect(result.name).toBe('queue:maintainers');
49+
});
50+
51+
test('2 write + 0 maintainer → queue:maintainers', () => {
52+
const result = determineLabel({
53+
maintainerApprovals: 0,
54+
coreApprovals: 2,
55+
softApprovals: 0,
56+
anyApproval: 2,
57+
});
58+
59+
expect(result.name).toBe('queue:maintainers');
60+
});
61+
62+
test('1 maintainer alone → queue:committers', () => {
63+
const result = determineLabel({
64+
maintainerApprovals: 1,
65+
coreApprovals: 1,
66+
softApprovals: 0,
67+
anyApproval: 1,
68+
});
69+
70+
expect(result.name).toBe('queue:committers');
71+
});
72+
73+
test('1 maintainer + 1 write → status: ready-to-merge', () => {
74+
const result = determineLabel({
75+
maintainerApprovals: 1,
76+
coreApprovals: 2,
77+
softApprovals: 0,
78+
anyApproval: 2,
79+
});
80+
81+
expect(result.name).toBe('status: ready-to-merge');
82+
});
83+
84+
test('1 maintainer + 1 soft → queue:committers', () => {
85+
const result = determineLabel({
86+
maintainerApprovals: 1,
87+
coreApprovals: 1,
88+
softApprovals: 1,
89+
anyApproval: 2,
90+
});
91+
92+
expect(result.name).toBe('queue:committers');
93+
});
94+
95+
test('3 soft approvals → queue:committers', () => {
96+
const result = determineLabel({
97+
maintainerApprovals: 0,
98+
coreApprovals: 0,
99+
softApprovals: 3,
100+
anyApproval: 3,
101+
});
102+
103+
expect(result.name).toBe('queue:committers');
104+
});
105+
106+
test('fully approved but ciFailing=true → queue:junior-committer', () => {
107+
const result = determineLabel(
108+
{
109+
maintainerApprovals: 1,
110+
coreApprovals: 2,
111+
softApprovals: 0,
112+
anyApproval: 2,
113+
},
114+
true
115+
);
116+
117+
expect(result.name).toBe('queue:junior-committer');
118+
});
119+
});
120+
121+
describe('ensureLabel', () => {
122+
test('creates label when missing', async () => {
123+
const mock = createMockGithub({
124+
existingLabels: {},
125+
});
126+
127+
await ensureLabel(
128+
mock,
129+
'o',
130+
'r',
131+
QUEUE_LABELS.JUNIOR,
132+
false
133+
);
134+
135+
expect(mock.calls.labelsCreated).toHaveLength(1);
136+
expect(mock.calls.labelsCreated[0].name)
137+
.toBe('queue:junior-committer');
138+
});
139+
140+
test('skips when label exists', async () => {
141+
const mock = createMockGithub({
142+
existingLabels: {
143+
'queue:junior-committer': true,
144+
},
145+
});
146+
147+
await ensureLabel(
148+
mock,
149+
'o',
150+
'r',
151+
QUEUE_LABELS.JUNIOR,
152+
false
153+
);
154+
155+
expect(mock.calls.labelsCreated).toHaveLength(0);
156+
});
157+
158+
test('dry run does not create', async () => {
159+
const mock = createMockGithub({
160+
existingLabels: {},
161+
});
162+
163+
await ensureLabel(
164+
mock,
165+
'o',
166+
'r',
167+
QUEUE_LABELS.JUNIOR,
168+
true
169+
);
170+
171+
expect(mock.calls.labelsCreated).toHaveLength(0);
172+
});
173+
});
174+
175+
describe('syncLabel', () => {
176+
test('no approvals, no labels → adds junior-committer', async () => {
177+
const mock = createMockGithub({
178+
roles: {},
179+
reviews: [],
180+
});
181+
182+
const changed = await syncLabel(
183+
mock,
184+
'o',
185+
'r',
186+
{
187+
number: 1,
188+
labels: [],
189+
head: { sha: '123' },
190+
user: { type: 'User' },
191+
},
192+
false
193+
);
194+
195+
expect(changed).toBe(true);
196+
expect(mock.calls.labelsAdded[0])
197+
.toBe('queue:junior-committer');
198+
});
199+
200+
test('already correct, no stale → returns false', async () => {
201+
const mock = createMockGithub({
202+
roles: {},
203+
reviews: [],
204+
});
205+
206+
const changed = await syncLabel(
207+
mock,
208+
'o',
209+
'r',
210+
{
211+
number: 1,
212+
labels: [
213+
{ name: 'queue:junior-committer' },
214+
{ name: COMMUNITY_REVIEW.name },
215+
],
216+
head: { sha: '123' },
217+
user: { type: 'Bot' },
218+
},
219+
false
220+
);
221+
222+
expect(changed).toBe(false);
223+
expect(mock.calls.labelsAdded).toHaveLength(0);
224+
});
225+
226+
test('stale label → adds correct, removes stale', async () => {
227+
const mock = createMockGithub({
228+
roles: {
229+
sophie: {
230+
role_name: 'maintain',
231+
permission: 'write',
232+
},
233+
bob: {
234+
role_name: 'write',
235+
permission: 'write',
236+
},
237+
},
238+
reviews: [
239+
{
240+
user: { login: 'sophie' },
241+
state: 'APPROVED',
242+
submitted_at: '2026-01-01T00:00:00Z',
243+
},
244+
{
245+
user: { login: 'bob' },
246+
state: 'APPROVED',
247+
submitted_at: '2026-01-02T00:00:00Z',
248+
},
249+
],
250+
});
251+
252+
const changed = await syncLabel(
253+
mock,
254+
'o',
255+
'r',
256+
{
257+
number: 1,
258+
labels: [{ name: 'queue:junior-committer' }],
259+
head: { sha: '123' },
260+
user: { type: 'User' },
261+
},
262+
false
263+
);
264+
265+
expect(changed).toBe(true);
266+
expect(mock.calls.labelsAdded)
267+
.toContain('status: ready-to-merge');
268+
expect(mock.calls.labelsRemoved)
269+
.toContain('queue:junior-committer');
270+
});
271+
272+
test('dry run logs but does not modify', async () => {
273+
const mock = createMockGithub({
274+
roles: {},
275+
reviews: [],
276+
});
277+
278+
const changed = await syncLabel(
279+
mock,
280+
'o',
281+
'r',
282+
{
283+
number: 1,
284+
labels: [{ name: 'queue:committers' }],
285+
head: { sha: '123' },
286+
user: { type: 'User' },
287+
},
288+
true
289+
);
290+
291+
expect(changed).toBe(true);
292+
expect(mock.calls.labelsAdded).toHaveLength(0);
293+
});
294+
295+
test('correct + stale present → cleans up stale', async () => {
296+
const mock = createMockGithub({
297+
roles: {},
298+
reviews: [],
299+
});
300+
301+
const changed = await syncLabel(
302+
mock,
303+
'o',
304+
'r',
305+
{
306+
number: 1,
307+
labels: [
308+
{ name: 'queue:junior-committer' },
309+
{ name: 'queue:committers' },
310+
],
311+
head: { sha: '123' },
312+
user: { type: 'User' },
313+
},
314+
false
315+
);
316+
317+
expect(changed).toBe(true);
318+
expect(mock.calls.labelsRemoved)
319+
.toContain('queue:committers');
320+
});
321+
322+
test('bot PR receives community review label if missing', async () => {
323+
const mock = createMockGithub({
324+
roles: {},
325+
reviews: [],
326+
});
327+
328+
const changed = await syncLabel(
329+
mock,
330+
'o',
331+
'r',
332+
{
333+
number: 1,
334+
labels: [{ name: 'queue:junior-committer' }],
335+
head: { sha: '123' },
336+
user: { type: 'Bot' },
337+
},
338+
false
339+
);
340+
341+
expect(changed).toBe(true);
342+
expect(mock.calls.labelsAdded)
343+
.toContain(COMMUNITY_REVIEW.name);
344+
});
345+
346+
test('human PR receives community review label if missing', async () => {
347+
const mock = createMockGithub({
348+
roles: {},
349+
reviews: [],
350+
});
351+
352+
const changed = await syncLabel(
353+
mock,
354+
'o',
355+
'r',
356+
{
357+
number: 1,
358+
labels: [{ name: 'queue:junior-committer' }],
359+
head: { sha: '123' },
360+
user: { type: 'User' },
361+
},
362+
false
363+
);
364+
365+
expect(changed).toBe(true);
366+
expect(mock.calls.labelsAdded)
367+
.toContain(COMMUNITY_REVIEW.name);
368+
});
369+
});

0 commit comments

Comments
 (0)