new command check to compare two values or to compare a value to the result of a command - command call now returns the value of the last statement
This commit is contained in:
110
src/commands.hxx
110
src/commands.hxx
@@ -111,7 +111,8 @@ class Command: public QObject {
|
|||||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void runScript(std::shared_ptr<Script> script,
|
bool runScript(Command* parentCommand,
|
||||||
|
std::shared_ptr<Script> script,
|
||||||
Script* parent, QWebFrame* frame,
|
Script* parent, QWebFrame* frame,
|
||||||
QStringList vars = QStringList(),
|
QStringList vars = QStringList(),
|
||||||
QStringList args = QStringList());
|
QStringList args = QStringList());
|
||||||
@@ -469,12 +470,13 @@ class Script: public QObject {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
void run(QWebFrame* frame) {
|
bool run(QWebFrame* frame) {
|
||||||
run(frame, _testsuites, targetdir(), _screenshots, _maxretries);
|
return run(frame, _testsuites, targetdir(), _screenshots, _maxretries);
|
||||||
}
|
}
|
||||||
void run(QWebFrame* frame, std::shared_ptr<xml::Node> testsuites,
|
bool run(QWebFrame* frame, std::shared_ptr<xml::Node> testsuites,
|
||||||
QString td = QString(), bool screenshots = true,
|
QString td = QString(), bool screenshots = true,
|
||||||
int maxretries = 0) {
|
int maxretries = 0) {
|
||||||
|
bool res(true);
|
||||||
_testsuites = testsuites;
|
_testsuites = testsuites;
|
||||||
_timeout = 20; // defaults to 20s
|
_timeout = 20; // defaults to 20s
|
||||||
_ignoreSignalsUntil.clear();
|
_ignoreSignalsUntil.clear();
|
||||||
@@ -502,7 +504,7 @@ class Script: public QObject {
|
|||||||
if (!_ignores.size() || (*cmd)->tag()=="label") { // not ignored
|
if (!_ignores.size() || (*cmd)->tag()=="label") { // not ignored
|
||||||
_timer.start(_timeout*1000);
|
_timer.start(_timeout*1000);
|
||||||
try {
|
try {
|
||||||
if (!(*cmd)->execute(this, frame)) {
|
if (!(res=(*cmd)->execute(this, frame))) {
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
if (!back) retries = 0; else --back;
|
if (!back) retries = 0; else --back;
|
||||||
testcase<<(xml::String("system-out") =
|
testcase<<(xml::String("system-out") =
|
||||||
@@ -608,6 +610,7 @@ class Script: public QObject {
|
|||||||
}
|
}
|
||||||
removeSignals(frame);
|
removeSignals(frame);
|
||||||
if (!_signals.empty()) throw UnhandledSignals(_signals);
|
if (!_signals.empty()) throw UnhandledSignals(_signals);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
QString& cout() {
|
QString& cout() {
|
||||||
return _cout;
|
return _cout;
|
||||||
@@ -718,6 +721,10 @@ class Script: public QObject {
|
|||||||
}
|
}
|
||||||
return txt;
|
return txt;
|
||||||
}
|
}
|
||||||
|
QString result() {
|
||||||
|
if (_script.size()) return (*_script.rbegin())->result();
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
void addSignals(QWebFrame* frame) {
|
void addSignals(QWebFrame* frame) {
|
||||||
connect(dynamic_cast<NetworkAccessManager*>
|
connect(dynamic_cast<NetworkAccessManager*>
|
||||||
(frame->page()->networkAccessManager()),
|
(frame->page()->networkAccessManager()),
|
||||||
@@ -1496,9 +1503,10 @@ class Set: public Command {
|
|||||||
"\n\n"
|
"\n\n"
|
||||||
"Sets the value of a variable either to a constant, or to the output"
|
"Sets the value of a variable either to a constant, or to the output"
|
||||||
" of a command. A command should be a command that produces an"
|
" of a command. A command should be a command that produces an"
|
||||||
" output, such as «do», which returns the result of JavaScript or"
|
" output, such as <do>, which returns the result of JavaScript or"
|
||||||
" «execute», which returns the output of the executed command."
|
" <execute>, which returns the output of the executed command, or"
|
||||||
" All variables are global with regrad to functions.";
|
" <call>, which returns the result of the last command."
|
||||||
|
" All variables are global with regard to functions.";
|
||||||
}
|
}
|
||||||
QString command() const {
|
QString command() const {
|
||||||
if (_next)
|
if (_next)
|
||||||
@@ -1840,14 +1848,14 @@ class Function: public Command {
|
|||||||
Logger log(this, script);
|
Logger log(this, script);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool call(QStringList args, Script* script, QWebFrame* frame) {
|
bool call(Command* parentCommand, QStringList args,
|
||||||
|
Script* script, QWebFrame* frame) {
|
||||||
Logger log(this, script);
|
Logger log(this, script);
|
||||||
try {
|
try {
|
||||||
runScript(_script, script, frame, _vars, args);
|
return runScript(parentCommand, _script, script, frame, _vars, args);
|
||||||
} catch (const std::exception& x) {
|
} catch (const std::exception& x) {
|
||||||
throw FunctionCallFailed(_name, _vars, args, x);
|
throw FunctionCallFailed(_name, _vars, args, x);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
QString _name;
|
QString _name;
|
||||||
@@ -1883,8 +1891,7 @@ class Call: public Command {
|
|||||||
}
|
}
|
||||||
bool execute(Script* script, QWebFrame* frame) {
|
bool execute(Script* script, QWebFrame* frame) {
|
||||||
Logger log(this, script);
|
Logger log(this, script);
|
||||||
script->function(_name)->call(_args, script, frame);
|
return script->function(_name)->call(this, _args, script, frame);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
QString _name;
|
QString _name;
|
||||||
@@ -1953,8 +1960,8 @@ class If: public Command {
|
|||||||
break;
|
break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
if (check) runScript(_script, script, frame);
|
if (check) return runScript(this, _script, script, frame);
|
||||||
else if (_else) runScript(_else, script, frame);
|
else if (_else) return runScript(this, _else, script, frame);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@@ -2023,6 +2030,71 @@ class TestCase: public Command {
|
|||||||
QString _name;
|
QString _name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Check: public Command {
|
||||||
|
public:
|
||||||
|
QString tag() const {
|
||||||
|
return "check";
|
||||||
|
}
|
||||||
|
QString description() const {
|
||||||
|
return
|
||||||
|
tag()+" <value1> <op> <value2>\n"+
|
||||||
|
tag()+" <value1>\n"
|
||||||
|
" <command>"
|
||||||
|
"\n\n"
|
||||||
|
"Compares two values (you can use variables) or compares a value to the"
|
||||||
|
" result of a command. The command should be a command that produces an"
|
||||||
|
" output, such as <do>, which returns the result of JavaScript or"
|
||||||
|
" <execute>, which returns the output of the executed command, or"
|
||||||
|
" <call>, which returns the result of the last command.";
|
||||||
|
}
|
||||||
|
QString command() const {
|
||||||
|
if (_next)
|
||||||
|
return tag()+" "+_value1+" "+QString(_cmp)+"\n "+_next->command();
|
||||||
|
else
|
||||||
|
return tag()+" "+_value1+" "+QString(_cmp)+" "+_value2;
|
||||||
|
}
|
||||||
|
std::shared_ptr<Command> parse(Script* script, QString args,
|
||||||
|
QStringList& in, int line) {
|
||||||
|
std::shared_ptr<Check> cmd(new Check());
|
||||||
|
cmd->_next = 0;
|
||||||
|
int pos(args.indexOf(QRegularExpression("[=^~<>]")));
|
||||||
|
if (pos<0) throw BadArgument(tag()+" needs a comparision, not: "+args);
|
||||||
|
cmd->_value1 = args.left(pos).trimmed();
|
||||||
|
cmd->_cmp = args[pos].toLatin1();
|
||||||
|
cmd->_value2 = args.mid(pos+1).trimmed();
|
||||||
|
if (in.size() && in.first().contains(QRegularExpression("^ "))) {
|
||||||
|
cmd->_next = script->parse(in, line+1);
|
||||||
|
cmd->_next->log(false); // suppress logging of subcommand
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
bool execute(Script* script, QWebFrame* frame) {
|
||||||
|
Logger log(this, script);
|
||||||
|
QString value1(script->replacevars(_value1));
|
||||||
|
QString value2(script->replacevars(_value2));
|
||||||
|
if (_next) {
|
||||||
|
_next->execute(script, frame);
|
||||||
|
value2 = script->replacevars(_next->result());
|
||||||
|
}
|
||||||
|
bool check(false);
|
||||||
|
switch (_cmp) {
|
||||||
|
case '=': check = value1==value2; break;
|
||||||
|
case '^': check = value1!=value2; break;
|
||||||
|
case '~': check = value1.contains(QRegularExpression(value2)); break;
|
||||||
|
case '<': check = value1.toInt()<value2.toInt(); break;
|
||||||
|
case '>': check = value1.toInt()>value2.toInt(); break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
if (!check) throw CheckFailed(value1, _cmp, value2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
QString _value1;
|
||||||
|
QString _value2;
|
||||||
|
char _cmp;
|
||||||
|
std::shared_ptr<Command> _next;
|
||||||
|
};
|
||||||
|
|
||||||
/* Template:
|
/* Template:
|
||||||
class : public Command {
|
class : public Command {
|
||||||
public:
|
public:
|
||||||
@@ -2079,7 +2151,8 @@ inline Logger::~Logger() {
|
|||||||
_script->log("---------------------");
|
_script->log("---------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Command::runScript(std::shared_ptr<Script> script,
|
inline bool Command::runScript(Command* parentCommand,
|
||||||
|
std::shared_ptr<Script> script,
|
||||||
Script* parent, QWebFrame* frame,
|
Script* parent, QWebFrame* frame,
|
||||||
QStringList vars,
|
QStringList vars,
|
||||||
QStringList args) {
|
QStringList args) {
|
||||||
@@ -2093,10 +2166,12 @@ inline void Command::runScript(std::shared_ptr<Script> script,
|
|||||||
connect(script.get(), SIGNAL(logging(QString)),
|
connect(script.get(), SIGNAL(logging(QString)),
|
||||||
parent, SLOT(log(QString)));
|
parent, SLOT(log(QString)));
|
||||||
parent->removeSignals(frame);
|
parent->removeSignals(frame);
|
||||||
script->run(frame);
|
bool res(script->run(frame));
|
||||||
parent->addSignals(frame);
|
parent->addSignals(frame);
|
||||||
disconnect(script.get(), SIGNAL(logging(QString)),
|
disconnect(script.get(), SIGNAL(logging(QString)),
|
||||||
parent, SLOT(log(QString)));
|
parent, SLOT(log(QString)));
|
||||||
|
parentCommand->_result = script->result();
|
||||||
|
return res;
|
||||||
} catch (const std::exception& x) {
|
} catch (const std::exception& x) {
|
||||||
parent->addSignals(frame);
|
parent->addSignals(frame);
|
||||||
disconnect(script.get(), SIGNAL(logging(QString)),
|
disconnect(script.get(), SIGNAL(logging(QString)),
|
||||||
@@ -2133,6 +2208,7 @@ inline void Script::initPrototypes() {
|
|||||||
add(new If);
|
add(new If);
|
||||||
add(new TestSuite);
|
add(new TestSuite);
|
||||||
add(new TestCase);
|
add(new TestCase);
|
||||||
|
add(new Check);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -253,4 +253,12 @@ class VariableNotFound: public TestFailed {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CheckFailed: public TestFailed {
|
||||||
|
public:
|
||||||
|
CheckFailed(QString value1, char cmp, QString value2):
|
||||||
|
TestFailed(QString("check failed: %1 %2 %3")
|
||||||
|
.arg(value1).arg(cmp).arg(value1)) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user