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
70 changes: 70 additions & 0 deletions web-report/src-e2e/extractComments.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {describe, it, expect} from "vitest";
import {extractComments} from "../src/lib/utils";

describe("extractComments", () => {
it("extracts Python # line comments above a test", () => {
const code = [
" # Calls:",
" # (415) POST:/v2/pet/{petId}/uploadImage",
" # Found 1 potential fault of type-code 101",
" @timeout_decorator.timeout(60)",
" def test_23_post_on_uploadImage_returnsMismatchResponseWithSchema(self):",
" pass",
].join("\n");

expect(extractComments(code)).toBe(
[
"Calls:",
"(415) POST:/v2/pet/{petId}/uploadImage",
"Found 1 potential fault of type-code 101",
].join("\n"),
);
});

it("extracts Java /** */ Javadoc blocks", () => {
const code = [
" /**",
" * Calls:",
" * (200) GET:/pets",
" */",
" @Test",
" public void test_1() { }",
].join("\n");

expect(extractComments(code)).toBe(["Calls:", "(200) GET:/pets"].join("\n"));
});

it("extracts // line comments", () => {
const code = [
" // Calls:",
" // (200) GET:/pets",
" public void test() { }",
].join("\n");

expect(extractComments(code)).toBe(["Calls:", "(200) GET:/pets"].join("\n"));
});

it("separates distinct comment blocks with a blank line", () => {
const code = [
"# first block",
"# more of first block",
"",
"code_line()",
"# second block",
].join("\n");

expect(extractComments(code)).toBe(
["first block\nmore of first block", "second block"].join("\n\n"),
);
});

it("returns empty string when there are no comments", () => {
const code = ["def test():", " pass"].join("\n");
expect(extractComments(code)).toBe("");
});

it("handles a single-line /* ... */ block", () => {
const code = ["/* hello world */", "def f(): pass"].join("\n");
expect(extractComments(code)).toBe("hello world");
});
});
64 changes: 49 additions & 15 deletions web-report/src/lib/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,57 @@ export const extractCodeLines = (
};

export const extractComments = (code: string): string => {
const blockRegex = /\/\*\*[\s\S]*?\*\//g;
const blocks = code.match(blockRegex);
if (!blocks || blocks.length === 0) {
return "";
const lines = code.split("\n");
const groups: string[] = [];
let current: string[] = [];
let inBlock = false;

const flush = () => {
if (current.length === 0) return;
const text = current.join("\n").trim();
if (text.length > 0) groups.push(text);
current = [];
};

for (const raw of lines) {
const trimmed = raw.trim();

if (inBlock) {
const endIdx = trimmed.indexOf("*/");
const body = (endIdx >= 0 ? trimmed.slice(0, endIdx) : trimmed).replace(/^\*+\s?/, "");
if (body.length > 0) current.push(body);
if (endIdx >= 0) {
inBlock = false;
flush();
}
continue;
}

if (trimmed.startsWith("/*")) {
const afterOpen = trimmed.replace(/^\/\*+\s?/, "");
const endIdx = afterOpen.indexOf("*/");
if (endIdx >= 0) {
const body = afterOpen.slice(0, endIdx).trim();
if (body) current.push(body);
flush();
} else {
inBlock = true;
if (afterOpen.length > 0) current.push(afterOpen);
}
continue;
}

const lineMatch = trimmed.match(/^(?:#|\/\/)\s?(.*)$/);
if (lineMatch) {
current.push(lineMatch[1]);
continue;
}

flush();
}
flush();

return blocks
.map(block => {
const inner = block.replace(/^\/\*\*/, "").replace(/\*\/$/, "");
return inner
.split("\n")
.map(line => line.replace(/^\s*\*\s?/, ""))
.join("\n")
.trim();
})
.filter(text => text.length > 0)
.join("\n\n");
return groups.join("\n\n");
};

export const calculateAllStatusCounts = (coveredHttpStatus: CoveredEndpoint[], endpointIds:string[]) => {
Expand Down
Loading