- Standardize Next.js Metadata and dynamic generateMetadata across all subpages - Fix duplicate main landmark in publications page by replacing nested main with div - Unify Members page spacing (space-y-10 sm:space-y-14, pt-6 md:pt-8) and responsive H2s - Add aria-label and focus ring to CategoryNav View All links for a11y - Derive dynamic course history semester ranges in Lectures page - Add 3 comprehensive E2E test cases (test_08, test_09, test_10) for highlights, active border, CITE brand links, and English H1 headers
177 lines
7.6 KiB
Python
177 lines
7.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Python Unittest Suite for ANL Homepage E2E Verification
|
|
Parses prerendered SSG HTML files to assert DOM structure, text content, and theme attributes.
|
|
"""
|
|
|
|
import unittest
|
|
import os
|
|
import re
|
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
SERVER_APP_DIR = os.path.join(BASE_DIR, ".next", "server", "app")
|
|
if not os.path.exists(SERVER_APP_DIR):
|
|
for candidate in [
|
|
os.path.join(os.getcwd(), "refer_landing_page", ".next", "server", "app"),
|
|
os.path.join(os.getcwd(), "website", ".next", "server", "app"),
|
|
os.path.join(os.getcwd(), ".next", "server", "app"),
|
|
]:
|
|
if os.path.exists(candidate):
|
|
SERVER_APP_DIR = candidate
|
|
break
|
|
|
|
class TestANLHomepageE2E(unittest.TestCase):
|
|
|
|
def read_html(self, relative_path):
|
|
full_path = os.path.join(SERVER_APP_DIR, relative_path)
|
|
self.assertTrue(os.path.exists(full_path), f"File {relative_path} does not exist")
|
|
with open(full_path, "r", encoding="utf-8") as f:
|
|
return f.read()
|
|
|
|
def test_01_home_page_structure(self):
|
|
"""TC-T1-F3: Verify Home page SSG HTML content and semantic structures."""
|
|
html = self.read_html("index.html")
|
|
|
|
# 1. Brand & Header titles
|
|
self.assertIn("ANL", html)
|
|
self.assertIn("AI Agent Networking LAB", html)
|
|
|
|
# 2. Research Areas keywords
|
|
self.assertIn("Quick UDP Internet Connection (QUIC)", html)
|
|
self.assertIn("Constrained Application Protocol (CoAP)", html)
|
|
self.assertIn("Stream Control Transmission Protocol (SCTP)", html)
|
|
self.assertIn("Tabu Search and Genetic Algorithm", html)
|
|
|
|
# 3. Location / Address section
|
|
self.assertIn("address", html.lower())
|
|
self.assertIn("Kyungpook National University", html)
|
|
self.assertIn("College of IT Engineering", html)
|
|
self.assertIn("Prof. Seok-Joo Koh", html)
|
|
self.assertIn("sjkoh@knu.ac.kr", html)
|
|
|
|
def test_02_members_page_content(self):
|
|
"""TC-T1-F4: Verify Members page active members & alumni records."""
|
|
html = self.read_html("members.html")
|
|
|
|
# Professor profile
|
|
self.assertIn("Prof. Seok-Joo Koh", html)
|
|
self.assertIn("Seok-Joo Koh", html)
|
|
self.assertIn("sjkoh@knu.ac.kr", html)
|
|
|
|
# Sections & Degree formatting checks
|
|
self.assertIn("LAB MEMBERS", html)
|
|
self.assertIn("Active Researchers", html)
|
|
self.assertIn("Graduates", html)
|
|
self.assertIn("Ph. D. Candidate", html)
|
|
self.assertIn("Project Editor", html)
|
|
|
|
def test_03_publications_category_routes(self):
|
|
"""TC-T1-F5: Verify Publications categories SSG static pages."""
|
|
cats = [
|
|
("intl-journal-conf.html", "International Journal"),
|
|
("domestic-journal-conf.html", "Domestic Journal"),
|
|
("patent.html", "Patent"),
|
|
]
|
|
for path_suffix, expected_text in cats:
|
|
rel_path = os.path.join("publications", path_suffix)
|
|
html = self.read_html(rel_path)
|
|
self.assertIn(expected_text, html, f"Category route {path_suffix} missing '{expected_text}'")
|
|
|
|
def test_04_lectures_page_content(self):
|
|
"""TC-T1-F6: Verify Lectures page HTML structure."""
|
|
html = self.read_html("lectures.html")
|
|
self.assertIn("Lectures", html)
|
|
|
|
def test_05_standardization_page_content(self):
|
|
"""TC-T1-F6: Verify Standardization page standards bodies."""
|
|
html = self.read_html("standardization.html")
|
|
self.assertIn("Standardization", html)
|
|
self.assertIn("IEC TC100", html)
|
|
|
|
def test_06_theme_css_variables(self):
|
|
"""TC-T1-F2: Verify globals.css and built assets contain theme tokens."""
|
|
globals_path = os.path.join(BASE_DIR, "app", "globals.css")
|
|
if not os.path.exists(globals_path):
|
|
globals_path = os.path.join(os.getcwd(), "refer_landing_page", "app", "globals.css")
|
|
with open(globals_path, "r", encoding="utf-8") as f:
|
|
css = f.read()
|
|
|
|
for token in ["--ink", "--ivory", "--paper", "--line", "--vermillion", "--cobalt"]:
|
|
self.assertIn(token, css, f"Missing CSS variable {token} in globals.css")
|
|
|
|
def test_07_research_projects_pageview(self):
|
|
"""TC-T1-F7: Verify Research Project PageView content in Home static SSG HTML (AC-27 / AC-31)."""
|
|
html = self.read_html("index.html")
|
|
|
|
# 1. Project PageView Title & Projects
|
|
self.assertIn("Research Projects", html)
|
|
self.assertIn("AI-RAN", html)
|
|
self.assertIn("MCM", html)
|
|
self.assertIn("MVQM", html)
|
|
|
|
# 2. Standards track labels
|
|
self.assertIn("National Research Foundation of Korea", html)
|
|
self.assertIn("IEC/TC 100/WG 12 supported by KEIT", html)
|
|
|
|
# 3. International Standardizations Section
|
|
self.assertIn("International Standardizations", html)
|
|
self.assertIn("IEC TC100: Multimedia Systems and Equipment", html)
|
|
self.assertIn("ISO/IEC JTC1/SC6: Reliable Multicasting", html)
|
|
|
|
# 4. Assert zero placeholder Funder labels (AC-31)
|
|
self.assertNotIn("Funder:", html)
|
|
|
|
def test_08_publications_highlights_and_category_nav(self):
|
|
"""TC-T1-F8: Verify 5 representative highlights and CategoryNav active border in Publications."""
|
|
html = self.read_html("publications.html")
|
|
|
|
# 1. Verify 5 designated representative publications
|
|
expected_highlights = [
|
|
"Globally Integrated Trust Authority (GITA) for Resource-Constrained Edge Devices in IoT and 6G",
|
|
"Application Level Trust Authority (APPLETA) for Resource-Constrained Edge Devices in IoT and 6G",
|
|
"mQUIC: Use of QUIC for Handover Support with Connection Migration in Wireless/Mobile Networks",
|
|
"Use of QUIC for CoAP Transport in IoT Networks",
|
|
"Use of QUIC for Mobile-Oriented Future Internet (Q-MOFI)",
|
|
]
|
|
for title in expected_highlights:
|
|
self.assertIn(title, html, f"Missing representative highlight publication: '{title}'")
|
|
|
|
# 2. Verify Highlights heading & section
|
|
self.assertIn("Highlights", html)
|
|
self.assertIn("Categories", html)
|
|
self.assertIn("(IoT Architecture & Protocols, etc ...)", html)
|
|
|
|
# 3. Verify category detail active card border & label
|
|
patent_html = self.read_html(os.path.join("publications", "patent.html"))
|
|
self.assertIn("border-2 border-cobalt-dark", patent_html)
|
|
self.assertIn("Active View ●", patent_html)
|
|
self.assertIn("Patent", patent_html)
|
|
|
|
def test_09_footer_cite_and_brand_links(self):
|
|
"""TC-T1-F9: Verify Footer CITE abbreviation and brand/contact elements."""
|
|
html = self.read_html("index.html")
|
|
|
|
# 1. Institution link label CITE
|
|
self.assertIn("<span>CITE</span>", html)
|
|
self.assertIn("<span>KNU</span>", html)
|
|
self.assertIn("<span>CSE</span>", html)
|
|
|
|
# 2. Advisor contact info
|
|
self.assertIn("Prof. Seok-Joo Koh", html)
|
|
self.assertIn("sjkoh@knu.ac.kr", html)
|
|
|
|
def test_10_subpage_layout_and_english_headers(self):
|
|
"""TC-T1-F10: Verify English page headers across all subpages."""
|
|
subpages = [
|
|
("members.html", "LAB MEMBERS"),
|
|
("publications.html", "PUBLICATIONS"),
|
|
("lectures.html", "LECTURES"),
|
|
("standardization.html", "International Standardization"),
|
|
]
|
|
for rel_path, expected_h1 in subpages:
|
|
html = self.read_html(rel_path)
|
|
self.assertIn(expected_h1, html, f"Subpage {rel_path} missing H1 '{expected_h1}'")
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|