Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/review/e2e-test-gen-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ export type E2eTestGenCommentInput = {
commit?: E2eTestGenCommitOutcome | undefined;
};

function markdownFenceFor(source: string): string {
const backtickRunLengths = Array.from(source.matchAll(/`+/g), (match) => match[0]!.length);
const longestBacktickRun = Math.max(0, ...backtickRunLengths);
return "`".repeat(Math.max(3, longestBacktickRun + 1));
}

/**
* Build the PR-comment body for a `@gittensory generate-tests` result. A null `testSource` renders a
* clear "nothing usable" note rather than silently posting no comment at all — the maintainer who invoked
Expand Down Expand Up @@ -74,6 +80,7 @@ export function buildE2eTestGenCommentBody(input: E2eTestGenCommentInput): strin
"",
]
: [];
const fence = markdownFenceFor(input.testSource);
return [
AGENT_COMMAND_COMMENT_MARKER,
"",
Expand All @@ -82,9 +89,9 @@ export function buildE2eTestGenCommentBody(input: E2eTestGenCommentInput): strin
"> This is a suggestion, not a guarantee — review it like any other test before merging.",
...declineNote,
"",
"```typescript",
`${fence}typescript`,
input.testSource,
"```",
fence,
"",
"---",
gittensoryFooter(),
Expand Down
21 changes: 21 additions & 0 deletions test/unit/e2e-test-gen-render.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ describe("buildE2eTestGenCommentBody", () => {
expect(body).toContain("```typescript\ntest('x', () => {});\n```");
});

it("uses a longer markdown fence when generated source contains backtick fences", () => {
const source = [
"import { test, expect } from '@playwright/test';",
"",
"test('injected markdown stays inside the code block', async ({ page }) => {",
" const attackerMarkdown = `",
"```",
"# rendered outside the fence before the fix",
"```",
" `;",
" expect(attackerMarkdown).toContain('# rendered outside');",
"});",
].join("\n");

const body = buildE2eTestGenCommentBody({ actor: "maintainer", testSource: source });

expect(body).toContain("````typescript\n");
expect(body).toContain(source + "\n````");
expect(body.split("\n")).not.toContain("```typescript");
});

it("uses a custom framework name when provided", () => {
const body = buildE2eTestGenCommentBody({ actor: "maintainer", testSource: "it('x', () => {});", framework: "Cypress" });
expect(body).toContain("AI-generated Cypress test for @maintainer");
Expand Down