diff --git a/config/browser.properties b/config/browser.properties index 7fd1f91e..5b185154 100644 --- a/config/browser.properties +++ b/config/browser.properties @@ -89,7 +89,7 @@ browserprofile.Chrome_1024x768.name = Chrome 1024x768 browserprofile.Chrome_1024x768.browser = chrome browserprofile.Chrome_1024x768.browserResolution = 1024x768 -browserprofile.Chrome_1024x768.arguments = -ignore-certificate-errors +browserprofile.Chrome_1024x768.arguments = -ignore-certificate-errors; --remote-allow-origins=* # Small Firefox browserprofile.Firefox_1024x768.name = Firefox 1024x768 diff --git a/config/localization.yaml b/config/localization.yaml index f6e0b0da..c5a71f53 100644 --- a/config/localization.yaml +++ b/config/localization.yaml @@ -1,52 +1,302 @@ default: + header: + topNavigation: + "1": + title: World of Nature + subCategory: + "1": Animals + "2": Flowers + "3": Trees + "2": + title: Dining + subCategory: + "1": Cold Cuts + "2": Main Dishes + "3": Sweets + "3": + title: Transportation + subCategory: + "1": Air Travel + "2": Classic Cars + "3": Railways + "4": + title: Panoramas + subCategory: + "1": Architecture + "2": Fireworks + "3": Landscapes + "4": XXL Panoramas + userMenu: + title: "WELCOME: " + createAccount: CREATE ACCOUNT + signIn: SIGN IN + accountOverview: MY ACCOUNT + logout: LOGOUT + miniCart: + title: + singular: ITEM IN THE CART + plural: ITEMS IN THE CART + subtotal: SUBTOTAL + viewCart: VIEW CART + sale: + first: "25% off (Almost) Everything! Use Code: Posters Sale" + second: "Our biggest sale yet 50% off all Posters" footer: - text: Copyright (c) 2013-2020 Xceptance Software Technologies GmbH -- This software is for demo purposes only and not meant to be used in production. - search: - results: - text: Your results for your search + copyright: Copyright (c) 2013-2020 Xceptance Software Technologies GmbH -- This software is for demo purposes only and not meant to be used in production. HomePage: title: Posters - The Ultimate Online Shop + slider: + headline: + "1": NORTH BOSTON + "2": BOSTON SUNSET + "3": BRYCE NATIONAL PARK, UTAH I + "4": BRYCE NATIONAL PARK, UTAH II + button: BUY + intro: Began with a simple idea "SHATATATATA!" - M. Scott + hotProducts: HOT PRODUCTS + featuredContent: + "1": "BLUE MORPHO BUTTERFLY" + "2": "SNOWDROP ANEMONE" + "3": "INDIAN SUMMER: RED BEECHES" + "4": "FINGER FOOD" + "5": "STUFFED TURKEY" + "6": "FRUIT TART WITH COCOA" + "7": "SWISS AIR AIRBUS A320" + "8": "IFA F8" + "9": "GERMAN STEAM LOCOMOTIVE" + "10": "GROCHWITZ CASTLE, GERMANY" + "11": "NEW YEAR'S FIREWORKS III" + "12": "LINNAEAN GARDEN AND MUSEUM, SWEDEN" + shopAllProducts: Shop All Products validation: successfulOrder: Thank you for shopping with us! successfulLogin: Login successful. Have fun in our shop! successfulAccountDeletion: Your account has been deleted. We hope to see you soon again! + CategoryPage: + search: + resultText: "Your results for your search: " + pagination: + goToNextPage: ">" + goToLastPage: ">>" + goToPrevPage: "<" + goToFirstPage: "<<" NoHitsPage: validation: noProductsFound: Sorry! No results found matching your search. Please try again. ProductdetailPage: - addToCartButton: - text: Add to cart - AccountPages: - email: Email address* - firstname: First name* - lastname: Last name* - password: Password* - passwordRepeat: Repeat password* - yourEmail: Your email* - yourPassword: Your password* - signIn: Sign in + size: + "16x12": 16 x 12 in + "32x24": 32 x 24 in + "64x48": 64 x 48 in + "96x32": 96 x 32 in + style: + matte: matte + gloss: gloss + print: "Print information:" + addToCartButton: Add to cart + CartPage: + title: Cart + errorMessage: Your cart is empty. Continue shopping. + GuestShippingAddressPage: + title: Enter a shipping address + ReturningCustomerShippingAddressPage: + title: Select or enter a shipping address + button: + addNewShipAddr: Add a new shipping address + useShipAddr: Continue + GuestBillingAddressPage: + title: Enter a billing address + ReturningCustomerBillingAddressPage: + title: Select or enter a billing address + button: + addNewBillAddr: Add a new billing address + useBillAddr: Use this billing address + AddressPages: + breadcrumb: + cart: CART/ + shippingAddress: SHIPPING ADDRESS / + billingAddress: BILLING ADDRESS / + payment: PAYMENT / + placeOrder: PLACE ORDER / + processWrap: + "1": + number: "01" + name: SHOPPING CART + "2": + number: "02" + name: SHIPPING ADDRESS + "3": + number: "03" + name: BILLING ADDRESS + "4": + number: "04" + name: PAYMENT METHOD + "5": + number: "05" + name: CHECKOUT + "6": + number: "06" + name: ORDER COMPLETE + fillIn: + headlines: + fullName: FULL NAME* + company: COMPANY + address: ADDRESS* + city: CITY* + state: STATE/PROVINCE* + zip: ZIP/POSTAL CODE* + country: COUNTRY* + useAddressForBilling: "Use this address for billing?*" + requiredFields: "* Required fields" + placeholder: + yourName: Your Name + companyName: company name + address: "Street address, Apartment, etc." + zip: "Zip / Postal" + dropdown: + usa: United States + germany: Germany + radio: + "yes": "YES" + "no": "NO" + button: Continue + GuestPaymentPage: + title: Enter a payment method + fillIn: + headlines: + cardNumber: "CARD NUMBER*" + cardHolderName: "CARDHOLDER'S NAME*" + expirationDate: EXPIRATION DATE* + placeholder: + cardNumber: Card number + cardOwnerName: "Cardholder's name" + expireMonth: + january: 01 + february: 02 + march: 03 + april: 04 + may: 05 + june: 06 + july: 07 + august: 08 + september: 09 + october: 10 + november: 11 + december: 12 + expireYear: + "2023": 2023 + "2024": 2024 + "2025": 2025 + "2026": 2026 + "2027": 2027 + "2028": 2028 + "2029": 2029 + "2030": 2030 + "2031": 2031 + "2032": 2032 + "2033": 2033 + button: Continue + ReturningCustomerPaymentPage: + title: Select or enter a credit card + button: + addNewCreditCard: Add a new credit card + useCreditCard: Use this credit card + PlaceOrderPage: + overview: + title: Order Overview + headlines: + shippingAddress: Shipping Address + billingAddress: Billing Address + payment: Payment Settings + button: Order with costs + OrderConfirmationPage: + thankYouMessage: Thank you for purchasing, Your order is complete + button: Continue Shopping + LoginPage: + title: Sign-In + headlines: + email: YOUR EMAIL* + password: YOUR PASSWORD* + placeholder: + email: Email address + password: Password + button: Sign in newCustomer: New customer - createAccount: Create account createNewAccount: Create new Account validation: - successfulAccountCreation: Your account has been created. Log in with your email address and password. - emailDoesNotExistError: The email address you entered doesn't exist. Please try again. - incorrectPasswordError: The password you entered is incorrect. Please try again. + successfulRegistration: Your account has been created. Log in with your email address and password. + emailDoesNotExist: The email address you entered doesn't exist. Please try again. + incorrectPassword: The password you entered is incorrect. Please try again. + RegisterPage: + title: Create an account + headlines: + firstName: FIRST NAME* + lastName: LAST NAME* + email: EMAIL ADDRESS* + password: PASSWORD* + passwordRepeat: REPEAT PASSWORD* + placeholder: + firstName: First name + lastName: Last name + email: Email address + password: Password + passwordRepeat: Confirm password + button: Create account + AccountOverviewPage: + title: My Account + button: + orderHistory: Order History + myAddresses: My Addresses + paymentSettings: Payment Settings + personalData: Personal Data + OrderHistoryPage: + title: Order History + tableHead: + purchasedPosters: PURCHASED POSTERS + orderDetails: ORDER DETAILS + quantity: QUANTITY + MyAddressesPage: + title: My Addresses + headlines: + shipAddr: Shipping Address + billAddr: Billing Address + PaymentSettingsPage: + title: Payment Settings + button: + addNewCreditCard: Add a new credit card + PersonalDataPage: + title: Personal Data + headlines: + name: Name + email: Email + buttons: + changeData: Change Name or Email + changePassword: Change your password + deleteAccount: Delete your account + DeleteAccontPage: + title: Delete your account + headline: YOUR PASSWORD* + placeholder: Password + button: Delete General: - addresses: - fullname: Full name* - company: Company - address: Address* - city: City* - state: State/Province* - zip: ZIP/Postal code* - country: Country* - payment: - cardnumber: Card number* - cardholdername: Cardholder's name* - expirationdate: Expiration date* product: - style: style - size: size - quantity: Quantity + style: style + size: size + quantity: Quantity + priceSummary: + title: Summary + subtotal: "Subtotal:" + shipping: "Shipping:" + tax: "Tax (6.0%)" + grandTotal: Total + productTable: + product: PRODUCT + unitPrice: UNIT PRICE + quantity: QUANTITY + update: REMOVE/UPDATE + totalPrice: TOTAL PRICE + button: + addNewShipAddr: Add a new shipping address + addNewBillAddr: Add a new billing address + \ No newline at end of file diff --git a/config/neodymium.properties b/config/neodymium.properties index be69ebd3..9891205d 100644 --- a/config/neodymium.properties +++ b/config/neodymium.properties @@ -1,8 +1,8 @@ neodymium.url = ${neodymium.url.protocol}://${neodymium.url.host}${neodymium.url.path} -neodymium.url.protocol = https +neodymium.url.protocol = http neodymium.url.host = localhost neodymium.url.path = ${neodymium.url.port}/ -neodymium.url.port = :8443 +neodymium.url.port = :8080 neodymium.locale = en_US diff --git a/src/test/java/posters/dataobjects/Address.java b/src/test/java/posters/dataobjects/Address.java deleted file mode 100644 index 5efa5408..00000000 --- a/src/test/java/posters/dataobjects/Address.java +++ /dev/null @@ -1,124 +0,0 @@ -package posters.dataobjects; - -/** - * @author pfotenhauer - */ -public class Address -{ - String firstName; - - String lastName; - - String company; - - String street; - - String city; - - String state; - - String zip; - - String country; - - /** - * @param firstName - * the firstName to set - * @param lastName - * the lastName to set - * @param company - * the company to set - * @param street - * the street to set - * @param city - * the city to set - * @param state - * the state to set - * @param zip - * the zip to set - * @param country - * the country to set - */ - public Address(String firstName, String lastName, String company, String street, String city, String state, String zip, String country) - { - this.firstName = firstName; - this.lastName = lastName; - this.company = company; - this.street = street; - this.city = city; - this.state = state; - this.zip = zip; - this.country = country; - } - - /** - * @return the firstName - */ - public String getFirstName() - { - return firstName; - } - - /** - * @return the lastName - */ - public String getLastName() - { - return lastName; - } - - /** - * @return the company - */ - public String getCompany() - { - return company; - } - - /** - * @return the street - */ - public String getStreet() - { - return street; - } - - /** - * @return the city - */ - public String getCity() - { - return city; - } - - /** - * @return the state - */ - public String getState() - { - return state; - } - - /** - * @return the zip - */ - public String getZip() - { - return zip; - } - - /** - * @return the country - */ - public String getCountry() - { - return country; - } - - @Override - public String toString() - { - return String.format("Address [firtName()=%s, lastName()=%s, company()=%s, street()=%s, zip()=%s, city()=%s, state()=%s, country()=%s]", - getFirstName(), getLastName(), getCompany(), getStreet(), getZip(), getCity(), getState(), getCountry()); - } -} diff --git a/src/test/java/posters/dataobjects/Product.java b/src/test/java/posters/dataobjects/Product.java deleted file mode 100644 index debf559a..00000000 --- a/src/test/java/posters/dataobjects/Product.java +++ /dev/null @@ -1,130 +0,0 @@ -package posters.dataobjects; - -import com.xceptance.neodymium.util.Neodymium; - -import posters.pageobjects.utility.PriceHelper; - -/** - * @author pfotenhauer - */ -public class Product -{ - String name; - - String unitPrice; - - String style; - - String size; - - int amount; - - /** - * @param name - * the name to set - * @param unitPrice - * the unitPrice to set - * @param style - * the style to set - * @param size - * the size to set - * @param amount - * the amount to set - */ - public Product(String name, String unitPrice, String style, String size, int amount) - { - this.name = name; - this.unitPrice = unitPrice; - this.style = style; - this.size = size; - this.amount = amount; - } - - /** - * @return the name - */ - public String getName() - { - return name; - } - - /** - * @return the unitPrice - */ - public String getUnitPrice() - { - return unitPrice; - } - - /** - * @return the style - */ - public String getStyle() - { - return style; - } - - /** - * @return the size - */ - public String getSize() - { - return size; - } - - /** - * @return the amount - */ - public int getAmount() - { - return amount; - } - - @Override - public String toString() - { - return String.format("Product [name()=%s, size()=%s, style()=%s, price()=%s]", getName(), getSize(), getStyle(), getUnitPrice(), getAmount()); - } - - @Override - public boolean equals(Object obj) - { - Product other = (Product) obj; - if (name.equals(other.name) && unitPrice.equals(other.unitPrice) && style.equals(other.style) && size.equals(other.size)) - { - return true; - } - return false; - } - - public String getRowRegex() - { - return getName() - + "\\n[a-zA-Z\\s\\.\\,0-9\\!]+\\n" - + Neodymium.localizedText("General.product.style") - + "\\:\\s" + getStyle() - + "\\n" - + Neodymium.localizedText("General.product.size") - + "\\:\\s" + getSize(); - } - - public String getCartRowRegex() - { - return getName() - + "\\n" - + Neodymium.localizedText("General.product.quantity") - + ":\\s" + "\\d+\\s\\(" + getStyle() - + ",\\s" + getSize() - + "\\s\\)\\n\\$\\d+\\.\\d+"; - } - - private double getUnitPriceDouble() - { - return Double.parseDouble(PriceHelper.removeCurrency(unitPrice)); - } - - public double getTotalPrice() - { - return amount * getUnitPriceDouble(); - } -} diff --git a/src/test/java/posters/dataobjects/User.java b/src/test/java/posters/dataobjects/User.java deleted file mode 100644 index fb906754..00000000 --- a/src/test/java/posters/dataobjects/User.java +++ /dev/null @@ -1,78 +0,0 @@ -package posters.dataobjects; - -/** - * @author pfotenhauer - */ -public class User -{ - String firstName; - - String lastName; - - String email; - - String password; - - /** - * - */ - public User() - { - } - - /** - * @param firstName - * the firstName to set - * @param lastName - * the lastName to set - * @param email - * the email to set - * @param password - * the password to set - */ - public User(String firstName, String lastName, String email, String password) - { - this.firstName = firstName; - this.lastName = lastName; - this.email = email; - this.password = password; - } - - /** - * @return the firstName - */ - public String getFirstName() - { - return firstName; - } - - /** - * @return the lastName - */ - public String getLastName() - { - return lastName; - } - - /** - * @return the email - */ - public String getEmail() - { - return email; - } - - /** - * @return the password - */ - public String getPassword() - { - return password; - } - - @Override - public String toString() - { - return String.format("User [firstName()=%s, lastName()=%s, email()=%s, password()=%s]", getFirstName(), getLastName(), getEmail(), getPassword()); - } -} diff --git a/src/test/java/posters/flows/CartCleanUpFlow.java b/src/test/java/posters/flows/CartCleanUpFlow.java index ba63f7ee..b6633990 100644 --- a/src/test/java/posters/flows/CartCleanUpFlow.java +++ b/src/test/java/posters/flows/CartCleanUpFlow.java @@ -1,31 +1,25 @@ package posters.flows; -import static com.codeborne.selenide.Selenide.$; - import io.qameta.allure.Step; import posters.pageobjects.pages.browsing.HomePage; -/** - * @author pfotenhauer - */ public class CartCleanUpFlow { - @Step("cart clean up flow") + @Step("clean up cart flow") public static void flow() { - // click on the shop logo to ensure a home page afterwards - $(".colorlib-nav #brand").click(); - - // open the minicart - var homePage = new HomePage(); - homePage.miniCart.openMiniCart(); + HomePage homePage = new HomePage(); // go to cart page - var cartPage = homePage.miniCart.openCartPage(); - while (cartPage.hasProductsInCart()) + var cartPage = homePage.header.miniCart.openCartPage(); + + // remove the first product as long as one is available + while (cartPage.header.miniCart.getTotalCount() != 0) { - // remove the first product as long as one is available cartPage.removeProduct(1); } + + // go to homepage + homePage = cartPage.openHomePage(); } } diff --git a/src/test/java/posters/flows/DeleteUserFlow.java b/src/test/java/posters/flows/DeleteUserFlow.java index d8692e7e..80cafcfc 100644 --- a/src/test/java/posters/flows/DeleteUserFlow.java +++ b/src/test/java/posters/flows/DeleteUserFlow.java @@ -1,52 +1,39 @@ package posters.flows; import io.qameta.allure.Step; -import posters.dataobjects.User; +import posters.tests.testdata.dataobjects.User; import posters.pageobjects.pages.browsing.HomePage; -import posters.pageobjects.pages.user.LoginPage; -/** - * @author pfotenhauer - */ public class DeleteUserFlow { - /** - * @param user - */ - @Step("delete user flow") - public static LoginPage flow(User user) + @Step("delete '{user}' flow") + public static void flow(User user) { - var homePage = new HomePage(); + HomePage homePage = new HomePage(); - // ensure that the user is logged in - var loginPage = new LoginPage(); - if (!homePage.userMenu.isLoggedIn()) - { - loginPage = homePage.userMenu.openLogin(); - homePage = loginPage.sendLoginform(user); - } - - // go to account page - var accountOverviewPage = homePage.userMenu.openAccountOverview(); + // go to account page and validate + var accountOverviewPage = homePage.header.userMenu.openAccountOverviewPage(); accountOverviewPage.validateStructure(); - // go to personal data page + // go to personal data page and validate var personalDataPage = accountOverviewPage.openPersonalData(); personalDataPage.validateStructure(); + personalDataPage.validatePersonalData(user); - // go to account deletion page - var deleteAccountPage = personalDataPage.openDeleteAccount(); + // go to account deletion page and validate + var deleteAccountPage = personalDataPage.openDeleteAccountPage(); + deleteAccountPage.validateStructure(); - // delete the account + // delete the account and validate success message homePage = deleteAccountPage.deleteAccount(user.getPassword()); homePage.validateSuccessfulDeletedAccount(); // verify that the account is not available anymore - loginPage = homePage.userMenu.openLogin(); - loginPage.validateStructure(); - loginPage.sendFalseLoginform(user); + var loginPage = homePage.header.userMenu.openLoginPage(); + loginPage.sendFalseLoginForm(user); loginPage.validateWrongEmail(user.getEmail()); - - return loginPage.isExpectedPage(); + + // go to homePage + homePage = loginPage.openHomePage(); } } diff --git a/src/test/java/posters/flows/OpenLoginPageFlow.java b/src/test/java/posters/flows/OpenLoginPageFlow.java index 663aa7f3..42091fac 100644 --- a/src/test/java/posters/flows/OpenLoginPageFlow.java +++ b/src/test/java/posters/flows/OpenLoginPageFlow.java @@ -12,7 +12,7 @@ public static LoginPage flow() var homePage = OpenHomePageFlow.flow(); // open login page and check for expected page - var loginPage = homePage.userMenu.openLogin(); + var loginPage = homePage.header.userMenu.openLoginPage(); loginPage.isExpectedPage(); return loginPage.isExpectedPage(); diff --git a/src/test/java/posters/pageobjects/components/CheckoutHeader.java b/src/test/java/posters/pageobjects/components/CheckoutHeader.java index 97dc1960..32693654 100644 --- a/src/test/java/posters/pageobjects/components/CheckoutHeader.java +++ b/src/test/java/posters/pageobjects/components/CheckoutHeader.java @@ -3,11 +3,12 @@ import static com.codeborne.selenide.Condition.exist; import static com.codeborne.selenide.Selenide.$; -/** - * @author pfotenhauer - */ +import io.qameta.allure.Step; + public class CheckoutHeader extends AbstractComponent { + @Override + @Step("ensure availability checkout header") public void isComponentAvailable() { $("#headerCheckout").should(exist); diff --git a/src/test/java/posters/pageobjects/components/ErrorMessage.java b/src/test/java/posters/pageobjects/components/ErrorMessage.java index 5eac148e..9b999490 100644 --- a/src/test/java/posters/pageobjects/components/ErrorMessage.java +++ b/src/test/java/posters/pageobjects/components/ErrorMessage.java @@ -13,25 +13,25 @@ public class ErrorMessage extends AbstractComponent { private SelenideElement errorMessage = $("#errorMessage"); + @Override + @Step("ensure availability error message") public void isComponentAvailable() { errorMessage.should(exist); } - @Step("validate that the error message {message} is visible") + /// ----- validate error message ----- /// + + @Step("validate visibility of error message '{message}'") public void validateErrorMessage(String message) { - // Wait until javascript makes the error message visible - // Waits until javascript makes the error message visible. - errorMessage.shouldBe(visible); - // Makes sure the correct text is displayed. - errorMessage.shouldHave(exactText("× " + message)); + errorMessage.find("strong").shouldHave(exactText(message)).shouldBe(visible); + errorMessage.find(".close").shouldHave(exactText("×")).shouldBe(visible); } @Step("validate that no error message is visible") public void validateNoErrorMessageOnPage() { - // Check that the error message is not visible. errorMessage.shouldNotBe(visible); } } diff --git a/src/test/java/posters/pageobjects/components/Footer.java b/src/test/java/posters/pageobjects/components/Footer.java index df657c09..4b13bd04 100644 --- a/src/test/java/posters/pageobjects/components/Footer.java +++ b/src/test/java/posters/pageobjects/components/Footer.java @@ -2,6 +2,7 @@ import static com.codeborne.selenide.Condition.text; import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; import com.codeborne.selenide.SelenideElement; @@ -13,17 +14,25 @@ public class Footer extends AbstractComponent { private SelenideElement footer = $("#footer"); + @Override + @Step("ensure availability footer") public void isComponentAvailable() { footer.should(exist); } - @Step("validate the footer") - public void validate() + /// ----- validate footer ----- /// + + @Step("validate footer") + public void validateStructure() { - isComponentAvailable(); - // Asserts the footer contains the correct text. - footer.shouldHave(text(Neodymium.localizedText("footer.text"))); - + // validate about xceptance + $("#footer .icon-twitter").shouldBe(visible); + $("#footer .icon-facebook").shouldBe(visible); + $("#footer .icon-linkedin").shouldBe(visible); + $("#footer .icon-dribbble").shouldBe(visible); + + // validate copyright text + footer.shouldHave(text(Neodymium.localizedText("footer.copyright"))); } } diff --git a/src/test/java/posters/pageobjects/components/Header.java b/src/test/java/posters/pageobjects/components/Header.java index 9c0a2c3c..862cb0f5 100644 --- a/src/test/java/posters/pageobjects/components/Header.java +++ b/src/test/java/posters/pageobjects/components/Header.java @@ -1,12 +1,41 @@ package posters.pageobjects.components; import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; +import io.qameta.allure.Step; + public class Header extends AbstractComponent { + public Search search = new Search(); + + public TopNavigation topNav = new TopNavigation(); + + public UserMenu userMenu = new UserMenu(); + + public MiniCart miniCart = new MiniCart(); + + public SaleBanner saleBanner = new SaleBanner(); + + @Override + @Step("validate availability header") public void isComponentAvailable() { $("#globalNavigation").should(exist); } + + /// ----- validate header ----- /// + + @Step("validate header") + public void validateStructure() + { + $("#brand").shouldBe(visible); + + search.validateStructure(); + topNav.validateStructure(); + userMenu.validateStructure(); + miniCart.validateStructure(); + saleBanner.validateStructure(); + } } diff --git a/src/test/java/posters/pageobjects/components/MiniCart.java b/src/test/java/posters/pageobjects/components/MiniCart.java index 07b5ee55..7c36cced 100644 --- a/src/test/java/posters/pageobjects/components/MiniCart.java +++ b/src/test/java/posters/pageobjects/components/MiniCart.java @@ -2,170 +2,221 @@ import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; import static com.codeborne.selenide.Condition.not; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; import static com.codeborne.selenide.Selenide.$$; +import com.codeborne.selenide.ElementsCollection; import com.codeborne.selenide.SelenideElement; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.Product; +import posters.tests.testdata.dataobjects.Product; import posters.pageobjects.pages.checkout.CartPage; import posters.pageobjects.utility.PriceHelper; -/** - * @author pfotenhauer - */ public class MiniCart extends AbstractComponent { private SelenideElement headerCart = $("#headerCartOverview"); - private final static String miniCartSelector = "#miniCartMenu"; + private SelenideElement subOrderPrice = $("#miniCartMenu .subOrderPrice"); - private SelenideElement miniCart = $(miniCartSelector); + private SelenideElement miniCart = $("#miniCartMenu"); - private SelenideElement subOrderPrice = $(miniCartSelector + " .subOrderPrice"); + private SelenideElement miniCartTitle = $(".cartMiniProductCounter"); private SelenideElement totalCountElement = $("#headerCartOverview .headerCartProductCount"); - + private SelenideElement goToCartButton = $(".goToCart"); + private ElementsCollection productCounts = $$(".prodCount"); + + private ElementsCollection productPrices = $$(".prodPrice strong"); + + @Override + @Step("ensure availability mini cart") public void isComponentAvailable() { $("#btnCartOverviewForm").should(exist); } + /// ----- mini cart navigation ------ /// + @Step("open the mini cart") public void openMiniCart() { - // Hover over the cart icon headerCart.hover(); - // Wait for mini cart to appear - // Wait for the mini cart to show - miniCart.waitUntil(visible, Neodymium.configuration().selenideTimeout()); + miniCart.waitUntil(visible, 9000); } @Step("close the mini cart") public void closeMiniCart() { - // Move the mouse out of the area $("#brand").hover(); - // Wait for mini cart to disappear - // Wait for the mini cart to disappear - miniCart.waitUntil(not(visible), Neodymium.configuration().selenideTimeout()); + miniCart.waitUntil(not(visible), 9000); } @Step("open the cart page") public CartPage openCartPage() { - - // Open the cart - // Click on the button to go to the Cart - goToCartButton.click(); + openMiniCart(); + goToCartButton.click(); return new CartPage().isExpectedPage(); } - @Step("get the total product count from mini cart") - public int getTotalCount() - { - return Integer.parseInt(totalCountElement.text()); - } - - @Step("validate the mini cart total product count") - public void validateTotalCount(int totalCount) - { - totalCountElement.shouldHave(exactText(Integer.toString(totalCount))); - } + /// ----- get data mini cart ----- /// @Step("get the subtotal price from mini cart") public String getSubtotal() { - // Store the mini cart subtotal - // Open mini cart openMiniCart(); - // Store subtotal in oldSubTotal String subtotal = subOrderPrice.text(); - // Close mini cart closeMiniCart(); return subtotal; } - @Step("validate the mini cart subtotal price") - public void validateSubtotal(String subtotal) + @Step("get the total product count from mini cart") + public int getTotalCount() { - // Verify the mini cart shows the specified subtotal - // Open mini cart - openMiniCart(); - // Verify subtotal equals specified subtotal - // Compare the subtotal to the parameter - subOrderPrice.shouldHave(exactText(subtotal)); - // Close Mini Cart - closeMiniCart(); + return Integer.parseInt(totalCountElement.text()); } /** - * @param position - * @param product + * Note: Loops through all total product prices in the mini cart and adds it to the "subtotal" variable. + * + * @return subtotal (The sum of all total product prices) */ + @Step("calculate sum of all total product prices") + public String calculateSubtotal() + { + double subtotal = 0; + + for (SelenideElement totalProductPrice : productPrices) + { + subtotal = PriceHelper.calculateSubtotalMiniCart(subtotal, totalProductPrice.getText()); + } - @Step("validate '{product}' in the mini cart") - public void validateMiniCart(int position, Product product) + return PriceHelper.format(subtotal); + } + + /** + * Note: If there is at least 1 item in the cart, it loops through all total product counts in the mini cart + * and adds it to the "totalCount" variable. + * + * @return totalCount (The sum of all total product counts) + */ + @Step("calculate total count via product counts") + public int calculateTotalCount() { - validateMiniCart(position, product.getName(), product.getStyle(), product.getSize(), product.getAmount(), - PriceHelper.format(product.getTotalPrice())); + int totalCount = 0; + + if ($(".cartItems").exists()) + { + for (SelenideElement productCount : productCounts) + { + totalCount = PriceHelper.calculateTotalCountMiniCart(totalCount, productCount.getText()); + } + + return totalCount; + } + + return totalCount; } - @Step("validate '{product}' in the mini cart by name") - public void validateMiniCartByProduct(Product product) + /// ----- validate mini cart structure ----- /// + + @Step("validate the mini cart total product count equals '{totalCount}'") + public void validateTotalCount(int totalCount) { - SelenideElement productContainer = $$(".cartItems").filter(matchText(product.getCartRowRegex())).shouldHaveSize(1).first(); + totalCountElement.shouldHave(exactText(Integer.toString(totalCount))); + } - productContainer.find(".prodName").shouldHave(exactText(product.getName())); - productContainer.find(".prodStyle").shouldHave(exactText(product.getStyle())); - productContainer.find(".prodSize").shouldHave(exactText(product.getSize())); - productContainer.find(".prodCount").shouldHave(exactText(Integer.toString(product.getAmount()))); - productContainer.find(".prodPrice").shouldHave(exactText(PriceHelper.format(product.getTotalPrice()))); + @Step("validate the mini cart title") + public void validateTitle() + { + if (getTotalCount() == 1) + { + miniCartTitle.shouldHave(exactText(getTotalCount() + " " + Neodymium.localizedText("header.miniCart.title.singular"))).shouldBe(visible); + } + else + { + miniCartTitle.shouldHave(exactText(getTotalCount() + " " + Neodymium.localizedText("header.miniCart.title.plural"))).shouldBe(visible); + } } - /** - * @param position - * @param product - * @param productAmount - * @param productTotalPrice - */ - @Step("validate '{product}' in the mini cart") - public void validateMiniCart(int position, Product product, int productAmount, String productTotalPrice) + @Step("validate the mini cart subtotal price equals '{subtotal}'") + public void validateSubtotal(String subtotal) { - validateMiniCart(position, product.getName(), product.getStyle(), product.getSize(), productAmount, productTotalPrice); + subOrderPrice.shouldHave(exactText(subtotal)).shouldBe(visible); + } + + @Step("validate mini cart") + public void validateStructure() + { + openMiniCart(); + + // validate shopping cart icon + $(".icon-shopping-cart").shouldBe(visible); + + // validate total count + validateTotalCount(calculateTotalCount()); + + // validate title + // TODO - fix consistency mini cart title + // validateTitle(); + + // validate label subtotal + $(".labelText").shouldHave(exactText(Neodymium.localizedText("header.miniCart.subtotal"))).shouldBe(visible); + + // validate subtotal + if (getTotalCount() == 0) + { + // if there are no items in cart + validateSubtotal("$0.00"); + } + else + { + // if there are items in cart + validateSubtotal(calculateSubtotal()); + } + + // validate view cart button + $("#miniCartMenu .linkButton").shouldHave(exactText(Neodymium.localizedText("header.miniCart.viewCart"))).shouldBe(visible); + + closeMiniCart(); } - private void validateMiniCart(int position, String productName, String productStyle, String productSize, int productCount, String prodTotalPrice) + /// ----- validate mini cart item ----- /// + + private void validateMiniCartItem(int position, String productName, String productStyle, String productSize, int productCount, String prodTotalPrice) { - // Open the mini cart openMiniCart(); - // Validate data of specified item - // Product Name - // ul.cartMiniElementList li:nth-child(" + position + ") ul.cartItems + + // selector for product SelenideElement miniCartItem = $$("#miniCartMenu .cartItems").get(position - 1); - // Compares the name of the cart item at position @{position} to the parameter + + // validate parameters miniCartItem.find(".prodName").shouldHave(exactText(productName)); - // Product Style - // Compares the style of the cart item at position @{position} to the parameter miniCartItem.find(".prodStyle").shouldHave(exactText(productStyle)); - // Product Size - // Compares the style of the cart item at position @{position} to the parameter miniCartItem.find(".prodSize").shouldHave(exactText(productSize)); - // Amount - // Compares the amount of the cart item at position @{position} to the parameter miniCartItem.find(".prodCount").shouldHave(exactText(Integer.toString(productCount))); - // Price - // Compares the price of the cart item at position @{position} to the parameter miniCartItem.find(".prodPrice").shouldHave(exactText(prodTotalPrice)); - // Close mini cart + closeMiniCart(); } + + @Step("validate '{product}' on position {position} in the mini cart") + public void validateMiniCartItem(int position, Product product) + { + validateMiniCartItem(position, product.getName(), product.getStyle(), product.getSize(), product.getAmount(), + PriceHelper.format(product.getTotalPrice())); + } + + @Step("validate '{product}' on position '{position}' in the mini cart after changing it's quantity") + public void validateMiniCartItem(int position, Product product, int productAmount, String productPrice) + { + validateMiniCartItem(position, product.getName(), product.getStyle(), product.getSize(), productAmount, productPrice); + } } diff --git a/src/test/java/posters/pageobjects/components/Pagination.java b/src/test/java/posters/pageobjects/components/Pagination.java index 69ffddf2..d55dad0e 100644 --- a/src/test/java/posters/pageobjects/components/Pagination.java +++ b/src/test/java/posters/pageobjects/components/Pagination.java @@ -1,46 +1,122 @@ package posters.pageobjects.components; -import static com.codeborne.selenide.Condition.matchText; +import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; -import java.util.Random; - -import com.codeborne.selenide.Selectors; +import com.codeborne.selenide.ElementsCollection; import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.pageobjects.pages.browsing.CategoryPage; public class Pagination extends AbstractComponent { private SelenideElement pagination = $("#pagination-bottom"); + private ElementsCollection paginationComponents = $$("#pagination-bottom li"); + public void isComponentAvailable() { pagination.shouldBe(visible); } - @Step("get number of available pages") - public int getNumberOfSites() + /// ----- pagination navigation ----- /// + + @Step("click on page number '{pageNumber}'") + public void goToPage(int pageNumber) + { + paginationComponents.findBy(exactText(Integer.toString(pageNumber))).click(); + } + + @Step("click on go to next page") + public void goToNextPage() + { + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToNextPage"))).click(); + } + + @Step("click on go to last page") + public void goToLastPage() + { + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToLastPage"))).click(); + } + + @Step("click on go to previous page") + public void goToPrevPage() { - return pagination.findAll("li > a").filter(matchText("\\d+")).size(); + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToPrevPage"))).click(); } - @Step("get the link to a specific page") - public SelenideElement getSite(String stringNumber) + @Step("click on go to first page") + public void goToFirstPage() { - return pagination.find(Selectors.withText(stringNumber)); + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToFirstPage"))).click(); } - @Step("click on any link represented by a number") - public CategoryPage clickOnRandomSite(Random random) + /// ----- validate pagination ----- /// + + /** + * Note: To get {numberOfPages} it divides {expectedResultCount} by 6 because only 6 results can be displayed + * per page. Then it loops through the page numbers and validates its existence and visibility. + * + * @param expectedResultCount + * (number of results for specific category/search) + */ + @Step("validate visibility numbers in pagination") + public void validateElementNumbers(int expectedResultCount) + { + int numberOfPages = expectedResultCount / 6; + for (int i = 1; i < numberOfPages; i++) + { + paginationComponents.findBy(exactText(Integer.toString(i))).shouldBe(visible); + } + } + + @Step("validate visibility right navigation") + public void validateRightNavigation() + { + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToNextPage"))).shouldBe(visible); + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToLastPage"))).shouldBe(visible); + } + + @Step("validate visibility left navigation") + public void validateLeftNavigation() + { + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToPrevPage"))).shouldBe(visible); + paginationComponents.findBy(exactText(Neodymium.localizedText("CategoryPage.pagination.goToFirstPage"))).shouldBe(visible); + } + + /** + * Note: If there is more than 1 result page it validates the pagination. It loops through the page numbers + * and validates the existence and visibility of the numbers themselves and the icon navigation (<, <<, >, >>) + * + * @param expectedResultCount + * (number of results for specific category/search) + */ + @Step("validate pagination") + public void validateStructure(int expectedResultCount) { - String stringChosenElementValue = Integer.toString(random.nextInt(getNumberOfSites()) + 1); - SelenideElement chosenPaginationLink = getSite(stringChosenElementValue); - chosenPaginationLink.scrollTo(); - chosenPaginationLink.click(); + int numberOfPages = expectedResultCount / 6; + if (numberOfPages > 1) + { + pagination.shouldBe(visible); + + validateElementNumbers(expectedResultCount); + validateRightNavigation(); + + for (int j = 2; j < numberOfPages; j++) + { + goToPage(j); + validateLeftNavigation(); + validateElementNumbers(expectedResultCount); + validateRightNavigation(); + } - return new CategoryPage().isExpectedPage(); + goToLastPage(); + validateLeftNavigation(); + validateElementNumbers(expectedResultCount); + } + else return; } } diff --git a/src/test/java/posters/pageobjects/components/SaleBanner.java b/src/test/java/posters/pageobjects/components/SaleBanner.java new file mode 100644 index 00000000..bf72ce2d --- /dev/null +++ b/src/test/java/posters/pageobjects/components/SaleBanner.java @@ -0,0 +1,33 @@ +package posters.pageobjects.components; + +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; + +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; + +public class SaleBanner extends AbstractComponent +{ + public void isComponentAvailable() + { + $(".sale").should(exist); + } + + /// ----- validate sale banner ----- /// + + private void validateSaleBanner(String text) + { + $$(".owl-stage").findBy(exactText(text)).waitUntil(visible, 9000); + } + + @Step("validate sale banner") + public void validateStructure() + { + validateSaleBanner(Neodymium.localizedText("header.sale.second")); + validateSaleBanner(Neodymium.localizedText("header.sale.first")); + } +} \ No newline at end of file diff --git a/src/test/java/posters/pageobjects/components/Search.java b/src/test/java/posters/pageobjects/components/Search.java index 59660527..0abe631d 100644 --- a/src/test/java/posters/pageobjects/components/Search.java +++ b/src/test/java/posters/pageobjects/components/Search.java @@ -15,23 +15,19 @@ public class Search extends AbstractComponent { private SelenideElement searchField = $("#s"); + @Override + @Step("validate availability search bar") public void isComponentAvailable() { searchField.should(exist); } - @Step("search for '{searchTerm}' without result") - public NoHitsPage noResult(String searchTerm) - { - search(searchTerm); - return new NoHitsPage(); - } - - @Step("search for '{searchTerm}' with result") - public CategoryPage categoryPageResult(String searchTerm) + /// ----- search navigation ----- /// + + @Step("open search field") + public void openSearch() { - search(searchTerm); - return new CategoryPage().isExpectedPage(); + searchField.scrollTo().click(); } @Step("search for '{searchTerm}'") @@ -40,21 +36,35 @@ public void search(String searchTerm) openSearch(); searchField.val(searchTerm).pressEnter(); } - - @Step("open search field") - public void openSearch() + + @Step("validate that '{searchTerm}' is still visible after search") + public void validateSearchTerm(String searchTerm) { - $("#btnSearch").scrollTo().exists(); + openSearch(); + searchField.shouldHave(exactValue(searchTerm)); + } + + @Step("search for '{searchTerm}' without result") + public NoHitsPage noHitsPageResult(String searchTerm) + { + search(searchTerm); + return new NoHitsPage().isExpectedPage(); } - @Step("validate that {searchTerm} is still visible after") - public void validateSearchTerm(String searchTerm) + @Step("search for '{searchTerm}' with result") + public CategoryPage categoryPageResult(String searchTerm) { - // Validate the entered search phrase is still visible in the input - openSearch(); - // Validate the entered search phrase is still visible in the input - searchField.should(visible); - // Validate the entered search phrase is still visible in the input - searchField.should(exactValue(searchTerm)); + search(searchTerm); + return new CategoryPage().isExpectedPage(); + } + + /// ----- validate search ----- /// + + @Step("validate search bar") + public void validateStructure() + { + searchField.shouldBe(visible); + $("#btnSearch").shouldBe(visible); + $(".icon-search").shouldBe(visible); } } diff --git a/src/test/java/posters/pageobjects/components/SuccessMessage.java b/src/test/java/posters/pageobjects/components/SuccessMessage.java index cd0047da..68603ea0 100644 --- a/src/test/java/posters/pageobjects/components/SuccessMessage.java +++ b/src/test/java/posters/pageobjects/components/SuccessMessage.java @@ -13,18 +13,19 @@ public class SuccessMessage extends AbstractComponent { private SelenideElement successMessage = $("#successMessage"); + @Override + @Step("ensure availability success message") public void isComponentAvailable() { successMessage.should(exist); } + + /// ----- validate success message ----- /// - @Step("validate that the success message '{message}' is visible") + @Step("validate visibility of success message '{message}'") public void validateSuccessMessage(String message) { - // Wait until javascript makes the success message visible - // Waits until javascript makes the success message visible. - successMessage.shouldBe(visible); - // Makes sure the correct text is displayed. - successMessage.shouldHave(exactText("× " + message)); + successMessage.find("strong").shouldHave(exactText(message)).shouldBe(visible); + successMessage.find(".close").shouldHave(exactText("×")).shouldBe(visible); } } diff --git a/src/test/java/posters/pageobjects/components/Title.java b/src/test/java/posters/pageobjects/components/Title.java index 1d71415f..bd39e7ef 100644 --- a/src/test/java/posters/pageobjects/components/Title.java +++ b/src/test/java/posters/pageobjects/components/Title.java @@ -3,8 +3,6 @@ import static com.codeborne.selenide.Selenide.title; import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.xceptance.neodymium.util.SelenideAddons; @@ -12,7 +10,6 @@ public class Title extends AbstractComponent { - public void isComponentAvailable() { } @@ -23,12 +20,5 @@ public void validateTitle(String title) SelenideAddons.wrapAssertionError(() -> { Assert.assertEquals(title, title()); }); - - Logger logger = LoggerFactory.getLogger(getClass()); - logger.trace("This is a logging example with severity: 'trace'. Can be found in posters.pageobjects.components.Title class."); - logger.debug("This is a logging example with severity: 'debug'. Can be found in posters.pageobjects.components.Title class."); - logger.info("This is a logging example with severity: 'info'. Can be found in posters.pageobjects.components.Title class."); - logger.warn("This is a logging example with severity: 'warn'. Can be found in posters.pageobjects.components.Title class."); - logger.error("This is a logging example with severity: 'error'. Can be found in posters.pageobjects.components.Title class."); } } diff --git a/src/test/java/posters/pageobjects/components/TopNavigation.java b/src/test/java/posters/pageobjects/components/TopNavigation.java index 797f38b6..b481ea08 100644 --- a/src/test/java/posters/pageobjects/components/TopNavigation.java +++ b/src/test/java/posters/pageobjects/components/TopNavigation.java @@ -1,96 +1,94 @@ package posters.pageobjects.components; +import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; import static com.codeborne.selenide.Selenide.$$; -import java.util.Random; - -import org.openqa.selenium.By; - import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; import posters.pageobjects.pages.browsing.CategoryPage; -/** - * @author pfotenhauer - */ public class TopNavigation extends AbstractComponent { - SelenideElement categoryMenu = $("#categoryMenu"); + private SelenideElement categoryMenu = $("#categoryMenu"); @Override + @Step("ensure availability top navigation") public void isComponentAvailable() { categoryMenu.should(exist); } - - @Step("get the subcategory name") - public String getSubCategoryNameByPosition(int categoryPosition, int subCategoryPosition) + + // ----- category navigation ------ // + + @Step("click on the top category '{topCategory}'") + public CategoryPage clickCategory(String topCategory) { - return $("#categoryMenu > ul > li:nth-of-type(" + categoryPosition + ") ul.dropdown li:nth-of-type(" + subCategoryPosition + ") a").attr("title"); - } - - @Step("click a subcategory") - public CategoryPage clickSubCategoryByPosition(int categoryPosition, int subCategoryPosition) - { - // Open the category page - SelenideElement topCat = $$("#categoryMenu .has-dropdown").get(categoryPosition - 1); - topCat.hover(); - // Clicks the subcategory with position @{subCategoryPosition} - // belonging to the category with position @{categoryPosition} - topCat.find(".dropdown-menu a", subCategoryPosition - 1).click(); + $$(".has-dropdown").findBy(exactText(topCategory)).scrollTo().click(); return new CategoryPage().isExpectedPage(); } - - @Step("click on '{categoryName}' category") - public CategoryPage clickCategory(String categoryName) + + @Step("click on the '{subCategory}' sub category within the top category '{topCategory}'") + public CategoryPage clickSubCategory(String topCategory, String subCategory) { - $(By.linkText(categoryName)).scrollTo().click(); + $$(".has-dropdown").findBy(exactText(topCategory)).hover(); + $$(".navi ul.dropdown-menu li").findBy(exactText(subCategory)).click(); return new CategoryPage().isExpectedPage(); } - - @Step("click on a '{subCategoryName}' subcategory within '{categoryName}'") - public CategoryPage clickSubCategoryByNames(String categoryName, String subCategoryName) + + // ----- validate top navigation ----- // + + @Step("validate top category name '{topCategory}'") + public void validateNavComponent(String topCategory) { - // Open the category page - categoryMenu.find(By.linkText(categoryName)).hover(); - // Clicks the subcategory with position @{subCategoryPosition} - // belonging to the category with position @{categoryPosition} - categoryMenu.find(By.linkText(subCategoryName)).click(); - return new CategoryPage(); + $$(".has-dropdown").findBy(exactText(topCategory)).shouldBe(visible); } - /** - * @param subCategoryName - * @return - */ - @Step("click on a product by name '{productName}'") - public CategoryPage clickSubcategoryByName(String subCategoryName) + @Step("validate sub category name '{subCategory}'") + public void validateSubNavComponent(String subCategory) { - categoryMenu.find(".dropdown-menu li > a[title='" + subCategoryName + "']").parent().parent().parent().hover(); - categoryMenu.find(By.linkText(subCategoryName)).click(); - - return new CategoryPage().isExpectedPage(); + $$(".navi ul.dropdown-menu li").findBy(exactText(subCategory)).shouldBe(visible); } - - @Step("get a random sub category name ") - public String getRandomSubcategoryName(Random random) + + @Step("validate structure top navigation") + public void validateStructure() { - // compute random horizontal category position (for posters: random value from 1 to 4) - // ["World of nature", "Dining", "Transportation", "Panoramas"] - int categoryPositionX = random.nextInt(3) + 1; - - // compute random vertical category position (for posters: random value from 1 to 4) - // if (categoryPositionX == 4) == true then categoryPositionY has range from 1 to 4 - // otherwise from 1 to 3, because any category has 3 subcategories instead of category 4, which has 4 - int categoryPositionY; - if (categoryPositionX == 4) - categoryPositionY = random.nextInt(3) + 1; - else - categoryPositionY = random.nextInt(2) + 1; - - return getSubCategoryNameByPosition(categoryPositionX, categoryPositionY); + // validate navigation bar + validateNavComponent(Neodymium.localizedText("header.topNavigation.1.title")); + validateNavComponent(Neodymium.localizedText("header.topNavigation.2.title")); + validateNavComponent(Neodymium.localizedText("header.topNavigation.3.title")); + validateNavComponent(Neodymium.localizedText("header.topNavigation.4.title")); + + // validate sub navigation "World Of Nature" + $$(".has-dropdown").findBy(exactText(Neodymium.localizedText("header.topNavigation.1.title"))).hover(); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.1.subCategory.1")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.1.subCategory.2")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.1.subCategory.3")); + + // validate sub navigation "Dining" + $$(".has-dropdown").findBy(exactText(Neodymium.localizedText("header.topNavigation.2.title"))).hover(); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.2.subCategory.1")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.2.subCategory.2")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.2.subCategory.3")); + + // validate sub navigation "Transportation" + $$(".has-dropdown").findBy(exactText(Neodymium.localizedText("header.topNavigation.3.title"))).hover(); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.3.subCategory.1")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.3.subCategory.2")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.3.subCategory.3")); + + // validate sub navigation "Panoramas" + $$(".has-dropdown").findBy(exactText(Neodymium.localizedText("header.topNavigation.4.title"))).hover(); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.4.subCategory.1")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.4.subCategory.2")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.4.subCategory.3")); + validateSubNavComponent(Neodymium.localizedText("header.topNavigation.4.subCategory.4")); + + // close sub navigation + $("#globalNavigation").hover(); } } diff --git a/src/test/java/posters/pageobjects/components/UserMenu.java b/src/test/java/posters/pageobjects/components/UserMenu.java index cb604623..b1bbdd40 100644 --- a/src/test/java/posters/pageobjects/components/UserMenu.java +++ b/src/test/java/posters/pageobjects/components/UserMenu.java @@ -1,9 +1,9 @@ package posters.pageobjects.components; -import static com.codeborne.selenide.Condition.cssClass; import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; import static com.codeborne.selenide.Condition.not; +import static com.codeborne.selenide.Condition.text; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; @@ -11,95 +11,124 @@ import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; +import posters.pageobjects.pages.browsing.HomePage; import posters.pageobjects.pages.user.AccountOverviewPage; import posters.pageobjects.pages.user.LoginPage; import posters.pageobjects.pages.user.RegisterPage; -/** - * @author pfotenhauer - */ public class UserMenu extends AbstractComponent { - private final SelenideElement userMenu = $("#userMenu"); + private SelenideElement userMenu = $("#userMenu"); - private final SelenideElement showUserMenu = $("#showUserMenu"); + private SelenideElement showUserMenu = $("#showUserMenu"); + @Override + @Step("ensure availability user menu") public void isComponentAvailable() { showUserMenu.should(exist); } + /// ----- user menu navigation ----- /// + @Step("open user menu") public void openUserMenu() { - // Click the mini cart icon - showUserMenu.scrollTo().click(); - // Wait for mini cart to appear - // Wait for the mini cart to show - userMenu.waitUntil(visible, Neodymium.configuration().selenideTimeout()); + showUserMenu.hover(); + userMenu.waitUntil(visible, 9000); } @Step("close user menu") public void closeUserMenu() { - // Click the mini cart icon again - showUserMenu.scrollTo().click(); - // Move the mouse out of the area - $("#brand").hover(); - // Wait for mini cart to disappear - // Wait for the mini cart to disappear - userMenu.waitUntil(not(visible), Neodymium.configuration().selenideTimeout()); + $(".top-menu").hover(); + userMenu.waitUntil(not(visible), 9000); + } + + @Step("open register page from user menu") + public RegisterPage openRegisterPage() + { + openUserMenu(); + userMenu.find(".goToRegistration").click(); + return new RegisterPage().isExpectedPage(); } @Step("open login page from user menu") - public LoginPage openLogin() + public LoginPage openLoginPage() { openUserMenu(); - userMenu.find(".goToLogin").scrollTo().click(); + userMenu.find(".goToLogin").click(); return new LoginPage().isExpectedPage(); } @Step("open account page from user menu") - public AccountOverviewPage openAccountOverview() + public AccountOverviewPage openAccountOverviewPage() { openUserMenu(); - userMenu.find(".goToAccountOverview").scrollTo().click(); + userMenu.find(".goToAccountOverview").click(); return new AccountOverviewPage().isExpectedPage(); } - @Step("open register page from user menu") - public RegisterPage openRegister() + @Step("perform logout") + public HomePage logout() { openUserMenu(); - userMenu.find(".goToRegistration").scrollTo().click(); - return new RegisterPage().isExpectedPage(); + userMenu.find(".goToLogout").click(); + return new HomePage().isExpectedPage(); } - /** - * @param firstName - */ - @Step("validate that '{firstName}' is logged in") - public void validateLoggedInName(String firstName) - { - // Click on the mini user menu symbol - openUserMenu(); - // Asserts the Menu shows your first name. - userMenu.find(".firstName").shouldHave(exactText(firstName)); - closeUserMenu(); - // Makes sure the mini menu element has the "logged" class active instead of the "not-logged" class. - showUserMenu.find(".icon-user2").shouldHave(cssClass("logged")).shouldHave(exactText("")); - } + /// ----- validate user menu ----- /// @Step("validate that nobody is logged in") public void validateNotLoggedIn() { - userMenu.find(".goToLogin").should(exist); + userMenu.find(".goToLogin").exists(); } @Step("validate that somebody is logged in") - public boolean isLoggedIn() + public boolean validateIsLoggedIn() { - return userMenu.find(".goToAccountOverview").exists(); + return userMenu.find(".firstName").exists(); + } + + @Step("validate that '{firstName}' is displayed in user menu") + public void validateLoggedInName(String firstName) + { + openUserMenu(); + userMenu.find(".firstName").shouldHave(exactText(firstName)); + closeUserMenu(); + } + + @Step("validate logged in user menu") + public void validateStructure() + { + openUserMenu(); + + // validate user icon + $(".icon-user2").shouldBe(visible); + + // validate title + userMenu.find(".userMenuHeader").shouldHave(text(Neodymium.localizedText("header.userMenu.title"))).shouldBe(visible); + + // validate buttons + if (validateIsLoggedIn()) + { + // if customer is logged in + userMenu.find(".goToAccountOverview").shouldHave(exactText(Neodymium.localizedText("header.userMenu.accountOverview"))).shouldBe(visible); + userMenu.find(".goToLogout").shouldHave(exactText(Neodymium.localizedText("header.userMenu.logout"))).shouldBe(visible); + userMenu.find(".icon-info-large").shouldBe(visible); + userMenu.find(".icon-log-out").shouldBe(visible); + } + else + { + // if customer is not logged in + userMenu.find(".goToRegistration").shouldHave(exactText(Neodymium.localizedText("header.userMenu.createAccount"))).shouldBe(visible); + userMenu.find(".goToLogin").shouldHave(exactText(Neodymium.localizedText("header.userMenu.signIn"))).shouldBe(visible); + userMenu.find(".icon-user-add-outline").shouldBe(visible); + userMenu.find(".icon-log-in").shouldBe(visible); + } + + closeUserMenu(); } } diff --git a/src/test/java/posters/pageobjects/pages/AbstractPageObject.java b/src/test/java/posters/pageobjects/pages/AbstractPageObject.java index 8d382317..dcf5b60f 100644 --- a/src/test/java/posters/pageobjects/pages/AbstractPageObject.java +++ b/src/test/java/posters/pageobjects/pages/AbstractPageObject.java @@ -2,16 +2,8 @@ import static com.codeborne.selenide.Selenide.$; -import org.apache.commons.lang3.StringUtils; - -import com.xceptance.neodymium.util.Neodymium; -import com.xceptance.neodymium.visual.ai.AI; - import posters.pageobjects.components.Title; -/** - * @author pfotenhauer - */ public abstract class AbstractPageObject { public Title title = new Title(); @@ -23,31 +15,6 @@ public AbstractPageObject isExpectedPage() abstract public void validateStructure(); - public void validateVisual(String testCaseName) - { - String className = this.getClass().getSimpleName(); - - if (StringUtils.isAllEmpty(testCaseName)) - { - new AI().execute(Neodymium.getDriver(), className, "validate" + className); - } - else - { - new AI().execute(Neodymium.getDriver(), testCaseName, "validate" + className); - } - } - - public void validateStructureAndVisual() - { - validateStructureAndVisual(null); - } - - public void validateStructureAndVisual(String testCaseName) - { - validateStructure(); - validateVisual(testCaseName); - } - public void scrollToTop() { $("body").scrollTo(); diff --git a/src/test/java/posters/pageobjects/pages/browsing/AbstractBrowsingPage.java b/src/test/java/posters/pageobjects/pages/browsing/AbstractBrowsingPage.java index 1a4ddfe0..71db6dcd 100644 --- a/src/test/java/posters/pageobjects/pages/browsing/AbstractBrowsingPage.java +++ b/src/test/java/posters/pageobjects/pages/browsing/AbstractBrowsingPage.java @@ -3,11 +3,7 @@ import posters.pageobjects.components.ErrorMessage; import posters.pageobjects.components.Footer; import posters.pageobjects.components.Header; -import posters.pageobjects.components.MiniCart; -import posters.pageobjects.components.Search; import posters.pageobjects.components.SuccessMessage; -import posters.pageobjects.components.TopNavigation; -import posters.pageobjects.components.UserMenu; import posters.pageobjects.pages.AbstractPageObject; public abstract class AbstractBrowsingPage extends AbstractPageObject @@ -16,14 +12,6 @@ public abstract class AbstractBrowsingPage extends AbstractPageObject public Footer footer = new Footer(); - public MiniCart miniCart = new MiniCart(); - - public Search search = new Search(); - - public TopNavigation topNav = new TopNavigation(); - - public UserMenu userMenu = new UserMenu(); - public SuccessMessage successMessage = new SuccessMessage(); public ErrorMessage errorMessage = new ErrorMessage(); @@ -35,10 +23,10 @@ public void validateStructure() header.isComponentAvailable(); footer.isComponentAvailable(); - miniCart.isComponentAvailable(); - search.isComponentAvailable(); - topNav.isComponentAvailable(); - userMenu.isComponentAvailable(); + header.miniCart.isComponentAvailable(); + header.search.isComponentAvailable(); + header.topNav.isComponentAvailable(); + header.userMenu.isComponentAvailable(); successMessage.isComponentAvailable(); errorMessage.isComponentAvailable(); } diff --git a/src/test/java/posters/pageobjects/pages/browsing/CategoryPage.java b/src/test/java/posters/pageobjects/pages/browsing/CategoryPage.java index 853bbdd9..2d11283a 100644 --- a/src/test/java/posters/pageobjects/pages/browsing/CategoryPage.java +++ b/src/test/java/posters/pageobjects/pages/browsing/CategoryPage.java @@ -1,32 +1,25 @@ package posters.pageobjects.pages.browsing; -import static com.codeborne.selenide.CollectionCondition.sizeGreaterThan; import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.text; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; -import static com.codeborne.selenide.Selenide.$$; -import java.util.Random; - -import com.codeborne.selenide.ElementsCollection; import com.codeborne.selenide.SelenideElement; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; import posters.pageobjects.components.Pagination; -/** - * @author pfotenhauer - */ public class CategoryPage extends AbstractBrowsingPage { public Pagination pagination = new Pagination(); private SelenideElement productOverview = $("#productOverview"); + private SelenideElement titleCategoryName = $("#titleCategoryName"); + @Override @Step("ensure this is a category page") public CategoryPage isExpectedPage() @@ -36,13 +29,7 @@ public CategoryPage isExpectedPage() return this; } - @Step("validate category name '{categoryName}' on category page") - public void validateCategoryName(String categoryName) - { - // Category name - // Ensures the category headline contains the category name - $("#titleCategoryName").shouldBe(text(categoryName)); - } + /// ----- validate content category page ----- /// @Override @Step("validate category page structure") @@ -50,149 +37,68 @@ public void validateStructure() { super.validateStructure(); - // Amount of results - // Assures the amount of posters displayed in the headline is not 0. - $("#totalProductCount").shouldNotBe(exactText("0")); - // Results - // Assures there's at least one product shown - $("#product0").shouldBe(visible); - } + // validate poster count in headline is not 0 + $("#totalProductCount").shouldNotBe(exactText("0")).shouldBe(visible); - /** - * @param row - * @param column - * @return - */ - @Step("click on a product by position in grid") - public ProductDetailPage clickProductByPosition(int row, int column) - { - // Open the product detail page - // Clicks a product by position. Because of the html code, this requires x and y coordinates. - SelenideElement rowContainer = $$("#products > .row").get(row - 1); - rowContainer.find(".thumbnail", column - 1).scrollTo().click(); - return new ProductDetailPage().isExpectedPage(); + // validate at least 1 poster is displayed + $("#product0").shouldBe(visible); } /** - * @param row - * @param column - * @return + * Note: If {categoryName} contains a ".", it's a localization string, localized by Neodymium. Else a search + * term was used. Both cases have a different headline to validate. + * + * @param categoryName + * (name of specific category of top navigation) + * @param expectedResultCount + * (number of results for specific category/search) */ - @Step("get a product name by position in grid") - public String getProductNameByPosition(int row, int column) + @Step("validate category name '{categoryName}' and amount results '{expectedResultCount}' is on category page") + public void validateCategoryHeadline(String categoryName, int expectedResultCount) { - SelenideElement rowContainer = productOverview.findAll("#products #pRows").get(row - 1); - return rowContainer.find("h2.pName", column - 1).text(); + if ($("#titleSearchText").exists()) + { + // if {categoryName} is search input + $("#titleSearchText").should(matchText(Neodymium.localizedText("CategoryPage.search.resultText"))).shouldBe(visible); + $("#searchTextValue").shouldHave(exactText(categoryName)).shouldBe(visible); + $("#totalProductCount").shouldHave(exactText(Integer.toString(expectedResultCount))).shouldBe(visible); + } + else + { + // if {categoryName} contains Neodymium localization + titleCategoryName.should(matchText(categoryName)).shouldBe(visible); + titleCategoryName.should(matchText(Integer.toString(expectedResultCount))).shouldBe(visible); + } } - /** - * @param position - * @return - */ - @Step("click on a product by position") - public ProductDetailPage clickProductByPosition(int position) + @Step("validate category page of category '{categoryName}'") + public void validate(String categoryName, int expectedResultCount) { - final int index = position - 1; - - // Open the product detail page - // Click on the product's image and open the product overview page - // Click the product link to open the product detail page - $("#product" + index + " img").scrollTo().click(); - return new ProductDetailPage().isExpectedPage(); + validateStructure(); + validateCategoryHeadline(categoryName, expectedResultCount); } - /** - * @param productName - * @return - */ - @Step("click on a product by name '{productName}'") - public ProductDetailPage clickProductByName(String productName) - { - // Open the product detail page - // Click on the product's image and open the product overview page - // Click the product link to open the product detail page - $("#productOverview .thumbnails .thumbnail a > img.pImage[title='" + productName + "']").scrollTo().click(); - return new ProductDetailPage().isExpectedPage(); - } + /// ----- product by position ----- /// - /** - * @param position - * @return - */ - @Step("get a product name by position") + @Step("get a product name by position '{position}'") public String getProductNameByPosition(int position) { - final int index = position - 1; - // Get the product name - return $("#product" + index + " .desc .pName").text(); + return $("#product" + (position - 1) + " h2").text(); } - /** - * @param searchTerm - * @param searchTermExpectedCount - */ - @Step("validate search results for '{searchTerm}' on category page") - public void validateSearchHits(String searchTerm, int searchTermExpectedCount) - { - $("#titleSearchText").should(exist); - // Validate the headline contains the search phrase - // \\(" + searchTermExpectedCount + " *\\) - $("#titleSearchText").should(matchText(Neodymium.localizedText("search.results.text") + ": '" + searchTerm + "' \\(" + searchTermExpectedCount - + ".*\\)")); - // Verify that the correct search term is displayed - // Validate the entered search phrase is still visible in the input - search.validateSearchTerm(searchTerm); - // Assert the Headline displays the search term. - $(".header-container #searchTextValue").shouldHave(exactText(searchTerm)); - // Verify there are search results - // There is at least one row of results - $("#productOverview #products .row").shouldBe(exist); - // There is at least one product in the results - $$("#productOverview .product-entry").shouldHave(sizeGreaterThan(0)); - // Verify that there is the specified amount of results - // The amount of products shown in the headline matches the expected value - $("#totalProductCount").shouldHave(exactText(Integer.toString(searchTermExpectedCount))); - } - - /** - * @param productName - */ - @Step("validate product '{productName}' is visible on category page") - public void validateProductVisible(String productName) - { - $("#productOverview .thumbnails .thumbnail a > img.pImage[title='" + productName + "']").shouldBe(visible); - } - - /** - * @param categoryName - */ - @Step("validate category page of category '{categoryName}'") - public void validate(String categoryName) - { - validateStructure(); - validateCategoryName(categoryName); - } - - /** - * @param categoryName - */ - @Step("validate category page of category '{categoryName}' and assert visually") - public void validateAndVisualAssert(String categoryName) + @Step("click on a product by position '{position}'") + public ProductDetailPage clickProductByPosition(int position) { - validateStructureAndVisual(); - validateCategoryName(categoryName); + $("#product" + (position - 1)).scrollTo().click(); + return new ProductDetailPage().isExpectedPage(); } - - public String getRandomProductDetailName(Random random) + + /// ----- category page navigation ----- /// + + @Step("open homepage from category page") + public HomePage openHomePage() { - ElementsCollection rows = productOverview.findAll(".thumbnails.row"); - int numberOfRows = rows.size(); - int productIndexX = random.nextInt(numberOfRows); - - SelenideElement row = rows.get(productIndexX); - int numberOfColumns = row.findAll(".thumbnail").filter(visible).size(); - int productIndexY = random.nextInt(numberOfColumns); - - return getProductNameByPosition(productIndexX + 1, productIndexY + 1); + $("#brand").scrollTo().click(); + return new HomePage().isExpectedPage(); } } diff --git a/src/test/java/posters/pageobjects/pages/browsing/HomePage.java b/src/test/java/posters/pageobjects/pages/browsing/HomePage.java index 84257e65..2a83d7e5 100644 --- a/src/test/java/posters/pageobjects/pages/browsing/HomePage.java +++ b/src/test/java/posters/pageobjects/pages/browsing/HomePage.java @@ -1,20 +1,28 @@ package posters.pageobjects.pages.browsing; -import static com.codeborne.selenide.CollectionCondition.sizeGreaterThan; import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; import static com.codeborne.selenide.Selenide.$$; +import com.codeborne.selenide.ElementsCollection; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.User; public class HomePage extends AbstractBrowsingPage { + private ElementsCollection slideNavigation = $$(".flex-control-nav a"); + + private ElementsCollection slideHeadline = $$("#titleSlide h1"); + + private ElementsCollection slideButton = $$("#titleSlide .btn-primary"); + + private ElementsCollection featuredCategories = $$(".pName"); + + private ElementsCollection featuredContent = $$("#productList h2"); + @Override @Step("ensure this is a home page") public HomePage isExpectedPage() @@ -24,91 +32,96 @@ public HomePage isExpectedPage() return this; } - @Step("validate home page structure") + /// ----- validate content homepage ----- /// + + @Step("validate poster slide") + public void validatePosterSlide(String position, String headline) + { + // TODO - improve + slideNavigation.findBy(exactText(position)).click(); + slideNavigation.findBy(exactText(position)).click(); + slideNavigation.findBy(exactText(position)).click(); + + slideHeadline.findBy(exactText(Neodymium.localizedText(headline))).shouldBe(visible); + slideButton.findBy(exactText(Neodymium.localizedText("HomePage.slider.button"))).shouldBe(visible); + } + + @Step("validate poster slide") + public void validatePosterSlide() + { + validatePosterSlide("4", "HomePage.slider.headline.4"); + validatePosterSlide("3", "HomePage.slider.headline.3"); + validatePosterSlide("2", "HomePage.slider.headline.2"); + validatePosterSlide("1", "HomePage.slider.headline.1"); + } + + @Step("validate featured categories") + public void validateFeaturedCategories() + { + $$(".featured-img").shouldHaveSize(4); + featuredCategories.findBy(exactText(Neodymium.localizedText("header.topNavigation.1.title"))).shouldBe(visible); + featuredCategories.findBy(exactText(Neodymium.localizedText("header.topNavigation.2.title"))).shouldBe(visible); + featuredCategories.findBy(exactText(Neodymium.localizedText("header.topNavigation.3.title"))).shouldBe(visible); + featuredCategories.findBy(exactText(Neodymium.localizedText("header.topNavigation.4.title"))).shouldBe(visible); + } + + @Step("validate featured content") + public void validateFeaturedContent() + { + $$(".colorlib-product .container .row h2").findBy(exactText(Neodymium.localizedText("HomePage.hotProducts"))).shouldBe(visible); + $$(".prod-img").shouldHaveSize(12); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.1"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.2"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.3"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.4"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.5"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.6"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.7"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.8"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.9"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.10"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.11"))).shouldBe(visible); + featuredContent.findBy(exactText(Neodymium.localizedText("HomePage.featuredContent.12"))).shouldBe(visible); + } + + @Override + @Step("validate structure home page") public void validateStructure() { super.validateStructure(); - // Verifies the company Logo and name are visible. - $("#colorlib-logo").shouldBe(visible); - - // Verifies the Navigation bar is visible - $("#categoryMenu .navi").shouldBe(visible); - // Asserts there's categories in the nav bar. - $$("#categoryMenu .has-dropdown").shouldHave(sizeGreaterThan(0)); - - // Asserts the first headline is there. - // $("#titleIndex").shouldBe(matchText("[A-Z].{3,}")); + // validate poster slide + // TODO - fix consistent click + //validatePosterSlide(); - // Asserts the animated poster rotation is there. - $(".flex-control-nav").shouldBe(visible); - - // Verifies the 'Intro Quote' section is there. - $(".colorlib-intro .container h2").shouldBe(matchText("[A-Z].{3,}")); + // validate intro + $("#intro").shouldHave(exactText(Neodymium.localizedText("HomePage.intro"))).shouldBe(visible); - // Verifies the "Hot products" section is there. - $(".colorlib-product .colorlib-heading h2").shouldBe(matchText("[A-Z].{3,}")); + // validate featured categories + validateFeaturedCategories(); - // Asserts there's a list of items under "Hot Products". - $(".colorlib-product #productList").shouldBe(visible); - // Asserts there's at least 1 item in the list. - $$(".container .row-pb-md .product-entry").shouldHave(sizeGreaterThan(0)); - } - - @Step("validate home page") - public void validate() - { - validateStructure(); - footer.validate(); - } - - @Step("validate successful order on home page") - public void validateSuccessfulOrder() - { - successMessage.validateSuccessMessage(Neodymium.localizedText("HomePage.validation.successfulOrder")); - // Verify that the mini cart is empty again - miniCart.validateTotalCount(0); - miniCart.validateSubtotal("$0.00"); + // validate featured content + validateFeaturedContent(); + + // validate shop all products button + $("a.btn-primary-shop").shouldHave(exactText(Neodymium.localizedText("HomePage.shopAllProducts"))).shouldBe(visible); } - - /** - * @param firstName - * The name should be shown in the mini User Menu - */ - @Step("validate successful login on home page") + + /// ----- validate success messages ----- /// + + @Step("validate successful login of user '{firstName}' on home page") public void validateSuccessfulLogin(String firstName) { - // Verify that you are logged in + // validate success message successMessage.validateSuccessMessage(Neodymium.localizedText("HomePage.validation.successfulLogin")); - // Verify that the user menu shows your first name - userMenu.validateLoggedInName(firstName); - - } - - /** - * @param user - */ - @Step("validate successful user login on home page") - public void validateSuccessfulLogin(User user) - { - validateSuccessfulLogin(user.getFirstName()); + + // validate {firstName} in user menu + header.userMenu.validateLoggedInName(firstName); } - + @Step("validate successful account deletion on home page") public void validateSuccessfulDeletedAccount() { successMessage.validateSuccessMessage(Neodymium.localizedText("HomePage.validation.successfulAccountDeletion")); } - - public void validateAndVisualAssert() - { - validateStructureAndVisual(); - footer.validate(); - } - - public ProductDetailPage clickOnPresentedProduct(String productName) - { - $$("#productList .thumbnail .pName").filter(exactText(productName)).shouldHaveSize(1).first().click(); - return new ProductDetailPage().isExpectedPage(); - } } diff --git a/src/test/java/posters/pageobjects/pages/browsing/NoHitsPage.java b/src/test/java/posters/pageobjects/pages/browsing/NoHitsPage.java index 8f51b172..9e35efd4 100644 --- a/src/test/java/posters/pageobjects/pages/browsing/NoHitsPage.java +++ b/src/test/java/posters/pageobjects/pages/browsing/NoHitsPage.java @@ -1,28 +1,45 @@ package posters.pageobjects.pages.browsing; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Selenide.$; + import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; public class NoHitsPage extends AbstractBrowsingPage -{ - - @Step("validate no hits page structure") - public void validateStructure() +{ + @Override + @Step("ensure this is a no hits page") + public NoHitsPage isExpectedPage() { - super.validateStructure(); + super.isExpectedPage(); + $("#errorMessage").should(exist); + return this; } - + + /// ----- validate no hits page ----- /// + @Step("validate that no products are on no hits page") public void validateNoProductsFound() { errorMessage.validateErrorMessage(Neodymium.localizedText("NoHitsPage.validation.noProductsFound")); } - - @Step("validate no hits page") - public void validate() + + @Override + @Step("validate structure no hits page") + public void validateStructure() { - validateStructure(); + super.validateStructure(); validateNoProductsFound(); } + + /// ----- no hits page navigation ----- /// + + @Step("open homepage from no hits page") + public HomePage openHomePage() + { + $("#brand").scrollTo().click(); + return new HomePage().isExpectedPage(); + } } diff --git a/src/test/java/posters/pageobjects/pages/browsing/ProductDetailPage.java b/src/test/java/posters/pageobjects/pages/browsing/ProductDetailPage.java index 3d64f0cb..3424c7c0 100644 --- a/src/test/java/posters/pageobjects/pages/browsing/ProductDetailPage.java +++ b/src/test/java/posters/pageobjects/pages/browsing/ProductDetailPage.java @@ -3,17 +3,16 @@ import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; import static com.codeborne.selenide.Condition.matchText; +import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; import com.codeborne.selenide.SelenideElement; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.Product; +import posters.tests.testdata.dataobjects.Product; -/** - * @author pfotenhauer - */ public class ProductDetailPage extends AbstractBrowsingPage { private SelenideElement addToCartButton = $("#btnAddToCart"); @@ -33,118 +32,153 @@ public ProductDetailPage isExpectedPage() return this; } + /// ----- validate content product detail page ----- /// + + private void validateSizeDropdown(String size) + { + productSize.should(matchText(size)).should(exist); + } + + @Step("validate size dropdown") + public void validateSizeDropdown() + { + productSize.scrollTo().click(); + + if ($$("#selectSize option").size() > 1) + { + validateSizeDropdown(Neodymium.localizedText("ProductdetailPage.size.16x12")); + validateSizeDropdown(Neodymium.localizedText("ProductdetailPage.size.32x24")); + validateSizeDropdown(Neodymium.localizedText("ProductdetailPage.size.64x48")); + } + else + { + validateSizeDropdown(Neodymium.localizedText("ProductdetailPage.size.96x32")); + } + + productSize.scrollTo().click(); + } + + @Step("validate style radio") + public void validateStyleRadio() + { + $("#selectStyle .radio:nth-of-type(1)").shouldHave(exactText(Neodymium.localizedText("ProductdetailPage.style.matte"))).shouldBe(visible); + $("#selectStyle .radio:nth-of-type(2)").shouldHave(exactText(Neodymium.localizedText("ProductdetailPage.style.gloss"))).shouldBe(visible); + } + @Override @Step("validate product detail page structure") public void validateStructure() { super.validateStructure(); - // Title - // Make sure we have the proper headline and it is not empty, at least 4 characters, starting with uppercase - // letter, - productName.shouldBe(matchText("[A-Z].{3,}")); - // Price - // Check that the price is correct in its form. A dollar symbol, followed by 1-3 digits, optionally more groups - // of exactly 3 digits separated by a comma as separator, a period and 2 digits for the cents as the end of the - // String. - productPrice.shouldBe(matchText("\\$(\\d{1,3})(,\\d{3})*\\.\\d{2}$")); - // Add to cart button - // Make sure we got an add to cart button and the text matches. - addToCartButton.shouldHave(exactText(Neodymium.localizedText("ProductdetailPage.addToCartButton.text"))); + // validate image + $("#prodImg").shouldBe(visible); + + // validate title + productName.should(matchText("[A-Z].{3,}")).shouldBe(visible); + + // validate product price + productPrice.should(matchText("\\$\\d+\\.\\d{2}")).shouldBe(visible); + + // validate product description + $("#prodDescriptionOverview").shouldBe(visible); + $("#prodDescriptionDetail").shouldBe(visible); + + // validate size selection + validateSizeDropdown(); + + // validate style selection + $("#selectStyle").shouldBe(visible); + validateStyleRadio(); + + // validate print information + $("#prodPrintInfoTitle").shouldHave(exactText(Neodymium.localizedText("ProductdetailPage.print"))).shouldBe(visible); + $("#prodPrintInfo").shouldBe(visible); + + // validate add to cart button + addToCartButton.shouldHave(exactText(Neodymium.localizedText("ProductdetailPage.addToCartButton"))).shouldBe(visible); + $("#btnAddToCart .icon-shopping-cart").shouldBe(visible); + } + + @Step("validate product name '{prodName}' on product detail page") + public void validateProductName(String prodName) + { + productName.shouldHave(exactText(prodName)); } - @Step("validate product name on product detail page") - public void validateProductName(String name) + @Step("validate product detail page") + public void validate(String productName) { - // Verify product name - // compares the displayed product name to the given parameter. - productName.shouldHave(exactText(name)); + validateStructure(); + validateProductName(productName); } - @Step("select size") + /// ----- select product size/style, add to cart ----- /// + + @Step("select size '{size}'") public void setSize(String size) { productSize.selectOptionContainingText(size); } - @Step("select style") + @Step("select style '{style}'") public void setStyle(String style) { $(".radio #finish-" + style).selectRadio(style); - } - @Step("add product to the cart") - public void addToCart() + @Step("click add to cart button") + public void clickAddToCartButton() { addToCartButton.scrollTo().click(); - } - @Step("add product with size:'{size}' and style:'{style}' to cart") + @Step("add product with size '{size}' and style '{style}' to cart") public void addToCart(String size, String style) { - // Style - // Checks the chosen style. - setStyle(style); - // Size - // Selects the chosen size. setSize(size); - // Click the Add to cart button - addToCart(); + setStyle(style); + clickAddToCartButton(); } + /// ----- get product details ----- /// + @Step("get product name from product detail page") public String getProductName() { - // Get the product name to enable usage outside this module. return productName.text(); } + @Step("get product price from product detail page") + public String getProductPrice() + { + return productPrice.text(); + } + @Step("get selected product style from product detail page") public String getChosenStyle() { - // Get the style to enable usage outside this module. - return $(".radio input[name='finish']:checked").val(); + return $("input[name='finish']:checked").val(); } @Step("get selected product size from product detail page") public String getChosenSize() { - // Get the size to enable usage outside this module. return productSize.getSelectedText(); } - @Step("get product price from product detail page") - public String getProductPrice() - { - // Get the product price to enable usage outside this module. - return productPrice.text(); - } - @Step("get product details from product detail page") public Product getProduct() { return new Product(getProductName(), getProductPrice(), getChosenStyle(), getChosenSize(), 1); } - - /** - * @param productName - */ - @Step("validate the product detail page of '{productName}'") - public void validate(String productName) - { - validateStructure(); - validateProductName(productName); - } - - /** - * @param productName - */ - @Step("validate the product detail page of '{productName}' and assert visually") - public void validateAndVisualAssert(String productName) + + /// ----- product detail page navigation ----- /// + + @Step("open homepage from product detail page") + public HomePage openHomePage() { - validateStructureAndVisual(); - validateProductName(productName); + $("#brand").scrollTo().click(); + return new HomePage().isExpectedPage(); } } diff --git a/src/test/java/posters/pageobjects/pages/checkout/AbstractCheckoutPage.java b/src/test/java/posters/pageobjects/pages/checkout/AbstractCheckoutPage.java index 17d448d0..5b890d7e 100644 --- a/src/test/java/posters/pageobjects/pages/checkout/AbstractCheckoutPage.java +++ b/src/test/java/posters/pageobjects/pages/checkout/AbstractCheckoutPage.java @@ -5,12 +5,9 @@ import posters.pageobjects.components.UserMenu; import posters.pageobjects.pages.AbstractPageObject; -/** - * @author pfotenhauer - */ public abstract class AbstractCheckoutPage extends AbstractPageObject { - public CheckoutHeader header = new CheckoutHeader(); + public CheckoutHeader checkoutHeader = new CheckoutHeader(); public Footer footer = new Footer(); @@ -21,7 +18,7 @@ public void validateStructure() { isExpectedPage(); - header.isComponentAvailable(); + checkoutHeader.isComponentAvailable(); footer.isComponentAvailable(); userMenu.isComponentAvailable(); } diff --git a/src/test/java/posters/pageobjects/pages/checkout/BillingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/BillingAddressPage.java deleted file mode 100644 index d51d204f..00000000 --- a/src/test/java/posters/pageobjects/pages/checkout/BillingAddressPage.java +++ /dev/null @@ -1,59 +0,0 @@ -package posters.pageobjects.pages.checkout; - -import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.visible; -import static com.codeborne.selenide.Selenide.$; - -import com.codeborne.selenide.SelenideElement; - -import io.qameta.allure.Step; - -/** - * @author pfotenhauer - */ -public class BillingAddressPage extends AbstractCheckoutPage -{ - private SelenideElement headline = $("#titleBillAddr"); - - @Override - @Step("ensure this is a billing address page") - public BillingAddressPage isExpectedPage() - { - headline.should(exist); - return this; - } - - @Override - @Step("validate billing address page structure") - public void validateStructure() - { - super.validateStructure(); - - // Headline - // Assert the headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // First address - // Makes sure at least one address is visible - $("#billAddr0").shouldBe(visible); - } - - /** - * @param position - * The position of the billing address you want to choose - * @return PaymentPage - */ - @Step("select a billing address") - public PaymentPage selectBillingAddress(int position) - { - final int index = position - 1; - // Select address - // Checks the radio button belonging to the delivery address with index @{index} - $("#billAddr" + index + " input").scrollTo().click(); - // Open the billing address page in the checkout process - // Clicks the continue button - $("#btnUseBillAddress").scrollTo().click(); - - return new PaymentPage().isExpectedPage(); - } -} diff --git a/src/test/java/posters/pageobjects/pages/checkout/CartPage.java b/src/test/java/posters/pageobjects/pages/checkout/CartPage.java index 63696510..b84adfbe 100644 --- a/src/test/java/posters/pageobjects/pages/checkout/CartPage.java +++ b/src/test/java/posters/pageobjects/pages/checkout/CartPage.java @@ -2,33 +2,31 @@ import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exactValue; -import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.hidden; -import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.text; -import static com.codeborne.selenide.Condition.value; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; import static com.codeborne.selenide.Selenide.$$; import org.junit.Assert; +import com.codeborne.selenide.ElementsCollection; import com.codeborne.selenide.SelenideElement; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.Product; +import posters.tests.testdata.dataobjects.Product; import posters.pageobjects.pages.browsing.AbstractBrowsingPage; +import posters.pageobjects.pages.browsing.HomePage; import posters.pageobjects.pages.browsing.ProductDetailPage; import posters.pageobjects.utility.PriceHelper; -/** - * @author pfotenhauer - */ public class CartPage extends AbstractBrowsingPage { + private SelenideElement title = $("#titleCart"); + private SelenideElement cartTable = $("#cartOverviewTable"); + private ElementsCollection tableHead = $$(".product-name span"); + private SelenideElement subTotal = $("#orderSubTotalValue"); @Override @@ -40,10 +38,16 @@ public CartPage isExpectedPage() return this; } - @Step("validate subtotal in the cart") - public void validateSubtotal(String subtotal) + /// ----- validate content cart page ----- /// + + @Step("validate product table head") + public void validateTableHead() { - $$("#cartSummaryList li").findBy(text("Subtotal")).find(".text-right").shouldHave(exactText(subtotal)); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.product"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.unitPrice"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.quantity"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.update"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.totalPrice"))).shouldBe(visible); } @Override @@ -52,296 +56,234 @@ public void validateStructure() { super.validateStructure(); - // Headline - // Makes sure the headline is there and starts with a capital letter - $("#titleCart").shouldBe(matchText("[A-Z].{3,}")); - // Assert there is an item list with at least one item present - // Makes sure the list of cart items is there - cartTable.shouldBe(visible); - // Makes sure there's at least one product in the item list - $("#product0").shouldBe(visible); - // Assert the cart summary is visible - // Makes sure the price breakdown list is there - $("#cartSummaryList").shouldBe(visible); - // Checkout Button - // Makes sure the checkout button is there. - $("#btnStartCheckout").should(exist); - } + // validate title + title.shouldHave(exactText(Neodymium.localizedText("CartPage.title"))).shouldBe(visible); - @Step("validate product in the cart") - public void validateContainsProduct(Product product) - { - SelenideElement productContainer = $$("div.hidden-xs").filter((matchText(product.getRowRegex()))).shouldHaveSize(1).first() - .parent().parent(); - productContainer.find(".productName").shouldHave(exactText(product.getName())); - productContainer.find(".productSize").shouldHave(exactText(product.getSize())); - productContainer.find(".productStyle").shouldHave(exactText(product.getStyle())); - productContainer.find(".productCount").shouldHave(value(Integer.toString(product.getAmount()))); - productContainer.find(".productUnitPrice").shouldHave(exactText(product.getUnitPrice())); - productContainer.find(".productTotalUnitPrice").shouldHave(exactText(PriceHelper.format(product.getTotalPrice()))); + // check if cart contains items, validate + if (header.miniCart.getTotalCount() == 0) + { + $("#errorCartMessage").shouldHave(exactText(Neodymium.localizedText("CartPage.errorMessage"))).shouldBe(visible); + } + else + { + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress + // indicator + // validateProcessWrap(); + + // validate product table head + validateTableHead(); + + // validate product list + cartTable.shouldBe(visible); + + // validate at least 1 product in product list + $("#product0").shouldBe(visible); + + // validate cart summary list + $("#cartSummaryList").shouldBe(visible); + + // validate checkout button + $("#btnStartCheckout").should(visible); + } } - @Step("validate shipping costs on cart page") + @Step("validate shipping costs '{shippingCosts}' on cart page") public void validateShippingCosts(String shippingCosts) { - // Assert the correct shipping price is shown $("#orderShippingCosts").shouldHave(exactText(shippingCosts)); } - /** - * @param shippingCosts - */ - @Step("validate cart page with shipping costs: '{shippingCosts}'") - public void validate(String shippingCosts) + @Step("validate tax on cart page") + public void validateTax(String shippingCosts, String subtotal) + { + String tax = PriceHelper.calculateTax(shippingCosts, subtotal); + $("#orderSubTotalTaxValue").shouldHave(exactText(tax)); + } + + @Step("validate cart page") + public void validate(String shippingCosts, String subtotal) { validateStructure(); validateShippingCosts(shippingCosts); + validateTax(shippingCosts, subtotal); } /** - * @param position - * @param product + * Note: It checks if the price change of subtotal is equal to the price change of the product. + * + * @param position (of specific product in cart) + * @param oldSubTotal (subtotal before adding new product to cart/ increasing product quantity) + * @param oldTotalProductPrice (product price before adding/ increasing product quantity) */ - @Step("validate '{product}' in on the cart page") - public void validateCartItem(int position, Product product) + @Step("validate sub total and line item total after adding on the cart page") + public void validateTotalAfterAdd(int position, String oldSubTotal, double oldTotalProductPrice) { - validateCartItem(position, product.getName(), product.getStyle(), product.getSize(), product.getAmount(), - product.getUnitPrice()); + /// ----- validate total unit price of specified product ----- /// + + SelenideElement productContainer = $("#product" + (position - 1)); + + // store product unit price (without $ sign) for 1 unit + String unitPrice = productContainer.find(".unitPriceShort").text(); + + // store product count + String quantity = $("#productCount" + (position - 1)).val(); + + // calculate price of specified product + String newTotalProductPrice = PriceHelper.totalProductPrice(unitPrice, quantity); + + // verify calculated unit price equals the displayed total unit price + productContainer.find(".productTotalUnitPrice").shouldHave(exactText(newTotalProductPrice)); + + /// ----- validate sub total ----- /// + + String newSubTotal = subTotal.text(); + + // new total - old total = price of item you just added + String productPrice = PriceHelper.substract(newSubTotal, oldSubTotal); + + // price difference for specific product after changing product amount + String totalProductPriceChange = PriceHelper.substract(newTotalProductPrice, PriceHelper.format(oldTotalProductPrice)); + + Assert.assertEquals(productPrice, totalProductPriceChange); } - /** - * @param position - * @param product - * @param productAmount - */ - @Step("validate '{product}' in on the cart page") - public void validateCartItem(int position, Product product, int productAmount) + @Step("validate sub total and line item total after removing on the cart page") + public void validateTotalAfterRemove(String oldSubTotal, String oldTotalProductPrice) { - validateCartItem(position, product.getName(), product.getStyle(), product.getSize(), - productAmount, product.getUnitPrice()); + String newSubTotal = PriceHelper.substract(oldSubTotal, oldTotalProductPrice); + subTotal.shouldHave(exactText(newSubTotal)); } + /// ----- validate product in cart ----- /// + private void validateCartItem(int position, String productName, String productStyle, String productSize, int productAmount, String productPrice) { + // selector for product SelenideElement productContainer = $("#product" + (position - 1)); - // Visibility - // Makes sure a product at the specified index exists and is visible - productContainer.shouldBe(visible); - // Name - // Compares the displayed name with the parameter + + // validate product image + productContainer.find(".product-img").shouldBe(visible); + + // validate parameters productContainer.find(".productName").shouldHave(exactText(productName)); - // Count - // Compares the displayed amount with the parameter - validateProductAmount(position, productAmount); - // Style - // Compares the displayed style with the parameter productContainer.find(".productStyle").shouldHave(exactText(productStyle)); - // Size - // Compares the displayed style with the parameter productContainer.find(".productSize").shouldHave(exactText(productSize)); - // Price - // Compares the displayed price with the parameter productContainer.find(".productUnitPrice").shouldHave(exactText(productPrice)); + productContainer.find(".productCount").shouldHave(exactValue(Integer.toString(productAmount))); + + // validate remove and update button + $("#btnRemoveProdCount" + (position - 1)).shouldBe(visible); + $("#btnUpdateProdCount" + (position - 1)).shouldBe(visible); } - @Step("validate sub total and line item total after adding on the cart page") - public void validateSubAndLineItemTotalAfterAdd(int position, String oldSubTotal, double totalPrice) + @Step("validate '{product}' on the cart page") + public void validateCartItem(int position, Product product) { - SelenideElement productContainer = $("#product" + (position - 1)); - // Store unit price (without $ sign) - // Takes the price per 1 unit of the specified item - String unitPriceShort_varDynamic = PriceHelper.removeCurrency(productContainer.find(".unitPriceShort").text()); - // Store product count - // Takes the amount of the specified item - String quantity_varDynamic = $("#productCount" + (position - 1)).val(); - - String subOrderPrice = PriceHelper.computeRowPrice(PriceHelper.addCurrency(unitPriceShort_varDynamic), quantity_varDynamic); - - // Verify calculated cost is the shown cost - // Compare calculated Unit Price to displayed total Unit Price - productContainer.find(".productTotalUnitPrice").shouldHave(exactText(subOrderPrice)); - - // Verify subtotal - // Stores the subtotal with the new item present - // Remove "$" symbol from price to be able to use it in a calculation - // Cuts off the first character from the string, which is the "$" symbol - String newSubTotal = subTotal.text(); - // New Total - Old Total = Price of item you just added - String price = PriceHelper.subtractFromPrice(newSubTotal, oldSubTotal); - String price2 = PriceHelper.subtractFromPrice(subOrderPrice, PriceHelper.format(totalPrice)); - - Assert.assertEquals(price, price2); + validateCartItem(position, product.getName(), product.getStyle(), product.getSize(), product.getAmount(), product.getUnitPrice()); } - @Step("validate line item amount on the cart page") - public void validateProductAmount(int position, int amount) + @Step("validate '{product}' on the cart page after changing it's quantity") + public void validateCartItem(int position, Product product, int productAmount) { - // Makes sure the amount of the item with index @{index} in the cart equals the parameter - $("#product" + (position - 1) + " .productCount").shouldHave(exactValue(Integer.toString(amount))); + validateCartItem(position, product.getName(), product.getStyle(), product.getSize(), productAmount, product.getUnitPrice()); } - @Step("get product name from line item on the cart page") + /// ----- get product data ----- /// + + @Step("get product name from line item on position '{position}' on the cart page") public String getProductName(int position) { - // Get the product name to enable usage outside this module. return $("#product" + (position - 1) + " .productName").text(); } - @Step("get product style from line item on the cart page") + @Step("get product style from line item on position '{position}' on the cart page") public String getProductStyle(int position) { - // Get the style to enable usage outside this module. return $("#product" + (position - 1) + " .productStyle").text(); } - @Step("get product size from line item on the cart page") + @Step("get product size from line item on position '{position}' on the cart page") public String getProductSize(int position) { - // Get the size to enable usage outside this module. return $("#product" + (position - 1) + " .productSize").text(); } - @Step("get product count from line item on the cart page") + @Step("get product count from line item on position '{position}' on the cart page") public String getProductCount(int position) { - // Get the size to enable usage outside this module. return $("#product" + (position - 1) + " .productCount").val(); } - @Step("get product unit price from line item on the cart page") + @Step("get product unit price from line item on position '{position}' on the cart page") public String getProductUnitPrice(int position) { - // Get the product price to enable usage outside this module. return $("#product" + (position - 1) + " .productUnitPrice").text(); } - @Step("get product total price from line item on the cart page") - public String getProductTotalUnitPrice(int position) + @Step("get product total price from line item on position '{position}' on the cart page") + public String getProductTotalPrice(int position) { - // Get the product price to enable usage outside this module. return $("#product" + (position - 1) + " .productTotalUnitPrice").text(); } - @Step("get product from line item on the cart page") + @Step("get product from line item on position '{position}' on the cart page") public Product getProduct(int position) { return new Product(getProductName(position), getProductUnitPrice(position), getProductStyle(position), getProductSize(position), Integer.parseInt(getProductCount(position))); } - /** - * @param position - * @param amount - */ - @Step("update product count on the cart page") + /// ----- update product data ----- /// + + @Step("update product count of product on position '{position}' on the cart page to '{amount}'") public void updateProductCount(int position, int amount) { SelenideElement productContainer = $("#product" + (position - 1)); - // Type in the specified amount - productContainer.find(".productCount").setValue(Integer.toString(amount)); - // Stores the new amount in an outside variable - // Click the update button - // Clicks the update button for the product - productContainer.find(".btnUpdateProduct").scrollTo().click(); - } - - private SelenideElement findProductContainer(String productName, String style, String size) - { - SelenideElement productContainer = $$("div.hidden-xs").filter(text(productName)).first().parent().parent(); - for (int i = 0; i < $$("div.hidden-xs").filter(text(productName)).size(); i++) - { - SelenideElement product = $$("div.hidden-xs").filter(text(productName)).get(i); - if (product.find(".productStyle").text().equals(style) && product.find(".productSize").text().equals(size)) - { - productContainer = product.parent().parent(); - } - } - return productContainer; - } - @Step("update product count by the name") - public void updateProductCountByName(String productName, String style, String size, int amount) - { - SelenideElement productContainer = findProductContainer(productName, style, size); + // type new amount productContainer.find(".productCount").setValue(Integer.toString(amount)); - productContainer.find(".btnUpdateProduct").scrollTo().click(); - } - @Step("remove product by name") - public void removeProductByName(String productName, String style, String size) - { - SelenideElement productContainer = findProductContainer(productName, style, size); - productContainer.find(".btnRemoveProduct").click(); - $("#buttonDelete").click(); + // click update button + productContainer.find(".btnUpdateProduct").scrollTo().click(); } - /** - * @param position - */ - @Step("remove product on the cart page") + @Step("remove product on position '{position}' on the cart page") public void removeProduct(int position) { - // Click delete button - // Click on the delete button for the product + // click delete button $("#btnRemoveProdCount" + (position - 1)).scrollTo().click(); - // Wait for the second delete button to appear - // Wait until the confirmation button is visible - $("#buttonDelete").waitUntil(visible, Neodymium.configuration().selenideTimeout()); - // Click delete button - // Click the confirmation button + + // click delete confirmation button $("#buttonDelete").scrollTo().click(); - // Wait until the confirmation button is gone - $("#buttonDelete").waitUntil(hidden, Neodymium.configuration().selenideTimeout()); - // Reload page to let IDs adjust to the deletion - miniCart.openMiniCart(); - miniCart.openCartPage(); } - /** - * @param oldSubTotal - * @param oldLineItemTotal - */ - @Step("validate sub total and line item total after removing on the cart page") - public void validateSubAndLineItemTotalAfterRemove(String oldSubTotal, String oldLineItemTotal) - { - String newSubTotal = PriceHelper.subtractFromPrice(oldSubTotal, oldLineItemTotal); - subTotal.shouldHave(exactText(newSubTotal)); - } + /// ----- cart page navigation ----- /// - /** - * @param position - */ - @Step("click on a product on the cart page") - public ProductDetailPage openProductPage(int position) + @Step("click on a product on position '{position}' on the cart page") + public ProductDetailPage openProductDetailPage(int position) { $("#product" + (position - 1) + " .product-img").scrollTo().click(); return new ProductDetailPage().isExpectedPage(); } - private void clickCheckoutButton() - { - $("#btnStartCheckout").scrollTo().click(); - } - - @Step("open new shipping address from the cart page") - public NewShippingAddressPage openNewShippingPage() + @Step("open homepage from cart page") + public HomePage openHomePage() { - clickCheckoutButton(); - return new NewShippingAddressPage().isExpectedPage(); + $("#brand").scrollTo().click(); + return new HomePage().isExpectedPage(); } - @Step("open shipping address from the cart page") - public ShippingAddressPage openShippingPage() + @Step("open guest shipping address from the cart page") + public GuestShippingAddressPage openGuestShippingAddressPage() { - clickCheckoutButton(); - return new ShippingAddressPage().isExpectedPage(); + $("#btnStartCheckout").scrollTo().click(); + return new GuestShippingAddressPage().isExpectedPage(); } - /** - * @return - */ - @Step("check if there are product on the cart page") - public boolean hasProductsInCart() + @Step("open returning customer shipping address from the cart page") + public ReturningCustomerShippingAddressPage openReturningCustomerShippingAddressPage() { - return $("#btnRemoveProdCount0").exists(); + $("#btnStartCheckout").scrollTo().click(); + return new ReturningCustomerShippingAddressPage().isExpectedPage(); } } diff --git a/src/test/java/posters/pageobjects/pages/checkout/GuestBillingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/GuestBillingAddressPage.java new file mode 100644 index 00000000..f2894ec4 --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/checkout/GuestBillingAddressPage.java @@ -0,0 +1,165 @@ +package posters.pageobjects.pages.checkout; + +import static com.codeborne.selenide.Condition.attribute; +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.matchText; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.tests.testdata.dataobjects.Address; + +public class GuestBillingAddressPage extends AbstractCheckoutPage +{ + private SelenideElement title = $("#titleBillAddr"); + + private SelenideElement addBillingButton = $("#btnAddBillAddr"); + + @Override + @Step("ensure this is a billing address page") + public GuestBillingAddressPage isExpectedPage() + { + super.isExpectedPage(); + title.should(exist); + return this; + } + + /// ----- validate content guest billing address page ----- /// + + @Step("validate breadcrumb") + public void validateBreadcrumb() + { + $("#btnToCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.cart"))).shouldBe(visible); + $("#btnShippAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.shippingAddress"))).shouldBe(visible); + $("#btnBillAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.billingAddress"))).shouldBe(visible); + $("#btnCreditCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.payment"))).shouldBe(visible); + $("#btnPlaceOrder").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.placeOrder"))).shouldBe(visible); + } + + @Step("validate process wrap") + public void validateProcessWrap() + { + // validate process numbers + $("#crt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.number"))).shouldBe(visible); + $("#ship span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.number"))).shouldBe(visible); + $("#bill span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.number"))).shouldBe(visible); + $("#payment span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.number"))).shouldBe(visible); + $("#chkout span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.number"))).shouldBe(visible); + $("#orderCmplt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.number"))).shouldBe(visible); + + // validate process names + $("#crt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.name"))).shouldBe(visible); + $("#ship h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.name"))).shouldBe(visible); + $("#bill h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.name"))).shouldBe(visible); + $("#payment h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.name"))).shouldBe(visible); + $("#chkout h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.name"))).shouldBe(visible); + $("#orderCmplt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.name"))).shouldBe(visible); + } + + private void validateFillInHeadlines(String headline) + { + $$(".form-group").findBy(exactText(headline)).shouldBe(visible); + } + + @Step("validate fill-in form headlines") + public void validateFillInHeadlines() + { + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.fullName")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.company")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.address")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.city")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.state")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.zip")); + // TODO - fix after issue is fixed + //validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.country")); + } + + @Step("validate fill-in form placeholder") + public void validateFillInPlaceholder() + { + $("#fullName").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.yourName")))).shouldBe(visible); + $("#company").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.companyName")))).shouldBe(visible); + $("#addressLine").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.address")))).shouldBe(visible); + $("#zip").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.zip")))).shouldBe(visible); + } + + @Step("validate country dropdown") + public void validateCountryDropdown() + { + $("#country").shouldBe(matchText(Neodymium.localizedText("AddressPages.fillIn.dropdown.usa"))).should(exist); + $("#country").shouldBe(matchText(Neodymium.localizedText("AddressPages.fillIn.dropdown.germany"))).should(exist); + } + + @Step("validate required string") + public void validateRequiredString() + { + $(".reqField").shouldHave(exactText(Neodymium.localizedText("AddressPages.fillIn.headlines.requiredFields"))).shouldBe(visible); + } + + @Override + @Step("validate shipping address page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate breadcrumb + validateBreadcrumb(); + + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress indicator + // validateProcessWrap(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("GuestBillingAddressPage.title"))).shouldBe(visible); + + // validate fill form headlines + validateFillInHeadlines(); + + // validate fill in form structure + validateFillInPlaceholder(); + + // validate country selection dropdown + validateCountryDropdown(); + + // validate "required fields" string + validateRequiredString(); + + // validate continue button + addBillingButton.shouldHave(exactText(Neodymium.localizedText("AddressPages.button"))).shouldBe(visible); + } + + /// ----- send billing address form ----- /// + + private GuestPaymentPage goToGuestPaymentPage(String name, String company, String address, String city, + String state, String zip, String country) + { + // fill in form with parameters + $("#fullName").val(name); + $("#company").val(company); + $("#addressLine").val(address); + $("#city").val(city); + $("#state").val(state); + $("#zip").val(zip); + $("#country").selectOption(country); + + // go to guest payment page + addBillingButton.scrollTo().click(); + + return new GuestPaymentPage().isExpectedPage(); + } + + @Step("fill and send new billing address form with '{billingAddress}'") + public GuestPaymentPage goToGuestPaymentPage(Address billingAddress) + { + String fullName = billingAddress.getFirstName() + " " + billingAddress.getLastName(); + + return goToGuestPaymentPage(fullName, billingAddress.getCompany(), billingAddress.getStreet(), + billingAddress.getCity(), billingAddress.getState(), billingAddress.getZip(), + billingAddress.getCountry()); + } +} diff --git a/src/test/java/posters/pageobjects/pages/checkout/GuestPaymentPage.java b/src/test/java/posters/pageobjects/pages/checkout/GuestPaymentPage.java new file mode 100644 index 00000000..389574f3 --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/checkout/GuestPaymentPage.java @@ -0,0 +1,209 @@ +package posters.pageobjects.pages.checkout; + +import java.time.LocalDate; + +import static com.codeborne.selenide.Condition.attribute; +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.matchText; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.tests.testdata.dataobjects.CreditCard; + +public class GuestPaymentPage extends AbstractCheckoutPage +{ + private SelenideElement title = $("#titlePayment"); + + private SelenideElement creditCardNumber = $("#creditCardNumber"); + + private SelenideElement creditCardName = $("#name"); + + private SelenideElement expirationMonth = $("#expirationDateMonth"); + + private SelenideElement expirationYear = $("#expirationDateYear"); + + private SelenideElement addPaymentButton = $("#btnAddPayment"); + + @Override + @Step("ensure this is a payment page") + public GuestPaymentPage isExpectedPage() + { + super.isExpectedPage(); + title.should(exist); + return this; + } + + /// ----- validate content guest payment page ----- /// + + @Step("validate breadcrumb") + public void validateBreadcrumb() + { + $("#btnToCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.cart"))).shouldBe(visible); + $("#btnShippAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.shippingAddress"))).shouldBe(visible); + $("#btnBillAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.billingAddress"))).shouldBe(visible); + $("#btnCreditCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.payment"))).shouldBe(visible); + $("#btnPlaceOrder").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.placeOrder"))).shouldBe(visible); + } + + @Step("validate process wrap") + public void validateProcessWrap() + { + // validate process numbers + $("#crt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.number"))).shouldBe(visible); + $("#ship span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.number"))).shouldBe(visible); + $("#bill span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.number"))).shouldBe(visible); + $("#payment span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.number"))).shouldBe(visible); + $("#chkout span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.number"))).shouldBe(visible); + $("#orderCmplt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.number"))).shouldBe(visible); + + // validate process names + $("#crt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.name"))).shouldBe(visible); + $("#ship h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.name"))).shouldBe(visible); + $("#bill h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.name"))).shouldBe(visible); + $("#payment h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.name"))).shouldBe(visible); + $("#chkout h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.name"))).shouldBe(visible); + $("#orderCmplt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.name"))).shouldBe(visible); + } + + private void validateFillInHeadlines(String headline) + { + $$(".form-group label").findBy(exactText(headline)).shouldBe(visible); + } + + @Step("validate fill-in form headlines") + public void validateFillInHeadlines() + { + validateFillInHeadlines(Neodymium.localizedText("GuestPaymentPage.fillIn.headlines.cardNumber")); + validateFillInHeadlines(Neodymium.localizedText("GuestPaymentPage.fillIn.headlines.cardHolderName")); + validateFillInHeadlines(Neodymium.localizedText("GuestPaymentPage.fillIn.headlines.expirationDate")); + } + + @Step("validate fill-in form placeholder") + public void validateFillInPlaceholder() + { + creditCardNumber.shouldHave(attribute("placeholder", (Neodymium.localizedText("GuestPaymentPage.fillIn.placeholder.cardNumber")))).shouldBe(visible); + creditCardName.shouldHave(attribute("placeholder", (Neodymium.localizedText("GuestPaymentPage.fillIn.placeholder.cardOwnerName")))).shouldBe(visible); + $("#expirationDateMonth [selected]").shouldHave(exactText("0" + Integer.toString(LocalDate.now().getMonthValue()))).shouldBe(visible); + $("#expirationDateYear [selected]").shouldHave(exactText(Integer.toString(LocalDate.now().getYear()))).shouldBe(visible); + } + + private void validateMonthDropdown(String month) + { + $$("#expirationDateMonth").findBy(matchText(month)).shouldBe(visible); + } + + @Step("validate month dropdown") + public void validateMonthDropdown() + { + // open dropdown + expirationMonth.scrollTo().click(); + + // validate months + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.january")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.february")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.march")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.april")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.may")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.june")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.july")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.august")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.september")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.october")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.november")); + validateMonthDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireMonth.december")); + } + + private void validateYearDropdown(String year) + { + $$("#expirationDateYear").findBy(matchText(year)).shouldBe(visible); + } + + @Step("validate year dropdown") + public void validateYearDropdown() + { + // open dropdown + expirationYear.scrollTo().click(); + + // validate years + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2023")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2024")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2025")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2026")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2027")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2028")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2029")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2030")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2031")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2032")); + validateYearDropdown(Neodymium.localizedText("GuestPaymentPage.fillIn.expireYear.2033")); + } + + @Step("validate required string") + public void validateRequiredString() + { + $(".reqField").shouldHave(exactText(Neodymium.localizedText("AddressPages.fillIn.headlines.requiredFields"))).shouldBe(visible); + } + + @Override + @Step("validate payment page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate breadcrumb + validateBreadcrumb(); + + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress indicator + //validateProcessWrap(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("GuestPaymentPage.title"))).shouldBe(visible); + + // validate fill in form headlines + validateFillInHeadlines(); + + // validate placeholder + validateFillInPlaceholder(); + + // validate month dropdown + validateMonthDropdown(); + + // validate year dropdown + validateYearDropdown(); + + // validate "required fields" string + validateRequiredString(); + + // validate continue button + addPaymentButton.shouldHave(exactText(Neodymium.localizedText("GuestPaymentPage.button"))).shouldBe(visible); + } + + /// ----- send payment form ----- /// + + private PlaceOrderPage goToPlaceOrderPage(String number, String name, String month, String year) + { + // fill in form with parameters + creditCardNumber.val(number); + creditCardName.val(name); + expirationMonth.selectOption(month); + expirationYear.selectOption(year); + + // go to place order page + addPaymentButton.scrollTo().click(); + + return new PlaceOrderPage().isExpectedPage(); + } + + @Step("fill and send payment form with '{creditCard}'") + public PlaceOrderPage goToPlaceOrderPage(CreditCard creditCard) + { + return goToPlaceOrderPage(creditCard.getCardNumber(), creditCard.getFullName(), creditCard.getExpDateMonth(), creditCard.getExpDateYear()); + } +} diff --git a/src/test/java/posters/pageobjects/pages/checkout/GuestShippingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/GuestShippingAddressPage.java new file mode 100644 index 00000000..25983dee --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/checkout/GuestShippingAddressPage.java @@ -0,0 +1,208 @@ +package posters.pageobjects.pages.checkout; + +import static com.codeborne.selenide.Condition.attribute; +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.matchText; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.tests.testdata.dataobjects.Address; + +public class GuestShippingAddressPage extends AbstractCheckoutPage +{ + private SelenideElement title = $("#titleDelAddr"); + + private SelenideElement addShippingButton = $("#btnAddDelAddr"); + + @Override + @Step("ensure this is a shipping address page") + public GuestShippingAddressPage isExpectedPage() + { + super.isExpectedPage(); + title.should(exist); + return this; + } + + /// ----- validate content guest shipping address page ----- /// + + @Step("validate breadcrumb") + public void validateBreadcrumb() + { + $("#btnToCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.cart"))).shouldBe(visible); + $("#btnShippAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.shippingAddress"))).shouldBe(visible); + $("#btnBillAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.billingAddress"))).shouldBe(visible); + $("#btnCreditCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.payment"))).shouldBe(visible); + $("#btnPlaceOrder").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.placeOrder"))).shouldBe(visible); + } + + @Step("validate process wrap") + public void validateProcessWrap() + { + // validate process numbers + $("#crt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.number"))).shouldBe(visible); + $("#ship span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.number"))).shouldBe(visible); + $("#bill span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.number"))).shouldBe(visible); + $("#payment span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.number"))).shouldBe(visible); + $("#chkout span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.number"))).shouldBe(visible); + $("#orderCmplt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.number"))).shouldBe(visible); + + // validate process names + $("#crt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.name"))).shouldBe(visible); + $("#ship h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.name"))).shouldBe(visible); + $("#bill h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.name"))).shouldBe(visible); + $("#payment h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.name"))).shouldBe(visible); + $("#chkout h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.name"))).shouldBe(visible); + $("#orderCmplt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.name"))).shouldBe(visible); + } + + private void validateFillInHeadlines(String headline) + { + $$(".form-group").findBy(exactText(headline)).shouldBe(visible); + } + + @Step("validate fill-in form headlines") + public void validateFillInHeadlines() + { + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.fullName")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.company")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.address")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.city")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.state")); + validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.zip")); + // TODO - fix after issue is fixed + //validateFillInHeadlines(Neodymium.localizedText("AddressPages.fillIn.headlines.country")); + } + + @Step("validate fill-in form placeholder") + public void validateFillInPlaceholder() + { + $("#fullName").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.yourName")))).shouldBe(visible); + $("#company").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.companyName")))).shouldBe(visible); + $("#addressLine").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.address")))).shouldBe(visible); + $("#zip").shouldHave(attribute("placeholder", (Neodymium.localizedText("AddressPages.fillIn.placeholder.zip")))).shouldBe(visible); + } + + @Step("validate country dropdown") + public void validateCountryDropdown() + { + $("#country").shouldBe(matchText(Neodymium.localizedText("AddressPages.fillIn.dropdown.usa"))).should(exist); + $("#country").shouldBe(matchText(Neodymium.localizedText("AddressPages.fillIn.dropdown.germany"))).should(exist); + } + + @Step("validate shipping address usage for billing address radio") + public void validateAddressRadio() + { + $(".control-label").shouldHave(exactText(Neodymium.localizedText("AddressPages.fillIn.headlines.useAddressForBilling"))).shouldBe(visible); + $(".radio :nth-of-type(1)").shouldHave(matchText(Neodymium.localizedText("AddressPages.fillIn.radio.yes"))).shouldBe(visible); + $(".radio :nth-of-type(2)").shouldHave(matchText(Neodymium.localizedText("AddressPages.fillIn.radio.no"))).shouldBe(visible); + } + + @Step("validate required string") + public void validateRequiredString() + { + $(".reqField").shouldHave(exactText(Neodymium.localizedText("AddressPages.fillIn.headlines.requiredFields"))).shouldBe(visible); + } + + @Override + @Step("validate shipping address page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate breadcrumb + validateBreadcrumb(); + + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress indicator + // validateProcessWrap(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("GuestShippingAddressPage.title"))).shouldBe(visible); + + // validate fill in form headlines + validateFillInHeadlines(); + + // validate fill in form structure + validateFillInPlaceholder(); + + // validate country selection dropdown + validateCountryDropdown(); + + // validate address usage radio + validateAddressRadio(); + + // validate "required fields" string + validateRequiredString(); + + // validate continue button + addShippingButton.shouldHave(exactText(Neodymium.localizedText("AddressPages.button"))).shouldBe(visible); + } + + /// ----- send shipping address form ----- /// + + private GuestBillingAddressPage goToGuestBillingAddressPage(String name, String company, String address, String city, + String state, String zip, String country) + { + // fill in form with parameters + $("#fullName").val(name); + $("#company").val(company); + $("#addressLine").val(address); + $("#city").val(city); + $("#state").val(state); + $("#zip").val(zip); + $("#country").selectOption(country); + + $("#billEqualShipp-No").scrollTo().click(); + + // go to guest billing address page + addShippingButton.scrollTo().click(); + + return new GuestBillingAddressPage().isExpectedPage(); + } + + @Step("fill and send shipping address form with '{shippingAddress}' and go to guest billing address page") + public GuestBillingAddressPage goToGuestBillingAddressPage(Address shippingAddress) + { + String fullName = shippingAddress.getFirstName() + " " + shippingAddress.getLastName(); + + return goToGuestBillingAddressPage(fullName, shippingAddress.getCompany(), shippingAddress.getStreet(), + shippingAddress.getCity(), shippingAddress.getState(), shippingAddress.getZip(), + shippingAddress.getCountry()); + } + + private GuestPaymentPage goToGuestPaymentPage(String name, String company, String address, String city, + String state, String zip, String country) + { + // fill in form with parameters + $("#fullName").val(name); + $("#company").val(company); + $("#addressLine").val(address); + $("#city").val(city); + $("#state").val(state); + $("#zip").val(zip); + $("#country").selectOption(country); + + $("#billEqualShipp-Yes").scrollTo().click(); + + // go to guest payment page + addShippingButton.scrollTo().click(); + + return new GuestPaymentPage().isExpectedPage(); + } + + @Step("fill and send shipping address form with '{shippingAddress}' and go to guest payment page") + public GuestPaymentPage goToGuestPaymentPage(Address shippingAddress) + { + String fullName = shippingAddress.getFirstName() + " " + shippingAddress.getLastName(); + + return goToGuestPaymentPage(fullName, shippingAddress.getCompany(), shippingAddress.getStreet(), + shippingAddress.getCity(), shippingAddress.getState(), shippingAddress.getZip(), + shippingAddress.getCountry()); + } +} diff --git a/src/test/java/posters/pageobjects/pages/checkout/NewBillingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/NewBillingAddressPage.java deleted file mode 100644 index defb4882..00000000 --- a/src/test/java/posters/pageobjects/pages/checkout/NewBillingAddressPage.java +++ /dev/null @@ -1,161 +0,0 @@ -package posters.pageobjects.pages.checkout; - -import static com.codeborne.selenide.Condition.exactText; -import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.visible; -import static com.codeborne.selenide.Selenide.$; - -import com.codeborne.selenide.SelenideElement; -import com.xceptance.neodymium.util.Neodymium; - -import io.qameta.allure.Step; -import posters.dataobjects.Address; - -/** - * @author pfotenhauer - */ -public class NewBillingAddressPage extends AbstractCheckoutPage -{ - private SelenideElement headline = $("#titleBillAddr"); - - private SelenideElement nameField = $("#fullName"); - - private SelenideElement companyField = $("#company"); - - private SelenideElement addressField = $("#addressLine"); - - private SelenideElement cityField = $("#city"); - - private SelenideElement stateField = $("#state"); - - private SelenideElement zipField = $("#zip"); - - private SelenideElement countryField = $("#country"); - - private SelenideElement addBillingButton = $("#btnAddBillAddr"); - - @Override - @Step("ensure this is a new billing address page") - public NewBillingAddressPage isExpectedPage() - { - super.isExpectedPage(); - headline.should(exist); - return this; - } - - @Override - @Step("validate new billing address page structure") - public void validateStructure() - { - super.validateStructure(); - - // Headline - // Assert the headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // Form - // Asserts the form is there at all - $("#formAddBillAddr").shouldBe(visible); - // Name - // Asserts the label next to the name field shows the right text - $("label[for='fullName']").shouldHave(exactText(Neodymium.localizedText("General.addresses.fullname"))); - // Asserts the name field is there - nameField.shouldBe(visible); - // Company - // Asserts the label next to the company field shows the right text - $("label[for='companyname']").shouldHave(exactText(Neodymium.localizedText("General.addresses.company"))); - // Asserts the company field is there - companyField.shouldBe(visible); - // Address - // Asserts the label next to the address field shows the right text - $("label[for='addressLine']").shouldHave(exactText(Neodymium.localizedText("General.addresses.address"))); - // Asserts the address field is there - addressField.shouldBe(visible); - // City - // Asserts the label next to the city field shows the right text - $("label[for='city']").shouldHave(exactText(Neodymium.localizedText("General.addresses.city"))); - // Asserts the city field is there - cityField.shouldBe(visible); - // State - // Asserts the label next to the state field shows the right text - $("label[for='state']").shouldHave(exactText(Neodymium.localizedText("General.addresses.state"))); - // Asserts the state field is there - stateField.shouldBe(visible); - // Zip - // Asserts the label next to the zip field shows the right text - $("label[for='zip']").shouldHave(exactText(Neodymium.localizedText("General.addresses.zip"))); - // Asserts the zip field is there - zipField.shouldBe(visible); - // Country - // Asserts the label next to the country field shows the right text - $("label[for='country']").shouldHave(exactText(Neodymium.localizedText("General.addresses.country"))); - // Asserts the country field is there - countryField.shouldBe(visible); - // Continue Button - // Asserts the Continue button is there - addBillingButton.shouldBe(visible); - } - - /** - * // - * - * @param name - * First and last name you want to use // T - * @param company - * The company you want to use - * @param address - * The address you want to use - * @param city - * The City you want to use - * @param state - * The state you want to use - * @param zip - * The Zip you want to use, has to be in numbers format - * @param country - * The country you want to use, currently only United States or Germany - */ - @Step("fill and send new billing address form") - public NewPaymentPage sendBillingAddressForm(String name, String company, String address, String city, - String state, String zip, String country) - { - // Name - // Enter the name parameter - nameField.val(name); - // Company - // Enter the company parameter - companyField.val(company); - // Address - // Enter the address parameter - addressField.val(address); - // City - // Enter the city parameter - cityField.val(city); - // State - // Enter the state parameter - stateField.val(state); - // Zip - // Enter the zip parameter - zipField.val(zip); - // Country - // Select the country whose label equals the parameter - countryField.selectOption(country); - // Open the billing addresses or payment options page, depending on which radio button you checked - // Click on Continue - addBillingButton.scrollTo().click(); - - return new NewPaymentPage().isExpectedPage(); - } - - /** - * @param billingAddress - * @return - */ - public NewPaymentPage sendBillingAddressForm(Address billingAddress) - { - String fullName = billingAddress.getFirstName() + " " + billingAddress.getLastName(); - - return sendBillingAddressForm(fullName, billingAddress.getCompany(), billingAddress.getStreet(), - billingAddress.getCity(), billingAddress.getState(), billingAddress.getZip(), - billingAddress.getCountry()); - } -} diff --git a/src/test/java/posters/pageobjects/pages/checkout/NewPaymentPage.java b/src/test/java/posters/pageobjects/pages/checkout/NewPaymentPage.java deleted file mode 100644 index c6707d2b..00000000 --- a/src/test/java/posters/pageobjects/pages/checkout/NewPaymentPage.java +++ /dev/null @@ -1,114 +0,0 @@ -package posters.pageobjects.pages.checkout; - -import static com.codeborne.selenide.Condition.exactText; -import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.visible; -import static com.codeborne.selenide.Selenide.$; - -import com.codeborne.selenide.SelenideElement; -import com.xceptance.neodymium.util.Neodymium; - -import io.qameta.allure.Step; -import posters.dataobjects.CreditCard; - -/** - * @author pfotenhauer - */ -public class NewPaymentPage extends AbstractCheckoutPage -{ - private SelenideElement headline = $("#titlePayment"); - - private SelenideElement creditCardNumber = $("#creditCardNumber"); - - private SelenideElement creditCardName = $("#name"); - - private SelenideElement expirationMonth = $("#expirationDateMonth"); - - private SelenideElement expirationYear = $("#expirationDateYear"); - - private SelenideElement addPaymentButton = $("#btnAddPayment"); - - @Override - @Step("ensure this is a new payment page") - public NewPaymentPage isExpectedPage() - { - super.isExpectedPage(); - headline.should(exist); - return this; - } - - @Override - @Step("validate new payment page structure") - public void validateStructure() - { - super.validateStructure(); - - // Headline - // Makes sure the headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // Form - // Make sure the form is there to begin with - $("#formAddPayment").should(exist); - // Credit Card Number - // Makes sure the label next to the card number field shows the correct text - $("label[for='creditCardNumber']").shouldHave(exactText(Neodymium.localizedText("General.payment.cardnumber"))); - // Makes sure the card number field is there - creditCardNumber.shouldBe(visible); - // Name - // Makes sure the label next to the card holder field shows the correct text - $("label[for='name']").shouldHave(exactText(Neodymium.localizedText("General.payment.cardholdername"))); - // Makes sure the card holder field is there - creditCardName.shouldBe(visible); - // Expiration - // Makes sure the label next to the expiration date fields shows the correct text - $("label[for='expirationDateMonth']").shouldHave(exactText(Neodymium.localizedText("General.payment.expirationdate"))); - // Makes sure the expiration month field is there - expirationMonth.shouldBe(visible); - // Makes sure the expiration year field is there - expirationYear.shouldBe(visible); - // Continue Button - // Makes sure the continue button is there - addPaymentButton.should(exist); - } - - /** - * @param number - * The credit card number, has to be 16 numbers - * @param name - * The full name - * @param month - * Expiration Month in numbers - * @param year - * Expiration year - */ - @Step("fill and send new payment form") - public PlaceOrderPage sendPaymentForm(String number, String name, String month, String year) - { - // Credit Card Number - // Fills the card number field with the parameter - creditCardNumber.val(number); - // Name - // Fills the card holder field with the parameter - creditCardName.val(name); - // Expiration - // Chooses the expiration month matching the parameter - expirationMonth.selectOption(month); - // Chooses the expiration year matching the parameter - expirationYear.selectOption(year); - // Opens the order overview page - // Clicks the Continue button - addPaymentButton.scrollTo().click(); - - return new PlaceOrderPage().isExpectedPage(); - } - - /** - * @param creditcard - * @return - */ - public PlaceOrderPage sendPaymentForm(CreditCard creditcard) - { - return sendPaymentForm(creditcard.getCardNumber(), creditcard.getFullName(), creditcard.getExpDateMonth(), creditcard.getExpDateYear()); - } -} diff --git a/src/test/java/posters/pageobjects/pages/checkout/NewShippingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/NewShippingAddressPage.java deleted file mode 100644 index e0507971..00000000 --- a/src/test/java/posters/pageobjects/pages/checkout/NewShippingAddressPage.java +++ /dev/null @@ -1,178 +0,0 @@ -package posters.pageobjects.pages.checkout; - -import static com.codeborne.selenide.Condition.exactText; -import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.visible; -import static com.codeborne.selenide.Selenide.$; -import static com.codeborne.selenide.Selenide.$$; - -import com.codeborne.selenide.SelenideElement; -import com.xceptance.neodymium.util.Neodymium; - -import io.qameta.allure.Step; -import posters.dataobjects.Address; - -/** - * @author pfotenhauer - */ -public class NewShippingAddressPage extends AbstractCheckoutPage -{ - private SelenideElement headline = $("#titleDelAddr"); - - private SelenideElement nameField = $("#fullName"); - - private SelenideElement companyField = $("#company"); - - private SelenideElement addressField = $("#addressLine"); - - private SelenideElement cityField = $("#city"); - - private SelenideElement stateField = $("#state"); - - private SelenideElement zipField = $("#zip"); - - private SelenideElement countryField = $("#country"); - - private SelenideElement addShippingButton = $("#btnAddDelAddr"); - - @Override - @Step("ensure this is a new shipping address page") - public NewShippingAddressPage isExpectedPage() - { - super.isExpectedPage(); - headline.should(exist); - return this; - } - - @Override - @Step("validate new shipping address page structure") - public void validateStructure() - { - super.validateStructure(); - - // Headline - // Assert the headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // Form - // Asserts the form is there at all - $("#formAddDelAddr").shouldBe(visible); - // Name - // Asserts the label next to the name field shows the right text - $("label[for='fullName']").shouldHave(exactText(Neodymium.localizedText("General.addresses.fullname"))); - // Asserts the name field is there - nameField.shouldBe(visible); - // Company - // Asserts the label next to the company field shows the right text - $("label[for='companyname']").shouldHave(exactText(Neodymium.localizedText("General.addresses.company"))); - // Asserts the company field is there - companyField.shouldBe(visible); - // Address - // Asserts the label next to the address field shows the right text - $("label[for='addressLine']").shouldHave(exactText(Neodymium.localizedText("General.addresses.address"))); - // Asserts the address field is there - addressField.shouldBe(visible); - // City - // Asserts the label next to the city field shows the right text - $("label[for='city']").shouldHave(exactText(Neodymium.localizedText("General.addresses.city"))); - // Asserts the city field is there - cityField.shouldBe(visible); - // State - // Asserts the label next to the state field shows the right text - $("label[for='state']").shouldHave(exactText(Neodymium.localizedText("General.addresses.state"))); - // Asserts the state field is there - stateField.shouldBe(visible); - // Zip - // Asserts the label next to the zip field shows the right text - $("label[for='zip']").shouldHave(exactText(Neodymium.localizedText("General.addresses.zip"))); - // Asserts the zip field is there - zipField.shouldBe(visible); - // Country - // Asserts the label next to the country field shows the right text - $("label[for='country']").shouldHave(exactText(Neodymium.localizedText("General.addresses.country"))); - // Asserts the country field is there - countryField.shouldBe(visible); - // Radio Button - // Assert the radio buttons are there - $$("input[name='billEqualShipp']").shouldHaveSize(2); - // Continue Button - // Asserts the Continue button is there - addShippingButton.shouldBe(visible); - } - - /** - * // - * - * @param name - * First and last name you want to use // T - * @param company - * The company you want to use - * @param address - * The address you want to use - * @param city - * The City you want to use - * @param state - * The state you want to use - * @param zip - * The Zip you want to use, has to be in numbers format - * @param country - * The country you want to use, currently only United States or Germany - * @param sameBillingAddress - * Decision whether or not use the same billing address - */ - @Step("fill and send new shipping address form") - public NewBillingAddressPage sendShippingAddressForm(String name, String company, String address, String city, - String state, String zip, String country, boolean sameBillingAddress) - { - // Name - // Enter the name parameter - nameField.val(name); - // Company - // Enter the company parameter - companyField.val(company); - // Address - // Enter the address parameter - addressField.val(address); - // City - // Enter the city parameter - cityField.val(city); - // State - // Enter the state parameter - stateField.val(state); - // Zip - // Enter the zip parameter - zipField.val(zip); - // Country - // Select the country whose label equals the parameter - countryField.selectOption(country); - // Radio Button - // Click the radio button for Yes or No - if (sameBillingAddress) - { - $("#billEqualShipp-Yes").scrollTo().click(); - } - else - { - $("#billEqualShipp-No").scrollTo().click(); - } - // Open the billing addresses or payment options page, depending on which radio button you checked - // Click on Continue - addShippingButton.scrollTo().click(); - - return new NewBillingAddressPage().isExpectedPage(); - } - - /** - * @param shippingAddress - * @param sameBillingAddress - * @return - */ - public NewBillingAddressPage sendShippingAddressForm(Address shippingAddress, boolean sameBillingAddress) - { - String fullName = shippingAddress.getFirstName() + " " + shippingAddress.getLastName(); - - return sendShippingAddressForm(fullName, shippingAddress.getCompany(), shippingAddress.getStreet(), - shippingAddress.getCity(), shippingAddress.getState(), shippingAddress.getZip(), - shippingAddress.getCountry(), sameBillingAddress); - } -} diff --git a/src/test/java/posters/pageobjects/pages/checkout/OrderConfirmationPage.java b/src/test/java/posters/pageobjects/pages/checkout/OrderConfirmationPage.java index 03c23cd4..0d81eb10 100644 --- a/src/test/java/posters/pageobjects/pages/checkout/OrderConfirmationPage.java +++ b/src/test/java/posters/pageobjects/pages/checkout/OrderConfirmationPage.java @@ -1,10 +1,9 @@ package posters.pageobjects.pages.checkout; -import static com.codeborne.selenide.CollectionCondition.sizeGreaterThan; +import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; -import static com.codeborne.selenide.Selenide.$$; import com.codeborne.selenide.SelenideElement; import com.xceptance.neodymium.util.Neodymium; @@ -17,7 +16,6 @@ public class OrderConfirmationPage extends AbstractBrowsingPage{ private SelenideElement homePageButton = $("#goHome"); - @Step("ensure this is the Order Confirmation page") public OrderConfirmationPage isExpectedPage() { @@ -26,63 +24,57 @@ public OrderConfirmationPage isExpectedPage() return this; } + /// ----- validate content order confirmation page ----- /// + + @Step("validate process wrap") + public void validateProcessWrap() + { + // validate process numbers + $("#crt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.number"))).shouldBe(visible); + $("#ship span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.number"))).shouldBe(visible); + $("#bill span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.number"))).shouldBe(visible); + $("#payment span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.number"))).shouldBe(visible); + $("#chkout span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.number"))).shouldBe(visible); + $("#orderCmplt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.number"))).shouldBe(visible); + + // validate process names + $("#crt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.name"))).shouldBe(visible); + $("#ship h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.name"))).shouldBe(visible); + $("#bill h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.name"))).shouldBe(visible); + $("#payment h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.name"))).shouldBe(visible); + $("#chkout h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.name"))).shouldBe(visible); + $("#orderCmplt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.name"))).shouldBe(visible); + } + + @Step("validate order confirmation page structure") public void validateStructure() { super.validateStructure(); - - - // Verifies the Navigation bar is visible - $("#categoryMenu .navi").shouldBe(visible); - - // Asserts there's categories in the nav bar. - $$("#categoryMenu .has-dropdown").shouldHave(sizeGreaterThan(0)); - - // Asserts the first headline is there. - // $("#titleIndex").shouldBe(matchText("[A-Z].{3,}")); + // validate success message + successMessage.validateSuccessMessage(Neodymium.localizedText("HomePage.validation.successfulOrder")); - // Verifies the Process chain is there. - $(".process-wrap").shouldBe(visible); + // validate process wrap + validateProcessWrap(); - // Asserts the Confirmation Check is there. - $(".confirmation #cnfmCheck").shouldBe(visible); + // validate check icon + $(".icon-check").shouldBe(visible); - // Verifies the Thank you text is visible - $("#tYouText").shouldBe(visible); + // validate thank you message + $("#tYouText").shouldHave(exactText(Neodymium.localizedText("OrderConfirmationPage.thankYouMessage"))).shouldBe(visible); // Verifies GoTo HomePage button is visible - $("#goHome").shouldBe(visible); - - + $("#goHome .icon-shopping-cart").shouldBe(visible); + $("#goHome").shouldHave(exactText(Neodymium.localizedText("OrderConfirmationPage.button"))).shouldBe(visible); } - @Step("validate Order Confirmation page") - public void validate() - { - validateStructure(); - footer.validate(); - } - - @Step("validate successful order on Confirmation page") - public void validateSuccessfulOrder() - { - successMessage.validateSuccessMessage(Neodymium.localizedText("HomePage.validation.successfulOrder")); - // Verify that the mini cart is empty again - miniCart.validateTotalCount(0); - miniCart.validateSubtotal("$0.00"); - } + /// ----- order confirmation page navigation ----- /// - public HomePage goHome() + @Step("open homepage from order confirmation page") + public HomePage openHomePage() { - - // Clicks the Continue Shopping button on the Order Confirmation page homePageButton.scrollTo().click(); return new HomePage().isExpectedPage(); - } - - - - } diff --git a/src/test/java/posters/pageobjects/pages/checkout/PaymentPage.java b/src/test/java/posters/pageobjects/pages/checkout/PaymentPage.java deleted file mode 100644 index 67a581f8..00000000 --- a/src/test/java/posters/pageobjects/pages/checkout/PaymentPage.java +++ /dev/null @@ -1,91 +0,0 @@ -package posters.pageobjects.pages.checkout; - -import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.visible; -import static com.codeborne.selenide.Selenide.$; - -import com.codeborne.selenide.SelenideElement; - -import io.qameta.allure.Step; - -/** - * @author pfotenhauer - */ -public class PaymentPage extends AbstractCheckoutPage -{ - private SelenideElement headline = $("#titlePayment"); - - private SelenideElement creditCardNumber = $("#creditCardNumber"); - - private SelenideElement creditCardName = $("#name"); - - private SelenideElement expirationMonth = $("#expirationDateMonth"); - - private SelenideElement expirationYear = $("#expirationDateYear"); - - private SelenideElement addPaymentButton = $("#btnAddPayment"); - - @Override - @Step("ensure this is a payment page") - public PaymentPage isExpectedPage() - { - super.isExpectedPage(); - headline.should(exist); - return this; - } - - @Override - @Step("validate payment page structure") - public void validateStructure() - { - super.validateStructure(); - - // Headline - // Makes sure the headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // First credit card - // Makes sure at least one credit card is saved - $("#payment0").shouldBe(visible); - } - - /** - * @param position - * The position of the credit card you want to select - * @return PPlaceOrder - */ - @Step("select a payment") - public PlaceOrderPage selectCreditCard(int position) - { - final int index = position - 1; - // Select address - // Checks the radio button belonging to the delivery address with index @{index} - $("#payment" + index + " input").scrollTo().click(); - // Open the billing address page in the checkout process - // Clicks the continue button - $("#btnUsePayment").scrollTo().click(); - - return new PlaceOrderPage().isExpectedPage(); - } - - @Step("fill and send payment form") - public PlaceOrderPage sendPaymentForm(String number, String name, String month, String year) - { - // Credit Card Number - // Fills the card number field with the parameter - creditCardNumber.val(number); - // Name - // Fills the card holder field with the parameter - creditCardName.val(name); - // Expiration - // Chooses the expiration month matching the parameter - expirationMonth.selectOption(month); - // Chooses the expiration year matching the parameter - expirationYear.selectOption(year); - // Opens the order overview page - // Clicks the Continue button - addPaymentButton.scrollTo().click(); - - return new PlaceOrderPage().isExpectedPage(); - } -} diff --git a/src/test/java/posters/pageobjects/pages/checkout/PlaceOrderPage.java b/src/test/java/posters/pageobjects/pages/checkout/PlaceOrderPage.java index f8e5b47f..e9a99c2c 100644 --- a/src/test/java/posters/pageobjects/pages/checkout/PlaceOrderPage.java +++ b/src/test/java/posters/pageobjects/pages/checkout/PlaceOrderPage.java @@ -1,7 +1,7 @@ package posters.pageobjects.pages.checkout; import static com.codeborne.selenide.Condition.exactText; -import static com.codeborne.selenide.Condition.value; +import static com.codeborne.selenide.Condition.exactValue; import static com.codeborne.selenide.Condition.exist; import static com.codeborne.selenide.Condition.matchText; import static com.codeborne.selenide.Condition.text; @@ -9,187 +9,298 @@ import static com.codeborne.selenide.Selenide.$; import static com.codeborne.selenide.Selenide.$$; +import org.apache.commons.lang3.StringUtils; + +import com.codeborne.selenide.ElementsCollection; import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.Address; -import posters.dataobjects.CreditCard; -import posters.dataobjects.Product; +import posters.tests.testdata.dataobjects.Address; +import posters.tests.testdata.dataobjects.CreditCard; +import posters.tests.testdata.dataobjects.Product; import posters.pageobjects.utility.PriceHelper; -/** - * @author pfotenhauer - */ public class PlaceOrderPage extends AbstractCheckoutPage { - private SelenideElement headline = $("#titleOrderOverview"); + private SelenideElement title = $("#titleOrderOverview"); + + private ElementsCollection headlines = $$(".total-wrap h3"); + + private ElementsCollection tableHead = $$(".product-name span"); private SelenideElement shippingAddressForm = $("#shippingAddr"); private SelenideElement billingAddressForm = $("#billingAddr"); private SelenideElement paymentForm = $("#payment"); + + private ElementsCollection totalProductPrices = $$(".totalUnitPriceShort"); + private SelenideElement subtotalContainer = $("#SubTotalValue"); + + private SelenideElement taxContainer = $("#SubTotalTaxValue"); + private SelenideElement orderButton = $("#btnOrder"); - - @Override @Step("ensure this is a place order page") public PlaceOrderPage isExpectedPage() { super.isExpectedPage(); - headline.should(exist); + title.should(exist); return this; } + /// ----- validate content place order page ----- /// + + @Step("validate breadcrumb") + public void validateBreadcrumb() + { + $("#btnToCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.cart"))).shouldBe(visible); + $("#btnShippAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.shippingAddress"))).shouldBe(visible); + $("#btnBillAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.billingAddress"))).shouldBe(visible); + $("#btnCreditCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.payment"))).shouldBe(visible); + $("#btnPlaceOrder").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.placeOrder"))).shouldBe(visible); + } + + @Step("validate product table head") + public void validateTableHead() + { + // TODO - fix after fixing issue + //tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.product"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.unitPrice"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.quantity"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("General.productTable.totalPrice"))).shouldBe(visible); + } + + @Step("validate process wrap") + public void validateProcessWrap() + { + // validate process numbers + $("#crt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.number"))).shouldBe(visible); + $("#ship span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.number"))).shouldBe(visible); + $("#bill span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.number"))).shouldBe(visible); + $("#payment span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.number"))).shouldBe(visible); + $("#chkout span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.number"))).shouldBe(visible); + $("#orderCmplt span").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.number"))).shouldBe(visible); + + // validate process names + $("#crt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.1.name"))).shouldBe(visible); + $("#ship h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.2.name"))).shouldBe(visible); + $("#bill h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.3.name"))).shouldBe(visible); + $("#payment h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.4.name"))).shouldBe(visible); + $("#chkout h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.5.name"))).shouldBe(visible); + $("#orderCmplt h3").shouldHave(exactText(Neodymium.localizedText("AddressPages.processWrap.6.name"))).shouldBe(visible); + } + @Override @Step("validate place order page structure") public void validateStructure() { super.validateStructure(); - // Headline - // Headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - shippingAddressForm.shouldBe(visible); - billingAddressForm.shouldBe(visible); - paymentForm.shouldBe(visible); - orderButton.shouldBe(visible); + // validate breadcrumb + validateBreadcrumb(); + + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress indicator + //validateProcessWrap(); + + // validate product table head + // TODO - after fixing issue 191: consistent table head CartPage and PlaceOrderPage + //validateTableHead(); + + // validate order with costs button + $("#btnOrder").shouldHave(exactText(Neodymium.localizedText("PlaceOrderPage.button"))).shouldBe(visible); } - - /** - * @param product - * The product - */ - @Step("validate order contains product '{product.name}'") - public void validateContainsProduct(Product product) + + /// ----- validate order overview ----- /// + + private void validateShippingAddressOverview(Address shippingAddress, String headline) { - SelenideElement productContainer = $$("div.hidden-xs").filter((matchText(product.getRowRegex()))).shouldHaveSize(1).first() - .parent().parent(); - - productContainer.find(".pName").shouldHave(exactText(product.getName())); - productContainer.find(".pSize").shouldHave(exactText(product.getSize())); - productContainer.find(".pStyle").shouldHave(exactText(product.getStyle())); - productContainer.find(".pCount").shouldHave(exactText(Integer.toString(product.getAmount()))); - productContainer.find(".pPrice").shouldHave(exactText(product.getUnitPrice())); - productContainer.find(".productLineItemPrice").shouldHave(exactText(PriceHelper.format(product.getTotalPrice()))); + // validate headline + headlines.findBy(exactText(headline)).shouldBe(visible); + + // validate name + String fullName = shippingAddress.getFirstName() + " " + shippingAddress.getLastName(); + shippingAddressForm.find(".name").shouldHave(exactText(fullName)).shouldBe(visible); + + // validate optional company name + if (!StringUtils.isBlank(shippingAddress.getCompany())) + { + shippingAddressForm.find(".company").shouldHave(exactText(shippingAddress.getCompany())).shouldBe(visible); + } + + // validate address + shippingAddressForm.find(".addressLine").shouldHave(exactText(shippingAddress.getStreet())).shouldBe(visible); + + // validate city, state, zip + shippingAddressForm.find(".city").shouldHave(exactText(shippingAddress.getCity())).shouldBe(visible); + shippingAddressForm.find(".state").shouldHave(exactText(shippingAddress.getState())).shouldBe(visible); + shippingAddressForm.find(".zip").shouldHave(exactText(shippingAddress.getZip())).shouldBe(visible); + + // validate country + shippingAddressForm.find(".country").shouldHave(exactText(shippingAddress.getCountry())).shouldBe(visible); } - - @Step("validate subtotal on the place order page") - public void validateSubtotal(String subtotal) + + private void validateBillingAddressOverview(Address billingAddress, String headline) { - $$("#checkoutSummaryList li").findBy(text("Subtotal")).find(".text-right").shouldBe(exactText(subtotal)); + // validate headline + headlines.findBy(exactText(headline)).shouldBe(visible); + + // validate name + String fullName = billingAddress.getFirstName() + " " + billingAddress.getLastName(); + billingAddressForm.find(".name").shouldHave(exactText(fullName)).shouldBe(visible); + + // validate optional company name + if (!StringUtils.isBlank(billingAddress.getCompany())) + { + billingAddressForm.find(".company").shouldHave(exactText(billingAddress.getCompany())).shouldBe(visible); + } + + // validate address + billingAddressForm.find(".addressLine").shouldHave(exactText(billingAddress.getStreet())).shouldBe(visible); + + // validate city, state, zip + billingAddressForm.find(".city").shouldHave(exactText(billingAddress.getCity())).shouldBe(visible); + billingAddressForm.find(".state").shouldHave(exactText(billingAddress.getState())).shouldBe(visible); + billingAddressForm.find(".zip").shouldHave(exactText(billingAddress.getZip())).shouldBe(visible); + + // validate country + billingAddressForm.find(".country").shouldHave(exactText(billingAddress.getCountry())).shouldBe(visible); } + + private void validatePaymentOverview(CreditCard creditCard, String headline) + { + // validate headline + headlines.findBy(exactText(headline)).shouldBe(visible); + + // validate name + paymentForm.find(".name").shouldHave(exactText(creditCard.getFullName())).shouldBe(visible); + + // validate censored card number + paymentForm.find(".cardNumber").shouldHave(exactText(creditCard.getCrypticCardNumber())).shouldBe(visible); + + // validate expiration date + paymentForm.find(".month").shouldHave(exactText(creditCard.getExpDateMonth())).shouldBe(visible); + paymentForm.find(".year").shouldHave(exactText(creditCard.getExpDateYear())).shouldBe(visible); + } + + @Step("validate order overview") + public void validateOrderOverview(Address shippingAddress, Address billingAddress, CreditCard creditCard) + { + // validate title + title.shouldHave(exactText(Neodymium.localizedText("PlaceOrderPage.overview.title"))).shouldBe(visible); + + // validate shipping address + validateShippingAddressOverview(shippingAddress, Neodymium.localizedText("PlaceOrderPage.overview.headlines.shippingAddress")); + + // validate billing address + validateBillingAddressOverview(billingAddress, Neodymium.localizedText("PlaceOrderPage.overview.headlines.billingAddress")); + + // validate payment + validatePaymentOverview(creditCard, Neodymium.localizedText("PlaceOrderPage.overview.headlines.payment")); + } + + /// ----- validate products ----- /// + + private void validateProduct(int position, String productName, String productStyle, String productSize, int productAmount, String productPrice) + { + // selector for product + SelenideElement productContainer = $("#product" + (position - 1)); - @Step("validate product '{productName}' on place order page") - public void validateProduct(int position, String productName, int productCount, String productStyle, String productSize) - { - final int index = position - 1; - // Item info evaluation - // The product at index @{index} exists - SelenideElement productContainer = $("#checkoutOverviewTable #product" + index); - productContainer.should(exist); - // Name - // The name equals the parameter + // validate product image + productContainer.find(".product-img").shouldBe(visible); + + // validate parameters productContainer.find(".pName").shouldHave(exactText(productName)); - // Amount - // The amount equals the parameter - //String Val = productContainer.find(".productCount").getAttribute("value"); - - productContainer.find(".productCount").shouldHave(value(Integer.toString(productCount))); - // Style - // The style equals the parameter productContainer.find(".productStyle").shouldHave(exactText(productStyle)); - // Size - // The size equals the parameter productContainer.find(".productSize").shouldHave(exactText(productSize)); + // TODO - after fixing issue 191: consistent price representation (not "$ 0.00" and "$0.00") + //productContainer.find(".productUnitPrice").shouldHave(value(productPrice)); + productContainer.find(".productCount").shouldHave(exactValue(Integer.toString(productAmount))); } - - - - @Step("validate addresses and payment on place order page") - public void validateAddressesAndPayment(Address shippingAddress, Address billingAddress, CreditCard creditcard) - { - // Shipping address - // fullName - // Makes sure the shipping address fullName matches the parameter - String firstName = shippingAddress.getFirstName(); - String lastName = shippingAddress.getLastName(); - String fullName = firstName + " " + lastName; - shippingAddressForm.find(".name").shouldHave(exactText(fullName)); - // Company - // Makes sure the shipping address company matches the parameter - shippingAddressForm.find(".company").shouldHave(exactText(shippingAddress.getCompany())); - // Address - // Makes sure the shipping address matches the parameter - shippingAddressForm.find(".addressLine").shouldHave(exactText(shippingAddress.getStreet())); - // City - // Makes sure the shipping address city matches the parameter - shippingAddressForm.find(".city").shouldHave(exactText(shippingAddress.getCity())); - // State - // Makes sure the shipping address state matches the parameter - shippingAddressForm.find(".state").shouldHave(exactText(shippingAddress.getState())); - // ZIP - // Makes sure the shipping address ZIP matches the parameter - shippingAddressForm.find(".zip").shouldHave(exactText(" " + shippingAddress.getZip())); - // Country - // Makes sure the shipping address country matches the parameter - shippingAddressForm.find(".country").shouldHave(exactText(shippingAddress.getCountry())); - // Billing address - // Name - // Makes sure the billing address name matches the parameter - billingAddressForm.find(".name").shouldHave(exactText(fullName)); - // Company - // Makes sure the billing address company matches the parameter - billingAddressForm.find(".company").shouldHave(exactText(billingAddress.getCompany())); - // Address - // Makes sure the billing address matches the parameter - billingAddressForm.find(".addressLine").shouldHave(exactText(billingAddress.getStreet())); - // City - // Makes sure the billing address city matches the parameter - billingAddressForm.find(".city").shouldHave(exactText(billingAddress.getCity())); - // State - // Makes sure the billing address state matches the parameter - billingAddressForm.find(".state").shouldHave(exactText(billingAddress.getState())); - // ZIP - // Makes sure the billing address ZIP matches the parameter - billingAddressForm.find(".zip").shouldHave(exactText(billingAddress.getZip())); - // Country - // Makes sure the billing address country matches the parameter - billingAddressForm.find(".country").shouldHave(exactText(billingAddress.getCountry())); - // Payment - // Name - // Makes sure the credit card holder matches the parameter - paymentForm.find(" .name .value").shouldHave(exactText(creditcard.getFullName())); - // Credit Card Number - // Makes sure the anonymized credit card number matches the parameter - paymentForm.find(" .cardNumber .value").shouldHave(exactText(creditcard.getCrypticCardNumber())); - // Expiration - // Makes sure the credit card expiration month matches the parameter - paymentForm.find(" .exp .month").shouldHave(exactText(creditcard.getExpDateMonth())); - // Makes sure the credit card expiration year matches the parameter - paymentForm.find(" .exp .year").shouldHave(exactText(creditcard.getExpDateYear())); + + @Step("validate '{product}' on the place order page") + public void validateProduct(int position, Product product) + { + validateProduct(position, product.getName(), product.getStyle(), product.getSize(), product.getAmount(), product.getUnitPrice()); } - - @Step("get order total costs from place order page") - public String getTotalCosts() + + /// ----- get price summary information ----- /// + + @Step("get sum of all total product prices") + public String getSubtotal() { - return $("#totalCosts").text(); + return subtotalContainer.text(); } + + @Step("get tax costs") + public String getTax() + { + return taxContainer.text(); + } + + /** + * Note: Loops through all total product prices on the place order page and adds it to the "subtotal" variable. + * + * @return subtotal (The sum of all total product prices) + */ + @Step("calculate sum of all total product prices") + public String calculateSubtotal() + { + double subtotal = 0; + + for (SelenideElement totalProductPrice : totalProductPrices) + { + subtotal = PriceHelper.calculateSubtotalPlaceOrderPage(subtotal, totalProductPrice.getText()); + } + return PriceHelper.format(subtotal); + } + + /// ----- validate price summary ----- /// + + @Step("validate description strings") + public void validateDescriptionStrings() + { + $$(".sub p").findBy(matchText(Neodymium.localizedText("General.priceSummary.subtotal"))).shouldBe(visible); + $$(".sub p").findBy(text(Neodymium.localizedText("General.priceSummary.shipping"))).shouldBe(visible); + $$(".sub p").findBy(text(Neodymium.localizedText("General.priceSummary.tax"))).shouldBe(visible); + $$(".grand-total p").findBy(text(Neodymium.localizedText("General.priceSummary.grandTotal"))).shouldBe(visible); + } + + @Step("validate price summary") + public void validatePriceSummary(String subtotal, String shippingCosts) + { + // validate title + $$(".sub").findBy(text(Neodymium.localizedText("General.priceSummary.title"))).shouldBe(visible); + + // validate descriptions + validateDescriptionStrings(); + + // validate subtotal + subtotalContainer.shouldHave(exactText(calculateSubtotal())); + + // validate shipping costs + $("#shippingCosts").shouldHave(exactText(shippingCosts)); + + // validate tax + taxContainer.shouldHave(exactText(PriceHelper.calculateTax(shippingCosts, subtotal))); + + // validate grand total + $("#orderTotal").shouldHave(exactText(PriceHelper.calculateGrandTotal(subtotal, shippingCosts, getTax()))); + } + + /// ----- place order page navigation ----- /// + @Step("place the order") public OrderConfirmationPage placeOrder() { - // Opens the OrderConfirmationPage - // Clicks the Order button + // click on "Order with costs" button orderButton.scrollTo().click(); return new OrderConfirmationPage().isExpectedPage(); - - } - - - } diff --git a/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerBillingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerBillingAddressPage.java new file mode 100644 index 00000000..45cb9b8a --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerBillingAddressPage.java @@ -0,0 +1,96 @@ +package posters.pageobjects.pages.checkout; + +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.tests.testdata.dataobjects.Address; + +public class ReturningCustomerBillingAddressPage extends AbstractCheckoutPage +{ + private SelenideElement title = $("#titleBillAddr"); + + private SelenideElement addBillingAddressButton = $(".form-group .btn"); + + private SelenideElement useBillingAddressButton = $("#btnUseBillAddress"); + + @Override + @Step("ensure this is a billing address page") + public ReturningCustomerBillingAddressPage isExpectedPage() + { + $("#billAddr0").should(exist); + return this; + } + + /// ----- validate content returning customer billing address page ----- /// + + @Step("validate breadcrumb") + public void validateBreadcrumb() + { + $("#btnToCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.cart"))).shouldBe(visible); + $("#btnShippAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.shippingAddress"))).shouldBe(visible); + $("#btnBillAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.billingAddress"))).shouldBe(visible); + $("#btnCreditCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.payment"))).shouldBe(visible); + $("#btnPlaceOrder").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.placeOrder"))).shouldBe(visible); + } + + @Override + @Step("validate returning customer billing address page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate breadcrumb + validateBreadcrumb(); + + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress indicator + //validateProcessWrap(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerBillingAddressPage.title"))).shouldBe(visible); + + // TODO - validate address count, get function needed + + // validate add new shipping address button + addBillingAddressButton.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerBillingAddressPage.button.addNewBillAddr"))).shouldBe(visible); + + // validate continue button + useBillingAddressButton.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerBillingAddressPage.button.useBillAddr"))).shouldBe(visible); + } + + @Step("validate billing address '{billingAddress}' on position '{position}' in address container") + public void validateAddressContainer(int position, Address billingAddress) + { + final int index = position - 1; + final SelenideElement addressContainer = $("#billAddr" + index); + final String fullName = billingAddress.getFirstName() + " " + billingAddress.getLastName(); + + // validate address data + addressContainer.find(".name").shouldHave(exactText(fullName)).shouldBe(visible); + addressContainer.find(".company").shouldHave(exactText(billingAddress.getCompany())).shouldBe(visible); + addressContainer.find(".city").shouldHave(exactText(billingAddress.getCity())).shouldBe(visible); + addressContainer.find(".state").shouldHave(exactText(billingAddress.getState())).shouldBe(visible); + addressContainer.find(".zip").shouldHave(exactText(billingAddress.getZip())).shouldBe(visible); + addressContainer.find(".country").shouldHave(exactText(billingAddress.getCountry())).shouldBe(visible); + } + + /// ----- select billing address ----- /// + + @Step("select a billing address on position '{position}'") + public ReturningCustomerPaymentPage selectBillingAddress(int position) + { + final int index = position - 1; + + // select address, press "Use this billing address" + $("#billAddr" + index + " input").scrollTo().click(); + useBillingAddressButton.scrollTo().click(); + + return new ReturningCustomerPaymentPage().isExpectedPage(); + } +} \ No newline at end of file diff --git a/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerPaymentPage.java b/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerPaymentPage.java new file mode 100644 index 00000000..d042d0a1 --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerPaymentPage.java @@ -0,0 +1,93 @@ +package posters.pageobjects.pages.checkout; + +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.tests.testdata.dataobjects.CreditCard; + +public class ReturningCustomerPaymentPage extends AbstractCheckoutPage +{ + private SelenideElement title = $("#titlePayment"); + + private SelenideElement addCreditCardButton = $(".form-group .btn"); + + private SelenideElement useCreditCardButton = $("#btnUsePayment"); + + + @Override + @Step("ensure this is a payment page") + public ReturningCustomerPaymentPage isExpectedPage() + { + super.isExpectedPage(); + $("#payment0").should(exist); + return this; + } + + /// ----- validate content returning customer payment page ----- /// + + @Step("validate breadcrumb") + public void validateBreadcrumb() + { + $("#btnToCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.cart"))).shouldBe(visible); + $("#btnShippAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.shippingAddress"))).shouldBe(visible); + $("#btnBillAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.billingAddress"))).shouldBe(visible); + $("#btnCreditCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.payment"))).shouldBe(visible); + $("#btnPlaceOrder").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.placeOrder"))).shouldBe(visible); + } + + @Override + @Step("validate returning customer payment page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate breadcrumb + validateBreadcrumb(); + + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress indicator + //validateProcessWrap(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerPaymentPage.title"))).shouldBe(visible); + + // validate add new shipping address button + addCreditCardButton.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerPaymentPage.button.addNewCreditCard"))).shouldBe(visible); + + // validate continue button + useCreditCardButton.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerPaymentPage.button.useCreditCard"))).shouldBe(visible); + } + + @Step("validate credit card '{creditCard}' on position '{position}' in credit card container") + public void validateCreditCardContainer(int position, CreditCard creditCard) + { + final int index = position - 1; + final SelenideElement creditCardContainer = $("#payment" + index); + final String expDate = creditCard.getExpDateMonth() + "/" + creditCard.getExpDateYear(); + + // validate address data + creditCardContainer.find(".name").shouldHave(exactText(creditCard.getFullName())).shouldBe(visible); + creditCardContainer.find(".creditCard").shouldHave(exactText(creditCard.getCrypticCardNumber())).shouldBe(visible); + creditCardContainer.find(".validTo").shouldHave(exactText(expDate)).shouldBe(visible); + } + + /// ----- select credit card ----- /// + + @Step("select a credit card on position '{position}'") + public PlaceOrderPage selectCreditCard(int position) + { + final int index = position - 1; + + // select address, press "Use this credit card" + $("#payment" + index + " input").scrollTo().click(); + useCreditCardButton.scrollTo().click(); + + return new PlaceOrderPage().isExpectedPage(); + } +} \ No newline at end of file diff --git a/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerShippingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerShippingAddressPage.java new file mode 100644 index 00000000..42fdaeda --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/checkout/ReturningCustomerShippingAddressPage.java @@ -0,0 +1,97 @@ +package posters.pageobjects.pages.checkout; + +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.tests.testdata.dataobjects.Address; + +public class ReturningCustomerShippingAddressPage extends AbstractCheckoutPage +{ + private SelenideElement title = $("#titleDelAddr"); + + private SelenideElement addShippingAddressButton = $(".form-group .btn"); + + private SelenideElement useShippingAddressButton = $("#btnUseAddressContinue"); + + @Override + @Step("ensure this is a shipping address page") + public ReturningCustomerShippingAddressPage isExpectedPage() + { + super.isExpectedPage(); + $("#delAddr0").should(exist); + return this; + } + + /// ----- validate content returning customer shipping address page ----- /// + + @Step("validate breadcrumb") + public void validateBreadcrumb() + { + $("#btnToCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.cart"))).shouldBe(visible); + $("#btnShippAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.shippingAddress"))).shouldBe(visible); + $("#btnBillAddr").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.billingAddress"))).shouldBe(visible); + $("#btnCreditCard").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.payment"))).shouldBe(visible); + $("#btnPlaceOrder").shouldHave(exactText(Neodymium.localizedText("AddressPages.breadcrumb.placeOrder"))).shouldBe(visible); + } + + @Override + @Step("validate returning customer shipping address page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate breadcrumb + validateBreadcrumb(); + + // validate process wrap + // TODO - after fixing issue 171: consistent element selectors for all checkout pages with progress indicator + //validateProcessWrap(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerShippingAddressPage.title"))).shouldBe(visible); + + // TODO - validate address count, get function needed + + // validate add new shipping address button + addShippingAddressButton.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerShippingAddressPage.button.addNewShipAddr"))).shouldBe(visible); + + // validate continue button + useShippingAddressButton.shouldHave(exactText(Neodymium.localizedText("ReturningCustomerShippingAddressPage.button.useShipAddr"))).shouldBe(visible); + } + + @Step("validate shipping address '{shippingAddress}' on position '{position}' in address container") + public void validateAddressContainer(int position, Address shippingAddress) + { + final int index = position - 1; + final SelenideElement addressContainer = $("#delAddr" + index); + final String fullName = shippingAddress.getFirstName() + " " + shippingAddress.getLastName(); + + // validate address data + addressContainer.find(".name").shouldHave(exactText(fullName)).shouldBe(visible); + addressContainer.find(".company").shouldHave(exactText(shippingAddress.getCompany())).shouldBe(visible); + addressContainer.find(".city").shouldHave(exactText(shippingAddress.getCity())).shouldBe(visible); + addressContainer.find(".state").shouldHave(exactText(shippingAddress.getState())).shouldBe(visible); + addressContainer.find(".zip").shouldHave(exactText(shippingAddress.getZip())).shouldBe(visible); + addressContainer.find(".country").shouldHave(exactText(shippingAddress.getCountry())).shouldBe(visible); + } + + /// ----- select shipping address ----- /// + + @Step("select a shipping address on position '{position}'") + public ReturningCustomerBillingAddressPage selectShippingAddress(int position) + { + final int index = position - 1; + + // select address, press "Continue" + $("#delAddr" + index + " input").scrollTo().click(); + useShippingAddressButton.scrollTo().click(); + + return new ReturningCustomerBillingAddressPage().isExpectedPage(); + } +} diff --git a/src/test/java/posters/pageobjects/pages/checkout/ShippingAddressPage.java b/src/test/java/posters/pageobjects/pages/checkout/ShippingAddressPage.java deleted file mode 100644 index abf1e0bb..00000000 --- a/src/test/java/posters/pageobjects/pages/checkout/ShippingAddressPage.java +++ /dev/null @@ -1,118 +0,0 @@ -package posters.pageobjects.pages.checkout; - -import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; -import static com.codeborne.selenide.Condition.visible; -import static com.codeborne.selenide.Selenide.$; - -import com.codeborne.selenide.SelenideElement; - -import io.qameta.allure.Step; - -/** - * @author pfotenhauer - */ -public class ShippingAddressPage extends AbstractCheckoutPage -{ - private SelenideElement headline = $("#titleDelAddr"); - - private SelenideElement nameField = $("#fullName"); - - private SelenideElement companyField = $("#company"); - - private SelenideElement addressField = $("#addressLine"); - - private SelenideElement cityField = $("#city"); - - private SelenideElement stateField = $("#state"); - - private SelenideElement zipField = $("#zip"); - - private SelenideElement countryField = $("#country"); - - private SelenideElement addShippingButton = $("#btnAddDelAddr"); - - @Override - @Step("ensure this is a shipping address page") - public ShippingAddressPage isExpectedPage() - { - super.isExpectedPage(); - headline.should(exist); - return this; - } - - @Override - @Step("validate shipping address page structure") - public void validateStructure() - { - super.validateStructure(); - - // Headline - // Assert the headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // First address - // Makes sure at least one address is visible - $("#delAddr0").shouldBe(visible); - } - - /** - * @param position - * position of the shipping address - * @return BillingAddressPage - */ - @Step("select a shipping address") - public BillingAddressPage selectShippingAddress(int position) - { - final int index = position - 1; - // Select address - // Checks the radio button belonging to the delivery address with index @{index} - $("#delAddr" + index + " input").scrollTo().click(); - // Open the billing address page in the checkout process - // Clicks the continue button - $("#btnUseAddressContinue").scrollTo().click(); - - return new BillingAddressPage().isExpectedPage(); - } - - @Step("fill and send shipping address form") - public BillingAddressPage sendShippingAddressForm(String name, String company, String address, String city, - String state, String zip, String country, boolean sameBillingAddress) - { - // Name - // Enter the name parameter - nameField.val(name); - // Company - // Enter the company parameter - companyField.val(company); - // Address - // Enter the address parameter - addressField.val(address); - // City - // Enter the city parameter - cityField.val(city); - // State - // Enter the state parameter - stateField.val(state); - // Zip - // Enter the zip parameter - zipField.val(zip); - // Country - // Select the country whose label equals the parameter - countryField.selectOption(country); - // Radio Button - // Click the radio button for Yes or No - if (sameBillingAddress) - { - $("#billEqualShipp-Yes").scrollTo().click(); - } - else - { - $("#billEqualShipp-No").scrollTo().click(); - } - // Open the billing addresses or payment options page, depending on which radio button you checked - // Click on Continue - addShippingButton.scrollTo().click(); - - return new BillingAddressPage().isExpectedPage(); - } -} diff --git a/src/test/java/posters/pageobjects/pages/user/AccountOverviewPage.java b/src/test/java/posters/pageobjects/pages/user/AccountOverviewPage.java index c76c8ddc..51038fcb 100644 --- a/src/test/java/posters/pageobjects/pages/user/AccountOverviewPage.java +++ b/src/test/java/posters/pageobjects/pages/user/AccountOverviewPage.java @@ -1,20 +1,25 @@ package posters.pageobjects.pages.user; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; import posters.pageobjects.pages.browsing.AbstractBrowsingPage; -/** - * @author pfotenhauer - */ public class AccountOverviewPage extends AbstractBrowsingPage { - private SelenideElement headline = $("#titleAccountOverview"); + private SelenideElement title = $("#titleAccountOverview"); + + private SelenideElement orderOverviewLink = $("#linkOrderOverview"); + + private SelenideElement myAddressesLink = $("#linkAddressOverview"); + + private SelenideElement paymentSettingsLink = $("#linkPaymentOverview"); private SelenideElement personalDataLink = $("#linkSettingOverview"); @@ -23,48 +28,55 @@ public class AccountOverviewPage extends AbstractBrowsingPage public AccountOverviewPage isExpectedPage() { super.isExpectedPage(); - headline.should(exist); + title.should(exist); return this; } + /// ----- validate content account overview page ----- /// + @Override @Step("validate account overview page structure") public void validateStructure() { super.validateStructure(); - // Headline - // Make sure the headline is there and start with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // Order Overview Link - // Make sure the link to the order history is there and the text starts with a capital letter - $("#linkOrderOverview").should(matchText("[A-Z].{3,}")); - // My Addresses Link - // Make sure the link to the Addresses page is there and the text starts with a capital letter - $("#linkAddressOverview").should(matchText("[A-Z].{3,}")); - // Payment Settings Link - // Make sure the link to the Credit Cards page is there and the text starts with a capital letter - $("#linkPaymentOverview").should(matchText("[A-Z].{3,}")); - // Personal Data Link - // Make sure the link to the Personal Data page is there and the text starts with a capital letter - personalDataLink.should(matchText("[A-Z].{3,}")); + // validate title + title.shouldHave(exactText(Neodymium.localizedText("AccountOverviewPage.title"))).shouldBe(visible); + + // validate navigation buttons + orderOverviewLink.shouldHave(exactText(Neodymium.localizedText("AccountOverviewPage.button.orderHistory"))).shouldBe(visible); + myAddressesLink.shouldHave(exactText(Neodymium.localizedText("AccountOverviewPage.button.myAddresses"))).shouldBe(visible); + paymentSettingsLink.shouldHave(exactText(Neodymium.localizedText("AccountOverviewPage.button.paymentSettings"))).shouldBe(visible); + personalDataLink.shouldHave(exactText(Neodymium.localizedText("AccountOverviewPage.button.personalData"))).shouldBe(visible); } - /** - * @return - */ + /// ----- account overview page navigation ----- /// + + @Step("open order history page") + public OrderHistoryPage openOrderHistory() + { + orderOverviewLink.scrollTo().click(); + return new OrderHistoryPage().isExpectedPage(); + } + + @Step("open my addresses page") + public MyAddressesPage openMyAddresses() + { + myAddressesLink.scrollTo().click(); + return new MyAddressesPage().isExpectedPage(); + } + + @Step("open payment settings page") + public PaymentSettingsPage openPaymentSettings() + { + paymentSettingsLink.scrollTo().click(); + return new PaymentSettingsPage().isExpectedPage(); + } + @Step("open personal data page") public PersonalDataPage openPersonalData() { - // Open the personal data page - // Click on the link to Personal Data personalDataLink.scrollTo().click(); return new PersonalDataPage().isExpectedPage(); } - - public OrderHistoryPage openOrderHistory() - { - $("#linkOrderOverview").scrollTo().click(); - return new OrderHistoryPage().isExpectedPage(); - } } diff --git a/src/test/java/posters/pageobjects/pages/user/DeleteAccountPage.java b/src/test/java/posters/pageobjects/pages/user/DeleteAccountPage.java index 8178db7c..5feb0284 100644 --- a/src/test/java/posters/pageobjects/pages/user/DeleteAccountPage.java +++ b/src/test/java/posters/pageobjects/pages/user/DeleteAccountPage.java @@ -1,8 +1,8 @@ package posters.pageobjects.pages.user; +import static com.codeborne.selenide.Condition.attribute; import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; @@ -13,9 +13,6 @@ import posters.pageobjects.pages.browsing.AbstractBrowsingPage; import posters.pageobjects.pages.browsing.HomePage; -/** - * @author pfotenhauer - */ public class DeleteAccountPage extends AbstractBrowsingPage { private SelenideElement deleteForm = $("#formDeleteAccount"); @@ -30,37 +27,48 @@ public DeleteAccountPage isExpectedPage() { super.isExpectedPage(); deleteForm.should(exist); + return this; } + /// ----- validate content delete account page ----- /// + + @Step("validate required string") + public void validateRequiredString() + { + $(".reqField").shouldHave(exactText(Neodymium.localizedText("AddressPages.fillIn.headlines.requiredFields"))).shouldBe(visible); + } + @Override @Step("validate delete account page structure") public void validateStructure() { super.validateStructure(); - // Headline - // Asserts the headline is there and starts with a capital letter - deleteForm.find(".h2").should(matchText("[A-Z].{3,}")); - // Password field - // Asserts the label belonging to the password field displays the correct text - $("label[for='password']").shouldBe(exactText(Neodymium.localizedText("AccountPages.yourPassword"))); - // Asserts the field to enter your password is there - passwordField.shouldBe(visible); - // Button - // Asserts the delete button is there - deleteButton.shouldBe(visible); + // validate title + deleteForm.find(".h2").shouldHave(exactText(Neodymium.localizedText("DeleteAccontPage.title"))).shouldBe(visible); + + // validate headline + $("label[for='password']").shouldBe(exactText(Neodymium.localizedText("DeleteAccontPage.headline"))); + + // validate placeholder + passwordField.shouldHave(attribute("placeholder", (Neodymium.localizedText("DeleteAccontPage.placeholder")))).shouldBe(visible); + + // validate "required fields" string + validateRequiredString(); + + // validate button + deleteButton.shouldHave(exactText(Neodymium.localizedText("DeleteAccontPage.button"))).shouldBe(visible); } + + /// ----- delete account page navigation ----- /// @Step("delete account") public HomePage deleteAccount(String password) { - // Password - // Type the parameter into the password field passwordField.setValue(password); - // Delete account and open the homepage - // click the confirmation button deleteButton.scrollTo().click(); + return new HomePage().isExpectedPage(); } } diff --git a/src/test/java/posters/pageobjects/pages/user/LoginPage.java b/src/test/java/posters/pageobjects/pages/user/LoginPage.java index 3b51a8bb..4f126108 100644 --- a/src/test/java/posters/pageobjects/pages/user/LoginPage.java +++ b/src/test/java/posters/pageobjects/pages/user/LoginPage.java @@ -1,23 +1,22 @@ package posters.pageobjects.pages.user; +import static com.codeborne.selenide.Condition.attribute; import static com.codeborne.selenide.Condition.exactText; -import static com.codeborne.selenide.Condition.exactValue; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; + +import org.junit.Assert; import com.codeborne.selenide.SelenideElement; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.User; +import posters.tests.testdata.dataobjects.User; import posters.pageobjects.pages.browsing.AbstractBrowsingPage; import posters.pageobjects.pages.browsing.HomePage; -/** - * @author pfotenhauer - */ public class LoginPage extends AbstractBrowsingPage { private SelenideElement loginForm = $("#formLogin"); @@ -39,116 +38,102 @@ public LoginPage isExpectedPage() return this; } + /// ----- validate content login page ----- /// + + @Step("validate required string") + public void validateRequiredString() + { + $(".reqField").shouldHave(exactText(Neodymium.localizedText("AddressPages.fillIn.headlines.requiredFields"))).shouldBe(visible); + } + @Override @Step("validate login page structure") public void validateStructure() { super.validateStructure(); - // Login headline - // Make sure the Headline is there and starts with a capital letter followed by at least 3 more symbols. - loginForm.find(".h2fwpr").should(matchText("[A-Z].{3,}")); - // Email field - // Asserts the Email field has a label displaying the value. - loginForm.find("label.control-label[for=email]").shouldHave(exactText(Neodymium.localizedText("AccountPages.yourEmail"))); - // Asserts the email field is present. - emailField.shouldBe(visible); - // Password field - // Verifies the password field has a label displaying the value. - loginForm.find("label.control-label[for=password]").shouldHave(exactText(Neodymium.localizedText("AccountPages.yourPassword"))); - // Asserts the password field is there. - passwordField.shouldBe(visible); - // Login button - // asserts the login button displays the value. - signInButton.shouldHave(exactText(Neodymium.localizedText("AccountPages.signIn"))); - // Register headline - // Asserts the Headline for the Registration is there. - $(".header-container .h2fwpr").shouldHave(exactText(Neodymium.localizedText("AccountPages.newCustomer"))); - // Registration page link - // Asserts the Register link is there and shows the correct text. - registerLink.shouldHave(exactText(Neodymium.localizedText("AccountPages.createNewAccount"))); - } - - @Step("send login form") - public void sendFormWithData(String email, String password) - { - // Input email - // Fill the email field with the parameter. - emailField.val(email); - // Input password - // Fill the password field with the parameter. - passwordField.val(password); - // Log in and open the homepage - // Click on the Sign In button. - signInButton.scrollTo().click(); + // validate title + loginForm.find("legend").shouldHave(exactText(Neodymium.localizedText("LoginPage.title"))).shouldBe(visible); + + // validate fill in headlines + $$("#formLogin .form-group label").findBy(exactText(Neodymium.localizedText("LoginPage.headlines.email"))).shouldBe(visible); + $$("#formLogin .form-group label").findBy(exactText(Neodymium.localizedText("LoginPage.headlines.password"))).shouldBe(visible); + + // validate fill in placeholder + emailField.shouldHave(attribute("placeholder", (Neodymium.localizedText("LoginPage.placeholder.email")))).shouldBe(visible); + passwordField.shouldHave(attribute("placeholder", (Neodymium.localizedText("LoginPage.placeholder.password")))).shouldBe(visible); + + // validate "required fields" string + validateRequiredString(); + + // validate sign in button + signInButton.shouldHave(exactText(Neodymium.localizedText("LoginPage.button"))); + + // validate new account creation + $(".header-container").shouldHave(exactText(Neodymium.localizedText("LoginPage.newCustomer"))); + registerLink.shouldHave(exactText(Neodymium.localizedText("LoginPage.createNewAccount"))); } - - /** - * @param email - * The email of the account you want to log into - * @param password - * The password of the account you want to log into - */ - @Step("send login form with valid data") - public HomePage sendLoginform(String email, String password) + + /// ----- validate success and error messages ----- /// + + @Step("validate successful registration message") + public void validateSuccessfulRegistration() { - sendFormWithData(email, password); - return new HomePage().isExpectedPage(); + successMessage.validateSuccessMessage(Neodymium.localizedText("LoginPage.validation.successfulRegistration")); } - /** - * @param user - * @return - */ - @Step("send login form with valid user data") - public HomePage sendLoginform(User user) + @Step("validate invalid email for login error message") + public void validateWrongEmail(String email) { - return sendLoginform(user.getEmail(), user.getPassword()); + errorMessage.validateErrorMessage(Neodymium.localizedText("LoginPage.validation.emailDoesNotExist")); + Assert.assertEquals(emailField.val(), email); } - - /** - * @param user - */ - @Step("send login form with erroneous user data") - public LoginPage sendFalseLoginform(User user) + + @Step("validate invalid password for login error message") + public void validateWrongPassword(String email) { - sendFormWithData(user.getEmail(), user.getPassword()); - return new LoginPage().isExpectedPage(); + errorMessage.validateErrorMessage(Neodymium.localizedText("LoginPage.validation.incorrectPassword")); + Assert.assertEquals(emailField.val(), email); } - - /** - * @return - */ + + /// ----- login page navigation ----- /// + @Step("open register page from login page") public RegisterPage openRegister() { registerLink.scrollTo().click(); return new RegisterPage().isExpectedPage(); } - - @Step("validate successful registration message") - public void validateSuccessfulRegistration() + + @Step("open homepage from login page") + public HomePage openHomePage() { - successMessage.validateSuccessMessage(Neodymium.localizedText("AccountPages.validation.successfulAccountCreation")); + $("#brand").scrollTo().click(); + return new HomePage().isExpectedPage(); } + + @Step("send login form") + public void sendFormWithData(String email, String password) + { + // fill out the login form + emailField.val(email); + passwordField.val(password); - /** - * @param eMail - */ - @Step("validate invalid email for login error message") - public void validateWrongEmail(String eMail) + // click on the Sign In button. + signInButton.scrollTo().click(); + } + + @Step("fill and send login form with valid user '{user}'") + public HomePage sendLoginForm(User user) { - errorMessage.validateErrorMessage(Neodymium.localizedText("AccountPages.validation.emailDoesNotExistError")); - emailField.shouldHave(exactValue(eMail)); + sendFormWithData(user.getEmail(), user.getPassword()); + return new HomePage().isExpectedPage(); } - - /** - * @param eMail - */ - @Step("validate invalid password for login error message") - public void validateWrongPassword(String eMail) + + @Step("fill and send login form with invalid user '{user}'") + public LoginPage sendFalseLoginForm(User user) { - errorMessage.validateErrorMessage(Neodymium.localizedText("AccountPages.validation.incorrectPasswordError")); - emailField.shouldHave(exactValue(eMail)); + sendFormWithData(user.getEmail(), user.getPassword()); + return new LoginPage().isExpectedPage(); } } diff --git a/src/test/java/posters/pageobjects/pages/user/MyAddressesPage.java b/src/test/java/posters/pageobjects/pages/user/MyAddressesPage.java new file mode 100644 index 00000000..5ca42c91 --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/user/MyAddressesPage.java @@ -0,0 +1,46 @@ +package posters.pageobjects.pages.user; + +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.pageobjects.pages.browsing.AbstractBrowsingPage; + +public class MyAddressesPage extends AbstractBrowsingPage +{ + private SelenideElement title = $("#titleAddressOverview"); + + @Override + @Step("ensure this is a personal data page") + public MyAddressesPage isExpectedPage() + { + super.isExpectedPage(); + title.should(exist); + return this; + } + + /// ----- validate content my addresses page ----- /// + + @Override + @Step("validate personal data page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("MyAddressesPage.title"))).shouldBe(visible); + + // validate shipping addresses overview + $("#titleDelAddr").shouldHave(exactText(Neodymium.localizedText("MyAddressesPage.headlines.shipAddr"))).shouldBe(visible); + $("#linkAddNewShipAddr").shouldHave(exactText(Neodymium.localizedText("General.button.addNewShipAddr"))).shouldBe(visible); + + // validate billing addresses overview + $("#titleBillAddr").shouldHave(exactText(Neodymium.localizedText("MyAddressesPage.headlines.billAddr"))).shouldBe(visible); + $("#linkAddNewBillAddr").shouldHave(exactText(Neodymium.localizedText("General.button.addNewBillAddr"))).shouldBe(visible); + } +} \ No newline at end of file diff --git a/src/test/java/posters/pageobjects/pages/user/OrderHistoryPage.java b/src/test/java/posters/pageobjects/pages/user/OrderHistoryPage.java index 097d57b4..03863dad 100644 --- a/src/test/java/posters/pageobjects/pages/user/OrderHistoryPage.java +++ b/src/test/java/posters/pageobjects/pages/user/OrderHistoryPage.java @@ -2,38 +2,46 @@ import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; +import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; import static com.codeborne.selenide.Selenide.$$; +import com.codeborne.selenide.ElementsCollection; import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.Product; import posters.pageobjects.pages.browsing.AbstractBrowsingPage; public class OrderHistoryPage extends AbstractBrowsingPage { - private SelenideElement headline = $("#titleOrderHistory"); + private SelenideElement title = $("#titleOrderHistory"); + + private ElementsCollection tableHead = $$(".product-name span"); @Override @Step("ensure this is an order history page") public OrderHistoryPage isExpectedPage() { super.isExpectedPage(); - headline.should(exist); + title.should(exist); return this; } - - @Step("validate product is in the order") - public void validateContainsProduct(Product product) + + /// ----- validate content order history page ----- /// + + @Override + @Step("validate personal data page structure") + public void validateStructure() { - SelenideElement productContainer = $$(".productInfo").filter((matchText(product.getRowRegex()))).shouldHaveSize(1).first() - .parent(); - - productContainer.find(".productName").shouldBe(exactText(product.getName())); - productContainer.find(".productStyle").shouldBe(exactText(product.getStyle())); - productContainer.find(".productSize").shouldBe(exactText(product.getSize())); - productContainer.find(".orderCount").shouldBe(exactText(Integer.toString(product.getAmount()) + "x")); + super.validateStructure(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("OrderHistoryPage.title"))).shouldBe(visible); + + // validate table Head + tableHead.findBy(exactText(Neodymium.localizedText("OrderHistoryPage.tableHead.purchasedPosters"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("OrderHistoryPage.tableHead.orderDetails"))).shouldBe(visible); + tableHead.findBy(exactText(Neodymium.localizedText("OrderHistoryPage.tableHead.quantity"))).shouldBe(visible); } -} +} \ No newline at end of file diff --git a/src/test/java/posters/pageobjects/pages/user/PaymentSettingsPage.java b/src/test/java/posters/pageobjects/pages/user/PaymentSettingsPage.java new file mode 100644 index 00000000..ba1894a8 --- /dev/null +++ b/src/test/java/posters/pageobjects/pages/user/PaymentSettingsPage.java @@ -0,0 +1,40 @@ +package posters.pageobjects.pages.user; + +import static com.codeborne.selenide.Condition.exist; +import static com.codeborne.selenide.Condition.exactText; +import static com.codeborne.selenide.Condition.visible; +import static com.codeborne.selenide.Selenide.$; + +import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Step; +import posters.pageobjects.pages.browsing.AbstractBrowsingPage; + +public class PaymentSettingsPage extends AbstractBrowsingPage +{ + private SelenideElement title = $("#titlePaymentOverview"); + + @Override + @Step("ensure this is a personal data page") + public PaymentSettingsPage isExpectedPage() + { + super.isExpectedPage(); + title.should(exist); + return this; + } + + /// ----- validate content payment settings page ----- /// + + @Override + @Step("validate personal data page structure") + public void validateStructure() + { + super.validateStructure(); + + // validate title + title.shouldHave(exactText(Neodymium.localizedText("PaymentSettingsPage.title"))).shouldBe(visible); + + $("#linkAddNewPayment").shouldHave(exactText(Neodymium.localizedText("PaymentSettingsPage.button.addNewCreditCard"))).shouldBe(visible); + } +} \ No newline at end of file diff --git a/src/test/java/posters/pageobjects/pages/user/PersonalDataPage.java b/src/test/java/posters/pageobjects/pages/user/PersonalDataPage.java index eea2048d..517062f1 100644 --- a/src/test/java/posters/pageobjects/pages/user/PersonalDataPage.java +++ b/src/test/java/posters/pageobjects/pages/user/PersonalDataPage.java @@ -1,21 +1,21 @@ package posters.pageobjects.pages.user; +import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; import com.codeborne.selenide.SelenideElement; +import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; import posters.pageobjects.pages.browsing.AbstractBrowsingPage; +import posters.tests.testdata.dataobjects.User; -/** - * @author pfotenhauer - */ public class PersonalDataPage extends AbstractBrowsingPage { - private SelenideElement headline = $("#titlePersonalData"); + private SelenideElement title = $("#titlePersonalData"); private SelenideElement deleteButton = $("#btnDeleteAccount"); @@ -24,36 +24,45 @@ public class PersonalDataPage extends AbstractBrowsingPage public PersonalDataPage isExpectedPage() { super.isExpectedPage(); - headline.should(exist); + title.should(exist); return this; } + /// ----- validate content personal data page ----- /// + @Override @Step("validate personal data page structure") public void validateStructure() { super.validateStructure(); - // Headline - // Makes sure the headline is there and starts with a capital letter - headline.should(matchText("[A-Z].{3,}")); - // Data - // Makes sure the form with your user Data is there - $("#customerName").shouldBe(visible); - $("#customerEmail").shouldBe(visible); - // Delete Account Button - // Make sure the button to delete your account is there - deleteButton.shouldBe(visible); + // validate title + title.shouldHave(exactText(Neodymium.localizedText("PersonalDataPage.title"))).shouldBe(visible); + + // validate buttons + $("#btnChangeNameEmail").shouldHave(exactText(Neodymium.localizedText("PersonalDataPage.buttons.changeData"))).shouldBe(visible); + $("#btnChangePassword").shouldHave(exactText(Neodymium.localizedText("PersonalDataPage.buttons.changePassword"))).shouldBe(visible); + deleteButton.shouldHave(exactText(Neodymium.localizedText("PersonalDataPage.buttons.deleteAccount"))).shouldBe(visible); } - - /** - * @return - */ + + @Step("validate personal data of '{user}") + public void validatePersonalData(User user) + { + // validate name + String fullName = user.getFirstName() + " " + user.getLastName(); + $$(".form-group strong").findBy(exactText(Neodymium.localizedText("PersonalDataPage.headlines.name"))).shouldBe(visible); + $("#customerName").shouldHave(exactText(fullName)).shouldBe(visible); + + // validate email + $$(".form-group strong").findBy(exactText(Neodymium.localizedText("PersonalDataPage.headlines.email"))).shouldBe(visible); + $("#customerEmail").shouldHave(exactText(user.getEmail())).shouldBe(visible); + } + + /// ----- personal data page navigation ----- /// + @Step("open delete account page from personal data page") - public DeleteAccountPage openDeleteAccount() + public DeleteAccountPage openDeleteAccountPage() { - // Open the delete account page - // Clicks the button to get to the Delete Account page deleteButton.scrollTo().click(); return new DeleteAccountPage().isExpectedPage(); } diff --git a/src/test/java/posters/pageobjects/pages/user/RegisterPage.java b/src/test/java/posters/pageobjects/pages/user/RegisterPage.java index 23f6fa1c..132e77cc 100644 --- a/src/test/java/posters/pageobjects/pages/user/RegisterPage.java +++ b/src/test/java/posters/pageobjects/pages/user/RegisterPage.java @@ -1,29 +1,27 @@ package posters.pageobjects.pages.user; +import static com.codeborne.selenide.Condition.attribute; import static com.codeborne.selenide.Condition.exactText; import static com.codeborne.selenide.Condition.exist; -import static com.codeborne.selenide.Condition.matchText; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; import com.codeborne.selenide.SelenideElement; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Step; -import posters.dataobjects.User; +import posters.tests.testdata.dataobjects.User; import posters.pageobjects.pages.browsing.AbstractBrowsingPage; -/** - * @author pfotenhauer - */ public class RegisterPage extends AbstractBrowsingPage { private SelenideElement registerForm = $("#formRegister"); - private SelenideElement firstnameField = $("#firstName"); + private SelenideElement firstNameField = $("#firstName"); - private SelenideElement lastnameField = $("#lastName"); + private SelenideElement lastNameField = $("#lastName"); private SelenideElement emailField = $("#eMail"); @@ -42,61 +40,74 @@ public RegisterPage isExpectedPage() return this; } + /// ----- validate content register page ----- /// + + private void validateFillInHeadlines(String headline) + { + $$("#formRegister .form-group label").findBy(exactText(headline)).shouldBe(visible); + } + + @Step("validate fill-in form headlines") + public void validateFillInHeadlines() + { + validateFillInHeadlines(Neodymium.localizedText("RegisterPage.headlines.firstName")); + validateFillInHeadlines(Neodymium.localizedText("RegisterPage.headlines.lastName")); + validateFillInHeadlines(Neodymium.localizedText("RegisterPage.headlines.email")); + validateFillInHeadlines(Neodymium.localizedText("RegisterPage.headlines.password")); + validateFillInHeadlines(Neodymium.localizedText("RegisterPage.headlines.passwordRepeat")); + } + + @Step("validate fill in form placeholder") + public void validateFillInPlaceholder() + { + firstNameField.shouldHave(attribute("placeholder", (Neodymium.localizedText("RegisterPage.placeholder.firstName")))).shouldBe(visible); + lastNameField.shouldHave(attribute("placeholder", (Neodymium.localizedText("RegisterPage.placeholder.lastName")))).shouldBe(visible); + emailField.shouldHave(attribute("placeholder", (Neodymium.localizedText("RegisterPage.placeholder.email")))).shouldBe(visible); + passwordField.shouldHave(attribute("placeholder", (Neodymium.localizedText("RegisterPage.placeholder.password")))).shouldBe(visible); + passwordRepeatField.shouldHave(attribute("placeholder", (Neodymium.localizedText("RegisterPage.placeholder.passwordRepeat")))).shouldBe(visible); + } + + @Step("validate required string") + public void validateRequiredString() + { + $(".reqField").shouldHave(exactText(Neodymium.localizedText("AddressPages.fillIn.headlines.requiredFields"))).shouldBe(visible); + } + @Override @Step("validate register page structure") public void validateStructure() { super.validateStructure(); - // Login headline - // Make sure the Headline is there and starts with a capital letter followed by at least 3 more symbols. - registerForm.find(".h2fwpr").should(matchText("[A-Z].{3,}")); - // Form - // Asserts the label belonging to the last name field displays the correct text - $("label[for='lastName']").shouldHave(exactText(Neodymium.localizedText("AccountPages.lastname"))); - // Make sure the field to type in the last name is visible. - lastnameField.shouldBe(visible); - // Asserts the label belonging to the first name field displays the correct text - $("label[for='firstName']").shouldHave(exactText(Neodymium.localizedText("AccountPages.firstname"))); - // Make sure the field to type in the first name is visible. - firstnameField.shouldBe(visible); - // Asserts the label belonging to the email field displays the correct text - $("label[for='eMail']").shouldHave(exactText(Neodymium.localizedText("AccountPages.email"))); - // Make sure the field to type in the e-Mail is visible. - emailField.shouldBe(visible); - // Asserts the label belonging to the password field displays the correct text - $("label[for='password']").shouldHave(exactText(Neodymium.localizedText("AccountPages.password"))); - // Make sure the field to type in the password is visible. - passwordField.shouldBe(visible); - // Asserts the label belonging to the second password field displays the correct text - $("label[for='passwordAgain']").shouldHave(exactText(Neodymium.localizedText("AccountPages.passwordRepeat"))); - // Make sure the field to type in the password again is visible. - passwordRepeatField.shouldBe(visible); - // Register button - // Make sure the Registration button displays the correct text. - registerButton.shouldHave(exactText(Neodymium.localizedText("AccountPages.createAccount"))); + // validate title + registerForm.find("legend").shouldHave(exactText(Neodymium.localizedText("RegisterPage.title"))).shouldBe(visible); + + // validate fill in headlines + validateFillInHeadlines(); + + // validate fill in placeholder + validateFillInPlaceholder(); + + // validate "required fields" string + validateRequiredString(); + + // validate sign in button + registerButton.shouldHave(exactText(Neodymium.localizedText("RegisterPage.button"))); } - /** - * @param user - * The User data of the account you want to log into - */ - @Step("fill and send register form") + /// ----- register page navigation ----- /// + + @Step("fill and send register form with '{user}'") public LoginPage sendRegisterForm(User user) { - // Fill out the registration form - // Type the last name parameter into the last name field. - lastnameField.val(user.getLastName()); - // Type the first name parameter into the first name field. - firstnameField.val(user.getFirstName()); - // Type the email parameter into the email field. + // fill out the registration form + lastNameField.val(user.getLastName()); + firstNameField.val(user.getFirstName()); emailField.val(user.getEmail()); - // Type the password parameter into the password field. passwordField.val(user.getPassword()); - // Type the second password parameter into the second password field. passwordRepeatField.val(user.getPassword()); - // Register and open the login page if successful - // Click on the Register Button + + // click on the Register Button registerButton.scrollTo().click(); return new LoginPage().isExpectedPage(); diff --git a/src/test/java/posters/pageobjects/utility/PriceHelper.java b/src/test/java/posters/pageobjects/utility/PriceHelper.java index 8a481717..05257f05 100644 --- a/src/test/java/posters/pageobjects/utility/PriceHelper.java +++ b/src/test/java/posters/pageobjects/utility/PriceHelper.java @@ -4,48 +4,105 @@ import java.text.DecimalFormatSymbols; import java.util.Locale; -/** - * @author pfotenhauer - */ +import io.qameta.allure.Step; + public class PriceHelper { public final static String CURRENCY = "$"; private final static DecimalFormat decimalFormat = new DecimalFormat("##0.00", new DecimalFormatSymbols(Locale.US)); - // Calculate units * price per unit - // calculates price per 1 unit * amount, rounds it to 2 decimals (to avoid things like 19.9 instead of 19.90) - public static String computeRowPrice(String unitPrice, String quantity) + /// ----- format string ----- /// + + @Step("remove $ from '{price}'") + public static String removeCurrency(String price) { - double res = (double) (Math.round(Double.valueOf(removeCurrency(unitPrice)) * Double.valueOf(quantity) * 100)) / 100; - return format(res); + return price.substring(1); } - // Subtracts the old subtotal from the new one, rounds the result to 2 decimals (to avoid things like 19.9 - // instead of 19.90) and compares it to the price of the new item - public static String subtractFromPrice(String from, String value) + @Step("add $ to '{price}'") + public static String addCurrency(String price) { - double res = (double) (Math.round((Double.valueOf(removeCurrency(from)) - Double.valueOf(removeCurrency(value))) * 100)) / 100; - return format(res); + return CURRENCY + price; } + @Step("get formatted price") public static String format(double input) { return addCurrency(decimalFormat.format(input)); } - public static String removeCurrency(String price) + /// ----- calculations for price summary ----- /// + + /** + * @return unitPrice * quantity + */ + @Step("calculate total product price") + public static String totalProductPrice(String unitPrice, String quantity) { - String s = price.substring(1); - return s; + double res = (double) (Math.round((Double.valueOf(removeCurrency(unitPrice)) * Double.valueOf(quantity)) * 100)) / 100; + return format(res); } /** - * @param price - * @return + * @return minuend - subtrahend */ - public static String addCurrency(String price) + @Step("calculate difference") + public static String substract(String minuend, String subtrahend) { - return CURRENCY + price; + double res = (double) (Math.round((Double.valueOf(removeCurrency(minuend)) - Double.valueOf(removeCurrency(subtrahend))) * 100)) / 100; + return format(res); + } + + /** + * @return oldSubtotal + totalProductPrice + */ + // TODO - after fixing issue: put together with calculateSubtotalMiniCart() + @Step("adds total product price to sum") + public static double calculateSubtotalPlaceOrderPage(double oldSubtotal, String totalProductPrice) + { + return (double) (Math.round((oldSubtotal + Double.valueOf(totalProductPrice)) * 100)) / 100; + } + + /** + * @return (shippingCosts + subtotal) * 0.06 + */ + @Step("calculate tax") + public static String calculateTax(String shippingCosts, String subtotal) + { + double totalPrice = (double) (Math.round((Double.valueOf(removeCurrency(shippingCosts)) + Double.valueOf(removeCurrency(subtotal))) * 100)) / 100; + double tax = (double) (Math.round((Double.valueOf(totalPrice) * 0.06) * 100)) / 100; + return format(tax); + } + + /** + * @return subtotal + shippingCosts + tax + */ + @Step("calculate grand total price") + public static String calculateGrandTotal(String subtotal, String shippingCosts, String tax) + { + double grandTotal = (double) (Math.round((Double.valueOf(removeCurrency(subtotal)) + Double.valueOf(removeCurrency(shippingCosts)) + + Double.valueOf(removeCurrency(tax))) * 100)) / 100; + return format(grandTotal); + } + + /// ----- calculations for mini cart ----- /// + + /** + * @return totalCount + productCount + */ + @Step("add productCount to totalCount") + public static int calculateTotalCountMiniCart(int totalCount, String productCount) + { + return (totalCount + Integer.parseInt(productCount)); + } + + /** + * @return oldSubtotal + totalProductPrice + */ + @Step("adds total product price to sum") + public static double calculateSubtotalMiniCart(double oldSubtotal, String totalProductPrice) + { + return (double) (Math.round((oldSubtotal + Double.valueOf(removeCurrency(totalProductPrice))) * 100)) / 100; } } diff --git a/src/test/java/posters/tests/AbstractTest.java b/src/test/java/posters/tests/AbstractTest.java index f5670906..740a5731 100644 --- a/src/test/java/posters/tests/AbstractTest.java +++ b/src/test/java/posters/tests/AbstractTest.java @@ -7,11 +7,8 @@ import com.xceptance.neodymium.NeodymiumRunner; import com.xceptance.neodymium.module.statement.browser.multibrowser.Browser; -/** - * @author pfotenhauer - */ @RunWith(NeodymiumRunner.class) -@Browser("Firefox_1024x768") +@Browser("Chrome_1024x768") public abstract class AbstractTest { protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractTest.class); diff --git a/src/test/java/posters/tests/component/HeaderTest.java b/src/test/java/posters/tests/component/HeaderTest.java new file mode 100644 index 00000000..70140b67 --- /dev/null +++ b/src/test/java/posters/tests/component/HeaderTest.java @@ -0,0 +1,50 @@ +package posters.tests.component; + +import org.junit.Test; + +import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.module.statement.testdata.SuppressDataSets; +import com.xceptance.neodymium.util.DataUtils; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Owner; +import io.qameta.allure.Severity; +import io.qameta.allure.SeverityLevel; +import io.qameta.allure.junit4.Tag; +import posters.flows.OpenHomePageFlow; +import posters.tests.AbstractTest; +import posters.tests.testdata.pageobjects.components.HeaderTestData; + +@Owner("Tim Brown") +@Severity(SeverityLevel.MINOR) +@Tag("smoke") +@SuppressDataSets +public class HeaderTest extends AbstractTest +{ + @Test + @DataSet(1) + public void testHeader() + { + // use test data + final HeaderTestData headerTestData = DataUtils.get(HeaderTestData.class); + + // go to homepage + var homePage = OpenHomePageFlow.flow(); + homePage.header.validateStructure(); + + // go to category page + var categoryPage = homePage.header.topNav.clickCategory(Neodymium.localizedText(headerTestData.getTopCategory())); + categoryPage.header.validateStructure(); + + //go to product detail page, add product to cart + var productDetailPage = categoryPage.clickProductByPosition(headerTestData.getResultPosition()); + productDetailPage.header.validateStructure(); + + // go to cart page + var cartPage = productDetailPage.header.miniCart.openCartPage(); + cartPage.header.validateStructure(); + + // go to homepage + homePage = cartPage.openHomePage(); + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/component/PaginationTest.java b/src/test/java/posters/tests/component/PaginationTest.java new file mode 100644 index 00000000..d4726760 --- /dev/null +++ b/src/test/java/posters/tests/component/PaginationTest.java @@ -0,0 +1,41 @@ +package posters.tests.component; + +import org.junit.Test; + +import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.module.statement.testdata.SuppressDataSets; +import com.xceptance.neodymium.util.DataUtils; +import com.xceptance.neodymium.util.Neodymium; + +import io.qameta.allure.Owner; +import io.qameta.allure.Severity; +import io.qameta.allure.SeverityLevel; +import io.qameta.allure.junit4.Tag; +import posters.flows.OpenHomePageFlow; +import posters.tests.AbstractTest; +import posters.tests.testdata.pageobjects.components.PaginationTestData; + +@Owner("Tim Brown") +@Severity(SeverityLevel.MINOR) +@Tag("smoke") +@SuppressDataSets +public class PaginationTest extends AbstractTest +{ + @Test + @DataSet(1) + public void testPagination() + { + // use test data + final PaginationTestData paginationTestData = DataUtils.get(PaginationTestData.class); + + // go to homepage + var homePage = OpenHomePageFlow.flow(); + + // go to category page + var categoryPage = homePage.header.topNav.clickCategory(Neodymium.localizedText(paginationTestData.getTopCategory())); + categoryPage.pagination.validateStructure(paginationTestData.getExpectedResultCount()); + + // go to homepage + homePage = categoryPage.openHomePage(); + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/smoke/AddToCartTest.java b/src/test/java/posters/tests/smoke/AddToCartTest.java index e5887a12..657bd5ee 100644 --- a/src/test/java/posters/tests/smoke/AddToCartTest.java +++ b/src/test/java/posters/tests/smoke/AddToCartTest.java @@ -1,15 +1,20 @@ package posters.tests.smoke; +import org.junit.After; import org.junit.Test; +import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.util.DataUtils; import com.xceptance.neodymium.util.Neodymium; import io.qameta.allure.Owner; import io.qameta.allure.Severity; import io.qameta.allure.SeverityLevel; import io.qameta.allure.junit4.Tag; +import posters.flows.CartCleanUpFlow; import posters.flows.OpenHomePageFlow; import posters.tests.AbstractTest; +import posters.tests.testdata.processes.AddToCartTestData; @Owner("Joe Fix") @Severity(SeverityLevel.CRITICAL) @@ -17,104 +22,138 @@ public class AddToCartTest extends AbstractTest { @Test + @DataSet(1) + @DataSet(2) public void testAddProductsToCart() - { + { + // use test data final String shippingCosts = Neodymium.dataValue("shippingCosts"); - int totalCount = 0; + final AddToCartTestData addToCartTestData = DataUtils.get(AddToCartTestData.class); - // Go to homepage + /// ----- PART 1: USE TOP NAVIGATION TO ADD PRODUCT TO CART ----- /// + + // go to homepage var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - - homePage.miniCart.validateTotalCount(totalCount); - homePage.miniCart.validateSubtotal("$0.00"); - final String oldSubtotal = homePage.miniCart.getSubtotal(); - - // Go to a top category page - final String topCatName = Neodymium.dataValue("topCatName"); - var categoryPage = homePage.topNav.clickCategory(topCatName); - categoryPage.validateCategoryName(topCatName); + + // store old subtotal + final String oldSubtotal = homePage.header.miniCart.getSubtotal(); - // Go to sub category page - final String categoryName = categoryPage.topNav.getSubCategoryNameByPosition(1, 1); - categoryPage = categoryPage.topNav.clickSubCategoryByPosition(1, 1); - categoryPage.validate(categoryName); + // go to sub category page + var categoryPage = homePage.header.topNav.clickCategory(Neodymium.localizedText(addToCartTestData.getTopCategory())); + var subCategoryPage = categoryPage.header.topNav.clickSubCategory(Neodymium.localizedText(addToCartTestData.getTopCategory()), Neodymium.localizedText(addToCartTestData.getSubCategory())); - // Go to product page and add to cart - final String productName = categoryPage.getProductNameByPosition(1, 1); - var productDetailPage = categoryPage.clickProductByPosition(1, 1); - productDetailPage.validate(productName); - productDetailPage.addToCart("16 x 12 in", "matte"); - - // Go to cart and validate + // go to product detail page, add and store displayed product + var productDetailPage = subCategoryPage.clickProductByPosition(addToCartTestData.getSubCategoryResultPosition()); + productDetailPage.addToCart(addToCartTestData.getSizeFirstProduct(), addToCartTestData.getStyleFirstProduct()); final var product = productDetailPage.getProduct(); - var cartPage = productDetailPage.miniCart.openCartPage(); - cartPage.validate(shippingCosts); - cartPage.miniCart.validateMiniCart(1, product); - cartPage.validateCartItem(1, product); - cartPage.validateSubAndLineItemTotalAfterAdd(1, oldSubtotal, 0.00); - - final String oldSubtotal2 = cartPage.miniCart.getSubtotal(); - cartPage.miniCart.validateTotalCount(++totalCount); - - // Search for product on cart page - final String searchTerm = Neodymium.dataValue("searchTerm"); - final int searchTermExpectedCount = 1; - categoryPage = cartPage.search.categoryPageResult(searchTerm); - categoryPage.validateSearchHits(searchTerm, searchTermExpectedCount); - final String productName2 = categoryPage.getProductNameByPosition(1, 1); - - // Go to product page and add to cart - productDetailPage = categoryPage.clickProductByPosition(1, 1); - productDetailPage.validate(productName2); - productDetailPage.addToCart("64 x 48 in", "gloss"); + // go to cart page + var cartPage = productDetailPage.header.miniCart.openCartPage(); + + // validate cart page + cartPage.validateCartItem(1, product); + cartPage.validate(shippingCosts, cartPage.header.miniCart.getSubtotal()); + cartPage.validateTotalAfterAdd(1, oldSubtotal, 0.00); + cartPage.header.miniCart.validateStructure(); + cartPage.header.miniCart.validateMiniCartItem(1, product); + + /// ----- PART 2: USE SEARCH BAR TO ADD PRODUCT TO CART ----- /// + + // store old subtotal + final String oldSubtotal2 = cartPage.header.miniCart.getSubtotal(); + + // go to category page via search + categoryPage = cartPage.header.search.categoryPageResult(addToCartTestData.getSearchTerm()); + + // go to product detail page, add and store displayed product + productDetailPage = categoryPage.clickProductByPosition(addToCartTestData.getSearchResultPosition()); + productDetailPage.addToCart(addToCartTestData.getSizeSecondProduct(), addToCartTestData.getStyleSecondProduct()); final var product2 = productDetailPage.getProduct(); - // Go to cart and validate - cartPage = productDetailPage.miniCart.openCartPage(); - cartPage.validate(shippingCosts); - - cartPage.miniCart.validateMiniCart(1, product2); + // go to cart page + cartPage = productDetailPage.header.miniCart.openCartPage(); - cartPage.miniCart.validateTotalCount(++totalCount); + // validate cart page cartPage.validateCartItem(1, product2); - cartPage.validateSubAndLineItemTotalAfterAdd(1, oldSubtotal2, 0.00); - - int productToUpdatePosition = 1; - int newProductAmount = 3; - final String oldSubtotal3 = cartPage.miniCart.getSubtotal(); - final var productBeforeUpdate = cartPage.getProduct(productToUpdatePosition); - - // Update amount of product on cart page - cartPage.updateProductCount(productToUpdatePosition, newProductAmount); - cartPage.validateProductAmount(productToUpdatePosition, newProductAmount); - - final String newLinItemPrice = cartPage.getProductTotalUnitPrice(productToUpdatePosition); - cartPage.validateSubAndLineItemTotalAfterAdd(productToUpdatePosition, - oldSubtotal3, - productBeforeUpdate.getTotalPrice()); - cartPage.validateCartItem(1, productBeforeUpdate, newProductAmount); - cartPage.miniCart.validateMiniCart(1, productBeforeUpdate, newProductAmount, newLinItemPrice); - totalCount = totalCount + newProductAmount - 1; - cartPage.miniCart.validateTotalCount(totalCount); - - final String oldLineItemTotal = cartPage.getProductTotalUnitPrice(productToUpdatePosition); - final String oldSubTotal4 = cartPage.miniCart.getSubtotal(); - - // Remove product on cart page - cartPage.removeProduct(productToUpdatePosition); - cartPage.validateSubAndLineItemTotalAfterRemove(oldSubTotal4, oldLineItemTotal); - totalCount = totalCount - newProductAmount; - cartPage.miniCart.validateTotalCount(totalCount); - - final var productFromCartPage = cartPage.getProduct(1); - productDetailPage = cartPage.openProductPage(1); - productDetailPage.validate(productFromCartPage.getName()); - productDetailPage.addToCart(productFromCartPage.getSize(), productFromCartPage.getStyle()); - cartPage = productDetailPage.miniCart.openCartPage(); - - cartPage.validateCartItem(1, productFromCartPage, 2); - cartPage.miniCart.validateTotalCount(++totalCount); + cartPage.validateCartItem(2, product); + cartPage.validate(shippingCosts, cartPage.header.miniCart.getSubtotal()); + cartPage.validateTotalAfterAdd(1, oldSubtotal2, 0.00); + cartPage.header.miniCart.validateStructure(); + cartPage.header.miniCart.validateMiniCartItem(1, product2); + cartPage.header.miniCart.validateMiniCartItem(2, product); + + /// ----- PART 3: CHANGE QUANTITY OF PRODUCT IN CART ----- /// + + // store old subtotal + final String oldSubtotal3 = cartPage.header.miniCart.getSubtotal(); + + // store product before update + final var productBeforeUpdate = cartPage.getProduct(addToCartTestData.getProductUpdatePosition()); + + // update amount of product on cart page + cartPage.updateProductCount(addToCartTestData.getProductUpdatePosition(), addToCartTestData.getAmountChange()); + + // store subtotal of updated product + String subtotalAfterUpdate = cartPage.getProductTotalPrice(addToCartTestData.getProductUpdatePosition()); + + // validate cart page + cartPage.validateCartItem(addToCartTestData.getProductUpdatePosition(), productBeforeUpdate, addToCartTestData.getAmountChange()); + cartPage.validate(shippingCosts, cartPage.header.miniCart.getSubtotal()); + cartPage.validateTotalAfterAdd(addToCartTestData.getProductUpdatePosition(), oldSubtotal3, productBeforeUpdate.getTotalPrice()); + cartPage.header.miniCart.validateStructure(); + cartPage.header.miniCart.validateMiniCartItem(1, productBeforeUpdate, addToCartTestData.getAmountChange(), subtotalAfterUpdate); + + /// ----- PART 4: REMOVE PRODUCT FROM CART ----- /// + + // store old subtotal + final String oldSubtotal4 = cartPage.header.miniCart.getSubtotal(); + + // store subtotal product before remove + final String subtotalBeforeRemove = cartPage.getProductTotalPrice(1); + + // remove first product on cart page + cartPage.removeProduct(1); + + // validate cart page + cartPage.validateCartItem(1, product); + cartPage.validate(shippingCosts, cartPage.header.miniCart.getSubtotal()); + cartPage.validateTotalAfterRemove(oldSubtotal4, subtotalBeforeRemove); + cartPage.header.miniCart.validateStructure(); + cartPage.header.miniCart.validateMiniCartItem(1, product); + + /// ----- PART 5: ADD SAME PRODUCT TO CART AGAIN ----- /// + + // store old subtotal + final String oldSubtotal5 = cartPage.header.miniCart.getSubtotal(); + + // store product on cart page + final var productFromCartPageBefore = cartPage.getProduct(1); + + // go to product detail page, add product to cart + productDetailPage = cartPage.openProductDetailPage(1); + productDetailPage.addToCart(productFromCartPageBefore.getSize(), productFromCartPageBefore.getStyle()); + + // go to cart + cartPage = productDetailPage.header.miniCart.openCartPage(); + + // store subtotal of updated product + subtotalAfterUpdate = cartPage.getProductTotalPrice(1); + final var productFromCartPageAfter = cartPage.getProduct(1); + + // validate cart page + cartPage.validateCartItem(1, productFromCartPageBefore, productFromCartPageAfter.getAmount()); + cartPage.validate(shippingCosts, cartPage.header.miniCart.getSubtotal()); + cartPage.validateTotalAfterAdd(1, oldSubtotal5, productFromCartPageBefore.getTotalPrice()); + cartPage.header.miniCart.validateStructure(); + cartPage.header.miniCart.validateMiniCartItem(1, productFromCartPageBefore, cartPage.header.miniCart.getTotalCount(), subtotalAfterUpdate); + + // go to homepage + homePage = cartPage.openHomePage(); + } + + @After + public void after() + { + CartCleanUpFlow.flow(); } } diff --git a/src/test/java/posters/tests/smoke/BrowseRandomVisualAssertTest.java b/src/test/java/posters/tests/smoke/BrowseRandomVisualAssertTest.java deleted file mode 100644 index 8ac9a099..00000000 --- a/src/test/java/posters/tests/smoke/BrowseRandomVisualAssertTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package posters.tests.smoke; - -import java.util.Random; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import com.xceptance.neodymium.module.statement.browser.multibrowser.Browser; -import com.xceptance.neodymium.util.DataUtils; - -import io.qameta.allure.Owner; -import io.qameta.allure.Severity; -import io.qameta.allure.SeverityLevel; -import io.qameta.allure.junit4.Tag; -import posters.flows.OpenHomePageFlow; -import posters.pageobjects.pages.browsing.CategoryPage; -import posters.pageobjects.pages.browsing.ProductDetailPage; -import posters.tests.AbstractTest; - -/** - * @author schaefer - */ -@Owner("Tim Brown") -@Severity(SeverityLevel.NORMAL) -@Tag("smoke") -@Browser("Firefox_headless") -@Ignore -public class BrowseRandomVisualAssertTest extends AbstractTest -{ - private static int numberOfProductDetailPages; - - private static Random random; - - @Before - public void setup() - { - try - { - random = new Random(DataUtils.asLong("seed")); - } - catch (Exception e) - { - random = new Random(); - } - - try - { - numberOfProductDetailPages = DataUtils.asInt("numberOfProductDetailPages"); - } - catch (Exception e) - { - numberOfProductDetailPages = random.nextInt(10) + 1; - } - } - - @Test - public void browseRandomCategoriesAndProducts() - { - CategoryPage categoryPage; - ProductDetailPage productPage; - - for (int i = 1; i <= numberOfProductDetailPages; i++) - { - // Go to homepage - LOGGER.info("Homepage"); - var homePage = OpenHomePageFlow.flow(); - homePage.validateAndVisualAssert(); - - // Go to category - LOGGER.info("Category page"); - String categoryName = homePage.topNav.getRandomSubcategoryName(random); - categoryPage = homePage.topNav.clickSubcategoryByName(categoryName); - categoryPage.validateAndVisualAssert(categoryName); - categoryPage = categoryPage.pagination.clickOnRandomSite(random); - categoryPage.scrollToTop(); - categoryPage.validateAndVisualAssert(categoryName); - - // Go to any product detail page - LOGGER.info("Product detail page"); - String productName = categoryPage.getRandomProductDetailName(random); - productPage = categoryPage.clickProductByName(productName); - productPage.validateAndVisualAssert(productName); - } - } -} \ No newline at end of file diff --git a/src/test/java/posters/tests/smoke/BrowseTest.java b/src/test/java/posters/tests/smoke/BrowseTest.java index 3e36e56e..29cee3aa 100644 --- a/src/test/java/posters/tests/smoke/BrowseTest.java +++ b/src/test/java/posters/tests/smoke/BrowseTest.java @@ -2,56 +2,71 @@ import org.junit.Test; +import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.util.DataUtils; +import com.xceptance.neodymium.util.Neodymium; + import io.qameta.allure.Owner; import io.qameta.allure.Severity; import io.qameta.allure.SeverityLevel; import io.qameta.allure.junit4.Tag; import posters.flows.OpenHomePageFlow; import posters.tests.AbstractTest; +import posters.tests.testdata.processes.BrowseTestData; -/** - * @author pfotenhauer - */ @Owner("Tim Brown") @Severity(SeverityLevel.NORMAL) @Tag("smoke") public class BrowseTest extends AbstractTest { @Test + @DataSet(1) public void testBrowsing() { - // Go to homepage + // use test data + final BrowseTestData browseTestData = DataUtils.get(BrowseTestData.class); + + // go to homepage var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - - // Go to category - final String categoryName = homePage.topNav.getSubCategoryNameByPosition(1, 1); - var categoryPage = homePage.topNav.clickSubCategoryByPosition(1, 1); - categoryPage.validate(categoryName); + homePage.validateStructure(); - // Go to product page - final String productName = categoryPage.getProductNameByPosition(1, 1); - var productDetailPage = categoryPage.clickProductByPosition(1, 1); + // go to category page and validate + var categoryPage = homePage.header.topNav.clickCategory(Neodymium.localizedText(browseTestData.getTopCategory1())); + categoryPage.validate(Neodymium.localizedText(browseTestData.getTopCategory1()), browseTestData.getExpectedResultCount1()); + + // go to product page and validate + final String productName = categoryPage.getProductNameByPosition(browseTestData.getResultPosition1()); + var productDetailPage = categoryPage.clickProductByPosition(browseTestData.getResultPosition1()); productDetailPage.validate(productName); - // Go to category - final String categoryName2 = productDetailPage.topNav.getSubCategoryNameByPosition(2, 2); - categoryPage = productDetailPage.topNav.clickSubCategoryByPosition(2, 2); - categoryPage.validate(categoryName2); - - // Go to product page - final String productName2 = categoryPage.getProductNameByPosition(2, 2); - productDetailPage = categoryPage.clickProductByPosition(2, 2); + // go to category page and validate + categoryPage = productDetailPage.header.topNav.clickCategory(Neodymium.localizedText(browseTestData.getTopCategory2())); + categoryPage.validate(Neodymium.localizedText(browseTestData.getTopCategory2()), browseTestData.getExpectedResultCount2()); + + // go to product page and validate + final String productName2 = categoryPage.getProductNameByPosition(browseTestData.getResultPosition2()); + productDetailPage = categoryPage.clickProductByPosition(browseTestData.getResultPosition2()); productDetailPage.validate(productName2); - - // Go to category - final String categoryName3 = productDetailPage.topNav.getSubCategoryNameByPosition(2, 3); - categoryPage = productDetailPage.topNav.clickSubCategoryByPosition(2, 3); - categoryPage.validate(categoryName3); - - // Go to product page - final String productName3 = categoryPage.getProductNameByPosition(2, 3); - productDetailPage = categoryPage.clickProductByPosition(2, 3); + + // go to category page and validate + categoryPage = productDetailPage.header.topNav.clickCategory(Neodymium.localizedText(browseTestData.getTopCategory3())); + categoryPage.validate(Neodymium.localizedText(browseTestData.getTopCategory3()), browseTestData.getExpectedResultCount3()); + + // go to product page and validate + final String productName3 = categoryPage.getProductNameByPosition(browseTestData.getResultPosition3()); + productDetailPage = categoryPage.clickProductByPosition(browseTestData.getResultPosition3()); productDetailPage.validate(productName3); + + // go to category page and validate + categoryPage = productDetailPage.header.topNav.clickCategory(Neodymium.localizedText(browseTestData.getTopCategory4())); + categoryPage.validate(Neodymium.localizedText(browseTestData.getTopCategory4()), browseTestData.getExpectedResultCount4()); + + // go to product page and validate + final String productName4 = categoryPage.getProductNameByPosition(browseTestData.getResultPosition4()); + productDetailPage = categoryPage.clickProductByPosition(browseTestData.getResultPosition4()); + productDetailPage.validate(productName4); + + // go to homepage + homePage = productDetailPage.openHomePage(); } -} +} \ No newline at end of file diff --git a/src/test/java/posters/tests/smoke/GuestOrderTest.java b/src/test/java/posters/tests/smoke/GuestOrderTest.java index 003e6cfe..5cce7868 100644 --- a/src/test/java/posters/tests/smoke/GuestOrderTest.java +++ b/src/test/java/posters/tests/smoke/GuestOrderTest.java @@ -2,6 +2,7 @@ import org.junit.Test; +import com.xceptance.neodymium.module.statement.testdata.DataSet; import com.xceptance.neodymium.util.DataUtils; import com.xceptance.neodymium.util.Neodymium; @@ -9,101 +10,83 @@ import io.qameta.allure.Severity; import io.qameta.allure.SeverityLevel; import io.qameta.allure.junit4.Tag; -import posters.dataobjects.Address; -import posters.dataobjects.CreditCard; import posters.flows.OpenHomePageFlow; +import posters.pageobjects.pages.checkout.GuestPaymentPage; +import posters.pageobjects.pages.checkout.PlaceOrderPage; import posters.tests.AbstractTest; +import posters.tests.testdata.processes.GuestOrderTestData; -/** - * @author pfotenhauer - */ @Owner("Joe Fix") @Severity(SeverityLevel.BLOCKER) @Tag("smoke") @Tag("registered") public class GuestOrderTest extends AbstractTest -{ +{ @Test + @DataSet(1) + @DataSet(2) public void testOrderingAsGuest() - { - // total product count will be updated throughout the test - int totalCount = 0; + { + // use test data final String shippingCosts = Neodymium.dataValue("shippingCosts"); - - - - // Go to homepage + final GuestOrderTestData guestOrderTestData = DataUtils.get(GuestOrderTestData.class); + + // go to homepage var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - - // Assure not logged in status - homePage.userMenu.validateNotLoggedIn(); - - // Assure an empty cart - homePage.miniCart.validateTotalCount(totalCount); - homePage.miniCart.validateSubtotal("$0.00"); - final String oldSubtotal = homePage.miniCart.getSubtotal(); - - // Go to category - final String categoryName = homePage.topNav.getSubCategoryNameByPosition(3, 2); - var categoryPage = homePage.topNav.clickSubCategoryByPosition(3, 2); - categoryPage.validate(categoryName); - // Goto product page - final String productName = categoryPage.getProductNameByPosition(1, 1); - var productDetailPage = categoryPage.clickProductByPosition(1, 1); - productDetailPage.validate(productName); - productDetailPage.addToCart("64 x 48 in", "gloss"); - - // Go to cart and validate + // go to category page + var categoryPage = homePage.header.topNav.clickCategory(Neodymium.localizedText(guestOrderTestData.getTopCategory())); + + // go to product detail page, add and store displayed product + var productDetailPage = categoryPage.clickProductByPosition(guestOrderTestData.getResultPosition()); + productDetailPage.addToCart(guestOrderTestData.getsSizeProduct(), guestOrderTestData.getStyleProduct()); final var product = productDetailPage.getProduct(); - var cartPage = productDetailPage.miniCart.openCartPage(); - cartPage.validateStructure(); - cartPage.validateShippingCosts(shippingCosts); - cartPage.miniCart.validateMiniCart(1, product); - cartPage.miniCart.validateTotalCount(++totalCount); - cartPage.validateCartItem(1, product); - cartPage.validateSubAndLineItemTotalAfterAdd(1, oldSubtotal, 0.00); - - // setup checkout data - final var shippingAddress = DataUtils.get(Address.class); - final boolean sameBillingAddress = false; - final var billingAddress = DataUtils.get(Address.class); - final var creditCard = DataUtils.get(CreditCard.class); - - // Go to shipping address and validate - var newShippingAddressPage = cartPage.openNewShippingPage(); - newShippingAddressPage.validateStructure(); - - // Send shipping address and validate billing form - var newBillingAddressPage = newShippingAddressPage.sendShippingAddressForm(shippingAddress, sameBillingAddress); - newBillingAddressPage.validateStructure(); - - // Send billing address and validate payment form - var newPaymentPage = newBillingAddressPage.sendBillingAddressForm(billingAddress); - newPaymentPage.validateStructure(); - - // Send payment data and validate place order page - var placeOrderPage = newPaymentPage.sendPaymentForm(creditCard); - placeOrderPage.validateStructure(); - placeOrderPage.validateProduct(1, product.getName(), product.getAmount(), product.getStyle(), product.getSize()); - placeOrderPage.validateAddressesAndPayment(shippingAddress, billingAddress, creditCard); - - // Place order - //homePage = placeOrderPage.placeOrder(); - // Place Order - var orderConfirmationPage = placeOrderPage.placeOrder(); + // go to cart page + var cartPage = productDetailPage.header.miniCart.openCartPage(); + + // go to shipping address page and validate + var shippingAddressPage = cartPage.openGuestShippingAddressPage(); + shippingAddressPage.validateStructure(); + + // declare variables used in if + GuestPaymentPage paymentPage; + PlaceOrderPage placeOrderPage; - // Validate order confirmation on the Order Confirmation page - orderConfirmationPage.validate(); - orderConfirmationPage.validateSuccessfulOrder(); + if (!guestOrderTestData.getShipAddrEqualBillAddr()) + { + // go to billing address page and validate + var billingAddressPage = shippingAddressPage.goToGuestBillingAddressPage(guestOrderTestData.getShippingAddress()); + billingAddressPage.validateStructure(); - //navigate to the Home Page - homePage = orderConfirmationPage.goHome(); + // go to payment page and validate + paymentPage = billingAddressPage.goToGuestPaymentPage(guestOrderTestData.getBillingAddress()); + paymentPage.validateStructure(); + + // go to place order page and validate order overview + placeOrderPage = paymentPage.goToPlaceOrderPage(guestOrderTestData.getCreditCard()); + placeOrderPage.validateOrderOverview(guestOrderTestData.getShippingAddress(), guestOrderTestData.getBillingAddress(), guestOrderTestData.getCreditCard()); + } + else + { + // go to payment page and validate + paymentPage = shippingAddressPage.goToGuestPaymentPage(guestOrderTestData.getShippingAddress()); + paymentPage.validateStructure(); + + // go to place order page and validate order overview + placeOrderPage = paymentPage.goToPlaceOrderPage(guestOrderTestData.getCreditCard()); + placeOrderPage.validateOrderOverview(guestOrderTestData.getShippingAddress(), guestOrderTestData.getShippingAddress(), guestOrderTestData.getCreditCard()); + } + + placeOrderPage.validateStructure(); + placeOrderPage.validateProduct(1, product); + placeOrderPage.validatePriceSummary(placeOrderPage.getSubtotal(), shippingCosts); + + // go to order confirmation page and validate + var orderConfirmationPage = placeOrderPage.placeOrder(); + orderConfirmationPage.validateStructure(); - - //Validate home page - homePage.validate(); + // go to homepage + homePage = orderConfirmationPage.openHomePage(); } } diff --git a/src/test/java/posters/tests/smoke/HomePageTest.java b/src/test/java/posters/tests/smoke/HomePageTest.java index 9e4d1cc9..cc242c5c 100644 --- a/src/test/java/posters/tests/smoke/HomePageTest.java +++ b/src/test/java/posters/tests/smoke/HomePageTest.java @@ -17,9 +17,6 @@ import posters.flows.OpenHomePageFlow; import posters.tests.AbstractTest; -/** - * @author pfotenhauer - */ @Severity(SeverityLevel.TRIVIAL) @Owner("Joe Fix") @Tag("smoke") @@ -35,7 +32,7 @@ public void testVisitingHomepage() { AllureAddons.addToReport("Find me in the report", "Some additional content. Could be the toString method of an complex object."); var homePage = OpenHomePageFlow.flow(); - homePage.validate(); homePage.title.validateTitle(Neodymium.localizedText("HomePage.title")); + homePage.validateStructure(); } } diff --git a/src/test/java/posters/tests/smoke/RegisterFromUserMenuTest.java b/src/test/java/posters/tests/smoke/RegisterFromUserMenuTest.java deleted file mode 100644 index 41b6a3c8..00000000 --- a/src/test/java/posters/tests/smoke/RegisterFromUserMenuTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package posters.tests.smoke; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.xceptance.neodymium.util.DataUtils; - -import io.qameta.allure.Owner; -import io.qameta.allure.Severity; -import io.qameta.allure.SeverityLevel; -import io.qameta.allure.junit4.Tag; -import posters.dataobjects.User; -import posters.flows.DeleteUserFlow; -import posters.flows.OpenHomePageFlow; -import posters.tests.AbstractTest; - -/** - * @author pfotenhauer - */ - -@Owner("Lisa Smith") -@Severity(SeverityLevel.NORMAL) -@Tag("smoke") -@Tag("registered") -public class RegisterFromUserMenuTest extends AbstractTest -{ - private User user; - - @Before - public void setup() - { - user = DataUtils.get(User.class); - } - - @Test - public void testRegisteringFromUserMenu() - { - // Go to homepage - var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - - // Assure not logged in status - homePage.userMenu.validateNotLoggedIn(); - - // Go to register form - var registerPage = homePage.userMenu.openRegister(); - registerPage.validateStructure(); - - var loginPage = registerPage.sendRegisterForm(user); - loginPage.validateSuccessfulRegistration(); - loginPage.validateStructure(); - - homePage = loginPage.sendLoginform(user); - homePage.validateSuccessfulLogin(user); - } - - @After - public void after() - { - DeleteUserFlow.flow(user); - } -} diff --git a/src/test/java/posters/tests/smoke/RegisterTest.java b/src/test/java/posters/tests/smoke/RegisterTest.java index c91c23d3..d39987bd 100644 --- a/src/test/java/posters/tests/smoke/RegisterTest.java +++ b/src/test/java/posters/tests/smoke/RegisterTest.java @@ -4,31 +4,24 @@ import org.junit.Before; import org.junit.Test; -import com.xceptance.neodymium.module.statement.browser.multibrowser.Browser; import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.module.statement.testdata.SuppressDataSets; import com.xceptance.neodymium.util.DataUtils; import io.qameta.allure.Owner; import io.qameta.allure.Severity; import io.qameta.allure.SeverityLevel; import io.qameta.allure.junit4.Tag; -import posters.dataobjects.User; import posters.flows.DeleteUserFlow; import posters.flows.OpenHomePageFlow; import posters.tests.AbstractTest; +import posters.tests.testdata.dataobjects.User; -/** - * The initial data base of Posters provides a default user to avoid a registration process. The used e-mail address is - * "john@doe.com". Using this user within the RegisterTest would lead to an expected error. - * - * @author pfotenhauer - */ @Owner("Lisa Smith") @Severity(SeverityLevel.CRITICAL) @Tag("smoke") @Tag("registered") -//@Browser("Chrome_1024x768") -@Browser("Firefox_1024x768") +@SuppressDataSets public class RegisterTest extends AbstractTest { private User user; @@ -38,34 +31,26 @@ public void setup() { user = DataUtils.get(User.class); } - + @Test @DataSet(2) - @DataSet(4) - @DataSet(id = "Jim's test") public void testRegistering() - { - // Go to homepage + { + // go to homepage var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - - // Assure that nobody is logged in - homePage.userMenu.validateNotLoggedIn(); - - // Go to login form - var loginPage = homePage.userMenu.openLogin(); - loginPage.validateStructure(); - // Go to register form - var registerPage = loginPage.openRegister(); + // go to register page and validate + var registerPage = homePage.header.userMenu.openRegisterPage(); registerPage.validateStructure(); - - loginPage = registerPage.sendRegisterForm(user); - loginPage.validateSuccessfulRegistration(); + + // go to login page and validate + var loginPage = registerPage.sendRegisterForm(user); loginPage.validateStructure(); - - homePage = loginPage.sendLoginform(user); - homePage.validateSuccessfulLogin(user); + loginPage.validateSuccessfulRegistration(); + + // send login form + homePage = loginPage.sendLoginForm(user); + homePage.validateSuccessfulLogin(user.getFirstName()); } @After diff --git a/src/test/java/posters/tests/smoke/RegisteredOrderTest.java b/src/test/java/posters/tests/smoke/RegisteredOrderTest.java index 9dbba0a9..0343154e 100644 --- a/src/test/java/posters/tests/smoke/RegisteredOrderTest.java +++ b/src/test/java/posters/tests/smoke/RegisteredOrderTest.java @@ -3,6 +3,7 @@ import org.junit.After; import org.junit.Test; +import com.xceptance.neodymium.module.statement.testdata.DataSet; import com.xceptance.neodymium.util.DataUtils; import com.xceptance.neodymium.util.Neodymium; @@ -10,101 +11,94 @@ import io.qameta.allure.Severity; import io.qameta.allure.SeverityLevel; import io.qameta.allure.junit4.Tag; -import posters.dataobjects.Address; -import posters.dataobjects.CreditCard; import posters.flows.CartCleanUpFlow; import posters.flows.OpenHomePageFlow; import posters.tests.AbstractTest; +import posters.tests.testdata.processes.RegisteredOrderTestData; -/** - * @author pfotenhauer - */ @Owner("Lisa Smith") @Severity(SeverityLevel.BLOCKER) @Tag("smoke") @Tag("registered") public class RegisteredOrderTest extends AbstractTest -{ +{ + @DataSet(1) + @DataSet(2) @Test public void testOrderingAsRegisteredUser() { - // total product count will be updated throughout the test - int totalCount = 0; + // use test data final String shippingCosts = Neodymium.dataValue("shippingCosts"); + final RegisteredOrderTestData registeredOrderTestData = DataUtils.get(RegisteredOrderTestData.class); - // Go to homepage + // go to homepage var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - - // Assure not logged in status - homePage.userMenu.validateNotLoggedIn(); - - // Assure an empty cart - homePage.miniCart.validateTotalCount(totalCount); - homePage.miniCart.validateSubtotal("$0.00"); - final String oldSubtotal = homePage.miniCart.getSubtotal(); - - // Go to login form - var loginPage = homePage.userMenu.openLogin(); - loginPage.validateStructure(); - final String email = Neodymium.dataValue("email"); - final String password = Neodymium.dataValue("password"); - homePage = loginPage.sendLoginform(email, password); - final String firstName = Neodymium.dataValue("firstName"); - homePage.validateSuccessfulLogin(firstName); - - // Go to category - final String categoryName = homePage.topNav.getSubCategoryNameByPosition(2, 3); - var categoryPage = homePage.topNav.clickSubCategoryByPosition(2, 3); - categoryPage.validate(categoryName); - - // Go to product page - final String productName = categoryPage.getProductNameByPosition(2, 1); - var productDetailPage = categoryPage.clickProductByPosition(2, 1); - productDetailPage.validate(productName); - productDetailPage.addToCart("32 x 24 in", "matte"); - - // Go to cart and validate - var product = productDetailPage.getProduct(); - var cartPage = productDetailPage.miniCart.openCartPage(); - cartPage.validateStructure(); - cartPage.validateShippingCosts(shippingCosts); - cartPage.miniCart.validateMiniCart(1, product); - cartPage.miniCart.validateTotalCount(++totalCount); - cartPage.validateCartItem(1, product); - cartPage.validateSubAndLineItemTotalAfterAdd(1, oldSubtotal, 0.00); - - // Go to shipping address and validate - var shippingAddressPage = cartPage.openShippingPage(); + + // go to login page + var loginPage = homePage.header.userMenu.openLoginPage(); + + // send login form + homePage = loginPage.sendLoginForm(registeredOrderTestData.getUser()); + homePage.validateSuccessfulLogin(registeredOrderTestData.getUser().getFirstName()); + + // go to category page + var categoryPage = homePage.header.topNav.clickCategory(Neodymium.localizedText(registeredOrderTestData.getTopCategory())); + + // go to product detail page, add and store displayed product + var productDetailPage = categoryPage.clickProductByPosition(registeredOrderTestData.getResultPosition()); + productDetailPage.addToCart(registeredOrderTestData.getsSizeProduct(), registeredOrderTestData.getStyleProduct()); + final var product = productDetailPage.getProduct(); + + // go to cart page + var cartPage = productDetailPage.header.miniCart.openCartPage(); + + // go to shipping address page + var shippingAddressPage = cartPage.openReturningCustomerShippingAddressPage(); shippingAddressPage.validateStructure(); + shippingAddressPage.validateAddressContainer(registeredOrderTestData.getShipAddrPos(), registeredOrderTestData.getShippingAddress()); - // Send shipping address and validate billing form - var billingAddressPage = shippingAddressPage.selectShippingAddress(1); + // go to billing address page + var billingAddressPage = shippingAddressPage.selectShippingAddress(registeredOrderTestData.getShipAddrPos()); billingAddressPage.validateStructure(); - // Send billing address and validate payment form - var paymentPage = billingAddressPage.selectBillingAddress(1); + if (!registeredOrderTestData.getShipAddrEqualBillAddr()) + { + billingAddressPage.validateAddressContainer(registeredOrderTestData.getBillAddrPos(), registeredOrderTestData.getBillingAddress()); + } + else + { + billingAddressPage.validateAddressContainer(registeredOrderTestData.getBillAddrPos(), registeredOrderTestData.getShippingAddress()); + } + + // go to payment page + var paymentPage = billingAddressPage.selectBillingAddress(registeredOrderTestData.getBillAddrPos()); paymentPage.validateStructure(); + paymentPage.validateCreditCardContainer(registeredOrderTestData.getCreditCardPos(), registeredOrderTestData.getCreditCard()); - // setup checkout data for validation - final var shippingAddress = DataUtils.get(Address.class); - final var billingAddress = DataUtils.get(Address.class); - final var creditCard = DataUtils.get(CreditCard.class); - - // Send payment data and validate place order page - var placeOrderPage = paymentPage.selectCreditCard(1); - placeOrderPage.validateStructure(); - placeOrderPage.validateProduct(1, product.getName(), product.getAmount(), product.getStyle(), product.getSize()); - placeOrderPage.validateAddressesAndPayment(shippingAddress, billingAddress, creditCard); + // go to place order page + var placeOrderPage = paymentPage.selectCreditCard(registeredOrderTestData.getCreditCardPos()); - // Place order - var OrderConfirmationPage = placeOrderPage.placeOrder(); + if (!registeredOrderTestData.getShipAddrEqualBillAddr()) + { + placeOrderPage.validateOrderOverview(registeredOrderTestData.getShippingAddress(), registeredOrderTestData.getBillingAddress(), registeredOrderTestData.getCreditCard()); + } + else + { + placeOrderPage.validateOrderOverview(registeredOrderTestData.getShippingAddress(), registeredOrderTestData.getShippingAddress(), registeredOrderTestData.getCreditCard()); + } - // Validate order confirmation on Order Confirmation Page - OrderConfirmationPage.validate(); - OrderConfirmationPage.validateSuccessfulOrder(); + placeOrderPage.validateStructure(); + placeOrderPage.validateProduct(1, product); + placeOrderPage.validatePriceSummary(placeOrderPage.getSubtotal(), shippingCosts); + + // go to order confirmation page + var orderConfirmationPage = placeOrderPage.placeOrder(); + orderConfirmationPage.validateStructure(); + + // go to homepage + homePage = orderConfirmationPage.openHomePage(); } - + @After public void after() { diff --git a/src/test/java/posters/tests/smoke/SearchTest.java b/src/test/java/posters/tests/smoke/SearchTest.java index 6cd6c9ea..466769e5 100644 --- a/src/test/java/posters/tests/smoke/SearchTest.java +++ b/src/test/java/posters/tests/smoke/SearchTest.java @@ -13,58 +13,54 @@ import io.qameta.allure.junit4.Tag; import posters.flows.OpenHomePageFlow; import posters.tests.AbstractTest; +import posters.tests.testdata.pageobjects.components.SearchTestData; -/** - * @author pfotenhauer - */ @Owner("Tim Brown") @Severity(SeverityLevel.MINOR) @Tag("smoke") @SuppressDataSets public class SearchTest extends AbstractTest -{ - private String searchTerm; - - private int position; - - private int searchTermExpectedCount; +{ + private SearchTestData searchTestData; @Before public void setup() { - searchTerm = DataUtils.asString("searchTerm"); - position = DataUtils.asInt("position", 0); - searchTermExpectedCount = DataUtils.asInt("searchTermExpectedCount", 0); + searchTestData = DataUtils.get(SearchTestData.class); } - + @Test @DataSet(1) public void testSearching() - { - // Go to homepage + { + // go to homepage var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - // Search - var categoryPage = homePage.search.categoryPageResult(searchTerm); - categoryPage.validateStructure(); - categoryPage.validateSearchHits(searchTerm, searchTermExpectedCount); + // go to category page + var categoryPage = homePage.header.search.categoryPageResult(searchTestData.getSearchTerm()); + categoryPage.validate(searchTestData.getSearchTerm(), searchTestData.getExpectedResultCount()); - final String productName = categoryPage.getProductNameByPosition(position); - var productDetailPage = categoryPage.clickProductByPosition(position); + //go to product detail page + final String productName = categoryPage.getProductNameByPosition(searchTestData.getResultPosition()); + var productDetailPage = categoryPage.clickProductByPosition(searchTestData.getResultPosition()); productDetailPage.validate(productName); + + // go to homepage + homePage = productDetailPage.openHomePage(); } @Test @DataSet(2) public void testSearchingWithoutResult() - { - // Go to homepage + { + // go to homepage var homePage = OpenHomePageFlow.flow(); - homePage.validate(); - // Search - var noHitsPage = homePage.search.noResult(searchTerm); - noHitsPage.validate(); + // go to no hits page + var noHitsPage = homePage.header.search.noHitsPageResult(searchTestData.getSearchTerm()); + noHitsPage.validateStructure(); + + // go to homepage + homePage = noHitsPage.openHomePage(); } } diff --git a/src/test/java/posters/tests/testdata/dataobjects/Address.java b/src/test/java/posters/tests/testdata/dataobjects/Address.java new file mode 100644 index 00000000..6407b7dd --- /dev/null +++ b/src/test/java/posters/tests/testdata/dataobjects/Address.java @@ -0,0 +1,81 @@ +package posters.tests.testdata.dataobjects; + +public class Address +{ + String firstName; + + String lastName; + + String company; + + String street; + + String city; + + String state; + + String zip; + + String country; + + public Address(String firstName, String lastName, String company, String street, String city, String state, String zip, String country) + { + this.firstName = firstName; + this.lastName = lastName; + this.company = company; + this.street = street; + this.city = city; + this.state = state; + this.zip = zip; + this.country = country; + } + + /// ----- get address data ----- /// + + public String getFirstName() + { + return firstName; + } + + public String getLastName() + { + return lastName; + } + + public String getCompany() + { + return company; + } + + public String getStreet() + { + return street; + } + + public String getCity() + { + return city; + } + + public String getState() + { + return state; + } + + public String getZip() + { + return zip; + } + + public String getCountry() + { + return country; + } + + @Override + public String toString() + { + return "Address [firstName=" + firstName + ", lastName=" + lastName + ", company=" + company + ", street=" + street + ", city=" + city + ", state=" + + state + ", zip=" + zip + ", country=" + country + "]"; + } +} \ No newline at end of file diff --git a/src/test/java/posters/dataobjects/CreditCard.java b/src/test/java/posters/tests/testdata/dataobjects/CreditCard.java similarity index 50% rename from src/test/java/posters/dataobjects/CreditCard.java rename to src/test/java/posters/tests/testdata/dataobjects/CreditCard.java index b710ea87..3d90106f 100644 --- a/src/test/java/posters/dataobjects/CreditCard.java +++ b/src/test/java/posters/tests/testdata/dataobjects/CreditCard.java @@ -1,8 +1,4 @@ -package posters.dataobjects; - -/** - * @author pfotenhauer - */ +package posters.tests.testdata.dataobjects; public class CreditCard { String fullName; @@ -15,18 +11,6 @@ public class CreditCard String expDateYear; - /** - * @param fullName - * the fullName to set - * @param cardNumber - * the cardNumber to set - * @param crypticCardNumber - * the crypticCardNumber to set - * @param expDateMonth - * the expDateMonth to set - * @param expDateYear - * the expDateYear to set - */ public CreditCard(String fullName, String cardNumber, String crypticCardNumber, String expDateMonth, String expDateYear) { this.fullName = fullName; @@ -36,41 +20,28 @@ public CreditCard(String fullName, String cardNumber, String crypticCardNumber, this.expDateYear = expDateYear; } - /** - * @return the fullName - */ + /// ----- get credit card data ----- /// + public String getFullName() { return fullName; } - /** - * @return the cardNumber - */ public String getCardNumber() { return cardNumber; } - /** - * @return the crypticCardNumber - */ public String getCrypticCardNumber() { return crypticCardNumber; } - /** - * @return the expDateMonth - */ public String getExpDateMonth() { return expDateMonth; } - /** - * @return the expDateYear - */ public String getExpDateYear() { return expDateYear; @@ -79,7 +50,7 @@ public String getExpDateYear() @Override public String toString() { - return String.format("CreditCard [fullName()=%s, cardNumber()=%s, crypticCardNumber()=%s, expMonth()=%s, expYear()=%s]", - getFullName(), getCardNumber(), getCrypticCardNumber(), getExpDateMonth(), getExpDateYear()); + return "CreditCard [fullName=" + fullName + ", cardNumber=" + cardNumber + ", crypticCardNumber=" + crypticCardNumber + ", expDateMonth=" + expDateMonth + + ", expDateYear=" + expDateYear + "]"; } } diff --git a/src/test/java/posters/tests/testdata/dataobjects/Product.java b/src/test/java/posters/tests/testdata/dataobjects/Product.java new file mode 100644 index 00000000..b4b1815f --- /dev/null +++ b/src/test/java/posters/tests/testdata/dataobjects/Product.java @@ -0,0 +1,70 @@ +package posters.tests.testdata.dataobjects; + +import posters.pageobjects.utility.PriceHelper; + +public class Product +{ + String name; + + String unitPrice; + + String style; + + String size; + + int amount; + + public Product(String name, String unitPrice, String style, String size, int amount) + { + this.name = name; + this.unitPrice = unitPrice; + this.style = style; + this.size = size; + this.amount = amount; + } + + // ----- get product data ----- // + + public String getName() + { + return name; + } + + public String getUnitPrice() + { + return unitPrice; + } + + public String getStyle() + { + return style; + } + + public String getSize() + { + return size; + } + + public int getAmount() + { + return amount; + } + + // ----- get total product price ----- // + + private double getUnitPriceDouble() + { + return Double.parseDouble(PriceHelper.removeCurrency(unitPrice)); + } + + public double getTotalPrice() + { + return amount * getUnitPriceDouble(); + } + + @Override + public String toString() + { + return "Product [name=" + name + ", unitPrice=" + unitPrice + ", style=" + style + ", size=" + size + ", amount=" + amount + "]"; + } +} diff --git a/src/test/java/posters/tests/testdata/dataobjects/User.java b/src/test/java/posters/tests/testdata/dataobjects/User.java new file mode 100644 index 00000000..bd99c658 --- /dev/null +++ b/src/test/java/posters/tests/testdata/dataobjects/User.java @@ -0,0 +1,48 @@ +package posters.tests.testdata.dataobjects; + +public class User +{ + String firstName; + + String lastName; + + String email; + + String password; + + public User(String firstName, String lastName, String email, String password) + { + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.password = password; + } + + /// ----- get user data ----- /// + + public String getFirstName() + { + return firstName; + } + + public String getLastName() + { + return lastName; + } + + public String getEmail() + { + return email; + } + + public String getPassword() + { + return password; + } + + @Override + public String toString() + { + return "User [firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", password=" + password + "]"; + } +} diff --git a/src/test/java/posters/tests/testdata/pageobjects/components/HeaderTestData.java b/src/test/java/posters/tests/testdata/pageobjects/components/HeaderTestData.java new file mode 100644 index 00000000..ab591760 --- /dev/null +++ b/src/test/java/posters/tests/testdata/pageobjects/components/HeaderTestData.java @@ -0,0 +1,18 @@ +package posters.tests.testdata.pageobjects.components; + +public class HeaderTestData +{ + private String topCategory; + + private int resultPosition; + + public String getTopCategory() + { + return topCategory; + } + + public int getResultPosition() + { + return resultPosition; + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/testdata/pageobjects/components/PaginationTestData.java b/src/test/java/posters/tests/testdata/pageobjects/components/PaginationTestData.java new file mode 100644 index 00000000..e9afaeb3 --- /dev/null +++ b/src/test/java/posters/tests/testdata/pageobjects/components/PaginationTestData.java @@ -0,0 +1,18 @@ +package posters.tests.testdata.pageobjects.components; + +public class PaginationTestData +{ + private String topCategory; + + private int expectedResultCount; + + public String getTopCategory() + { + return topCategory; + } + + public int getExpectedResultCount() + { + return expectedResultCount; + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/testdata/pageobjects/components/SearchTestData.java b/src/test/java/posters/tests/testdata/pageobjects/components/SearchTestData.java new file mode 100644 index 00000000..f5fb42f5 --- /dev/null +++ b/src/test/java/posters/tests/testdata/pageobjects/components/SearchTestData.java @@ -0,0 +1,26 @@ +package posters.tests.testdata.pageobjects.components; + +public class SearchTestData +{ + private String searchTerm; + + private int expectedResultCount; + + private int resultPosition; + + public String getSearchTerm() + { + return searchTerm; + } + + public int getExpectedResultCount() + { + return expectedResultCount; + } + + public int getResultPosition() + { + return resultPosition; + } + +} \ No newline at end of file diff --git a/src/test/java/posters/tests/testdata/processes/AddToCartTestData.java b/src/test/java/posters/tests/testdata/processes/AddToCartTestData.java new file mode 100644 index 00000000..8f86d23d --- /dev/null +++ b/src/test/java/posters/tests/testdata/processes/AddToCartTestData.java @@ -0,0 +1,96 @@ +package posters.tests.testdata.processes; + +public class AddToCartTestData +{ + private String topCategory; + + private int categoryResultPosition; + + private String subCategory; + + private int subCategoryResultPosition; + + private String sizeFirstProduct; + + private String styleFirstProduct; + + private String searchTerm; + + private int searchResultPosition; + + private String sizeSecondProduct; + + private String styleSecondProduct; + + private int productUpdatePosition; + + private int amountChange; + + /// ----- top category ----- /// + + public String getTopCategory() + { + return topCategory; + } + + public int getCategoryResultPosition() + { + return categoryResultPosition; + } + + /// ----- sub category ----- /// + + public String getSubCategory() + { + return subCategory; + } + + public int getSubCategoryResultPosition() + { + return subCategoryResultPosition; + } + + public String getSizeFirstProduct() + { + return sizeFirstProduct; + } + + public String getStyleFirstProduct() + { + return styleFirstProduct; + } + + /// ----- search term ----- /// + + public String getSearchTerm() + { + return searchTerm; + } + + public int getSearchResultPosition() + { + return searchResultPosition; + } + + public String getSizeSecondProduct() + { + return sizeSecondProduct; + } + + public String getStyleSecondProduct() + { + return styleSecondProduct; + } + + /// ----- update data ----- /// + + public int getProductUpdatePosition() + { + return productUpdatePosition; + } + + public int getAmountChange() + { + return amountChange; + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/testdata/processes/BrowseTestData.java b/src/test/java/posters/tests/testdata/processes/BrowseTestData.java new file mode 100644 index 00000000..3f85ad5b --- /dev/null +++ b/src/test/java/posters/tests/testdata/processes/BrowseTestData.java @@ -0,0 +1,88 @@ +package posters.tests.testdata.processes; + +public class BrowseTestData +{ + private String topCategory1; + + private int expectedResultCount1; + + private int resultPosition1; + + private String topCategory2; + + private int expectedResultCount2; + + private int resultPosition2; + + private String topCategory3; + + private int expectedResultCount3; + + private int resultPosition3; + + private String topCategory4; + + private int expectedResultCount4; + + private int resultPosition4; + + public String getTopCategory1() + { + return topCategory1; + } + + public int getExpectedResultCount1() + { + return expectedResultCount1; + } + + public int getResultPosition1() + { + return resultPosition1; + } + + public String getTopCategory2() + { + return topCategory2; + } + + public int getExpectedResultCount2() + { + return expectedResultCount2; + } + + public int getResultPosition2() + { + return resultPosition2; + } + + public String getTopCategory3() + { + return topCategory3; + } + + public int getExpectedResultCount3() + { + return expectedResultCount3; + } + + public int getResultPosition3() + { + return resultPosition3; + } + + public String getTopCategory4() + { + return topCategory4; + } + + public int getExpectedResultCount4() + { + return expectedResultCount4; + } + + public int getResultPosition4() + { + return resultPosition4; + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/testdata/processes/GuestOrderTestData.java b/src/test/java/posters/tests/testdata/processes/GuestOrderTestData.java new file mode 100644 index 00000000..1ef0fffa --- /dev/null +++ b/src/test/java/posters/tests/testdata/processes/GuestOrderTestData.java @@ -0,0 +1,63 @@ +package posters.tests.testdata.processes; + +import posters.tests.testdata.dataobjects.Address; +import posters.tests.testdata.dataobjects.CreditCard; + +public class GuestOrderTestData +{ + private String topCategory; + + private int resultPosition; + + private String sizeProduct; + + private String styleProduct; + + private Address shippingAddress; + + private Boolean shipAddrEqualBillAddr; + + private Address billingAddress; + + private CreditCard creditCard; + + public String getTopCategory() + { + return topCategory; + } + + public int getResultPosition() + { + return resultPosition; + } + + public String getsSizeProduct() + { + return sizeProduct; + } + + public String getStyleProduct() + { + return styleProduct; + } + + public Address getShippingAddress() + { + return shippingAddress; + } + + public Boolean getShipAddrEqualBillAddr() + { + return shipAddrEqualBillAddr; + } + + public Address getBillingAddress() + { + return billingAddress; + } + + public CreditCard getCreditCard() + { + return creditCard; + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/testdata/processes/RegisteredOrderTestData.java b/src/test/java/posters/tests/testdata/processes/RegisteredOrderTestData.java new file mode 100644 index 00000000..d1a07717 --- /dev/null +++ b/src/test/java/posters/tests/testdata/processes/RegisteredOrderTestData.java @@ -0,0 +1,92 @@ +package posters.tests.testdata.processes; + +import posters.tests.testdata.dataobjects.Address; +import posters.tests.testdata.dataobjects.CreditCard; +import posters.tests.testdata.dataobjects.User; + +public class RegisteredOrderTestData +{ + private User user; + + private String topCategory; + + private int resultPosition; + + private String sizeProduct; + + private String styleProduct; + + private int shipAddrPos; + + private int billAddrPos; + + private int creditCardPos; + + private Boolean shipAddrEqualBillAddr; + + private Address shippingAddress; + + private Address billingAddress; + + private CreditCard creditCard; + + public User getUser() + { + return user; + } + + public String getTopCategory() + { + return topCategory; + } + + public int getResultPosition() + { + return resultPosition; + } + + public String getsSizeProduct() + { + return sizeProduct; + } + + public String getStyleProduct() + { + return styleProduct; + } + + public int getShipAddrPos() + { + return shipAddrPos; + } + + public int getBillAddrPos() + { + return billAddrPos; + } + + public int getCreditCardPos() + { + return creditCardPos; + } + + public Boolean getShipAddrEqualBillAddr() + { + return shipAddrEqualBillAddr; + } + + public Address getShippingAddress() + { + return shippingAddress; + } + + public Address getBillingAddress() + { + return billingAddress; + } + + public CreditCard getCreditCard() + { + return creditCard; + } +} \ No newline at end of file diff --git a/src/test/java/posters/tests/unit/LoginTest.java b/src/test/java/posters/tests/unit/LoginTest.java index 7667e2f0..1dbdafc0 100644 --- a/src/test/java/posters/tests/unit/LoginTest.java +++ b/src/test/java/posters/tests/unit/LoginTest.java @@ -5,29 +5,25 @@ import com.xceptance.neodymium.module.statement.browser.multibrowser.Browser; import com.xceptance.neodymium.module.statement.testdata.DataSet; -import com.xceptance.neodymium.module.statement.testdata.SuppressDataSets; import com.xceptance.neodymium.util.DataUtils; import io.qameta.allure.Owner; import io.qameta.allure.Severity; import io.qameta.allure.SeverityLevel; import io.qameta.allure.junit4.Tag; -import posters.dataobjects.User; import posters.flows.OpenLoginPageFlow; import posters.pageobjects.pages.user.LoginPage; import posters.tests.AbstractTest; +import posters.tests.testdata.dataobjects.User; -/** - * @author pfotenhauer - */ -//@Browser("Chrome_1024x768") -@Browser("Firefox_1024x768") +@Browser("Chrome_1024x768") +//@Browser("Firefox_1024x768") @Owner("Tim Brown") @Severity(SeverityLevel.NORMAL) @Tag("functionality") @Tag("registered") public class LoginTest extends AbstractTest -{ +{ private User user; private LoginPage loginPage; @@ -39,62 +35,50 @@ public void setup() loginPage = prepareTest(); } + + private LoginPage prepareTest() + { + // go to login page + loginPage = OpenLoginPageFlow.flow(); + loginPage.validateStructure(); + + // validate that nobody is logged in + loginPage.header.userMenu.validateNotLoggedIn(); + + return new LoginPage().isExpectedPage(); + } @Test @DataSet(1) public void testSuccessfulLogin() { - var homePage = loginPage.sendLoginform(user); - homePage.validateSuccessfulLogin(user); + var homePage = loginPage.sendLoginForm(user); + homePage.header.userMenu.validateStructure(); + homePage.validateSuccessfulLogin(user.getFirstName()); } @Test @DataSet(2) - @DataSet(3) - public void testLoginWithPasswordFailure() + public void testLoginWithWrongPasswort() { - loginPage.sendFalseLoginform(user); + loginPage.sendFalseLoginForm(user); loginPage.validateWrongPassword(user.getEmail()); } @Test - @DataSet(4) + @DataSet(3) public void testLoginWithEmailFailure() { - loginPage.sendFalseLoginform(user); + loginPage.sendFalseLoginForm(user); loginPage.validateWrongEmail(user.getEmail()); } @Test + @DataSet(4) @DataSet(5) - @DataSet(6) public void testLoginWithoutRequiredFields() { - loginPage.sendFalseLoginform(user); + loginPage.sendFalseLoginForm(user); loginPage.errorMessage.validateNoErrorMessageOnPage(); } - - @Test - @SuppressDataSets - public void testLoginWithUnregisteredUser() - { - final var user = new User("Jens", "Doe", "jens@doe.com", "topsecret"); - loginPage.sendFalseLoginform(user); - loginPage.validateWrongEmail(user.getEmail()); - } - - private LoginPage prepareTest() - { - // Page types to use - var loginPage = new LoginPage(); - - // Go to login page - loginPage = OpenLoginPageFlow.flow(); - loginPage.validateStructure(); - - // Assure not logged in status - loginPage.userMenu.validateNotLoggedIn(); - - return loginPage; - } -} +} \ No newline at end of file diff --git a/src/test/resources/posters/tests/component/HeaderTest.json b/src/test/resources/posters/tests/component/HeaderTest.json new file mode 100644 index 00000000..b9dc58b0 --- /dev/null +++ b/src/test/resources/posters/tests/component/HeaderTest.json @@ -0,0 +1,6 @@ +[ + { + "topCategory": "header.topNavigation.1.title", + "resultPosition": "1" + } +] diff --git a/src/test/resources/posters/tests/component/PaginationTest.json b/src/test/resources/posters/tests/component/PaginationTest.json new file mode 100644 index 00000000..efe0b639 --- /dev/null +++ b/src/test/resources/posters/tests/component/PaginationTest.json @@ -0,0 +1,6 @@ +[ + { + "topCategory": "header.topNavigation.1.title", + "expectedResultCount": "30" + } +] diff --git a/src/test/resources/posters/tests/smoke/AddToCartTest.json b/src/test/resources/posters/tests/smoke/AddToCartTest.json index 9bb835de..8f14d89e 100644 --- a/src/test/resources/posters/tests/smoke/AddToCartTest.json +++ b/src/test/resources/posters/tests/smoke/AddToCartTest.json @@ -1,6 +1,30 @@ [ { - "topCatName": "World of Nature", - "searchTerm": "pizza" + "topCategory": "header.topNavigation.1.title", + "categoryResultPosition": "1", + "subCategory": "header.topNavigation.1.subCategory.1", + "subCategoryResultPosition": "1", + "sizeFirstProduct": "16 x 12 in", + "styleFirstProduct": "matte", + "searchTerm": "pizza", + "searchResultPosition": "1", + "sizeSecondProduct": "64 x 48 in", + "styleSecondProduct": "gloss", + "productUpdatePosition": "1", + "amountChange": "3" + }, + { + "topCategory": "header.topNavigation.3.title", + "categoryResultPosition": "2", + "subCategory": "header.topNavigation.3.subCategory.2", + "subCategoryResultPosition": "2", + "sizeFirstProduct": "32 x 24 in", + "styleFirstProduct": "gloss", + "searchTerm": "boston", + "searchResultPosition": "4", + "sizeSecondProduct": "96 x 32 in", + "styleSecondProduct": "matte", + "productUpdatePosition": "1", + "amountChange": "5" } ] diff --git a/src/test/resources/posters/tests/smoke/BrowseRandomVisualAssertTest.json b/src/test/resources/posters/tests/smoke/BrowseRandomVisualAssertTest.json deleted file mode 100644 index bfc3e255..00000000 --- a/src/test/resources/posters/tests/smoke/BrowseRandomVisualAssertTest.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "numberOfProductDetailPages": "1", - "seed": "3524646135135" - }, - { - "numberOfProductDetailPages": "2", - "seed": "8645363546353" - }, - { - "numberOfProductDetailPages": "4", - "seed": "166346543535434" - }, - { - "numberOfProductDetailPages": "5", - "seed": "64541654646546" - } -] diff --git a/src/test/resources/posters/tests/smoke/BrowseTest.json b/src/test/resources/posters/tests/smoke/BrowseTest.json new file mode 100644 index 00000000..150691e1 --- /dev/null +++ b/src/test/resources/posters/tests/smoke/BrowseTest.json @@ -0,0 +1,16 @@ +[ + { + "topCategory1": "header.topNavigation.1.title", + "expectedResultCount1": "30", + "resultPosition1": "4", + "topCategory2": "header.topNavigation.2.title", + "expectedResultCount2": "30", + "resultPosition2": "3", + "topCategory3": "header.topNavigation.3.title", + "expectedResultCount3": "30", + "resultPosition3": "2", + "topCategory4": "header.topNavigation.4.title", + "expectedResultCount4": "34", + "resultPosition4": "1" + } +] diff --git a/src/test/resources/posters/tests/smoke/GuestOrderTest.json b/src/test/resources/posters/tests/smoke/GuestOrderTest.json index 81e2d7e0..a3e6d43a 100644 --- a/src/test/resources/posters/tests/smoke/GuestOrderTest.json +++ b/src/test/resources/posters/tests/smoke/GuestOrderTest.json @@ -1,16 +1,65 @@ [ { - "name":"Jimmy Blue", - "company":"Ochsenknecht Records", - "street":"6 Wall St", - "city":"Burlington", - "state":"Massachusetts", - "zip":"01803", - "country":"United States", - "fullName":"Jimmy Blue", - "cardNumber":"4111111111111111", - "crypticCardNumber":"xxxx xxxx xxxx 1111", - "expDateMonth":"04", - "expDateYear":"2023" + "topCategory": "header.topNavigation.1.title", + "resultPosition": "5", + "sizeProduct": "64 x 48 in", + "styleProduct": "gloss", + "shippingAddress": + { + "firstName": "Jimmy Blue", + "lastName": "Ochsenknecht", + "company": "Ochsenknecht Records", + "street": "6 Wall St", + "city": "Burlington", + "state": "Massachusetts", + "zip": "01803", + "country": "United States" + }, + "shipAddrEqualBillAddr": false, + "billingAddress": + { + "firstName": "Jimmy Blue", + "lastName": "Ochsenknecht", + "company": "", + "street": "9 Floor St", + "city": "Los Angeles", + "state": "California", + "zip": "00018", + "country": "United States" + }, + "creditCard": + { + "fullName": "Jimmy Blue", + "cardNumber": "4111111111111111", + "crypticCardNumber": "xxxx xxxx xxxx 1111", + "expDateMonth": "12", + "expDateYear": "2026" + } + }, + { + "topCategory": "header.topNavigation.2.title", + "resultPosition": "2", + "sizeProduct": "16 x 12 in", + "styleProduct": "matte", + "shippingAddress": + { + "firstName": "Gregor", + "lastName": "Onkh", + "company": "Ocha-Ocha GmbH", + "street": "Lizardstraße 77", + "city": "Braunschweig", + "state": "Niedersachsen", + "zip": "38100", + "country": "Germany" + }, + "shipAddrEqualBillAddr": true, + "creditCard": + { + "fullName": "Gregor Onkh", + "cardNumber": "4111111111111111", + "crypticCardNumber": "xxxx xxxx xxxx 1111", + "expDateMonth": "12", + "expDateYear": "2026" + } } ] diff --git a/src/test/resources/posters/tests/smoke/RegisterFromUserMenuTest.json b/src/test/resources/posters/tests/smoke/RegisterFromUserMenuTest.json deleted file mode 100644 index 26180a1f..00000000 --- a/src/test/resources/posters/tests/smoke/RegisterFromUserMenuTest.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "firstName": "Jane", - "lastName": "Doe", - "email": "jane@doe.com", - "password": "topsecret", - "testId": "Jane's test" - } -] diff --git a/src/test/resources/posters/tests/smoke/RegisterTest.json b/src/test/resources/posters/tests/smoke/RegisterTest.json index bcc52ad0..1e78a684 100644 --- a/src/test/resources/posters/tests/smoke/RegisterTest.json +++ b/src/test/resources/posters/tests/smoke/RegisterTest.json @@ -2,56 +2,56 @@ { "firstName": "Jane", "lastName": "Doe", - "email": "jane@doe.com", + "email": "jane@varmail.net", "password": "topsecret", "testId": "Jane's test" }, { "firstName": "Simon", "lastName": "Doe", - "email": "simon@doe.com", + "email": "simon@varmail.net", "password": "topsecret", "testId": "Simons's test" }, { "firstName": "James", "lastName": "Doe", - "email": "james@doe.com", + "email": "james@varmail.net", "password": "topsecret", "testId": "James' test" }, { "firstName": "Josh", "lastName": "Doe", - "email": "josh@doe.com", + "email": "josh@varmail.net", "password": "topsecret", "testId": "Josh's test" }, { "firstName": "Jim", "lastName": "Doe", - "email": "jim@doe.com", + "email": "jim@varmail.net", "password": "topsecret", "testId": "Jim's test" }, { "firstName": "Jude", "lastName": "Doe", - "email": "jude@doe.com", + "email": "jude@varmail.net", "password": "topsecret", "testId": "Jude's test" }, { "firstName": "Joel", "lastName": "Doe", - "email": "joel@doe.com", + "email": "joel@varmail.net", "password": "topsecret", "testId": "Joel's test" }, { "firstName": "Jeremiah", "lastName": "Doe", - "email": "jeremiah@doe.com", + "email": "jeremiah@varmail.net", "password": "topsecret", "testId": "Jeremiah's test" } diff --git a/src/test/resources/posters/tests/smoke/RegisteredOrderTest.json b/src/test/resources/posters/tests/smoke/RegisteredOrderTest.json index 4b48ccb3..e77a8872 100644 --- a/src/test/resources/posters/tests/smoke/RegisteredOrderTest.json +++ b/src/test/resources/posters/tests/smoke/RegisteredOrderTest.json @@ -1,19 +1,85 @@ [ - { - "email": "john@doe.com", - "password": "topsecret", - "firstName": "John", - "lastName": "Doe", - "company": "John Doe Inc.", - "street": "5-7 John Doe street", - "city": "New York", - "state": "NY", - "zip": "12345", - "country": "United States", - "fullName": "John Doe", - "cardNumber": "4111111111111111", - "crypticCardNumber": "xxxx xxxx xxxx 1111", - "expDateMonth": "08", - "expDateYear": "2022" - } + { + "user": + { + "firstName": "Jonas", + "lastName": "Doe", + "email": "jonas@varmail.net", + "password": "topsecret" + }, + "topCategory": "header.topNavigation.2.title", + "resultPosition": "6", + "sizeProduct": "32 x 24 in", + "styleProduct": "gloss", + "shipAddrPos": 1, + "billAddrPos": 1, + "creditCardPos": 1, + "shipAddrEqualBillAddr": true, + "shippingAddress": + { + "firstName": "Jonas", + "lastName": "Doe", + "company": "Jonas Doe Inc.", + "street": "5-7 Jonas Doe street", + "city": "New York City", + "state": "New York", + "zip": "12345", + "country": "United States" + }, + "creditCard": + { + "fullName": "Jonas Doe", + "cardNumber": "4111111111111111", + "crypticCardNumber": "xxxx xxxx xxxx 1111", + "expDateMonth": "06", + "expDateYear": "2028" + } + }, + { + "user": + { + "firstName": "Jonas", + "lastName": "Doe", + "email": "jonas@varmail.net", + "password": "topsecret" + }, + "topCategory": "header.topNavigation.4.title", + "resultPosition": "2", + "sizeProduct": "16 x 12 in", + "styleProduct": "matte", + "shipAddrPos": 1, + "billAddrPos": 2, + "creditCardPos": 1, + "shipAddrEqualBillAddr": false, + "shippingAddress": + { + "firstName": "Jonas", + "lastName": "Doe", + "company": "Jonas Doe Inc.", + "street": "5-7 Jonas Doe street", + "city": "New York City", + "state": "New York", + "zip": "12345", + "country": "United States" + }, + "billingAddress": + { + "firstName": "Jonas", + "lastName": "Doe", + "company": "Jonas Doe GmbH", + "street": "Jonas Doe Straße 10", + "city": "Hannover", + "state": "Niedersachsen", + "zip": "30159", + "country": "Germany" + }, + "creditCard": + { + "fullName": "Jonas Doe", + "cardNumber": "4111111111111111", + "crypticCardNumber": "xxxx xxxx xxxx 1111", + "expDateMonth": "06", + "expDateYear": "2028" + } + } ] diff --git a/src/test/resources/posters/tests/smoke/SearchTest.json b/src/test/resources/posters/tests/smoke/SearchTest.json index 8157ad8c..d521d2bd 100644 --- a/src/test/resources/posters/tests/smoke/SearchTest.json +++ b/src/test/resources/posters/tests/smoke/SearchTest.json @@ -1,12 +1,10 @@ [ { "searchTerm": "bear", - "position": "1", - "searchTermExpectedCount": "3" + "expectedResultCount": "3", + "resultPosition": "1" }, { - "searchTerm": "Foobar", - "position": "", - "searchTermExpectedCount": "" + "searchTerm": "Foobar" } ] diff --git a/src/test/resources/posters/tests/unit/LoginTest.json b/src/test/resources/posters/tests/unit/LoginTest.json index af0a974d..cfcc73a4 100644 --- a/src/test/resources/posters/tests/unit/LoginTest.json +++ b/src/test/resources/posters/tests/unit/LoginTest.json @@ -2,30 +2,23 @@ { "firstName": "John", "lastName": "Doe", - "email": "john@doe.com", + "email": "john@varmail.net", "password": "topsecret", "testId": "happy path" }, { "firstName": "John", "lastName": "Doe", - "email": "john@doe.com", + "email": "john@varmail.net", "password": "notsecret", "testId": "wrong password" }, - { - "firstName": "John", - "lastName": "Doe", - "email": "john@doe.com", - "password": "topsecret123", - "testId": "extended password" - }, { "firstName": "John", "lastName": "Doe", "email": "john@doe.company", "password": "topsecret", - "testId": "extended email" + "testId": "wrong email" }, { "firstName": "John", @@ -37,7 +30,7 @@ { "firstName": "John", "lastName": "Doe", - "email": "john@doe.com", + "email": "john@varmail.net", "password": "", "testId": "missing password" }