├── .gitignore ├── configuration.properties ├── pom.xml ├── readme.md └── src └── test ├── java └── com │ └── cybertek │ └── library │ ├── pages │ ├── BasePage.java │ ├── BooksPage.java │ ├── DashBoardPage.java │ ├── LoginPage.java │ └── UsersPage.java │ ├── pojos │ ├── Book.java │ └── User.java │ ├── runners │ ├── CukesRunner.java │ └── FailedTestRunner.java │ ├── step_definitions │ ├── BaseStep.java │ ├── BooksStepDefs.java │ ├── DashboardNavigationStepDefs.java │ ├── Hooks.java │ ├── LoginStepDefs.java │ └── UserStepDefs.java │ └── utilities │ ├── api │ ├── AuthenticationUtility.java │ ├── Endpoints.java │ ├── LibrarianAuthenticationUtility.java │ └── StudentAuthenticationUtility.java │ ├── common │ ├── Encoder.java │ ├── Environment.java │ ├── LibraryConstants.java │ └── LibraryUserUtility.java │ ├── db │ └── DBUtils.java │ └── ui │ ├── BrowserUtils.java │ ├── Driver.java │ └── Pages.java └── resources ├── env ├── qa1.properties ├── qa2.properties └── qa3.properties ├── features ├── AddUserAPITests.feature ├── BookInformationValidation.feature ├── PageNavigation.feature ├── SearchResults.feature └── UserTable.feature └── test-data ├── Library QA 1 user data.pdf └── Library QA 2 user data.xlsx /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | *.iml 3 | target 4 | .DS_Store 5 | test-output 6 | -------------------------------------------------------------------------------- /configuration.properties: -------------------------------------------------------------------------------- 1 | browser=chrome 2 | env=qa1 -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.syslibrary 8 | syslibrary-cucumber-framework 9 | 1.0-SNAPSHOT 10 | 11 | 1.8 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | 16 | 17 | 18 | org.seleniumhq.selenium 19 | selenium-java 20 | 3.141.59 21 | 22 | 23 | io.cucumber 24 | cucumber-java 25 | 5.6.0 26 | 27 | 28 | io.cucumber 29 | cucumber-junit 30 | 5.6.0 31 | 32 | 33 | io.github.bonigarcia 34 | webdrivermanager 35 | 3.8.1 36 | 37 | 38 | mysql 39 | mysql-connector-java 40 | 8.0.18 41 | 42 | 43 | io.rest-assured 44 | rest-assured 45 | 4.3.0 46 | 47 | 48 | com.github.javafaker 49 | javafaker 50 | 1.0.2 51 | 52 | 53 | com.google.code.gson 54 | gson 55 | 2.8.6 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-surefire-plugin 64 | 3.0.0-M4 65 | 66 | 67 | **/CukesRunner.java 68 | 69 | true 70 | methods 71 | 3 72 | false 73 | perthread 74 | 75 | 76 | 77 | net.masterthought 78 | maven-cucumber-reporting 79 | 5.0.0 80 | 81 | 82 | execution 83 | verify 84 | 85 | generate 86 | 87 | 88 | Cucumber HTML Reports 89 | ${project.build.directory} 90 | ${project.build.directory} 91 | 92 | **/cucumber*.json 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybertek-Mentors/syslibrary-cucumber-framework/06eaff8452df8c9be61332cd389fc59e4abfe20f/readme.md -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/pages/BasePage.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.pages; 2 | 3 | import com.cybertek.library.utilities.ui.Driver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | 8 | public abstract class BasePage { 9 | public BasePage() { 10 | PageFactory.initElements(Driver.getDriver(), this); 11 | } 12 | 13 | @FindBy(xpath = "//span[@class='title'][.='Users']") 14 | public WebElement users; 15 | 16 | @FindBy(xpath = "//span[@class='title'][.='Dashboard']") 17 | public WebElement dashboard; 18 | 19 | @FindBy(xpath = "//span[@class='title'][.='Books']") 20 | public WebElement books; 21 | 22 | @FindBy(tagName = "h3") 23 | public WebElement pageHeader; 24 | 25 | @FindBy(css = "#navbarDropdown>span") 26 | public WebElement accountHolderName; 27 | 28 | @FindBy(linkText = "Log Out") 29 | public WebElement logOutLink; 30 | 31 | public void logOut(){ 32 | accountHolderName.click(); 33 | logOutLink.click(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/pages/BooksPage.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.pages; 2 | 3 | import com.cybertek.library.utilities.ui.Driver; 4 | import org.openqa.selenium.By; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.Select; 8 | 9 | import java.util.List; 10 | 11 | public class BooksPage extends BasePage { 12 | 13 | @FindBy(xpath = "//table/tbody/tr") 14 | public List allRows; 15 | 16 | @FindBy(tagName = "input") 17 | public WebElement search; 18 | 19 | @FindBy(css = "[href='tpl/add-book.html']") 20 | public WebElement addBook; 21 | 22 | @FindBy(name = "name") 23 | public WebElement bookName; 24 | 25 | @FindBy(name = "isbn") 26 | public WebElement isbn; 27 | 28 | @FindBy(name = "year") 29 | public WebElement year; 30 | 31 | @FindBy(xpath = "(//input[@type='text'])[4]") 32 | public WebElement author; 33 | 34 | @FindBy(id = "description") 35 | public WebElement description; 36 | 37 | @FindBy(id = "book_group_id") 38 | public WebElement categoryElement; 39 | 40 | @FindBy(id = "book_categories") 41 | public WebElement mainCategoryElement; 42 | 43 | public WebElement editBook(String book) { 44 | String xpath = "//td[3][.='" + book + "']/../td/a"; 45 | return Driver.getDriver().findElement(By.xpath(xpath)); 46 | } 47 | 48 | public Select categoryList() { 49 | return new Select(categoryElement); 50 | } 51 | 52 | public Select mainCategoryList() { 53 | return new Select(mainCategoryElement); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/pages/DashBoardPage.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.pages; 2 | 3 | import org.openqa.selenium.WebElement; 4 | import org.openqa.selenium.support.FindBy; 5 | 6 | public class DashBoardPage extends BasePage { 7 | @FindBy(id = "user_count") 8 | public WebElement userCount; 9 | 10 | @FindBy(id = "book_count") 11 | public WebElement bookCount; 12 | 13 | @FindBy(id = "borrowed_books") 14 | public WebElement borrowedBooksCount; 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/pages/LoginPage.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.pages; 2 | 3 | import com.cybertek.library.utilities.ui.Driver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | 8 | public class LoginPage { 9 | public LoginPage() { 10 | PageFactory.initElements(Driver.getDriver(), this); 11 | } 12 | 13 | @FindBy(id = "inputEmail") 14 | public WebElement email; 15 | 16 | @FindBy(id = "inputPassword") 17 | public WebElement password; 18 | 19 | @FindBy(tagName = "button") 20 | public WebElement signIn; 21 | 22 | public void login(String email, String password) { 23 | this.email.sendKeys(email); 24 | this.password.sendKeys(password); 25 | signIn.click(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/pages/UsersPage.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.pages; 2 | 3 | import org.openqa.selenium.WebElement; 4 | import org.openqa.selenium.support.FindBy; 5 | import org.openqa.selenium.support.ui.Select; 6 | 7 | import java.util.List; 8 | 9 | public class UsersPage extends BasePage { 10 | @FindBy(name = "tbl_users_length") 11 | public WebElement showRecords; 12 | 13 | @FindBy(xpath = "//table/tbody/tr") 14 | public List allRows; 15 | 16 | @FindBy(tagName = "input") 17 | public WebElement search; 18 | 19 | @FindBy(xpath = "//table/tbody/tr/td[2]") 20 | public List allUserIds; 21 | 22 | @FindBy(xpath = "//table/tbody/tr/td[3]") 23 | public List allFullNames; 24 | 25 | @FindBy(xpath = "//table/tbody/tr/td[4]") 26 | public List allEmails; 27 | 28 | @FindBy(tagName = "th") 29 | public List columnNames; 30 | 31 | @FindBy(css = "a.btn-lg") 32 | public WebElement addUsers; 33 | 34 | @FindBy(name = "full_name") 35 | public WebElement fullName; 36 | 37 | @FindBy(name = "password") 38 | public WebElement password; 39 | 40 | @FindBy(name = "email") 41 | public WebElement email; 42 | 43 | @FindBy(id = "address") 44 | public WebElement address; 45 | 46 | @FindBy(id = "user_group_id") 47 | public WebElement group; 48 | 49 | @FindBy(id = "status") 50 | public WebElement status; 51 | 52 | @FindBy(css="a.page-link:not([title])") 53 | public List pagesList; 54 | 55 | public Select getShowRecords() { 56 | return new Select(showRecords); 57 | } 58 | 59 | public Select getGroup(){ 60 | return new Select(group); 61 | } 62 | 63 | public Select getStatus(){ 64 | return new Select(status); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/pojos/Book.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.pojos; 2 | 3 | public class Book { 4 | private String name; 5 | private String author; 6 | private String year; 7 | private String category; 8 | private String isbn; 9 | private String description; 10 | 11 | public Book(String name, String author, String year) { 12 | this.name = name; 13 | this.author = author; 14 | this.year = year; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | 25 | public String getAuthor() { 26 | return author; 27 | } 28 | 29 | public void setAuthor(String author) { 30 | this.author = author; 31 | } 32 | 33 | public String getYear() { 34 | return year; 35 | } 36 | 37 | public void setYear(String year) { 38 | this.year = year; 39 | } 40 | 41 | public String getCategory() { 42 | return category; 43 | } 44 | 45 | public void setCategory(String category) { 46 | this.category = category; 47 | } 48 | 49 | public String getIsbn() { 50 | return isbn; 51 | } 52 | 53 | public void setIsbn(String isbn) { 54 | this.isbn = isbn; 55 | } 56 | 57 | public String getDescription() { 58 | return description; 59 | } 60 | 61 | public void setDescription(String description) { 62 | this.description = description; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return "Book{" + 68 | "name='" + name + '\'' + 69 | ", author='" + author + '\'' + 70 | ", year='" + year + '\'' + 71 | '}'; 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/pojos/User.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.pojos; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class User { 6 | 7 | @SerializedName("id") 8 | private String id; 9 | 10 | @SerializedName("full_name") 11 | private String fullName; 12 | 13 | @SerializedName("email") 14 | private String email; 15 | 16 | @SerializedName("password") 17 | private String password; 18 | 19 | @SerializedName("user_group_id") 20 | private String userGroupId; 21 | 22 | @SerializedName("image") 23 | private Object image; 24 | 25 | @SerializedName("extra_data") 26 | private Object extraData; 27 | 28 | @SerializedName("status") 29 | private String status; 30 | 31 | @SerializedName("is_admin") 32 | private String isAdmin; 33 | 34 | @SerializedName("start_date") 35 | private String startDate; 36 | 37 | @SerializedName("end_date") 38 | private String endDate; 39 | 40 | @SerializedName("address") 41 | private String address; 42 | 43 | /** 44 | * No args constructor for use in serialization 45 | * 46 | */ 47 | public User() { 48 | } 49 | 50 | /** 51 | * 52 | * @param userGroupId 53 | * @param image 54 | * @param password 55 | * @param address 56 | * @param extraData 57 | * @param endDate 58 | * @param fullName 59 | * @param id 60 | * @param isAdmin 61 | * @param email 62 | * @param startDate 63 | * @param status 64 | */ 65 | public User(String id, String fullName, String email, String password, String userGroupId, Object image, Object extraData, String status, String isAdmin, String startDate, String endDate, String address) { 66 | super(); 67 | this.id = id; 68 | this.fullName = fullName; 69 | this.email = email; 70 | this.password = password; 71 | this.userGroupId = userGroupId; 72 | this.image = image; 73 | this.extraData = extraData; 74 | this.status = status; 75 | this.isAdmin = isAdmin; 76 | this.startDate = startDate; 77 | this.endDate = endDate; 78 | this.address = address; 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return "User{" + 84 | "id='" + id + '\'' + 85 | ", fullName='" + fullName + '\'' + 86 | ", email='" + email + '\'' + 87 | ", password='" + password + '\'' + 88 | ", userGroupId='" + userGroupId + '\'' + 89 | ", image=" + image + 90 | ", extraData=" + extraData + 91 | ", status='" + status + '\'' + 92 | ", isAdmin='" + isAdmin + '\'' + 93 | ", startDate='" + startDate + '\'' + 94 | ", endDate='" + endDate + '\'' + 95 | ", address='" + address + '\'' + 96 | '}'; 97 | } 98 | 99 | public String getId() { 100 | return id; 101 | } 102 | 103 | public void setId(String id) { 104 | this.id = id; 105 | } 106 | 107 | public String getFullName() { 108 | return fullName; 109 | } 110 | 111 | public void setFullName(String fullName) { 112 | this.fullName = fullName; 113 | } 114 | 115 | public String getEmail() { 116 | return email; 117 | } 118 | 119 | public void setEmail(String email) { 120 | this.email = email; 121 | } 122 | 123 | public String getPassword() { 124 | return password; 125 | } 126 | 127 | public void setPassword(String password) { 128 | this.password = password; 129 | } 130 | 131 | public String getUserGroupId() { 132 | return userGroupId; 133 | } 134 | 135 | public void setUserGroupId(String userGroupId) { 136 | this.userGroupId = userGroupId; 137 | } 138 | 139 | public Object getImage() { 140 | return image; 141 | } 142 | 143 | public void setImage(Object image) { 144 | this.image = image; 145 | } 146 | 147 | public Object getExtraData() { 148 | return extraData; 149 | } 150 | 151 | public void setExtraData(Object extraData) { 152 | this.extraData = extraData; 153 | } 154 | 155 | public String getStatus() { 156 | return status; 157 | } 158 | 159 | public void setStatus(String status) { 160 | this.status = status; 161 | } 162 | 163 | public String getIsAdmin() { 164 | return isAdmin; 165 | } 166 | 167 | public void setIsAdmin(String isAdmin) { 168 | this.isAdmin = isAdmin; 169 | } 170 | 171 | public String getStartDate() { 172 | return startDate; 173 | } 174 | 175 | public void setStartDate(String startDate) { 176 | this.startDate = startDate; 177 | } 178 | 179 | public String getEndDate() { 180 | return endDate; 181 | } 182 | 183 | public void setEndDate(String endDate) { 184 | this.endDate = endDate; 185 | } 186 | 187 | public String getAddress() { 188 | return address; 189 | } 190 | 191 | public void setAddress(String address) { 192 | this.address = address; 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/runners/CukesRunner.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.runners; 2 | 3 | import io.cucumber.junit.Cucumber; 4 | import io.cucumber.junit.CucumberOptions; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(Cucumber.class) 8 | @CucumberOptions( 9 | plugin = { 10 | "pretty", 11 | "json:target/cucumber.json", 12 | "rerun:target/rerun.txt" 13 | }, 14 | 15 | features = "src/test/resources/features", 16 | glue = "com/cybertek/library/step_definitions", 17 | dryRun = false 18 | // tags = "@lib-132" 19 | ) 20 | public class CukesRunner { 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/runners/FailedTestRunner.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.runners; 2 | 3 | import io.cucumber.junit.Cucumber; 4 | import io.cucumber.junit.CucumberOptions; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(Cucumber.class) 8 | @CucumberOptions( 9 | glue = "com/cybertek/library/step_definitions", 10 | features = "@target/rerun.txt" 11 | ) 12 | public class FailedTestRunner { 13 | 14 | } 15 | // this does not report. to report add "html:target/default-cucumber-reports", 16 | // if you use the same report name as your runner file, it will 17 | // delete that report and create new one only ofr failed tests 18 | // if you write a differnet name, it wil create second report. -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/step_definitions/BaseStep.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.step_definitions; 2 | 3 | import com.cybertek.library.utilities.api.AuthenticationUtility; 4 | import com.cybertek.library.utilities.ui.Pages; 5 | 6 | import java.util.Map; 7 | 8 | public class BaseStep { 9 | protected AuthenticationUtility authenticationUtility; 10 | protected Pages pages = new Pages(); 11 | protected static Map user; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/step_definitions/BooksStepDefs.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.step_definitions; 2 | 3 | import com.cybertek.library.pages.BooksPage; 4 | import com.cybertek.library.pojos.Book; 5 | import com.cybertek.library.utilities.api.AuthenticationUtility; 6 | import com.cybertek.library.utilities.api.Endpoints; 7 | import com.cybertek.library.utilities.api.LibrarianAuthenticationUtility; 8 | import com.cybertek.library.utilities.db.DBUtils; 9 | import com.cybertek.library.utilities.ui.BrowserUtils; 10 | import io.cucumber.java.en.Then; 11 | import io.cucumber.java.en.When; 12 | import io.restassured.http.ContentType; 13 | import io.restassured.response.Response; 14 | import org.openqa.selenium.WebElement; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | import static io.restassured.RestAssured.given; 21 | import static org.hamcrest.MatcherAssert.assertThat; 22 | import static org.hamcrest.Matchers.is; 23 | import static org.junit.Assert.assertEquals; 24 | 25 | public class BooksStepDefs extends BaseStep { 26 | @Then("book information must match the api for {}") 27 | public void book_information_must_match_the_api_for_The_kite_runner(String book) { 28 | // call the database to get the book id for 29 | String query = "SELECT id FROM books WHERE name = '" + book + "'"; 30 | String id = DBUtils.getCellValue(query).toString(); 31 | // get the token 32 | AuthenticationUtility authenticationUtility = new LibrarianAuthenticationUtility(); 33 | String token = authenticationUtility.getToken(); 34 | // use the id to make the call to api 35 | Response response = given(). 36 | log().all(). 37 | header("x-library-token", token). 38 | pathParam("id", id). 39 | when(). 40 | get(Endpoints.GET_BOOK_BY_ID). 41 | prettyPeek(); 42 | // verify response vs ui 43 | response.then().statusCode(200).contentType(ContentType.JSON); 44 | Book bookPojo = response.as(Book.class); 45 | 46 | assertThat(bookPojo.getName(), is(pages.booksPage().bookName.getAttribute("value"))); 47 | assertThat(bookPojo.getAuthor(), is(pages.booksPage().author.getAttribute("value"))); 48 | assertThat(bookPojo.getIsbn(), is(pages.booksPage().isbn.getAttribute("value"))); 49 | assertThat(bookPojo.getDescription(), is(pages.booksPage().description.getAttribute("value"))); 50 | 51 | } 52 | 53 | @When("I open book {}") 54 | public void i_edit_book_The_kiterunner(String book) { 55 | System.out.println("book = " + book); 56 | BrowserUtils.waitForClickability(pages.booksPage().search, 5).sendKeys(book); 57 | BrowserUtils.waitForClickability(pages.booksPage().editBook(book), 5).click(); 58 | 59 | } 60 | 61 | @Then("book information must match the database for {}") 62 | public void book_information_must_match_the_database_for_The_kite_runner(String book) { 63 | 64 | String sql = "SELECT b.isbn, b.year, b.author, bc.name, b.description\n" + 65 | "FROM books b\n" + 66 | "JOIN book_categories bc\n" + 67 | "ON b.book_category_id = bc.id\n" + 68 | "WHERE b.name = '" + book + "';"; 69 | Map dbData = DBUtils.getRowMap(sql); 70 | 71 | DBUtils.getColumnNames(sql); 72 | 73 | assertEquals("author did not match", dbData.get("author").toString(), pages.booksPage().author.getAttribute("value")); 74 | assertEquals("year did not match", dbData.get("year").toString(), pages.booksPage().year.getAttribute("value")); 75 | assertEquals("isbn did not match", dbData.get("isbn").toString(), pages.booksPage().isbn.getAttribute("value")); 76 | assertEquals("description did not match", dbData.get("description").toString(), pages.booksPage().description.getAttribute("value")); 77 | assertEquals("category did not match", dbData.get("name").toString(), pages.booksPage().categoryList().getFirstSelectedOption().getText()); 78 | } 79 | @Then("book categories must match book_categories table from db") 80 | public void book_categories_must_match_book_categories_table_from_db() { 81 | // get the expected categories from the database as a list 82 | String sql = "SELECT name FROM book_categories;"; 83 | List namesObj = DBUtils.getColumnData(sql, "name"); 84 | List exNames = new ArrayList<>(); 85 | for (Object o : namesObj) { 86 | exNames.add(o.toString()); 87 | } 88 | // get the actual categories from UI as webelements 89 | // convert the web elements to list 90 | List optionsEl = pages.booksPage().mainCategoryList().getOptions(); 91 | List acNames = BrowserUtils.getElementsText(optionsEl); 92 | // remove the first option ALL from acList. 93 | acNames.remove(0); 94 | // compare 2 lists 95 | assertEquals("Categories did not match", exNames, acNames); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/step_definitions/DashboardNavigationStepDefs.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.step_definitions; 2 | 3 | import com.cybertek.library.utilities.common.LibraryConstants; 4 | import com.cybertek.library.utilities.ui.BrowserUtils; 5 | import com.cybertek.library.utilities.ui.Driver; 6 | import io.cucumber.java.en.Then; 7 | import io.cucumber.java.en.When; 8 | import org.junit.Assert; 9 | 10 | public class DashboardNavigationStepDefs extends BaseStep{ 11 | @When("I go/navigate to {string} page") 12 | public void i_go_to_page(String page) { 13 | switch (page.toLowerCase()) { 14 | case LibraryConstants.DASHBOARD: 15 | pages.dashBoardPage().dashboard.click(); 16 | break; 17 | case LibraryConstants.USERS: 18 | pages.dashBoardPage().users.click(); 19 | break; 20 | case LibraryConstants.BOOKS: 21 | pages.dashBoardPage().books.click(); 22 | break; 23 | } 24 | } 25 | @Then("{string} page should be displayed") 26 | public void page_should_be_displayed(String page) { 27 | BrowserUtils.wait(1); 28 | Assert.assertTrue(Driver.getDriver().getCurrentUrl().endsWith(page.toLowerCase())); 29 | switch (page.toLowerCase()) { 30 | case "users": 31 | String actual = pages.dashBoardPage().pageHeader.getText(); 32 | 33 | actual = pages.dashBoardPage().pageHeader.getText(); 34 | Assert.assertEquals("User Management", actual); 35 | break; 36 | case "books": 37 | actual = pages.dashBoardPage().pageHeader.getText(); 38 | Assert.assertEquals("Book Management", actual); 39 | break; 40 | } 41 | } 42 | 43 | @When("I click on {string} link") 44 | public void i_click_on_link(String link) { 45 | switch (link.toLowerCase()) { 46 | case "dashboard": 47 | pages.dashBoardPage().dashboard.click(); 48 | break; 49 | case "users": 50 | pages.dashBoardPage().users.click(); 51 | break; 52 | case "books": 53 | pages.dashBoardPage().books.click(); 54 | break; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/step_definitions/Hooks.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.step_definitions; 2 | 3 | 4 | import com.cybertek.library.utilities.common.Encoder; 5 | import com.cybertek.library.utilities.common.Environment; 6 | import com.cybertek.library.utilities.db.DBUtils; 7 | import com.cybertek.library.utilities.ui.Driver; 8 | import io.cucumber.java.*; 9 | import io.restassured.RestAssured; 10 | import org.openqa.selenium.OutputType; 11 | import org.openqa.selenium.TakesScreenshot; 12 | 13 | import java.util.concurrent.TimeUnit; 14 | 15 | public class Hooks extends BaseStep { 16 | 17 | @Before(order = 0) 18 | public void setUpScenario() { 19 | Driver.getDriver().manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); 20 | // Driver.getDriver().manage().window().fullscreen(); 21 | RestAssured.baseURI = Environment.getProperty("base_url"); 22 | 23 | } 24 | 25 | @Before(value = "@db", order = 1) 26 | public void connect() { 27 | String url = "jdbc:mysql://" + Environment.getProperty("qa2_db_host") + 28 | Environment.getProperty("db_name"); 29 | String username = Environment.getProperty("db_username"); 30 | String password = Environment.getProperty("db_password"); 31 | password = Encoder.decrypt(password); 32 | DBUtils.createConnection(url, username, password); 33 | } 34 | 35 | @After 36 | public void tearDownScenario(Scenario scenario) { 37 | if (scenario.isFailed()) { 38 | // take screenshot using selenium 39 | byte[] screenshot = ((TakesScreenshot) Driver.getDriver()).getScreenshotAs(OutputType.BYTES); 40 | // attach to report 41 | scenario.embed(screenshot, "image/png", scenario.getName()); 42 | } 43 | Driver.closeDriver(); 44 | } 45 | 46 | @After("@db") 47 | public void closeConnection() { 48 | DBUtils.destroy(); 49 | } 50 | 51 | 52 | } -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/step_definitions/LoginStepDefs.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.step_definitions; 2 | 3 | import com.cybertek.library.utilities.common.Encoder; 4 | import com.cybertek.library.utilities.common.Environment; 5 | import com.cybertek.library.utilities.common.LibraryConstants; 6 | import com.cybertek.library.utilities.ui.Driver; 7 | import io.cucumber.java.en.Given; 8 | import io.cucumber.java.en.When; 9 | 10 | public class LoginStepDefs extends BaseStep { 11 | @Given("I am on the login page") 12 | public void i_am_on_the_login_page() { 13 | String url = Environment.getProperty("url"); 14 | Driver.getDriver().get(url); 15 | 16 | } 17 | 18 | @Given("I login to application as a {word}") 19 | public void i_login_to_application_as_a(String user) throws Exception { 20 | String email = null, password = null; 21 | switch (user.toLowerCase()) { 22 | case LibraryConstants.LIBRARIAN: 23 | email = Environment.getProperty("librarian_email"); 24 | password = Environment.getProperty("librarian_password"); 25 | password = Encoder.decrypt(password); 26 | break; 27 | case LibraryConstants.STUDENT: 28 | email = Environment.getProperty("student_email"); 29 | password = Environment.getProperty("student_password"); 30 | password = Encoder.decrypt(password); 31 | break; 32 | default: 33 | throw new Exception("Wrong user type is provided: " + user); 34 | } 35 | pages.loginPage().login(email, password); 36 | } 37 | 38 | @When("I login as a librarian/student") 39 | @When("I login as the new user created using add_user endpoint") 40 | public void i_login_as_the_new_user_created_using_add_user_endpoint() { 41 | Driver.getDriver().get(Environment.getProperty("url")); 42 | String email = user.get("email").toString(); 43 | String password = user.get("password").toString(); 44 | pages.loginPage().login(email, password); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/step_definitions/UserStepDefs.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.step_definitions; 2 | 3 | import com.cybertek.library.utilities.api.Endpoints; 4 | import com.cybertek.library.utilities.api.LibrarianAuthenticationUtility; 5 | import com.cybertek.library.utilities.common.Environment; 6 | import com.cybertek.library.utilities.common.LibraryConstants; 7 | import com.cybertek.library.utilities.common.LibraryUserUtility; 8 | import com.cybertek.library.utilities.ui.BrowserUtils; 9 | import com.cybertek.library.utilities.ui.Driver; 10 | import io.cucumber.java.en.Given; 11 | import io.cucumber.java.en.Then; 12 | import io.cucumber.java.en.When; 13 | import io.restassured.response.Response; 14 | import org.junit.Assert; 15 | import org.openqa.selenium.WebElement; 16 | 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | import static io.restassured.RestAssured.given; 21 | import static org.junit.Assert.*; 22 | import static org.junit.Assert.assertEquals; 23 | 24 | public class UserStepDefs extends BaseStep { 25 | 26 | 27 | @Given("new {word} user is available") 28 | @Given("new {word} is added using the add_user endpoint") 29 | public void new_student_is_added_using_the_add_user_endpoint(String userType) { 30 | // get a token 31 | authenticationUtility = new LibrarianAuthenticationUtility(); 32 | String librarianToken = authenticationUtility.getToken(); 33 | // create new user information 34 | if (userType.equalsIgnoreCase(LibraryConstants.LIBRARIAN)) { 35 | user = LibraryUserUtility.createUser(2); 36 | } else if (userType.equalsIgnoreCase(LibraryConstants.STUDENT)) { 37 | user = LibraryUserUtility.createUser(3); 38 | } 39 | // create using using the add_user 40 | Response response = given(). 41 | header("x-library-token", librarianToken). 42 | formParams(user). 43 | log().all(). 44 | when(). 45 | post(Endpoints.ADD_USER). 46 | prettyPeek(); 47 | response.then().statusCode(200); 48 | user.put("id", response.path("id")); 49 | } 50 | 51 | @When("I search for {string}") 52 | public void i_search_for(String searchString) { 53 | BrowserUtils.waitForClickability(pages.usersPage().search, 5); 54 | pages.usersPage().search.sendKeys(searchString); 55 | BrowserUtils.wait(1); 56 | } 57 | 58 | @Then("table should contain rows with {string}") 59 | public void table_should_contain_rows_with(String expectedString) { 60 | 61 | int size = pages.usersPage().allUserIds.size(); 62 | for (int i = 0; i < size; i++) { 63 | String id = pages.usersPage().allUserIds.get(i).getText().toLowerCase(); 64 | String name = pages.usersPage().allFullNames.get(i).getText().toLowerCase(); 65 | String email = pages.usersPage().allEmails.get(i).getText().toLowerCase(); 66 | 67 | 68 | boolean found = id.contains(expectedString) || 69 | name.contains(expectedString) || 70 | email.contains(expectedString); 71 | assertTrue("Expedted string was not found in table: " + expectedString, found); 72 | } 73 | 74 | } 75 | 76 | @Then("table should have following column names:") 77 | public void table_should_have_following_column_names(List expectedColumnsNames) { 78 | List actualColumnsNames = BrowserUtils.getElementsText(pages.usersPage().columnNames); 79 | assertEquals(expectedColumnsNames, actualColumnsNames); 80 | 81 | } 82 | 83 | @Then("show records default value should be {int}") 84 | public void show_records_default_value_should_be(Integer selected) { 85 | String actual = pages.usersPage().getShowRecords().getFirstSelectedOption().getText(); 86 | Assert.assertEquals(selected + "", actual); 87 | 88 | } 89 | 90 | @Then("show records should have following options:") 91 | public void show_records_should_have_following_options(List options) { 92 | List webElements = pages.usersPage().getShowRecords().getOptions(); 93 | List elementsText = BrowserUtils.getElementsText(webElements); 94 | Assert.assertEquals(options, elementsText); 95 | 96 | } 97 | 98 | @When("I select Show {int} records") 99 | public void i_select_Show_records(Integer option) { 100 | pages.usersPage().getShowRecords().selectByVisibleText(option.toString()); 101 | } 102 | 103 | @Then("the users table must display {int} records") 104 | public void the_users_table_must_display_records(int expectedCount) { 105 | BrowserUtils.wait(1); 106 | int actualCount = pages.usersPage().allRows.size(); 107 | Assert.assertEquals(expectedCount, actualCount); 108 | 109 | } 110 | 111 | } 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/api/AuthenticationUtility.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.api; 2 | 3 | import io.restassured.response.Response; 4 | 5 | import static io.restassured.RestAssured.given; 6 | 7 | public interface AuthenticationUtility { 8 | 9 | Response getLoginResponse(); 10 | 11 | String getToken(); 12 | 13 | String getRedirectUrl(); 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/api/Endpoints.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.api; 2 | 3 | public interface Endpoints { 4 | String ADD_USER = "/add_user"; 5 | String LOGIN = "/login"; 6 | String GET_BOOK_BY_ID = "/get_book_by_id/{id}"; 7 | } 8 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/api/LibrarianAuthenticationUtility.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.api; 2 | 3 | import com.cybertek.library.utilities.common.Encoder; 4 | import com.cybertek.library.utilities.common.Environment; 5 | import io.restassured.response.Response; 6 | 7 | import static io.restassured.RestAssured.given; 8 | 9 | public class LibrarianAuthenticationUtility implements AuthenticationUtility { 10 | private static Response response; 11 | private String token; 12 | private String redirectUrl; 13 | 14 | @Override 15 | public Response getLoginResponse() { 16 | if (response == null) { 17 | String username = Environment.getProperty("librarian_email"); 18 | String password = Environment.getProperty("librarian_password"); 19 | password = Encoder.decrypt(password); 20 | response = given(). 21 | formParam("email", username). 22 | formParam("password", password). 23 | log().all(). 24 | when(). 25 | post(Endpoints.LOGIN).prettyPeek(); 26 | response.then().statusCode(200); 27 | } 28 | return response; 29 | } 30 | 31 | @Override 32 | public String getToken() { 33 | if (token == null) { 34 | token = getLoginResponse().jsonPath().getString("token"); 35 | } 36 | return token; 37 | } 38 | 39 | @Override 40 | public String getRedirectUrl() { 41 | if (redirectUrl == null) { 42 | redirectUrl = getLoginResponse().jsonPath().getString("redirect_uri"); 43 | } 44 | return redirectUrl; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/api/StudentAuthenticationUtility.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.api; 2 | 3 | import com.cybertek.library.utilities.common.Encoder; 4 | import com.cybertek.library.utilities.common.Environment; 5 | import io.restassured.response.Response; 6 | 7 | import static io.restassured.RestAssured.given; 8 | 9 | public class StudentAuthenticationUtility implements AuthenticationUtility { 10 | private static Response response; 11 | private String token; 12 | private String redirectUrl; 13 | 14 | @Override 15 | public Response getLoginResponse() { 16 | if (response == null) { 17 | String username = Environment.getProperty("student_email"); 18 | String password = Environment.getProperty("student_password"); 19 | password = Encoder.decrypt(password); 20 | response = given(). 21 | formParam("email", username). 22 | formParam("password", password). 23 | log().all(). 24 | when(). 25 | post(Endpoints.LOGIN).prettyPeek(); 26 | response.then().statusCode(200); 27 | } 28 | return response; 29 | } 30 | 31 | @Override 32 | public String getToken() { 33 | if (token == null) { 34 | token = response.jsonPath().getString("token"); 35 | } 36 | return token; 37 | } 38 | 39 | @Override 40 | public String getRedirectUrl() { 41 | if (redirectUrl == null) { 42 | redirectUrl = response.jsonPath().getString("redirect_uri"); 43 | } 44 | return redirectUrl; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/common/Encoder.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.common; 2 | 3 | import org.apache.commons.codec.binary.Base64; 4 | 5 | import javax.crypto.Cipher; 6 | import javax.crypto.spec.IvParameterSpec; 7 | import javax.crypto.spec.SecretKeySpec; 8 | import java.nio.charset.StandardCharsets; 9 | 10 | /* 11 | This is a class example to show how Cipher works. Do not use this class at work. Use proper encryption libraries such as spring-security-crypto 12 | */ 13 | public class Encoder { 14 | private static String key = "AD#$ouwed32ljads"; // 128 bit key 15 | private static String initVector = "randomstringvect"; // 16 bytes IV 16 | 17 | public static String encrypt(String value) { 18 | try { 19 | IvParameterSpec iv = new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8)); 20 | SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); 21 | 22 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); 23 | cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 24 | 25 | byte[] encrypted = cipher.doFinal(value.getBytes()); 26 | 27 | return Base64.encodeBase64String(encrypted); 28 | } catch (Exception ex) { 29 | ex.printStackTrace(); 30 | } 31 | 32 | return null; 33 | } 34 | 35 | public static String decrypt(String encrypted) { 36 | try { 37 | IvParameterSpec iv = new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8)); 38 | SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); 39 | 40 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); 41 | cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 42 | 43 | byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted)); 44 | 45 | return new String(original); 46 | } catch (Exception ex) { 47 | ex.printStackTrace(); 48 | } 49 | 50 | return null; 51 | } 52 | 53 | public static void main(String[] args) { 54 | 55 | String encyrpted = encrypt("Pzi75akktLC4BoI9"); 56 | System.out.println(encyrpted); 57 | String decrypted = decrypt( encyrpted); 58 | System.out.println(decrypted); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/common/Environment.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.common; 2 | 3 | 4 | import java.io.FileInputStream; 5 | import java.util.Properties; 6 | 7 | public class Environment { 8 | private static Properties properties; 9 | 10 | static { 11 | try { 12 | // LOAD GENERAL PROPERTIES 13 | String path = "configuration.properties"; 14 | FileInputStream input = new FileInputStream(path); 15 | 16 | properties = new Properties(); 17 | properties.load(input); 18 | 19 | // LOAD ENVIRONMENT SPECIFIC PROPERTIES 20 | if (System.getProperty("env") != null) { 21 | path = "src/test/resources/env/" + System.getProperty("env") + ".properties"; 22 | } else { 23 | path = "src/test/resources/env/" + properties.getProperty("env") + ".properties"; 24 | } 25 | input = new FileInputStream(path); 26 | properties.load(input); 27 | 28 | 29 | input.close(); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | 33 | } 34 | } 35 | 36 | public static String getProperty(String keyName) { 37 | return properties.getProperty(keyName); 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/common/LibraryConstants.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.common; 2 | 3 | public interface LibraryConstants { 4 | String STUDENT = "student"; 5 | String LIBRARIAN = "librarian"; 6 | String DASHBOARD = "dashboard"; 7 | String USERS = "users"; 8 | String BOOKS = "books"; 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/common/LibraryUserUtility.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.common; 2 | 3 | import com.github.javafaker.Faker; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class LibraryUserUtility { 9 | /** 10 | * take user type create map that contains student or librarian user form data 11 | * @param userGroup 12 | * 13 | * @return 14 | * user map 15 | */ 16 | public static Map createUser(int userGroup){ 17 | Faker faker = new Faker(); 18 | String fullName = faker.name().fullName(); 19 | String usernameEmail = faker.name().username(); 20 | String companyUrl = faker.company().url().substring(4); 21 | String email = usernameEmail + "@"+companyUrl; 22 | String address = faker.address().fullAddress(); 23 | Map user = new HashMap<>(); 24 | user.put("full_name", fullName); 25 | user.put("email", email); 26 | user.put("password", faker.number().digits(5)); 27 | user.put("user_group_id", userGroup); 28 | user.put("status", "active"); 29 | user.put("start_date", "2020-05-05"); 30 | user.put("end_date", "2021-05-05"); 31 | user.put("address", address); 32 | return user; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/db/DBUtils.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.db; 2 | 3 | import java.sql.*; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public class DBUtils { 10 | private static Connection connection; 11 | private static Statement statement; 12 | private static ResultSet resultSet; 13 | 14 | 15 | public static void createConnection(String DB_URL, String DB_USERNAME, String DB_PASSWORD) { 16 | try { 17 | connection = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD); 18 | } catch (SQLException e) { 19 | // TODO Auto-generated catch block 20 | e.printStackTrace(); 21 | } 22 | } 23 | 24 | public static void destroy() { 25 | try { 26 | if (resultSet != null) { 27 | resultSet.close(); 28 | } 29 | if (statement != null) { 30 | statement.close(); 31 | } 32 | if (connection != null) { 33 | connection.close(); 34 | } 35 | } catch (SQLException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | /** 41 | * @param query 42 | * @return returns a single cell value. If the results in multiple rows and/or 43 | * columns of data, only first column of the first row will be returned. 44 | * The rest of the data will be ignored 45 | */ 46 | public static Object getCellValue(String query) { 47 | return getQueryResultList(query).get(0).get(0); 48 | } 49 | 50 | /** 51 | * @param query 52 | * @return returns a list of Strings which represent a row of data. If the query 53 | * results in multiple rows and/or columns of data, only first row will 54 | * be returned. The rest of the data will be ignored 55 | */ 56 | public static List getRowList(String query) { 57 | return getQueryResultList(query).get(0); 58 | } 59 | 60 | /** 61 | * @param query 62 | * @return returns a map which represent a row of data where key is the column 63 | * name. If the query results in multiple rows and/or columns of data, 64 | * only first row will be returned. The rest of the data will be ignored 65 | */ 66 | public static Map getRowMap(String query) { 67 | return getQueryResultMap(query).get(0); 68 | } 69 | 70 | /** 71 | * @param query 72 | * @return returns query result in a list of lists where outer list represents 73 | * collection of rows and inner lists represent a single row 74 | */ 75 | public static List> getQueryResultList(String query) { 76 | executeQuery(query); 77 | List> rowList = new ArrayList<>(); 78 | ResultSetMetaData rsmd; 79 | try { 80 | rsmd = resultSet.getMetaData(); 81 | while (resultSet.next()) { 82 | List row = new ArrayList<>(); 83 | for (int i = 1; i <= rsmd.getColumnCount(); i++) { 84 | row.add(resultSet.getObject(i)); 85 | } 86 | rowList.add(row); 87 | } 88 | } catch (SQLException e) { 89 | // TODO Auto-generated catch block 90 | e.printStackTrace(); 91 | } 92 | return rowList; 93 | } 94 | 95 | /** 96 | * @param query 97 | * @param column 98 | * @return list of values of a single column from the result set 99 | */ 100 | public static List getColumnData(String query, String column) { 101 | executeQuery(query); 102 | List rowList = new ArrayList<>(); 103 | ResultSetMetaData rsmd; 104 | try { 105 | rsmd = resultSet.getMetaData(); 106 | while (resultSet.next()) { 107 | rowList.add(resultSet.getObject(column)); 108 | } 109 | } catch (SQLException e) { 110 | // TODO Auto-generated catch block 111 | e.printStackTrace(); 112 | } 113 | return rowList; 114 | } 115 | 116 | /** 117 | * @param query 118 | * @return returns query result in a list of maps where the list represents 119 | * collection of rows and a map represents represent a single row with 120 | * key being the column name 121 | */ 122 | public static List> getQueryResultMap(String query) { 123 | executeQuery(query); 124 | List> rowList = new ArrayList<>(); 125 | ResultSetMetaData rsmd; 126 | try { 127 | rsmd = resultSet.getMetaData(); 128 | while (resultSet.next()) { 129 | Map colNameValueMap = new HashMap<>(); 130 | for (int i = 1; i <= rsmd.getColumnCount(); i++) { 131 | colNameValueMap.put(rsmd.getColumnName(i), resultSet.getObject(i)); 132 | } 133 | rowList.add(colNameValueMap); 134 | } 135 | } catch (SQLException e) { 136 | // TODO Auto-generated catch block 137 | e.printStackTrace(); 138 | } 139 | return rowList; 140 | } 141 | 142 | /** 143 | * @param query 144 | * @return List of columns returned in result set 145 | */ 146 | public static List getColumnNames(String query) { 147 | executeQuery(query); 148 | List columns = new ArrayList<>(); 149 | ResultSetMetaData rsmd; 150 | try { 151 | rsmd = resultSet.getMetaData(); 152 | int columnCount = rsmd.getColumnCount(); 153 | for (int i = 1; i <= columnCount; i++) { 154 | columns.add(rsmd.getColumnName(i)); 155 | } 156 | } catch (SQLException e) { 157 | // TODO Auto-generated catch block 158 | e.printStackTrace(); 159 | } 160 | return columns; 161 | } 162 | 163 | private static void executeQuery(String query) { 164 | try { 165 | statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); 166 | } catch (SQLException e) { 167 | // TODO Auto-generated catch block 168 | e.printStackTrace(); 169 | } 170 | try { 171 | resultSet = statement.executeQuery(query); 172 | } catch (SQLException e) { 173 | // TODO Auto-generated catch block 174 | e.printStackTrace(); 175 | } 176 | } 177 | 178 | /** 179 | * shows the row count of the most recent query result 180 | * @return 181 | * @throws Exception 182 | */ 183 | public static int getRowCount() throws Exception { 184 | resultSet.last(); 185 | int rowCount = resultSet.getRow(); 186 | return rowCount; 187 | } 188 | } -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/ui/BrowserUtils.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.ui; 2 | 3 | import com.google.common.base.Function; 4 | import org.junit.Assert; 5 | import org.openqa.selenium.*; 6 | import org.openqa.selenium.JavascriptExecutor; 7 | import org.openqa.selenium.WebElement; 8 | import org.openqa.selenium.interactions.Actions; 9 | import org.openqa.selenium.support.ui.*; 10 | 11 | import java.time.Duration; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.NoSuchElementException; 15 | import java.util.Random; 16 | 17 | import static org.junit.Assert.assertTrue; 18 | 19 | 20 | public class BrowserUtils { 21 | 22 | public static void wait(int secs) { 23 | try { 24 | Thread.sleep(1000 * secs); 25 | } catch (InterruptedException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | /* 31 | * switches to new window by the exact title 32 | * returns to original window if windows with given title not found 33 | */ 34 | public static void switchToWindow(String targetTitle) { 35 | String origin = Driver.getDriver().getWindowHandle(); 36 | for (String handle : Driver.getDriver().getWindowHandles()) { 37 | Driver.getDriver().switchTo().window(handle); 38 | if (Driver.getDriver().getTitle().equals(targetTitle)) { 39 | return; 40 | } 41 | } 42 | Driver.getDriver().switchTo().window(origin); 43 | } 44 | 45 | public static void hover(WebElement element) { 46 | Actions actions = new Actions(Driver.getDriver()); 47 | actions.moveToElement(element).perform(); 48 | } 49 | 50 | /** 51 | * return a list of string from a list of web elements 52 | * 53 | * @param list 54 | * @return 55 | */ 56 | public static List getElementsText(List list) { 57 | List elemTexts = new ArrayList<>(); 58 | for (WebElement el : list) { 59 | elemTexts.add(el.getText()); 60 | } 61 | return elemTexts; 62 | } 63 | 64 | public static List getElementsText(By locator) { 65 | 66 | List elems = Driver.getDriver().findElements(locator); 67 | List elemTexts = new ArrayList<>(); 68 | 69 | for (WebElement el : elems) { 70 | elemTexts.add(el.getText()); 71 | } 72 | return elemTexts; 73 | } 74 | 75 | public static WebElement waitForVisibility(WebElement element, int timeToWaitInSec) { 76 | WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeToWaitInSec); 77 | return wait.until(ExpectedConditions.visibilityOf(element)); 78 | } 79 | 80 | public static WebElement waitForVisibility(By locator, int timeout) { 81 | WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeout); 82 | return wait.until(ExpectedConditions.visibilityOfElementLocated(locator)); 83 | } 84 | 85 | public static WebElement waitForClickability(WebElement element, int timeout) { 86 | WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeout); 87 | return wait.until(ExpectedConditions.elementToBeClickable(element)); 88 | } 89 | 90 | public static WebElement waitForClickability(By locator, int timeout) { 91 | WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeout); 92 | return wait.until(ExpectedConditions.elementToBeClickable(locator)); 93 | } 94 | 95 | public static void waitForPageToLoad(long timeOutInSeconds) { 96 | ExpectedCondition expectation = new ExpectedCondition() { 97 | public Boolean apply(WebDriver driver) { 98 | return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete"); 99 | } 100 | }; 101 | try { 102 | WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeOutInSeconds); 103 | wait.until(expectation); 104 | } catch (Throwable error) { 105 | error.printStackTrace(); 106 | } 107 | } 108 | 109 | public static WebElement fluentWait(final WebElement webElement, int timeinsec) { 110 | FluentWait wait = new FluentWait(Driver.getDriver()) 111 | .withTimeout(Duration.ofSeconds(timeinsec)) 112 | .pollingEvery(Duration.ofMillis(500)) 113 | .ignoring(NoSuchElementException.class); 114 | WebElement element = wait.until(new Function() { 115 | public WebElement apply(WebDriver driver) { 116 | return webElement; 117 | } 118 | }); 119 | return element; 120 | } 121 | 122 | /** 123 | * Verifies whether the element matching the provided locator is displayed on page 124 | * fails if the element matching the provided locator is not found or not displayed 125 | * 126 | * @param by 127 | */ 128 | public static void verifyElementDisplayed(By by) { 129 | try { 130 | assertTrue("Element not visible: " + by, Driver.getDriver().findElement(by).isDisplayed()); 131 | } catch (NoSuchElementException e) { 132 | Assert.fail("Element not found: " + by); 133 | 134 | } 135 | } 136 | 137 | /** 138 | * Verifies whether the element is displayed on page 139 | * fails if the element is not found or not displayed 140 | * 141 | * @param element 142 | */ 143 | public static void verifyElementDisplayed(WebElement element) { 144 | try { 145 | assertTrue("Element not visible: " + element, element.isDisplayed()); 146 | } catch (NoSuchElementException e) { 147 | Assert.fail("Element not found: " + element); 148 | 149 | } 150 | } 151 | 152 | 153 | /** 154 | * Waits for element to be not stale 155 | * 156 | * @param element 157 | */ 158 | public void waitForStaleElement(WebElement element) { 159 | int y = 0; 160 | while (y <= 15) { 161 | if (y == 1) 162 | try { 163 | element.isDisplayed(); 164 | break; 165 | } catch (StaleElementReferenceException st) { 166 | y++; 167 | try { 168 | Thread.sleep(300); 169 | } catch (InterruptedException e) { 170 | e.printStackTrace(); 171 | } 172 | } catch (WebDriverException we) { 173 | y++; 174 | try { 175 | Thread.sleep(300); 176 | } catch (InterruptedException e) { 177 | e.printStackTrace(); 178 | } 179 | } 180 | } 181 | } 182 | 183 | /** 184 | * Selects a random value from a dropdown list and returns the selected Web Element 185 | * 186 | * @param select 187 | * @return 188 | */ 189 | public WebElement selectRandomTextFromDropdown(Select select) { 190 | Random random = new Random(); 191 | List weblist = select.getOptions(); 192 | int optionIndex = 1 + random.nextInt(weblist.size() - 1); 193 | select.selectByIndex(optionIndex); 194 | return select.getFirstSelectedOption(); 195 | } 196 | 197 | /** 198 | * Clicks on an element using JavaScript 199 | * 200 | * @param element 201 | */ 202 | public void clickWithJS(WebElement element) { 203 | ((JavascriptExecutor) Driver.getDriver()).executeScript("arguments[0].scrollIntoView(true);", element); 204 | ((JavascriptExecutor) Driver.getDriver()).executeScript("arguments[0].click();", element); 205 | } 206 | 207 | 208 | /** 209 | * Scrolls down to an element using JavaScript 210 | * 211 | * @param element 212 | */ 213 | public void scrollToElement(WebElement element) { 214 | ((JavascriptExecutor) Driver.getDriver()).executeScript("arguments[0].scrollIntoView(true);", element); 215 | } 216 | 217 | /** 218 | * Performs double click action on an element 219 | * 220 | * @param element 221 | */ 222 | public void doubleClick(WebElement element) { 223 | new Actions(Driver.getDriver()).doubleClick(element).build().perform(); 224 | } 225 | 226 | /** 227 | * Changes the HTML attribute of a Web Element to the given value using JavaScript 228 | * 229 | * @param element 230 | * @param attributeName 231 | * @param attributeValue 232 | */ 233 | public void setAttribute(WebElement element, String attributeName, String attributeValue) { 234 | ((JavascriptExecutor) Driver.getDriver()).executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", element, attributeName, attributeValue); 235 | } 236 | 237 | /** 238 | * @param element 239 | * @param check 240 | */ 241 | public void selectCheckBox(WebElement element, boolean check) { 242 | if (check) { 243 | if (!element.isSelected()) { 244 | element.click(); 245 | } 246 | } else { 247 | if (element.isSelected()) { 248 | element.click(); 249 | } 250 | } 251 | } 252 | 253 | } 254 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/ui/Driver.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.ui; 2 | 3 | 4 | import com.cybertek.library.utilities.common.Environment; 5 | import io.github.bonigarcia.wdm.WebDriverManager; 6 | import org.openqa.selenium.Platform; 7 | import org.openqa.selenium.WebDriver; 8 | import org.openqa.selenium.WebDriverException; 9 | import org.openqa.selenium.chrome.ChromeDriver; 10 | import org.openqa.selenium.chrome.ChromeOptions; 11 | import org.openqa.selenium.edge.EdgeDriver; 12 | import org.openqa.selenium.firefox.FirefoxDriver; 13 | import org.openqa.selenium.firefox.FirefoxOptions; 14 | import org.openqa.selenium.ie.InternetExplorerDriver; 15 | import org.openqa.selenium.remote.DesiredCapabilities; 16 | import org.openqa.selenium.remote.RemoteWebDriver; 17 | import org.openqa.selenium.safari.SafariDriver; 18 | import org.openqa.selenium.safari.SafariOptions; 19 | 20 | import java.net.MalformedURLException; 21 | import java.net.URL; 22 | 23 | 24 | public class Driver { 25 | private static final String GRID_URL = "http://100.26.171.118:4444/wd/hub"; 26 | public static final String USERNAME = "vasylfomiuk1"; 27 | public static final String AUTOMATE_KEY = "shPeppvXmzdSTZqAZH3f"; 28 | public static final String URL = "https://" + USERNAME + ":" + AUTOMATE_KEY + "@hub-cloud.browserstack.com/wd/hub"; 29 | 30 | private Driver() { 31 | } 32 | 33 | private static ThreadLocal driverPool = new ThreadLocal<>(); 34 | 35 | 36 | public static synchronized WebDriver getDriver() { 37 | if (driverPool.get() == null) { 38 | 39 | // check the command line argument browser. if it has value, use that value 40 | // if no browser value is passed from command line, the user properties file 41 | // mvn test -Dbrowser=remote-chrome 42 | // mvn test -Dbrowser=remote-firefox 43 | // mvn test -Dcucumber.filter.tags=@regression -Dbrowser=remote-firefox 44 | String browser = System.getProperty("browser") != null ? System.getProperty("browser") : Environment.getProperty("browser"); 45 | 46 | switch (browser) { 47 | case "chrome": 48 | WebDriverManager.chromedriver().setup(); 49 | driverPool.set(new ChromeDriver()); 50 | break; 51 | case "chrome-headless": 52 | WebDriverManager.chromedriver().setup(); 53 | driverPool.set(new ChromeDriver(new ChromeOptions().setHeadless(true))); 54 | break; 55 | case "firefox": 56 | WebDriverManager.firefoxdriver().setup(); 57 | driverPool.set(new FirefoxDriver()); 58 | break; 59 | case "firefox-headless": 60 | WebDriverManager.firefoxdriver().setup(); 61 | driverPool.set(new FirefoxDriver(new FirefoxOptions().setHeadless(true))); 62 | break; 63 | case "ie": 64 | if (!System.getProperty("os.name").toLowerCase().contains("windows")) 65 | throw new WebDriverException("Your OS doesn't support Internet Explorer"); 66 | WebDriverManager.iedriver().setup(); 67 | driverPool.set(new InternetExplorerDriver()); 68 | break; 69 | 70 | case "edge": 71 | if (!System.getProperty("os.name").toLowerCase().contains("windows")) 72 | throw new WebDriverException("Your OS doesn't support Edge"); 73 | WebDriverManager.edgedriver().setup(); 74 | driverPool.set(new EdgeDriver()); 75 | break; 76 | 77 | case "safari": 78 | if (!System.getProperty("os.name").toLowerCase().contains("mac")) 79 | throw new WebDriverException("Your OS doesn't support Safari"); 80 | WebDriverManager.getInstance(SafariDriver.class).setup(); 81 | driverPool.set(new SafariDriver()); 82 | break; 83 | 84 | case "remote-chrome": 85 | try { 86 | URL url = new URL(GRID_URL); 87 | ChromeOptions chromeOptions = new ChromeOptions(); 88 | driverPool.set(new RemoteWebDriver(url, chromeOptions)); 89 | } catch (MalformedURLException e) { 90 | e.printStackTrace(); 91 | } 92 | break; 93 | case "remote-firefox-linux": 94 | try { 95 | URL url = new URL(GRID_URL); 96 | FirefoxOptions firefoxOptions = new FirefoxOptions(); 97 | firefoxOptions.setCapability("platform", Platform.LINUX); 98 | driverPool.set(new RemoteWebDriver(url, firefoxOptions)); 99 | } catch (MalformedURLException e) { 100 | e.printStackTrace(); 101 | } 102 | case "remote-firefox-win": 103 | try { 104 | URL url = new URL(GRID_URL); 105 | FirefoxOptions firefoxOptions = new FirefoxOptions(); 106 | firefoxOptions.setCapability("versopm", "asd"); 107 | driverPool.set(new RemoteWebDriver(url, firefoxOptions)); 108 | } catch (MalformedURLException e) { 109 | e.printStackTrace(); 110 | } 111 | case "remote-safari": 112 | try { 113 | URL url = new URL(GRID_URL); 114 | SafariOptions s = new SafariOptions(); 115 | driverPool.set(new RemoteWebDriver(url, s)); 116 | } catch (MalformedURLException e) { 117 | e.printStackTrace(); 118 | } 119 | case "browser-stack-chrome": 120 | try { 121 | URL url = new URL(URL); 122 | DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); 123 | desiredCapabilities.setCapability("browser", "Chrome"); 124 | desiredCapabilities.setCapability("browser_version", "83.0"); 125 | desiredCapabilities.setCapability("os", "Windows"); 126 | desiredCapabilities.setCapability("os_version", "10"); 127 | desiredCapabilities.setCapability("resolution", "1920x1080"); 128 | desiredCapabilities.setCapability("name", "Library Automation"); 129 | driverPool.set(new RemoteWebDriver(url, desiredCapabilities)); 130 | } catch (MalformedURLException e) { 131 | e.printStackTrace(); 132 | } 133 | break; 134 | case "browser-stack-android": 135 | try { 136 | URL url = new URL(URL); 137 | DesiredCapabilities caps = new DesiredCapabilities(); 138 | caps.setCapability("browserName", "android"); 139 | caps.setCapability("device", "Samsung Galaxy S20"); 140 | caps.setCapability("realMobile", "true"); 141 | caps.setCapability("os_version", "10.0"); 142 | caps.setCapability("name", "Library Automation"); 143 | driverPool.set(new RemoteWebDriver(url, caps)); 144 | } catch (MalformedURLException e) { 145 | e.printStackTrace(); 146 | } 147 | break; 148 | } 149 | } 150 | return driverPool.get(); 151 | } 152 | 153 | public static void closeDriver() { 154 | if (driverPool.get() != null) { 155 | driverPool.get().quit(); 156 | driverPool.remove(); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/test/java/com/cybertek/library/utilities/ui/Pages.java: -------------------------------------------------------------------------------- 1 | package com.cybertek.library.utilities.ui; 2 | 3 | import com.cybertek.library.pages.BooksPage; 4 | import com.cybertek.library.pages.DashBoardPage; 5 | import com.cybertek.library.pages.LoginPage; 6 | import com.cybertek.library.pages.UsersPage; 7 | 8 | public class Pages { 9 | private DashBoardPage dashBoardPage; 10 | private LoginPage loginPage; 11 | private UsersPage usersPage; 12 | private BooksPage booksPage; 13 | 14 | public Pages() { 15 | this.dashBoardPage = new DashBoardPage(); 16 | this.loginPage = new LoginPage(); 17 | this.usersPage = new UsersPage(); 18 | this.booksPage = new BooksPage(); 19 | } 20 | 21 | public DashBoardPage dashBoardPage() { 22 | return dashBoardPage; 23 | } 24 | 25 | public LoginPage loginPage() { 26 | return loginPage; 27 | } 28 | 29 | public UsersPage usersPage() { 30 | return usersPage; 31 | } 32 | 33 | public BooksPage booksPage() { 34 | return booksPage; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/resources/env/qa1.properties: -------------------------------------------------------------------------------- 1 | url=http://library1.cybertekschool.com/ 2 | librarian_email=librarian22@library 3 | librarian_password=jrwz8qDdYVJKcTAX+IpakA== 4 | student_email=student6@library 5 | student_password=SNK6Oi7RrxuR4BdHd3iuxA== 6 | db_host=ec2-18-233-97-71.compute-1.amazonaws.com/ 7 | db_name=library1 8 | db_username=library1_client 9 | db_password=j/DiXcOD1TDMy76E42JPxQVJKEES/YQ9jyMPk4Q29q8= 10 | base_url=http://library1.cybertekschool.com/rest/v1 11 | -------------------------------------------------------------------------------- /src/test/resources/env/qa2.properties: -------------------------------------------------------------------------------- 1 | url=http://library2.cybertekschool.com/ 2 | librarian_email=librarian21@library 3 | librarian_password=v+SXURngD/jVGNHyCrnZQA== 4 | student_email=student22@library 5 | student_password=hks3L1ehE/GT1ulasQABFw== 6 | db_host=ec2-18-233-97-71.compute-1.amazonaws.com/ 7 | db_name=library2 8 | db_username=library2_client 9 | db_password=8C7uaEAH1Duq3bqZEprLbnxXECdSf7qMwEAKNP4FUHQ= 10 | base_url=http://library2.cybertekschool.com/rest/v1 11 | -------------------------------------------------------------------------------- /src/test/resources/env/qa3.properties: -------------------------------------------------------------------------------- 1 | url=http://library3.cybertekschool.com/ 2 | librarian_email=librarian21@library 3 | librarian_password=v+SXURngD/jVGNHyCrnZQA== 4 | student_email=student22@library 5 | student_password=hks3L1ehE/GT1ulasQABFw== 6 | db_host=ec2-18-233-97-71.compute-1.amazonaws.com/ 7 | db_name=library3 8 | db_username=library3_client 9 | db_password=Sl76Lms7WLCsQ79tgMxZf+iIIE0tj1f00KmHRv1JGdo= 10 | base_url=http://library3.cybertekschool.com/rest/v1 11 | -------------------------------------------------------------------------------- /src/test/resources/features/AddUserAPITests.feature: -------------------------------------------------------------------------------- 1 | @smoke @add_user @lib-433 2 | Feature: Add user end point test 3 | 4 | Scenario: add student using add user service 5 | Given new student is added using the add_user endpoint 6 | When I login as the new user created using add_user endpoint 7 | Then "Books" page should be displayed 8 | 9 | Scenario: add student using add user service 10 | Given new librarian is added using the add_user endpoint 11 | When I login as the new user created using add_user endpoint 12 | Then "Dashboard" page should be displayed 13 | -------------------------------------------------------------------------------- /src/test/resources/features/BookInformationValidation.feature: -------------------------------------------------------------------------------- 1 | @regression @lib-324 2 | Feature: Book information 3 | 4 | @db 5 | Scenario: Verify book information with db 6 | Given I am on the login page 7 | And I login to application as a librarian 8 | And I navigate to "Books" page 9 | When I open book The kite runner 10 | Then book information must match the database for The kite runner 11 | 12 | @db 13 | Scenario: Book categories validation 14 | Given I am on the login page 15 | And I login to application as a librarian 16 | When I navigate to "Books" page 17 | Then book categories must match book_categories table from db -------------------------------------------------------------------------------- /src/test/resources/features/PageNavigation.feature: -------------------------------------------------------------------------------- 1 | @smoke @lib-132 @navigation 2 | Feature: Page navigation links 3 | 4 | Scenario Outline: Go go 5 | Given I am on the login page 6 | And I login to application as a librarian 7 | When I click on "" link 8 | Then "" page should be displayed 9 | 10 | Examples: 11 | | link | page | 12 | | Books | books | 13 | | Dashboard | dashboard | 14 | | Users | users | 15 | -------------------------------------------------------------------------------- /src/test/resources/features/SearchResults.feature: -------------------------------------------------------------------------------- 1 | @lib-2423 @smoke @regression 2 | Feature: Search functionality on the users page 3 | 4 | Background: 5 | Given new librarian user is available 6 | And I login as a librarian 7 | And I click on "Users" link 8 | 9 | Scenario: Search accuracy 10 | When I search for "test" 11 | Then table should contain rows with "test" 12 | 13 | Scenario: Table columns names 14 | Then table should have following column names: 15 | | Actions | 16 | | User ID | 17 | | Full Name | 18 | | Email | 19 | | Group | 20 | | Status | -------------------------------------------------------------------------------- /src/test/resources/features/UserTable.feature: -------------------------------------------------------------------------------- 1 | @show_records @regression @lib-7031 2 | Feature: Show records functionality on user page 3 | 4 | Background: 5 | Given I am on the login page 6 | And I login to application as a librarian 7 | 8 | @smoke 9 | Scenario: verify default values in Users page 10 | When I click on "Users" link 11 | Then show records default value should be 10 12 | And show records should have following options: 13 | | 5 | 14 | | 10 | 15 | | 15 | 16 | | 50 | 17 | | 100 | 18 | | 200 | 19 | | 500 | 20 | 21 | Scenario Outline: Show records for options 22 | And I click on "Users" link 23 | When I select Show records 24 | Then show records default value should be 25 | And the users table must display records 26 | 27 | Examples: 28 | | count | 29 | | 5 | 30 | | 10 | 31 | | 15 | 32 | | 50 | 33 | | 100 | 34 | -------------------------------------------------------------------------------- /src/test/resources/test-data/Library QA 1 user data.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybertek-Mentors/syslibrary-cucumber-framework/06eaff8452df8c9be61332cd389fc59e4abfe20f/src/test/resources/test-data/Library QA 1 user data.pdf -------------------------------------------------------------------------------- /src/test/resources/test-data/Library QA 2 user data.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybertek-Mentors/syslibrary-cucumber-framework/06eaff8452df8c9be61332cd389fc59e4abfe20f/src/test/resources/test-data/Library QA 2 user data.xlsx --------------------------------------------------------------------------------