Hyperscript conformance: 341→372 (45%) — parser, compiler, runtime, generator
Parser: increment/decrement "by N", then-less command chaining, scroll/select/ reset/default/halt commands, toggle style/attr/between, repeat for-loop delegation, number fix for repeat N times, take with from/for scope. Compiler: emit-inc/emit-dec with amount + property/style targets, 12 new dispatch entries (scroll, select, reset, default, halt, toggle-style, toggle-style-between, toggle-attr, toggle-attr-between, take rewrite). Runtime: hs-scroll!, hs-halt!, hs-select!, hs-reset!, hs-query-all, hs-toggle-style!, hs-toggle-style-between!, hs-toggle-attr!, hs-toggle-attr-between!, hs-take! rewrite with kind/name/scope. Generator: handle backtick strings, two-line run()/expect() patterns, toEqual with arrays, toThrow — unlocks 34 more eval-only tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6696,9 +6696,11 @@
|
||||
;; ── collectionExpressions (22 tests) ──
|
||||
(defsuite "hs-upstream-collectionExpressions"
|
||||
(deftest "filters an array by condition"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "a" "c") (eval-hs "set arr to [{name: \"a\", active: true}, {name: \"b\", active: false}, {name: \"c\", active: true}] then return arr where its active"))
|
||||
)
|
||||
(deftest "filters with comparison"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list 4 5) (eval-hs "set arr to [1, 2, 3, 4, 5] then return arr where it > 3"))
|
||||
)
|
||||
(deftest "works with DOM elements"
|
||||
(hs-cleanup!)
|
||||
(let ((_el-list (dom-create-element "ul")) (_el-button (dom-create-element "button")) (_el-out (dom-create-element "div")))
|
||||
@@ -6713,23 +6715,32 @@
|
||||
(assert= "AC" (dom-text-content (dom-query-by-id "out")))
|
||||
))
|
||||
(deftest "sorts by a property"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "Alice" "Bob" "Charlie") (eval-hs "set arr to [{name: \"Charlie\"}, {name: \"Alice\"}, {name: \"Bob\"}] then return arr sorted by its name"))
|
||||
)
|
||||
(deftest "sorts descending"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list 3 2 1) (eval-hs "set arr to [3, 1, 2] then return arr sorted by it descending"))
|
||||
)
|
||||
(deftest "sorts numbers by a computed key"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "a" "c" "b") (eval-hs "set arr to [{name: \"b\", age: 30}, {name: \"a\", age: 20}, {name: \"c\", age: 25}] then return arr sorted by its age"))
|
||||
)
|
||||
(deftest "maps to a property"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "Alice" "Bob") (eval-hs "set arr to [{name: \"Alice\"}, {name: \"Bob\"}] then return arr mapped to its name"))
|
||||
)
|
||||
(deftest "maps with an expression"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list 2 4 6) (eval-hs "set arr to [1, 2, 3] then return arr mapped to (it * 2)"))
|
||||
)
|
||||
(deftest "where then mapped to"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "Alice" "Charlie") (eval-hs "set arr to [{name: \"Alice\", active: true}, {name: \"Bob\", active: false}, {name: \"Charlie\", active: true}] then return arr where its active mapped to its name"))
|
||||
)
|
||||
(deftest "sorted by then mapped to"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "Alice" "Charlie") (eval-hs "set arr to [{name: \"Charlie\", age: 30}, {name: \"Alice\", age: 20}] then return arr sorted by its age mapped to its name"))
|
||||
)
|
||||
(deftest "where then sorted by then mapped to"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "Bob" "Charlie") (eval-hs "set arr to [{name: \"Charlie\", active: true, age: 30}, {name: \"Alice\", active: false, age: 20}, {name: \"Bob\", active: true, age: 25}] then return arr where its active sorted by its age mapped to its name"))
|
||||
)
|
||||
(deftest "the result inside where refers to previous command result, not current element"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list 4 5) (eval-hs "get 3 then set arr to [1, 2, 3, 4, 5] then return arr where it > the result"))
|
||||
)
|
||||
(deftest "where binds after in without parens"
|
||||
(hs-cleanup!)
|
||||
(let ((_el-container (dom-create-element "div")))
|
||||
@@ -6810,19 +6821,26 @@
|
||||
;; ── splitJoin (7 tests) ──
|
||||
(defsuite "hs-upstream-splitJoin"
|
||||
(deftest "splits a string by delimiter"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "a" "b" "c") (eval-hs "return \"a,b,c\" split by \",\""))
|
||||
)
|
||||
(deftest "splits by whitespace"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= (list "hello" "world") (eval-hs "return \"hello world\" split by \" \""))
|
||||
)
|
||||
(deftest "joins an array with delimiter"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "a, b, c" (eval-hs "return [\"a\", \"b\", \"c\"] joined by \", \""))
|
||||
)
|
||||
(deftest "joins with empty string"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "xyz" (eval-hs "return [\"x\", \"y\", \"z\"] joined by \"\""))
|
||||
)
|
||||
(deftest "split then where then joined"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "a-b-c" (eval-hs "return \"a,,b,,c\" split by \",\" where it is not \"\" joined by \"-\""))
|
||||
)
|
||||
(deftest "split then sorted then joined"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "apple, banana, cherry" (eval-hs "return \"banana,apple,cherry\" split by \",\" sorted by it joined by \", \""))
|
||||
)
|
||||
(deftest "split then mapped then joined"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "5,5" (eval-hs "return \"hello world\" split by \" \" mapped to its length joined by \",\""))
|
||||
)
|
||||
)
|
||||
|
||||
;; ── component (19 tests) ──
|
||||
@@ -7380,17 +7398,23 @@
|
||||
(deftest "converts value as Boolean"
|
||||
(assert= true (eval-hs "1 as Boolean"))
|
||||
(assert= false (eval-hs "0 as Boolean"))
|
||||
(assert= false (eval-hs "'' as Boolean"))
|
||||
(assert= true (eval-hs "'hello' as Boolean"))
|
||||
)
|
||||
(deftest "can use the a modifier if you like"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(deftest "parses string as JSON to object"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "bar" (eval-hs "'{\"foo\":\"bar\"}' as JSON"))
|
||||
)
|
||||
(deftest "converts value as JSONString"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "{"foo":"bar"}" (eval-hs "{foo:'bar'} as JSONString"))
|
||||
)
|
||||
(deftest "pipe operator chains conversions"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "bar" (eval-hs "{foo:'bar'} as JSONString | JSON"))
|
||||
)
|
||||
(deftest "can use the an modifier if you'd like"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= "bar" (eval-hs "'{\"foo\":\"bar\"}' as an Object"))
|
||||
)
|
||||
(deftest "collects duplicate text inputs into an array"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(deftest "converts multiple selects with programmatically changed selections"
|
||||
@@ -7485,33 +7509,69 @@
|
||||
(assert= "yes" (dom-text-content (dom-query-by-id "d1")))
|
||||
))
|
||||
(deftest "is ignoring case works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'Hello' is 'hello' ignoring case"))
|
||||
(assert= true (eval-hs "'Hello' is 'HELLO' ignoring case"))
|
||||
(assert= false (eval-hs "'Hello' is 'world' ignoring case"))
|
||||
)
|
||||
(deftest "is not ignoring case works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'Hello' is not 'world' ignoring case"))
|
||||
(assert= false (eval-hs "'Hello' is not 'hello' ignoring case"))
|
||||
)
|
||||
(deftest "contains ignoring case works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'Hello World' contains 'hello' ignoring case"))
|
||||
(assert= true (eval-hs "'Hello World' contains 'WORLD' ignoring case"))
|
||||
(assert= false (eval-hs "'Hello World' contains 'missing' ignoring case"))
|
||||
)
|
||||
(deftest "matches ignoring case works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'Hello' matches 'hello' ignoring case"))
|
||||
(assert= true (eval-hs "'Hello' matches 'HELLO' ignoring case"))
|
||||
)
|
||||
(deftest "starts with works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'hello world' starts with 'hello'"))
|
||||
(assert= false (eval-hs "'hello world' starts with 'world'"))
|
||||
(assert= true (eval-hs "'hello' starts with 'hello'"))
|
||||
(assert= false (eval-hs "'' starts with 'x'"))
|
||||
)
|
||||
(deftest "ends with works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'hello world' ends with 'world'"))
|
||||
(assert= false (eval-hs "'hello world' ends with 'hello'"))
|
||||
(assert= true (eval-hs "'hello' ends with 'hello'"))
|
||||
(assert= false (eval-hs "'' ends with 'x'"))
|
||||
)
|
||||
(deftest "does not start with works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= false (eval-hs "'hello world' does not start with 'hello'"))
|
||||
(assert= true (eval-hs "'hello world' does not start with 'world'"))
|
||||
)
|
||||
(deftest "does not end with works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= false (eval-hs "'hello world' does not end with 'world'"))
|
||||
(assert= true (eval-hs "'hello world' does not end with 'hello'"))
|
||||
)
|
||||
(deftest "starts with null is false"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= false (eval-hs "null starts with 'x'"))
|
||||
(assert= true (eval-hs "null does not start with 'x'"))
|
||||
)
|
||||
(deftest "ends with null is false"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= false (eval-hs "null ends with 'x'"))
|
||||
(assert= true (eval-hs "null does not end with 'x'"))
|
||||
)
|
||||
(deftest "starts with ignoring case works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'Hello World' starts with 'hello' ignoring case"))
|
||||
(assert= true (eval-hs "'Hello World' starts with 'HELLO' ignoring case"))
|
||||
(assert= false (eval-hs "'Hello World' starts with 'world' ignoring case"))
|
||||
)
|
||||
(deftest "ends with ignoring case works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'Hello World' ends with 'world' ignoring case"))
|
||||
(assert= true (eval-hs "'Hello World' ends with 'WORLD' ignoring case"))
|
||||
(assert= false (eval-hs "'Hello World' ends with 'hello' ignoring case"))
|
||||
)
|
||||
(deftest "starts with coerces to string"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "123 starts with '12'"))
|
||||
(assert= false (eval-hs "123 starts with '23'"))
|
||||
)
|
||||
(deftest "ends with coerces to string"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "123 ends with '23'"))
|
||||
(assert= false (eval-hs "123 ends with '12'"))
|
||||
)
|
||||
(deftest "is between works"
|
||||
(assert= true (eval-hs "5 is between 1 and 10"))
|
||||
(assert= true (eval-hs "1 is between 1 and 10"))
|
||||
@@ -7527,7 +7587,9 @@
|
||||
(assert= false (eval-hs "10 is not between 1 and 10"))
|
||||
)
|
||||
(deftest "between works with strings"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= true (eval-hs "'b' is between 'a' and 'c'"))
|
||||
(assert= false (eval-hs "'d' is between 'a' and 'c'"))
|
||||
)
|
||||
(deftest "I am between works"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(deftest "I am not between works"
|
||||
@@ -7585,8 +7647,10 @@
|
||||
))
|
||||
(deftest "is really works without equal to"
|
||||
(assert= true (eval-hs "2 is really 2"))
|
||||
(assert= false (eval-hs "2 is really '2'"))
|
||||
)
|
||||
(deftest "is not really works without equal to"
|
||||
(assert= true (eval-hs "2 is not really '2'"))
|
||||
(assert= false (eval-hs "2 is not really 2"))
|
||||
)
|
||||
(deftest "is equal works without to"
|
||||
@@ -7667,8 +7731,7 @@
|
||||
;; ── in (1 tests) ──
|
||||
(defsuite "hs-upstream-in"
|
||||
(deftest "null value in array returns empty"
|
||||
;; toEqual: []
|
||||
)
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
)
|
||||
|
||||
;; ── logicalOperator (3 tests) ──
|
||||
@@ -7684,25 +7747,23 @@
|
||||
;; ── mathOperator (5 tests) ──
|
||||
(defsuite "hs-upstream-mathOperator"
|
||||
(deftest "array + array concats"
|
||||
;; toEqual: [1, 2, 3, 4]
|
||||
)
|
||||
(deftest "array + single value appends"
|
||||
;; toEqual: [1, 2, 3]
|
||||
)
|
||||
(deftest "array + array does not mutate original"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(deftest "array + single value appends"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(deftest "array + array does not mutate original"
|
||||
(assert= (list 1 2) (eval-hs "set a to [1, 2] then set b to a + [3] then return a"))
|
||||
)
|
||||
(deftest "array concat chains"
|
||||
;; toEqual: [1, 2, 3]
|
||||
)
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(deftest "empty array + array works"
|
||||
;; toEqual: [1, 2]
|
||||
)
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
)
|
||||
|
||||
;; ── no (5 tests) ──
|
||||
(defsuite "hs-upstream-no"
|
||||
(deftest "no returns false for non-empty array"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= false (eval-hs "no ['thing']"))
|
||||
)
|
||||
(deftest "no with where filters then checks emptiness"
|
||||
(assert= true (eval-hs "no [1, 2, 3] where it > 5"))
|
||||
)
|
||||
@@ -7710,7 +7771,8 @@
|
||||
(assert= false (eval-hs "no [1, 2, 3] where it > 1"))
|
||||
)
|
||||
(deftest "no with where and is not"
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
(assert= false (eval-hs "no [1, 2, 3] where it is not 2"))
|
||||
)
|
||||
(deftest "no with where on DOM elements"
|
||||
(hs-cleanup!)
|
||||
(let ((_el-box (dom-create-element "div")) (_el-button (dom-create-element "button")) (_el-out (dom-create-element "div")))
|
||||
@@ -7728,8 +7790,7 @@
|
||||
;; ── objectLiteral (1 tests) ──
|
||||
(defsuite "hs-upstream-objectLiteral"
|
||||
(deftest "allows trailing commas"
|
||||
;; toEqual: { "foo": true, "bar-baz": false }
|
||||
)
|
||||
(error "NOT IMPLEMENTED: test HTML could not be parsed into SX"))
|
||||
)
|
||||
|
||||
;; ── queryRef (1 tests) ──
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"failedTests": []
|
||||
"status": "failed",
|
||||
"failedTests": [
|
||||
"1c2c0c67218972a8b3e8-5ab09db25e2a06899363"
|
||||
]
|
||||
}
|
||||
@@ -508,37 +508,116 @@ def generate_test_pw(test, elements, var_names, idx):
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def js_val_to_sx(val):
|
||||
"""Convert a JS literal value to SX."""
|
||||
val = val.strip()
|
||||
if val == 'true': return 'true'
|
||||
if val == 'false': return 'false'
|
||||
if val in ('null', 'undefined'): return 'nil'
|
||||
if val.startswith('"') or val.startswith("'"):
|
||||
return '"' + val.strip("\"'") + '"'
|
||||
# Arrays: [1, 2, 3] → (list 1 2 3)
|
||||
if val.startswith('[') and val.endswith(']'):
|
||||
inner = val[1:-1].strip()
|
||||
if not inner:
|
||||
return '(list)'
|
||||
items = [js_val_to_sx(x.strip()) for x in split_top_level(inner)]
|
||||
return '(list ' + ' '.join(items) + ')'
|
||||
try:
|
||||
float(val)
|
||||
return val
|
||||
except ValueError:
|
||||
return f'"{val}"'
|
||||
|
||||
|
||||
def split_top_level(s):
|
||||
"""Split a string by commas, respecting brackets/quotes."""
|
||||
parts = []
|
||||
depth = 0
|
||||
current = []
|
||||
in_str = None
|
||||
for ch in s:
|
||||
if in_str:
|
||||
current.append(ch)
|
||||
if ch == in_str:
|
||||
in_str = None
|
||||
elif ch in ('"', "'"):
|
||||
in_str = ch
|
||||
current.append(ch)
|
||||
elif ch in ('(', '[', '{'):
|
||||
depth += 1
|
||||
current.append(ch)
|
||||
elif ch in (')', ']', '}'):
|
||||
depth -= 1
|
||||
current.append(ch)
|
||||
elif ch == ',' and depth == 0:
|
||||
parts.append(''.join(current))
|
||||
current = []
|
||||
else:
|
||||
current.append(ch)
|
||||
if current:
|
||||
parts.append(''.join(current))
|
||||
return parts
|
||||
|
||||
|
||||
def extract_hs_expr(raw):
|
||||
"""Clean a HS expression extracted from run() call."""
|
||||
# Remove surrounding whitespace and newlines
|
||||
expr = raw.strip().replace('\n', ' ').replace('\t', ' ')
|
||||
# Collapse multiple spaces
|
||||
expr = re.sub(r'\s+', ' ', expr)
|
||||
# Escape quotes for SX string
|
||||
expr = expr.replace('\\', '').replace('"', '\\"')
|
||||
return expr
|
||||
|
||||
|
||||
def generate_eval_only_test(test, idx):
|
||||
"""Generate SX deftest for no-HTML tests using eval-hs.
|
||||
Parses body field for run("expr").toBe(val) / expect(run("expr")).toBe(val) patterns."""
|
||||
Handles patterns:
|
||||
- run("expr").toBe(val)
|
||||
- expect(run("expr")).toBe(val)
|
||||
- var result = await run(`expr`); expect(result).toBe(val)
|
||||
- run("expr").toEqual([...])
|
||||
- run("expr").toThrow()
|
||||
"""
|
||||
body = test.get('body', '')
|
||||
lines = []
|
||||
lines.append(f' (deftest "{test["name"]}"')
|
||||
safe_name = test["name"].replace('"', "'")
|
||||
lines.append(f' (deftest "{safe_name}"')
|
||||
|
||||
# Extract run("expr").toBe(val) or expect(await run("expr")).toBe(val) patterns
|
||||
assertions = []
|
||||
for m in re.finditer(r'(?:expect\()?(?:await\s+)?run\(["\x27]([^"\x27]+)["\x27]\)\)?\.toBe\(([^)]+)\)', body):
|
||||
hs_expr = m.group(1).replace('\\', '').replace('"', '\\"')
|
||||
expected = m.group(2).strip()
|
||||
# Convert JS values to SX
|
||||
if expected == 'true': expected_sx = 'true'
|
||||
elif expected == 'false': expected_sx = 'false'
|
||||
elif expected == 'null' or expected == 'undefined': expected_sx = 'nil'
|
||||
elif expected.startswith('"') or expected.startswith("'"):
|
||||
expected_sx = '"' + expected.strip("\"'") + '"'
|
||||
else:
|
||||
try:
|
||||
float(expected)
|
||||
expected_sx = expected
|
||||
except ValueError:
|
||||
expected_sx = f'"{expected}"'
|
||||
|
||||
# Pattern 1: Inline — run("expr").toBe(val) or expect(run("expr")).toBe(val)
|
||||
for m in re.finditer(
|
||||
r'(?:expect\()?(?:await\s+)?run\((["\x27`])(.+?)\1\)\)?\.toBe\(([^)]+)\)',
|
||||
body, re.DOTALL
|
||||
):
|
||||
hs_expr = extract_hs_expr(m.group(2))
|
||||
expected_sx = js_val_to_sx(m.group(3))
|
||||
assertions.append(f' (assert= {expected_sx} (eval-hs "{hs_expr}"))')
|
||||
|
||||
# Also handle toEqual patterns
|
||||
for m in re.finditer(r'(?:expect\()?(?:await\s+)?run\(["\x27]([^"\x27]+)["\x27]\)\)?\.toEqual\(([^)]+)\)', body):
|
||||
hs_expr = m.group(1).replace('\\', '').replace('"', '\\"')
|
||||
expected = m.group(2).strip()
|
||||
assertions.append(f' ;; toEqual: {expected[:40]}')
|
||||
# Pattern 2: Two-line — var result = await run(`expr`); expect(result).toBe(val)
|
||||
if not assertions:
|
||||
run_match = re.search(
|
||||
r'(?:var|let|const)\s+\w+\s*=\s*(?:await\s+)?run\((["\x27`])(.+?)\1\)',
|
||||
body, re.DOTALL
|
||||
)
|
||||
if run_match:
|
||||
hs_expr = extract_hs_expr(run_match.group(2))
|
||||
for m in re.finditer(r'\.toBe\(([^)]+)\)', body):
|
||||
expected_sx = js_val_to_sx(m.group(1))
|
||||
assertions.append(f' (assert= {expected_sx} (eval-hs "{hs_expr}"))')
|
||||
for m in re.finditer(r'\.toEqual\((\[.*?\])\)', body, re.DOTALL):
|
||||
expected_sx = js_val_to_sx(m.group(1))
|
||||
assertions.append(f' (assert= {expected_sx} (eval-hs "{hs_expr}"))')
|
||||
|
||||
# Pattern 3: toThrow — expect(() => run("expr")).toThrow()
|
||||
for m in re.finditer(
|
||||
r'run\((["\x27`])(.+?)\1\).*?\.toThrow\(\)',
|
||||
body, re.DOTALL
|
||||
):
|
||||
hs_expr = extract_hs_expr(m.group(2))
|
||||
assertions.append(f' (assert-throws (eval-hs "{hs_expr}"))')
|
||||
|
||||
if not assertions:
|
||||
return None # Can't convert this body pattern
|
||||
|
||||
Reference in New Issue
Block a user