From 709cb6c9e98ebe046c97f2de1867a9a415777aba Mon Sep 17 00:00:00 2001 From: quality Date: Sun, 4 Oct 2026 16:54:21 -0400 Subject: [PATCH] test(bundle): drive handlePullReq's unsupported-job and failed-lgtm-read arms through dist/index.js Adds __tests__/bundle/pullReqJobsArms.test.ts: a pull_request synchronize run with an unsupported `jobs` entry, one whose lgtm job's labels read answers 500, and one mixing a working lgtm job with an unsupported job. Covers src/pullReq/handlePullReq.ts lines 62-66 and 75-80 and src/pullReq/onPrLgtm.ts line 30 end-to-end (npm run test:coverage:e2e: handlePullReq.ts 80.76 -> 96.15 % lines, onPrLgtm.ts 83.33 -> 91.66 %). Signed-off-by: quality --- __tests__/bundle/pullReqJobsArms.test.ts | 66 ++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 __tests__/bundle/pullReqJobsArms.test.ts diff --git a/__tests__/bundle/pullReqJobsArms.test.ts b/__tests__/bundle/pullReqJobsArms.test.ts new file mode 100644 index 0000000..9ce8474 --- /dev/null +++ b/__tests__/bundle/pullReqJobsArms.test.ts @@ -0,0 +1,66 @@ +import type { FakeGithub } from './fakeGithub' +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' + +import pullReqOpenedEvent from '../fixtures/pullReq/pullReqOpenedEvent.json' +import { start } from './fakeGithub' +import { helpersFor, ownersProbe, ownersReads, repo, token } from './helpers' +import { runBundle } from './runBundle' + +vi.setConfig({ testTimeout: 30_000 }) + +// the arms of handlePullReq's `jobs` input — an unsupported job, and the lgtm job's failed +// labels read — driven through dist/index.js like the happy paths in bundle.test.ts +describe('dist/index.js pull_request jobs input', () => { + let gh: FakeGithub + const { routeOwners } = helpersFor(() => gh) + + beforeAll(async () => { + gh = await start() + }) + beforeEach(() => { + gh.mergeQueueFallback({ pullRequestId: 'PR_none', headOid: pullReqOpenedEvent.pull_request.head.sha, enabled: false }) + routeOwners({}, ['src/file1.txt']) + }) + afterEach(() => gh.reset()) + afterAll(() => gh.close()) + + function synchronize(jobs: string) { + return runBundle({ + eventName: 'pull_request', + payload: { ...pullReqOpenedEvent, action: 'synchronize' }, + inputs: { ...token, jobs }, + apiUrl: gh.url, + }) + } + + it('an unsupported job fails the run naming the job after the registered handlers have run', async () => { + const result = await synchronize('frobnicate') + + expect(result.status, result.stdout).toBe(1) + expect(result.errors).toEqual(['TypeError: error handling pull request: Error: could not execute frobnicate. May not be supported - please refer to docs']) + // owners-label and approve's probe still run; the unknown job reads nothing + expect(gh.requests.map(r => `${r.method} ${r.path}`)).toEqual([...ownersReads, ownersProbe]) + }) + + it('lgtm job: a failed labels read fails the run and removes nothing', async () => { + gh.route('GET', `${repo}/issues/1`, { status: 500, body: { message: 'boom' } }) + + const result = await synchronize('lgtm') + + expect(result.status, result.stdout).toBe(1) + expect(result.errors).toHaveLength(1) + expect(result.errors[0]).toContain('TypeError: error handling pull request: Error: could not get labels from issue') + expect(gh.requests.map(r => `${r.method} ${r.path}`)).toEqual([...ownersReads, ownersProbe, `GET ${repo}/issues/1`]) + }) + + it('one failing job does not stop another: lgtm removes the label while the unsupported job fails the run', async () => { + gh.route('GET', `${repo}/issues/1`, { status: 200, body: { labels: [{ name: 'lgtm' }] } }) + gh.route('DELETE', `${repo}/issues/1/labels/lgtm`, { status: 200, body: [] }) + + const result = await synchronize('lgtm frobnicate') + + expect(result.status, result.stdout).toBe(1) + expect(result.errors).toEqual(['TypeError: error handling pull request: Error: could not execute frobnicate. May not be supported - please refer to docs']) + expect(gh.requests.map(r => `${r.method} ${r.path}`)).toEqual([...ownersReads, ownersProbe, `GET ${repo}/issues/1`, `DELETE ${repo}/issues/1/labels/lgtm`]) + }) +})