package org.jboss.as.quickstarts.spring.petclinic.test.webdriver; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.jboss.arquillian.graphene.Graphene.guardHttp; import static org.jboss.arquillian.graphene.Graphene.waitAjax; import static org.jboss.arquillian.graphene.Graphene.waitGui; import static org.jboss.arquillian.graphene.Graphene.waitModel; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.ArrayList; import java.util.List; import nu.xom.Builder; import nu.xom.Document; import nu.xom.Node; import nu.xom.Nodes; import nu.xom.ParsingException; import nu.xom.ValidityException; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.graphene.findby.ByJQuery; import org.jboss.arquillian.graphene.findby.FindByJQuery; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.junit.InSequence; import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.shrinkwrap.api.Archive; import org.json.JSONArray; import org.json.JSONObject; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; /** * @author <a href="kpiwko@redhat.com>Karel Piwko</a> * @author <a href="rfalhar@redhat.com>Radek Falhar</a> */ @RunWith(Arquillian.class) public class PetclinicTest { private final CloseableHttpClient httpClient = HttpClientBuilder.create().build(); @FindByJQuery("h2:contains('Pets and Visits')") WebElement PETS_AND_VISITS; @FindByJQuery("a:contains('Find owners')") WebElement FIND_OWNER_LINK; @FindByJQuery("input#lastName") WebElement LAST_NAME_INPUT; @FindByJQuery("button:contains('Find Owner')") WebElement LAST_NAME_SUBMIT; @FindByJQuery("a:contains('Add Visit')") List<WebElement> ADD_VISIT_LINK; @FindByJQuery("table:contains('Samantha') a:contains('Add Visit')") WebElement SAMANTHA_ADD_VISIT_LINK; @FindByJQuery("table:contains('Samantha') table tr:eq(3)") WebElement SAMANTHA_THIRD_VISIT; @FindBy(id = "date") WebElement VISIT_DATE; @FindBy(id = "description") WebElement VISIT_DESCRIPTION; @FindByJQuery("button:contains('Add Visit')") WebElement VISIT_SUBMIT; @FindByJQuery("a:contains('Edit Pet')") List<WebElement> EDIT_PET_LINK; @FindBy(id = "name") WebElement PET_NAME; @FindBy(id = "birthDate") WebElement PET_BIRTH; @FindByJQuery("#type option[value = 'hamster']") WebElement HAMSTER; @FindByJQuery("table tr dl:contains('Maxous')") WebElement HAMSTER_MAXOUS; @FindByJQuery("button:contains('Update Pet')") WebElement PET_SUBMIT; @FindByJQuery("input[value='Delete Pet']") WebElement DELETE_PET_SUBMIT; @FindByJQuery("span:contains('invalid date')") WebElement DATE_ERROR; @FindByJQuery("span:contains('numeric value out of bounds')") WebElement NUMERIC_ERROR; @FindByJQuery("span:contains('is required')") WebElement IS_REQUIRED_ERROR; @FindByJQuery("a:contains('Add Owner')") WebElement ADD_OWNER_LINK; @FindByJQuery("#add-owner-form input") List<WebElement> NEW_OWNER_FORM; @FindByJQuery("button:contains('Add Owner')") WebElement ADD_OWNER_BUTTON; @FindByJQuery("table:contains('Telephone')") WebElement OWNER_FORM; @FindByJQuery("a:contains('Add New Pet')") WebElement ADD_NEW_PET_LINK; @FindByJQuery("button:contains('Add Pet')") WebElement ADD_PET_BUTTON; @FindByJQuery("form#pet input") List<WebElement> NEW_PET_FORM; @FindByJQuery("#type option[value = 'snake']") WebElement SNAKE; @FindByJQuery("table tr dl:contains('Dean')") WebElement SNAKE_DEAN; @FindByJQuery("a:contains('Veterinarians')") WebElement VETERINARIANS_LINK; @FindByJQuery("table#vets tbody tr") List<WebElement> VETS_TABLE_ROWS; @FindByJQuery("label:contains('Search') input") WebElement SEARCH_INPUT; @FindByJQuery("a:contains('Error')") WebElement ERROR_LINK; @FindByJQuery("h2:contains('Something happened...')") WebElement ERROR_LABEL; @Drone protected WebDriver driver; @ArquillianResource URL contextPath; @Deployment(testable = false) public static Archive<?> archive() { return Deployments.archive(); } @Test @InSequence(1) public void findOwner() { driver.get(contextPath.toString()); waitModel().withMessage("Waiting for owner search link").until().element(FIND_OWNER_LINK).is().visible(); guardHttp(FIND_OWNER_LINK).click(); LAST_NAME_INPUT.sendKeys("Coleman"); guardHttp(LAST_NAME_SUBMIT).click(); waitModel().withMessage("Pets and visits page should be loaded").until().element(PETS_AND_VISITS).is().visible(); Assert.assertEquals("There should be two pet which can have a visit added.", 2, ADD_VISIT_LINK.size()); } @Test @InSequence(2) public void addVisit() { guardHttp(SAMANTHA_ADD_VISIT_LINK).click(); VISIT_DATE.clear(); VISIT_DATE.sendKeys("2009/03/21"); VISIT_DESCRIPTION.sendKeys("Check paws!"); guardHttp(VISIT_SUBMIT).click(); waitModel().withMessage("Pets and visits page should be loaded").until().element(PETS_AND_VISITS).is().visible(); // TODO: fix the date Assert.assertTrue(SAMANTHA_THIRD_VISIT.getText().contains("Check paws!") && SAMANTHA_THIRD_VISIT.getText().contains("2009-03-2")); } @Test @InSequence(3) public void editPet() { Assert.assertEquals("There are two pet which can be edited.", 2, EDIT_PET_LINK.size()); guardHttp(EDIT_PET_LINK.get(0)).click(); waitGui().withMessage("Name input is not present").until().element(PET_NAME).is().visible(); PET_NAME.clear(); PET_NAME.sendKeys("Maxous"); PET_BIRTH.clear(); PET_BIRTH.sendKeys("1995/03/33"); guardHttp(PET_SUBMIT).click(); waitGui().withMessage("The date is incorrect").until().element(DATE_ERROR).is().visible(); PET_BIRTH.clear(); PET_BIRTH.sendKeys("1995/03/09"); HAMSTER.click(); guardHttp(PET_SUBMIT).click(); waitGui().withMessage("Pets and visits page should be loaded").until().element(HAMSTER_MAXOUS).is().visible(); Assert.assertTrue(HAMSTER_MAXOUS.getText().contains("hamster")); // TODO: fix the date Assert.assertTrue(HAMSTER_MAXOUS.getText().contains("1995-03-0")); Assert.assertTrue(HAMSTER_MAXOUS.getText().contains("hamster")); } @Test @InSequence(4) public void addOwner() { waitModel().withMessage("Waiting for owner search link").until().element(FIND_OWNER_LINK).is().visible(); guardHttp(FIND_OWNER_LINK).click(); waitGui().until().element(ADD_OWNER_LINK).is().visible(); guardHttp(ADD_OWNER_LINK).click(); String[] newOwner = new String[] { "Sal", "Paradise", "Market Street 1", "Denver", "telephone" }; for (int i = 0; i < newOwner.length; i++) { NEW_OWNER_FORM.get(i).clear(); NEW_OWNER_FORM.get(i).sendKeys(newOwner[i]); } guardHttp(ADD_OWNER_BUTTON).click(); waitModel().until().element(NUMERIC_ERROR).is().visible(); NEW_OWNER_FORM.get(4).clear(); NEW_OWNER_FORM.get(4).sendKeys("486351729"); guardHttp(ADD_OWNER_BUTTON).click(); waitModel().until().element(OWNER_FORM).is().visible(); Assert.assertEquals(newOwner[0] + " " + newOwner[1], OWNER_FORM.findElement(ByJQuery.selector("tr:contains('Name') td b")).getText()); Assert.assertEquals(newOwner[2], OWNER_FORM.findElement(ByJQuery.selector("tr:contains('Address') td")).getText()); Assert.assertEquals(newOwner[3], OWNER_FORM.findElement(ByJQuery.selector("tr:contains('City') td")).getText()); Assert.assertEquals("486351729", OWNER_FORM.findElement(ByJQuery.selector("tr:contains('Telephone') td")).getText()); } @Test @InSequence(5) public void addPet() { waitGui().until().element(ADD_NEW_PET_LINK).is().visible(); guardHttp(ADD_NEW_PET_LINK).click(); waitGui().until().element(ADD_PET_BUTTON).is().visible(); NEW_PET_FORM.get(1).clear(); NEW_PET_FORM.get(1).sendKeys("Dean"); NEW_PET_FORM.get(2).clear(); NEW_PET_FORM.get(2).sendKeys("2013/09/11"); guardHttp(ADD_PET_BUTTON).click(); waitGui().until().element(IS_REQUIRED_ERROR).is().visible(); SNAKE.click(); guardHttp(ADD_PET_BUTTON).click(); waitModel().until().element(SNAKE_DEAN).is().visible(); // TODO: fix the date Assert.assertTrue(SNAKE_DEAN.getText().contains("2013-09-1")); Assert.assertTrue(SNAKE_DEAN.getText().contains("snake")); } @Test @InSequence(6) public void findVet() { openVetsPage(); SEARCH_INPUT.sendKeys("ra"); Assert.assertThat(VETS_TABLE_ROWS.size(), is(equalTo(3))); SEARCH_INPUT.sendKeys("d"); Assert.assertThat(VETS_TABLE_ROWS.size(), is(equalTo(2))); SEARCH_INPUT.clear(); SEARCH_INPUT.sendKeys("sha"); Assert.assertThat(VETS_TABLE_ROWS.size(), is(equalTo(1))); SEARCH_INPUT.sendKeys("x"); Assert.assertThat(VETS_TABLE_ROWS.size(), is(equalTo(1))); VETS_TABLE_ROWS.get(0).getText().contains("No matching records found"); } @Test @InSequence(7) public void checkXmlAndFeedOfVets() throws UnsupportedEncodingException, IOException, ValidityException, ParsingException { openVetsPage(); List<Vet> vets = new ArrayList<>(); for (WebElement vetRow : VETS_TABLE_ROWS) { List<WebElement> vetAttributes = vetRow.findElements(ByJQuery.selector("td")); String[] vetName = vetAttributes.get(0).getText().split(" "); String[] vetSpecialties = vetAttributes.get(1).getText().split(" "); vets.add(new Vet(vetName[0], vetName[1], vetSpecialties)); } URL url = new URL(driver.getCurrentUrl().replace("vets.html", "vets.xml")); InputStreamReader is = new InputStreamReader(url.openStream(), "UTF-8"); checkXml(vets, new Builder().build(is)); checkJson(vets, driver.getCurrentUrl().replace("vets.html", "vets.json")); } @Test @InSequence(8) public void throwException() { waitGui().until().element(ERROR_LINK).is().visible(); guardHttp(ERROR_LINK).click(); waitAjax().until().element(ERROR_LABEL).is().visible(); } private void openVetsPage() { waitGui().until().element(VETERINARIANS_LINK).is().visible(); guardHttp(VETERINARIANS_LINK).click(); waitModel().until().element(SEARCH_INPUT).is().visible(); Assert.assertThat(VETS_TABLE_ROWS.size(), is(equalTo(6))); } private void checkJson(List<Vet> vets, String url) throws ClientProtocolException, IOException { HttpResponse response = httpClient.execute(new HttpGet(url)); Assert.assertEquals(200, response.getStatusLine().getStatusCode()); String responseBody = EntityUtils.toString(response.getEntity()); JSONArray vetArr = new JSONObject(responseBody).getJSONArray("vetList"); List<Vet> vetsFromJson = createListOfVetsFromJson(vetArr); // TODO more complex check whether the lists of Vets are equal than just checking the size Assert.assertEquals(vets.size(), vetsFromJson.size()); } private List<Vet> createListOfVetsFromJson(JSONArray vetArr) { List<Vet> vetsFromJson = new ArrayList<>(); for (int i = 0; i < vetArr.length(); i++) { JSONObject jsonVet = vetArr.getJSONObject(i); JSONArray specialtiesArr = jsonVet.getJSONArray("specialties"); String firstName = jsonVet.getString("firstName"); String lastName = jsonVet.getString("lastName"); String[] specialties = new String[specialtiesArr.length() == 0 ? 1 : specialtiesArr.length()]; if (specialtiesArr.length() == 0) { specialtiesArr.put(new JSONObject("{\"name\":none}")); } for (int j = 0; j < specialtiesArr.length(); j++) { specialties[j] = specialtiesArr.getJSONObject(j).getString("name"); } vetsFromJson.add(new Vet(firstName, lastName, specialties)); } return vetsFromJson; } private void checkXml(List<Vet> vets, Document document) { Assert.assertThat(document.query("//vetList").size(), is(equalTo(6))); String queryTemplate = "//vetList/firstName[text()='%1$s' and ../lastName[text()='%2$s']%3$s]/../id"; for (Vet vet : vets) { String query = ""; int numberOfSpecs = 0; if (vet.getSpecialties().length > 0 && !vet.getSpecialties()[0].equals("none")) { StringBuilder specQuery = new StringBuilder(""); numberOfSpecs = vet.getSpecialties().length; for (int i = 1; i <= numberOfSpecs; i++) { specQuery.append(" and ../specialties/name[text()='%" + i + "$s']"); } query = String.format(queryTemplate, vet.getFirstName(), vet.getLastName(), specQuery.toString()); query = String.format(query, (Object[]) vet.getSpecialties()); } else { query = String.format(queryTemplate, vet.getFirstName(), vet.getLastName(), ""); } Nodes nodes = document.query(query); Assert.assertThat(nodes.size(), is(equalTo(1))); Node vetId = nodes.get(0); Assert.assertThat(vetId.query("../firstName").size(), is(equalTo(1))); Assert.assertThat(vetId.query("../lastName").size(), is(equalTo(1))); Assert.assertThat(vetId.query("../specialties").size(), is(equalTo(numberOfSpecs))); } } }