diff --git a/scripts/90wt-mode.wt b/scripts/90wt-mode.el.in similarity index 87% rename from scripts/90wt-mode.wt rename to scripts/90wt-mode.el.in index fa07712..5099bdf 100644 --- a/scripts/90wt-mode.wt +++ b/scripts/90wt-mode.el.in @@ -4,6 +4,7 @@ ;; ;; Set up to autoload +(add-to-list 'load-path "@emacsdir@") (autoload 'wt-mode "wt-mode" "Major mode for editing Webtester test scripts" t) (setq auto-mode-alist (cons '("\\.wt\\'" . wt-mode) auto-mode-alist)) diff --git a/scripts/makefile.am b/scripts/makefile.am index 2eeff34..47717dc 100644 --- a/scripts/makefile.am +++ b/scripts/makefile.am @@ -12,7 +12,13 @@ emacsdir = ${datadir}/emacs/site-lisp dist_emacs_SCRIPTS = wt-mode.el 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 diff --git a/scripts/wt-mode.el b/scripts/wt-mode.el index e17b8b0..7621539 100644 --- a/scripts/wt-mode.el +++ b/scripts/wt-mode.el @@ -25,7 +25,7 @@ ;; echo $(webrunner -h | sed -n 's, COMMAND: ,,p') | sed 's, ,\\\\|,g' (defconst wt-font-lock-keywords (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)) "Highlighting expressions for Webtester") diff --git a/src/commands.hxx b/src/commands.hxx index fe9f569..fba1676 100644 --- a/src/commands.hxx +++ b/src/commands.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -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)< 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< _signals; + QSet _ignore; ///< signals to ignore QTimer _timer; int _step; QSet _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()+" <...>" + "\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 parse(Script*, QString args, + QStringList&, QString, int, int) { + std::shared_ptr 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()+" <...>" + "\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 parse(Script*, QString args, + QStringList&, QString, int, int) { + std::shared_ptr 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 diff --git a/src/editor.hxx b/src/editor.hxx index 57e6cf6..4b3b411 100644 --- a/src/editor.hxx +++ b/src/editor.hxx @@ -19,7 +19,7 @@ class Highlighter: public QSyntaxHighlighter { void include(QString); public: 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< received): + std::pair received, + QStringList sigs): PossibleRetryLoad ("expected: \""+signal+" "+args.join(' ')+"\"; " - "received: \""+received.first+" "+received.second.join(' ')+"\"") { + "received: \""+received.first+" "+received.second.join(' ') + +"\"; queue: "+sigs.join(", ")) { } };