new commands ignore and unignore to (un-) ignore signals
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
;; Set up to autoload
|
;; Set up to autoload
|
||||||
|
(add-to-list 'load-path "@emacsdir@")
|
||||||
(autoload 'wt-mode "wt-mode" "Major mode for editing Webtester test scripts" t)
|
(autoload 'wt-mode "wt-mode" "Major mode for editing Webtester test scripts" t)
|
||||||
(setq auto-mode-alist
|
(setq auto-mode-alist
|
||||||
(cons '("\\.wt\\'" . wt-mode) auto-mode-alist))
|
(cons '("\\.wt\\'" . wt-mode) auto-mode-alist))
|
@@ -12,7 +12,13 @@ emacsdir = ${datadir}/emacs/site-lisp
|
|||||||
dist_emacs_SCRIPTS = wt-mode.el
|
dist_emacs_SCRIPTS = wt-mode.el
|
||||||
|
|
||||||
emacsconfdir = ${sysconfdir}/emacs/site-start.d
|
emacsconfdir = ${sysconfdir}/emacs/site-start.d
|
||||||
dist_emacsconf = 90wt-mode.el
|
emacsconf_DATA = 90wt-mode.el
|
||||||
|
|
||||||
|
EXTRA_DIST = 90wt-mode.el.in
|
||||||
|
|
||||||
|
90wt-mode.el: 90wt-mode.el.in
|
||||||
|
sed 's,@emacsdir@,'"${emacsdir}"',g' $< > $@
|
||||||
|
|
||||||
|
CLEANFILES = 90wt-mode.el
|
||||||
MAINTAINERCLEANFILES = makefile.in
|
MAINTAINERCLEANFILES = makefile.in
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
;; echo $(webrunner -h | sed -n 's, COMMAND: ,,p') | sed 's, ,\\\\|,g'
|
;; echo $(webrunner -h | sed -n 's, COMMAND: ,,p') | sed 's, ,\\\\|,g'
|
||||||
(defconst wt-font-lock-keywords
|
(defconst wt-font-lock-keywords
|
||||||
(list
|
(list
|
||||||
'("^ *\\(auth\\|ca-certificate\\|call\\|case\\|check\\|clear-cookies\\|click\\|clicktype\\|client-certificate\\|do\\|download\\|echo\\|execute\\|exists\\|exit\\|expect\\|fail\\|for\\|function\\|if\\|while\\|ignoreto\\|include\\|label\\|load\\|not\\|offline-storage-path\\|open\\|screenshot\\|set\\|setvalue\\|sleep\\|testcase\\|testsuite\\|timeout\\|unset\\|upload\\) " . font-lock-builtin-face)
|
'("^ *\\(auth\\|ca-certificate\\|call\\|case\\|check\\|clear-cookies\\|click\\|clicktype\\|client-certificate\\|do\\|download\\|echo\\|execute\\|exists\\|exit\\|expect\\|fail\\|for\\|function\\|if\\|while\\|ignore\\|unignore\\|ignoreto\\|include\\|label\\|load\\|not\\|offline-storage-path\\|open\\|screenshot\\|set\\|setvalue\\|sleep\\|testcase\\|testsuite\\|timeout\\|unset\\|upload\\)\\b" . font-lock-builtin-face)
|
||||||
'("^ *#.*$" . font-lock-comment-face))
|
'("^ *#.*$" . font-lock-comment-face))
|
||||||
"Highlighting expressions for Webtester")
|
"Highlighting expressions for Webtester")
|
||||||
|
|
||||||
|
159
src/commands.hxx
159
src/commands.hxx
@@ -25,6 +25,7 @@
|
|||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QNetworkCookieJar>
|
#include <QNetworkCookieJar>
|
||||||
#include <QNetworkCookie>
|
#include <QNetworkCookie>
|
||||||
|
#include <QSet>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -566,6 +567,7 @@ class Script: public QObject {
|
|||||||
}
|
}
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
reset();
|
reset();
|
||||||
|
_ignore.clear();
|
||||||
_variables.clear();
|
_variables.clear();
|
||||||
_rvariables.clear();
|
_rvariables.clear();
|
||||||
_timeout = _defaultTimeout;
|
_timeout = _defaultTimeout;
|
||||||
@@ -822,15 +824,58 @@ class Script: public QObject {
|
|||||||
_testsuites->last().attr("failures") = "0";
|
_testsuites->last().attr("failures") = "0";
|
||||||
(*_testsuites)<<testsuite;
|
(*_testsuites)<<testsuite;
|
||||||
}
|
}
|
||||||
|
QStringList getSignals() {
|
||||||
|
QStringList res;
|
||||||
|
for (std::queue<Signal> sigs(_signals); !sigs.empty(); sigs.pop())
|
||||||
|
res+=sigs.front().first;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
Signal getSignal() {
|
Signal getSignal() {
|
||||||
while (!_signals.size()) QCoreApplication::processEvents();
|
while (_signals.empty()) QCoreApplication::processEvents();
|
||||||
Signal res(_signals.front());
|
Signal res(_signals.front());
|
||||||
_signals.pop();
|
_signals.pop();
|
||||||
return res;
|
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() {
|
QTimer& timer() {
|
||||||
return _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) {
|
void ignoreto(const QString& l) {
|
||||||
_ignores.insert(l);
|
_ignores.insert(l);
|
||||||
}
|
}
|
||||||
@@ -859,6 +904,8 @@ class Script: public QObject {
|
|||||||
_testsuites = o._testsuites;
|
_testsuites = o._testsuites;
|
||||||
_testclass = o._testclass;
|
_testclass = o._testclass;
|
||||||
_targetdir = o._targetdir;
|
_targetdir = o._targetdir;
|
||||||
|
_ignore = o._ignore;
|
||||||
|
_ignores = o._ignores;
|
||||||
_maxretries = o._maxretries;
|
_maxretries = o._maxretries;
|
||||||
_screenshots = o._screenshots;
|
_screenshots = o._screenshots;
|
||||||
_cout.clear();
|
_cout.clear();
|
||||||
@@ -1043,6 +1090,10 @@ class Script: public QObject {
|
|||||||
void javaScriptWindowObjectCleared() {
|
void javaScriptWindowObjectCleared() {
|
||||||
}
|
}
|
||||||
void loadFinished(bool ok) {
|
void loadFinished(bool ok) {
|
||||||
|
if (_ignore.contains("loadFinished")) {
|
||||||
|
log("ignored loadFinished");
|
||||||
|
return;
|
||||||
|
}
|
||||||
QString sig(ok?"true":"false");
|
QString sig(ok?"true":"false");
|
||||||
if (_ignoreSignalsUntil.size() &&
|
if (_ignoreSignalsUntil.size() &&
|
||||||
_ignoreSignalsUntil != "loadFinished "+sig) {
|
_ignoreSignalsUntil != "loadFinished "+sig) {
|
||||||
@@ -1054,6 +1105,10 @@ class Script: public QObject {
|
|||||||
_signals.push(std::make_pair("loadFinished", QStringList(sig)));
|
_signals.push(std::make_pair("loadFinished", QStringList(sig)));
|
||||||
}
|
}
|
||||||
void loadStarted() {
|
void loadStarted() {
|
||||||
|
if (_ignore.contains("loadStarted")) {
|
||||||
|
log("ignored loadStarted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_ignoreSignalsUntil.size() && _ignoreSignalsUntil != "loadStarted") {
|
if (_ignoreSignalsUntil.size() && _ignoreSignalsUntil != "loadStarted") {
|
||||||
log("warning: ignored loadStarted, waiting for "+_ignoreSignalsUntil);
|
log("warning: ignored loadStarted, waiting for "+_ignoreSignalsUntil);
|
||||||
return;
|
return;
|
||||||
@@ -1063,11 +1118,23 @@ class Script: public QObject {
|
|||||||
_signals.push(std::make_pair("loadStarted", QStringList()));
|
_signals.push(std::make_pair("loadStarted", QStringList()));
|
||||||
}
|
}
|
||||||
void frameChanged() {
|
void frameChanged() {
|
||||||
|
if (_ignore.contains("frameChanged")) {
|
||||||
|
log("ignored frameChanged");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void titleChanged(const QString&) {
|
void titleChanged(const QString&) {
|
||||||
|
if (_ignore.contains("titleChanged")) {
|
||||||
|
log("ignored titleChanged");
|
||||||
|
return;
|
||||||
|
}
|
||||||
//_signals.push(std::make_pair("titleChanged", QStringList(title)));
|
//_signals.push(std::make_pair("titleChanged", QStringList(title)));
|
||||||
}
|
}
|
||||||
void urlChanged(const QUrl& url) {
|
void urlChanged(const QUrl& url) {
|
||||||
|
if (_ignore.contains("urlChanged")) {
|
||||||
|
log("ignored urlChanged");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_ignoreSignalsUntil.size() && _ignoreSignalsUntil != "urlChanged") {
|
if (_ignoreSignalsUntil.size() && _ignoreSignalsUntil != "urlChanged") {
|
||||||
log("warning: ignored urlChanged, waiting for "+_ignoreSignalsUntil);
|
log("warning: ignored urlChanged, waiting for "+_ignoreSignalsUntil);
|
||||||
return;
|
return;
|
||||||
@@ -1090,6 +1157,7 @@ class Script: public QObject {
|
|||||||
Prototypes _prototypes;
|
Prototypes _prototypes;
|
||||||
Commands _script;
|
Commands _script;
|
||||||
std::queue<Signal> _signals;
|
std::queue<Signal> _signals;
|
||||||
|
QSet<QString> _ignore; ///< signals to ignore
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
int _step;
|
int _step;
|
||||||
QSet<QString> _ignores;
|
QSet<QString> _ignores;
|
||||||
@@ -1236,21 +1304,21 @@ class Expect: public Command {
|
|||||||
bool execute(Script* script, QWebFrame*) {
|
bool execute(Script* script, QWebFrame*) {
|
||||||
Logger log(this, script);
|
Logger log(this, script);
|
||||||
QStringList args(script->replacevars(_signal._args));
|
QStringList args(script->replacevars(_signal._args));
|
||||||
Script::Signal lastsignal(script->getSignal());
|
|
||||||
if (_signal._signal=="load") { // special signal load
|
if (_signal._signal=="load") { // special signal load
|
||||||
while (lastsignal.first=="loadStarted") {
|
while (!script->ignore("loadStarted") && script->checkSignal("loadStarted")) {
|
||||||
log("ignore signal: loadStarted");
|
log("ignore signal: loadStarted"); // ignore optional loadStarted
|
||||||
lastsignal = script->getSignal(); // ignore optional loadStarted
|
|
||||||
}
|
}
|
||||||
if (lastsignal.first!="urlChanged" || (args.size() && lastsignal.second!=args))
|
if (!script->checkSignal("urlChanged", args))
|
||||||
error(log, WrongSignal("urlChanged", args, lastsignal));
|
error(log, WrongSignal("urlChanged", args, script->getSignal(),
|
||||||
lastsignal = script->getSignal();
|
script->getSignals()));
|
||||||
args=QStringList("true");
|
args=QStringList("true");
|
||||||
if (lastsignal.first!="loadFinished" || (lastsignal.second!=args))
|
if (!script->checkSignal("loadFinished", args))
|
||||||
error(log, WrongSignal("loadFinished", args, lastsignal));
|
error(log, WrongSignal("loadFinished", args, script->getSignal(),
|
||||||
|
script->getSignals()));
|
||||||
} else {
|
} else {
|
||||||
if (lastsignal.first!=_signal._signal || (args.size() && lastsignal.second!=args))
|
if (!script->checkSignal(_signal._signal, args))
|
||||||
error(log, WrongSignal(_signal._signal, args, lastsignal));
|
error(log, WrongSignal(_signal._signal, args, script->getSignal(),
|
||||||
|
script->getSignals()));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2962,6 +3030,70 @@ class Auth: public Command {
|
|||||||
QString _password;
|
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:
|
/* Template:
|
||||||
class : public Command {
|
class : public Command {
|
||||||
public:
|
public:
|
||||||
@@ -3067,6 +3199,7 @@ inline bool Command::runScript(Logger& log, Command* parentCommand,
|
|||||||
parentCommand->_result = scriptCopy.result();
|
parentCommand->_result = scriptCopy.result();
|
||||||
Q_FOREACH(QString key, scriptCopy.variables()) // copy new variables to parent
|
Q_FOREACH(QString key, scriptCopy.variables()) // copy new variables to parent
|
||||||
if (!vars.contains(key)) parent->set(key, scriptCopy.variable(key));
|
if (!vars.contains(key)) parent->set(key, scriptCopy.variable(key));
|
||||||
|
parent->ignore(scriptCopy); // copy ignore list
|
||||||
if (parentCommand->_result.size())
|
if (parentCommand->_result.size())
|
||||||
parent->log("result: "+parentCommand->_result);
|
parent->log("result: "+parentCommand->_result);
|
||||||
return res;
|
return res;
|
||||||
@@ -3118,6 +3251,8 @@ inline void Script::initPrototypes() {
|
|||||||
add(new Case);
|
add(new Case);
|
||||||
add(new Fail);
|
add(new Fail);
|
||||||
add(new Auth);
|
add(new Auth);
|
||||||
|
add(new Ignore);
|
||||||
|
add(new UnIgnore);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -19,7 +19,7 @@ class Highlighter: public QSyntaxHighlighter {
|
|||||||
void include(QString);
|
void include(QString);
|
||||||
public:
|
public:
|
||||||
Highlighter(QTextDocument *parent): QSyntaxHighlighter(parent) {
|
Highlighter(QTextDocument *parent): QSyntaxHighlighter(parent) {
|
||||||
QString commands="auth|ca-certificate|call|case|check|clear-cookies|click|clicktype|client-certificate|do|download|echo|execute|exists|exit|expect|fail|for|function|if|while|ignoreto|include|label|load|not|offline-storage-path|open|screenshot|set|setvalue|sleep|testcase|testsuite|timeout|unset|upload";
|
QString commands="auth|ca-certificate|call|case|check|clear-cookies|click|clicktype|client-certificate|do|download|echo|execute|exists|exit|expect|fail|for|function|if|while|ignore|unignore|ignoreto|include|label|load|not|offline-storage-path|open|screenshot|set|setvalue|sleep|testcase|testsuite|timeout|unset|upload";
|
||||||
_expressions<<Expression("^ *("+commands+")\\b").weight(QFont::Bold).fg(Qt::darkBlue)
|
_expressions<<Expression("^ *("+commands+")\\b").weight(QFont::Bold).fg(Qt::darkBlue)
|
||||||
<<Expression("^ *#.*$").weight(QFont::Bold).fg(Qt::black);
|
<<Expression("^ *#.*$").weight(QFont::Bold).fg(Qt::black);
|
||||||
}
|
}
|
||||||
|
@@ -68,10 +68,12 @@ class PossibleRetryLoad: public TestFailed {
|
|||||||
class WrongSignal: public PossibleRetryLoad {
|
class WrongSignal: public PossibleRetryLoad {
|
||||||
public:
|
public:
|
||||||
WrongSignal(QString signal, QStringList args,
|
WrongSignal(QString signal, QStringList args,
|
||||||
std::pair<QString, QStringList> received):
|
std::pair<QString, QStringList> received,
|
||||||
|
QStringList sigs):
|
||||||
PossibleRetryLoad
|
PossibleRetryLoad
|
||||||
("expected: \""+signal+" "+args.join(' ')+"\"; "
|
("expected: \""+signal+" "+args.join(' ')+"\"; "
|
||||||
"received: \""+received.first+" "+received.second.join(' ')+"\"") {
|
"received: \""+received.first+" "+received.second.join(' ')
|
||||||
|
+"\"; queue: "+sigs.join(", ")) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user