/**
* Copyright (C) 2008 Ovea <dev@testatoo.org>
*
* 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 org.testatoo.cartridge.html4;
import org.testatoo.core.ComponentException;
import org.testatoo.core.Duration;
import java.util.Arrays;
import java.util.List;
import static java.util.concurrent.TimeUnit.*;
import static org.testatoo.core.Language.max;
public abstract class By {
public abstract String id(HtmlEvaluator evaluator);
public abstract String id(HtmlEvaluator evaluator, Duration duration, Duration frequency);
public abstract List<String> ids(HtmlEvaluator evaluator);
public abstract List<String> ids(HtmlEvaluator evaluator, Duration duration, Duration frequency);
public abstract String toString();
public static By id(final String id) {
if (id == null)
throw new IllegalArgumentException("Cannot find component with a null id.");
return new By() {
@Override
public String id(HtmlEvaluator evaluator) {
return id(evaluator, new Duration(2000, MILLISECONDS), new Duration(500, MILLISECONDS));
}
@Override
public String id(HtmlEvaluator evaluator, Duration duration, Duration frequency) {
return waitUntilId(evaluator, id, duration, frequency);
}
@Override
public List<String> ids(HtmlEvaluator evaluator) {
return ids(evaluator, new Duration(2000, MILLISECONDS), new Duration(500, MILLISECONDS));
}
@Override
public List<String> ids(HtmlEvaluator evaluator, Duration duration, Duration frequency) {
return Arrays.asList(waitUntilIds(evaluator, id, duration, frequency));
}
@Override
public String toString() {
return "by id=" + id;
}
};
}
public static By $(final String jQueryExpression) {
return $(jQueryExpression, max(2, SECONDS));
}
public static By $(final String jQueryExpression, final Duration duration) {
if (jQueryExpression == null)
throw new IllegalArgumentException("Cannot find component when jQueryExpression is null.");
return new By() {
@Override
public String id(HtmlEvaluator evaluator) {
return id(evaluator, duration, max(500, MILLISECONDS));
}
@Override
public String id(HtmlEvaluator evaluator, Duration duration, Duration frequency) {
return waitUntilId(evaluator, "jquery:" + jQueryExpression(), duration, frequency);
}
@Override
public List<String> ids(HtmlEvaluator evaluator) {
return ids(evaluator, duration, max(500, MILLISECONDS));
}
@Override
public List<String> ids(HtmlEvaluator evaluator, Duration duration, Duration frequency) {
return Arrays.asList(waitUntilIds(evaluator, "jquery:" + jQueryExpression(), duration, frequency));
}
@Override
public String toString() {
return "by jQueryExpression=" + jQueryExpression();
}
private String jQueryExpression() {
if (!jQueryExpression.startsWith("$")) {
return "$('" + jQueryExpression + "')";
} else {
return jQueryExpression;
}
}
};
}
@Deprecated
public static By jQuery(final String jQueryExpression) {
return $(jQueryExpression, max(5, SECONDS));
}
@Deprecated
public static By jQuery(final String jQueryExpression, final Duration duration) {
return $(jQueryExpression, duration);
}
private static String waitUntilId(HtmlEvaluator evaluator, String expression, Duration duration, Duration frequency) {
String[] ids = waitUntilIds(evaluator, expression, duration, frequency);
if (ids.length > 1)
throw new ComponentException("Find more than one component defined by jQueryExpression=" + expression.substring(7));
else
return ids[0];
}
private static String[] waitUntilIds(HtmlEvaluator evaluator, String expression, Duration duration, Duration frequency) {
Throwable ex = null;
try {
final long step = frequency.unit.toMillis(frequency.duration);
for (long timeout = duration.unit.toMillis(duration.duration); timeout > 0 && !Thread.currentThread().isInterrupted(); timeout -= step, Thread.sleep(step)) {
try {
return evaluator.elementsId(expression);
} catch (RuntimeException e) {
ex = e;
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
ex = e;
}
if (ex instanceof EvaluatorException) {
if (expression.startsWith("jquery:"))
throw new ComponentException("Cannot find component defined by jQueryExpression=" + expression.substring(7));
else
throw new ComponentException("Cannot find component defined by id=" + expression);
}
throw new RuntimeException("Unable to reach the condition in " + duration.duration + " " + duration.unit, ex);
}
}