from __future__ import annotations from core.extractor import ExpressionExtractor def test_extract_fraction_derivative_and_order(): extractor = ExpressionExtractor() inner, params = extractor.extract(r"\frac{d^5}{dx^5} x^3") assert inner == "x^3" assert params["variable"] == "x" assert params["order"] == 5 def test_extract_plain_derivative_notation(): extractor = ExpressionExtractor() inner, params = extractor.extract("d^2/dx^2 sin(x)") assert inner == "sin(x)" assert params["variable"] == "x" assert params["order"] == 2 def test_extract_definite_integral_and_bounds(): extractor = ExpressionExtractor() inner, params = extractor.extract(r"\int_{0}^{1} x^2 dx") assert inner == "x^2" assert params["lower"] == 0 assert params["upper"] == 1 assert params["variable"] == "x" def test_extract_limit_plain_text_arrow_unicode(): extractor = ExpressionExtractor() inner, params = extractor.extract("lim_(x → ∞) (1+(1)/(x))^x") assert inner == "(1+(1)/(x))^x" assert params["variable"] == "x" assert params["point"] == "∞" def test_extract_returns_original_when_no_wrapper_found(): extractor = ExpressionExtractor() latex = "x^2 + 3x + 2" inner, params = extractor.extract(latex, params={"variable": "x"}) assert inner == latex assert params["variable"] == "x" def test_parse_bound_infinity_tokens(): assert ExpressionExtractor._parse_bound(r"\infty") == "oo" assert ExpressionExtractor._parse_bound(r"-\infty") == "-oo" assert ExpressionExtractor._parse_bound("2.5") == 2.5 def test_extract_partial_derivative_branch(): extractor = ExpressionExtractor() inner, params = extractor.extract(r"\frac{\partial^2}{\partial x^2} (x^2 y)") assert inner == "(x^2 y)" assert params["variable"] == "x" assert params["order"] == 2 def test_extract_prime_notation_branch(): extractor = ExpressionExtractor() inner, params = extractor.extract("y''(t)") assert inner == "y''(t)" assert params["variable"] == "t" assert params["order"] == 2 def test_extract_definite_integral_non_braced_pattern(): extractor = ExpressionExtractor() inner, params = extractor.extract(r"\int_0^1 x^2 dx") assert inner == "x^2" assert params["lower"] == 0 assert params["upper"] == 1 assert params["variable"] == "x" def test_extract_plain_integral_patterns(): extractor = ExpressionExtractor() inner1, p1 = extractor.extract("int_0^2 x dx") assert inner1 == "x" assert p1["lower"] == 0 and p1["upper"] == 2 and p1["variable"] == "x" inner2, p2 = extractor.extract("∫ x^2 dx") assert inner2 == "x^2" assert p2["variable"] == "x" def test_extract_limit_latex_and_plain_variants(): extractor = ExpressionExtractor() inner1, p1 = extractor.extract(r"\lim_{x \to 0} \frac{\sin x}{x}") assert p1["variable"] == "x" and p1["point"] == "0" assert inner1 == r"\frac{\sin x}{x}" inner2, p2 = extractor.extract("lim x->0 sin(x)/x") assert p2["variable"] == "x" and p2["point"] == "0" assert inner2 == "sin(x)/x" inner3, p3 = extractor.extract("lim x to 0 sin(x)/x") assert p3["variable"] == "x" and p3["point"] == "0" assert inner3 == "sin(x)/x" def test_extract_sum_branch(): extractor = ExpressionExtractor() inner, params = extractor.extract(r"\sum_{n=1}^{10} n^2") assert "n^2" in inner assert params["variable"] == "n" assert params["lower"] == 1 # Current extractor regex does not capture upper bound robustly for this form. # Keep this as a branch-coverage regression guard. assert "upper" in params def test_extract_indefinite_integral_latex_branch(): extractor = ExpressionExtractor() inner, params = extractor.extract(r"\int x^3 dx") assert inner == "x^3" assert params["variable"] == "x"