import tempfile import unittest from pathlib import Path from app import create_app from boker.auth import hash_password from boker.db import db class SeoTests(unittest.TestCase): def setUp(self): self.tmpdir = tempfile.TemporaryDirectory() db_path = Path(self.tmpdir.name) / "test.sqlite3" self.app = create_app( { "TESTING": True, "APP_BASE_URL": "https://myboker.org", "SQLALCHEMY_DATABASE_URI": f"sqlite:///{db_path}", } ) self.client = self.app.test_client() with self.app.app_context(): db.create_all() def tearDown(self): with self.app.app_context(): db.session.remove() db.drop_all() db.engine.dispose() self.tmpdir.cleanup() def test_landing_page_has_search_metadata(self): response = self.client.get("/") html = response.get_data(as_text=True) self.assertEqual(response.status_code, 200) self.assertIn("Free Home Poker Tracker, Ledger & League Leaderboards", html) self.assertIn('name="description"', html) self.assertIn("Track home poker sessions, buy-ins, cashouts, settlements", html) self.assertIn('rel="canonical" href="https://myboker.org/"', html) self.assertIn('application/ld+json', html) def test_robots_txt_allows_public_crawling_and_points_to_sitemap(self): response = self.client.get("/robots.txt") body = response.get_data(as_text=True) self.assertEqual(response.status_code, 200) self.assertEqual(response.mimetype, "text/plain") self.assertIn("Allow: /", body) self.assertIn("Disallow: /internal/", body) self.assertIn("Disallow: /account/", body) self.assertIn("Sitemap: https://myboker.org/sitemap.xml", body) def test_sitemap_xml_lists_public_static_pages(self): response = self.client.get("/sitemap.xml") body = response.get_data(as_text=True) self.assertEqual(response.status_code, 200) self.assertEqual(response.mimetype, "application/xml") self.assertIn("https://myboker.org/", body) self.assertIn("https://myboker.org/explore", body) self.assertIn("https://myboker.org/help", body) def test_explore_requires_search_before_showing_public_leagues(self): with self.app.app_context(): from boker.db_models import League, User owner = User(email="owner@example.com", password_hash=hash_password("password123")) db.session.add(owner) db.session.flush() league = League( name="Friday Night Poker", slug="friday-night-poker", public_key="friday1", created_by_user_id=owner.id, visibility="public", ) db.session.add(league) db.session.commit() default_response = self.client.get("/explore") default_html = default_response.get_data(as_text=True) search_response = self.client.get("/explore?q=Friday") search_html = search_response.get_data(as_text=True) sitemap_response = self.client.get("/sitemap.xml") sitemap_xml = sitemap_response.get_data(as_text=True) self.assertEqual(default_response.status_code, 200) self.assertIn("Enter a league name to search", default_html) self.assertNotIn("Friday Night Poker", default_html) self.assertEqual(search_response.status_code, 200) self.assertIn("Friday Night Poker", search_html) self.assertNotIn("/l/friday-night-poker-friday1", sitemap_xml) def test_explore_search_handles_missing_database_tables(self): with tempfile.TemporaryDirectory() as tmpdir: db_path = Path(tmpdir) / "missing-tables.sqlite3" app = create_app( { "TESTING": True, "SQLALCHEMY_DATABASE_URI": f"sqlite:///{db_path}", } ) client = app.test_client() response = client.get("/explore?q=Friday") with app.app_context(): db.session.remove() db.engine.dispose() html = response.get_data(as_text=True) self.assertEqual(response.status_code, 200) self.assertIn("No public leagues found", html) if __name__ == "__main__": unittest.main()