/******************************************************************************* * Copyright 2017 Ivan Shubin http://galenframework.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.galenframework.suite.actions; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeoutException; import com.galenframework.browser.Browser; import com.galenframework.page.Page; import com.galenframework.page.PageElement; import com.galenframework.reports.TestReport; import com.galenframework.specs.page.Locator; import com.galenframework.suite.GalenPageAction; import com.galenframework.suite.GalenPageTest; import com.galenframework.validation.ValidationListener; import com.galenframework.browser.Browser; import com.galenframework.page.Page; import com.galenframework.page.PageElement; import com.galenframework.reports.TestReport; import com.galenframework.specs.page.Locator; import com.galenframework.suite.GalenPageAction; import com.galenframework.suite.GalenPageTest; import com.galenframework.validation.ValidationListener; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; public class GalenPageActionWait extends GalenPageAction { private int timeout; private List<Until> untilElements; public enum UntilType { EXIST, GONE, VISIBLE, HIDDEN; public static UntilType parseNonStrict(String text) { if ("visible".equals(text)) { return VISIBLE; } else if ("hidden".equals(text)) { return HIDDEN; } else if ("exist".equals(text)) { return EXIST; } else if ("gone".equals(text)) { return GONE; } else return null; } @Override public String toString() { switch(this) { case EXIST: return "exist"; case GONE: return "gone"; case VISIBLE: return "visible"; case HIDDEN: return "hidden"; default: return ""; } } } public static class Until { private UntilType type; private Locator locator; public Until(UntilType type, Locator locator) { this.type = type; this.locator = locator; } public UntilType getType() { return type; } public void setType(UntilType type) { this.type = type; } public Locator getLocator() { return locator; } public void setLocator(Locator locator) { this.locator = locator; } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj == this) return true; if (!(obj instanceof Until)) return false; Until rhs = (Until)obj; return new EqualsBuilder() //@formatter:off .append(this.type, rhs.type) .append(this.locator, rhs.locator) .isEquals(); //@formatter:on } @Override public int hashCode() { //@formatter:off return new HashCodeBuilder() .append(this.type) .append(this.locator) .toHashCode(); //@formatter:on } @Override public String toString() { return new ToStringBuilder(this) //@formatter:off .append("type", this.type) .append("locator", this.locator) .toString(); //@formatter:on } } @Override public void execute(TestReport report, Browser browser, GalenPageTest pageTest, ValidationListener validationListener) throws Exception { Page page = browser.getPage(); if (untilElements == null || untilElements.isEmpty()) { Thread.sleep(timeout); } else { // waiting for elements int period = 500; int tries = timeout / period; while(tries-- > 0) { Thread.sleep(period); if (checkAllConditions(page, null)) { return; } } StringBuffer results = new StringBuffer(); if (!checkAllConditions(page, results)) { throw new TimeoutException("Failed waiting for:\n" + results.toString()); } } } private boolean checkAllConditions(Page page, StringBuffer result) { boolean state = true; for (Until until : untilElements) { PageElement element = page.getObject(until.getLocator()); if (!checkElement(element, until)) { state = false; if (result != null) { result.append(" - " + until.getType().toString() + " " + until.getLocator().prettyString() + "\n"); } } } return state; } private boolean checkElement(PageElement element, Until until) { if (until.getType() == UntilType.VISIBLE) { return element.isVisible(); } else if (until.getType() == UntilType.HIDDEN) { return !element.isVisible(); } else if (until.getType() == UntilType.EXIST) { return element.isPresent(); } else if (until.getType() == UntilType.GONE) { return !element.isPresent(); } else return true; } public GalenPageActionWait withTimeout(int timeoutInMillis) { this.setTimeout(timeoutInMillis); return this; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } @Override public String toString() { return new ToStringBuilder(this) //@formatter:off .append("timeout", this.timeout) .append("untilElements", this.untilElements) .toString(); //@formatter:on } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj == this) return true; if (!(obj instanceof GalenPageActionWait)) return false; GalenPageActionWait rhs = (GalenPageActionWait)obj; return new EqualsBuilder() //@formatter:off .append(this.timeout, rhs.timeout) .append(this.untilElements, rhs.untilElements) .isEquals(); //@formatter:on } @Override public int hashCode() { return new HashCodeBuilder() //@formatter:off .append(this.timeout) .append(this.untilElements) .toHashCode(); //@formatter:on } public List<Until> getUntilElements() { return untilElements; } public void setUntilElements(List<Until> untilElements) { this.untilElements = untilElements; } public GalenPageActionWait withUntilElements(List<Until> list) { if (this.untilElements == null) { this.untilElements = new LinkedList<>(); } this.untilElements.addAll(list); return this; } }