/*
* 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.richValidator;
import java.text.MessageFormat;
import java.util.EnumMap;
import java.util.Map;
import org.jboss.arquillian.graphene.Graphene;
import org.jboss.arquillian.graphene.condition.element.WebElementConditionFactory;
import org.jboss.arquillian.graphene.page.Page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.richfaces.fragment.message.RichFacesMessage;
import org.richfaces.fragment.popupPanel.PopupPanel;
import org.richfaces.fragment.status.Status.StatusState;
import org.richfaces.tests.metamer.ftest.AbstractWebDriverTest;
import org.richfaces.tests.metamer.ftest.webdriver.MetamerPage.WaitRequestType;
import org.richfaces.tests.metamer.validation.AssertFalseBean;
import org.richfaces.tests.metamer.validation.AssertTrueBean;
import org.richfaces.tests.metamer.validation.DecimalMinMaxBean;
import org.richfaces.tests.metamer.validation.DigitsBean;
import org.richfaces.tests.metamer.validation.FutureBean;
import org.richfaces.tests.metamer.validation.MaxBean;
import org.richfaces.tests.metamer.validation.MinBean;
import org.richfaces.tests.metamer.validation.MinMaxBean;
import org.richfaces.tests.metamer.validation.NotEmptyBean;
import org.richfaces.tests.metamer.validation.NotNullBean;
import org.richfaces.tests.metamer.validation.PastBean;
import org.richfaces.tests.metamer.validation.PatternBean;
import org.richfaces.tests.metamer.validation.SizeBean;
import org.richfaces.tests.metamer.validation.StringSizeBean;
import org.richfaces.tests.metamer.validator.StringRichFacesValidator;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import com.google.common.base.Predicate;
/**
* Abstract class with selenium test for validators
*
* @author <a href="mailto:jjamrich@redhat.com">Jan Jamrich</a>
*/
public abstract class AbstractValidatorsTest extends AbstractWebDriverTest {
private final Map<ID, String[]> messages = new EnumMap<AbstractValidatorsTest.ID, String[]>(AbstractValidatorsTest.ID.class);
@Page
private ValidatorSimplePage page;
private final Map<ID, String> wrongValue = new EnumMap<AbstractValidatorsTest.ID, String>(AbstractValidatorsTest.ID.class);
private void checkAllErrorMessagesAreVisibleAndCorrect() {
waitUtilMessageWithIDIsVisibleAndCorrect(ID.assertFalse);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.assertTrue);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.custom);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.decimalMinMax);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.digits);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.future);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.max);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.min);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.minMax);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.notEmpty);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.notNull);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.past);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.pattern);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.size);
waitUtilMessageWithIDIsVisibleAndCorrect(ID.stringSize);
if (new WebElementConditionFactory(getPage().getInputRegexp()).isPresent().apply(driver)) {
// regExp validator isn't present in JSR303 validation
waitUtilMessageWithIDIsVisibleAndCorrect(ID.regexp);
}
}
private void clickCorrectButton() {
getMetamerPage().performJSClickOnButton(getPage().getSetCorrectBtn(), WaitRequestType.NONE);
}
private void clickWrongButton() {
getMetamerPage().performJSClickOnButton(getPage().getSetWrongBtn(), WaitRequestType.NONE);
}
protected RichFacesMessage getMessageForID(ID id) {
switch (id) {
case assertFalse:
return getPage().getMsgAssertFalse();
case assertTrue:
return getPage().getMsgAssertTrue();
case custom:
return getPage().getMsgCustom();
case decimalMinMax:
return getPage().getMsgDecimalMinMax();
case digits:
return getPage().getMsgDigits();
case future:
return getPage().getMsgFuture();
case max:
return getPage().getMsgMax();
case min:
return getPage().getMsgMin();
case minMax:
return getPage().getMsgMinMax();
case notEmpty:
return getPage().getMsgNotEmpty();
case notNull:
return getPage().getMsgNotNull();
case past:
return getPage().getMsgPast();
case pattern:
return getPage().getMsgPattern();
case regexp:
return getPage().getMsgRegexp();
case size:
return getPage().getMsgSize();
case stringSize:
return getPage().getMsgStringSize();
default:
throw new UnsupportedOperationException("Unsupported id " + id);
}
}
/**
* @return the page
*/
public ValidatorSimplePage getPage() {
return page;
}
@BeforeClass(groups = "smoke")
public void init() {
messages.put(ID.assertTrue, new String[] { AssertTrueBean.VALIDATION_MSG });
messages.put(ID.assertFalse, new String[] { AssertFalseBean.VALIDATION_MSG });
messages.put(ID.decimalMinMax, new String[] { DecimalMinMaxBean.VALIDATION_MSG });
messages.put(ID.digits, new String[] { DigitsBean.VALIDATION_MSG });
messages.put(ID.future, new String[] { FutureBean.VALIDATION_MSG });
messages.put(ID.max, new String[] { MaxBean.VALIDATION_MSG });
messages.put(ID.min, new String[] { MinBean.VALIDATION_MSG });
messages.put(ID.minMax, new String[] { MinMaxBean.VALIDATION_MSG });
messages.put(ID.notEmpty, new String[] { NotEmptyBean.VALIDATION_MSG });
messages.put(ID.notNull, new String[] { NotNullBean.VALIDATION_MSG });
messages.put(ID.past, new String[] { PastBean.VALIDATION_MSG });
messages.put(ID.pattern, new String[] { PatternBean.VALIDATION_MSG });
messages.put(ID.custom, new String[] { StringRichFacesValidator.VALIDATION_ERROR_MSG });
messages.put(ID.regexp, new String[] { "Regex pattern of '\\d{3}' not matched", "Validation Error: Value not according to pattern '\\d{3}'" });
messages.put(ID.stringSize, new String[] { StringSizeBean.VALIDATION_MSG });
messages.put(ID.size, new String[] { SizeBean.VALIDATION_MSG }); // RF-11035
wrongValue.put(ID.assertTrue, "false");
wrongValue.put(ID.assertFalse, "true");
wrongValue.put(ID.decimalMinMax, "10.688");
wrongValue.put(ID.digits, "15.627123");
wrongValue.put(ID.future, "1 Jan 2013");
wrongValue.put(ID.max, "122");
wrongValue.put(ID.min, "-544");
wrongValue.put(ID.minMax, "-5");
wrongValue.put(ID.notEmpty, "");
wrongValue.put(ID.notNull, null);
wrongValue.put(ID.past, "1 Jan 3013");
wrongValue.put(ID.pattern, "@@@");
wrongValue.put(ID.custom, "@@@");
wrongValue.put(ID.regexp, "@@@");
wrongValue.put(ID.stringSize, "JSF 2");
wrongValue.put(ID.size, "B"); // RF-11035
}
protected void preventViewExpiredException() {
blur(WaitRequestType.NONE);
waiting(500);
getMetamerPage().getStatus().advanced().waitUntilStatusStateChanges(StatusState.STOP).perform();
}
@BeforeMethod(alwaysRun = true)
public void resizePopup() {
if (isInPopupTemplate()) {
jsUtils.scrollToView(popupTemplate.advanced().getContentElement());
popupTemplate.advanced().resizeFromLocation(PopupPanel.ResizerLocation.S, 100, 0);
}
}
protected void submitAjax() {
getMetamerPage().performJSClickOnButton(getPage().getA4jCommandBtn(), WaitRequestType.XHR);
}
public void verifyAllWrongWithAjaxSubmit() {
clickWrongButton();
submitAjax();
checkAllErrorMessagesAreVisibleAndCorrect();
}
public void verifyAllWrongWithJSFSubmit() {
clickWrongButton();
waiting(3000);// stabilization wait time, wait for all ajax requests are completed
getMetamerPage().getStatus().advanced().waitUntilStatusStateChanges(StatusState.STOP).perform();
getMetamerPage().performJSClickOnButton(getPage().gethCommandBtn(), WaitRequestType.HTTP);
checkAllErrorMessagesAreVisibleAndCorrect();
}
/**
* Boolean input, verify false
*/
public void verifyBooleanFalse() {
clickCorrectButton();
// checkBoolean to false
getPage().getInputAssertFalse().click();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.assertFalse);
}
/**
* Boolean input, verify true
*/
public void verifyBooleanTrue() {
clickCorrectButton();
// checkBoolean to true
getPage().getInputAssertTrue().click();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.assertTrue);
}
/**
* Integer input, verify custom string
*/
protected void verifyCustom() {
clickCorrectButton();
// string input custom string
getPage().getInputCustom().clear();
getPage().getInputCustom().sendKeys(wrongValue.get(ID.custom));
waitForRequestToComplete();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.custom);
preventViewExpiredException();
}
/**
* Integer input, verify date in future
*/
protected void verifyDateFuture() {
clickCorrectButton();
// date input future
getPage().getInputFuture().clear();
getPage().getInputFuture().sendKeys(wrongValue.get(ID.future));
waitForRequestToComplete();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.future);
preventViewExpiredException();
}
/**
* Integer input, verify date in past
*/
protected void verifyDatePast() {
clickCorrectButton();
// date input past
getPage().getInputPast().clear();
getPage().getInputPast().sendKeys(wrongValue.get(ID.past));
waitForRequestToComplete();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.past);
preventViewExpiredException();
}
/**
* Decimal input, verify digits
*/
protected void verifyDecimalDigits() {
clickCorrectButton();
// decimal input digits
getPage().getInputDigits().clear();
getPage().getInputDigits().sendKeys(wrongValue.get(ID.digits));
waitForRequestToComplete();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.digits);
}
/**
* Decimal input, verify from 2.5 to 9.688
*/
protected void verifyDecimalMinMax() {
clickCorrectButton();
// Decimal input
getPage().getInputDecimalMinMax().clear();
getPage().getInputDecimalMinMax().sendKeys(wrongValue.get(ID.decimalMinMax));
waitForRequestToComplete();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.decimalMinMax);
preventViewExpiredException();
}
/**
* Integer input, verify max
*/
protected void verifyMax() {
clickCorrectButton();
// integer input max
getPage().getInputMax().clear();
getPage().getInputMax().sendKeys(wrongValue.get(ID.max));
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.max);
}
/**
* Integer input, verify min
*/
protected void verifyMin() {
clickCorrectButton();
// integer input min
// selenium.type(inputFormat.format(ID.min), wrongValue.get(ID.min));
getPage().getInputMin().clear();
getPage().getInputMin().sendKeys(wrongValue.get(ID.min));
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.min);
}
/**
* Integer input, verify min max
*/
protected void verifyMinMax() {
clickCorrectButton();
// integer input min and max
// selenium.type(inputFormat.format(ID.minMax), wrongValue.get(ID.minMax));
getPage().getInputMinMax().clear();
getPage().getInputMinMax().sendKeys(wrongValue.get(ID.minMax));
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.minMax);
}
/**
* Integer input, verify not empty
*/
protected void verifyNotEmpty() {
clickCorrectButton();
// string input not empty
// selenium.type(inputFormat.format(ID.notEmpty), wrongValue.get(ID.notEmpty));
getPage().getInputNotEmpty().clear();
getPage().getInputNotEmpty().sendKeys(wrongValue.get(ID.notEmpty));
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.notEmpty);
}
/**
* Integer input, verify not null
*/
protected void verifyNotNull() {
clickCorrectButton();
// string input not null
getPage().getInputNotNull().clear();
getPage().getInputNotNull().sendKeys("");
waitForRequestToComplete();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.notNull);
}
/**
* Integer input, verify string pattern
*/
protected void verifyPattern() {
clickCorrectButton();
// string input custom pattern
getPage().getInputPattern().clear();
getPage().getInputPattern().sendKeys(wrongValue.get(ID.pattern));
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.pattern);
}
/**
* Integer input, verify regExp
*/
protected void verifyRegExp() {
clickCorrectButton();
// string input regExp pattern
getPage().getInputRegexp().clear();
getPage().getInputRegexp().sendKeys(wrongValue.get(ID.regexp));
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.regexp);
}
/**
* Integer input, verify selection size
*/
protected void verifySelectionSize() {
clickCorrectButton();
// many checkBox input selection size
WebElement selectionItemByLabel = getPage().getSelectionItemByLabel(wrongValue.get(ID.size));
jsUtils.scrollToView(selectionItemByLabel);
selectionItemByLabel.click();
waitForRequestToComplete();
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.size);
}
/**
* Integer input, verify string size
*/
protected void verifyStringSize() {
clickCorrectButton();
// string input string size
getPage().getInputStringSize().clear();
getPage().getInputStringSize().sendKeys(wrongValue.get(ID.stringSize));
submitAjax();
waitUtilMessageWithIDIsVisibleAndCorrect(ID.stringSize);
}
/**
* If there is an ajax request in progress, or the request will be sent when the current input is blurred, wait until the
* request is done by waiting for Metamer's status to change.
*/
private void waitForRequestToComplete() {
getMetamerPage().getBlurButton().click();// blur the current input, this can sent ajax request
waiting(500);// wait until the request is initiated
getMetamerPage().getStatus().advanced().waitUntilStatusStateChanges(StatusState.STOP);// wait for status changes to 'stop' state
}
protected void waitUtilMessageWithIDIsVisibleAndCorrect(final ID id) {
Graphene
.waitGui()
.until(new Predicate<WebDriver>() {
@Override
public boolean apply(WebDriver t) {
// 'endsWith' because of MyFaces is inserting the input's label before the message
for (String expectedMsg : messages.get(id)) {
if (getMessageForID(id).getDetail().endsWith(expectedMsg)) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
@Override
public String toString() {
return MessageFormat.format("message with ID: {0}, to be visible and contain expected text: {1}. Actual text: {2}", id, messages.get(id), getMessageForID(id).getDetail());
}
});
}
protected enum ID {
/**
* Boolean, true
*/
assertTrue, /**
* Boolean false
*/
assertFalse, /**
* Decimal from 2.5 to 9.688
*/
decimalMinMax, /**
* Decimal 3 digits and 4 fract
*/
digits, /**
* Integer max 10
*/
max, /**
* Integer min 2
*/
min, /**
* Integer from 2 to 10
*/
minMax, /**
* Text, not empty
*/
notEmpty, /**
* Text, not null
*/
notNull, /**
* Text, pattern '[a-z].*'
*/
pattern, /**
* custom validator
*/
custom, /**
* custom regExp validator
*/
regexp, /**
* date past
*/
past, /**
* date future
*/
future, /**
* String size from 2 to 4
*/
stringSize, /**
* Selection size
*/
size
}
}