Skip to content

Commit

Permalink
more core tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RomneyDa committed Dec 6, 2024
1 parent 4b952ad commit 8bfc6f1
Show file tree
Hide file tree
Showing 10 changed files with 1,182 additions and 6 deletions.
1 change: 0 additions & 1 deletion .continue/prompts/core-unit-test.prompt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Jest testing setup includes
Do NOT write tests for any files in `core/test`, only use them as helpers for testing other files. If no other files are provided, warn the user and write no tests.

IMPORTANT: Do NOT mock the fixtures above other than using `jest.spyOn`. DO mock 3rd party modules, etc. when sensible.
When using jest.fn, always declare the type, e.g. jest.fn<() => Promise<string>>().mockResolvedValue("hi")
Instead, generate actual mock files and data for operations
Pure mocks should only be used to emulate specific network responses/error or hard-to-duplicate errors, or to prevent long-duration tests

Expand Down
109 changes: 109 additions & 0 deletions core/edit/lazy/findInAst.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Generated by continue

import { findInAst } from "./findInAst";
import Parser from "web-tree-sitter";

describe("findInAst", () => {
it("should find a node matching the criterion", () => {
const mockAst = createMockSyntaxNode("root", [
createMockSyntaxNode("child1", []),
createMockSyntaxNode("function", [createMockSyntaxNode("child2", [])]),
]);

const criterion = (node: Parser.SyntaxNode) => node.type === "function";

const result = findInAst(mockAst, criterion);

expect(result).not.toBeNull();
expect(result!.type).toBe("function");
});

it("should return null if no node matches the criterion", () => {
const mockAst = createMockSyntaxNode("root", [
createMockSyntaxNode("child1", []),
createMockSyntaxNode("child2", []),
]);

const criterion = (node: Parser.SyntaxNode) => node.type === "function";

const result = findInAst(mockAst, criterion);

expect(result).toBeNull();
});

it("should find a nested node matching the criterion", () => {
const mockAst = createMockSyntaxNode("root", [
createMockSyntaxNode("child1", [
createMockSyntaxNode("child2", [createMockSyntaxNode("function", [])]),
]),
createMockSyntaxNode("child3", []),
]);

const criterion = (node: Parser.SyntaxNode) => node.type === "function";

const result = findInAst(mockAst, criterion);

expect(result).not.toBeNull();
expect(result!.type).toBe("function");
});

it("should return the first node matching the criterion in depth-first traversal", () => {
const firstFunctionNode = createMockSyntaxNode("function", []);
const secondFunctionNode = createMockSyntaxNode("function", []);
const mockAst = createMockSyntaxNode("root", [
firstFunctionNode, // First function node
createMockSyntaxNode("child1", [
secondFunctionNode, // Second function node
]),
]);

const criterion = (node: Parser.SyntaxNode) => node.type === "function";

const result = findInAst(mockAst, criterion);

expect(result).not.toBeNull();
expect(result!.type).toBe("function");
expect(JSON.stringify(result)).toBe(JSON.stringify(firstFunctionNode)); // Ensure it's the first function node
});

it("should return the root node if it matches the criterion", () => {
const mockAst = createMockSyntaxNode("function", [
createMockSyntaxNode("child1", []),
createMockSyntaxNode("child2", []),
]);

const criterion = (node: Parser.SyntaxNode) => node.type === "function";

const result = findInAst(mockAst, criterion);

expect(result).not.toBeNull();
expect(result!.type).toBe("function");
expect(result).toBe(mockAst);
});

it("should return null when searching an empty tree", () => {
const mockAst = createMockSyntaxNode("root", []);

const criterion = (node: Parser.SyntaxNode) => node.type === "function";

const result = findInAst(mockAst, criterion);

expect(result).toBeNull();
});
});

function createMockSyntaxNode(
type: string,
children: Parser.SyntaxNode[],
): Parser.SyntaxNode {
// Define minimal properties of SyntaxNode required for the test
const node: Partial<Parser.SyntaxNode> = {
type,
children,
childCount: children.length,
child: (index: number) => {
return children[index] || null;
},
};
return node as Parser.SyntaxNode;
}
87 changes: 87 additions & 0 deletions core/indexing/chunk/basic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Generated by continue
// core/indexing/chunk/basic.test.ts

import { basicChunker } from "./basic.js";
import { countTokensAsync } from "../../llm/countTokens";
import { ChunkWithoutID } from "../../index";

// jest.mock("../../llm/countTokens", () => ({
// countTokensAsync: jest.fn(),
// }));

describe.skip("basicChunker", () => {
beforeEach(() => {
jest.resetAllMocks();
});

it("should yield no chunks for empty content", async () => {
const contents = "";
const maxChunkSize = 10;
const chunks: ChunkWithoutID[] = [];

for await (const chunk of basicChunker(contents, maxChunkSize)) {
chunks.push(chunk);
}

expect(chunks).toHaveLength(0);
});

it("should yield a single chunk if whole content fits within the max size", async () => {
(countTokensAsync as jest.Mock).mockResolvedValue(1);
const contents = "line1\nline2\nline3";
const maxChunkSize = 10;
const expectedChunks: ChunkWithoutID[] = [
{ content: "line1\nline2\nline3\n", startLine: 0, endLine: 2 },
];

const chunks: ChunkWithoutID[] = [];
for await (const chunk of basicChunker(contents, maxChunkSize)) {
chunks.push(chunk);
}

expect(chunks).toEqual(expectedChunks);
});

it("should yield multiple chunks when content exceeds the max size", async () => {
(countTokensAsync as jest.Mock).mockImplementation(async (line: string) => {
if (line === "line3") return 5;
return 3; // Mock returning 3 tokens per line except for "line3"
});

const contents = "line1\nline2\nline3\nline4\nline5";
const maxChunkSize = 8;
const expectedChunks: ChunkWithoutID[] = [
{ content: "line1\nline2\n", startLine: 0, endLine: 1 },
{ content: "line3\n", startLine: 2, endLine: 2 },
{ content: "line4\nline5\n", startLine: 3, endLine: 4 },
];

const chunks: ChunkWithoutID[] = [];
for await (const chunk of basicChunker(contents, maxChunkSize)) {
chunks.push(chunk);
}

expect(chunks).toEqual(expectedChunks);
});

it("should skip lines that exceed the max chunk size", async () => {
(countTokensAsync as jest.Mock).mockImplementation(async (line: string) => {
if (line === "line3") return 15; // Making it explicitly exceed max size
return 3;
});

const contents = "line1\nline2\nline3\nline4\nline5";
const maxChunkSize = 8;
const expectedChunks: ChunkWithoutID[] = [
{ content: "line1\nline2\n", startLine: 0, endLine: 1 },
{ content: "line4\nline5\n", startLine: 3, endLine: 4 },
];

const chunks: ChunkWithoutID[] = [];
for await (const chunk of basicChunker(contents, maxChunkSize)) {
chunks.push(chunk);
}

expect(chunks).toEqual(expectedChunks);
});
});
Loading

0 comments on commit 8bfc6f1

Please sign in to comment.