From 362ed82820124cec63e065d9ac1e32937c2475ca Mon Sep 17 00:00:00 2001 From: quality Date: Mon, 5 Oct 2026 05:29:37 -0400 Subject: [PATCH 1/2] test(bundle): drive commandLines' fence-closer, indented-code and info-string guards through dist/index.js Adds __tests__/bundle/commandMarkdown.test.ts: 13 issue_comment cases using /hold as the probe. Six assert the command fires once after Markdown code that ends (closed backtick/tilde fences, a longer closer, a closer with trailing whitespace, a backtick opener disqualified by a backtick in its info string, an indented paragraph continuation); seven assert no API call for a /hold inside a fence a shorter/different/trailing-text line does not close, indented code after a blank line or at the start of the body, tab-indented code, and a later line of an indented block. src/utils/command.ts end-to-end coverage (npm run test:coverage:e2e): 87.09 -> 98.38 % lines, 79.41 -> 94.11 % branches. No src/, helpers.ts or existing suite is changed. Closes #323 Signed-off-by: quality --- __tests__/bundle/commandMarkdown.test.ts | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 __tests__/bundle/commandMarkdown.test.ts diff --git a/__tests__/bundle/commandMarkdown.test.ts b/__tests__/bundle/commandMarkdown.test.ts new file mode 100644 index 00000000..f8baa7ba --- /dev/null +++ b/__tests__/bundle/commandMarkdown.test.ts @@ -0,0 +1,72 @@ +import type { FakeGithub } from './fakeGithub' +import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest' + +import { start } from './fakeGithub' +import { comment, configReads, helpersFor, repo, token } from './helpers' +import { runBundle } from './runBundle' + +vi.setConfig({ testTimeout: 30_000 }) + +// src/utils/command.ts commandLines: the Markdown that cannot carry a command, driven through dist/index.js. +// bundle.test.ts already shows a /kind inside an unclosed ``` fence is ignored; these are the arms it leaves +// unreached in the bundle — a fence that closes (and the lines that do not close it), indented code, and a +// backtick fence whose info string disqualifies it. /hold is the probe: it reads the repository's labels and +// posts do-not-merge/hold when it fires, and touches nothing when it does not. +describe('dist/index.js issue_comment commands inside Markdown code', () => { + let gh: FakeGithub + const { expectRequests } = helpersFor(() => gh) + + const labelsRead = `GET ${repo}/labels?per_page=100` + const labelsPost = `POST ${repo}/issues/1/labels` + + beforeAll(async () => { + gh = await start() + }) + afterEach(() => gh.reset()) + afterAll(() => gh.close()) + + function run(body: string) { + return runBundle({ eventName: 'issue_comment', payload: comment(body), inputs: { ...token, 'prow-commands': '/hold' }, apiUrl: gh.url }) + } + + function routeHold() { + gh.route('GET', `${repo}/labels`, { status: 200, body: [{ name: 'do-not-merge/hold' }] }) + gh.route('POST', `${repo}/issues/1/labels`, { status: 200, body: [] }) + } + + it.each([ + ['a closed ``` fence', 'quoting:\n```\n/hold\n```\n/hold'], + ['a closed ~~~ fence', 'quoting:\n~~~\n/hold\n~~~\n/hold'], + ['a ```` fence closed by a longer `````', 'quoting:\n````\n/hold\n`````\n/hold'], + ['a ``` fence closed with trailing whitespace', 'quoting:\n```\n/hold\n``` \n/hold'], + ['a ``` opener whose info string holds a backtick, which is not a fence', '```not`a`fence\n/hold'], + ['an indented line continuing a paragraph, which is not code', 'please\n /hold'], + ])('applies the /hold that follows %s, once', async (_name, body) => { + routeHold() + + const result = await run(body) + + expect(result.status, result.stdout).toBe(0) + expect(result.errors).toEqual([]) + const posts = gh.requestsMatching('POST', /\/issues\/1\/labels$/) + expect(posts).toHaveLength(1) + expect(posts[0].body).toEqual({ labels: ['do-not-merge/hold'] }) + expectRequests(configReads(), [labelsRead, labelsPost]) + }) + + it.each([ + ['a ```` fence a shorter ``` does not close', 'quoting:\n````\n/hold\n```\n/hold'], + ['a ``` fence a ~~~ does not close', 'quoting:\n```\n/hold\n~~~\n/hold'], + ['a ``` fence a closer with trailing text does not close', 'quoting:\n```\n/hold\n``` done\n/hold'], + ['indented code after a blank line', 'quoting:\n\n /hold'], + ['indented code at the start of the body', ' /hold'], + ['a tab-indented code block after a blank line', 'quoting:\n\n\t/hold'], + ['a second indented line of the same code block', 'quoting:\n\n first\n /hold'], + ])('ignores a /hold inside %s without calling the api', async (_name, body) => { + const result = await run(body) + + expect(result.status, result.stdout).toBe(0) + expect(result.errors).toEqual([]) + expect(gh.requests).toEqual([]) + }) +}) From a64d2680d0a49c4466ee0ee1940f936790c03f15 Mon Sep 17 00:00:00 2001 From: quality Date: Wed, 7 Oct 2026 22:16:25 -0400 Subject: [PATCH 2/2] test(bundle): keep only the three markdown rows that reach new command.ts lines Signed-off-by: quality --- __tests__/bundle/commandMarkdown.test.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/__tests__/bundle/commandMarkdown.test.ts b/__tests__/bundle/commandMarkdown.test.ts index f8baa7ba..deb7630d 100644 --- a/__tests__/bundle/commandMarkdown.test.ts +++ b/__tests__/bundle/commandMarkdown.test.ts @@ -35,10 +35,6 @@ describe('dist/index.js issue_comment commands inside Markdown code', () => { } it.each([ - ['a closed ``` fence', 'quoting:\n```\n/hold\n```\n/hold'], - ['a closed ~~~ fence', 'quoting:\n~~~\n/hold\n~~~\n/hold'], - ['a ```` fence closed by a longer `````', 'quoting:\n````\n/hold\n`````\n/hold'], - ['a ``` fence closed with trailing whitespace', 'quoting:\n```\n/hold\n``` \n/hold'], ['a ``` opener whose info string holds a backtick, which is not a fence', '```not`a`fence\n/hold'], ['an indented line continuing a paragraph, which is not code', 'please\n /hold'], ])('applies the /hold that follows %s, once', async (_name, body) => { @@ -55,13 +51,7 @@ describe('dist/index.js issue_comment commands inside Markdown code', () => { }) it.each([ - ['a ```` fence a shorter ``` does not close', 'quoting:\n````\n/hold\n```\n/hold'], - ['a ``` fence a ~~~ does not close', 'quoting:\n```\n/hold\n~~~\n/hold'], - ['a ``` fence a closer with trailing text does not close', 'quoting:\n```\n/hold\n``` done\n/hold'], ['indented code after a blank line', 'quoting:\n\n /hold'], - ['indented code at the start of the body', ' /hold'], - ['a tab-indented code block after a blank line', 'quoting:\n\n\t/hold'], - ['a second indented line of the same code block', 'quoting:\n\n first\n /hold'], ])('ignores a /hold inside %s without calling the api', async (_name, body) => { const result = await run(body)