Skip to content

Conversation

@Prajwal7842
Copy link
Contributor

@Prajwal7842 Prajwal7842 commented Jan 5, 2026

This PR adds playwright integration tests for /events Audit log page for Airflow UI.

Covers following things from listed down in the issues:

Audit Logs Display

  1. Navigate to the Audit Logs page (/events)
  2. Verify the logs table is displayed
  3. Verify log entries show: timestamp, event type, DAG ID, user, etc.
  4. Verify pagination works
  5. Verify column sorting works

Search/Filter Logs

  1. Verify search input is visible

closes: #59931
releated: #59028

The integration tests were locally run 5+ times consecutively and all runs passed successfully to avoid any flakiness
Sample run:
Screenshot 2026-01-20 at 7 40 21 PM

@boring-cyborg boring-cyborg bot added the area:UI Related to UI/UX. For Frontend Developers. label Jan 5, 2026
@Prajwal7842 Prajwal7842 changed the title Add integration tests for /events Audit log page Add integration tests for /events Audit log page (Part 1) Jan 5, 2026
@Prajwal7842 Prajwal7842 force-pushed the prajwal7842/issue_59931 branch from 71c92e3 to 8b842f2 Compare January 6, 2026 09:57
@Prajwal7842
Copy link
Contributor Author

@vatsrahul1001 can you take a look. Builds are passing now. Thanks

@vatsrahul1001
Copy link
Contributor

Thanks, I will review it soon!

@vatsrahul1001
Copy link
Contributor

@Prajwal7842 Thanks for the PR! A few things to address:

  1. Test naming - Remove "should" prefix (use "verify ..." instead of "should verify ...")

  2. Remove hardcoded waits - waitForTimeout(5000) is slow and fragile. Use proper Playwright assertions:
    await expect(async () => {
    const indicator = await eventsPage.getColumnSortIndicator(0);
    expect(indicator).not.toBe("none");
    }).toPass({ timeout: 10_000 });

  3. Move DAG trigger to beforeAll - Current "Events with Generated Data" tests depend on first test running. Move triggerDag to beforeAll for proper isolation

  4. Column selectors are fragile - Using .nth(1), .nth(2) breaks if column order changes. Use text/role-based selectors:
    this.eventTypeColumn = page.getByRole("columnheader", { name: /event/i });
    5. Sorting test weak - Only checks indicator, not actual sort order. Capture data before/after and verify it changed

  5. Filter test incomplete - Only opens menu, doesn't apply filter. Add test that applies filter and verifies results

  6. Fix pagination URL - Missing / prefix and limit=1 is too small:
    return "/events?limit=5&offset=0";
    8. Remove waitForTimeout method

Let me know if you have questions!

await eventsPage.navigate();
await eventsPage.waitForEventsTable();

