import { test, expect, Page } from "@playwright/test"; const TEST_USER = { username: "testuser", password: "testpass123" }; async function login(page: Page) { await page.goto("/login"); await page.locator("#username").fill(TEST_USER.username); await page.locator("#password").fill(TEST_USER.password); await page.locator('button[type="submit"]').click(); await page.waitForURL("**/", { timeout: 10000 }); } test.describe("Signal Cancel & Related Pages", () => { test.beforeEach(async ({ page }) => { await login(page); }); test("should access signals page and see signal table", async ({ page }) => { await page.goto("/signals"); // Wait for page title to appear await expect(page.getByText("KJB 매매 신호")).toBeVisible({ timeout: 10000, }); // Signal table should be visible await expect(page.locator("table").first()).toBeVisible(); // Summary cards should be visible await expect(page.getByText("매수 신호")).toBeVisible(); await expect(page.getByText("매도 신호", { exact: true })).toBeVisible(); await page.screenshot({ path: "../docs/screenshots/signals-page.png", fullPage: true, }); }); test("should show cancel button for EXECUTED signals", async ({ page }) => { await page.goto("/signals"); await expect(page.getByText("KJB 매매 신호")).toBeVisible({ timeout: 10000, }); // Switch to history view for executed signals const historyButton = page.getByText("신호 이력"); if (await historyButton.isVisible()) { await historyButton.click(); await page.waitForTimeout(2000); } // Check if any executed signal rows exist const executedBadges = page.locator('text="실행됨"'); const count = await executedBadges.count(); if (count > 0) { // There should be a cancel button near the executed signal const cancelButtons = page.locator('button:has-text("취소")'); const cancelCount = await cancelButtons.count(); expect(cancelCount).toBeGreaterThan(0); await page.screenshot({ path: "../docs/screenshots/signals-executed-with-cancel.png", fullPage: true, }); } else { // No executed signals - verify the page structure is correct console.log( "No EXECUTED signals found - cancel button test skipped (no data)" ); await expect(page.locator("table").first()).toBeVisible(); await page.screenshot({ path: "../docs/screenshots/signals-history.png", fullPage: true, }); } }); test("should show realized/unrealized PnL cards on portfolio detail page", async ({ page, }) => { // First check if any portfolio exists await page.goto("/portfolio"); await page.waitForTimeout(2000); // Try to find a portfolio link const portfolioLinks = page.locator('a[href^="/portfolio/"]'); const linkCount = await portfolioLinks.count(); if (linkCount > 0) { await portfolioLinks.first().click(); await page.waitForTimeout(3000); } else { await page.goto("/portfolio/1"); await page.waitForTimeout(3000); } // Check for realized/unrealized PnL cards const realizedPnlLabel = page.getByText("실현 수익"); const unrealizedPnlLabel = page.getByText("미실현 수익"); const hasRealizedCard = await realizedPnlLabel .isVisible() .catch(() => false); const hasUnrealizedCard = await unrealizedPnlLabel .isVisible() .catch(() => false); if (hasRealizedCard && hasUnrealizedCard) { await expect(realizedPnlLabel).toBeVisible(); await expect(unrealizedPnlLabel).toBeVisible(); await expect(page.getByText("매도 확정 손익")).toBeVisible(); await expect(page.getByText("보유 중 평가 손익")).toBeVisible(); } else { console.log( "Portfolio detail page may not have data - PnL cards not visible" ); } await page.screenshot({ path: "../docs/screenshots/portfolio-detail.png", fullPage: true, }); }); test("should render strategy compare page", async ({ page }) => { await page.goto("/strategy/compare"); // Wait for page title await expect( page.getByRole("heading", { name: "전략 비교" }) ).toBeVisible({ timeout: 10000, }); // Check description text await expect( page.getByText("멀티팩터, 퀄리티, 밸류모멘텀") ).toBeVisible(); // Check the compare execution button const runButton = page.getByText("전략 비교 실행"); await expect(runButton).toBeVisible(); await page.screenshot({ path: "../docs/screenshots/strategy-compare.png", fullPage: true, }); }); });