Skip to content

Commit

Permalink
#203 Simplify dialog capture and continue E2E tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexhad6 committed Jan 1, 2024
1 parent a482a93 commit 79cac46
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 156 deletions.
184 changes: 92 additions & 92 deletions cypress/e2e/parameter-navigation.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,96 +108,96 @@ describe("parameter data for latest commit", () => {
});
});

// it("collapses all items when the collapse all button is clicked", () => {
// // Children do not exist (collapsed)
// cy.getByTestId("parameter-list-item-dict")
// .as("dict")
// .should("exist")
// .within(() => {
// cy.getByTestId("parameter-list-item-int").should("not.exist");
// });
// cy.getByTestId("parameter-list-item-paramDict")
// .as("paramDict")
// .should("exist")
// .within(() => {
// cy.getByTestId("parameter-list-item-int").should("not.exist");
// });

// // Wait briefly to allow for other processes to finish (this test fails
// // intermittently, so this is an attempt to fix it).
// // eslint-disable-next-line cypress/no-unnecessary-waiting
// cy.wait(10);

// // Click dict item
// cy.get("@dict").find('[role="button"]').click();

// // Children are visible (expended)
// cy.get("@dict").within(() => {
// cy.getByTestId("parameter-list-item-int").should("be.visible");
// });

// // Wait briefly to allow for other processes to finish (this test fails
// // intermittently, so this is an attempt to fix it).
// // eslint-disable-next-line cypress/no-unnecessary-waiting
// cy.wait(10);

// // Click paramDict item
// cy.get("@paramDict").find('[role="button"]').click();

// // Children are visible (expended)
// cy.get("@paramDict").within(() => {
// cy.getByTestId("parameter-list-item-int").should("be.visible");
// });

// // Wait briefly to allow for other processes to finish (this test fails
// // intermittently, so this is an attempt to fix it).
// // eslint-disable-next-line cypress/no-unnecessary-waiting
// cy.wait(10);

// // Click collapse all button
// cy.getByTestId("collapse-all-button").click();

// // Children do not exist (collapsed)
// cy.get("@dict").within(() => {
// cy.getByTestId("parameter-list-item-int").should("not.exist");
// });
// cy.get("@paramDict").within(() => {
// cy.getByTestId("parameter-list-item-int").should("not.exist");
// });
// });

// it("resets root item to expanded when collapse all button is clicked", () => {
// // Children are visible (expended)
// cy.getByTestId("parameter-list-item-root")
// .as("root")
// .within(() => {
// cy.getByTestId("parameter-list-item-int").should("be.visible");
// });

// // Wait briefly to allow for other processes to finish (this test fails
// // intermittently, so this is an attempt to fix it).
// // eslint-disable-next-line cypress/no-unnecessary-waiting
// cy.wait(10);

// // Click root item
// cy.get("@root").find('[role="button"]').first().click();

// // Children do not exist (collapsed)
// cy.get("@root").within(() => {
// cy.getByTestId("parameter-list-item-int").should("not.exist");
// });

// // Wait briefly to allow for other processes to finish (this test fails
// // intermittently, so this is an attempt to fix it).
// // eslint-disable-next-line cypress/no-unnecessary-waiting
// cy.wait(10);

// // Click collapse all button
// cy.getByTestId("collapse-all-button").click();

// // Children are visible (expended)
// cy.get("@root").within(() => {
// cy.getByTestId("parameter-list-item-int").should("be.visible");
// });
// });
it("collapses all items when the collapse all button is clicked", () => {
// Children do not exist (collapsed)
cy.getByTestId("parameter-list-item-dict")
.as("dict")
.should("exist")
.within(() => {
cy.getByTestId("parameter-list-item-int").should("not.exist");
});
cy.getByTestId("parameter-list-item-paramDict")
.as("paramDict")
.should("exist")
.within(() => {
cy.getByTestId("parameter-list-item-int").should("not.exist");
});

// Wait briefly to allow for other processes to finish (this test fails
// intermittently, so this is an attempt to fix it).
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(10);

// Click dict item
cy.get("@dict").find('[role="button"]').click();

// Children are visible (expended)
cy.get("@dict").within(() => {
cy.getByTestId("parameter-list-item-int").should("be.visible");
});

// Wait briefly to allow for other processes to finish (this test fails
// intermittently, so this is an attempt to fix it).
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(10);

// Click paramDict item
cy.get("@paramDict").find('[role="button"]').click();

// Children are visible (expended)
cy.get("@paramDict").within(() => {
cy.getByTestId("parameter-list-item-int").should("be.visible");
});

// Wait briefly to allow for other processes to finish (this test fails
// intermittently, so this is an attempt to fix it).
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(10);

// Click collapse all button
cy.getByTestId("collapse-all-button").click();

// Children do not exist (collapsed)
cy.get("@dict").within(() => {
cy.getByTestId("parameter-list-item-int").should("not.exist");
});
cy.get("@paramDict").within(() => {
cy.getByTestId("parameter-list-item-int").should("not.exist");
});
});

