diff --git a/e2e/tests/core.spec.js b/e2e/tests/core.spec.js index 020e34f..e14ff54 100644 --- a/e2e/tests/core.spec.js +++ b/e2e/tests/core.spec.js @@ -76,6 +76,19 @@ test("core PKI workflow", async ({ page }) => { await page.locator(".nav-tabs").getByRole("tab", { name: "Extensions", exact: true }).click(); await expect(page.getByText("serverAuth", { exact: false })).toBeVisible(); + // Certificate list links to the detail route in both views. + const certDetailUrl = /\/vaults\/[^/]+\/certificates\/[^/]+$/; + await page.goto(`${vaultUrl}/certificates`); + await page.getByRole("link", { name: leafName, exact: true }).click(); + await expect(page).toHaveURL(certDetailUrl); + await expect(page.getByRole("heading", { name: leafName })).toBeVisible(); + + await page.goto(`${vaultUrl}/certificates`); + await page.getByRole("button", { name: "Plain view" }).click(); + await page.getByRole("link", { name: leafName, exact: true }).click(); + await expect(page).toHaveURL(certDetailUrl); + await expect(page.getByRole("heading", { name: leafName })).toBeVisible(); + // Search await page.goto(`${vaultUrl}/search`); await page.locator("input[placeholder='Search…']").fill(leafName); diff --git a/web/src/pages/certificates.rs b/web/src/pages/certificates.rs index 2fa0c83..267d7fd 100644 --- a/web/src/pages/certificates.rs +++ b/web/src/pages/certificates.rs @@ -234,6 +234,10 @@ pub fn CertificatesPage(vault_id: String) -> View { } } +fn certificate_href(vault_id: &str, cert_id: &str) -> String { + format!("/vaults/{}/certificates/{}", escape(vault_id), escape(cert_id)) +} + fn flat_html(rows: &[CertificateSummary], vault_id: &str, selected: &[String]) -> String { if rows.is_empty() { return "

No certificates match.

".to_string(); @@ -242,10 +246,9 @@ fn flat_html(rows: &[CertificateSummary], vault_id: &str, selected: &[String]) - for cert in rows { let (badge_class, badge_label) = status_badge(cert); body.push_str(&format!( - "{}{}
{}
{}{}{}{}{}{}{}", + "{}{}
{}
{}{}{}{}{}{}{}", checkbox(cert, selected), - escape(vault_id), - escape(&cert.id), + certificate_href(vault_id, &cert.id), escape(&cert.name), escape(&cert.subject), escape(&cert.issuer_name), @@ -303,10 +306,9 @@ fn node_html( format!("issuer: {}", cert.issuer_name) }; let mut row = format!( - "
{}{}{} {}{}expires {}{}
", + "
{}{}{} {}{}expires {}{}
", checkbox(cert, selected), - escape(vault_id), - escape(&cert.id), + certificate_href(vault_id, &cert.id), escape(&cert.name), if cert.is_ca { " CA" } else { "" }, badge_class, @@ -371,3 +373,29 @@ fn escape(value: &str) -> String { .replace('>', ">") .replace('"', """) } + +#[cfg(test)] +mod tests { + use super::*; + + fn cert(id: &str, name: &str) -> CertificateSummary { + CertificateSummary { + id: id.to_string(), + name: name.to_string(), + ..CertificateSummary::default() + } + } + + #[test] + fn certificate_links_point_at_the_detail_route() { + let cert = cert("cert-1", "Leaf"); + + let flat = flat_html(std::slice::from_ref(&cert), "vault-1", &[]); + assert!(flat.contains("href=\"/vaults/vault-1/certificates/cert-1\"")); + assert!(!flat.contains("href=\"/vaults/vault-1/cert-1\"")); + + let tree = tree_html(std::slice::from_ref(&cert), "vault-1", &[]); + assert!(tree.contains("href=\"/vaults/vault-1/certificates/cert-1\"")); + assert!(!tree.contains("href=\"/vaults/vault-1/cert-1\"")); + } +}