/*
* JBoss, Home of Professional Open Source
* Copyright 2010-2016, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.richfaces.tests.metamer.ftest.richProgressBar;
import static org.richfaces.tests.metamer.ftest.extension.configurator.use.annotation.ValuesFrom.FROM_FIELD;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jboss.arquillian.graphene.Graphene;
import org.jboss.arquillian.graphene.page.Page;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;
import org.richfaces.fragment.common.Utils;
import org.richfaces.tests.metamer.bean.rich.RichProgressBarBean;
import org.richfaces.tests.metamer.ftest.AbstractWebDriverTest;
import org.richfaces.tests.metamer.ftest.BasicAttributes;
import org.richfaces.tests.metamer.ftest.extension.attributes.coverage.annotations.CoversAttributes;
import org.richfaces.tests.metamer.ftest.extension.configurator.templates.annotation.Templates;
import org.richfaces.tests.metamer.ftest.extension.configurator.use.annotation.UseWithField;
import org.richfaces.tests.metamer.ftest.webdriver.Attributes;
import org.richfaces.tests.metamer.ftest.webdriver.MetamerPage;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* Test case for page /faces/components/richProgressBar/ajaxMode.xhtml
*
* @author <a href="https://community.jboss.org/people/ppitonak">Pavol Pitonak</a>
* @author <a href="mailto:jstefek@redhat.com">Jiri Stefek</a>
* @since 4.3.0.M3
*/
public class TestProgressBarAjax extends AbstractWebDriverTest {
private static final DateTimeFormatter FORMATTER = DateTimeFormat.forPattern("HH:mm:ss.SSS");
private final Integer[] ints = { 2000, 2500 };
@Page
private ProgressBarPage page;
private final Attributes<ProgressBarAttributes> progressBarAttributes = getAttributes();
private Integer testInterval;
private long countAverage(List<DateTime> times) {
long total = 0;
for (int i = 0; i < times.size() - 1; i++) {
total += times.get(i + 1).getMillis() - times.get(i).getMillis();
}
return Math.abs(total / (times.size() - 1));
}
private int getExpectedNumberOfUpdates() {
int max = Integer.parseInt(progressBarAttributes.get(ProgressBarAttributes.maxValue));
double interval = Double.parseDouble(progressBarAttributes.get(ProgressBarAttributes.interval));
double maximumTime = RichProgressBarBean.UPDATE_INTERVAL * max;//s
int updates = (int) (maximumTime / interval) - 1; //-1 to be sure that no invalid values will be gathered
if (updates < 2) {
throw new RuntimeException("The measurement will not be possible. "
+ "Reduce the @interval or increase the @maxValue.");
}
return updates;
}
private long getExpectedRunTimeInMillis() {
int max = Integer.parseInt(progressBarAttributes.get(ProgressBarAttributes.maxValue));
double maximumTime = RichProgressBarBean.UPDATE_INTERVAL * max;//s
return (long) (maximumTime * 1.5);
}
private int getProgress() {
String width = page.getProgressElement().getCssValue("width");
float result;
if (width.contains("%")) {
result = Float.parseFloat(width.replace("%", ""));
} else {
result = Float.parseFloat(width.replace("px", "")) / 2; // progress bar width is 200px
}
result *= Integer.valueOf(progressBarAttributes.get(ProgressBarAttributes.maxValue)) / 100.0;//normalize
return (int) result;
}
@Override
public String getComponentTestPagePath() {
return "richProgressBar/ajaxMode.xhtml";
}
@Test
@CoversAttributes("data")
public void testData() {
testData(new Action() {
@Override
public void perform() {
MetamerPage.requestTimeChangesWaiting(page.getStartButtonElement()).click();
// waiting for next request, which will carry the data
String reqTime = page.getRequestTimeElement().getText();
Graphene.waitAjax().withMessage("Page was not updated")
.until().element(page.getRequestTimeElement()).text().not().equalTo(reqTime);
}
});
MetamerPage.requestTimeChangesWaiting(page.getStopPollingButtonElement()).click();
int timeout = Integer.parseInt(progressBarAttributes.get(ProgressBarAttributes.interval)) + 300;
waiting(timeout);//wait for the last request to finish
}
@Test(groups = "smoke")
@CoversAttributes("enabled")
public void testEnabled() {
progressBarAttributes.set(ProgressBarAttributes.maxValue, 100);//longer progress
int timeout = Integer.parseInt(progressBarAttributes.get(ProgressBarAttributes.interval)) + 300;
MetamerPage.requestTimeChangesWaiting(page.getStartButtonElement()).click();
waiting(timeout * 2);//wait for 2 requests
//waiting for next request, which will carry the data
MetamerPage.requestTimeChangesWaiting(page.getStopPollingButtonElement()).click();
waiting(timeout);//wait for the last request
String reqTime = page.getRequestTimeElement().getText();
try {
Graphene.waitModel()
.withTimeout(timeout, TimeUnit.MILLISECONDS)
.until().element(page.getRequestTimeElement()).text().not().equalTo(reqTime);
} catch (TimeoutException e) {// OK
String progress = Utils.getTextFromHiddenElement(page.getLabelElement()).replace("%", "").trim();
Assert.assertTrue(Integer.valueOf(progress) < 100, "Progress should be lower than 100 %");
return;
}
Assert.fail("The request time should not change after polling is stopped.");
}
@Test
@CoversAttributes({ "maxValue", "onbegin", "onbeforedomupdate", "oncomplete" })
public void testEvents() {
attsSetter()
.setAttribute(ProgressBarAttributes.maxValue).toValue(5)
.setAttribute(ProgressBarAttributes.onbegin).toValue("metamerEvents += \"begin \"")
.setAttribute(ProgressBarAttributes.onbeforedomupdate).toValue("metamerEvents += \"beforedomupdate \"")
.setAttribute(ProgressBarAttributes.oncomplete).toValue("metamerEvents += \"complete \"")
.asSingleAction().perform();
long expectedRunTime = getExpectedRunTimeInMillis();
executeJS("metamerEvents = \"\"");
MetamerPage.requestTimeChangesWaiting(page.getStartButtonElement()).click();
Graphene.waitAjax()
.withTimeout(expectedRunTime, TimeUnit.MILLISECONDS)
.withMessage("Progress bar should disappear after it finishes.")
.until()
.element(page.getRestartButtonElement())
.is().present();
String[] events = ((String) executeJS("return metamerEvents")).split(" ");
assertEquals(events.length % 3, 0, "Number of events should be a multiple of 3.");
for (int i = 0; i < events.length; i += 3) {
assertEquals(events[i], "begin", "Event nr." + i + " should be begin.");
assertEquals(events[i + 1], "beforedomupdate", "Event nr." + (i + 1) + " should be beforedomupdate.");
assertEquals(events[i + 2], "complete", "Event nr." + (i + 2) + " should be complete.");
}
}
@Test
@CoversAttributes("finishClass")
@Templates(value = "plain")
public void testFinishClass() {
testStyleClass(page.getFinishElement(), BasicAttributes.finishClass);
}
@Test
public void testInit() {
assertPresent(page.getProgressBarElement(), "Progress bar is not present on the page.");
assertVisible(page.getProgressBarElement(), "Progress bar should be visible on the page.");
assertVisible(page.getInitialOutputElement(), "Initial output should be visible on the page.");
assertNotPresent(page.getFinishOutputElement(), "Finish output should not be present on the page.");
assertVisible(page.getStartButtonElement(), "Start button is not visible on the page.");
assertNotPresent(page.getRestartButtonElement(), "Restart button should not be present on the page.");
assertNotVisible(page.getRemainElement(), "Progress bar should not show progress.");
assertNotVisible(page.getProgressElement(), "Progress bar should not show progress.");
assertNotVisible(page.getLabelElement(), "Progress bar should not show progress.");
}
@Test
@CoversAttributes("initialClass")
@Templates(value = "plain")
public void testInitialClass() {
testStyleClass(page.getInitElement(), BasicAttributes.initialClass);
}
@Test
@CoversAttributes("interval")
@UseWithField(field = "testInterval", valuesFrom = FROM_FIELD, value = "ints")
public void testInterval() {
testOneRunOfProgressBar(page.getStartButtonElement(), testInterval);
}
@Test
@CoversAttributes("onclick")
@Templates(value = "plain")
public void testOnclick() {
testFireEvent(progressBarAttributes, ProgressBarAttributes.onclick, new Actions(driver).click(page.getProgressBarElement())
.build());
}
@Test
@CoversAttributes("ondblclick")
@Templates(value = "plain")
public void testOndblclick() {
testFireEvent(progressBarAttributes, ProgressBarAttributes.ondblclick,
new Actions(driver).doubleClick(page.getProgressBarElement()).build());
}
private void testOneRunOfProgressBar(WebElement button, int interval) {
progressBarAttributes.set(ProgressBarAttributes.interval, interval);
long delta = (long) (interval * 0.5);
long maxWaitTime = interval + delta;
List<String> timesString = new ArrayList<String>();
List<String> labelsList = new ArrayList<String>();
List<Integer> progressList = new ArrayList<Integer>();
long expectedRunTime = getExpectedRunTimeInMillis();
int expectedNumberOfUpdates = getExpectedNumberOfUpdates();
MetamerPage.requestTimeChangesWaiting(button).click();
String timeString = page.getRequestTimeElement().getText();
timesString.add(timeString);
for (int i = 0; i < expectedNumberOfUpdates; i++) {
Graphene.waitGui().withTimeout(maxWaitTime, TimeUnit.MILLISECONDS)
.withMessage("Page was not updated")
.until().element(page.getRequestTimeElement()).text().not().equalTo(timeString);
timeString = page.getRequestTimeElement().getText();
timesString.add(timeString);
labelsList.add(page.getLabelElement().getText().replace(" %", ""));
progressList.add(getProgress());
}
labelsList.remove("");//there can be empty string from label after progress finishes
List<DateTime> timesList = new ArrayList<DateTime>(timesString.size());
for (String s : timesString) {
timesList.add(FORMATTER.parseDateTime(s));
}
long average = countAverage(timesList);
assertTrue(Math.abs(average - interval) < delta, "Average interval " + average + " is too far from set value ("
+ interval + ")");
assertFalse(average < interval, "Average interval " + average + " cannot be smaller than set value ("
+ interval + ")");
int first, second;
for (int i = 0; i < labelsList.size() - 1; i++) {
first = Integer.parseInt(labelsList.get(i));
second = Integer.parseInt(labelsList.get(i + 1));
assertTrue(first <= second, "Number of percent in label should be increasing: " + first + "!<= " + second);
}
for (int i = 0; i < progressList.size() - 1; i++) {
first = progressList.get(i);
second = progressList.get(i + 1);
assertTrue(progressList.get(i) <= progressList.get(i + 1), "Progress of progress bar should be increasing: " + first + "!<= " + second);
}
Graphene.waitGui()
.withTimeout(expectedRunTime, TimeUnit.MILLISECONDS)
.withMessage("Progress bar should disappear after it finishes.")
.until()
.element(page.getRestartButtonElement())
.is().present();
assertPresent(page.getFinishOutputElement(), "Complete output should be present on the page.");
assertPresent(page.getProgressBarElement(), "Progress bar is not present on the page.");
assertNotPresent(page.getInitialOutputElement(), "Initial output should not be present on the page.");
assertPresent(page.getFinishOutputElement(), "Complete output should be present on the page.");
assertNotPresent(page.getStartButtonElement(), "Start button should not be present on the page.");
assertPresent(page.getRestartButtonElement(), "Restart button should be present on the page.");
assertNotVisible(page.getRemainElement(), "Progress bar should not show progress.");
}
@Test
@CoversAttributes({ "maxValue", "onfinish" })
public void testOnfinish() {
attsSetter()
.setAttribute(ProgressBarAttributes.maxValue).toValue(5)//the test will be quicker
.setAttribute(ProgressBarAttributes.onfinish).toValue("metamerEvents += \"finish \"")
.asSingleAction().perform();
executeJS("metamerEvents = \"\"");
long expectedRunTime = getExpectedRunTimeInMillis();
MetamerPage.requestTimeChangesWaiting(page.getStartButtonElement()).click();
Graphene.waitAjax()
.withTimeout(expectedRunTime, TimeUnit.MILLISECONDS)
.withMessage("Progress bar should disappear after it finishes.")
.until()
.element(page.getRestartButtonElement())
.is().present();
String[] events = ((String) executeJS("return metamerEvents")).split(" ");
assertEquals(events.length, 1, "Only one event should be fired.");
assertEquals(events[0], "finish", "Onfinish doesn't work.");
}
@Test
@CoversAttributes("onmousedown")
@Templates(value = "plain")
public void testOnmousedown() {
testFireEvent(progressBarAttributes, ProgressBarAttributes.onmousedown,
new Actions(driver).clickAndHold(page.getProgressBarElement()).build());
}
@Test
@CoversAttributes("onmousemove")
@Templates(value = "plain")
public void testOnmousemove() {
testFireEvent(progressBarAttributes, ProgressBarAttributes.onmousemove,
new Actions(driver).moveToElement(page.getProgressBarElement()).build());
}
@Test
@CoversAttributes("onmouseout")
@Templates(value = "plain")
public void testOnmouseout() {
testFireEventWithJS(page.getProgressBarElement(), progressBarAttributes, ProgressBarAttributes.onmouseout);
}
@Test
@CoversAttributes("onmouseover")
@Templates(value = "plain")
public void testOnmouseover() {
new Actions(driver).moveToElement(page.getRequestTimeElement()).perform();
testFireEvent(progressBarAttributes, ProgressBarAttributes.onmouseover,
new Actions(driver).moveToElement(page.getProgressBarElement()).build());
}
@Test
@CoversAttributes("onmouseup")
@Templates(value = "plain")
public void testOnmouseup() {
testFireEvent(progressBarAttributes, ProgressBarAttributes.onmouseup,
new Actions(driver).click(page.getProgressBarElement()).build());
}
@Test
@CoversAttributes("mode")// ajax
public void testProgress() {
testOneRunOfProgressBar(page.getStartButtonElement(), 2000);
testOneRunOfProgressBar(page.getRestartButtonElement(), 2000);
}
@Test
@CoversAttributes("progressClass")
@Templates(value = "plain")
public void testProgressClass() {
testStyleClass(page.getProgressElement(), BasicAttributes.progressClass);
}
@Test
@CoversAttributes("remainingClass")
@Templates(value = "plain")
public void testRemainingClass() {
testStyleClass(page.getRemainElement(), BasicAttributes.remainingClass);
}
@Test
@CoversAttributes("rendered")
@Templates(value = "plain")
public void testRendered() {
progressBarAttributes.set(ProgressBarAttributes.rendered, Boolean.FALSE);
assertNotPresent(page.getProgressBarElement(), "Progress bar should not be rendered when rendered=false.");
}
@Test
public void testStart() {
MetamerPage.requestTimeChangesWaiting(page.getStartButtonElement()).click();
String labelValue = page.getLabelElement().getText();
assertTrue("1 %".equals(labelValue) || "2 %".equals(labelValue),
"Progress bar's label after start should be \"1 %\" or \"2 %\".");
assertVisible(page.getRemainElement(), "Progress bar should show progress.");
assertVisible(page.getProgressElement(), "Progress bar should not show progress.");
assertVisible(page.getProgressBarElement(), "Progress bar should be visible on the page.");
assertNotPresent(page.getInitialOutputElement(), "Initial output should not be present on the page.");
assertNotPresent(page.getFinishOutputElement(), "Complete output should not be present on the page.");
assertNotPresent(page.getStartButtonElement(), "Start button should not be present on the page.");
assertNotPresent(page.getRestartButtonElement(), "Restart button should not be present on the page.");
}
@Test
@CoversAttributes("style")
@Templates(value = "plain")
public void testStyle() {
testStyle(page.getProgressBarElement());
}
@Test
@CoversAttributes("styleClass")
@Templates(value = "plain")
public void testStyleClass() {
testStyleClass(page.getProgressBarElement());
}
}