diff --git a/README.md b/README.md index 69e007d..f645e9d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # Practice of automation school 2016 See all info in repo [autoschool/autoschool.github.io](https://github.com/autoschool/autoschool.github.io) + +See Dockerfile in repo [OneginES/Docker](https://github.com/OneginES/Docker) diff --git a/api-tests-module/pom.xml b/api-tests-module/pom.xml new file mode 100644 index 0000000..013fa65 --- /dev/null +++ b/api-tests-module/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + + school-2016 + ru.qatools.school + 1.0-SNAPSHOT + + + api-tests-module + + API Module + + + + ru.qatools.school + steps-module + 1.0-SNAPSHOT + test + + + ru.qatools.school + dbclient-module + ${project.version} + + + ru.yandex.qatools.matchers + collection-matchers + 1.3 + + + + + true + + + ru.yandex.qatools.allure + allure-maven-plugin + 2.0 + + + + diff --git a/api-tests-module/src/test/java/ru/qatools/school/apitests/RestAssuredTest.java b/api-tests-module/src/test/java/ru/qatools/school/apitests/RestAssuredTest.java new file mode 100644 index 0000000..fc7ec6d --- /dev/null +++ b/api-tests-module/src/test/java/ru/qatools/school/apitests/RestAssuredTest.java @@ -0,0 +1,148 @@ +package ru.qatools.school.apitests; + +import com.jayway.restassured.builder.RequestSpecBuilder; +import com.jayway.restassured.specification.RequestSpecification; +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.apidata.SuggestResp; +import ru.qatools.school.apidata.WeatherResp; +import ru.qatools.school.tp.TPInformerRule; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.TestCaseId; +import ru.yandex.qatools.allure.annotations.Title; + +import java.util.List; + +import static com.jayway.restassured.RestAssured.given; +import static java.util.Arrays.asList; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; +import static ru.yandex.qatools.matchers.collection.HasSameItemsAsListMatcher.hasSameItemsAsList; + +/** + * @author onegines (Eugene Kirienko) + */ +public class RestAssuredTest { + + private static final String MAIN_PAGE = "http://weather.lanwen.ru/"; + private static final String BASE_PATH = "api"; + + private static final String CITYNAME = "Chita"; + private static final String CITYNAMEBEGIN = "Saint"; + private static final String CITYNAMEPART = "ain"; + + private RequestSpecification reqSpec; + + private DbClient dbClient; + + @Rule + public TPInformerRule tms = new TPInformerRule("onegines"); + + @Before + public void init() { + dbClient = new DbClient(); + + reqSpec = new RequestSpecBuilder().build() + .baseUri(MAIN_PAGE) + .basePath(BASE_PATH); + } + + @After + public void close() { + dbClient.close(); + } + + @Test + @Features("Suggest") + @Title("Должны получить код 400 после отправки запроса саджеста без параметров") + @TestCaseId("53") + public void shouldGetErrorCode400AfterSendNoQueryToSuggest() throws Exception { + given().spec(reqSpec) + .get("suggest") + .then().assertThat() + .statusCode(HttpStatus.SC_BAD_REQUEST); + } + + @Test + @Features("Suggest") + @Title("Должны получить список городов, содержащих в названии строку из запроса") + @TestCaseId("42") + public void shouldGetSuggestsContainsPartOfName() throws Exception { + given().spec(reqSpec) + .param("query", CITYNAMEBEGIN) + .get("suggest") + .then().assertThat() + .statusCode(HttpStatus.SC_OK) + .and().body("name", everyItem(containsString(CITYNAMEBEGIN))); + } + + @Test + @Features("Suggest") + @Title("Должны совпадать списки (от API и DB) саджестов, содержащих в названии города строку из запроса") + @TestCaseId("75") + public void shouldMatchSuggestsFromApiAndDb() throws Exception { + + List respApi = asList( + given().spec(reqSpec) + .param("query", CITYNAMEPART) + .expect().statusCode(HttpStatus.SC_OK) + .get("suggest") + .as(SuggestResp[].class) + ); + + List respDb = dbClient.getSuggestCitiesByNamePart(CITYNAMEPART); + + assertThat("Списки из API и DB должны совпадать", respApi, hasSameItemsAsList(respDb)); + + } + + @Test + @Features("Weather") + @Title("Должны получить погоду в городе с названием, указанным в запросе") + @TestCaseId("55") + public void shouldGetWeatherWithCityName() throws Exception { + + WeatherResp resp = + given().spec(reqSpec) + .param("city", CITYNAME) + .expect().statusCode(HttpStatus.SC_OK) + .get("weather") + .as(WeatherResp.class); + + assertThat("Неправильный город", resp.getCity(), is(CITYNAME)); + + } + + @Test + @Features("Weather") + @Title("Должны получить погоду в городе с названием '0'") + @TestCaseId("60") + public void shouldGetWeatherWithCityName0() throws Exception { + + WeatherResp resp = + given().spec(reqSpec) + .param("city", "0") + .expect().statusCode(HttpStatus.SC_OK) + .get("weather") + .as(WeatherResp.class); + + assertThat("Неправильный город", resp.getCity(), is("0")); + + } + + @Test + @Features("Weather") + @Title("Должны получить код 400 после отправки запроса погоды без параметров") + @TestCaseId("65") + public void shouldGetErrorCode400AfterSendNoQueryToWeather() throws Exception { + given().spec(reqSpec) + .get("weather") + .then().assertThat() + .statusCode(HttpStatus.SC_BAD_REQUEST); + } + +} diff --git a/api-tests-module/src/test/java/ru/qatools/school/apitests/RetrofitTest.java b/api-tests-module/src/test/java/ru/qatools/school/apitests/RetrofitTest.java new file mode 100644 index 0000000..64c5443 --- /dev/null +++ b/api-tests-module/src/test/java/ru/qatools/school/apitests/RetrofitTest.java @@ -0,0 +1,109 @@ +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 retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import ru.qatools.school.DbClient; +import ru.qatools.school.apidata.SuggestResp; +import ru.qatools.school.apidata.WeatherApi; +import ru.qatools.school.apidata.WeatherResp; +import ru.qatools.school.tp.TPInformerRule; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Title; + +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; +import static ru.yandex.qatools.matchers.collection.HasSameItemsAsListMatcher.hasSameItemsAsList; + +/** + * @author onegines (Eugene Kirienko) + */ +public class RetrofitTest { + + private static final String MAIN_PAGE = "http://weather.lanwen.ru/"; + private static final String CITYNAMEBEGIN = "Saint"; + private static final String CITYNAMEPART = "ain"; + + private WeatherApi weatherApi; + private DbClient dbClient; + + private Retrofit retrofit = new Retrofit.Builder() + .baseUrl(MAIN_PAGE) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + + @Rule + public TPInformerRule tms = new TPInformerRule("onegines"); + + @Before + public void init() { + weatherApi = retrofit.create(WeatherApi.class); + dbClient = new DbClient(); + } + + @After + public void close() { + dbClient.close(); + } + + @Test + @Features("Suggest") + @Title("Должны получить код 400 после отправки запроса саджеста без параметров") + //@TestCaseId("53") + public void shouldGetErrorCode400AfterSendNoQueryToSuggest() throws IOException { + + Response> resp = weatherApi.suggest().execute(); + + assertThat("Неправильный код ответа", resp.code(), is(HttpStatus.SC_BAD_REQUEST)); + + } + + @Test + @Features("Suggest") + @Title("Должны получить список городов, содержащих в названии строку из запроса") + //@TestCaseId("42") + public void shouldGetSuggestsContainsPartOfName() throws IOException { + + Response> resp = weatherApi.suggest(CITYNAMEBEGIN).execute(); + + assertThat("Request status different from expected", resp.code(), is(HttpStatus.SC_OK)); + assertThat("Все города должны содержать строку из запроса", resp.body(), everyItem(hasProperty("name", containsString(CITYNAMEBEGIN)))); + + } + + @Test + @Features("Suggest") + @Title("Должны совпадать списки (от API и DB) саджестов, содержащих в названии города строку из запроса") + //@TestCaseId("75") + public void shouldMatchSuggestsFromApiAndDb() throws IOException { + + Response> respApi = weatherApi.suggest(CITYNAMEPART).execute(); + List respDb = dbClient.getSuggestCitiesByNamePart(CITYNAMEPART); + + assertThat("Неправильный код ответа", respApi.code(), is(HttpStatus.SC_OK)); + assertThat("Списки из API и DB должны совпадать", respApi.body(), hasSameItemsAsList(respDb)); + + } + + @Test + @Features("Weather") + @Title("Должны получить код 400 после отправки запроса погоды без параметров") + //@TestCaseId("65") + public void shouldGetErrorCode400AfterSendNoQueryToWeather() throws IOException { + + Response resp = weatherApi.weather().execute(); + + assertThat("Неправильный код ответа", resp.code(), is(HttpStatus.SC_BAD_REQUEST)); + + } + + +} diff --git a/commons-module/pom.xml b/commons-module/pom.xml index 97cb03e..ac63ece 100644 --- a/commons-module/pom.xml +++ b/commons-module/pom.xml @@ -53,5 +53,4 @@ - 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 deleted file mode 100644 index a4c5a40..0000000 --- a/commons-module/src/test/java/ru/qatools/school/webtests/WeatherWebTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package ru.qatools.school.webtests; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import ru.qatools.school.pages.MainPage; -import ru.qatools.school.rules.WebDriverRule; -import ru.qatools.school.steps.websteps.DefaultSteps; -import ru.yandex.qatools.allure.annotations.Title; - -public class WeatherWebTest { - - public static final String MOSCOW = "Moscow"; - - private DefaultSteps defaultSteps; - - @Rule - public WebDriverRule webDriverRule = new WebDriverRule(); - - @Before - public void initSteps() { - defaultSteps = new DefaultSteps(webDriverRule.getDriver()); - } - - @Test - @Title("Должны видеть виджет на главной странице") - public void shouldSeeWidgetOnMainPage() { - defaultSteps.openMainPageWithCity(MOSCOW); - defaultSteps.shouldSee(onMainPage().getWeatherWidget().get(0)); - } - - private MainPage onMainPage() { - return new MainPage(webDriverRule.getDriver()); - } - -} diff --git a/commons-module/src/test/java/ru/qatools/school/webtests/WebTests.java b/commons-module/src/test/java/ru/qatools/school/webtests/WebTests.java new file mode 100644 index 0000000..70e157e --- /dev/null +++ b/commons-module/src/test/java/ru/qatools/school/webtests/WebTests.java @@ -0,0 +1,329 @@ +package ru.qatools.school.webtests; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import ru.qatools.school.pages.MainPage; +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; +import ru.yandex.qatools.htmlelements.element.HtmlElement; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; + +import static java.lang.String.format; +import static java.util.Arrays.asList; + +/** + * @author by onegines (Eugene Kirienko) + */ +public class WebTests { + + private static final String CITY = "Saint Petersburg"; + private static final String CITY2 = "Moscow"; + private static final String CITY2_BEGIN = "Mosc"; + private static final String TITLE = "Weather"; + + private DefaultSteps defaultSteps; + + @Rule + public WebDriverRule webDriverRule = new WebDriverRule(); + + @Rule + public TPInformerRule tms = new TPInformerRule("onegines"); + + @Before + public void initSteps() { + defaultSteps = new DefaultSteps(webDriverRule.getDriver()); + } + + private MainPage onMainPage() { + return new MainPage(webDriverRule.getDriver()); + } + + @Test + @Title("Должна открыться требуемая страница") + @TestCaseId("6") + public void shouldBeOnCorrectPage() { + defaultSteps.openMainPage(); + defaultSteps.shouldBeUrl(DefaultSteps.MAIN_PAGE); + defaultSteps.shouldBeTitle(TITLE); + } + + @Test + @Title("Должны видеть кнопку '+' на странице, открытой без параметров") + @TestCaseId("5") + public void shouldSeeAddWidgetButtonOnPageWithNoQuery() { + defaultSteps.openMainPage(); + defaultSteps.shouldSee(onMainPage().getAddWidgetButton()); + } + + @Test + @Title("Должны видеть кнопку '+' на странице, открытой с указанием города в параметрах") + @TestCaseId("7") + public void shouldSeeAddWidgetButtonOnPageWithQuery() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.shouldSee(onMainPage().getAddWidgetButton()); + } + + @Test + @Title("Должны видеть виджет города из запроса") + @TestCaseId("8") + public void shouldSeeWidgetFromQuery() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY); + } + + @Test + @Title("Должны видеть все компоненты виджета") + @TestCaseId("9") + public void shouldSeeAllWidgetBlocks() { + defaultSteps.openMainPageWithCities(CITY); + + List allWidgetBlocks = asList( + onMainPage().getFirstWidget().getWidgetTitle().getCityName(), + onMainPage().getFirstWidget().getWidgetTitle().getCurrentTimeAndDate(), + + onMainPage().getFirstWidget().getWidgetText().getWeatherImage(), + onMainPage().getFirstWidget().getWidgetText().getWeatherTemperatureDigit(), + onMainPage().getFirstWidget().getWidgetText().getWeatherTemperatureUnit(), + + onMainPage().getFirstWidget().getWidgetText().getSunriseLine().getTitle(), + onMainPage().getFirstWidget().getWidgetText().getSunriseLine().getImage(), + onMainPage().getFirstWidget().getWidgetText().getSunriseLine().getValue(), + + onMainPage().getFirstWidget().getWidgetText().getSunsetLine().getTitle(), + onMainPage().getFirstWidget().getWidgetText().getSunsetLine().getImage(), + onMainPage().getFirstWidget().getWidgetText().getSunsetLine().getValue(), + + onMainPage().getFirstWidget().getWidgetText().getWindLine().getTitle(), + onMainPage().getFirstWidget().getWidgetText().getWindLine().getImage(), + onMainPage().getFirstWidget().getWidgetText().getWindLine().getValue(), + + onMainPage().getFirstWidget().getWidgetText().getHumidityLine().getTitle(), + onMainPage().getFirstWidget().getWidgetText().getHumidityLine().getImage(), + onMainPage().getFirstWidget().getWidgetText().getHumidityLine().getValue(), + + onMainPage().getFirstWidget().getWidgetActions().getRemoveWidgetButton() + ); + + defaultSteps.shouldSee(allWidgetBlocks); + } + + @Test + @Title("Должны видеть градусы Цельсия в виджете на странице, открытой с указанием города в параметрах") + @TestCaseId("19") + public void shouldSeeCelsiusInWidgetOnMainPage() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperatureUnit(), "°C"); + } + + @Test + @Title("Должен добавиться новый виджет после щелчка на кнопке '+'") + @TestCaseId("4") + public void shouldBeAddedNewWidget() { + defaultSteps.openMainPageWithCities(CITY); + int numberOfWidgets = onMainPage().getWeatherWidgets().size(); + defaultSteps.clickOn(onMainPage().getAddWidgetButton()); + defaultSteps.shouldBeThisNumberOfElements(onMainPage().getWeatherWidgets(), numberOfWidgets + 1); + } + + @Test + @Title("Должен измениться город в первом виджете после ввода полного названия города и Return") + @TestCaseId("10") + public void shouldBeRenamedFirstWidgetAfterEnterFullName() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2); + defaultSteps.confirmText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.waitUntilElementReady(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), 3); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2); + } + + @Test + @Title("Должен удалиться виджет после нажатия на кнопку удаления") + @TestCaseId("11") + public void shouldBeDeletedOneWidget() { + defaultSteps.openMainPageWithCities(CITY, CITY2); + int numberOfWidgets = onMainPage().getWeatherWidgets().size(); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetActions().getRemoveWidgetButton()); + defaultSteps.shouldBeThisNumberOfElements(onMainPage().getWeatherWidgets(), numberOfWidgets - 1); + } + + @Test + @Title("Должны видеть два виджета на главной странице после загрузки") + @TestCaseId("14") + public void shouldSeeTwoWidgetsOnMainPage() { + defaultSteps.openMainPageWithCities(CITY, CITY2); + defaultSteps.shouldBeThisNumberOfElements(onMainPage().getWeatherWidgets(), 2); + defaultSteps.shouldSee(onMainPage().getWeatherWidgets()); + } + + @Test + @Title("Должны видеть в виджете градусы Кельвина после одного нажатия на указатель температуры") + @TestCaseId("20") + public void shouldSeeKelvinInWidgetAfterOneClick() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperature(), 1); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperatureUnit(), "°K"); + } + + @Test + @Title("Должны видеть в виджете градусы Фаренгейта после двух нажатий на указатель температуры") + @TestCaseId("21") + public void shouldSeeFahrenheitInWidgetAfterTwoClick() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperature(), 2); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperatureUnit(), "°F"); + } + + @Test + @Title("Должны видеть в виджете градусы по кайфу после трёх нажатий на указатель температуры") + @TestCaseId("22") + public void shouldSeeKaifInWidgetAfterThreeClick() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperature(), 3); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperatureUnit(), "°Kaif"); + } + + @Test + @Title("Должны видеть в виджете градусы Цельсия после четырёх нажатий на указатель температуры") + @TestCaseId("23") + public void shouldSeeCelsiusInWidgetAfterFourClick() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperature(), 4); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetText().getWeatherTemperatureUnit(), "°C"); + } + + @Test + @Title("Должны видеть 0 виджетов и кнопку '+' после удаления последнего виджета") + @TestCaseId("16") + public void shouldSeeNoWidgetsAfterDeleteLastOne() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetActions().getRemoveWidgetButton()); + defaultSteps.shouldBeThisNumberOfElements(onMainPage().getWeatherWidgets(), 0); + defaultSteps.shouldSee(onMainPage().getAddWidgetButton()); + } + + @Test + @Title("После изменения города в виджете должен поменяться URL") + @TestCaseId("17") + public void shouldChangeUrlAfterWidgetRename() throws UnsupportedEncodingException { + String city2UrlEncode = URLEncoder.encode(CITY2, "UTF-8"); + + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2); + defaultSteps.confirmText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.shouldBeUrl(DefaultSteps.MAIN_PAGE + format(DefaultSteps.QUERY, city2UrlEncode)); + } + + @Test + @Title("После удаления виджета должен поменяться URL") + @TestCaseId("18") + public void shouldChangeUrlAfterWidgetRemove() throws UnsupportedEncodingException { + String city2UrlEncode = URLEncoder.encode(CITY2, "UTF-8"); + + defaultSteps.openMainPageWithCities(CITY, CITY2); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetActions().getRemoveWidgetButton()); + defaultSteps.shouldBeUrl("http://weather.lanwen.ru/#?cities=" + city2UrlEncode); + defaultSteps.shouldBeUrl(DefaultSteps.MAIN_PAGE + format(DefaultSteps.QUERY, city2UrlEncode)); + } + + @Test + @Title("Должны видеть саджест после ввода начала названия города") + @TestCaseId("13") + public void shouldSeeSuggestAfterEnterCityNameBegin() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2_BEGIN); + defaultSteps.waitUntilElementReady(onMainPage().getFirstWidget().getWidgetTitle().getFirstSuggest(), 2); + defaultSteps.shouldSee(onMainPage().getFirstWidget().getWidgetTitle().getCitySuggests()); + } + + @Test + @Title("Должен измениться город в виджете после выбора города в саджесте (на выбранный)") + @TestCaseId("15") + public void shouldSeeCityInWidgetChosenInSuggest() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2_BEGIN); + + String cityNameInSuggest = onMainPage().getFirstWidget().getWidgetTitle().getFirstSuggest().getCityName().getText(); + + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getFirstSuggest()); + defaultSteps.waitUntilElementReady(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), 2); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), cityNameInSuggest); + + } + + @Test + @Title("Должен исчезнуть саджест после выбора города в нём") + @TestCaseId("24") + public void shouldSeeNoSuggestAfterChooseCityInIt() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2_BEGIN); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getFirstSuggest()); + defaultSteps.shouldNotSee(onMainPage().getFirstWidget().getWidgetTitle().getCitySuggestBlock()); + } + + @Test + @Title("Должен исчезнуть саджест при клике мимо него") + @TestCaseId("25") + public void shouldSeeNoSuggestAfterClickNotOnIt() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2_BEGIN); + defaultSteps.clickOn(onMainPage().getBody()); + defaultSteps.shouldNotSee(onMainPage().getFirstWidget().getWidgetTitle().getCitySuggestBlock()); + } + + @Test + @Title("Должен остаться прежний город в виджете при клике мимо саджеста") + @TestCaseId("26") + public void shouldSeeSameWidgetCityAfterClickNotOnSuggest() { + defaultSteps.openMainPageWithCities(CITY); + + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2_BEGIN); + defaultSteps.clickOn(onMainPage().getBody()); + defaultSteps.waitUntilElementReady(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), 2); + defaultSteps.shouldHaveText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY); + } + + @Test + @Title("В саджесте не должны присутствовать undefined элементы") + @TestCaseId("27") + public void shouldSeeNoUndefinedInSuggest() { + defaultSteps.openMainPageWithCities(CITY); + + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.enterText(onMainPage().getFirstWidget().getWidgetTitle().getCityName(), CITY2_BEGIN); + + defaultSteps.shouldNotHaveText(onMainPage().getFirstWidget().getWidgetTitle().getCitySuggests(), "undefined"); + } + + @Test + @Title("Должны видеть поле с названием города после после удаления текста в нём") + @TestCaseId("12") + public void shouldSeeCityNameInTitleAfterEraseTextInIt() { + defaultSteps.openMainPageWithCities(CITY); + defaultSteps.clickOn(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.eraseText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.confirmText(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + defaultSteps.shouldSee(onMainPage().getFirstWidget().getWidgetTitle().getCityName()); + } +} diff --git a/dbclient-module/pom.xml b/dbclient-module/pom.xml index 2994039..08e2292 100644 --- a/dbclient-module/pom.xml +++ b/dbclient-module/pom.xml @@ -2,12 +2,13 @@ + 4.0.0 + school-2016 ru.qatools.school 1.0-SNAPSHOT - 4.0.0 dbclient-module @@ -22,7 +23,10 @@ mysql-connector-java 5.1.6 + + ru.qatools.school + steps-module + 1.0-SNAPSHOT + - - \ 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..7518941 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,15 @@ 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 ru.qatools.school.apidata.SuggestResp; 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 +21,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; @@ -33,10 +37,18 @@ public DbClient() { public String getCityById(Integer id) { Record1 result = create.select(field("name")) - .from(table("table_name")) + .from(table("City")) .where(field("id").equal(id)) .fetchOne(); - return result.getValue(0, String.class); + return result.getValue(0, String.class); + } + + public List getSuggestCitiesByNamePart(String namePart) { + List result = create.select() + .from(table("City")) + .where(field("name").contains(namePart)) + .fetchInto(SuggestResp.class); + return result; } public void close() { diff --git a/pom.xml b/pom.xml index 2f0da8b..9a09fc6 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ steps-module commons-module + api-tests-module dbclient-module @@ -27,14 +28,6 @@ 1.8.5 - - - junit - junit - 4.12 - - - @@ -77,6 +70,27 @@ + + + junit + junit + 4.12 + + + com.squareup.retrofit2 + retrofit + 2.0.2 + + + com.squareup.retrofit2 + converter-gson + 2.0.2 + + + com.jayway.restassured + rest-assured + + @@ -88,6 +102,7 @@ ${compiler.version} ${compiler.version} + UTF-8 @@ -116,6 +131,4 @@ - - diff --git a/steps-module/pom.xml b/steps-module/pom.xml index 9bcfe79..ed37785 100644 --- a/steps-module/pom.xml +++ b/steps-module/pom.xml @@ -40,12 +40,10 @@ ru.yandex.qatools.htmlelements htmlelements-matchers - - com.jayway.restassured - rest-assured + org.slf4j + slf4j-simple + 1.7.21 - - diff --git a/steps-module/src/main/java/ru/qatools/school/apidata/CitiesResp.java b/steps-module/src/main/java/ru/qatools/school/apidata/CitiesResp.java new file mode 100644 index 0000000..4e6296d --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/apidata/CitiesResp.java @@ -0,0 +1,18 @@ +package ru.qatools.school.apidata; + +/** + * @author onegines (Eugene Kirienko) + */ +public class CitiesResp { + private int uid; + + private String name; + + public int getUid() { + return uid; + } + + public String getName() { + return name; + } +} diff --git a/steps-module/src/main/java/ru/qatools/school/apidata/SuggestResp.java b/steps-module/src/main/java/ru/qatools/school/apidata/SuggestResp.java new file mode 100644 index 0000000..51085f6 --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/apidata/SuggestResp.java @@ -0,0 +1,76 @@ +package ru.qatools.school.apidata; + +/** + * @author onegines (Eugene Kirienko) + */ +public class SuggestResp { + private long id; + private long uid; + private String name; + private String country; + + public long getId() { + return id; + } + + public long getUid() { + return uid; + } + + public String getName() { + return name; + } + + public String getCountry() { + return country; + } + + public void setId(long id) { + this.id = id; + } + + public void setUid(long uid) { + this.uid = uid; + } + + public void setName(String name) { + this.name = name; + } + + public void setCountry(String country) { + this.country = country; + } + + @Override + public String toString() { + return "SuggestResp{" + + "id=" + id + + ", uid=" + uid + + ", name='" + name + '\'' + + ", country='" + country + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SuggestResp that = (SuggestResp) o; + + if (id != that.id) return false; + if (uid != that.uid) return false; + if (name != null ? !name.equals(that.name) : that.name != null) return false; + return country != null ? country.equals(that.country) : that.country == null; + + } + + @Override + public int hashCode() { + int result = (int) (id ^ (id >>> 32)); + result = 31 * result + (int) (uid ^ (uid >>> 32)); + result = 31 * result + (name != null ? name.hashCode() : 0); + result = 31 * result + (country != null ? country.hashCode() : 0); + return result; + } +} diff --git a/steps-module/src/main/java/ru/qatools/school/apidata/Temperature.java b/steps-module/src/main/java/ru/qatools/school/apidata/Temperature.java new file mode 100644 index 0000000..bfaee6a --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/apidata/Temperature.java @@ -0,0 +1,18 @@ +package ru.qatools.school.apidata; + +/** + * @author onegines + */ +public class Temperature { + + private float value; + private String unit; + + public float getValue() { + return value; + } + + public String getUnit() { + return unit; + } +} diff --git a/steps-module/src/main/java/ru/qatools/school/apidata/WeatherApi.java b/steps-module/src/main/java/ru/qatools/school/apidata/WeatherApi.java new file mode 100644 index 0000000..7d974a0 --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/apidata/WeatherApi.java @@ -0,0 +1,31 @@ +package ru.qatools.school.apidata; + +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Query; + +import java.util.List; + +/** + * @author onegines (Eugene Kirienko) + */ +public interface WeatherApi { + + @GET("/api/suggest") + Call> suggest(); + + @GET("/api/suggest") + Call> suggest(@Query("query") String query); + + @GET("/api/cities") + Call> cities(); + + @GET("/api/cities") + Call> cities(@Query("limit") int limit); + + @GET("/api/weather") + Call weather(); + + @GET("/api/weather") + Call weather(@Query("city") String city); +} diff --git a/steps-module/src/main/java/ru/qatools/school/apidata/WeatherResp.java b/steps-module/src/main/java/ru/qatools/school/apidata/WeatherResp.java new file mode 100644 index 0000000..56cd773 --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/apidata/WeatherResp.java @@ -0,0 +1,21 @@ +package ru.qatools.school.apidata; + +import java.util.List; + +/** + * @author onegines (Eugene Kirienko) + */ +public class WeatherResp { + + private String city; + + private List temperatures; + + public String getCity() { + return city; + } + + public List getTemperatures() { + return temperatures; + } +} 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..9704efd 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; @@ -12,19 +13,39 @@ /** * Created by kurau. + * Changed by onegines (Eugene Kirienko). */ public class MainPage { + @Name("Тело страницы") + @FindBy(tagName = "body") + private HtmlElement body; + + @Name("Список виджетов") + @FindBy(css = ".card.card_md") + private List weatherWidgets; + + @Name("Кнопка добавления виджета") + @FindBy(css = ".new-card") + private HtmlElement addWidgetButton; + public MainPage(WebDriver driver) { PageFactory.initElements(new HtmlElementDecorator(new HtmlElementLocatorFactory(driver)), this); } - @Name("Список виджетов") - @FindBy(css = ".card.card_md") - private List weatherWidget; + public List getWeatherWidgets() { + return weatherWidgets; + } - public List getWeatherWidget() { - return weatherWidget; + public WeatherWidget getFirstWidget() { + return getWeatherWidgets().get(0); } + public HtmlElement getAddWidgetButton() { + return addWidgetButton; + } + + public HtmlElement getBody() { + return body; + } } 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..44294c8 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 @@ -3,6 +3,7 @@ import org.openqa.selenium.Rectangle; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; +import ru.qatools.school.pages.blocks.widgetblocks.WidgetActions; import ru.qatools.school.pages.blocks.widgetblocks.WidgetText; import ru.qatools.school.pages.blocks.widgetblocks.WidgetTitle; import ru.yandex.qatools.htmlelements.annotations.Name; @@ -10,6 +11,7 @@ /** * Created by kurau. + * Changed by onegines (Eugene Kirienko). */ public class WeatherWidget extends HtmlElement { @@ -23,7 +25,7 @@ public class WeatherWidget extends HtmlElement { @Name("Панель управления виджетом") @FindBy(css = ".card-actions") - private WebElement actions; + private WidgetActions widgetActions; public WidgetText getWidgetText() { return widgetText; @@ -33,8 +35,8 @@ public WidgetTitle getWidgetTitle() { return widgetTitle; } - public WebElement getActions() { - return actions; + public WidgetActions getWidgetActions() { + return widgetActions; } public Rectangle getRect() { diff --git a/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetActions.java b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetActions.java new file mode 100644 index 0000000..0985961 --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/WidgetActions.java @@ -0,0 +1,24 @@ +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; + +/** + * Created by onegines (Eugene Kirienko). + */ +public class WidgetActions extends HtmlElement { + + @Name("Кнопка удаления виджета") + @FindBy(css = ".remove-card") + private HtmlElement removeWidgetButton; + + public HtmlElement getRemoveWidgetButton() { + return removeWidgetButton; + } + + public Rectangle getRect() { + return null; + } +} 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..76aed28 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,13 @@ 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.qatools.school.pages.blocks.widgetblocks.infoline.InfoLine; import ru.yandex.qatools.htmlelements.annotations.Name; import ru.yandex.qatools.htmlelements.element.HtmlElement; +import java.util.List; + /** * Created by kurau. */ @@ -13,12 +15,60 @@ 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 weatherTemperature; + + @Name("Цифра градусов") + @FindBy(css = ".weather-temperature__digit") + private HtmlElement weatherTemperatureDigit; - public WebElement getWeatherImage() { + @Name("Условная единица градусов") + @FindBy(css = ".weather-temperature__unit") + private HtmlElement weatherTemperatureUnit; + + @Name("Строки дополнительной информации") + @FindBy(css = ".line.info-line") + private List infoLines; + + public HtmlElement getWeatherImage() { return weatherImage; } + public HtmlElement getWeatherTemperatureDigit() { + return weatherTemperatureDigit; + } + + public HtmlElement getWeatherTemperatureUnit() { + return weatherTemperatureUnit; + } + + public List getInfoLines() { + return infoLines; + } + + public InfoLine getSunriseLine() { + return getInfoLines().get(0); + } + + public InfoLine getSunsetLine() { + return getInfoLines().get(1); + } + + public InfoLine getWindLine() { + return getInfoLines().get(2); + } + + public InfoLine getHumidityLine() { + return getInfoLines().get(3); + } + + public HtmlElement getWeatherTemperature() { + return weatherTemperature; + } + 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..ee08b65 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,14 +1,56 @@ package ru.qatools.school.pages.blocks.widgetblocks; import org.openqa.selenium.Rectangle; +import org.openqa.selenium.support.FindBy; +import ru.qatools.school.pages.blocks.widgetblocks.suggestblocks.CitySuggest; +import ru.yandex.qatools.htmlelements.annotations.Name; import ru.yandex.qatools.htmlelements.element.HtmlElement; +import java.util.List; + /** * Created by kurau. + * Changed by onegines (Eugene Kirienko). */ public class WidgetTitle extends HtmlElement { + @Name("Название города") + @FindBy(css = ".inplace") + private HtmlElement cityName; + + @Name("Текущее время и дата") + @FindBy(css = ".card-title__secondary > div > div") + private HtmlElement currentTimeAndDate; + + @Name("Блок предложенных городов") + @FindBy(css = ".city-suggest") + private HtmlElement citySuggestBlock; + + @Name("Список предложенных городов") + @FindBy(css = ".city") + private List citySuggests; + public Rectangle getRect() { return null; } + + public HtmlElement getCityName() { + return cityName; + } + + public List getCitySuggests() { + return citySuggests; + } + + public HtmlElement getCurrentTimeAndDate() { + return currentTimeAndDate; + } + + public CitySuggest getFirstSuggest() { + return getCitySuggests().get(0); + } + + public HtmlElement getCitySuggestBlock() { + return citySuggestBlock; + } } diff --git a/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/infoline/InfoLine.java b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/infoline/InfoLine.java new file mode 100644 index 0000000..e689331 --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/infoline/InfoLine.java @@ -0,0 +1,40 @@ +package ru.qatools.school.pages.blocks.widgetblocks.infoline; + +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; + +/** + * Created by onegines (Eugene Kirienko). + */ +public class InfoLine extends HtmlElement { + + @Name("Параметр") + @FindBy(css = ".info-line__title") + private HtmlElement title; + + @Name("Значение") + @FindBy(css = ".info-line__value") + private HtmlElement value; + + @Name("Иконка") + @FindBy(css = ".info-line__image") + private HtmlElement image; + + public Rectangle getRect() { + return null; + } + + public HtmlElement getTitle() { + return title; + } + + public HtmlElement getValue() { + return value; + } + + public HtmlElement getImage() { + return image; + } +} diff --git a/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/suggestblocks/CitySuggest.java b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/suggestblocks/CitySuggest.java new file mode 100644 index 0000000..6e271a1 --- /dev/null +++ b/steps-module/src/main/java/ru/qatools/school/pages/blocks/widgetblocks/suggestblocks/CitySuggest.java @@ -0,0 +1,32 @@ +package ru.qatools.school.pages.blocks.widgetblocks.suggestblocks; + +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; + +/** + * Created by onegines (Eugene Kirienko). + */ +public class CitySuggest extends HtmlElement { + + @Name("Название города") + @FindBy(css = ".city__name") + private HtmlElement cityName; + + @Name("Регион") + @FindBy(css = ".city__country") + private HtmlElement countryName; + + public Rectangle getRect() { + return null; + } + + public HtmlElement getCityName() { + return cityName; + } + + public HtmlElement getCountryName() { + return countryName; + } +} 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..526e682 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 @@ -4,8 +4,11 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; +import java.util.concurrent.TimeUnit; + /** * Created by kurau. + * Changed by onegines (Eugene Kirienko). */ public class WebDriverRule extends ExternalResource { @@ -13,6 +16,8 @@ public class WebDriverRule extends ExternalResource { protected void before() throws Throwable { this.driver = new FirefoxDriver(); + this.driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS); + driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS); } 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..3e123f9 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,20 +1,35 @@ package ru.qatools.school.steps.websteps; +import org.apache.commons.lang3.StringUtils; +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.pages.MainPage; 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.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.core.Every.everyItem; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertThat; -import static ru.yandex.qatools.htmlelements.matchers.WebElementMatchers.isDisplayed; +import static ru.yandex.qatools.htmlelements.matchers.WebElementMatchers.*; /** * Created by kurau. + * Changed by onegines (Eugene Kirienko). */ public class DefaultSteps { - public static final String MAIN_PAGE = "http://weather.lanwen.ru/#?cities=%s"; + public static final String MAIN_PAGE = "http://weather.lanwen.ru/"; + public static final String QUERY = "#?cities=%s"; private WebDriver driver; @@ -22,14 +37,95 @@ public DefaultSteps(WebDriver driver) { this.driver = driver; } - @Step("Открываем главную страницу для города «{0}»") - public void openMainPageWithCity(String city) { - driver.get(format(MAIN_PAGE, city)); + @Step("Открываем главную страницу без параметров»") + public void openMainPage() { + driver.get(MAIN_PAGE); + } + + @Step("Открываем главную страницу для городов «{0}»") + public void openMainPageWithCities(String... cities) { + driver.get(MAIN_PAGE + format(QUERY, StringUtils.join(cities, ','))); + } + + @Step("Должен быть заголовок «{0}»") + public void shouldBeTitle(String title) { + assertThat("Заголовок страницы не совпадает", driver.getTitle(), is(title)); + } + + @Step("Должен быть URL «{0}»") + public void shouldBeUrl(String url) { + assertThat("URL страницы не совпадает", driver.getCurrentUrl(), is(url)); } - @Step("Должны видеть на странице «{0}»") + @Step("Должны видеть на странице элемент «{0}»") public void shouldSee(WebElement element) { - assertThat("Должны видеть элемент", element, isDisplayed()); + assertThat("Должны видеть элемент", element, allOf(exists(), isDisplayed())); + } + + @Step("Должны видеть на странице элементы «{0}»") + public void shouldSee(List elements) { + assertThat("Должны видеть элемент", elements, everyItem(allOf(exists(), isDisplayed()))); + } + + @Step("Должны не видеть на странице элемент «{0}»") + public void shouldNotSee(WebElement element) { + assertThat("Должны не видеть элемент", element, not(isDisplayed())); + } + + @Step("Должны увидеть «{1}» элементов(ов) в списке «{0}»") + public void shouldBeThisNumberOfElements(List elements, int count) { + assertThat("Количество элементов не соответствует ожидаемому", elements.size(), is(count)); + } + + @Step("Кликаем по элементу {0}") + public void clickOn(HtmlElement element) { + element.click(); + } + + @Step("Кликаем по элементу {0} {1} раз") + public void clickOn(HtmlElement element, int n) { + for (int i = 0; i < n; i++) { + element.click(); + } + } + + @Step("Удаляем текст в элементе «{0}»") + public void eraseText(WebElement element) { + element.clear(); + } + + @Step("Вводим текст «{1}» в элемент «{0}»") + public void enterText(WebElement element, String text) { + element.sendKeys(text); + } + + @Step("Подтверждаем нажатием Return ввод в элементе «{0}»") + public void confirmText(WebElement element) { + element.sendKeys(Keys.RETURN); + } + + @Step("Элемент «{0}» должен содержать текст «{1}»") + public void shouldHaveText(HtmlElement element, String text) { + assertThat("Текст в элементе не соответствует ожидаемому", element, hasText(text)); + } + + @Step("Элемент «{0}» не должен содержать текст «{1}»") + public void shouldNotHaveText(HtmlElement element, String text) { + assertThat("Текст в элементе должен быть другим", element, not(hasText(text))); + } + + @Step("Элементы в «{0}» не должны содержать текст «{1}»") + public void shouldNotHaveText(List elements, String text) { + assertThat("Текст в элементе должен быть другим", new ArrayList<>(elements), everyItem(not(hasText(text)))); + } + + @Step("Ждём элемент «{0}» максимум «{1}» секунд(ы)") + public void waitUntilElementReady(HtmlElement element, int timeOut) { + (new WebDriverWait(driver, timeOut)) + .until(ExpectedConditions.and( + ExpectedConditions.not(ExpectedConditions.stalenessOf(element)), + ExpectedConditions.visibilityOf(element)) + ); } private MainPage onMainPage() {