import base64 import io import json import os import runpy import zipfile from fastapi.testclient import TestClient from docslib import HeaderButton, __version__, build from docslib.components import H1, Image, P from docslib.hooks import Page from docslib.server import create_app def test_all_endpoints_and_self_contained_build(tmp_path): assets = tmp_path / "assets" assets.mkdir() image_bytes = b"not-a-real-png-but-good-enough-for-encoding" (assets / "hero.png").write_bytes(image_bytes) custom_css = tmp_path / "inject.css" custom_css.write_text(".content { --custom-test: yes; }", encoding="utf-8") custom_js = tmp_path / "inject.js" custom_js.write_text('document.body.dataset.customTest = "yes";', encoding="utf-8") @Page("1.1", "Child") def child(): return P("Second page") @Page("1.", "Home") def home(): return [H1("Welcome"), Image("hero.png", "Hero")] app = create_app( title="Test docs", assets_dir=assets, custom_css=custom_css, custom_js=custom_js, manifest_path="http://127.0.0.1:9000/", header_buttons=[ HeaderButton("Home", home), HeaderButton.local("Child", "Child", section="1"), HeaderButton.external("Source", "https://example.com"), {"label": "Download", "href": "/index.zip"}, ], ) client = TestClient(app) manifest_response = client.get("/manifest.json") assert manifest_response.status_code == 200 manifest = manifest_response.json() assert [page["number"] for page in manifest["pages"]] == ["1", "1.1"] assert manifest["assets"]["hero.png"]["data"] == base64.b64encode(image_bytes).decode() assert manifest["schema_version"] == 2 assert "html, body { width: 100%; height: 100dvh" in manifest["client"]["css"]["system"] assert manifest["client"]["css"]["custom"] == ".content { --custom-test: yes; }" assert "placeholderTick" in manifest["client"]["js"]["system"] assert manifest["client"]["js"]["custom"] == 'document.body.dataset.customTest = "yes";' assert len(manifest["revision"]) == 20 assert manifest["ui"]["header_buttons"] == [ {"label": "Home", "page": "1"}, {"label": "Child", "page": "1.1"}, {"label": "Source", "href": "https://example.com", "target": "_blank"}, {"label": "Download", "href": "/index.zip"}, ] assert manifest_response.headers["cache-control"] == "no-store" html_response = client.get("/index.html") html = html_response.text assert html_response.status_code == 200 assert "http://127.0.0.1:9000/manifest.json" in html assert ".content { --custom-test: yes; }" in html assert r'document.body.dataset.customTest = \"yes\";' in html assert 'id="docslib-loading"' in html assert "position: fixed; inset: 0; z-index: 2147483647; width: 100vw; height: 100dvh; background: #808080" in html assert 'id="docslib-loader-style"' in html assert "docslib:rendered" in html assert "docslib-runtime-style" in html assert "indexedDB.open" in html assert "link.dataset.page = button.page" in html assert 'class="brand-mark"' not in html assert ">Knowledge base<" not in html assert ">Search<" not in html assert ">Ctrl K<" not in html assert ">Up to date<" not in html assert "manifestIdentity" in html assert "100dvh" in html assert "100vh" not in html assert "html, body { width: 100%; height: 100dvh" in html assert "min-height: calc(100dvh - 240px)" not in html assert "overflow-y: auto" in html assert "flex: 1 1 auto; flex-direction: column" in html assert "padding: 0 18px 22px" in html assert "--desktop-sidebar-width: clamp(270px, 25vw, 400px)" in html assert "--selection-bg: #111111" in html assert "--selection-bg: #f0f0f0" in html assert ".mobile-menu-view .tree-link.active { color: var(--selection-text); background: var(--selection-bg); }" in html assert "--elevated: #d4d4d4" in html assert "--shadow: 0 24px 70px rgba(0, 0, 0, .4)" in html assert "elements.pageSurface.scrollTo" in html assert "font-family: system-ui; font-size: 16px" in html assert ".glyph-button, .refresh-glyph { font-family: Arial" in html assert ".nav-arrow { font-family: system-ui; }" in html assert "--shell: #000000" in html assert 'id="desktop-search-input"' in html assert '
' in html assert '