diff --git a/test/features/login.feature b/test/features/login.feature new file mode 100644 index 0000000..ddce41b --- /dev/null +++ b/test/features/login.feature @@ -0,0 +1,12 @@ +Feature: Login + + Scenario Outline: Error Messages + Given I am on the studentbeans homepage + And I accept cookies + And I click the Login link + When I enter '' and '' in the login form + # Note: Below step fails as manual recaptch validation is required: + Then I see the '' + Examples: + | Username | Password | Error | + | test@test.com | testingStuff | The password you entered is incorrect. Please try again. | diff --git a/test/features/simpleSearch.feature b/test/features/simpleSearch.feature index 0267f8d..813b056 100644 --- a/test/features/simpleSearch.feature +++ b/test/features/simpleSearch.feature @@ -1,8 +1,8 @@ Feature: Simple Search -Scenario: As a user I want to search for a brand on studentbeans.com so that I can see if I can get a discount on that brand - Given I am on the studentbeans homepage - And I open the search bar - When I enter "Samsung" - Then I should select the 4th "Samsung" search listing - + Scenario: As a user I want to search for a brand on studentbeans.com so that I can see if I can get a discount on that brand + Given I am on the studentbeans homepage + And I open the search bar + When I enter "Samsung" + # Note: There were only 3 "Samsung" listings returned, so I selected the 3rd listing: + Then I should select the 3rd "Samsung" search listing diff --git a/test/features/trendingNow.feature b/test/features/trendingNow.feature new file mode 100644 index 0000000..225ee25 --- /dev/null +++ b/test/features/trendingNow.feature @@ -0,0 +1,7 @@ +Feature: Trending Now + + Scenario: As a user I want to open the 6th discount within the Trending Now offers list + Given I am on the studentbeans homepage + And I accept cookies + When I click the 'Trending Now' offers link + Then I open the 6th discount diff --git a/test/pageObjects/loginPageObject.js b/test/pageObjects/loginPageObject.js new file mode 100644 index 0000000..a49e949 --- /dev/null +++ b/test/pageObjects/loginPageObject.js @@ -0,0 +1,50 @@ +const ParentPageObject = require('./parentPageObject'); + +class LoginPageObject extends ParentPageObject { + get loginLink() { + return $('[data-testid="nav-login"]'); + } + + get emailInput() { + return $('#email'); + } + + get passwordInput() { + return $('#password'); + } + + get recaptchaCheckbox() { + return $('.recaptcha-checkbox-border'); + } + + get loginBtns() { + return $$('button=Log in'); + } + + async clickCaptcha() { + await browser.switchToFrame(await $('iframe[title="reCAPTCHA"]')); + await this.recaptchaCheckbox.click(); + } + + async enterLoginDetails(user, pass) { + await browser.switchToFrame(null); + await this.emailInput.setValue(user); + await this.passwordInput.setValue(pass); + + await this.loginBtns[1].click(); // Click the 'Login' button - second button (0-based index). This is required cause there are 2 buttons on the page with 'Log in' text + await browser.pause(5000); + } + + async clickLoginLink() { + await this.loginLink.click(); + } + + async verifyInputError() { + await this.isElementEqualToExpected( + $('[data-testid="input-alert"]'), + 'The password you entered is incorrect. Please try again.' + ); + } +} + +module.exports = LoginPageObject; diff --git a/test/pageObjects/parentPageObject.js b/test/pageObjects/parentPageObject.js index 4392f5e..ff437c1 100644 --- a/test/pageObjects/parentPageObject.js +++ b/test/pageObjects/parentPageObject.js @@ -1,10 +1,12 @@ -const { assert } = require('chai') +const { assert } = require('chai'); class ParentPageObject { - async isElementEqualToExpected (element, expectedText) { - const rrorMessage = 'Actual does not match expected' - assert(await expect(await element.getText(), errorMessage).to.equal(expectedText)) + async isElementEqualToExpected(element, expectedText) { + const errorMessage = 'Actual does not match expected'; + assert( + await expect(await element.getText(), errorMessage).to.equal(expectedText) + ); } } -module.exports = ParentPageObject +module.exports = ParentPageObject; diff --git a/test/pageObjects/simpleSearchPageObject.js b/test/pageObjects/simpleSearchPageObject.js index fcce9f3..e060095 100644 --- a/test/pageObjects/simpleSearchPageObject.js +++ b/test/pageObjects/simpleSearchPageObject.js @@ -1,14 +1,64 @@ -const ParentPageObject = require('./parentPageObject') +const ParentPageObject = require('./parentPageObject'); class SimpleSearchPageObject extends ParentPageObject { - async goToHomePage () { - // the below url call is relative to the base url in the wdio.conf.js so the below call will actually just result in going straight to the base url - await browser.url('') + async goToHomePage() { + await browser.url(''); } - async verifyHomePage () { - await this.isElementEqualToExpected($('h2=Recommended For You'), 'Recommended For You') + async verifyHomePage() { + await this.isElementEqualToExpected( + $('h2=Recommended For You'), + 'Recommended For You' + ); + } + + get acceptButton() { + return $('#onetrust-accept-btn-handler'); + } + + get searchButton() { + return $('[data-testid="nav-search-desktop"]'); + } + + get searchInput() { + return $('[data-testid="search-input"]'); + } + + async openSearchBar() { + this.acceptCookies(); + this.searchButton.click(); + } + + async enterTextInSearchBar(txt) { + this.searchInput.setValue(txt); + } + + async selectThirdSearchListing(txt) { + await browser.pause(5000); + const elementIndex = 2; // Index 2 corresponds to the 3rd element (0-based index) + const selectedElement = await this.selectElementByTextAndIndex( + 'span', + txt, + elementIndex + ); + + if (selectedElement) { + selectedElement.click(); + } else { + console.log(`No 3rd element with the text "${txt}" found.`); + } + } + + async selectElementByTextAndIndex(tag, text, index) { + const xpathSelector = `//${tag}[text()="${text}"]`; + const elements = $$(xpathSelector); + + return elements[index]; + } + + async acceptCookies() { + this.acceptButton.click(); } } -module.exports = SimpleSearchPageObject +module.exports = SimpleSearchPageObject; diff --git a/test/pageObjects/trendingNowPageObject.js b/test/pageObjects/trendingNowPageObject.js new file mode 100644 index 0000000..78e107d --- /dev/null +++ b/test/pageObjects/trendingNowPageObject.js @@ -0,0 +1,24 @@ +const ParentPageObject = require('./parentPageObject'); + +class TrendingNowPageObject extends ParentPageObject { + get acceptButton() { + return $('#onetrust-accept-btn-handler'); + } + + clickLinkByText(txt) { + const link = $(`//a[text()="${txt}"]`); + link.click(); + } + + async acceptCookies() { + this.acceptButton.click(); + } + + async selectSixthListing() { + await browser.pause(5000); + const elementsWithTestId = $$('[data-testid="offer-tile-title-container"]'); + elementsWithTestId[5].click(); // Click the 6th element (0-based index) + } +} + +module.exports = TrendingNowPageObject; diff --git a/test/stepDefs/loginStepDef.js b/test/stepDefs/loginStepDef.js new file mode 100644 index 0000000..c2be330 --- /dev/null +++ b/test/stepDefs/loginStepDef.js @@ -0,0 +1,17 @@ +const { Given, When, Then } = require('@cucumber/cucumber'); +const LoginPageObject = require('../pageObjects/loginPageObject'); + +const loginPageObject = new LoginPageObject(); + +Given('I click the Login link', async () => { + await loginPageObject.clickLoginLink(); +}); + +When('I enter {string} and {string} in the login form', async (user, pass) => { + await loginPageObject.clickCaptcha(); + await loginPageObject.enterLoginDetails(user, pass); +}); + +Then('I see the {string}', async (txt) => { + await loginPageObject.verifyInputError(); +}); diff --git a/test/stepDefs/simpleSearchStepDef.js b/test/stepDefs/simpleSearchStepDef.js index 174130e..c7f298a 100644 --- a/test/stepDefs/simpleSearchStepDef.js +++ b/test/stepDefs/simpleSearchStepDef.js @@ -1,9 +1,21 @@ -const { Given } = require('@cucumber/cucumber') -const SimpleSearchPageObject = require('../pageObjects/simpleSearchPageObject') +const { Given, When, Then } = require('@cucumber/cucumber'); +const SimpleSearchPageObject = require('../pageObjects/simpleSearchPageObject'); -const simpleSearchPageObject = new SimpleSearchPageObject() +const simpleSearchPageObject = new SimpleSearchPageObject(); Given('I am on the studentbeans homepage', async () => { - await simpleSearchPageObject.goToHomePage() - await simpleSearchPageObject.verifyHomePage() -}) + await simpleSearchPageObject.goToHomePage(); + await simpleSearchPageObject.verifyHomePage(); +}); + +Given('I open the search bar', async () => { + await simpleSearchPageObject.openSearchBar(); +}); + +When('I enter {string}', async (txt) => { + await simpleSearchPageObject.enterTextInSearchBar(txt); +}); + +Then('I should select the 3rd {string} search listing', async (txt) => { + await simpleSearchPageObject.selectThirdSearchListing(txt); +}); diff --git a/test/stepDefs/trendingNowStepDef.js b/test/stepDefs/trendingNowStepDef.js new file mode 100644 index 0000000..104e1ee --- /dev/null +++ b/test/stepDefs/trendingNowStepDef.js @@ -0,0 +1,16 @@ +const { Given, When, Then } = require('@cucumber/cucumber'); +const TrendingNowPageObject = require('../pageObjects/trendingNowPageObject'); + +const trendingNowPageObject = new TrendingNowPageObject(); + +Given('I accept cookies', async () => { + await trendingNowPageObject.acceptCookies(); +}); + +When('I click the {string} offers link', async (txt) => { + await trendingNowPageObject.clickLinkByText(txt); +}); + +Then('I open the 6th discount', async () => { + await trendingNowPageObject.selectSixthListing(); +});