diff --git a/api-tests-module/pom.xml b/api-tests-module/pom.xml
new file mode 100644
index 0000000..cbede40
--- /dev/null
+++ b/api-tests-module/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ school-2016
+ ru.qatools.school
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ api-tests-module
+ API Tests
+
+
+
+ com.jayway.restassured
+ rest-assured
+ 2.9.0
+
+
+ com.squareup.retrofit2
+ retrofit
+ 2.0.2
+
+
+ com.google.code.gson
+ gson
+ 2.6.2
+
+
+ com.squareup.retrofit2
+ converter-gson
+ 2.0.2
+
+
+ org.hamcrest
+ hamcrest-all
+
+
+ ru.yandex.qatools.allure
+ allure-junit-adaptor
+
+
+ ru.qatools.school
+ dbclient-module
+ 1.0-SNAPSHOT
+
+
+ ru.yandex.qatools.matchers
+ collection-matchers
+ 1.3
+
+
+
+
\ No newline at end of file
diff --git a/api-tests-module/src/test/java/ru/qatools/school/Responses/CitiesResponse.java b/api-tests-module/src/test/java/ru/qatools/school/Responses/CitiesResponse.java
new file mode 100644
index 0000000..f35b949
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/Responses/CitiesResponse.java
@@ -0,0 +1,10 @@
+package ru.qatools.school.Responses;
+
+/**
+ * @author ava1on
+ */
+public class CitiesResponse {
+
+ public CitiesResponse() {
+ }
+}
diff --git a/api-tests-module/src/test/java/ru/qatools/school/Responses/SuggestResponse.java b/api-tests-module/src/test/java/ru/qatools/school/Responses/SuggestResponse.java
new file mode 100644
index 0000000..699b312
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/Responses/SuggestResponse.java
@@ -0,0 +1,12 @@
+package ru.qatools.school.Responses;
+
+/**
+ * @author ava1on
+ */
+public class SuggestResponse {
+ private int id;
+
+ public SuggestResponse(int id){
+ this.id = id;
+ }
+}
diff --git a/api-tests-module/src/test/java/ru/qatools/school/Responses/TemperatureValues.java b/api-tests-module/src/test/java/ru/qatools/school/Responses/TemperatureValues.java
new file mode 100644
index 0000000..965a8c4
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/Responses/TemperatureValues.java
@@ -0,0 +1,16 @@
+package ru.qatools.school.Responses;
+
+/**
+ * @author ava1on
+ */
+public class TemperatureValues {
+ private double value;
+
+ public TemperatureValues(double value) {
+ this.value = value;
+ }
+
+ public double getValue() {
+ return value;
+ }
+}
diff --git a/api-tests-module/src/test/java/ru/qatools/school/Responses/WeatherResponse.java b/api-tests-module/src/test/java/ru/qatools/school/Responses/WeatherResponse.java
new file mode 100644
index 0000000..219e4b1
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/Responses/WeatherResponse.java
@@ -0,0 +1,20 @@
+package ru.qatools.school.Responses;
+
+/**
+ * @author ava1on
+ */
+public class WeatherResponse {
+ private TemperatureValues[] temperatures;
+
+ public WeatherResponse(TemperatureValues[] temperatures) {
+ this.temperatures = temperatures;
+ }
+
+ public TemperatureValues[] getTemperatures() {
+ return temperatures;
+ }
+
+ public Double recalculateCelsiusToFahrenheit(){
+ return (this.getTemperatures()[0].getValue()*9/5+32);
+ }
+}
diff --git a/api-tests-module/src/test/java/ru/qatools/school/apitests/DbAPITest.java b/api-tests-module/src/test/java/ru/qatools/school/apitests/DbAPITest.java
new file mode 100644
index 0000000..1ec7df2
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/apitests/DbAPITest.java
@@ -0,0 +1,48 @@
+package ru.qatools.school.apitests;
+
+import org.apache.http.HttpStatus;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import ru.qatools.school.DbClient;
+import ru.qatools.school.rules.DbClientRule;
+import ru.yandex.qatools.allure.annotations.Title;
+
+import java.util.List;
+
+import static com.jayway.restassured.RestAssured.given;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static ru.qatools.school.data.Constants.*;
+
+/**
+ * @author ava1on
+ */
+public class DbAPITest {
+ private DbClient dbClient;
+
+ @Rule
+ public DbClientRule dbClientRule = new DbClientRule();
+
+ @Before
+ public void setupDbConnection(){
+ dbClient = dbClientRule.getDbClient();
+ }
+
+ @Test
+ @Title("Списки городов, полученные через API и Database, должны совпадать")
+ public void apiResponseShouldMatchDatabaseData(){
+ List ids =
+ given()
+ .baseUri(BASE_URL)
+ .param(QUERY_PARAMETER, CITYNAME_PART)
+ .when()
+ .get(SUGGEST_REQUEST)
+ .then()
+ .assertThat().statusCode(HttpStatus.SC_OK)
+ .and().extract().body().path("id");
+ assertThat("Полученные через API данные не соответствуют Database", ids,
+ is(dbClient.getCitiesByNamePart(CITYNAME_PART)));
+ }
+}
diff --git a/api-tests-module/src/test/java/ru/qatools/school/apitests/RestAssuredAPITests.java b/api-tests-module/src/test/java/ru/qatools/school/apitests/RestAssuredAPITests.java
new file mode 100644
index 0000000..4f9bd6b
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/apitests/RestAssuredAPITests.java
@@ -0,0 +1,51 @@
+package ru.qatools.school.apitests;
+
+import org.apache.http.HttpStatus;
+import org.junit.Test;
+import ru.qatools.school.Responses.CitiesResponse;
+import ru.qatools.school.Responses.WeatherResponse;
+import ru.yandex.qatools.allure.annotations.Title;
+
+import static com.jayway.restassured.RestAssured.given;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.closeTo;
+import static org.hamcrest.Matchers.is;
+import static ru.qatools.school.data.Constants.*;
+
+/**
+ * @author ava1on
+ */
+public class RestAssuredAPITests {
+
+ @Test
+ @Title("Должны получить заданное в параметре количество городов в ответе")
+ public void shouldReturnRequestedNumberOfCities(){
+ CitiesResponse[] citiesArray =
+ given().
+ baseUri(BASE_URL).
+ param(LIMIT_PARAMETER, LIMIT_VALUE).
+ when().
+ get(CITIES_REQUEST).
+ then().statusCode(HttpStatus.SC_OK).
+ and().extract().
+ body().as(CitiesResponse[].class);
+ assertThat("Неверное количество городов в ответе", citiesArray.length, is(LIMIT_VALUE));
+ }
+
+ @Test
+ @Title("Значение температуры по шкале Фаренгейта должно соответствовать значению по шкале Цельсия")
+ public void shouldReturnCompatibleTemperatureValuesForCelsiusAndFahrenheit(){
+ WeatherResponse weatherResponse =
+ given().
+ baseUri(BASE_URL).
+ param(CITY_PARAMETER, CITY_VALUE).
+ when().
+ get(WEATHER_REQUEST).
+ then().statusCode(HttpStatus.SC_OK).
+ and().extract().
+ body().as(WeatherResponse.class);
+ assertThat("Значение температуры не правильно переведено из шкалы Цельсия в шкалу Фаренгейта",
+ weatherResponse.getTemperatures()[2].getValue(),
+ is(closeTo(weatherResponse.recalculateCelsiusToFahrenheit(), TEMPERATURE_ERROR)));
+ }
+}
\ No newline at end of file
diff --git a/api-tests-module/src/test/java/ru/qatools/school/apitests/RetrofitAPITests.java b/api-tests-module/src/test/java/ru/qatools/school/apitests/RetrofitAPITests.java
new file mode 100644
index 0000000..3b6e40e
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/apitests/RetrofitAPITests.java
@@ -0,0 +1,55 @@
+package ru.qatools.school.apitests;
+
+import org.apache.http.HttpStatus;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+import ru.qatools.school.Responses.CitiesResponse;
+import ru.qatools.school.Responses.WeatherResponse;
+import ru.qatools.school.interfaces.Cities;
+import ru.qatools.school.interfaces.Weather;
+import ru.yandex.qatools.allure.annotations.Title;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.closeTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static ru.qatools.school.data.Constants.*;
+
+/**
+ * @author ava1on
+ */
+public class RetrofitAPITests {
+
+ private static Retrofit retrofit;
+
+ @BeforeClass
+ public static void initRetrofit(){
+ retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
+ }
+
+ @Test
+ @Title("Должны получить заданное в параметре количество городов в ответе")
+ public void shouldReturnRequestedNumberOfCities() throws IOException{
+ Cities cities = retrofit.create(Cities.class);
+ Response> response = cities.citiesList(LIMIT_VALUE).execute();
+ assertThat("Код ответа неверный", response.code(), is(HttpStatus.SC_OK));
+ assertThat("Неверное количество городов в ответе", response.body(), hasSize(LIMIT_VALUE));
+ }
+
+ @Test
+ @Title("Значение температуры по шкале Фаренгейта должно соответствовать значению по шкале Цельсия")
+ public void shouldReturnCompatibleTemperatureValuesForCelsiusAndFahrenheit() throws IOException{
+ Weather weather = retrofit.create(Weather.class);
+ Response response = weather.weather(CITY_PARAMETER, null).execute();
+ assertThat("Код ответа неверный", response.code(), is(HttpStatus.SC_OK));
+ assertThat("Значение температуры не правильно переведено из шкалы Цельсия в шкалу Фаренгейта",
+ response.body().getTemperatures()[2].getValue(),
+ is(closeTo(response.body().recalculateCelsiusToFahrenheit(), TEMPERATURE_ERROR)));
+ }
+}
\ No newline at end of file
diff --git a/api-tests-module/src/test/java/ru/qatools/school/data/Constants.java b/api-tests-module/src/test/java/ru/qatools/school/data/Constants.java
new file mode 100644
index 0000000..91be564
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/data/Constants.java
@@ -0,0 +1,19 @@
+package ru.qatools.school.data;
+
+/**
+ * @author ava1on
+ */
+public class Constants {
+ public static final String BASE_URL = "http://weather.lanwen.ru/api/";
+ public static final String LIMIT_PARAMETER = "limit";
+ public static final String CITIES_REQUEST = "cities";
+ public static final int LIMIT_VALUE = 3;
+ public static final String WEATHER_REQUEST = "weather";
+ public static final String CITY_PARAMETER = "city";
+ public static final String CITY_VALUE = "Saint Petersburg";
+ public static final double TEMPERATURE_ERROR = 0.1;
+ public static final String REGION_PARAMETER = "region";
+ public static final String SUGGEST_REQUEST = "suggest";
+ public static final String QUERY_PARAMETER = "query";
+ public static final String CITYNAME_PART = "Saint";
+}
diff --git a/api-tests-module/src/test/java/ru/qatools/school/interfaces/Cities.java b/api-tests-module/src/test/java/ru/qatools/school/interfaces/Cities.java
new file mode 100644
index 0000000..3e32fe8
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/interfaces/Cities.java
@@ -0,0 +1,18 @@
+package ru.qatools.school.interfaces;
+
+import retrofit2.Call;
+import retrofit2.http.GET;
+import retrofit2.http.Query;
+import ru.qatools.school.Responses.CitiesResponse;
+
+import java.util.List;
+
+import static ru.qatools.school.data.Constants.LIMIT_PARAMETER;
+
+/**
+ * @author ava1on
+ */
+public interface Cities {
+ @GET("cities")
+ Call> citiesList(@Query(LIMIT_PARAMETER) int limitValue);
+}
diff --git a/api-tests-module/src/test/java/ru/qatools/school/interfaces/Weather.java b/api-tests-module/src/test/java/ru/qatools/school/interfaces/Weather.java
new file mode 100644
index 0000000..6ff0d8a
--- /dev/null
+++ b/api-tests-module/src/test/java/ru/qatools/school/interfaces/Weather.java
@@ -0,0 +1,17 @@
+package ru.qatools.school.interfaces;
+
+import retrofit2.Call;
+import retrofit2.http.GET;
+import retrofit2.http.Query;
+import ru.qatools.school.Responses.WeatherResponse;
+
+import static ru.qatools.school.data.Constants.CITY_PARAMETER;
+import static ru.qatools.school.data.Constants.REGION_PARAMETER;
+
+/**
+ * @author ava1on
+ */
+public interface Weather {
+ @GET("weather")
+ Call weather(@Query(CITY_PARAMETER) String city, @Query(REGION_PARAMETER) String region);
+}
\ No newline at end of file
diff --git a/commons-module/pom.xml b/commons-module/pom.xml
index 97cb03e..13c90d9 100644
--- a/commons-module/pom.xml
+++ b/commons-module/pom.xml
@@ -29,8 +29,6 @@
com.tngtech.java
junit-dataprovider
- 1.10.4
- test
diff --git a/commons-module/src/test/java/ru/qatools/school/webtests/WeatherWebTest.java b/commons-module/src/test/java/ru/qatools/school/webtests/WeatherWebTest.java
index a4c5a40..a36cc5a 100644
--- a/commons-module/src/test/java/ru/qatools/school/webtests/WeatherWebTest.java
+++ b/commons-module/src/test/java/ru/qatools/school/webtests/WeatherWebTest.java
@@ -1,36 +1,202 @@
package ru.qatools.school.webtests;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import ru.qatools.school.data.DataPatterns;
import ru.qatools.school.pages.MainPage;
+import ru.qatools.school.pages.blocks.WeatherWidget;
import ru.qatools.school.rules.WebDriverRule;
import ru.qatools.school.steps.websteps.DefaultSteps;
+import ru.qatools.school.tp.TPInformerRule;
+import ru.yandex.qatools.allure.annotations.TestCaseId;
import ru.yandex.qatools.allure.annotations.Title;
+@RunWith(DataProviderRunner.class)
public class WeatherWebTest {
- public static final String MOSCOW = "Moscow";
+ private static final String MOSCOW = "Moscow";
+ private static final String SPB = "Saint Petersburg";
+ private static final String PART_OF_CITYNAME = "Saint P";
+ private static final String PAGE_TITLE = "Weather";
+ private static final String NEW_WIDGET = "What a city?";
+
+ @DataProvider
+ public static Object[][] weatherDataFormat() {
+ return new Object[][]{
+ {0, DataPatterns.SUNRISE},
+ {1, DataPatterns.SUNSET},
+ {2, DataPatterns.WIND},
+ {3, DataPatterns.HUMIDITY}
+ };
+ }
+
+ @DataProvider
+ public static Object[][] temperatureFormat(){
+ return new Object[][]{
+ {0, DataPatterns.CELSIUS},
+ {1, DataPatterns.KELVIN},
+ {2, DataPatterns.FAHRENHEIT},
+ {3, DataPatterns.KAIF},
+ {4, DataPatterns.CELSIUS}
+ };
+ }
private DefaultSteps defaultSteps;
@Rule
public WebDriverRule webDriverRule = new WebDriverRule();
+ @Rule
+ public TPInformerRule tms = new TPInformerRule("ava1on");
+
@Before
public void initSteps() {
defaultSteps = new DefaultSteps(webDriverRule.getDriver());
}
@Test
+ @TestCaseId("6")
+ @Title("Должны видеть только кнопку [+] ")
+ public void shouldSeeOnlyAddWidgetButton(){
+ defaultSteps.openMainPageWithoutParameters();
+ defaultSteps.shouldSee(onMainPage().getAddNewWidgetButton());
+ defaultSteps.shouldHaveWidgetNumberOnMainPage(0);
+ }
+
+ @Test
+ @TestCaseId("2")
@Title("Должны видеть виджет на главной странице")
public void shouldSeeWidgetOnMainPage() {
defaultSteps.openMainPageWithCity(MOSCOW);
- defaultSteps.shouldSee(onMainPage().getWeatherWidget().get(0));
+ defaultSteps.shouldSee(getFirstWidget());
+ }
+
+ @Test
+ @TestCaseId("8")
+ @Title("В заголовке виджета должны видеть город, указанный в запросе")
+ public void shouldSeeSelectedCityOnWidgetTitle() {
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.shouldSeeCityInWidgetsTitle(MOSCOW);
+ }
+
+ @Test
+ @TestCaseId("16")
+ @Title("Должны видеть новый виджет при открытии страницы без параметров")
+ public void shouldSeeNewWidgetOnMainPageWithoutParameters() {
+ defaultSteps.openMainPageWithCity("");
+ defaultSteps.shouldSeeCityInWidgetsTitle(NEW_WIDGET);
+ }
+
+ @Test
+ @TestCaseId("3")
+ @Title("Должны видеть на один виджет больше после нажатия на кнопку [+]")
+ public void shouldSeeOneMoreWidget() {
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ int numberOfWidgets = onMainPage().getWeatherWidgets().size();
+ defaultSteps.clickOn(onMainPage().getAddNewWidgetButton());
+ defaultSteps.shouldHaveWidgetNumberOnMainPage(numberOfWidgets+1);
+ }
+
+ @Test
+ @TestCaseId("5")
+ @Title("Должны видеть на один виджет меньше после нажатия на кнопку [-]")
+ public void shouldSeeLessWidgets(){
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ int numberOfWidgets = onMainPage().getWeatherWidgets().size();
+ defaultSteps.clickOn(getFirstWidget().getRemoveWidgetButton());
+ defaultSteps.shouldHaveWidgetNumberOnMainPage(numberOfWidgets-1);
+ }
+
+ @Test
+ @TestCaseId("9")
+ @Title("Должны видеть время и дату в формате \"Ч AM/PM, дд ммм гг\"")
+ public void shouldSeeDateAndTime(){
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.shouldMatchPattern(getFirstWidget().getWidgetTitle().getCurrentTime(), DataPatterns.TIME_DATE);
+ }
+
+ @Test
+ @TestCaseId("11")
+ @Title("Должны видеть новое название города после изменения")
+ public void shouldSeeNewCityAfterChangeUsingEnterKey(){
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.changeWidgetTitle(getFirstWidget(), SPB);
+ defaultSteps.shouldSeeCityInWidgetsTitle(SPB);
+ }
+
+ @Test
+ @TestCaseId("12")
+ @Title("Должны видеть список автозаполнения")
+ public void shouldSeeSuggestCitiesList(){
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.suggestList(PART_OF_CITYNAME, getFirstWidget().getWidgetTitle());
+ defaultSteps.shouldSee(getFirstWidget().getWidgetTitle().getSuggestedCitiesList());
+ }
+
+ @Test
+ @TestCaseId("13")
+ @Title("В списке автозаполнения должны отображаться только города, содержащие введенную строку")
+ public void shouldSeeSuitableSuggestedCities(){
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.suggestList(PART_OF_CITYNAME, getFirstWidget().getWidgetTitle());
+ defaultSteps.shouldOnlySeeCitiesContaining(PART_OF_CITYNAME);
+ }
+
+ @Test
+ @TestCaseId("14")
+ @Title("Должны изменить город используя список автозаполения")
+ public void shouldSeeNewCityAfterChangeUsingSuggestedList(){
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.suggestList(PART_OF_CITYNAME, getFirstWidget().getWidgetTitle());
+ defaultSteps.selectItemFromSuggestedList(SPB);
+ defaultSteps.shouldSeeCityInWidgetsTitle(SPB);
+ }
+
+ @Test
+ @UseDataProvider("temperatureFormat")
+ @TestCaseId("4")
+ @Title("Температура должна отображатся в правильном формате")
+ public void shouldSeeTemperature(int numberOfClicks, DataPatterns pattern) {
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.clickOnSeveralTimes(getFirstWidget().getWidgetText().getTemperature(), numberOfClicks);
+ defaultSteps.shouldMatchPattern(getFirstWidget().getWidgetText().getTemperature(), pattern);
+ }
+
+ @Test
+ @UseDataProvider("weatherDataFormat")
+ @TestCaseId("7")
+ @Title("Погодные данные должны отображаться в правильном формате")
+ public void shouldSeeWeatherData(int id, DataPatterns pattern) {
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.shouldMatchPattern(getFirstWidget().getWidgetText().getWeatherData().get(id), pattern);
+ }
+
+ @Test
+ @TestCaseId("10")
+ @Title("Должны видеть заголовок страницы")
+ public void shouldSeePageTitle(){
+ defaultSteps.openMainPageWithoutParameters();
+ defaultSteps.shouldSeeTitle(PAGE_TITLE);
+ }
+
+ @Test
+ @TestCaseId("23")
+ @Title("Должны видеть иконку погоды")
+ public void shouldSeeWeatherImage(){
+ defaultSteps.openMainPageWithCity(MOSCOW);
+ defaultSteps.shouldSee(getFirstWidget().getWidgetText().getWeatherImage());
}
private MainPage onMainPage() {
return new MainPage(webDriverRule.getDriver());
}
-}
+ private WeatherWidget getFirstWidget() {
+ return onMainPage().getWeatherWidgets().get(0);
+ }
+}
\ No newline at end of file
diff --git a/dbclient-module/src/main/java/ru/qatools/school/DbClient.java b/dbclient-module/src/main/java/ru/qatools/school/DbClient.java
index 12e1204..b9fb76d 100644
--- a/dbclient-module/src/main/java/ru/qatools/school/DbClient.java
+++ b/dbclient-module/src/main/java/ru/qatools/school/DbClient.java
@@ -1,11 +1,14 @@
package ru.qatools.school;
-import org.jooq.*;
+import org.jooq.DSLContext;
+import org.jooq.Record1;
+import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
+import java.util.List;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.table;
@@ -17,7 +20,7 @@ public class DbClient {
private static final String CONNECTION_STRING =
System.getProperty("db.url", "jdbc:mysql://db.host.ru:3310/db_name");
private static final String USER = System.getProperty("db.user", "user");
- private static final String PASSWORD = System.getProperty("db.password", "password");;
+ private static final String PASSWORD = System.getProperty("db.password", "password");
private Connection connection;
private DSLContext create;
@@ -39,6 +42,12 @@ public String getCityById(Integer id) {
return result.getValue(0, String.class);
}
+ public List getCitiesByNamePart(String namePart){
+ return create.selectFrom(table("City"))
+ .where(field("name").like("%" + namePart + "%"))
+ .fetch().getValues(field("id"), Integer.class);
+ }
+
public void close() {
try {
connection.close();
diff --git a/dbclient-module/src/main/java/ru/qatools/school/rules/dbClientRule.java b/dbclient-module/src/main/java/ru/qatools/school/rules/dbClientRule.java
new file mode 100644
index 0000000..5565e17
--- /dev/null
+++ b/dbclient-module/src/main/java/ru/qatools/school/rules/dbClientRule.java
@@ -0,0 +1,24 @@
+package ru.qatools.school.rules;
+
+import org.junit.rules.ExternalResource;
+import ru.qatools.school.DbClient;
+
+/**
+ * @author ava1on
+ */
+public class DbClientRule extends ExternalResource {
+
+ private DbClient dbClient;
+
+ public void before(){
+ this.dbClient = new DbClient();
+ }
+
+ public void after(){
+ dbClient.close();
+ }
+
+ public DbClient getDbClient(){
+ return dbClient;
+ }
+}
diff --git a/pom.xml b/pom.xml
index 2f0da8b..bd58953 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,7 @@
steps-module
commons-module
+ api-tests-module
dbclient-module
@@ -33,18 +34,22 @@
junit
4.12
+
+ com.tngtech.java
+ junit-dataprovider
+ 1.10.4
+ test
+
-
com.jayway.restassured
rest-assured
2.9.0
-
ru.yandex.qatools.allure
allure-junit-adaptor
diff --git a/steps-module/pom.xml b/steps-module/pom.xml
index 9bcfe79..cb8a2be 100644
--- a/steps-module/pom.xml
+++ b/steps-module/pom.xml
@@ -40,11 +40,20 @@
ru.yandex.qatools.htmlelements
htmlelements-matchers
-
com.jayway.restassured
rest-assured
+
+ org.cthul
+ cthul-matchers
+ 1.1.0
+
+
+ ru.yandex.qatools.matchers
+ webdriver-matchers
+ 1.3
+
diff --git a/steps-module/src/main/java/ru/qatools/school/data/DataPatterns.java b/steps-module/src/main/java/ru/qatools/school/data/DataPatterns.java
new file mode 100644
index 0000000..ae2260d
--- /dev/null
+++ b/steps-module/src/main/java/ru/qatools/school/data/DataPatterns.java
@@ -0,0 +1,32 @@
+package ru.qatools.school.data;
+
+/**
+ * @author ava1on
+ */
+public enum DataPatterns {
+ CELSIUS("^-?\\d{1,2}\\.\\d °C$"),
+ KELVIN("^[1-3]\\d{2}\\.\\d °K$"),
+ FAHRENHEIT("^-?[1]?\\d{1,2}\\.\\d °F$"),
+ KAIF("^-?\\d{1,2}\\.\\d °Kaif$"),
+ SUNRISE("^Sunrise\\s[0-2][0-9]:[0-5][0-9]$"),
+ SUNSET("^Sunset\\s[0-2][0-9]:[0-5][0-9]$"),
+ WIND("^Wind\\s\\d{1,}\\.?\\d{0,2}? m\\/s$"),
+ HUMIDITY("^Humidity\\s[0-9]{1,} %$"),
+ TIME_DATE("^1?\\d [A|P]M, [0-3]\\d \\w{3} \\d{2}");
+
+ private final String pattern;
+
+ DataPatterns(String pattern) {
+ this.pattern = pattern;
+ }
+
+ public String getPattern(){
+ return pattern;
+ }
+
+ @Override
+ public String toString(){
+ return pattern;
+ }
+
+}
diff --git a/steps-module/src/main/java/ru/qatools/school/pages/MainPage.java b/steps-module/src/main/java/ru/qatools/school/pages/MainPage.java
index 4d75376..2cef9c8 100644
--- a/steps-module/src/main/java/ru/qatools/school/pages/MainPage.java
+++ b/steps-module/src/main/java/ru/qatools/school/pages/MainPage.java
@@ -5,6 +5,7 @@
import org.openqa.selenium.support.PageFactory;
import ru.qatools.school.pages.blocks.WeatherWidget;
import ru.yandex.qatools.htmlelements.annotations.Name;
+import ru.yandex.qatools.htmlelements.element.HtmlElement;
import ru.yandex.qatools.htmlelements.loader.decorator.HtmlElementDecorator;
import ru.yandex.qatools.htmlelements.loader.decorator.HtmlElementLocatorFactory;
@@ -21,10 +22,17 @@ public MainPage(WebDriver driver) {
@Name("Список виджетов")
@FindBy(css = ".card.card_md")
- private List weatherWidget;
+ private List weatherWidgets;
- public List getWeatherWidget() {
- return weatherWidget;
+ @Name("Кнопка добавления виджетов")
+ @FindBy(css = ".new-card")
+ private HtmlElement addNewWidgetButton;
+
+ public List getWeatherWidgets() {
+ return weatherWidgets;
}
+ public HtmlElement getAddNewWidgetButton(){
+ return addNewWidgetButton;
+ }
}
diff --git a/steps-module/src/main/java/ru/qatools/school/pages/blocks/WeatherWidget.java b/steps-module/src/main/java/ru/qatools/school/pages/blocks/WeatherWidget.java
index 3990d85..4f54264 100644
--- a/steps-module/src/main/java/ru/qatools/school/pages/blocks/WeatherWidget.java
+++ b/steps-module/src/main/java/ru/qatools/school/pages/blocks/WeatherWidget.java
@@ -1,7 +1,6 @@
package ru.qatools.school.pages.blocks;
import org.openqa.selenium.Rectangle;
-import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import ru.qatools.school.pages.blocks.widgetblocks.WidgetText;
import ru.qatools.school.pages.blocks.widgetblocks.WidgetTitle;
@@ -21,9 +20,9 @@ public class WeatherWidget extends HtmlElement {
@FindBy(css = ".card-text")
private WidgetText widgetText;
- @Name("Панель управления виджетом")
- @FindBy(css = ".card-actions")
- private WebElement actions;
+ @Name("Кнопка удаления виджета")
+ @FindBy(css = ".remove-card")
+ private HtmlElement removeWidgetButton;
public WidgetText getWidgetText() {
return widgetText;
@@ -33,8 +32,8 @@ public WidgetTitle getWidgetTitle() {
return widgetTitle;
}
- public WebElement getActions() {
- return actions;
+ public HtmlElement getRemoveWidgetButton() {
+ return removeWidgetButton;
}
public Rectangle getRect() {
diff --git a/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetText.java b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetText.java
index 510d070..1207171 100644
--- a/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetText.java
+++ b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetText.java
@@ -1,11 +1,12 @@
package ru.qatools.school.pages.blocks.widgetblocks;
import org.openqa.selenium.Rectangle;
-import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import ru.yandex.qatools.htmlelements.annotations.Name;
import ru.yandex.qatools.htmlelements.element.HtmlElement;
+import java.util.List;
+
/**
* Created by kurau.
*/
@@ -13,12 +14,28 @@ public class WidgetText extends HtmlElement {
@Name("Картинка текущей погоды")
@FindBy(css = ".weather-image")
- private WebElement weatherImage;
+ private HtmlElement weatherImage;
+
+ @Name("Температура")
+ @FindBy(css = ".weather-temperature.md-12")
+ private HtmlElement temperature;
- public WebElement getWeatherImage() {
+ @Name("Погодные данные")
+ @FindBy(css = ".line.info-line")
+ private List weatherData;
+
+ public HtmlElement getWeatherImage() {
return weatherImage;
}
+ public HtmlElement getTemperature() {
+ return temperature;
+ }
+
+ public List getWeatherData() {
+ return weatherData;
+ }
+
public Rectangle getRect() {
return null;
}
diff --git a/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetTitle.java b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetTitle.java
index 8a88782..71800c2 100644
--- a/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetTitle.java
+++ b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetTitle.java
@@ -1,13 +1,49 @@
package ru.qatools.school.pages.blocks.widgetblocks;
import org.openqa.selenium.Rectangle;
+import org.openqa.selenium.support.FindBy;
+import ru.yandex.qatools.htmlelements.annotations.Name;
import ru.yandex.qatools.htmlelements.element.HtmlElement;
+import java.util.List;
+
/**
* Created by kurau.
*/
public class WidgetTitle extends HtmlElement {
+ @Name("Название города")
+ @FindBy(css = ".inplace")
+ private HtmlElement cityName;
+
+ @Name("Время и дата")
+ @FindBy(css = ".card-title__secondary")
+ private HtmlElement currentTime;
+
+ @Name("Список автозаполнения")
+ @FindBy(css = ".city-suggest")
+ private HtmlElement suggestedCitiesList;
+
+ @Name("Элементы списка автозаполнения")
+ @FindBy(css = ".city__name")
+ private List suggestedCities;
+
+ public HtmlElement getCityName(){
+ return cityName;
+ }
+
+ public HtmlElement getCurrentTime() {
+ return currentTime;
+ }
+
+ public HtmlElement getSuggestedCitiesList() {
+ return suggestedCitiesList;
+ }
+
+ public List getSuggestedCities() {
+ return suggestedCities;
+ }
+
public Rectangle getRect() {
return null;
}
diff --git a/steps-module/src/main/java/ru/qatools/school/rules/WebDriverRule.java b/steps-module/src/main/java/ru/qatools/school/rules/WebDriverRule.java
index 418c363..2f0c894 100644
--- a/steps-module/src/main/java/ru/qatools/school/rules/WebDriverRule.java
+++ b/steps-module/src/main/java/ru/qatools/school/rules/WebDriverRule.java
@@ -3,6 +3,7 @@
import org.junit.rules.ExternalResource;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
+import org.openqa.selenium.support.ui.WebDriverWait;
/**
* Created by kurau.
@@ -10,9 +11,11 @@
public class WebDriverRule extends ExternalResource {
private WebDriver driver;
+ private WebDriverWait webDriverWait;
protected void before() throws Throwable {
this.driver = new FirefoxDriver();
+ this.webDriverWait = new WebDriverWait(driver, 5);
}
protected void after() {
diff --git a/steps-module/src/main/java/ru/qatools/school/steps/websteps/DefaultSteps.java b/steps-module/src/main/java/ru/qatools/school/steps/websteps/DefaultSteps.java
index 1425a42..64f3269 100644
--- a/steps-module/src/main/java/ru/qatools/school/steps/websteps/DefaultSteps.java
+++ b/steps-module/src/main/java/ru/qatools/school/steps/websteps/DefaultSteps.java
@@ -1,25 +1,41 @@
package ru.qatools.school.steps.websteps;
+import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+import ru.qatools.school.data.DataPatterns;
import ru.qatools.school.pages.MainPage;
+import ru.qatools.school.pages.blocks.WeatherWidget;
+import ru.qatools.school.pages.blocks.widgetblocks.WidgetTitle;
import ru.yandex.qatools.allure.annotations.Step;
+import ru.yandex.qatools.htmlelements.element.HtmlElement;
+
+import java.util.ArrayList;
+import java.util.List;
import static java.lang.String.format;
+import static org.cthul.matchers.CthulMatchers.containsPattern;
+import static org.hamcrest.Matchers.*;
+import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
-import static ru.yandex.qatools.htmlelements.matchers.WebElementMatchers.isDisplayed;
+import static ru.yandex.qatools.htmlelements.matchers.WebElementMatchers.*;
+import static ru.yandex.qatools.matchers.webdriver.TextMatcher.text;
/**
* Created by kurau.
*/
public class DefaultSteps {
- public static final String MAIN_PAGE = "http://weather.lanwen.ru/#?cities=%s";
+ private static final String MAIN_PAGE = "http://weather.lanwen.ru/#?cities=%s";
+ private static final String MAIN_PAGE_WITHOUT_PARAMETERS = "http://weather.lanwen.ru";
private WebDriver driver;
+ private WebDriverWait webDriverWait;
public DefaultSteps(WebDriver driver) {
this.driver = driver;
+ webDriverWait = new WebDriverWait(driver, 5);
}
@Step("Открываем главную страницу для города «{0}»")
@@ -27,12 +43,86 @@ public void openMainPageWithCity(String city) {
driver.get(format(MAIN_PAGE, city));
}
+ @Step("Открываем главную страницу приложения")
+ public void openMainPageWithoutParameters(){
+ driver.get(MAIN_PAGE_WITHOUT_PARAMETERS);
+ }
+
@Step("Должны видеть на странице «{0}»")
- public void shouldSee(WebElement element) {
- assertThat("Должны видеть элемент", element, isDisplayed());
+ public void shouldSee(HtmlElement element) {
+ assertThat("Должны видеть элемент", element, allOf(exists(),isDisplayed()));
+ }
+
+ @Step("Должны видеть в заголовке виджета текст: {0}")
+ public void shouldSeeCityInWidgetsTitle(String city){
+ assertThat("Должны видеть текст",
+ onMainPage().getWeatherWidgets().get(0).getWidgetTitle().getCityName(), hasText(city));
+ }
+
+ @Step("Число виджетов на странице должно быть равно: {0}")
+ public void shouldHaveWidgetNumberOnMainPage(int numberOfWidgets){
+ assertThat("Должны видеть виджетов", onMainPage().getWeatherWidgets(), hasSize(numberOfWidgets));
+ }
+
+ @Step("Изменяем город в заголовке")
+ public void changeWidgetTitle(WeatherWidget weatherWidget, String newCity){
+ clickOn(weatherWidget.getWidgetTitle().getCityName());
+ enterText(newCity, weatherWidget.getWidgetTitle().getCityName());
+ weatherWidget.getWidgetTitle().getCityName().sendKeys(Keys.RETURN);
+ }
+
+ @Step("Ввод текста в заголовок и ожидание появления списка автозаполнения")
+ public void suggestList(String part, WidgetTitle widgetTitle){
+ clickOn(widgetTitle.getCityName());
+ enterText(part, widgetTitle.getCityName());
+ webDriverWait.until(ExpectedConditions.elementToBeClickable(widgetTitle.getSuggestedCitiesList()));
+ }
+
+ @Step("В списке должны быть только города, содержащие {0}")
+ public void shouldOnlySeeCitiesContaining(String part){
+ assertThat("", new ArrayList<>(onMainPage().getWeatherWidgets().get(0).getWidgetTitle().getSuggestedCities()),
+ everyItem(text(containsString(part))));
+ }
+
+ @Step("Данные в {0} отображаются в формате {1}")
+ public void shouldMatchPattern(HtmlElement element, DataPatterns pattern){
+ assertThat("Данные отображаются в неверном формате", element.getText(), containsPattern(pattern.toString()));
+ }
+
+ @Step("Должны видеть в заголовке страницы {0}")
+ public void shouldSeeTitle(String text){
+ assertThat("Неверный заголовок страницы", driver.getTitle(), is(text));
+ }
+
+ @Step("Выбираем город из списка автозаполнения")
+ public void selectItemFromSuggestedList(String city){
+ clickOn(findElementByName(city, onMainPage().getWeatherWidgets().get(0).getWidgetTitle().getSuggestedCities()));
+ webDriverWait.until(ExpectedConditions.not(ExpectedConditions.stalenessOf(onMainPage().getWeatherWidgets().get(0))));
}
private MainPage onMainPage() {
return new MainPage(driver);
}
+
+ private void enterText(String text, HtmlElement field){
+ field.clear();
+ field.sendKeys(text);
+ }
+
+ public void clickOn(HtmlElement element){
+ element.click();
+ }
+
+ public void clickOnSeveralTimes(HtmlElement element, int times){
+ while(times-- > 0)
+ element.click();
+ }
+
+ private HtmlElement findElementByName(String item, List list){
+ for(HtmlElement elem : list)
+ if(elem.getText().equals(item)) {
+ return elem;
+ }
+ return null;
+ }
}