improved waiting for elements: defaults to timeout-1 if element should be there, defaults to timeout/3 if element is optional

This commit is contained in:
Marc Wäckerlin
2017-07-28 09:29:36 +00:00
parent 248d3b5032
commit 605c4eea79
8 changed files with 356 additions and 43 deletions

View File

@@ -33,6 +33,7 @@
#include <sstream>
#include <cassert>
#include <xml-cxx/xml.hxx>
#include <mrw/stdext.hxx>
#ifdef HAVE_CXXABI_H
#include <cxxabi.h>
@@ -151,11 +152,8 @@ class Command: public QObject {
virtual bool isTestcase() {
return true;
}
static void realMouseClick(Logger& log, QWebFrame* frame, QString selector) {
QWebElement element(find(frame, selector));
if (element.isNull()) error(log, ElementNotFound(selector));
realMouseClick(element);
}
static void realMouseClick(Logger& log, QWebFrame* frame,
Script* script, QString selector);
static void realMouseClick(const QWebElement& element) {
QWidget* web(element.webFrame()->page()->view());
QRect elGeom=element.geometry();
@@ -248,8 +246,9 @@ class Command: public QObject {
return element;
}
static QWebElement find1(QWebFrame* frame, QString selector,
int repeat = 5, int sleepsec = 1) {
int repeat = 2, int sleepsec = 1) {
QWebElement element;
if (repeat<1) repeat=1;
for (int i=0; i<repeat; ++i) {
element = frame->findFirstElement(selector);
if (!element.isNull()) return element;
@@ -257,7 +256,7 @@ class Command: public QObject {
element = find1(childFrame, selector, 1, 0);
if (!element.isNull()) return element;
}
if (sleepsec) sleep(sleepsec);
if (i+1<repeat && sleepsec) sleep(sleepsec);
}
return element;
}
@@ -855,7 +854,8 @@ class Script: public QObject {
void ignore(const Script& o) {
_ignore = o._ignore;
}
bool ignore(const QString& sig) {
bool ignores(const QString& sig = QString()) {
if (sig.isEmpty()) return !_ignore.empty();
return _ignore.contains(sig);
}
void ignore(QStringList sigs = QStringList()) {
@@ -932,6 +932,9 @@ class Script: public QObject {
void timeout(int t) {
_timeout = t;
}
int timeout() {
return _timeout;
}
void defaultTimeout(int t) {
_defaultTimeout = t;
}
@@ -995,7 +998,7 @@ class Script: public QObject {
SLOT(titleChanged(const QString&))));
assert(connect(frame, SIGNAL(urlChanged(const QUrl&)),
SLOT(urlChanged(const QUrl&))));
assert(connect(&_timer, SIGNAL(timeout()), SLOT(timeout())));
assert(connect(&_timer, SIGNAL(timeout()), SLOT(timedout())));
}
void removeSignals(QWebFrame* frame) {
disconnect(dynamic_cast<NetworkAccessManager*>
@@ -1023,7 +1026,7 @@ class Script: public QObject {
this, SLOT(urlChanged(const QUrl&)));
disconnect(frame, SIGNAL(urlChanged(const QUrl&)),
this, SLOT(urlChanged(const QUrl&)));
disconnect(&_timer, SIGNAL(timeout()), this, SLOT(timeout()));
disconnect(&_timer, SIGNAL(timeout()), this, SLOT(timedout()));
}
public Q_SLOTS:
void log(QString text, Command* command = 0) {
@@ -1144,7 +1147,7 @@ class Script: public QObject {
_signals.push(std::make_pair("urlChanged",
QStringList(url.toString())));
}
void timeout() {
void timedout() {
error(TimeOut());
}
private:
@@ -1222,7 +1225,7 @@ class Do: public Command {
Logger log(this, script);
QWebElement element(frame->documentElement());
if (_selector.size()) {
element = find(frame, script->replacevars(_selector));
element = find(frame, script->replacevars(_selector), script->timeout()-1);
if (element.isNull())
error(log, ElementNotFound(script->replacevars(_selector)));
}
@@ -1305,7 +1308,7 @@ class Expect: public Command {
Logger log(this, script);
QStringList args(script->replacevars(_signal._args));
if (_signal._signal=="load") { // special signal load
while (!script->ignore("loadStarted") && script->checkSignal("loadStarted")) {
while (!script->ignores("loadStarted") && script->checkSignal("loadStarted")) {
log("ignore signal: loadStarted"); // ignore optional loadStarted
}
if (!script->checkSignal("urlChanged", args))
@@ -1532,7 +1535,7 @@ class Upload: public Command {
if (files.size()==1) filename=files[0];
}
page->setNextUploadFile(filename);
realMouseClick(log, frame, script->replacevars(_selector));
realMouseClick(log, frame, script, script->replacevars(_selector));
if (page->uploadPrepared())
error(log, SetFileUploadFailed(script->replacevars(_selector), filename));
return true;
@@ -1576,7 +1579,7 @@ class Exists: public Command {
QString selector(script->replacevars(_selector));
QString text(script->replacevars(_text));
QStringList notfound;
QWebElement firstelement(find(frame, selector));
QWebElement firstelement(find(frame, selector, script->timeout()-1));
Q_FOREACH(QWebElement element, frame->findAllElements(selector)) {
if (text.isEmpty()) return true; // just find element
if (element.toOuterXml().indexOf(text)!=-1) return true;
@@ -1631,6 +1634,8 @@ class Not: public Command {
Logger log(this, script);
QString selector(script->replacevars(_selector));
QString text(script->replacevars(_text));
QWebElement firstelement(find(frame, selector,
mrw::max(mrw::min(script->timeout()/3, 10), 2)));
Q_FOREACH(QWebElement element, frame->findAllElements(selector)) {
if (text.isEmpty())
error(log, AssertionFailed("element must not exists: "+selector));
@@ -1828,12 +1833,12 @@ class Click: public Command {
QString clicktarget(script->replacevars(_selector));
switch (_clicktype ? *_clicktype : script->clicktype()) {
case Script::REAL_MOUSE_CLICK: {
realMouseClick(log, frame, clicktarget);
realMouseClick(log, frame, script, clicktarget);
break;
}
case Script::JAVASCRIPT_CLICK:
default: {
QWebElement element(find(frame, clicktarget));
QWebElement element(find(frame, clicktarget, script->timeout()-1));
if (element.isNull())
error(log, ElementNotFound(clicktarget));
_result = element.evaluateJavaScript("this.click();").toString();
@@ -2145,7 +2150,8 @@ class SetValue: public Command {
}
bool execute(Script* script, QWebFrame* frame) {
Logger log(this, script);
QWebElement element(find(frame, script->replacevars(_selector)));
QWebElement element(find(frame, script->replacevars(_selector),
script->timeout()-1));
if (element.isNull())
error(log, ElementNotFound(script->replacevars(_selector)));
QString value(script->replacevars(_value));
@@ -2334,6 +2340,8 @@ class If: public CommandContainer {
QString selector(script->replacevars(_variable));
bool check(false);
if (_cmp=="->") {
QWebElement firstelement(find(frame, selector,
mrw::max(mrw::min(script->timeout()/3, 10), 2)));
Q_FOREACH(QWebElement element, frame->findAllElements(selector)) {
if (value.isEmpty() || // just find element
element.toOuterXml().indexOf(value)!=-1 ||
@@ -2439,6 +2447,8 @@ class While: public CommandContainer {
for (bool check(true); check;) {
if (_cmp=="->") {
check = false;
QWebElement firstelement(find(frame, selector,
mrw::max(mrw::min(script->timeout()/3, 10), 2)));
Q_FOREACH(QWebElement element, frame->findAllElements(selector)) {
if (value.isEmpty() || // just find element
element.toOuterXml().indexOf(value)!=-1 ||
@@ -2899,6 +2909,8 @@ class Case: public Command {
log("terminate with default branch");
check = true;
} else if (condition.cmp=="->") {
QWebElement firstelement(find(frame, selector,
mrw::max(mrw::min(script->timeout()/3, 10), 2)));
Q_FOREACH(QWebElement element, frame->findAllElements(selector)) {
if (value.isEmpty() || // just find element
element.toOuterXml().indexOf(value)!=-1 ||
@@ -3159,6 +3171,13 @@ inline Logger::~Logger() {
}
}
inline void Command::realMouseClick(Logger& log, QWebFrame* frame,
Script* script, QString selector) {
QWebElement element(find(frame, selector, script->timeout()-1));
if (element.isNull()) error(log, ElementNotFound(selector));
realMouseClick(element);
}
inline std::shared_ptr<Script> Command::subParser(Script* parent, const QStringList& in,
const QString& file,
int line, int indent) {