WebHost: fix links on sitemap, switch to url_for and add test to prevent future breakage (#5318)

This commit is contained in:
Fabian Dill
2025-08-12 16:52:34 +02:00
committed by GitHub
parent 378cc91a4d
commit 9057ce0ce3
3 changed files with 92 additions and 24 deletions

View File

@@ -11,32 +11,32 @@
<h1>Site Map</h1>
<h2>Base Pages</h2>
<ul>
<li><a href="/discord">Discord Link</a></li>
<li><a href="/faq/en">F.A.Q. Page</a></li>
<li><a href="/favicon.ico">Favicon</a></li>
<li><a href="/generate">Generate Game Page</a></li>
<li><a href="/">Homepage</a></li>
<li><a href="/uploads">Host Game Page</a></li>
<li><a href="/datapackage">Raw Data Package</a></li>
<li><a href="{{ url_for('check')}}">Settings Validator</a></li>
<li><a href="/sitemap">Site Map</a></li>
<li><a href="/start-playing">Start Playing</a></li>
<li><a href="/games">Supported Games Page</a></li>
<li><a href="/tutorial">Tutorials Page</a></li>
<li><a href="/user-content">User Content</a></li>
<li><a href="{{url_for('stats')}}">Game Statistics</a></li>
<li><a href="/glossary/en">Glossary</a></li>
<li><a href="{{url_for("show_session")}}">Session / Login</a></li>
<li><a href="{{ url_for('discord') }}">Discord Link</a></li>
<li><a href="{{ url_for('faq', lang='en') }}">F.A.Q. Page</a></li>
<li><a href="{{ url_for('favicon') }}">Favicon</a></li>
<li><a href="{{ url_for('generate') }}">Generate Game Page</a></li>
<li><a href="{{ url_for('landing') }}">Homepage</a></li>
<li><a href="{{ url_for('uploads') }}">Host Game Page</a></li>
<li><a href="{{ url_for('get_datapackage') }}">Raw Data Package</a></li>
<li><a href="{{ url_for('check') }}">Settings Validator</a></li>
<li><a href="{{ url_for('get_sitemap') }}">Site Map</a></li>
<li><a href="{{ url_for('start_playing') }}">Start Playing</a></li>
<li><a href="{{ url_for('games') }}">Supported Games Page</a></li>
<li><a href="{{ url_for('tutorial_landing') }}">Tutorials Page</a></li>
<li><a href="{{ url_for('user_content') }}">User Content</a></li>
<li><a href="{{ url_for('stats') }}">Game Statistics</a></li>
<li><a href="{{ url_for('glossary', lang='en') }}">Glossary</a></li>
<li><a href="{{ url_for('show_session') }}">Session / Login</a></li>
</ul>
<h2>Tutorials</h2>
<ul>
<li><a href="/tutorial/Archipelago/setup/en">Multiworld Setup Tutorial</a></li>
<li><a href="/tutorial/Archipelago/mac/en">Setup Guide for Mac</a></li>
<li><a href="/tutorial/Archipelago/commands/en">Server and Client Commands</a></li>
<li><a href="/tutorial/Archipelago/advanced_settings/en">Advanced YAML Guide</a></li>
<li><a href="/tutorial/Archipelago/triggers/en">Triggers Guide</a></li>
<li><a href="/tutorial/Archipelago/plando/en">Plando Guide</a></li>
<li><a href="{{ url_for('tutorial', game='Archipelago', file='setup_en') }}">Multiworld Setup Tutorial</a></li>
<li><a href="{{ url_for('tutorial', game='Archipelago', file='mac_en') }}">Setup Guide for Mac</a></li>
<li><a href="{{ url_for('tutorial', game='Archipelago', file='commands_en') }}">Server and Client Commands</a></li>
<li><a href="{{ url_for('tutorial', game='Archipelago', file='advanced_settings_en') }}">Advanced YAML Guide</a></li>
<li><a href="{{ url_for('tutorial', game='Archipelago', file='triggers_en') }}">Triggers Guide</a></li>
<li><a href="{{ url_for('tutorial', game='Archipelago', file='plando_en') }}">Plando Guide</a></li>
</ul>
<h2>Game Info Pages</h2>

View File

@@ -3,7 +3,7 @@ from typing import List, Optional, Tuple, Type, Union
from BaseClasses import CollectionState, Item, ItemClassification, Location, MultiWorld, Region
from worlds import network_data_package
from worlds.AutoWorld import World, call_all
from worlds.AutoWorld import World, WebWorld, call_all
gen_steps = (
"generate_early",
@@ -17,7 +17,7 @@ gen_steps = (
def setup_solo_multiworld(
world_type: Type[World], steps: Tuple[str, ...] = gen_steps, seed: Optional[int] = None
world_type: Type[World], steps: Tuple[str, ...] = gen_steps, seed: Optional[int] = None
) -> MultiWorld:
"""
Creates a multiworld with a single player of `world_type`, sets default options, and calls provided gen steps.
@@ -62,11 +62,16 @@ def setup_multiworld(worlds: Union[List[Type[World]], Type[World]], steps: Tuple
return multiworld
class TestWebWorld(WebWorld):
tutorials = []
class TestWorld(World):
game = f"Test Game"
item_name_to_id = {}
location_name_to_id = {}
hidden = True
web = TestWebWorld()
# add our test world to the data package, so we can test it later

View File

@@ -0,0 +1,63 @@
import urllib.parse
import html
import re
from flask import url_for
import WebHost
from . import TestBase
class TestSitemap(TestBase):
# Codes for OK and some redirects that we use
valid_status_codes = [200, 302, 308]
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
WebHost.copy_tutorials_files_to_static()
def test_sitemap_route(self) -> None:
"""Verify that the sitemap route works correctly and renders the template without errors."""
with self.app.test_request_context():
# Test the /sitemap route
with self.client.open("/sitemap") as response:
self.assertEqual(response.status_code, 200)
self.assertIn(b"Site Map", response.data)
# Test the /index route which should also serve the sitemap
with self.client.open("/index") as response:
self.assertEqual(response.status_code, 200)
self.assertIn(b"Site Map", response.data)
# Test using url_for with the function name
with self.client.open(url_for('get_sitemap')) as response:
self.assertEqual(response.status_code, 200)
self.assertIn(b'Site Map', response.data)
def test_sitemap_links(self) -> None:
"""
Verify that all links in the sitemap are valid by making a request to each one.
"""
with self.app.test_request_context():
with self.client.open(url_for("get_sitemap")) as response:
self.assertEqual(response.status_code, 200)
html_content = response.data.decode()
# Extract all href links using regex
href_pattern = re.compile(r'href=["\'](.*?)["\']')
links = href_pattern.findall(html_content)
self.assertTrue(len(links) > 0, "No links found in sitemap")
# Test each link
for link in links:
# Skip external links
if link.startswith(("http://", "https://")):
continue
link = urllib.parse.unquote(html.unescape(link))
with self.client.open(link) as response, self.subTest(link=link):
self.assertIn(response.status_code, self.valid_status_codes,
f"Link {link} returned invalid status code {response.status_code}")