import pytest from mdgrep import Block, SearchEngine from mdgrep.web import create_app BLOCKS = [ Block("1", "rust news", title="Rust", meta={"lang": "en", "url": "u1", "markdown": "**rust**"}), Block("2", "rust nachrichten", title="Rust", meta={"lang": "de", "url": "u1", "markdown": "x"}), Block("3", "go news", title="Go", meta={"lang": "en", "url": "u2", "markdown": "y"}), Block("4", "rust again", title="Rust", meta={"lang": "en", "url": "u1", "markdown": "z"}), ] @pytest.fixture def client(): app = create_app(SearchEngine(BLOCKS), filters=["lang"], group_by=lambda b: (b.meta["lang"], b.meta["url"])) return app.test_client() def test_search_ok(client): data = client.get("/search?q=rust").get_json() assert data["total_blocks"] == 3 and data["total_groups"] == 2 first = data["results"][0] assert first["block"]["id"] == "1" and [b["id"] for b in first["also"]] == ["4"] assert "markdown" not in first["block"]["meta"] assert "markdown" not in first["also"][0]["meta"] def test_filters(client): assert client.get("/search?q=rust&lang=de").get_json()["total_blocks"] == 1 assert client.get("/search?q=rust&lang=all").get_json()["total_blocks"] == 3 assert client.get("/search?q=rust&lang=de,en").get_json()["total_blocks"] == 3 def test_paging_and_limit_clamping(client): data = client.get("/search?q=news OR rust&limit=1").get_json() assert len(data["results"]) == 1 and data["next_offset"] == 1 data = client.get("/search?q=rust&limit=9999&offset=-5").get_json() assert data["limit"] == 100 and data["offset"] == 0 def test_empty_query(client): data = client.get("/search?q=").get_json() assert data["results"] == [] and data["total_groups"] == 0 def test_syntax_error_400(client): resp = client.get("/search?q=(rust") assert resp.status_code == 400 assert resp.get_json()["error"] == {"code": "unclosed_paren", "message": "Missing closing parenthesis", "position": 0} def test_too_long_query(client): resp = client.get("/search?q=" + "a" * 400) assert resp.status_code == 400 and resp.get_json()["error"]["code"] == "too_long" def test_unicode_not_escaped(client): app = create_app(SearchEngine([Block("x", "Größe")])) body = app.test_client().get("/search?q=größe").get_data(as_text=True) assert "Größe" in body def test_widget_assets_served(client): assert client.get("/mdgrep-static/mdgrep-widget.js").status_code == 200 assert client.get("/mdgrep-static/mdgrep-widget.css").status_code == 200 def test_static_dir_and_prefix(tmp_path): (tmp_path / "index.html").write_text("

home

") (tmp_path / "sub").mkdir() (tmp_path / "sub" / "index.html").write_text("sub page") app = create_app(SearchEngine(BLOCKS), url_prefix="/api", static_dir=tmp_path) c = app.test_client() assert c.get("/").get_data(as_text=True) == "

home

" assert c.get("/sub/").get_data(as_text=True) == "sub page" assert c.get("/api/search?q=go").get_json()["total_blocks"] == 1 assert c.get("/../etc/passwd").status_code == 404