117 lines
4.2 KiB
Python
117 lines
4.2 KiB
Python
import base64
|
|
import io
|
|
import json
|
|
import os
|
|
import runpy
|
|
import zipfile
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from docslib import HeaderButton
|
|
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")
|
|
|
|
@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,
|
|
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 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 "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 "overflow-y: auto" in html
|
|
assert "document.body.append(elements.headerActions)" in html
|
|
assert "elements.workspace.scrollTo" in html
|
|
assert "--bg: #000000" in html
|
|
assert "--accent: #ffffff" in html
|
|
assert 'id="header-actions"' in html
|
|
assert 'id="actions-overlay"' in html
|
|
assert "<script src=" not in html
|
|
assert "<link rel=" not in html
|
|
|
|
zip_response = client.get("/index.zip")
|
|
assert zip_response.status_code == 200
|
|
with zipfile.ZipFile(io.BytesIO(zip_response.content)) as archive:
|
|
assert archive.namelist() == ["index.html"]
|
|
assert archive.read("index.html") == html_response.content
|
|
|
|
assert client.get("/live").status_code == 404
|
|
|
|
|
|
def test_live_preview_reloads_a_changed_main_source(tmp_path):
|
|
source = tmp_path / "docs.py"
|
|
source.write_text(
|
|
'from docslib.hooks import Page\n@Page("1", "Live")\ndef page(): return "<p>one</p>"\n',
|
|
encoding="utf-8",
|
|
)
|
|
runpy.run_path(str(source), run_name="__main__")
|
|
client = TestClient(create_app(live_preview=True))
|
|
initial = client.get("/manifest.json").json()
|
|
assert "one" in initial["pages"][0]["content"]
|
|
|
|
source.write_text(
|
|
'from docslib.hooks import Page\n@Page("1", "Live")\ndef page(): return "<p>two</p>"\n',
|
|
encoding="utf-8",
|
|
)
|
|
stat = source.stat()
|
|
os.utime(source, ns=(stat.st_atime_ns, stat.st_mtime_ns + 1_000_000_000))
|
|
|
|
live = client.get("/live").json()
|
|
assert live["changed"] is True
|
|
assert live["error"] is None
|
|
assert live["revision"] != initial["revision"]
|
|
assert "two" in client.get("/manifest.json").json()["pages"][0]["content"]
|