Add unit tests for TypeScript/JavaScript validator error reporting
Tests for: - Error location reporting with line numbers and code snippets - Markdown code block parsing with various scenarios - Multiple code blocks with mixed valid/invalid content - Real-world TypeScript patterns (async, try-catch, template literals) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
07ae9db684
commit
8800614d1c
1 changed files with 206 additions and 0 deletions
|
|
@ -262,3 +262,209 @@ export function generateCorrelationId(service: string default "cf-api"): string
|
|||
assert isinstance(is_valid, bool)
|
||||
assert not is_valid
|
||||
assert error is not None
|
||||
|
||||
|
||||
class TestErrorLocationReporting:
|
||||
"""Tests for error location reporting in validation errors."""
|
||||
|
||||
def test_error_includes_line_number(self) -> None:
|
||||
"""Test that syntax errors include line number in error message."""
|
||||
code = """function broken( {
|
||||
return 123;
|
||||
}"""
|
||||
is_valid, error = validate_javascript_syntax(code)
|
||||
assert is_valid is False
|
||||
assert error is not None
|
||||
assert "line" in error.lower()
|
||||
|
||||
def test_error_includes_code_snippet(self) -> None:
|
||||
"""Test that syntax errors include code snippet in error message."""
|
||||
code = """function broken( {
|
||||
return 123;
|
||||
}"""
|
||||
is_valid, error = validate_javascript_syntax(code)
|
||||
assert is_valid is False
|
||||
assert error is not None
|
||||
# Error should contain part of the problematic line
|
||||
assert "broken" in error or "function" in error
|
||||
|
||||
def test_typescript_error_includes_line_number(self) -> None:
|
||||
"""Test that TypeScript syntax errors include line number."""
|
||||
code = """interface User {
|
||||
name: string
|
||||
age number // missing colon
|
||||
}"""
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
assert is_valid is False
|
||||
assert error is not None
|
||||
assert "line" in error.lower()
|
||||
|
||||
def test_markdown_error_includes_line_number(self) -> None:
|
||||
"""Test that errors in markdown code blocks include line number."""
|
||||
code = """```typescript:test.ts
|
||||
function valid(): string {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
function broken( {
|
||||
return 123;
|
||||
}
|
||||
```"""
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
assert is_valid is False
|
||||
assert error is not None
|
||||
assert "line" in error.lower()
|
||||
|
||||
def test_error_on_specific_line(self) -> None:
|
||||
"""Test that error reports correct line number for error on line 3."""
|
||||
code = """const a = 1;
|
||||
const b = 2;
|
||||
const c = broken(;
|
||||
const d = 4;"""
|
||||
is_valid, error = validate_javascript_syntax(code)
|
||||
assert is_valid is False
|
||||
assert error is not None
|
||||
# Error should be on line 3
|
||||
assert "line 3" in error.lower() or "line 3," in error
|
||||
|
||||
def test_typescript_async_function_with_template_literal(self) -> None:
|
||||
"""Test that async functions with template literals validate correctly."""
|
||||
code = """```typescript:src/ctl/mongo_shell_utils.ts
|
||||
import * as utils from "./utils";
|
||||
|
||||
const command_args = process.argv.slice(3);
|
||||
|
||||
async function execMongoEval(queryExpression, appsmithMongoURI) {
|
||||
queryExpression = queryExpression.trim();
|
||||
|
||||
if (command_args.includes("--pretty")) {
|
||||
queryExpression += ".pretty()";
|
||||
}
|
||||
|
||||
return await utils.execCommand([
|
||||
"mongosh",
|
||||
appsmithMongoURI,
|
||||
`--eval=${queryExpression}`,
|
||||
]);
|
||||
}
|
||||
```"""
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
||||
def test_typescript_try_catch_function(self) -> None:
|
||||
"""Test that functions with try-catch blocks validate correctly."""
|
||||
code = """```typescript:src/ctl/restore.ts
|
||||
import fsPromises from "fs/promises";
|
||||
import path from "path";
|
||||
|
||||
async function figureOutContentsPath(root: string): Promise<string> {
|
||||
const subfolders = await fsPromises.readdir(root, { withFileTypes: true });
|
||||
|
||||
try {
|
||||
await fsPromises.access(path.join(root, "manifest.json"));
|
||||
return root;
|
||||
} catch (error) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
for (const subfolder of subfolders) {
|
||||
if (subfolder.isDirectory()) {
|
||||
try {
|
||||
await fsPromises.access(
|
||||
path.join(root, subfolder.name, "manifest.json"),
|
||||
);
|
||||
return path.join(root, subfolder.name);
|
||||
} catch (error) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Could not find the contents.");
|
||||
}
|
||||
```"""
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
||||
|
||||
class TestMarkdownParsing:
|
||||
"""Tests for markdown code block parsing in validation."""
|
||||
|
||||
def test_empty_markdown_no_code_blocks(self) -> None:
|
||||
"""Test validation when markdown has no matching code blocks."""
|
||||
# This markdown has python blocks, not typescript
|
||||
# Note: Raw markdown with ``` actually parses as valid TypeScript
|
||||
# because backticks form template literals in TypeScript/JavaScript
|
||||
code = """```python
|
||||
def hello():
|
||||
return "world"
|
||||
```"""
|
||||
# When no typescript blocks found, it should fall through to validate raw
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
# The raw markdown happens to be valid TypeScript (template literals)
|
||||
# This verifies the warning is logged and fallback validation runs
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
||||
def test_multiple_valid_code_blocks(self) -> None:
|
||||
"""Test that multiple valid code blocks all pass validation."""
|
||||
code = """```typescript:file1.ts
|
||||
function add(a: number, b: number): number {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
```typescript:file2.ts
|
||||
function multiply(a: number, b: number): number {
|
||||
return a * b;
|
||||
}
|
||||
```"""
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
||||
def test_one_invalid_block_fails_all(self) -> None:
|
||||
"""Test that one invalid block in multiple blocks fails validation."""
|
||||
code = """```typescript:valid.ts
|
||||
function valid(): number {
|
||||
return 42;
|
||||
}
|
||||
```
|
||||
```typescript:invalid.ts
|
||||
function invalid( {
|
||||
return broken;
|
||||
}
|
||||
```"""
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
assert is_valid is False
|
||||
assert error is not None
|
||||
|
||||
def test_javascript_markdown_blocks(self) -> None:
|
||||
"""Test JavaScript code in markdown blocks."""
|
||||
code = """```javascript:utils.js
|
||||
function formatDate(date) {
|
||||
return date.toISOString();
|
||||
}
|
||||
```"""
|
||||
is_valid, error = validate_javascript_syntax(code)
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
||||
def test_js_shorthand_in_markdown(self) -> None:
|
||||
"""Test that 'js' shorthand works in markdown blocks."""
|
||||
code = """```js:utils.js
|
||||
const add = (a, b) => a + b;
|
||||
```"""
|
||||
is_valid, error = validate_javascript_syntax(code)
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
||||
def test_ts_shorthand_in_markdown(self) -> None:
|
||||
"""Test that 'ts' shorthand works in markdown blocks."""
|
||||
code = """```ts:utils.ts
|
||||
const add = (a: number, b: number): number => a + b;
|
||||
```"""
|
||||
is_valid, error = validate_typescript_syntax(code)
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
|
|
|||
Loading…
Reference in a new issue