mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-04 00:23:53 +08:00
* docs: align page file names and nav labels with published URLs Signed-off-by: Johnny Greco <jogreco@nvidia.com> * docs: redirect moved dev pages and fix agent guide redirects Signed-off-by: Johnny Greco <jogreco@nvidia.com> * ci(docs): check that page URLs match their file paths Signed-off-by: Johnny Greco <jogreco@nvidia.com> * fix(docs): align navigation checks with repo conventions Signed-off-by: Johnny Greco <jogreco@nvidia.com> * docs: omit historical redirect aliases Signed-off-by: Johnny Greco <jogreco@nvidia.com> * fix(docs): preserve published overview and TypeScript URLs Signed-off-by: Johnny Greco <jogreco@nvidia.com> * fix(docs): redirect unversioned overview and TypeScript URLs Signed-off-by: Johnny Greco <jogreco@nvidia.com> --------- Signed-off-by: Johnny Greco <jogreco@nvidia.com>
243 lines
6.3 KiB
Python
243 lines
6.3 KiB
Python
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from __future__ import annotations
|
|
|
|
import textwrap
|
|
from typing import TYPE_CHECKING
|
|
|
|
import check_docs_nav
|
|
import pytest
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
FERN_CONFIG = """\
|
|
instances:
|
|
- url: example.docs.buildwithfern.com/openshell
|
|
versions:
|
|
- display-name: Dev
|
|
path: ../docs/index.yml
|
|
slug: dev
|
|
"""
|
|
|
|
|
|
def page(title: str, **extra: str) -> str:
|
|
lines = (
|
|
["---", f'title: "{title}"']
|
|
+ [f'{k}: "{v}"' for k, v in extra.items()]
|
|
+ ["---", ""]
|
|
)
|
|
return "\n".join(lines)
|
|
|
|
|
|
def build(tmp_path: Path, nav: str, pages: dict[str, str], redirects: str = "") -> Path:
|
|
docs = tmp_path / "docs"
|
|
for rel, content in pages.items():
|
|
(docs / rel).parent.mkdir(parents=True, exist_ok=True)
|
|
(docs / rel).write_text(content)
|
|
(docs / "index.yml").write_text(textwrap.dedent(nav))
|
|
(tmp_path / "fern").mkdir()
|
|
(tmp_path / "fern" / "docs.yml").write_text(
|
|
FERN_CONFIG + textwrap.dedent(redirects)
|
|
)
|
|
return tmp_path
|
|
|
|
|
|
def test_fern_slug_splits_camel_case() -> None:
|
|
assert check_docs_nav.fern_slug("TypeScript") == "type-script"
|
|
assert check_docs_nav.fern_slug("Why OpenShell") == "why-open-shell"
|
|
assert check_docs_nav.fern_slug("API Errors") == "api-errors"
|
|
assert check_docs_nav.fern_slug("0.1.0") == "0-1-0"
|
|
|
|
|
|
def test_matching_nav_passes(tmp_path: Path) -> None:
|
|
root = build(
|
|
tmp_path,
|
|
"""
|
|
navigation:
|
|
- section: "Guides"
|
|
slug: guides
|
|
path: guides/index.mdx
|
|
contents:
|
|
- page: "Setup"
|
|
path: guides/setup.mdx
|
|
- page: "Policy Prover"
|
|
path: guides/prover.mdx
|
|
slug: prover
|
|
""",
|
|
{
|
|
"guides/index.mdx": page("Guides"),
|
|
"guides/setup.mdx": page("Set Up", **{"sidebar-title": "Setup"}),
|
|
"guides/prover.mdx": page("Policy Prover"),
|
|
},
|
|
)
|
|
assert check_docs_nav.run(root) == []
|
|
|
|
|
|
def test_label_url_that_differs_from_file_path_fails(tmp_path: Path) -> None:
|
|
root = build(
|
|
tmp_path,
|
|
"""
|
|
navigation:
|
|
- section: "SDK"
|
|
slug: sdk
|
|
contents:
|
|
- page: "TypeScript"
|
|
path: sdk/typescript.mdx
|
|
""",
|
|
{"sdk/typescript.mdx": page("TypeScript")},
|
|
)
|
|
issues = check_docs_nav.run(root)
|
|
assert len(issues) == 1
|
|
assert "URL /sdk/type-script" in issues[0]
|
|
assert "relative slug in docs/index.yml" in issues[0]
|
|
|
|
|
|
def test_frontmatter_slug_can_pin_the_url_to_the_file_path(tmp_path: Path) -> None:
|
|
root = build(
|
|
tmp_path,
|
|
"""
|
|
navigation:
|
|
- section: "SDK"
|
|
slug: sdk
|
|
contents:
|
|
- page: "TypeScript"
|
|
path: sdk/typescript.mdx
|
|
""",
|
|
{"sdk/typescript.mdx": page("TypeScript", slug="sdk/typescript")},
|
|
)
|
|
assert check_docs_nav.run(root) == []
|
|
|
|
|
|
def test_sidebar_name_must_match_nav_label(tmp_path: Path) -> None:
|
|
root = build(
|
|
tmp_path,
|
|
"""
|
|
navigation:
|
|
- section: "About"
|
|
slug: about
|
|
contents:
|
|
- page: "Overview"
|
|
path: about/overview.mdx
|
|
""",
|
|
{"about/overview.mdx": page("Overview of the Product")},
|
|
)
|
|
issues = check_docs_nav.run(root)
|
|
assert issues == [
|
|
"about/overview.mdx: title 'Overview of the Product' does not match nav label 'Overview'"
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("nav", "rel"),
|
|
[
|
|
(
|
|
"""
|
|
navigation:
|
|
- section: Guides
|
|
slug: ignored
|
|
skip-slug: true
|
|
contents:
|
|
- page: Setup
|
|
path: setup.mdx
|
|
""",
|
|
"setup.mdx",
|
|
),
|
|
(
|
|
"""
|
|
navigation:
|
|
- section: Guides
|
|
contents:
|
|
- page: Setup
|
|
slug: ignored
|
|
skip-slug: true
|
|
path: guides/index.mdx
|
|
""",
|
|
"guides/index.mdx",
|
|
),
|
|
(
|
|
"""
|
|
navigation:
|
|
- section: Guides
|
|
contents:
|
|
- folder: guides
|
|
slug: ignored
|
|
skip-slug: true
|
|
""",
|
|
"guides/setup.mdx",
|
|
),
|
|
],
|
|
)
|
|
def test_skip_slug_omits_navigation_level(tmp_path: Path, nav: str, rel: str) -> None:
|
|
root = build(tmp_path, nav, {rel: page("Setup")})
|
|
assert check_docs_nav.run(root) == []
|
|
|
|
|
|
def test_skip_slug_detects_url_that_differs_from_file_path(tmp_path: Path) -> None:
|
|
root = build(
|
|
tmp_path,
|
|
"""
|
|
navigation:
|
|
- section: Guides
|
|
skip-slug: true
|
|
contents:
|
|
- page: Setup
|
|
path: guides/setup.mdx
|
|
""",
|
|
{"guides/setup.mdx": page("Setup")},
|
|
)
|
|
issues = check_docs_nav.run(root)
|
|
assert len(issues) == 1
|
|
assert "URL /setup" in issues[0]
|
|
assert "does not match its file path /guides/setup" in issues[0]
|
|
|
|
|
|
def test_folder_pages_use_file_names_and_orphans_fail(tmp_path: Path) -> None:
|
|
root = build(
|
|
tmp_path,
|
|
"""
|
|
navigation:
|
|
- folder: kubernetes
|
|
title: "Kubernetes"
|
|
""",
|
|
{
|
|
"kubernetes/openshift.mdx": page("OpenShift"),
|
|
"stray.mdx": page("Stray"),
|
|
},
|
|
)
|
|
assert check_docs_nav.run(root) == ["stray.mdx: not reachable from docs/index.yml"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("redirect", "expected"),
|
|
[
|
|
(
|
|
' - source: "/openshell/dev/old"\n destination: "/openshell/dev/missing"\n',
|
|
"destination does not exist",
|
|
),
|
|
(
|
|
' - source: "/openshell/dev/guides/setup"\n destination: "/openshell/dev/guides/setup"\n',
|
|
"is still a live page",
|
|
),
|
|
],
|
|
)
|
|
def test_dev_redirects_must_point_to_live_pages(
|
|
tmp_path: Path, redirect: str, expected: str
|
|
) -> None:
|
|
root = build(
|
|
tmp_path,
|
|
"""
|
|
navigation:
|
|
- section: "Guides"
|
|
slug: guides
|
|
contents:
|
|
- page: "Setup"
|
|
path: guides/setup.mdx
|
|
""",
|
|
{"guides/setup.mdx": page("Setup")},
|
|
"redirects:\n" + redirect,
|
|
)
|
|
issues = check_docs_nav.run(root)
|
|
assert len(issues) == 1 and expected in issues[0]
|