it("resets root item to expanded when collapse all button is clicked", () => {
// Children are visible (expended)
cy.getByTestId("parameter-list-item-root")
.as("root")
.within(() => {
cy.getByTestId("parameter-list-item-int").should("be.visible");
});

// Wait briefly to allow for other processes to finish (this test fails
// intermittently, so this is an attempt to fix it).
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(10);

// Click root item
cy.get("@root").find('[role="button"]').first().click();

// Children do not exist (collapsed)
cy.get("@root").within(() => {
cy.getByTestId("parameter-list-item-int").should("not.exist");
});

// Wait briefly to allow for other processes to finish (this test fails
// intermittently, so this is an attempt to fix it).
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(10);

// Click collapse all button
cy.getByTestId("collapse-all-button").click();

// Children are visible (expended)
cy.get("@root").within(() => {
cy.getByTestId("parameter-list-item-int").should("be.visible");
});
});
});
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ paramview = "paramview._cli:main"
strict = true

[tool.pytest.ini_options]
addopts = ["--import-mode=importlib"]
addopts = ["--import-mode=importlib", "--tracing=retain-on-failure"]
base_url = "http://127.0.0.1:5051"
filterwarnings = ["ignore::DeprecationWarning:eventlet.support.greenlets"]
27 changes: 27 additions & 0 deletions tests/e2e/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Global fixtures for E2E tests.
Called automatically by Pytest before running tests.
"""

from __future__ import annotations
import pytest
from playwright.sync_api import Page, Dialog
from tests.e2e.helpers import CaptureDialogs


@pytest.fixture(name="capture_dialogs")
def fixture_capture_dialogs(page: Page) -> CaptureDialogs:
"""Capture dialogs and expose a an object with settings and captured values."""
capture_dialogs = CaptureDialogs()

def handle_dialog(dialog: Dialog) -> None:
capture_dialogs.num_dialogs += 1
capture_dialogs.last_dialog_message = dialog.message
if capture_dialogs.accept:
dialog.accept()
else:
dialog.dismiss()

page.on("dialog", handle_dialog)
return capture_dialogs
44 changes: 38 additions & 6 deletions tests/e2e/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations
from typing import Any
import os
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from sqlalchemy import delete
from freezegun import freeze_time
Expand Down Expand Up @@ -53,20 +54,33 @@ def get_datetime_display(commit_id: int) -> str:
return get_datetime(commit_id).astimezone().strftime("%m/%d/%y, %I:%M:%S %p")


def get_commit_message(commit_id: int, message: str | None = None) -> str:
"""Get the commit message corresponding to the given commit ID."""
if message is not None:
return message
if commit_id == 1:
return "Initial commit"
return f"Commit {commit_id}"


def get_commit_message_display(commit_id: int, message: str | None = None) -> str:
"""Get the commit message as displayed in the app."""
return f"{commit_id}: {get_commit_message(commit_id, message)}"


def clear_db() -> None:
"""Clear the database."""
with _DB._Session.begin() as session: # pylint: disable=no-member,protected-access
session.execute(delete(_Snapshot)) # Clear all commits


def commit_to_db(message: str | None = None, data: Any | None = None) -> None:
def commit_to_db(data: Any | None = None, message: str | None = None) -> None:
"""Make a commit with the given message."""
num_commits = _DB.num_commits
commit_id = num_commits + 1
message = f"Commit {commit_id}" if message is None else message
data = ParamDict(commit_id=commit_id, b=2, c=3) if data is None else data
with freeze_time(get_datetime(num_commits + 1)):
_DB.commit(message, data)
_DB.commit(get_commit_message(commit_id, message), data)


def reset_db(num_commits: int = 1) -> None:
Expand All @@ -93,7 +107,7 @@ def reset_db(num_commits: int = 1) -> None:
"param": CustomParam(int=123, str="test"),
}
)
commit_to_db("Initial commit", initial_data)
commit_to_db(initial_data)
for _ in range(2, num_commits + 1):
commit_to_db()

Expand All @@ -106,5 +120,23 @@ def load_classes_from_db() -> None:
_DB.load()


if __name__ == "__main__":
reset_db()
@dataclass
class CaptureDialogs:
"""Settings and captured values exposed by the ``capture_dialogs`` fixture."""

accept: bool = False
"""Whether to accept subsequent dialogs (default is ``False``)."""
num_dialogs: int = 0
"""Number of dialogs captured in the current test."""
last_dialog_message: str | None = None
"""Message of the last dialog message captured."""


# pylint: disable-next=too-few-public-methods
class CommitInfo:
"""Information for a given commit."""

def __init__(self, commit_id: int) -> None:
self.id = commit_id
self.date = get_datetime_display(commit_id)
self.message = get_commit_message_display(commit_id)
62 changes: 62 additions & 0 deletions tests/e2e/test_commit_selection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Tests for commit selection."""

