|
|
|
@ -25,6 +25,7 @@ |
|
|
|
|
#include <QRegularExpression> |
|
|
|
|
#include <QNetworkCookieJar> |
|
|
|
|
#include <QNetworkCookie> |
|
|
|
|
#include <QSet> |
|
|
|
|
#include <vector> |
|
|
|
|
#include <queue> |
|
|
|
|
#include <map> |
|
|
|
@ -566,6 +567,7 @@ class Script: public QObject { |
|
|
|
|
} |
|
|
|
|
void cleanup() { |
|
|
|
|
reset(); |
|
|
|
|
_ignore.clear(); |
|
|
|
|
_variables.clear(); |
|
|
|
|
_rvariables.clear(); |
|
|
|
|
_timeout = _defaultTimeout; |
|
|
|
@ -822,15 +824,58 @@ class Script: public QObject { |
|
|
|
|
_testsuites->last().attr("failures") = "0"; |
|
|
|
|
(*_testsuites)<<testsuite; |
|
|
|
|
} |
|
|
|
|
QStringList getSignals() { |
|
|
|
|
QStringList res; |
|
|
|
|
for (std::queue<Signal> sigs(_signals); !sigs.empty(); sigs.pop()) |
|
|
|
|
res+=sigs.front().first; |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
Signal getSignal() { |
|
|
|
|
while (!_signals.size()) QCoreApplication::processEvents(); |
|
|
|
|
while (_signals.empty()) QCoreApplication::processEvents(); |
|
|
|
|
Signal res(_signals.front()); |
|
|
|
|
_signals.pop(); |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
bool checkSignal(const QString& name, const QStringList& args = QStringList()) { |
|
|
|
|
if (_ignore.contains(name)) { |
|
|
|
|
log(QString("ignoring signal check for %1").arg(name)); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
while (_signals.empty()) QCoreApplication::processEvents(); |
|
|
|
|
Signal res(_signals.front()); |
|
|
|
|
if (res.first==name && (args.empty() || res.second==args)) { |
|
|
|
|
_signals.pop(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
QTimer& timer() { |
|
|
|
|
return _timer; |
|
|
|
|
} |
|
|
|
|
void ignore(const Script& o) { |
|
|
|
|
_ignore = o._ignore; |
|
|
|
|
} |
|
|
|
|
bool ignore(const QString& sig) { |
|
|
|
|
return _ignore.contains(sig); |
|
|
|
|
} |
|
|
|
|
void ignore(QStringList sigs = QStringList()) { |
|
|
|
|
if (sigs.empty()) |
|
|
|
|
sigs<<"loadFinished"<<"loadStarted"<<"frameChanged"<<"titleChanged"<<"urlChanged"; |
|
|
|
|
Q_FOREACH(const QString& sig, sigs) { |
|
|
|
|
log("start ignoring: '"+sig+"'"); |
|
|
|
|
_ignore<<sig; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void unignore(QStringList sigs = QStringList()) { |
|
|
|
|
if (sigs.empty()) |
|
|
|
|
sigs<<"loadFinished"<<"loadStarted"<<"frameChanged"<<"titleChanged"<<"urlChanged"; |
|
|
|
|
Q_FOREACH(const QString& sig, sigs) { |
|
|
|
|
if (_ignore.contains(sig)) { |
|
|
|
|
log("stop ignoring: '"+sig+"'"); |
|
|
|
|
_ignore.erase(_ignore.find(sig)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void ignoreto(const QString& l) { |
|
|
|
|
_ignores.insert(l); |
|
|
|
|
} |
|
|
|
@ -859,6 +904,8 @@ class Script: public QObject { |
|
|
|
|
_testsuites = o._testsuites; |
|
|
|
|
_testclass = o._testclass; |
|
|
|
|
_targetdir = o._targetdir; |
|
|
|
|
_ignore = o._ignore; |
|
|
|
|
_ignores = o._ignores; |
|
|
|
|
_maxretries = o._maxretries; |
|
|
|
|
_screenshots = o._screenshots; |
|
|
|
|
_cout.clear(); |
|
|
|
@ -1043,6 +1090,10 @@ class Script: public QObject { |
|
|
|
|
void javaScriptWindowObjectCleared() { |
|
|
|
|
} |
|
|
|
|
void loadFinished(bool ok) { |
|
|
|
|
if (_ignore.contains("loadFinished")) { |
|
|
|
|
log("ignored loadFinished"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
QString sig(ok?"true":"false"); |
|
|
|
|
if (_ignoreSignalsUntil.size() && |
|
|
|
|
_ignoreSignalsUntil != "loadFinished "+sig) { |
|
|
|
@ -1054,6 +1105,10 @@ class Script: public QObject { |
|
|
|
|
_signals.push(std::make_pair("loadFinished", QStringList(sig))); |
|
|
|
|
} |
|
|
|
|
void loadStarted() { |
|
|
|
|
if (_ignore.contains("loadStarted")) { |
|
|
|
|
log("ignored loadStarted"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (_ignoreSignalsUntil.size() && _ignoreSignalsUntil != "loadStarted") { |
|
|
|
|
log("warning: ignored loadStarted, waiting for "+_ignoreSignalsUntil); |
|
|
|
|
return; |
|
|
|
@ -1063,11 +1118,23 @@ class Script: public QObject { |
|
|
|
|
_signals.push(std::make_pair("loadStarted", QStringList())); |
|
|
|
|
} |
|
|
|
|
void frameChanged() { |
|
|
|
|
if (_ignore.contains("frameChanged")) { |
|
|
|
|
log("ignored frameChanged"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void titleChanged(const QString&) { |
|
|
|
|
if (_ignore.contains("titleChanged")) { |
|
|
|
|
log("ignored titleChanged"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
//_signals.push(std::make_pair("titleChanged", QStringList(title)));
|
|
|
|
|
} |
|
|
|
|
void urlChanged(const QUrl& url) { |
|
|
|
|
if (_ignore.contains("urlChanged")) { |
|
|
|
|
log("ignored urlChanged"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (_ignoreSignalsUntil.size() && _ignoreSignalsUntil != "urlChanged") { |
|
|
|
|
log("warning: ignored urlChanged, waiting for "+_ignoreSignalsUntil); |
|
|
|
|
return; |
|
|
|
@ -1090,6 +1157,7 @@ class Script: public QObject { |
|
|
|
|
Prototypes _prototypes; |
|
|
|
|
Commands _script; |
|
|
|
|
std::queue<Signal> _signals; |
|
|
|
|
QSet<QString> _ignore; ///< signals to ignore
|
|
|
|
|
QTimer _timer; |
|
|
|
|
int _step; |
|
|
|
|
QSet<QString> _ignores; |
|
|
|
@ -1236,21 +1304,21 @@ class Expect: public Command { |
|
|
|
|
bool execute(Script* script, QWebFrame*) { |
|
|
|
|
Logger log(this, script); |
|
|
|
|
QStringList args(script->replacevars(_signal._args)); |
|
|
|
|
Script::Signal lastsignal(script->getSignal()); |
|
|
|
|
if (_signal._signal=="load") { // special signal load
|
|
|
|
|
while (lastsignal.first=="loadStarted") { |
|
|
|
|
log("ignore signal: loadStarted"); |
|
|
|
|
lastsignal = script->getSignal(); // ignore optional loadStarted
|
|
|
|
|
while (!script->ignore("loadStarted") && script->checkSignal("loadStarted")) { |
|
|
|
|
log("ignore signal: loadStarted"); // ignore optional loadStarted
|
|
|
|
|
} |
|
|
|
|
if (lastsignal.first!="urlChanged" || (args.size() && lastsignal.second!=args)) |
|
|
|
|
error(log, WrongSignal("urlChanged", args, lastsignal)); |
|
|
|
|
lastsignal = script->getSignal(); |
|
|
|
|
if (!script->checkSignal("urlChanged", args)) |
|
|
|
|
error(log, WrongSignal("urlChanged", args, script->getSignal(), |
|
|
|
|
script->getSignals())); |
|
|
|
|
args=QStringList("true"); |
|
|
|
|
if (lastsignal.first!="loadFinished" || (lastsignal.second!=args)) |
|
|
|
|
error(log, WrongSignal("loadFinished", args, lastsignal)); |
|
|
|
|
if (!script->checkSignal("loadFinished", args)) |
|
|
|
|
error(log, WrongSignal("loadFinished", args, script->getSignal(), |
|
|
|
|
script->getSignals())); |
|
|
|
|
} else { |
|
|
|
|
if (lastsignal.first!=_signal._signal || (args.size() && lastsignal.second!=args)) |
|
|
|
|
error(log, WrongSignal(_signal._signal, args, lastsignal)); |
|
|
|
|
if (!script->checkSignal(_signal._signal, args)) |
|
|
|
|
error(log, WrongSignal(_signal._signal, args, script->getSignal(), |
|
|
|
|
script->getSignals())); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -2962,6 +3030,70 @@ class Auth: public Command { |
|
|
|
|
QString _password; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Ignore: public Command { |
|
|
|
|
public: |
|
|
|
|
QString tag() const { |
|
|
|
|
return "ignore"; |
|
|
|
|
} |
|
|
|
|
QString description() const { |
|
|
|
|
return |
|
|
|
|
tag()+" <signal1> <signal2> <...>" |
|
|
|
|
"\n\n" |
|
|
|
|
"Ignores a specific signal. It will not be placed in the queue " |
|
|
|
|
"and any expect for this signal is always true. You can call " |
|
|
|
|
"ignore with a space separated list of signal names. You cannot " |
|
|
|
|
"specify signal arguments. An empty ignore ignores all signals."; |
|
|
|
|
} |
|
|
|
|
QString command() const { |
|
|
|
|
return tag()+" "+_signals.join(" "); |
|
|
|
|
} |
|
|
|
|
std::shared_ptr<Command> parse(Script*, QString args, |
|
|
|
|
QStringList&, QString, int, int) { |
|
|
|
|
std::shared_ptr<Ignore> cmd(new Ignore()); |
|
|
|
|
cmd->_signals = args.split(' ', QString::SkipEmptyParts); |
|
|
|
|
return cmd; |
|
|
|
|
} |
|
|
|
|
bool execute(Script* script, QWebFrame* frame) { |
|
|
|
|
Logger log(this, script); |
|
|
|
|
script->ignore(_signals); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
private: |
|
|
|
|
QStringList _signals; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class UnIgnore: public Command { |
|
|
|
|
public: |
|
|
|
|
QString tag() const { |
|
|
|
|
return "unignore"; |
|
|
|
|
} |
|
|
|
|
QString description() const { |
|
|
|
|
return |
|
|
|
|
tag()+" <signal1> <signal2> <...>" |
|
|
|
|
"\n\n" |
|
|
|
|
"Undo ignoring a specific signal. It will be placed in the queue " |
|
|
|
|
"and any expect this signal checks the queue. You can call " |
|
|
|
|
"unignore with a space separated list of signal names. You cannot " |
|
|
|
|
"specify signal arguments. An empty ignore activates all signals."; |
|
|
|
|
} |
|
|
|
|
QString command() const { |
|
|
|
|
return tag()+" "+_signals.join(" "); |
|
|
|
|
} |
|
|
|
|
std::shared_ptr<Command> parse(Script*, QString args, |
|
|
|
|
QStringList&, QString, int, int) { |
|
|
|
|
std::shared_ptr<UnIgnore> cmd(new UnIgnore()); |
|
|
|
|
cmd->_signals = args.split(' ', QString::SkipEmptyParts); |
|
|
|
|
return cmd; |
|
|
|
|
} |
|
|
|
|
bool execute(Script* script, QWebFrame* frame) { |
|
|
|
|
Logger log(this, script); |
|
|
|
|
script->unignore(_signals); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
private: |
|
|
|
|
QStringList _signals; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/* Template:
|
|
|
|
|
class : public Command { |
|
|
|
|
public: |
|
|
|
@ -3067,6 +3199,7 @@ inline bool Command::runScript(Logger& log, Command* parentCommand, |
|
|
|
|
parentCommand->_result = scriptCopy.result(); |
|
|
|
|
Q_FOREACH(QString key, scriptCopy.variables()) // copy new variables to parent
|
|
|
|
|
if (!vars.contains(key)) parent->set(key, scriptCopy.variable(key)); |
|
|
|
|
parent->ignore(scriptCopy); // copy ignore list
|
|
|
|
|
if (parentCommand->_result.size()) |
|
|
|
|
parent->log("result: "+parentCommand->_result); |
|
|
|
|
return res; |
|
|
|
@ -3118,6 +3251,8 @@ inline void Script::initPrototypes() { |
|
|
|
|
add(new Case); |
|
|
|
|
add(new Fail); |
|
|
|
|
add(new Auth); |
|
|
|
|
add(new Ignore); |
|
|
|
|
add(new UnIgnore); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|