import { SELECTORS } from "../../fixtures/selectors"; import { expect, test } from "../../fixtures/test"; test.describe("Deep Link Permalink Tests @smoke", () => { test.beforeEach(async ({ waitForAppReady }) => { await waitForAppReady(); }); test("valid article permalink opens modal automatically", async ({ page, gotoApp, isSummaryModalOpen, }) => { // First get an article ID from the feed await gotoApp(); await page.waitForSelector(SELECTORS.feed.articles, { timeout: 10000 }); const firstArticle = page.locator(SELECTORS.feed.articles).first(); const articleId = await firstArticle .getAttribute("id") .then((id) => (id ? parseInt(id.replace("news-", "")) : null)); expect(articleId).not.toBeNull(); // Navigate to article permalink await gotoApp({ articleId: articleId! }); await page.waitForTimeout(2000); // Wait for modal to open // Modal should be open const isOpen = await isSummaryModalOpen(); expect(isOpen).toBe(true); // Modal should show correct article const modal = page.locator(SELECTORS.summaryModal.root); const modalHeadline = await modal .locator(SELECTORS.summaryModal.headline) .textContent(); const articleHeadline = await firstArticle.locator("h3").textContent(); expect(modalHeadline).toBe(articleHeadline); }); test("invalid article permalink shows error state", async ({ page, gotoApp, }) => { // Navigate to invalid article ID await gotoApp({ articleId: 999999 }); await page.waitForTimeout(2000); // Should not show summary modal const modal = page.locator(SELECTORS.summaryModal.root); await expect(modal).not.toBeVisible(); // Should still show the page (not crash) const hero = page.locator(SELECTORS.hero.root); const feed = page.locator(SELECTORS.feed.root); const heroVisible = await hero.isVisible().catch(() => false); const feedVisible = await feed.isVisible().catch(() => false); expect(heroVisible || feedVisible).toBe(true); }); test("hero-origin modal flow via permalink", async ({ page, gotoApp, isSummaryModalOpen, }) => { // Get hero article ID await gotoApp(); await page.waitForSelector(SELECTORS.hero.root, { timeout: 10000 }); const hero = page.locator(SELECTORS.hero.root); const heroId = await hero .getAttribute("id") .then((id) => (id ? parseInt(id.replace("news-", "")) : null)); expect(heroId).not.toBeNull(); // Navigate directly to hero article await gotoApp({ articleId: heroId! }); await page.waitForTimeout(2000); // Modal should open const isOpen = await isSummaryModalOpen(); expect(isOpen).toBe(true); // Modal should show hero article content const modal = page.locator(SELECTORS.summaryModal.root); const modalHeadline = await modal .locator(SELECTORS.summaryModal.headline) .textContent(); const heroHeadline = await hero.locator("h1").textContent(); expect(modalHeadline).toBe(heroHeadline); }); test("closing permalink modal updates URL", async ({ page, gotoApp, isSummaryModalOpen, }) => { // Open via permalink await gotoApp({ articleId: 1 }); await page.waitForTimeout(2000); // URL should have article parameter await expect(page).toHaveURL(/\?article=\d+/); // Close modal await page.keyboard.press("Escape"); await page.waitForTimeout(500); // URL should be cleaned up (parameter removed) await expect(page).toHaveURL(/\/$/); await expect(page).not.toHaveURL(/\?article=/); }); test("modal state persists on page refresh", async ({ page, gotoApp, isSummaryModalOpen, }) => { // Open via permalink await gotoApp({ articleId: 1 }); await page.waitForTimeout(2000); // Verify modal is open expect(await isSummaryModalOpen()).toBe(true); // Refresh page await page.reload(); await page.waitForTimeout(2000); // Modal should still be open expect(await isSummaryModalOpen()).toBe(true); }); }); test.describe("Policy Modal Deep Links", () => { test("terms policy modal opens via URL parameter", async ({ page, gotoApp, }) => { await gotoApp({ policy: "terms" }); await page.waitForTimeout(1000); // Policy modal should be visible const modal = page.locator(SELECTORS.policyModal.root); await expect(modal).toBeVisible(); // Should show terms title const title = modal.locator(SELECTORS.policyModal.termsTitle); await expect(title).toBeVisible(); }); test("attribution policy modal opens via URL parameter", async ({ page, gotoApp, }) => { await gotoApp({ policy: "attribution" }); await page.waitForTimeout(1000); // Policy modal should be visible const modal = page.locator(SELECTORS.policyModal.root); await expect(modal).toBeVisible(); // Should show attribution title const title = modal.locator(SELECTORS.policyModal.attributionTitle); await expect(title).toBeVisible(); }); test("closing policy modal clears URL parameter", async ({ page, gotoApp, }) => { await gotoApp({ policy: "terms" }); await page.waitForTimeout(1000); // URL should have policy parameter await expect(page).toHaveURL(/\?policy=terms/); // Close modal const modal = page.locator(SELECTORS.policyModal.root); await modal.locator(SELECTORS.policyModal.closeButton).click(); await page.waitForTimeout(500); // URL should be cleaned up await expect(page).toHaveURL(/\/$/); await expect(page).not.toHaveURL(/\?policy=/); }); });