Repository: apache/airflow
File: airflow-core/src/airflow/ui/tests/e2e/specs/task-logs.spec.ts (TypeScript)

Code before:
import { expect, test } from "@playwright/test";
import { AUTH_FILE, testConfig } from "playwright.config";

import { TaskInstancePage } from "../pages/TaskInstancePage";

test.describe("Verify task logs display", () => {
  test.describe.configure({ mode: "serial" });

  const testDagId = testConfig.testDag.id;
  const testTaskId = testConfig.testTask.id;

  let dagRunId: string;

  test.beforeAll(async ({ browser }) => {
    test.setTimeout(120_000);

    const context = await browser.newContext({ storageState: AUTH_FILE });
    const page = await context.newPage();
    const taskInstancePage = new TaskInstancePage(page);

    await taskInstancePage.triggerDagAndWaitForSuccess(testDagId);

    const url = page.url();
    const match = /runs\/([^/]+)/.exec(url);

    dagRunId = match?.[1] ?? "";

    await context.close();
  });

  test.beforeEach(async ({ page }) => {
    const taskInstancePage = new TaskInstancePage(page);

    await taskInstancePage.navigateToTaskLogs(testDagId, dagRunId, testTaskId);
  });

  test("Verify log content is displayed", async ({ page }) => {
    const virtualizedList = page.locator('[data-testid="virtualized-list"]');

    await expect(virtualizedList).toBeVisible({ timeout: 30_000 });
    const logItems = page.locator('[data-testid^="virtualized-item-"]');

    await expect(logItems.first()).toBeVisible({ timeout: 10_000 });
  });

  test("Verify log levels are visible", async ({ page }) => {
    const virtualizedList = page.locator('[data-testid="virtualized-list"]');

    await expect(virtualizedList).toBeVisible({ timeout: 30_000 });

    await expect(virtualizedList).toContainText(/INFO|WARNING|ERROR|CRITICAL/);

Review comment (bug):
If URL doesn't match, dagRunId becomes empty string and all tests fail silently. Should throw an error:

`if (!dagRunId) {
  throw new Error(`Could not extract dagRunId from URL: ${url}`);
}`

Code after:
import { expect, test } from "@playwright/test";
import { AUTH_FILE, testConfig } from "playwright.config";

import { TaskInstancePage } from "../pages/TaskInstancePage";

test.describe("Verify task logs display", () => {
  test.describe.configure({ mode: "serial" });

  const testDagId = testConfig.testDag.id;
  const testTaskId = testConfig.testTask.id;

  let dagRunId: string;

  test.beforeAll(async ({ browser }) => {
    test.setTimeout(120_000);

    const context = await browser.newContext({ storageState: AUTH_FILE });
    const page = await context.newPage();
    const taskInstancePage = new TaskInstancePage(page);

    await taskInstancePage.triggerDagAndWaitForSuccess(testDagId);

    const url = page.url();
    const match = /runs\/([^/]+)/.exec(url);

    dagRunId = match?.[1] ?? "";

    if (!dagRunId) {
      throw new Error(`Could not extract dagRunId from URL: ${url}`);
    }

    await context.close();
  });

  test.beforeEach(async ({ page }) => {
    const taskInstancePage = new TaskInstancePage(page);

    await taskInstancePage.navigateToTaskInstance(testDagId, dagRunId, testTaskId);
  });

  test("Verify log content is displayed", async ({ page }) => {
    const virtualizedList = page.locator('[data-testid="virtualized-list"]');

    await expect(virtualizedList).toBeVisible({ timeout: 30_000 });
    const logItems = page.locator('[data-testid^="virtualized-item-"]');

    await expect(logItems.first()).toBeVisible({ timeout: 10_000 });
  });

  test("Verify log levels are visible", async ({ page }) => {
    const virtualizedList = page.locator('[data-testid="virtualized-list"]');