From 77789a8417fd98acefe30ab451ab02dc292db64b Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Mon, 20 Jul 2026 17:42:57 -0700 Subject: [PATCH] fix(ci): split Enterprise host work-item tests under max-lines Move GHES/SSH host-routing cases out of work-item-details.test.ts so the suite stays within the 800-line test max-lines budget. --- .../work-item-details-enterprise-host.test.ts | 297 ++++++++++++++++++ src/main/github/work-item-details.test.ts | 205 ------------ 2 files changed, 297 insertions(+), 205 deletions(-) create mode 100644 src/main/github/work-item-details-enterprise-host.test.ts diff --git a/src/main/github/work-item-details-enterprise-host.test.ts b/src/main/github/work-item-details-enterprise-host.test.ts new file mode 100644 index 00000000000..2f29217b9ec --- /dev/null +++ b/src/main/github/work-item-details-enterprise-host.test.ts @@ -0,0 +1,297 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' + +type RateLimitGuardResult = + | { blocked: false } + | { blocked: true; remaining: number; limit: number; resetAt: number } + +const { + ghExecFileAsyncMock, + getOwnerRepoMock, + getEnterpriseGitHubRepoSlugMock, + getWorkItemMock, + getWorkItemByOwnerRepoMock, + getPRChecksMock, + getPRCommentsMock, + repositoryRateLimitGuardMock, + noteRepositoryRateLimitSpendMock +} = vi.hoisted(() => ({ + ghExecFileAsyncMock: vi.fn(), + getOwnerRepoMock: vi.fn(), + getEnterpriseGitHubRepoSlugMock: vi.fn(), + getWorkItemMock: vi.fn(), + getWorkItemByOwnerRepoMock: vi.fn(), + getPRChecksMock: vi.fn(), + getPRCommentsMock: vi.fn(), + repositoryRateLimitGuardMock: vi.fn< + ( + repository: { host?: string } | null | undefined, + bucket: 'core' | 'graphql' | 'search', + options?: { cwd?: string; host?: string; wslDistro?: string } + ) => RateLimitGuardResult + >(() => ({ blocked: false })), + noteRepositoryRateLimitSpendMock: vi.fn() +})) + +vi.mock('./gh-utils', () => ({ + ghExecFileAsync: ghExecFileAsyncMock, + getOwnerRepo: getOwnerRepoMock, + getOwnerRepoForRemote: vi.fn(), + ghRepoExecOptions: vi.fn((context: { connectionId?: string | null; repoPath: string }) => + context.connectionId ? {} : { cwd: context.repoPath } + ), + githubRepoContext: vi.fn((repoPath: string, connectionId?: string | null) => ({ + repoPath, + connectionId: connectionId ?? null + })), + acquire: vi.fn().mockResolvedValue(undefined), + release: vi.fn() +})) + +vi.mock('./client', () => ({ + getWorkItem: getWorkItemMock, + getWorkItemByOwnerRepo: getWorkItemByOwnerRepoMock, + getPRChecks: getPRChecksMock, + getPRComments: getPRCommentsMock +})) + +vi.mock('./github-enterprise-repository', () => ({ + getEnterpriseGitHubRepoSlug: getEnterpriseGitHubRepoSlugMock, + getEnterpriseGitHubRepoSlugForRemote: vi.fn().mockResolvedValue(null), + isGitHubHostAuthenticated: vi.fn().mockResolvedValue(true) +})) + +vi.mock('./rate-limit', () => ({ + repositoryRateLimitGuard: repositoryRateLimitGuardMock, + noteRepositoryRateLimitSpend: noteRepositoryRateLimitSpendMock +})) + +import { getWorkItemDetails } from './work-item-details' + +import { _resetOriginGitHubApiRepositoryCache } from './github-api-repository' + +// The origin-repository cache is module-level state; reset it so slugs +// resolved by one test cannot leak into the next. +beforeEach(() => { + _resetOriginGitHubApiRepositoryCache() +}) + +describe('getWorkItemDetails Enterprise host routing', () => { + beforeEach(() => { + ghExecFileAsyncMock.mockReset() + getOwnerRepoMock.mockReset() + getEnterpriseGitHubRepoSlugMock.mockReset() + getEnterpriseGitHubRepoSlugMock.mockResolvedValue(null) + getWorkItemMock.mockReset() + getWorkItemByOwnerRepoMock.mockReset() + getPRChecksMock.mockReset() + getPRCommentsMock.mockReset() + repositoryRateLimitGuardMock.mockReset() + repositoryRateLimitGuardMock.mockReturnValue({ blocked: false }) + noteRepositoryRateLimitSpendMock.mockReset() + }) + + it('uses the GitHub Enterprise host for SSH-backed issue work item details', async () => { + const enterpriseRepository = { + owner: 'team', + repo: 'orca', + host: 'github.acme-corp.com' + } + getWorkItemMock.mockResolvedValueOnce({ + id: 'issue:7', + type: 'issue', + number: 7, + title: 'Enterprise issue', + state: 'open', + url: 'https://github.acme-corp.com/team/orca/issues/7', + labels: [], + updatedAt: '2026-07-16T00:00:00Z', + author: 'issue-author' + }) + getOwnerRepoMock.mockResolvedValue(null) + getEnterpriseGitHubRepoSlugMock.mockResolvedValue(enterpriseRepository) + ghExecFileAsyncMock.mockImplementation(async (args: string[]) => { + const query = args.find((arg) => arg.startsWith('query=')) ?? '' + if (query.includes('comments(first: 100)')) { + return { + stdout: JSON.stringify({ + data: { + repository: { + issue: { + body: 'Enterprise issue body', + assignees: { nodes: [] }, + participants: { nodes: [] }, + comments: { nodes: [] } + } + } + } + }) + } + } + const endpoint = args.find((arg) => arg.startsWith('repos/')) ?? '' + if (endpoint === 'repos/team/orca/issues/7/timeline?per_page=100&page=1') { + return { stdout: '' } + } + throw new Error(`unexpected gh call: ${args.join(' ')}`) + }) + + const details = await getWorkItemDetails('/remote/repo', 7, 'issue', 'ssh-1') + + expect(details?.body).toBe('Enterprise issue body') + expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'issue', 'ssh-1') + expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() + expect(getEnterpriseGitHubRepoSlugMock).toHaveBeenCalledTimes(1) + expect(repositoryRateLimitGuardMock).toHaveBeenCalledWith(enterpriseRepository, 'graphql', { + host: 'github.acme-corp.com' + }) + expect(noteRepositoryRateLimitSpendMock).toHaveBeenCalled() + expect( + ghExecFileAsyncMock.mock.calls.every( + ([, options]) => options?.host === 'github.acme-corp.com' + ) + ).toBe(true) + }) + + it('does not query the default host when an SSH issue repository is unresolved', async () => { + getWorkItemMock.mockResolvedValue(null) + + await expect(getWorkItemDetails('/remote/repo', 7, 'issue', 'ssh-1')).resolves.toBeNull() + + expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'issue', 'ssh-1') + expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() + expect(ghExecFileAsyncMock).not.toHaveBeenCalled() + }) + + it('uses the GitHub Enterprise host for SSH-backed PR work item details', async () => { + getWorkItemMock.mockResolvedValueOnce({ + id: 'pr:7', + type: 'pr', + number: 7, + title: 'Enterprise PR files', + state: 'open', + url: 'https://github.acme-corp.com/team/orca/pull/7', + labels: [], + updatedAt: '2026-07-16T00:00:00Z', + author: 'pr-author', + prRepo: { owner: 'team', repo: 'orca', host: 'github.acme-corp.com' } + }) + getPRCommentsMock.mockResolvedValue([]) + getPRChecksMock.mockResolvedValue([]) + ghExecFileAsyncMock.mockImplementation(async (args: string[]) => { + const endpoint = args.find((arg) => arg.startsWith('repos/')) ?? '' + if (endpoint === 'repos/team/orca/pulls/7') { + return { + stdout: JSON.stringify({ + body: 'Enterprise PR body', + head: { sha: 'head-sha' }, + base: { sha: 'base-sha' } + }) + } + } + if (endpoint === 'repos/team/orca/pulls/7/files?per_page=100') { + return { + stdout: JSON.stringify([ + { + filename: 'src/enterprise.ts', + status: 'modified', + additions: 2, + deletions: 1, + changes: 3, + patch: '@@ -1 +1 @@' + } + ]) + } + } + const query = args.find((arg) => arg.startsWith('query=')) ?? '' + if (query.includes('viewerViewedState')) { + return { + stdout: JSON.stringify({ + data: { + repository: { + pullRequest: { + id: 'PR_enterprise', + files: { + pageInfo: { hasNextPage: false, endCursor: null }, + nodes: [{ path: 'src/enterprise.ts', viewerViewedState: 'VIEWED' }] + } + } + } + } + }) + } + } + if (query.includes('participants(first: 100)')) { + return { + stdout: JSON.stringify({ + data: { repository: { pullRequest: { participants: { nodes: [] } } } } + }) + } + } + throw new Error(`unexpected gh call: ${args.join(' ')}`) + }) + + const details = await getWorkItemDetails('/remote/repo', 7, 'pr', 'ssh-1') + + expect(details?.body).toBe('Enterprise PR body') + expect(details?.headSha).toBe('head-sha') + expect(details?.baseSha).toBe('base-sha') + expect(details?.filesUnavailable).toBe(false) + expect(details?.files).toEqual([ + { + path: 'src/enterprise.ts', + oldPath: undefined, + status: 'modified', + additions: 2, + deletions: 1, + isBinary: false, + reviewCommentLineNumbers: [], + viewerViewedState: 'VIEWED' + } + ]) + expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'pr', 'ssh-1') + expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() + expect(getPRCommentsMock).toHaveBeenCalledWith( + '/remote/repo', + 7, + { prRepo: { owner: 'team', repo: 'orca', host: 'github.acme-corp.com' } }, + 'ssh-1' + ) + expect(getPRChecksMock).toHaveBeenCalledWith( + '/remote/repo', + 7, + 'head-sha', + { owner: 'team', repo: 'orca', host: 'github.acme-corp.com' }, + undefined, + 'ssh-1' + ) + const apiCalls = ghExecFileAsyncMock.mock.calls + .map(([args]) => args as string[]) + .filter((args) => args[0] === 'api') + expect(apiCalls.length).toBeGreaterThan(0) + expect(apiCalls.every((args) => !args.includes('--hostname'))).toBe(true) + expect( + ghExecFileAsyncMock.mock.calls.every( + ([, options]) => options?.host === 'github.acme-corp.com' + ) + ).toBe(true) + }) + + it('does not fall back to the default host after an Enterprise PR lookup fails', async () => { + getWorkItemMock.mockResolvedValue(null) + + await expect(getWorkItemDetails('/remote/repo', 7, 'pr', 'ssh-1')).resolves.toBeNull() + + expect(getWorkItemMock).toHaveBeenCalledTimes(1) + expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() + expect(ghExecFileAsyncMock).not.toHaveBeenCalled() + }) + + it('does not query the default host when an SSH PR repository is unresolved', async () => { + getWorkItemMock.mockResolvedValue(null) + + await expect(getWorkItemDetails('/remote/repo', 7, 'pr', 'ssh-1')).resolves.toBeNull() + + expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'pr', 'ssh-1') + expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() + expect(ghExecFileAsyncMock).not.toHaveBeenCalled() + }) +}) diff --git a/src/main/github/work-item-details.test.ts b/src/main/github/work-item-details.test.ts index 5d939eda1f2..1f224b7d2a0 100644 --- a/src/main/github/work-item-details.test.ts +++ b/src/main/github/work-item-details.test.ts @@ -590,77 +590,6 @@ describe('getWorkItemDetails', () => { expect(details?.body).toBe('Remote issue body') }) - it('uses the GitHub Enterprise host for SSH-backed issue work item details', async () => { - const enterpriseRepository = { - owner: 'team', - repo: 'orca', - host: 'github.acme-corp.com' - } - getWorkItemMock.mockResolvedValueOnce({ - id: 'issue:7', - type: 'issue', - number: 7, - title: 'Enterprise issue', - state: 'open', - url: 'https://github.acme-corp.com/team/orca/issues/7', - labels: [], - updatedAt: '2026-07-16T00:00:00Z', - author: 'issue-author' - }) - getOwnerRepoMock.mockResolvedValue(null) - getEnterpriseGitHubRepoSlugMock.mockResolvedValue(enterpriseRepository) - ghExecFileAsyncMock.mockImplementation(async (args: string[]) => { - const query = args.find((arg) => arg.startsWith('query=')) ?? '' - if (query.includes('comments(first: 100)')) { - return { - stdout: JSON.stringify({ - data: { - repository: { - issue: { - body: 'Enterprise issue body', - assignees: { nodes: [] }, - participants: { nodes: [] }, - comments: { nodes: [] } - } - } - } - }) - } - } - const endpoint = args.find((arg) => arg.startsWith('repos/')) ?? '' - if (endpoint === 'repos/team/orca/issues/7/timeline?per_page=100&page=1') { - return { stdout: '' } - } - throw new Error(`unexpected gh call: ${args.join(' ')}`) - }) - - const details = await getWorkItemDetails('/remote/repo', 7, 'issue', 'ssh-1') - - expect(details?.body).toBe('Enterprise issue body') - expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'issue', 'ssh-1') - expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() - expect(getEnterpriseGitHubRepoSlugMock).toHaveBeenCalledTimes(1) - expect(repositoryRateLimitGuardMock).toHaveBeenCalledWith(enterpriseRepository, 'graphql', { - host: 'github.acme-corp.com' - }) - expect(noteRepositoryRateLimitSpendMock).toHaveBeenCalled() - expect( - ghExecFileAsyncMock.mock.calls.every( - ([, options]) => options?.host === 'github.acme-corp.com' - ) - ).toBe(true) - }) - - it('does not query the default host when an SSH issue repository is unresolved', async () => { - getWorkItemMock.mockResolvedValue(null) - - await expect(getWorkItemDetails('/remote/repo', 7, 'issue', 'ssh-1')).resolves.toBeNull() - - expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'issue', 'ssh-1') - expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() - expect(ghExecFileAsyncMock).not.toHaveBeenCalled() - }) - it('routes local WSL PR detail fan-out through the selected distro', async () => { const localGitOptions = { wslDistro: 'Ubuntu' } getWorkItemMock.mockResolvedValueOnce({ @@ -742,140 +671,6 @@ describe('getWorkItemDetails', () => { ) }) - it('uses the GitHub Enterprise host for SSH-backed PR work item details', async () => { - getWorkItemMock.mockResolvedValueOnce({ - id: 'pr:7', - type: 'pr', - number: 7, - title: 'Enterprise PR files', - state: 'open', - url: 'https://github.acme-corp.com/team/orca/pull/7', - labels: [], - updatedAt: '2026-07-16T00:00:00Z', - author: 'pr-author', - prRepo: { owner: 'team', repo: 'orca', host: 'github.acme-corp.com' } - }) - getPRCommentsMock.mockResolvedValue([]) - getPRChecksMock.mockResolvedValue([]) - ghExecFileAsyncMock.mockImplementation(async (args: string[]) => { - const endpoint = args.find((arg) => arg.startsWith('repos/')) ?? '' - if (endpoint === 'repos/team/orca/pulls/7') { - return { - stdout: JSON.stringify({ - body: 'Enterprise PR body', - head: { sha: 'head-sha' }, - base: { sha: 'base-sha' } - }) - } - } - if (endpoint === 'repos/team/orca/pulls/7/files?per_page=100') { - return { - stdout: JSON.stringify([ - { - filename: 'src/enterprise.ts', - status: 'modified', - additions: 2, - deletions: 1, - changes: 3, - patch: '@@ -1 +1 @@' - } - ]) - } - } - const query = args.find((arg) => arg.startsWith('query=')) ?? '' - if (query.includes('viewerViewedState')) { - return { - stdout: JSON.stringify({ - data: { - repository: { - pullRequest: { - id: 'PR_enterprise', - files: { - pageInfo: { hasNextPage: false, endCursor: null }, - nodes: [{ path: 'src/enterprise.ts', viewerViewedState: 'VIEWED' }] - } - } - } - } - }) - } - } - if (query.includes('participants(first: 100)')) { - return { - stdout: JSON.stringify({ - data: { repository: { pullRequest: { participants: { nodes: [] } } } } - }) - } - } - throw new Error(`unexpected gh call: ${args.join(' ')}`) - }) - - const details = await getWorkItemDetails('/remote/repo', 7, 'pr', 'ssh-1') - - expect(details?.body).toBe('Enterprise PR body') - expect(details?.headSha).toBe('head-sha') - expect(details?.baseSha).toBe('base-sha') - expect(details?.filesUnavailable).toBe(false) - expect(details?.files).toEqual([ - { - path: 'src/enterprise.ts', - oldPath: undefined, - status: 'modified', - additions: 2, - deletions: 1, - isBinary: false, - reviewCommentLineNumbers: [], - viewerViewedState: 'VIEWED' - } - ]) - expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'pr', 'ssh-1') - expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() - expect(getPRCommentsMock).toHaveBeenCalledWith( - '/remote/repo', - 7, - { prRepo: { owner: 'team', repo: 'orca', host: 'github.acme-corp.com' } }, - 'ssh-1' - ) - expect(getPRChecksMock).toHaveBeenCalledWith( - '/remote/repo', - 7, - 'head-sha', - { owner: 'team', repo: 'orca', host: 'github.acme-corp.com' }, - undefined, - 'ssh-1' - ) - const apiCalls = ghExecFileAsyncMock.mock.calls - .map(([args]) => args as string[]) - .filter((args) => args[0] === 'api') - expect(apiCalls.length).toBeGreaterThan(0) - expect(apiCalls.every((args) => !args.includes('--hostname'))).toBe(true) - expect( - ghExecFileAsyncMock.mock.calls.every( - ([, options]) => options?.host === 'github.acme-corp.com' - ) - ).toBe(true) - }) - - it('does not fall back to the default host after an Enterprise PR lookup fails', async () => { - getWorkItemMock.mockResolvedValue(null) - - await expect(getWorkItemDetails('/remote/repo', 7, 'pr', 'ssh-1')).resolves.toBeNull() - - expect(getWorkItemMock).toHaveBeenCalledTimes(1) - expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() - expect(ghExecFileAsyncMock).not.toHaveBeenCalled() - }) - - it('does not query the default host when an SSH PR repository is unresolved', async () => { - getWorkItemMock.mockResolvedValue(null) - - await expect(getWorkItemDetails('/remote/repo', 7, 'pr', 'ssh-1')).resolves.toBeNull() - - expect(getWorkItemMock).toHaveBeenCalledWith('/remote/repo', 7, 'pr', 'ssh-1') - expect(getWorkItemByOwnerRepoMock).not.toHaveBeenCalled() - expect(ghExecFileAsyncMock).not.toHaveBeenCalled() - }) - // Why: a rate-limited/auth-failed file fetch must not render as an empty PR; // the Files tab keys its retry state off details.filesUnavailable. it('flags filesUnavailable when the PR file fetch fails but leaves the PR empty otherwise intact', async () => {