blob: 1d777b1e1fad9761bf355a68ccf0e33179bed33c [file]
# Copyright 2026 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Tests for dev.js (local development and staging preview utilities)."""
import unittest
from helpers import (
DocsServer,
get_chromium_executable,
get_docs_dir,
)
from playwright.sync_api import sync_playwright
class DevTest(unittest.TestCase):
"""Client-side URL rewriter tests."""
@classmethod
def setUpClass(cls):
cls.docs_dir = get_docs_dir()
cls.server = DocsServer(cls.docs_dir)
cls.server.start()
@classmethod
def tearDownClass(cls):
cls.server.stop()
def test_header_links_rewritten(self):
"""Verifies that top-level header links have absolute pigweed.dev URLs
rewritten to relative paths."""
chromium_bin = get_chromium_executable()
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=chromium_bin,
headless=True,
)
context = browser.new_context(
viewport={"width": 1280, "height": 800}
)
page = context.new_page()
page.goto(
self.server.url_for("pw_analog/docs.html"),
wait_until="domcontentloaded",
)
# Brand link in header
brand_link = page.locator("#pw-header-brand a").first
brand_link.wait_for(state="attached", timeout=5000)
href = brand_link.get_attribute("href")
self.assertIsNotNone(href)
self.assertEqual(
href,
"../index.html",
f"Brand link should be rewritten to '../index.html', got '{href}'",
)
browser.close()
def test_sidebar_api_links_rewritten(self):
"""Verifies that links inside the primary sidebar (such as C/C++ API
references) have absolute pigweed.dev URLs rewritten to relative
paths."""
chromium_bin = get_chromium_executable()
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=chromium_bin,
headless=True,
)
context = browser.new_context(
viewport={"width": 1280, "height": 800}
)
page = context.new_page()
page.goto(
self.server.url_for("pw_analog/docs.html"),
wait_until="domcontentloaded",
)
# Find C/C++ API reference link in #pst-primary-sidebar / .bd-sidebar-primary
sidebar_link = page.locator(
'.bd-sidebar-primary a[href*="group__pw__analog"]'
).first
sidebar_link.wait_for(state="attached", timeout=5000)
href = sidebar_link.get_attribute("href")
self.assertIsNotNone(href)
self.assertFalse(
href.startswith("https://pigweed.dev/"),
f"Sidebar link href '{href}' should not start with https://pigweed.dev/",
)
self.assertTrue(
href.startswith("../") or href.startswith("./"),
f"Sidebar link href '{href}' should be rewritten to relative path",
)
browser.close()
def test_rustdoc_main_content_link_rewritten(self):
"""Verifies that links within main content on Rustdoc pages (e.g.
'Pigweed Homepage' on rustdoc/pigweed/index.html) have absolute
pigweed.dev URLs rewritten to relative paths."""
chromium_bin = get_chromium_executable()
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=chromium_bin,
headless=True,
)
context = browser.new_context(
viewport={"width": 1280, "height": 800}
)
page = context.new_page()
page.goto(
self.server.url_for("rustdoc/pigweed/index.html"),
wait_until="domcontentloaded",
)
# Find 'Pigweed Homepage' link within main content
link = page.locator('main a:has-text("Pigweed Homepage")').first
link.wait_for(state="attached", timeout=5000)
href = link.get_attribute("href")
self.assertIsNotNone(href)
self.assertFalse(
href.startswith("https://pigweed.dev/"),
f"Rustdoc main content link href '{href}' should not start with https://pigweed.dev/",
)
browser.close()
def test_section_directory_urls_not_truncated(self):
"""Verifies that section directory URLs ending in '/' are rewritten to
their corresponding index.html without truncating the section path."""
chromium_bin = get_chromium_executable()
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=chromium_bin,
headless=True,
)
context = browser.new_context(
viewport={"width": 1280, "height": 800}
)
page = context.new_page()
# Test on nested subpage (root is '../')
page.goto(
self.server.url_for("pw_bytes/docs.html"),
wait_until="domcontentloaded",
)
results = page.evaluate(
"""() => {
const testCases = [
{ input: 'https://pigweed.dev/contributing/', expected: '../contributing/index.html' },
{ input: 'https://pigweed.dev/contributing/#guidelines', expected: '../contributing/index.html#guidelines' },
{ input: 'https://pigweed.dev/docs/build/', expected: '../docs/build/index.html' },
{ input: 'https://pigweed.dev/', expected: '../index.html' },
{ input: 'https://pigweed.dev/index.html', expected: '../index.html' },
{ input: 'https://pigweed.dev/search.html?q=test', expected: '../search.html?q=test' },
];
return testCases.map(tc => {
const a = document.createElement('a');
a.setAttribute('href', tc.input);
document.body.appendChild(a);
rewriteUrls();
const actual = a.getAttribute('href');
a.remove();
return { input: tc.input, actual, expected: tc.expected };
});
}"""
)
for res in results:
self.assertEqual(
res["actual"],
res["expected"],
f"Failed rewrite for {res['input']}: expected {res['expected']}, got {res['actual']}",
)
# Test on root page (root is './')
page.goto(
self.server.url_for("index.html"),
wait_until="domcontentloaded",
)
root_results = page.evaluate(
"""() => {
const testCases = [
{ input: 'https://pigweed.dev/contributing/', expected: './contributing/index.html' },
{ input: 'https://pigweed.dev/contributing/#guidelines', expected: './contributing/index.html#guidelines' },
{ input: 'https://pigweed.dev/', expected: './index.html' },
];
return testCases.map(tc => {
const a = document.createElement('a');
a.setAttribute('href', tc.input);
document.body.appendChild(a);
rewriteUrls();
const actual = a.getAttribute('href');
a.remove();
return { input: tc.input, actual, expected: tc.expected };
});
}"""
)
for res in root_results:
self.assertEqual(
res["actual"],
res["expected"],
f"Failed root rewrite for {res['input']}: expected {res['expected']}, got {res['actual']}",
)
browser.close()
if __name__ == "__main__":
unittest.main()