new feature: if tatement for conditions in functions
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
|
2015-05-06 23:09 marc
|
||||||
|
|
||||||
|
* ChangeLog, bootstrap.sh, doc/doxyfile.in,
|
||||||
|
scripts/doxygen-webtester.sed, scripts/example.wt,
|
||||||
|
scripts/makefile.am: better doxygen support
|
||||||
|
|
||||||
2015-05-06 16:56 marc
|
2015-05-06 16:56 marc
|
||||||
|
|
||||||
* debian/control.in: reprepo requires a section
|
* debian/control.in: reprepo requires a section
|
||||||
|
@@ -65,7 +65,7 @@ AC_DEFUN([AX_ADD_MAKEFILE_TARGET_DEP], [
|
|||||||
# $1 = variable name
|
# $1 = variable name
|
||||||
AC_DEFUN([AX_SUBST], [
|
AC_DEFUN([AX_SUBST], [
|
||||||
AC_SUBST([$1])
|
AC_SUBST([$1])
|
||||||
tmp_var=$(echo "${$1}" | sed ':a;N;$!ba;s/\n/\\n/g')
|
tmp_var=$(echo "${$1}" | awk 1 ORS='\\n')
|
||||||
tmp_var=${tmp_var//\"/\\\"}
|
tmp_var=${tmp_var//\"/\\\"}
|
||||||
tmp_var=${tmp_var//\'/\'\"\'\"\'}
|
tmp_var=${tmp_var//\'/\'\"\'\"\'}
|
||||||
tmp_var=${tmp_var//#/\\#}
|
tmp_var=${tmp_var//#/\\#}
|
||||||
@@ -105,7 +105,7 @@ AC_DEFUN([AX_INIT_STANDARD_PROJECT], [
|
|||||||
AX_SUBST(DISTRO)
|
AX_SUBST(DISTRO)
|
||||||
BUILD_NUMBER=${BUILD_NUMBER:-1}
|
BUILD_NUMBER=${BUILD_NUMBER:-1}
|
||||||
AX_SUBST(BUILD_NUMBER)
|
AX_SUBST(BUILD_NUMBER)
|
||||||
BUILD_DATE=$(date -R)
|
BUILD_DATE=$(date +"%Y-%m-%d %H:%M %Z")
|
||||||
AX_SUBST(BUILD_DATE)
|
AX_SUBST(BUILD_DATE)
|
||||||
if test -f "${PROJECT_NAME}-logo.png"; then
|
if test -f "${PROJECT_NAME}-logo.png"; then
|
||||||
PROJECT_LOGO="${PROJECT_NAME}-logo.png"
|
PROJECT_LOGO="${PROJECT_NAME}-logo.png"
|
||||||
@@ -365,8 +365,9 @@ AC_DEFUN([AX_PKG_REQUIRE], [
|
|||||||
if test ${$1_found} -eq 0; then
|
if test ${$1_found} -eq 0; then
|
||||||
for p in /usr/include ${$1_CFLAGS}; do
|
for p in /usr/include ${$1_CFLAGS}; do
|
||||||
$1_file=$(find ${p#-I} -name $3)
|
$1_file=$(find ${p#-I} -name $3)
|
||||||
if test -e ${$1_file}; then
|
if test -e "${$1_file}"; then
|
||||||
$1_CFLAGS="${$1_CFLAGS} -I${$1_file%/*}"
|
AC_MSG_NOTICE([Header file $3 found in sub path as ${$1_file}])
|
||||||
|
$1_CFLAGS="${$1_CFLAGS} -I${$1_file%/$3}"
|
||||||
$1_found=1
|
$1_found=1
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@@ -396,7 +397,8 @@ AC_DEFUN([AX_PKG_REQUIRE], [
|
|||||||
for p in /usr/include ${$1_CFLAGS}; do
|
for p in /usr/include ${$1_CFLAGS}; do
|
||||||
$1_file=$(find ${p#-I} -name $3)
|
$1_file=$(find ${p#-I} -name $3)
|
||||||
if test -e ${$1_file}; then
|
if test -e ${$1_file}; then
|
||||||
$1_CFLAGS="${$1_CFLAGS} -I${$1_file%/*}"
|
AC_MSG_NOTICE([Header file $3 found in sub path as ${$1_file}])
|
||||||
|
$1_CFLAGS="${$1_CFLAGS} -I${$1_file%/$3}"
|
||||||
$1_found=1
|
$1_found=1
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
@@ -216,7 +216,7 @@ done
|
|||||||
|
|
||||||
HEADER='## @id '"\$Id\$"'
|
HEADER='## @id '"\$Id\$"'
|
||||||
#
|
#
|
||||||
# This file has been added by '${MY_NAME}' on '$(date -R)'
|
# This file has been added by '${MY_NAME}' on '$(date +"%Y-%m-%d %H:%M %Z")'
|
||||||
# Feel free to change it or even remove and rebuild it, up to your needs
|
# Feel free to change it or even remove and rebuild it, up to your needs
|
||||||
#
|
#
|
||||||
## 1 2 3 4 5 6 7 8
|
## 1 2 3 4 5 6 7 8
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
# docker build --pull --force-rm --rm -t dev0004:5000/libraries/webtester .
|
# docker build --pull --force-rm --rm -t dev0004:5000/library/webtester .
|
||||||
# docker push dev0004:5000/libraries/webtester
|
# docker push dev0004:5000/libray/webtester
|
||||||
FROM ubuntu:latest
|
FROM ubuntu:latest
|
||||||
MAINTAINER "Marc Wäckerlin"
|
MAINTAINER "Marc Wäckerlin"
|
||||||
|
|
||||||
|
222
src/commands.hxx
222
src/commands.hxx
@@ -62,18 +62,6 @@ class Command: public QObject {
|
|||||||
int line() const {
|
int line() const {
|
||||||
return _line;
|
return _line;
|
||||||
}
|
}
|
||||||
void testsuite(QString name) {
|
|
||||||
_testsuite = name;
|
|
||||||
}
|
|
||||||
QString testsuite() {
|
|
||||||
return _testsuite;
|
|
||||||
}
|
|
||||||
void targetdir(QString name) {
|
|
||||||
_targetdir = name;
|
|
||||||
}
|
|
||||||
QString targetdir() {
|
|
||||||
return _targetdir;
|
|
||||||
}
|
|
||||||
bool log() {
|
bool log() {
|
||||||
return _log;
|
return _log;
|
||||||
}
|
}
|
||||||
@@ -123,6 +111,19 @@ class Command: public QObject {
|
|||||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
|
void subScript(std::shared_ptr<Script> script,
|
||||||
|
Script* parent, QWebFrame* frame,
|
||||||
|
QStringList vars = QStringList(),
|
||||||
|
QStringList args = QStringList());
|
||||||
|
QStringList subCommandBlock(QStringList& in) {
|
||||||
|
QStringList commands;
|
||||||
|
int pos(-1);
|
||||||
|
while (in.size() && in[0].size() && in[0][0]==' ') {
|
||||||
|
if (pos<0) pos=in[0].toStdString().find_first_not_of(' ');
|
||||||
|
commands += in.takeFirst().mid(pos);
|
||||||
|
}
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
QStringList commaSeparatedList(QString value) {
|
QStringList commaSeparatedList(QString value) {
|
||||||
switch (value.size()>1&&value.at(0)==value.at(value.size()-1)
|
switch (value.size()>1&&value.at(0)==value.at(value.size()-1)
|
||||||
?value.at(0).toLatin1():'\0') {
|
?value.at(0).toLatin1():'\0') {
|
||||||
@@ -169,8 +170,6 @@ class Command: public QObject {
|
|||||||
QString _result;
|
QString _result;
|
||||||
private:
|
private:
|
||||||
int _line;
|
int _line;
|
||||||
QString _testsuite;
|
|
||||||
QString _targetdir;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Empty: public Command {
|
class Empty: public Command {
|
||||||
@@ -463,9 +462,17 @@ class Script: public QObject {
|
|||||||
linenr+=oldsize-in.size())
|
linenr+=oldsize-in.size())
|
||||||
_script.push_back(parse(in, linenr));
|
_script.push_back(parse(in, linenr));
|
||||||
}
|
}
|
||||||
void run(QWebFrame* frame, xml::Node& testsuite,
|
void run(QWebFrame* frame, QString td = QString(), bool screenshots = true,
|
||||||
QString targetdir = QString(), bool screenshots = true,
|
|
||||||
int maxretries = 0) {
|
int maxretries = 0) {
|
||||||
|
assert(_internalTestsuiteNode);
|
||||||
|
run(frame, *_internalTestsuiteNode, td,
|
||||||
|
screenshots, maxretries); //( @todo extract from parent
|
||||||
|
}
|
||||||
|
void run(QWebFrame* frame, xml::Node& testsuiteNode,
|
||||||
|
QString td = QString(), bool screenshots = true,
|
||||||
|
int maxretries = 0) {
|
||||||
|
_internalTestsuiteNode = &testsuiteNode;
|
||||||
|
assert(_internalTestsuiteNode);
|
||||||
_timeout = 20; // defaults to 20s
|
_timeout = 20; // defaults to 20s
|
||||||
_ignoreSignalsUntil.clear();
|
_ignoreSignalsUntil.clear();
|
||||||
addSignals(frame);
|
addSignals(frame);
|
||||||
@@ -476,15 +483,14 @@ class Script: public QObject {
|
|||||||
xml::Node testcase("testcase");
|
xml::Node testcase("testcase");
|
||||||
try {
|
try {
|
||||||
testcase.attr("classname") =
|
testcase.attr("classname") =
|
||||||
testsuite.attr("name");
|
testsuiteNode.attr("name");
|
||||||
//xmlattr((*cmd)->command(), true).toStdString();
|
//xmlattr((*cmd)->command(), true).toStdString();
|
||||||
testcase.attr("name") =
|
testcase.attr("name") =
|
||||||
xmlattr((*cmd)->tag(), true).toStdString();
|
xmlattr((*cmd)->tag(), true).toStdString();
|
||||||
if (!_ignores.size() || (*cmd)->tag()=="label") { // not ignored
|
if (!_ignores.size() || (*cmd)->tag()=="label") { // not ignored
|
||||||
_timer.start(_timeout*1000);
|
_timer.start(_timeout*1000);
|
||||||
(*cmd)->testsuite(xmlstr(testsuite.attr("name")));
|
testsuite(xmlstr(testsuiteNode.attr("name")));
|
||||||
(*cmd)->targetdir(!targetdir.isEmpty() ? targetdir :
|
targetdir(!td.isEmpty() ? td : xmlstr(testsuiteNode.attr("name")));
|
||||||
xmlstr(testsuite.attr("name")));
|
|
||||||
try {
|
try {
|
||||||
if (!(*cmd)->execute(this, frame)) {
|
if (!(*cmd)->execute(this, frame)) {
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
@@ -495,7 +501,7 @@ class Script: public QObject {
|
|||||||
xmlattr(_cerr).toStdString());
|
xmlattr(_cerr).toStdString());
|
||||||
_cout.clear();
|
_cout.clear();
|
||||||
_cerr.clear();
|
_cerr.clear();
|
||||||
testsuite<<testcase;
|
testsuiteNode<<testcase;
|
||||||
break; // test is successfully finished
|
break; // test is successfully finished
|
||||||
}
|
}
|
||||||
} catch (PossibleRetryLoad& e) {
|
} catch (PossibleRetryLoad& e) {
|
||||||
@@ -504,8 +510,8 @@ class Script: public QObject {
|
|||||||
if (screenshots)
|
if (screenshots)
|
||||||
try { // take a screenshot on error
|
try { // take a screenshot on error
|
||||||
QString filename(Screenshot::screenshot
|
QString filename(Screenshot::screenshot
|
||||||
((*cmd)->line(), (*cmd)->targetdir(),
|
((*cmd)->line(), targetdir(),
|
||||||
QFileInfo((*cmd)->testsuite()).baseName(),
|
QFileInfo(testsuite()).baseName(),
|
||||||
QString("retry-%1")
|
QString("retry-%1")
|
||||||
.arg((ulong)retries, 2, 10,
|
.arg((ulong)retries, 2, 10,
|
||||||
QLatin1Char('0')),
|
QLatin1Char('0')),
|
||||||
@@ -557,7 +563,7 @@ class Script: public QObject {
|
|||||||
xmlattr(_cerr).toStdString());
|
xmlattr(_cerr).toStdString());
|
||||||
_cout.clear();
|
_cout.clear();
|
||||||
_cerr.clear();
|
_cerr.clear();
|
||||||
testsuite<<testcase;
|
testsuiteNode<<testcase;
|
||||||
}
|
}
|
||||||
} catch (Exception& e) {
|
} catch (Exception& e) {
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
@@ -568,28 +574,30 @@ class Script: public QObject {
|
|||||||
xmlattr(_cerr).toStdString());
|
xmlattr(_cerr).toStdString());
|
||||||
_cout.clear();
|
_cout.clear();
|
||||||
_cerr.clear();
|
_cerr.clear();
|
||||||
testsuite<<testcase;
|
testsuiteNode<<testcase;
|
||||||
removeSignals(frame);
|
removeSignals(frame);
|
||||||
e.line((*cmd)->line());
|
e.line((*cmd)->line());
|
||||||
if (screenshots)
|
if (screenshots)
|
||||||
try { // write html source and take a last screenshot on error
|
try { // write html source and take a last screenshot on error
|
||||||
{
|
{
|
||||||
QString filename(Screenshot::sourceHtml
|
QString filename(Screenshot::sourceHtml
|
||||||
((*cmd)->line(), (*cmd)->targetdir(),
|
((*cmd)->line(), targetdir(),
|
||||||
QFileInfo((*cmd)->testsuite()).baseName(),
|
QFileInfo(testsuite()).baseName(),
|
||||||
"error", frame));
|
"error", frame));
|
||||||
plainlog("[[ATTACHMENT|"+filename+"]]");
|
plainlog("[[ATTACHMENT|"+filename+"]]");
|
||||||
} {
|
} {
|
||||||
QString filename(Screenshot::screenshot
|
QString filename(Screenshot::screenshot
|
||||||
((*cmd)->line(), (*cmd)->targetdir(),
|
((*cmd)->line(), targetdir(),
|
||||||
QFileInfo((*cmd)->testsuite()).baseName(),
|
QFileInfo(testsuite()).baseName(),
|
||||||
"error", frame));
|
"error", frame));
|
||||||
plainlog("[[ATTACHMENT|"+filename+"]]");
|
plainlog("[[ATTACHMENT|"+filename+"]]");
|
||||||
}
|
}
|
||||||
} catch (... ) {} // ignore exception in screenshot
|
} catch (... ) {} // ignore exception in screenshot
|
||||||
|
_internalTestsuiteNode = 0;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_internalTestsuiteNode = 0;
|
||||||
removeSignals(frame);
|
removeSignals(frame);
|
||||||
if (!_signals.empty()) throw UnhandledSignals(_signals);
|
if (!_signals.empty()) throw UnhandledSignals(_signals);
|
||||||
}
|
}
|
||||||
@@ -605,6 +613,18 @@ class Script: public QObject {
|
|||||||
bool screenshots() {
|
bool screenshots() {
|
||||||
return _screenshots;
|
return _screenshots;
|
||||||
}
|
}
|
||||||
|
void testsuite(QString name) {
|
||||||
|
_testsuite = name;
|
||||||
|
}
|
||||||
|
QString testsuite() {
|
||||||
|
return _testsuite;
|
||||||
|
}
|
||||||
|
void targetdir(QString name) {
|
||||||
|
_targetdir = name;
|
||||||
|
}
|
||||||
|
QString targetdir() {
|
||||||
|
return _targetdir;
|
||||||
|
}
|
||||||
Signal getSignal() {
|
Signal getSignal() {
|
||||||
while (!_signals.size()) QCoreApplication::processEvents();
|
while (!_signals.size()) QCoreApplication::processEvents();
|
||||||
Signal res(_signals.front());
|
Signal res(_signals.front());
|
||||||
@@ -624,11 +644,21 @@ class Script: public QObject {
|
|||||||
_variables[name] = value;
|
_variables[name] = value;
|
||||||
_rvariables[value] = name;
|
_rvariables[value] = name;
|
||||||
}
|
}
|
||||||
|
QString variable(QString name) {
|
||||||
|
QMap<QString, QString>::iterator it(_variables.find(name));
|
||||||
|
if (it==_variables.end()) throw VariableNotFound(name);
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
/// Copy context from other script
|
||||||
void set(const Script& o) {
|
void set(const Script& o) {
|
||||||
_variables = o._variables;
|
_variables = o._variables;
|
||||||
_rvariables = o._rvariables;
|
_rvariables = o._rvariables;
|
||||||
_timeout = o._timeout;
|
_timeout = o._timeout;
|
||||||
_clicktype = o._clicktype;
|
_clicktype = o._clicktype;
|
||||||
|
_testsuite = o._testsuite;
|
||||||
|
_internalTestsuiteNode = o._internalTestsuiteNode;
|
||||||
|
assert(_internalTestsuiteNode);
|
||||||
|
_targetdir = o._targetdir;
|
||||||
_cout.clear();
|
_cout.clear();
|
||||||
_cerr.clear();
|
_cerr.clear();
|
||||||
_ignoreSignalsUntil.clear();
|
_ignoreSignalsUntil.clear();
|
||||||
@@ -811,6 +841,9 @@ class Script: public QObject {
|
|||||||
QMap<QString, std::shared_ptr<Function> > _functions;
|
QMap<QString, std::shared_ptr<Function> > _functions;
|
||||||
int _timeout;
|
int _timeout;
|
||||||
ClickType _clicktype;
|
ClickType _clicktype;
|
||||||
|
QString _testsuite;
|
||||||
|
QString _targetdir;
|
||||||
|
xml::Node* _internalTestsuiteNode; ///< only valid within run
|
||||||
};
|
};
|
||||||
|
|
||||||
class Do: public Command {
|
class Do: public Command {
|
||||||
@@ -835,8 +868,7 @@ class Do: public Command {
|
|||||||
QStringList& in, int) {
|
QStringList& in, int) {
|
||||||
std::shared_ptr<Do> cmd(new Do());
|
std::shared_ptr<Do> cmd(new Do());
|
||||||
cmd->_selector = args;
|
cmd->_selector = args;
|
||||||
while (in.size() && in[0].size() && in[0][0]==' ')
|
cmd->_javascript = subCommandBlock(in).join("\n");
|
||||||
cmd->_javascript += "\n"+in.takeFirst();
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
bool execute(Script* script, QWebFrame* frame) {
|
bool execute(Script* script, QWebFrame* frame) {
|
||||||
@@ -1271,11 +1303,7 @@ class Execute: public Command {
|
|||||||
std::shared_ptr<Execute> cmd(new Execute());
|
std::shared_ptr<Execute> cmd(new Execute());
|
||||||
cmd->_args = args.split(' ');
|
cmd->_args = args.split(' ');
|
||||||
cmd->_command = cmd->_args.takeFirst();
|
cmd->_command = cmd->_args.takeFirst();
|
||||||
int pos(-1);
|
cmd->_script = subCommandBlock(in);
|
||||||
while (in.size() && in[0].size() && in[0][0]==' ') {
|
|
||||||
if (pos<0) pos=in[0].toStdString().find_first_not_of(' ');
|
|
||||||
cmd->_script += in.takeFirst().mid(pos);
|
|
||||||
}
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
bool execute(Script* script, QWebFrame*) {
|
bool execute(Script* script, QWebFrame*) {
|
||||||
@@ -1786,14 +1814,8 @@ class Function: public Command {
|
|||||||
cmd->_name = allargs.takeFirst().trimmed();
|
cmd->_name = allargs.takeFirst().trimmed();
|
||||||
cmd->_vars = commaSeparatedList(allargs.join(' '));
|
cmd->_vars = commaSeparatedList(allargs.join(' '));
|
||||||
script->function(cmd->_name, cmd);
|
script->function(cmd->_name, cmd);
|
||||||
QStringList commands;
|
|
||||||
int pos(-1);
|
|
||||||
while (in.size() && in[0].size() && in[0][0]==' ') {
|
|
||||||
if (pos<0) pos=in[0].toStdString().find_first_not_of(' ');
|
|
||||||
commands += in.takeFirst().mid(pos);
|
|
||||||
}
|
|
||||||
cmd->_script = std::shared_ptr<Script>(new Script);
|
cmd->_script = std::shared_ptr<Script>(new Script);
|
||||||
cmd->_script->parse(commands);
|
cmd->_script->parse(subCommandBlock(in));
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
bool execute(Script* script, QWebFrame*) {
|
bool execute(Script* script, QWebFrame*) {
|
||||||
@@ -1802,27 +1824,9 @@ class Function: public Command {
|
|||||||
}
|
}
|
||||||
bool call(QStringList args, Script* script, QWebFrame* frame) {
|
bool call(QStringList args, Script* script, QWebFrame* frame) {
|
||||||
Logger log(this, script);
|
Logger log(this, script);
|
||||||
if (args.size()!=_vars.size())
|
|
||||||
throw WrongNumberOfArguments(_name, _vars, args);
|
|
||||||
xml::Node suite("testcase");
|
|
||||||
suite.attr("classname") = _name.toStdString();
|
|
||||||
suite.attr("name") = testsuite().toStdString();
|
|
||||||
_script->set(*script);
|
|
||||||
for (QStringList::iterator var(_vars.begin()), arg(args.begin());
|
|
||||||
var<_vars.end() && arg<args.end(); ++var, ++arg)
|
|
||||||
_script->set(*var, script->replacevars(*arg));
|
|
||||||
try {
|
try {
|
||||||
connect(_script.get(), SIGNAL(logging(QString)),
|
subScript(_script, script, frame, _vars, args);
|
||||||
script, SLOT(log(QString)));
|
|
||||||
script->removeSignals(frame);
|
|
||||||
_script->run(frame, suite, targetdir());
|
|
||||||
script->addSignals(frame);
|
|
||||||
disconnect(_script.get(), SIGNAL(logging(QString)),
|
|
||||||
script, SLOT(log(QString)));
|
|
||||||
} catch (const std::exception& x) {
|
} catch (const std::exception& x) {
|
||||||
script->addSignals(frame);
|
|
||||||
disconnect(_script.get(), SIGNAL(logging(QString)),
|
|
||||||
script, SLOT(log(QString)));
|
|
||||||
throw FunctionCallFailed(_name, _vars, args, x);
|
throw FunctionCallFailed(_name, _vars, args, x);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -1869,6 +1873,67 @@ class Call: public Command {
|
|||||||
QStringList _args;
|
QStringList _args;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class If: public Command {
|
||||||
|
public:
|
||||||
|
QString tag() const {
|
||||||
|
return "if";
|
||||||
|
}
|
||||||
|
QString description() const {
|
||||||
|
return
|
||||||
|
tag()+" <variable> <cmp> <value>\n"
|
||||||
|
" <command1>\n"
|
||||||
|
" <command2>\n"
|
||||||
|
" <...>\n"
|
||||||
|
"\n\n"
|
||||||
|
"Execute commands conditionally. "
|
||||||
|
"The comparision <cmp> can be = ^ ~ < >, "
|
||||||
|
"which means equal, different, match, "
|
||||||
|
"less (as integer), bigger (as integer). "
|
||||||
|
"Match allows a regular expression.";
|
||||||
|
}
|
||||||
|
QString command() const {
|
||||||
|
return tag();
|
||||||
|
}
|
||||||
|
std::shared_ptr<Command> parse(Script*, QString args,
|
||||||
|
QStringList& in, int) {
|
||||||
|
std::shared_ptr<If> cmd(new If());
|
||||||
|
int pos(args.indexOf(QRegularExpression("[=^~<>]")));
|
||||||
|
if (pos<0) throw BadArgument(tag()+" needs a comparision, not: "+args);
|
||||||
|
cmd->_variable = args.left(pos).trimmed();
|
||||||
|
cmd->_cmp = args[pos].toLatin1();
|
||||||
|
cmd->_value = args.mid(pos+1).trimmed();
|
||||||
|
cmd->_script = std::shared_ptr<Script>(new Script);
|
||||||
|
cmd->_script->parse(subCommandBlock(in));
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
bool execute(Script* script, QWebFrame* frame) {
|
||||||
|
Logger log(this, script);
|
||||||
|
QString value(script->replacevars(_value));
|
||||||
|
bool check(false);
|
||||||
|
switch (_cmp) {
|
||||||
|
case '=': check = script->variable(_variable)==value;
|
||||||
|
break;
|
||||||
|
case '^': check = script->variable(_variable)!=value;
|
||||||
|
break;
|
||||||
|
case '~': check =
|
||||||
|
script->variable(_variable).contains(QRegularExpression(value));
|
||||||
|
break;
|
||||||
|
case '<': check = script->variable(_variable).toInt()<value.toInt();
|
||||||
|
break;
|
||||||
|
case '>': check = script->variable(_variable).toInt()>value.toInt();
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
if (check) subScript(_script, script, frame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
QString _variable;
|
||||||
|
char _cmp;
|
||||||
|
QString _value;
|
||||||
|
std::shared_ptr<Script> _script;
|
||||||
|
};
|
||||||
|
|
||||||
/* Template:
|
/* Template:
|
||||||
class : public Command {
|
class : public Command {
|
||||||
public:
|
public:
|
||||||
@@ -1899,9 +1964,9 @@ class : public Command {
|
|||||||
inline bool Screenshot::execute(Script* script, QWebFrame* frame) {
|
inline bool Screenshot::execute(Script* script, QWebFrame* frame) {
|
||||||
if (!script->screenshots()) return true;
|
if (!script->screenshots()) return true;
|
||||||
Logger log(this, script);
|
Logger log(this, script);
|
||||||
QString filename(screenshot(line(), targetdir(),
|
QString filename(screenshot(line(), script->targetdir(),
|
||||||
QFileInfo(testsuite()).baseName(),
|
QFileInfo(script->testsuite()).baseName(),
|
||||||
_filename, frame));
|
script->replacevars(_filename), frame));
|
||||||
log["[[ATTACHMENT|"+filename+"]]"];
|
log["[[ATTACHMENT|"+filename+"]]"];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1925,6 +1990,32 @@ inline Logger::~Logger() {
|
|||||||
_script->log("---------------------");
|
_script->log("---------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Command::subScript(std::shared_ptr<Script> script,
|
||||||
|
Script* parent, QWebFrame* frame,
|
||||||
|
QStringList vars,
|
||||||
|
QStringList args) {
|
||||||
|
script->set(*parent);
|
||||||
|
if (args.size()!=vars.size())
|
||||||
|
throw WrongNumberOfArguments(vars, args);
|
||||||
|
for (QStringList::iterator var(vars.begin()), arg(args.begin());
|
||||||
|
var<vars.end() && arg<args.end(); ++var, ++arg)
|
||||||
|
script->set(*var, parent->replacevars(*arg));
|
||||||
|
try {
|
||||||
|
connect(script.get(), SIGNAL(logging(QString)),
|
||||||
|
parent, SLOT(log(QString)));
|
||||||
|
parent->removeSignals(frame);
|
||||||
|
script->run(frame, parent->targetdir());
|
||||||
|
parent->addSignals(frame);
|
||||||
|
disconnect(script.get(), SIGNAL(logging(QString)),
|
||||||
|
parent, SLOT(log(QString)));
|
||||||
|
} catch (const std::exception& x) {
|
||||||
|
parent->addSignals(frame);
|
||||||
|
disconnect(script.get(), SIGNAL(logging(QString)),
|
||||||
|
parent, SLOT(log(QString)));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void Script::initPrototypes() {
|
inline void Script::initPrototypes() {
|
||||||
add(new Do);
|
add(new Do);
|
||||||
add(new Load);
|
add(new Load);
|
||||||
@@ -1950,6 +2041,7 @@ inline void Script::initPrototypes() {
|
|||||||
add(new SetValue);
|
add(new SetValue);
|
||||||
add(new Function);
|
add(new Function);
|
||||||
add(new Call);
|
add(new Call);
|
||||||
|
add(new If);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -221,9 +221,9 @@ class ScriptExecutionFailed: public ScriptFailed {
|
|||||||
|
|
||||||
class WrongNumberOfArguments: public TestFailed {
|
class WrongNumberOfArguments: public TestFailed {
|
||||||
public:
|
public:
|
||||||
WrongNumberOfArguments(QString name, QStringList vars, QStringList args):
|
WrongNumberOfArguments(QStringList vars, QStringList args):
|
||||||
TestFailed(QString("%1 has %2 arguments, but %3 were given")
|
TestFailed(QString("function has %1 arguments, but %2 were given")
|
||||||
.arg(name).arg(vars.size()).arg(args.size())) {
|
.arg(vars.size()).arg(args.size())) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -246,4 +246,11 @@ class FunctionNotFound: public TestFailed {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VariableNotFound: public TestFailed {
|
||||||
|
public:
|
||||||
|
VariableNotFound(QString name):
|
||||||
|
TestFailed("variable not found: "+name) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -368,7 +368,11 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
} else {
|
} else {
|
||||||
appendCommand("click "+map(selected));
|
appendCommand("click "+map(selected));
|
||||||
}
|
}
|
||||||
if (_lastFocused.tagName()=="INPUT") {
|
if (_lastFocused.tagName()=="TEXTAREA" ||
|
||||||
|
_lastFocused.tagName()=="INPUT" &&
|
||||||
|
_lastFocused.attribute("type")=="text") {
|
||||||
|
// user clickt in a text edit field, so not the klick
|
||||||
|
// is important, but the text that will be typed
|
||||||
_typing = true;
|
_typing = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user