From f34e9bad57d93cf631c169372036886f28603a95 Mon Sep 17 00:00:00 2001 From: Godopu Date: Mon, 24 Aug 2026 16:10:11 +0900 Subject: [PATCH] refactor(pages,a11y,seo): enhance subpage metadata, semantic HTML, accessibility, and E2E regression tests - 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 --- refer_landing_page/app/lectures/page.tsx | 11 +++- refer_landing_page/app/members/page.tsx | 20 +++++--- .../app/publications/[category]/page.tsx | 16 +++++- .../publications/_components/CategoryNav.tsx | 3 +- refer_landing_page/app/publications/page.tsx | 11 ++-- .../app/standardization/page.tsx | 6 +++ refer_landing_page/tests/e2e_test_suite.py | 51 +++++++++++++++++++ 7 files changed, 102 insertions(+), 16 deletions(-) diff --git a/refer_landing_page/app/lectures/page.tsx b/refer_landing_page/app/lectures/page.tsx index 8498c4a..0e83f89 100644 --- a/refer_landing_page/app/lectures/page.tsx +++ b/refer_landing_page/app/lectures/page.tsx @@ -1,10 +1,19 @@ import React from "react"; +import type { Metadata } from "next"; import { semesters } from "../../content/lectures"; +export const metadata: Metadata = { + title: "Lectures", + description: "AI Agent Networking Lab (ANL) lecture courses and curriculum history", +}; + export default function LecturesPage() { const recentSemesters = semesters.slice(0, 3); const olderSemesters = semesters.slice(3); + const oldestSem = olderSemesters[olderSemesters.length - 1]; + const newestOlderSem = olderSemesters[0]; + return (
{/* Page Header */} @@ -73,7 +82,7 @@ export default function LecturesPage() { Browse all semesters

- Course history from 2016 Fall to 2024 Spring + Course history from {oldestSem ? `${oldestSem.year} ${oldestSem.term}` : "2004 Spring"} to {newestOlderSem ? `${newestOlderSem.year} ${newestOlderSem.term}` : "2024 Fall"} ({olderSemesters.length} Semesters)

diff --git a/refer_landing_page/app/members/page.tsx b/refer_landing_page/app/members/page.tsx index 8363950..97442ef 100644 --- a/refer_landing_page/app/members/page.tsx +++ b/refer_landing_page/app/members/page.tsx @@ -1,7 +1,13 @@ import React from "react"; +import type { Metadata } from "next"; import { activeMembers, alumni } from "../../content/members"; import { ProfessorDetailsDialog } from "./_components/ProfessorDetailsDialog"; +export const metadata: Metadata = { + title: "Members", + description: "AI Agent Networking Lab (ANL) professor, active researchers, and alumni directory", +}; + const DEGREE_LABEL: Record = { Professor: "Professor", PhD: "Ph. D.", @@ -24,16 +30,16 @@ export default function MembersPage() { ); return ( -
+
{/* Page Header */}
-

+

LAB MEMBERS

{/* Professor Section */} -
+

@@ -77,10 +83,10 @@ export default function MembersPage() {

{/* Active Researchers Section */} -
+
-

+

Active Researchers

@@ -148,10 +154,10 @@ export default function MembersPage() {
{/* Alumni Section (Native
/ progressive disclosure) */} -
+
-

+

Graduates

diff --git a/refer_landing_page/app/publications/[category]/page.tsx b/refer_landing_page/app/publications/[category]/page.tsx index d477189..a927504 100644 --- a/refer_landing_page/app/publications/[category]/page.tsx +++ b/refer_landing_page/app/publications/[category]/page.tsx @@ -1,4 +1,5 @@ import React from "react"; +import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { CategoryNav } from "../_components/CategoryNav"; import { publications, patents } from "../../../content/publications"; @@ -11,6 +12,17 @@ interface PageProps { }; } +export function generateMetadata({ params }: PageProps): Metadata { + const currentCat = PUB_CATEGORIES.find((c) => c.slug === params.category); + if (!currentCat) { + return { title: "Publications" }; + } + return { + title: `${currentCat.label} | Publications`, + description: `AI Agent Networking Lab (ANL) ${currentCat.label} research inventory and records`, + }; +} + // SSG static pre-rendering (● SSG) for Next.js 14 export function generateStaticParams() { return PUB_CATEGORIES.map((cat) => ({ @@ -84,10 +96,10 @@ export default function PublicationCategoryPage({ params }: PageProps) { {records.length === 0 ? (

- 현재 등록된 실적이 0건입니다. + No records found in this category.

- (D-01 카테고리 정류 확정 후 후속 배치가 수행됩니다) + Records will be updated periodically.

) : ( diff --git a/refer_landing_page/app/publications/_components/CategoryNav.tsx b/refer_landing_page/app/publications/_components/CategoryNav.tsx index c62e320..8c27613 100644 --- a/refer_landing_page/app/publications/_components/CategoryNav.tsx +++ b/refer_landing_page/app/publications/_components/CategoryNav.tsx @@ -89,7 +89,8 @@ export function CategoryNav({ currentCategory }: CategoryNavProps) { ) : ( View All → diff --git a/refer_landing_page/app/publications/page.tsx b/refer_landing_page/app/publications/page.tsx index 3d80757..ae24fad 100644 --- a/refer_landing_page/app/publications/page.tsx +++ b/refer_landing_page/app/publications/page.tsx @@ -1,8 +1,9 @@ +import type { Metadata } from "next"; import { CategoryNav } from "./_components/CategoryNav"; import { publications } from "../../content/publications"; -export const metadata = { - title: "Publications | ANL", +export const metadata: Metadata = { + title: "Publications", description: "AI Agent Networking Lab (ANL) research publications and patents overview", }; @@ -23,7 +24,7 @@ export default function PublicationsIndexPage() { ).filter((p): p is (typeof publications)[0] => Boolean(p)); return ( -
+
{/* Page Header */}

@@ -68,13 +69,13 @@ export default function PublicationsIndexPage() { )} {pub.venue && (

- {pub.venue} + {pub.venue}{pub.volume ? `, ${pub.volume}` : ""}

)} ))}

- +
); } diff --git a/refer_landing_page/app/standardization/page.tsx b/refer_landing_page/app/standardization/page.tsx index 6e5c762..9c2b491 100644 --- a/refer_landing_page/app/standardization/page.tsx +++ b/refer_landing_page/app/standardization/page.tsx @@ -1,6 +1,12 @@ import React from "react"; +import type { Metadata } from "next"; import { standardsBodies } from "../../content/standards"; +export const metadata: Metadata = { + title: "Standardization", + description: "AI Agent Networking Lab (ANL) international standardization research and contributions", +}; + export default function StandardizationPage() { return (
diff --git a/refer_landing_page/tests/e2e_test_suite.py b/refer_landing_page/tests/e2e_test_suite.py index 1358889..3528258 100644 --- a/refer_landing_page/tests/e2e_test_suite.py +++ b/refer_landing_page/tests/e2e_test_suite.py @@ -121,5 +121,56 @@ class TestANLHomepageE2E(unittest.TestCase): # 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("CITE", html) + self.assertIn("KNU", html) + self.assertIn("CSE", 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()