Branch PR status now resolves open PRs only, revalidates closed/merged associations on a discovery cadence, and clears authoritative empty results so the panel can self-heal without a manual refresh. Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
90 lines
2.5 KiB
JavaScript
90 lines
2.5 KiB
JavaScript
import { beforeEach, describe, expect, mock, test } from 'bun:test';
|
|
|
|
const listMock = mock(async () => ({ data: [] }));
|
|
|
|
mock.module('../git/index.js', () => ({
|
|
getRemotes: async () => [],
|
|
getStatus: async () => null,
|
|
}));
|
|
|
|
mock.module('./repo/index.js', () => ({
|
|
resolveGitHubRepoFromDirectory: async () => null,
|
|
}));
|
|
|
|
mock.module('./rate-limit.js', () => ({
|
|
noteIfGitHubRateLimit: () => {},
|
|
}));
|
|
|
|
const { findFirstMatchingPr, invalidateRepoPullsCache } = await import('./pr-status.js');
|
|
|
|
const openPr = {
|
|
number: 15,
|
|
state: 'open',
|
|
head: {
|
|
ref: 'feature',
|
|
label: 'acme:feature',
|
|
user: { login: 'acme' },
|
|
repo: { owner: { login: 'acme' }, name: 'app' },
|
|
},
|
|
};
|
|
|
|
const closedPr = {
|
|
number: 12,
|
|
state: 'closed',
|
|
merged_at: '2026-01-01T00:00:00Z',
|
|
head: {
|
|
ref: 'feature',
|
|
label: 'acme:feature',
|
|
user: { login: 'acme' },
|
|
repo: { owner: { login: 'acme' }, name: 'app' },
|
|
},
|
|
};
|
|
|
|
describe('findFirstMatchingPr open-only branch status', () => {
|
|
beforeEach(() => {
|
|
listMock.mockReset();
|
|
invalidateRepoPullsCache('acme', 'app');
|
|
});
|
|
|
|
test('returns a matching open PR', async () => {
|
|
listMock.mockImplementation(async ({ state }) => {
|
|
if (state === 'open') {
|
|
return { data: [openPr] };
|
|
}
|
|
return { data: [closedPr] };
|
|
});
|
|
|
|
const pr = await findFirstMatchingPr({
|
|
octokit: { rest: { pulls: { list: listMock } } },
|
|
target: { repo: { owner: 'acme', repo: 'app' }, remoteName: 'origin' },
|
|
branch: 'feature',
|
|
sourceCandidates: [{ repo: { owner: 'acme', repo: 'app' } }],
|
|
force: true,
|
|
});
|
|
|
|
expect(pr?.number).toBe(15);
|
|
expect(listMock.mock.calls.every((call) => call[0]?.state === 'open')).toBe(true);
|
|
});
|
|
|
|
test('returns null when only a closed/merged PR exists for the head branch', async () => {
|
|
listMock.mockImplementation(async ({ state }) => {
|
|
if (state === 'open') {
|
|
return { data: [] };
|
|
}
|
|
return { data: [closedPr] };
|
|
});
|
|
|
|
const pr = await findFirstMatchingPr({
|
|
octokit: { rest: { pulls: { list: listMock } } },
|
|
target: { repo: { owner: 'acme', repo: 'app' }, remoteName: 'origin' },
|
|
branch: 'feature',
|
|
sourceCandidates: [{ repo: { owner: 'acme', repo: 'app' } }],
|
|
force: true,
|
|
});
|
|
|
|
expect(pr).toBeNull();
|
|
expect(listMock.mock.calls.every((call) => call[0]?.state === 'open')).toBe(true);
|
|
expect(listMock.mock.calls.some((call) => call[0]?.state === 'closed')).toBe(false);
|
|
});
|
|
});
|