diff options
Diffstat (limited to 'src/test/java/webui')
| -rw-r--r-- | src/test/java/webui/ApplicationTest.java | 20 | ||||
| -rw-r--r-- | src/test/java/webui/PantryItemTest.java | 99 | ||||
| -rw-r--r-- | src/test/java/webui/pages/ApplicationPage.java | 50 | ||||
| -rw-r--r-- | src/test/java/webui/pages/IndexPage.java | 128 | ||||
| -rw-r--r-- | src/test/java/webui/pages/components/AddItemComponent.java | 121 |
5 files changed, 418 insertions, 0 deletions
diff --git a/src/test/java/webui/ApplicationTest.java b/src/test/java/webui/ApplicationTest.java new file mode 100644 index 0000000..a486f8f --- /dev/null +++ b/src/test/java/webui/ApplicationTest.java @@ -0,0 +1,20 @@ +package webui; + +import java.net.URL; + +import com.microsoft.playwright.BrowserContext; + +import io.quarkiverse.playwright.InjectPlaywright; +import io.quarkiverse.playwright.WithPlaywright; +import io.quarkus.test.common.http.TestHTTPResource; + +@WithPlaywright +public class ApplicationTest { + + @InjectPlaywright + BrowserContext context; + + @TestHTTPResource("/") + URL indexLocation; + +} diff --git a/src/test/java/webui/PantryItemTest.java b/src/test/java/webui/PantryItemTest.java new file mode 100644 index 0000000..71948b8 --- /dev/null +++ b/src/test/java/webui/PantryItemTest.java @@ -0,0 +1,99 @@ +package webui; + +import org.junit.jupiter.api.Test; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; + +import com.microsoft.playwright.Locator; + +import dev.submelon.model.PantryItem; +import io.quarkiverse.quinoa.testing.QuinoaTestProfiles; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import webui.pages.IndexPage; +import webui.pages.components.AddItemComponent; + +@QuarkusTest +@TestProfile(QuinoaTestProfiles.Enable.class) +public class PantryItemTest extends ApplicationTest { + + private static PantryItem[] testItems = new PantryItem[] { + PantryItem.builder() + .name("Flour") + .description("White unbleached") + .quantity(12.4d) + .quantityUnitType("cups") + .build(), + PantryItem.builder() + .name("Ponzu Sauce") + .quantity(4d) + .quantityUnitType("oz") + .build() + }; + + @Test + public void testLanding() { + // Arrange + final IndexPage page = new IndexPage(context.newPage()); + + // Act + page.loadAndVerifyPage(indexLocation); + + // Assert + page.checkItemTableIsEmpty(); + + // Check add item button is visible and enabled + Locator addButton = page.getAddItemButton(); + assertThat(addButton).isVisible(); + assertThat(addButton).isEnabled(); + } + + @Test + public void testAddItemCancel() { + // Arrange + final PantryItem testItem = testItems[0]; + final IndexPage page = new IndexPage(context.newPage()); + + // Act + page.loadAndVerifyPage(indexLocation); + page.checkItemTableIsEmpty(); + + AddItemComponent addItem = AddItemComponent.open(page); + addItem.enterPantryItem(testItem); + addItem.cancel(); + + // Assert + page.checkItemTableIsEmpty(); + } + + @Test + public void testAddItemSubmit() { + // Arrange + final PantryItem testItem = testItems[0]; + final IndexPage page = new IndexPage(context.newPage()); + + // Act + page.loadAndVerifyPage(indexLocation); + page.checkItemTableIsEmpty(); + + AddItemComponent addItem = AddItemComponent.open(page); + addItem.enterPantryItem(testItem); + addItem.submit(); + + // Assert + page.validateAddItemNotification(testItem); + + List<Locator> items = page.getCurrentItems(1); + assertEquals(1, items.size()); + + Locator newItem = items.get(0); + assertThat(newItem).containsText(testItem.getName()); + assertThat(newItem).containsText(testItem.getDescription()); + assertThat(newItem).containsText(testItem.getQuantity().toString()); + assertThat(newItem).containsText(testItem.getQuantityUnitType()); + } + +} diff --git a/src/test/java/webui/pages/ApplicationPage.java b/src/test/java/webui/pages/ApplicationPage.java new file mode 100644 index 0000000..2182a5d --- /dev/null +++ b/src/test/java/webui/pages/ApplicationPage.java @@ -0,0 +1,50 @@ +package webui.pages; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.URL; + +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.Response; +import com.microsoft.playwright.options.AriaRole; + +/** + * Provide abstract class to track Pantry-wide locators, components, integrations, and tests + */ +public abstract class ApplicationPage { + + private static final String TOAST_DIV_SELECTOR = "div#toast-holder"; + + protected final Page page; + + public ApplicationPage(Page page) { + this.page = page; + } + + /** + * Navigate to page with table of Pantry Items + */ + public void loadAndVerifyPage(URL location, String title) { + Response response = page.navigate(location.toString()); + assertEquals("OK", response.statusText()); + + page.waitForLoadState(); + + assertThat(page).hasTitle(title); + } + + + /** + * Assert that a notification is displayed with the specified header and text + */ + public Locator findAndValidateNotification(final String header, final String text) { + Locator specifiedNotification = page.locator(TOAST_DIV_SELECTOR) + .getByRole(AriaRole.ALERT) + .filter(new Locator.FilterOptions().setHasText(text)); + assertThat(specifiedNotification).isVisible(); + assertThat(specifiedNotification).containsText(header); + return specifiedNotification; + } +}
\ No newline at end of file diff --git a/src/test/java/webui/pages/IndexPage.java b/src/test/java/webui/pages/IndexPage.java new file mode 100644 index 0000000..ce9a5b6 --- /dev/null +++ b/src/test/java/webui/pages/IndexPage.java @@ -0,0 +1,128 @@ +package webui.pages; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +import java.net.URL; +import java.util.List; + +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.options.AriaRole; + +import dev.submelon.model.PantryItem; + +/** + * Provide locators and methodical tests for the index page of the Pantry application + */ +public class IndexPage extends ApplicationPage { + + private static final String INDEX_PAGE_TITLE = "Pantry"; + + private static final String ADD_ITEM_LABEL = "Add Item"; + private static final String ITEM_NAME_LABEL = "Item Name"; + private static final String ITEM_DESCRIPTION_LABEL = "Item Description"; + private static final String ITEM_QUANTITY_LABEL = "Item Quantity"; + private static final String ITEM_QUANTITY_TYPE_LABEL = "Quantity Type"; + private static final String SUBMIT_ITEM_LABEL = "Submit Item"; + private static final String CANCEL_LABEL = "Cancel"; + + private static final String PANTRY_TABLE_ROW_SELECTOR = "css=table#tbl-pantry > tbody > tr"; + private static final String EMPTY_TABLE_MESSAGE_SELECTOR = "div#tbl-msg-empty"; + + private static final String EMPTY_TABLE_MESSAGE_TEXT = "Nothing's in the pantry at the moment!"; + private static final String ADD_ITEM_NOTIFICATION_HEADER = "Item added successfully"; + private static final String ADD_ITEM_NOTIFICATION_TEMPLATE = "Stored \"%s\" in the pantry!"; + + public IndexPage(Page page) { + super(page); + } + + /** + * Navigate to page with table of Pantry Items + */ + public void loadAndVerifyPage(URL location) { + loadAndVerifyPage(location, INDEX_PAGE_TITLE); + } + + /** + * Check table is empty with appropriate message + */ + public void checkItemTableIsEmpty() { + Locator td = page.locator(EMPTY_TABLE_MESSAGE_SELECTOR); + assertThat(td).isVisible(); + assertThat(td).containsText(EMPTY_TABLE_MESSAGE_TEXT); + } + + /** + * Obtain a list of items or rows (`tr`s) in the Pantry Item table + */ + public List<Locator> getCurrentItems(int numExpectedItems) { + if (numExpectedItems == 0) { + checkItemTableIsEmpty(); + } + + Locator table = page.locator(PANTRY_TABLE_ROW_SELECTOR) + .filter(new Locator.FilterOptions().setHasNotText(EMPTY_TABLE_MESSAGE_TEXT)); + assertThat(table).hasCount(numExpectedItems); + + return table.all(); + } + + /** + * Obtain the add item button on the index page + */ + public Locator getAddItemButton() { + return page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(ADD_ITEM_LABEL)); + } + + /** + * Obtain the item name input in the add item component + */ + public Locator getItemNameInput() { + return page.getByLabel(ITEM_NAME_LABEL); + } + + /** + * Obtain the item description input in the add item component + */ + public Locator getItemDescriptionInput() { + return page.getByLabel(ITEM_DESCRIPTION_LABEL); + } + + /** + * Obtain the item quantity input in the add item component + */ + public Locator getItemQuantityInput() { + return page.getByLabel(ITEM_QUANTITY_LABEL); + } + + /** + * Obtain the item quantity type input in the add item component + */ + public Locator getQuantityTypeInput() { + return page.getByLabel(ITEM_QUANTITY_TYPE_LABEL); + } + + /** + * Obtain the submit item button in the add item component + */ + public Locator getSubmitItemButton() { + return page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(SUBMIT_ITEM_LABEL)); + } + + /** + * Obtain the cancel button in the add item component + */ + public Locator getCancelButton() { + return page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName(CANCEL_LABEL)); + } + + /** + * assert notification is displayed that item has been added + */ + public Locator validateAddItemNotification(final PantryItem item) { + return findAndValidateNotification(ADD_ITEM_NOTIFICATION_HEADER, + String.format(ADD_ITEM_NOTIFICATION_TEMPLATE, item.getName())); + } + +} diff --git a/src/test/java/webui/pages/components/AddItemComponent.java b/src/test/java/webui/pages/components/AddItemComponent.java new file mode 100644 index 0000000..ba799fd --- /dev/null +++ b/src/test/java/webui/pages/components/AddItemComponent.java @@ -0,0 +1,121 @@ +package webui.pages.components; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +import com.microsoft.playwright.Locator; + +import dev.submelon.model.PantryItem; +import webui.pages.IndexPage; + +/** + * A component to add an item to the pantry on the index page + */ +public class AddItemComponent { + + private Locator nameInput; + private Locator descriptionInput; + private Locator quantityInput; + private Locator quantityTypeInput; + private Locator submitButton; + private Locator cancelButton; + + /** + * Opens the add item component on the index page and creates the instance + * of the AddItemComponent. + */ + public static AddItemComponent open(final IndexPage page) { + + // Check button is visible and enabled + Locator addButton = page.getAddItemButton(); + assertThat(addButton).isVisible(); + assertThat(addButton).isEnabled(); + + // make available add item component + addButton.click(); + + // verify initial state of inputs and buttons + assertThat(addButton).isHidden(); + + // find and assign inputs for the component + AddItemComponent component = new AddItemComponent(); + component.nameInput = page.getItemNameInput(); + component.descriptionInput = page.getItemDescriptionInput(); + component.quantityInput = page.getItemQuantityInput(); + component.quantityTypeInput = page.getQuantityTypeInput(); + + // find and assign buttons for the component + component.submitButton = page.getSubmitItemButton(); + component.cancelButton = page.getCancelButton(); + + component.verifyOpen(); + + return component; + } + + /** + * Enter values into the inputs based on a {@link PantryItem} + */ + public void enterPantryItem(final PantryItem item) { + if (item.getName() != null) { + nameInput.fill(item.getName()); + } + if (item.getDescription() != null) { + descriptionInput.fill(item.getDescription()); + } + if (item.getQuantity() != null) { + quantityInput.fill(String.valueOf(item.getQuantity())); + } + if (item.getQuantityUnitType() != null) { + quantityTypeInput.fill(item.getQuantityUnitType()); + } + } + + /** + * Submits the item to the API and closes the add item component + */ + public void submit() { + submitButton.click(); + + verifyClosed(); + } + + /** + * Closes the add item component without saving + */ + public void cancel() { + cancelButton.click(); + + verifyClosed(); + } + + /** + * Verify the expected inputs and buttons appear as expected on opening + */ + public void verifyOpen() { + assertThat(nameInput).isVisible(); + assertThat(nameInput).isEditable(); + assertThat(descriptionInput).isVisible(); + assertThat(descriptionInput).isEditable(); + assertThat(quantityInput).isVisible(); + assertThat(quantityInput).isEditable(); + assertThat(quantityTypeInput).isVisible(); + assertThat(quantityTypeInput).isEditable(); + assertThat(submitButton).isVisible(); + assertThat(submitButton).isDisabled(); + assertThat(cancelButton).isVisible(); + assertThat(cancelButton).isEnabled(); + } + + /** + * Verify all of the expected inputs and buttons no longer appear + */ + public void verifyClosed() { + assertThat(nameInput).isHidden(); + assertThat(descriptionInput).isHidden(); + assertThat(quantityInput).isHidden(); + assertThat(quantityTypeInput).isHidden(); + assertThat(submitButton).isHidden(); + assertThat(cancelButton).isHidden(); + } + +} |
