From b37a76ecc94d8b3b266f9aeee776ee7ee9195018 Mon Sep 17 00:00:00 2001 From: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com> Date: Tue, 20 Oct 2026 12:46:20 -0400 Subject: [PATCH] test(lgtmBinding): pin hasLgtmLabel's .some and case fold, unbindLgtm's pending body and 140-char bound, and isLgtmBound's per_page=100 A single-operator mutation probe over src/plugins/lgtmBinding.ts left four non-equivalent survivors: hasLgtmLabel's .some -> .every and its .toLowerCase() removal, unbindLgtm's slice(0, 140) -> slice(0, 141), and isLgtmBound's per_page: 100 -> 30. Each now fails at least one test. Refs #523 Signed-off-by: quality <280983584+hivecommons-hive[bot]@users.noreply.github.com> --- __tests__/plugins/lgtmBinding.test.ts | 35 ++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/__tests__/plugins/lgtmBinding.test.ts b/__tests__/plugins/lgtmBinding.test.ts index 55668610..bef3732d 100644 --- a/__tests__/plugins/lgtmBinding.test.ts +++ b/__tests__/plugins/lgtmBinding.test.ts @@ -4,7 +4,7 @@ import { http } from 'msw' import { setupServer } from 'msw/node' import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' -import { bindLgtm, isLgtmBound, lgtmOnPullRequest, lgtmSettings, unbindLgtm } from '../../src/plugins/lgtmBinding' +import { bindLgtm, hasLgtmLabel, isLgtmBound, lgtmOnPullRequest, lgtmSettings, unbindLgtm } from '../../src/plugins/lgtmBinding' import { mergeProwConfig } from '../../src/utils/config' import { newOctokit } from '../../src/utils/octokit' import labelFileContents from '../fixtures/labels/labelFileContentsResp.json' @@ -41,6 +41,17 @@ describe('lgtmSettings', () => { }) }) +describe('hasLgtmLabel', () => { + it.each([ + ['lgtm among other labels', ['approved', 'lgtm', 'kind/bug'], true], + ['LGTM in another case', ['LGTM'], true], + ['only other labels', ['approved', 'kind/bug'], false], + ['no labels', [], false], + ])('%s', (_, labels, expected) => { + expect(hasLgtmLabel(labels)).toBe(expected) + }) +}) + describe('lgtmOnPullRequest', () => { it('labeled lgtm by a human binds the label to the payload head', async () => { const status = new utils.ObserveRequest() @@ -121,6 +132,19 @@ describe('the binding primitives', () => { expect(body).not.toHaveProperty('target_url') }) + it('unbindLgtm sets prow/lgtm to pending and truncates the description to 140 characters', async () => { + const status = new utils.ObserveRequest() + server.use(http.post(`${repo}/statuses/abc`, utils.mockResponse(201, {}, status))) + + await expect(unbindLgtm(octokit, context, 'abc', 'y'.repeat(200))).resolves.toBeUndefined() + + expect(await status.body()).toEqual({ + state: 'pending', + context: 'prow/lgtm', + description: 'y'.repeat(140), + }) + }) + it('unbindLgtm warns instead of throwing', async () => { server.use(http.post(`${repo}/statuses/abc`, utils.mockResponse(500, { message: 'boom' }))) const warning = vi.spyOn(core, 'warning').mockImplementation(() => {}) @@ -140,6 +164,15 @@ describe('the binding primitives', () => { await expect(isLgtmBound(octokit, context, 'abc')).resolves.toBe(bound) }) + it('isLgtmBound reads the combined status with per_page=100', async () => { + const combined = new utils.ObserveRequest() + server.use(http.get(`${repo}/commits/abc/status`, utils.mockResponse(200, { state: 'x', statuses: [] }, combined))) + + await isLgtmBound(octokit, context, 'abc') + + expect(new URL(combined.ref!.url).searchParams.get('per_page')).toBe('100') + }) + it('isLgtmBound wraps any other error without the permission hint', async () => { server.use(http.get(`${repo}/commits/abc/status`, utils.mockResponse(500, { message: 'boom' })))