await eventsPage.waitForTimeout(5000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds 10 seconds of unnecessary wait time

await expect(async () => {
  const sortIndicator = await eventsPage.getColumnSortIndicator(0);
  expect(sortIndicator).not.toBe("none");
}).toPass({ timeout: 10_000 });

test.setTimeout(3 * 60 * 1000); // 3 minutes timeout

// First, trigger a DAG to generate audit log entries
await dagsPage.triggerDag(testDagId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move trigger dag to beforeAll


test.describe("Events with Generated Data", () => {
  const testDagId = testConfig.testDag.id;

  test.beforeAll(async ({ browser }) => {
    test.setTimeout(3 * 60 * 1000);
    const context = await browser.newContext({ storageState: AUTH_FILE });
    const page = await context.newPage();
    const dagsPage = new DagsPage(page);
    
    await dagsPage.triggerDag(testDagId);
    await context.close();
  });

  test.beforeEach(({ page }) => {
    eventsPage = new EventsPage(page);
  });

this.eventsTable = page.getByRole("table");
this.filterBar = page.locator('div:has(button:has-text("Filter"))').first();
// Use table header selectors - will check for presence of key columns
this.timestampColumn = page.locator("thead th").first();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If column order changes, all tests break.
Maybe we can use something like below

this.timestampColumn = page.getByRole("columnheader", { name: /when/i });
this.eventTypeColumn = page.getByRole("columnheader", { name: /event/i });
this.userColumn = page.getByRole("columnheader", { name: /user/i });

await expect(eventsPage.eventsTable).toBeVisible({ timeout: 10_000 });
});

test("should verify column sorting works", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't verify the data is actually sorted.
Capture data before/after and verify order

eventsPage = new EventsPage(page);
});

test("should verify search input is visible", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test only checks that the filter UI exists:

  • Opens filter menu
  • Verifies menu items visible
  • Closes menu

This is NOT a filter test - it's just checking the filter UI is present.

@Prajwal7842
Copy link
Contributor Author

@Prajwal7842 Thanks for the PR! A few things to address:

  1. Test naming - Remove "should" prefix (use "verify ..." instead of "should verify ...")
  2. Remove hardcoded waits - waitForTimeout(5000) is slow and fragile. Use proper Playwright assertions:
    await expect(async () => {
    const indicator = await eventsPage.getColumnSortIndicator(0);
    expect(indicator).not.toBe("none");
    }).toPass({ timeout: 10_000 });
  3. Move DAG trigger to beforeAll - Current "Events with Generated Data" tests depend on first test running. Move triggerDag to beforeAll for proper isolation
  4. Column selectors are fragile - Using .nth(1), .nth(2) breaks if column order changes. Use text/role-based selectors:
    this.eventTypeColumn = page.getByRole("columnheader", { name: /event/i });
    5. Sorting test weak - Only checks indicator, not actual sort order. Capture data before/after and verify it changed
  5. Filter test incomplete - Only opens menu, doesn't apply filter. Add test that applies filter and verifies results
  6. Fix pagination URL - Missing / prefix and limit=1 is too small:
    return "/events?limit=5&offset=0";
    8. Remove waitForTimeout method

Let me know if you have questions!

Thanks @vatsrahul1001 for the review. I have addressed the comments.
For point (5), regarding integration tests for filter, I am working on it in the follow up diff. Thanks.

@Prajwal7842 Prajwal7842 force-pushed the prajwal7842/issue_59931 branch from 28790a3 to b76c454 Compare January 8, 2026 14:04
@vatsrahul1001
Copy link
Contributor

@Prajwal7842 #59734 is already merged now. Can you rebase. I think you can reuse alot of code

@vatsrahul1001
Copy link
Contributor

@Prajwal7842 How are we progressing on this?

@Prajwal7842
Copy link
Contributor Author

@Prajwal7842 How are we progressing on this?

#59931 (comment)

@Prajwal7842 Prajwal7842 force-pushed the prajwal7842/issue_59931 branch from b76c454 to eab74e8 Compare January 20, 2026 14:19
@Prajwal7842 Prajwal7842 changed the title Add integration tests for /events Audit log page (Part 1) Add integration tests for /events Audit log page Jan 20, 2026
@Prajwal7842
Copy link
Contributor Author

@vatsrahul1001 updated the tests as per suggestions. PTAL. Thanks

@vatsrahul1001
Copy link
Contributor

Thanks @Prajwal7842 I will review soon

const menuItem = filterMenu.locator(`[role="menuitem"]:has-text("${filterName}")`);

await menuItem.click();
await this.page.waitForTimeout(300);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use explicit wait

@@ -21,8 +21,10 @@ import { BasePage } from "tests/e2e/pages/BasePage";

export class EventsPage extends BasePage {
public readonly eventColumn: Locator;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are defined but not directly used:
eventColumn, extraColumn, ownerColumn, whenColumn
clickColumnHeader() (only clickColumnToSort() is used)

Consider removing if not needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, these columns are being used in dag-audit-log.spec.ts and its usage is added into the previous diff, hence will be keeping this.

const eventText = await eventCell.textContent();
const userText = await userCell.textContent();

if (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use this
expect(whenText?.trim()).toBeTruthy();

@Prajwal7842 Prajwal7842 force-pushed the prajwal7842/issue_59931 branch 2 times, most recently from 8d66c9a to a01107f Compare January 27, 2026 13:18
@vatsrahul1001
Copy link
Contributor

@Prajwal7842 I see tests are failing. can you check?

@Prajwal7842 Prajwal7842 force-pushed the prajwal7842/issue_59931 branch from a01107f to 343ad0a Compare January 28, 2026 06:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UI Related to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UI E2E Test || BROWSE-001: Verify Audit Logs Page

2 participants