diff --git a/jdi-light-angular-tests/src/main/java/io/github/com/StaticSite.java b/jdi-light-angular-tests/src/main/java/io/github/com/StaticSite.java index 0c329d4132..7870c37d20 100644 --- a/jdi-light-angular-tests/src/main/java/io/github/com/StaticSite.java +++ b/jdi-light-angular-tests/src/main/java/io/github/com/StaticSite.java @@ -5,15 +5,16 @@ import io.github.com.pages.AngularPage; import io.github.com.pages.AutocompletePage; import io.github.com.pages.BadgePage; -import io.github.com.pages.InputPage; import io.github.com.pages.ButtonTogglePage; import io.github.com.pages.ButtonsPage; import io.github.com.pages.CheckBoxPage; import io.github.com.pages.DividerPage; +import io.github.com.pages.InputPage; import io.github.com.pages.ProgressBarPage; import io.github.com.pages.ProgressSpinnerPage; import io.github.com.pages.RadioButtonPage; import io.github.com.pages.SlideTogglePage; +import io.github.com.pages.SnackBarPage; @JSite("https://jdi-testing.github.io/jdi-light/angular-page/#/") public class StaticSite { @@ -37,10 +38,10 @@ public class StaticSite { public static BadgePage badgePage; @Url("buttons_toggle") - public static ButtonTogglePage buttonTogglePage; + public static ButtonTogglePage buttonTogglePage; @Url("divider") - public static DividerPage dividerPage; + public static DividerPage dividerPage; @Url("autocompletes") public static AutocompletePage autocompletePage; @@ -53,4 +54,7 @@ public class StaticSite { @Url("slide_toggle") public static SlideTogglePage slideTogglePage; + + @Url("snack_bar") + public static SnackBarPage snackBarPage; } diff --git a/jdi-light-angular-tests/src/main/java/io/github/com/pages/AngularPage.java b/jdi-light-angular-tests/src/main/java/io/github/com/pages/AngularPage.java index 776bc1c465..690b23fdd7 100644 --- a/jdi-light-angular-tests/src/main/java/io/github/com/pages/AngularPage.java +++ b/jdi-light-angular-tests/src/main/java/io/github/com/pages/AngularPage.java @@ -7,7 +7,6 @@ import com.epam.jdi.light.ui.html.elements.common.Icon; import io.github.com.pages.sections.GridListSection; import io.github.com.pages.sections.ListSection; -import io.github.com.pages.sections.SnackbarSection; import io.github.com.pages.sections.TabGroupSection; import io.github.com.pages.sections.TableSection; @@ -22,7 +21,6 @@ public class AngularPage extends WebPage { public static Dialog dialog; public static ListSection listSection; public static GridListSection gridListSection; - public static SnackbarSection snackbarSection; public static TabGroupSection tabsSection; public static TableSection tableSection; } diff --git a/jdi-light-angular-tests/src/main/java/io/github/com/pages/SnackBarPage.java b/jdi-light-angular-tests/src/main/java/io/github/com/pages/SnackBarPage.java new file mode 100644 index 0000000000..179221624b --- /dev/null +++ b/jdi-light-angular-tests/src/main/java/io/github/com/pages/SnackBarPage.java @@ -0,0 +1,39 @@ +package io.github.com.pages; + +import com.epam.jdi.light.angular.elements.complex.Snackbar; +import com.epam.jdi.light.elements.complex.dropdown.Dropdown; +import com.epam.jdi.light.elements.pageobjects.annotations.locators.JDropdown; +import com.epam.jdi.light.elements.pageobjects.annotations.locators.UI; +import com.epam.jdi.light.ui.html.elements.common.Button; +import com.epam.jdi.light.ui.html.elements.common.TextField; + +public class SnackBarPage extends AngularPage { + @UI("#snack-bar-custom-component-input") + public static TextField durationInput; + + @UI("#snack-bar-custom-component-button") + public static Button showCustomSnackbarButton; + + @UI("#snack-bar-custom-component") + public static Snackbar customSnackbar; + + @UI("#snack-bar-message-input") + public static TextField basicSnackbarMessageInput; + + @UI("#snack-bar-action-input") + public static TextField basicSnackbarActionInput; + + @UI("#snack-bar-open-button") + public static Button showBasicSnackbarButton; + @UI("//simple-snack-bar") + public static Snackbar snackbar; + + @JDropdown(root = "mat-form-field.mat-mdc-form-field-type-mat-select:has(#snack-bar-position-horizontal-select)", value = "span.mat-mdc-select-min-line", list = "//ancestor::body//mat-option") + public static Dropdown horizontalPositionDropdown; + + @JDropdown(root = "mat-form-field.mat-mdc-form-field-type-mat-select:has(#snack-bar-position-vertival-select)", value = "span.mat-mdc-select-min-line", list = "//ancestor::body//mat-option") + public static Dropdown verticalPositionDropdown; + + @UI("#snack-bar-position-open-button") + public static Button showPositionSnackbarButton; +} diff --git a/jdi-light-angular-tests/src/main/java/io/github/com/pages/sections/SnackbarSection.java b/jdi-light-angular-tests/src/main/java/io/github/com/pages/sections/SnackbarSection.java deleted file mode 100644 index 6583b5e363..0000000000 --- a/jdi-light-angular-tests/src/main/java/io/github/com/pages/sections/SnackbarSection.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.com.pages.sections; - -import com.epam.jdi.light.angular.elements.complex.Snackbar; -import com.epam.jdi.light.elements.composite.Section; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.UI; -import com.epam.jdi.light.ui.html.elements.common.Button; -import com.epam.jdi.light.ui.html.elements.common.TextField; - -public class SnackbarSection extends Section { - - @UI("#snack-bar-message-input") - public TextField messageInput; - - @UI("#snack-bar-action-input") - public TextField actionInput; - - @UI("#snack-bar-open-button") - public Button openButton; - - @UI("//simple-snack-bar") - public Snackbar basicSnackbar; - - @UI("#snack-bar-custom-component-input") - public TextField durationInput; - - @UI("#snack-bar-custom-component-button") - public Button customSnackbarOpenButton; - - @UI("#snack-bar-custom-component") - public Snackbar customSnackbar; -} diff --git a/jdi-light-angular-tests/src/test/java/io/github/epam/angular/tests/elements/complex/SnackbarTests.java b/jdi-light-angular-tests/src/test/java/io/github/epam/angular/tests/elements/complex/SnackbarTests.java index 5fa5fcd158..6c3db446f7 100644 --- a/jdi-light-angular-tests/src/test/java/io/github/epam/angular/tests/elements/complex/SnackbarTests.java +++ b/jdi-light-angular-tests/src/test/java/io/github/epam/angular/tests/elements/complex/SnackbarTests.java @@ -1,70 +1,121 @@ package io.github.epam.angular.tests.elements.complex; -import com.jdiai.tools.func.JAction; +import com.epam.jdi.light.angular.elements.enums.Position; import io.github.epam.TestsInit; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Ignore; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import static io.github.com.StaticSite.angularPage; -import static io.github.com.pages.AngularPage.snackbarSection; -import static io.github.epam.site.steps.States.shouldBeLoggedIn; +import static com.epam.jdi.light.angular.elements.enums.Position.CENTER_BOTTOM; +import static com.epam.jdi.light.angular.elements.enums.Position.CENTER_TOP; +import static com.epam.jdi.light.angular.elements.enums.Position.LEFT_BOTTOM; +import static com.epam.jdi.light.angular.elements.enums.Position.LEFT_TOP; +import static com.epam.jdi.light.angular.elements.enums.Position.RIGHT_BOTTOM; +import static com.epam.jdi.light.angular.elements.enums.Position.RIGHT_TOP; +import static com.epam.jdi.light.elements.base.Conditions.hidden; +import static com.epam.jdi.light.elements.base.Conditions.visible; +import static com.jdiai.tools.Timer.waitCondition; +import static io.github.com.StaticSite.snackBarPage; +import static io.github.com.pages.SnackBarPage.basicSnackbarActionInput; +import static io.github.com.pages.SnackBarPage.basicSnackbarMessageInput; +import static io.github.com.pages.SnackBarPage.customSnackbar; +import static io.github.com.pages.SnackBarPage.durationInput; +import static io.github.com.pages.SnackBarPage.horizontalPositionDropdown; +import static io.github.com.pages.SnackBarPage.showBasicSnackbarButton; +import static io.github.com.pages.SnackBarPage.showCustomSnackbarButton; +import static io.github.com.pages.SnackBarPage.showPositionSnackbarButton; +import static io.github.com.pages.SnackBarPage.snackbar; +import static io.github.com.pages.SnackBarPage.verticalPositionDropdown; -// TODO Move to the new page -@Ignore public class SnackbarTests extends TestsInit { private static final String MESSAGE = "Test Message"; private static final String ACTION = "Test Action"; - @BeforeMethod + @BeforeClass public void before() { - shouldBeLoggedIn(); - angularPage.shouldBeOpened(); + snackBarPage.open(); + waitCondition(() -> snackBarPage.isOpened()); + snackBarPage.checkOpened(); } @Test - public void checkBasicSnackbarTest() { - snackbarSection.messageInput.setValue(MESSAGE); - snackbarSection.actionInput.setValue(ACTION); - snackbarSection.openButton.click(); - - snackbarSection.basicSnackbar.is().displayed(); - snackbarSection.basicSnackbar.has().message(MESSAGE); - snackbarSection.basicSnackbar.has().action(ACTION); + public void basicSnackbarTest() { + basicSnackbarMessageInput.setValue(MESSAGE); + basicSnackbarActionInput.setValue(ACTION); + showBasicSnackbarButton.click(); + + snackbar.is() + .displayed(); + snackbar.has() + .message(MESSAGE); + snackbar.action() + .has() + .text(ACTION); } @Test - public void checkSnackbarClickActionDismissTest() { - snackbarSection.messageInput.setValue(MESSAGE); - snackbarSection.actionInput.setValue(ACTION); - snackbarSection.openButton.click(); + public void snackbarDismissAfterClickActionTest() { + basicSnackbarMessageInput.setValue(MESSAGE); + basicSnackbarActionInput.setValue(ACTION); + showBasicSnackbarButton.click(); - snackbarSection.basicSnackbar.clickAction(); - snackbarSection.basicSnackbar.is().disappear(); + snackbar.action() + .click(); + snackbar.is() + .disappear(); } @Test - public void checkSnackbarWithNoActionTest() { - snackbarSection.messageInput.setValue(MESSAGE); - snackbarSection.actionInput.setValue(""); - snackbarSection.openButton.click(); + public void snackbarWithNoActionTest() { + basicSnackbarMessageInput.setValue(MESSAGE); + basicSnackbarActionInput.setValue(""); + showBasicSnackbarButton.click(); - snackbarSection.basicSnackbar.has().action(); + snackbar.has() + .shown(); + snackbar.action() + .has() + .notAppear(); } @Test - public void checkSnackbarDurationTest() { - final int DURATION = 5; + public void snackbarDurationTest() { + final int DURATION = 3; + + durationInput.setValue(String.valueOf(DURATION)); + showCustomSnackbarButton.click(); - JAction action = () -> { - snackbarSection.customSnackbar.base().timer().wait(() -> snackbarSection.customSnackbar.isDisplayed()); - snackbarSection.customSnackbar.base().timer().wait(() -> snackbarSection.customSnackbar.isHidden()); - }; + customSnackbar.shouldBe(visible); + customSnackbar.is() + .notHidden(DURATION); + customSnackbar.shouldBe(hidden); + } - snackbarSection.durationInput.setValue(String.valueOf(DURATION)); - snackbarSection.customSnackbarOpenButton.click(); + @Test(dataProvider = "positionProvider") + public void snackbarPositionTest(String horizontal, String vertical, Position position) { + horizontalPositionDropdown.select(horizontal); + verticalPositionDropdown.select(vertical); + showPositionSnackbarButton.click(); + snackbar.has() + .shown() + .and() + .has() + .position(position); + } - //duration(DURATION, 1000, action); + @DataProvider(name = "positionProvider") + public Object[][] providePositions() { + return new Object[][]{ + {"Start", "Top", LEFT_TOP}, + {"Center", "Top", CENTER_TOP}, + {"End", "Top", RIGHT_TOP}, + {"Left", "Top", LEFT_TOP}, + {"Right", "Top", RIGHT_TOP}, + {"Start", "Bottom", LEFT_BOTTOM}, + {"Center", "Bottom", CENTER_BOTTOM}, + {"End", "Bottom", RIGHT_BOTTOM}, + {"Left", "Bottom", LEFT_BOTTOM}, + {"Right", "Bottom", RIGHT_BOTTOM}}; } -} +} \ No newline at end of file diff --git a/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/asserts/PositionAssert.java b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/asserts/PositionAssert.java new file mode 100644 index 0000000000..adda7368b4 --- /dev/null +++ b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/asserts/PositionAssert.java @@ -0,0 +1,24 @@ +package com.epam.jdi.light.angular.asserts; + +import com.epam.jdi.light.angular.elements.enums.Position; +import com.epam.jdi.light.angular.elements.interfaces.HasPosition; +import com.epam.jdi.light.asserts.generic.UIAssert; +import com.epam.jdi.light.common.JDIAction; +import org.hamcrest.Matchers; + +import static com.epam.jdi.light.asserts.core.SoftAssert.jdiAssert; + +public abstract class PositionAssert, E extends HasPosition> extends UIAssert { + + @JDIAction(value = "Assert that '{name}' has position '{0}'", isAssert = true) + public A position(String position) { + jdiAssert(element().position(), Matchers.is(Position.fromFullString(position))); + return (A) this; + } + + @JDIAction(value = "Assert that '{name}' has position '{0}'", isAssert = true) + public A position(Position position) { + jdiAssert(element().position(), Matchers.is(position)); + return (A) this; + } +} diff --git a/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/asserts/SnackbarAssert.java b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/asserts/SnackbarAssert.java index 2f2d0da173..c9df06655c 100644 --- a/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/asserts/SnackbarAssert.java +++ b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/asserts/SnackbarAssert.java @@ -1,29 +1,52 @@ package com.epam.jdi.light.angular.asserts; import com.epam.jdi.light.angular.elements.complex.Snackbar; -import com.epam.jdi.light.asserts.generic.UIAssert; import com.epam.jdi.light.common.JDIAction; +import com.jdiai.tools.Timer; +import com.jdiai.tools.func.JAction; import org.hamcrest.Matchers; import static com.epam.jdi.light.asserts.core.SoftAssert.jdiAssert; -public class SnackbarAssert extends UIAssert { +public class SnackbarAssert extends PositionAssert { @JDIAction(value = "Assert that '{name}' has message '{0}'", isAssert = true) public SnackbarAssert message(String expected) { - jdiAssert(element().getMessageText(), Matchers.is(expected)); + jdiAssert(element().message() + .getText(), Matchers.containsString(expected)); return this; } - @JDIAction(value = "Assert that '{name}' has no action", isAssert = true) - public SnackbarAssert action() { - jdiAssert(element().isActionDisplayed(), Matchers.is(false), "ERROR MESSAGE IS REQUIRED"); + @JDIAction(value = "Assert that '{name}' has action '{0}'", isAssert = true) + public SnackbarAssert action(String expected) { + jdiAssert(element().action() + .getText(), Matchers.containsString(expected)); return this; } - @JDIAction(value = "Assert that '{name}' has action {0}", isAssert = true) - public SnackbarAssert action(String expected) { - jdiAssert(element().getActionText(), Matchers.is(expected)); + @JDIAction(value = "Assert that '{name}' has action button", isAssert = true) + public SnackbarAssert hasAction() { + jdiAssert(element().action() + .isExist(), Matchers.is(true), "Action doesn't exist in snackbar"); + return this; + } + + @JDIAction(value = "Assert that '{name}' has no action button", isAssert = true) + public SnackbarAssert hasNoAction() { + jdiAssert(element().action() + .isNotExist(), Matchers.is(true), "Action exists in snackbar"); + return this; + } + + @JDIAction(value = "Assert that '{name}' is visible during '{0}' seconds", isAssert = true) + public SnackbarAssert notHidden(int timeoutSec) { + JAction action = () -> { + element().base() + .timer() + .wait(() -> element().isDisplayed()); + }; + boolean result = new Timer(timeoutSec * 1000L).wait(action); + jdiAssert(result ? "displayed" : "hidden", Matchers.is("displayed")); return this; } } diff --git a/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/complex/Snackbar.java b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/complex/Snackbar.java index c72973dfb0..3877cefb0d 100644 --- a/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/complex/Snackbar.java +++ b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/complex/Snackbar.java @@ -1,6 +1,9 @@ package com.epam.jdi.light.angular.elements.complex; import com.epam.jdi.light.angular.asserts.SnackbarAssert; +import com.epam.jdi.light.angular.elements.common.Button; +import com.epam.jdi.light.angular.elements.enums.Position; +import com.epam.jdi.light.angular.elements.interfaces.HasPosition; import com.epam.jdi.light.common.JDIAction; import com.epam.jdi.light.elements.base.UIBaseElement; import com.epam.jdi.light.elements.common.UIElement; @@ -9,39 +12,31 @@ * To see an example of Snackbar web element please visit https://material.angular.io/components/snack-bar/overview. */ -public class Snackbar extends UIBaseElement { - protected UIElement message; - protected String messageLocator = "./span"; +public class Snackbar extends UIBaseElement implements HasPosition { + private static final String MESSAGE_LOCATOR = ".mat-mdc-snack-bar-label .mdc-snackbar__label"; + private static final String ACTION_LOCATOR = ".//button"; + private static final String OVERLAY_LOCATOR = "//ancestor::div[@class='cdk-global-overlay-wrapper']"; - protected UIElement action; - protected String actionLocator = ".//button"; - - public Snackbar() { - message = new UIElement(); - message.core().setLocator(messageLocator); - - action = new UIElement(); - action.core().setLocator(actionLocator); + @JDIAction("Get '{name}' action") + public Button action() { + return new Button().setCore(Button.class, core().find(ACTION_LOCATOR)); } @JDIAction("Get '{name}' message") - public String getMessageText() { - return message.getValue(); - } - - @JDIAction("Get '{name}' action") - public String getActionText() { - return action.getValue(); + public UIElement message() { + return core().find(MESSAGE_LOCATOR); } - @JDIAction("Click '{name}' action") - public void clickAction() { - action.click(); + @Override + @JDIAction("Get '{name}' position") + public Position position() { + return getPositionFromAttribute("style"); } - @JDIAction("Is '{name}' action displayed") - public boolean isActionDisplayed() { - return action.isDisplayed(); + @Override + public Position getPositionFromAttribute(String attributeValue) { + return Position.fromFullString(core().find(OVERLAY_LOCATOR) + .attr(attributeValue)); } @Override diff --git a/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/enums/Position.java b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/enums/Position.java new file mode 100644 index 0000000000..06aac22fa2 --- /dev/null +++ b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/enums/Position.java @@ -0,0 +1,73 @@ +package com.epam.jdi.light.angular.elements.enums; + +import org.apache.commons.lang3.StringUtils; + +import static com.epam.jdi.light.common.Exceptions.runtimeException; +import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; + +/** + * Contains named constants representing element positions. + * Each constant includes information about its string representation. + */ +public enum Position { + TOP(null, "align-items: flex-start;"), + BOTTOM(null, "align-items: flex-end;"), + + CENTER("justify-content: center;", null), + LEFT("justify-content: flex-start;", null), + RIGHT("justify-content: flex-end;", null), + + CENTER_BOTTOM("justify-content: center;", "align-items: flex-end;"), + LEFT_BOTTOM("justify-content: flex-start;", "align-items: flex-end;"), + RIGHT_BOTTOM("justify-content: flex-end;", "align-items: flex-end;"), + CENTER_TOP("justify-content: center;", "align-items: flex-start;"), + LEFT_TOP("justify-content: flex-start;", "align-items: flex-start;"), + RIGHT_TOP("justify-content: flex-end;", "align-items: flex-start;"); + private static String justifyContent = "justify-content"; + private static String alignItems = "align-items"; + private final String horizontalPosition; + private final String verticalPosition; + + Position(String horizontalPosition, String verticalPosition) { + this.horizontalPosition = horizontalPosition; + this.verticalPosition = verticalPosition; + } + + public String getHorizontalPosition() { + return horizontalPosition; + } + + public String getVerticalPosition() { + return verticalPosition; + } + + public static Position fromFullString(String text) { + if (StringUtils.isBlank(text)) { + throw runtimeException(String.format("%s: input string can't be empty", Position.class.getName())); + } + boolean horizontalPositionMatches = containsIgnoreCase(text, justifyContent); + boolean verticalPositionMatches = containsIgnoreCase(text, alignItems); + for (Position position : Position.values()) { + boolean horizontal; + boolean vertical; + if (horizontalPositionMatches) { + horizontal = containsIgnoreCase(text, position.horizontalPosition); + } else { + horizontal = position.horizontalPosition == null; + } + if (verticalPositionMatches) { + vertical = containsIgnoreCase(text, position.verticalPosition); + } else { + vertical = position.verticalPosition == null; + } + if (horizontal && vertical) { + return position; + } + } + throw runtimeException(String.format("No appropriate %s constant found for value '%s'", Position.class.getName(), text)); + } + + public String toString() { + return horizontalPosition + " " + verticalPosition; + } +} diff --git a/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/interfaces/HasPosition.java b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/interfaces/HasPosition.java new file mode 100644 index 0000000000..0467334822 --- /dev/null +++ b/jdi-light-angular/src/main/java/com/epam/jdi/light/angular/elements/interfaces/HasPosition.java @@ -0,0 +1,35 @@ +package com.epam.jdi.light.angular.elements.interfaces; + +import com.epam.jdi.light.angular.elements.enums.Position; +import com.epam.jdi.light.elements.common.UIElement; +import com.epam.jdi.light.elements.interfaces.base.ICoreElement; +import org.apache.commons.lang3.StringUtils; + +public interface HasPosition extends ICoreElement { + + Position position(); + + /** + * Gets {@link Position} named constant from the given class name. + * + * @param className String class name to find position + * @param element UIElement to check + * @return position as {@link Position} + */ + default Position getPositionFromClass(UIElement element, String className) { + return Position.fromFullString(element.classes().stream() + .filter(c -> StringUtils.startsWith(c, className)) + .map(c -> c.replace(className, "")) + .findFirst().orElse("")); + } + + /** + * Gets {@link Position} named constant from the given attribute value. + * + * @param attributeValue String attribute value to find position + * @return position as {@link Position} + */ + default Position getPositionFromAttribute(String attributeValue) { + return Position.fromFullString(core().attr(attributeValue)); + } +}