import pytest
from playwright.sync_api import Page, expect
from tests.e2e.helpers import reset_db, CommitInfo

FIRST_COMMIT = CommitInfo(1)
LATEST_COMMIT = CommitInfo(3)


@pytest.fixture(autouse=True)
def setup(page: Page) -> None:
"""Automatically run before each test in this module."""
reset_db(3)
page.goto("/")


def test_commit_select_inputs(page: Page) -> None:
"""Displays the latest commit, latest is checked, and inputs are not disabled."""
commit_select_combobox = page.get_by_test_id("commit-select-combobox")
commit_select_combobox_input = commit_select_combobox.get_by_role("combobox")
latest_checkbox = page.get_by_test_id("latest-checkbox")
commit_id_item = page.get_by_test_id("parameter-list-item-commit_id")

expect(commit_select_combobox).to_contain_text(LATEST_COMMIT.date)
expect(commit_select_combobox_input).to_have_value(LATEST_COMMIT.message)
expect(latest_checkbox).to_be_checked()
expect(commit_id_item).to_have_text(f"commit_id{LATEST_COMMIT.id}")


def test_commit_search(page: Page) -> None:
"""Searches for the initial commit and switches to it."""
commit_select_combobox = page.get_by_test_id("commit-select-combobox")
commit_select_combobox_input = commit_select_combobox.get_by_role("combobox")
commit_id_item = page.get_by_test_id("parameter-list-item-commit_id")

# Search and select first commit
commit_select_combobox_input.fill(FIRST_COMMIT.message[:8])
commit_select_combobox_input.press("Enter")
expect(commit_select_combobox).to_contain_text(FIRST_COMMIT.date)
expect(commit_select_combobox_input).to_have_value(FIRST_COMMIT.message)
expect(commit_id_item).to_have_text(f"commit_id{FIRST_COMMIT.id}")


def test_latest_checkbox(page: Page) -> None:
"""Switches to latest commit when latest checkbox is checked."""
commit_select_combobox = page.get_by_test_id("commit-select-combobox")
commit_select_combobox_input = commit_select_combobox.get_by_role("combobox")
latest_checkbox = page.get_by_test_id("latest-checkbox")
commit_id_item = page.get_by_test_id("parameter-list-item-commit_id")

# Switch to first commit
commit_select_combobox_input.fill(FIRST_COMMIT.message[:8])
commit_select_combobox_input.press("Enter")
expect(latest_checkbox).not_to_be_checked()

# Check the latest checkbox
latest_checkbox.check()
expect(latest_checkbox).to_be_checked()
expect(commit_select_combobox).to_contain_text(LATEST_COMMIT.date)
expect(commit_select_combobox_input).to_have_value(LATEST_COMMIT.message)
expect(commit_id_item).to_have_text(f"commit_id{LATEST_COMMIT.id}")
22 changes: 22 additions & 0 deletions tests/e2e/test_database_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Tests for the page title."""

import pytest
from playwright.sync_api import Page, expect
from tests.e2e.helpers import DB_NAME, reset_db


@pytest.fixture(autouse=True)
def setup(page: Page) -> None:
"""Automatically run before each test in this module."""
reset_db()
page.goto("/")


def test_page_title(page: Page) -> None:
"""Page title is the database file name."""
expect(page).to_have_title(DB_NAME)


def test_database_name(page: Page) -> None:
"""Database name header is the database file name."""
expect(page.get_by_test_id("database-name")).to_have_text(DB_NAME)
Loading

0 comments on commit 79cac46

Please sign in to comment.