improved waiting for elements: defaults to timeout-1 if element should be there, defaults to timeout/3 if element is optional
This commit is contained in:
		| @@ -274,9 +274,9 @@ AC_DEFUN([AX_QT_NO_KEYWORDS], [ | |||||||
| ]) | ]) | ||||||
|  |  | ||||||
| AC_DEFUN([AX_INIT_QT], [ | AC_DEFUN([AX_INIT_QT], [ | ||||||
|  |   if test -n "${AX_ADDITIONAL_QT_RULES_HACK}"; then | ||||||
|     test -f src/makefile.in && cat >> src/makefile.in <<EOF |     test -f src/makefile.in && cat >> src/makefile.in <<EOF | ||||||
| #### HERE |  | ||||||
| ${AX_ADDITIONAL_QT_RULES_HACK} | ${AX_ADDITIONAL_QT_RULES_HACK} | ||||||
| #### WE ARE |  | ||||||
| EOF | EOF | ||||||
|  |   fi | ||||||
| ]) | ]) | ||||||
|   | |||||||
| @@ -90,7 +90,7 @@ dnl refers to ${prefix}.  Thus we have to use `eval' twice. | |||||||
| #     $3 = filename of makefile.in | #     $3 = filename of makefile.in | ||||||
| AC_DEFUN([AX_ADD_MAKEFILE_TARGET_DEP], [ | AC_DEFUN([AX_ADD_MAKEFILE_TARGET_DEP], [ | ||||||
|   sh_add_makefile_target_dep() { |   sh_add_makefile_target_dep() { | ||||||
|     sed -i -e ':a;/^'${1}':.*\\$/{N;s/\\\n//;ta};s/^'${1}':.*$/& '${2}'/' "${srcdir}/${3}" |     sed -i -e ':a;/^'${1}':.*\\$/{N;s/\\\n//;ta};s/^'"${1}"':.*$/& '"${2}"'/' "${srcdir}/${3}" | ||||||
|     if ! egrep -q "${1}:.* ${2}" "${srcdir}/${3}"; then |     if ! egrep -q "${1}:.* ${2}" "${srcdir}/${3}"; then | ||||||
|         echo "${1}: ${2}" >> "${srcdir}/${3}" |         echo "${1}: ${2}" >> "${srcdir}/${3}" | ||||||
|     fi |     fi | ||||||
| @@ -1229,4 +1229,5 @@ AC_DEFUN([AX_OUTPUT], [ | |||||||
|   AX_RPM_RESOLVE |   AX_RPM_RESOLVE | ||||||
|   AC_OUTPUT |   AC_OUTPUT | ||||||
|   AX_INIT_QT |   AX_INIT_QT | ||||||
|  |   AC_MSG_NOTICE([configured for ${PACKAGE_NAME}-${VERSION}]) | ||||||
| ]) | ]) | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								bootstrap.sh
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								bootstrap.sh
									
									
									
									
									
								
							| @@ -138,6 +138,8 @@ GENERATED FILES | |||||||
|     * build-resource-file.sh - build resource.qrc file from a resource directory |     * build-resource-file.sh - build resource.qrc file from a resource directory | ||||||
|     * sql-to-dot.sed - script to convert SQL schema files to graphviz dot in doxygen |     * sql-to-dot.sed - script to convert SQL schema files to graphviz dot in doxygen | ||||||
|     * mac-create-app-bundle.sh - script to create apple mac os-x app-bundle |     * mac-create-app-bundle.sh - script to create apple mac os-x app-bundle | ||||||
|  |     * dependency-graph.sh - script to draw project dependencies | ||||||
|  |     * template.sh - generic template for bash scripts | ||||||
|     * test/runtests.sh - template file to run test scripts, i.e. docker based |     * test/runtests.sh - template file to run test scripts, i.e. docker based | ||||||
|     * AUTHORS - replace your name in AUTHORS before first run |     * AUTHORS - replace your name in AUTHORS before first run | ||||||
|     * NEWS - empty file add your project's news |     * NEWS - empty file add your project's news | ||||||
| @@ -549,6 +551,8 @@ copy rpmsign.exp | |||||||
| copy build-resource-file.sh | copy build-resource-file.sh | ||||||
| copy sql-to-dot.sed | copy sql-to-dot.sed | ||||||
| copy mac-create-app-bundle.sh | copy mac-create-app-bundle.sh | ||||||
|  | copy dependency-graph.sh | ||||||
|  | copy template.sh | ||||||
| AUTHOR=$(gpg -K 2>/dev/null | sed -n 's,uid *\(\[ultimate\] *\)\?,,p' | head -1) | AUTHOR=$(gpg -K 2>/dev/null | sed -n 's,uid *\(\[ultimate\] *\)\?,,p' | head -1) | ||||||
| if test -z "${AUTHOR}"; then | if test -z "${AUTHOR}"; then | ||||||
|     AUTHOR="FIRSTNAME LASTNAME (URL) <EMAIL>" |     AUTHOR="FIRSTNAME LASTNAME (URL) <EMAIL>" | ||||||
| @@ -1635,7 +1639,7 @@ BuildRequires: which, pkgconfig, gnupg, expect, ${VCSDEPENDS_RPM}make, automake, | |||||||
| %if 0%{?suse_version} || 0%{?sles_version} | %if 0%{?suse_version} || 0%{?sles_version} | ||||||
| BuildRequires: lsb-release$( | BuildRequires: lsb-release$( | ||||||
|     if testtag AX_REQUIRE_QT || testtag AX_CHECK_QT; then |     if testtag AX_REQUIRE_QT || testtag AX_CHECK_QT; then | ||||||
|       echo -n ", libqt5-qtbase-devel, libqt5-qttools, libQt5WebKit5-devel libqt5-qtwebengine-devel libQt5WebKitWidgets-devel"; |       echo -n ", libqt5-qtbase-devel, libqt5-qttools, libqt5-linguist-devel, libQt5WebKit5-devel libqt5-qtwebengine-devel libQt5WebKitWidgets-devel"; | ||||||
|     fi) |     fi) | ||||||
| %else | %else | ||||||
| $( | $( | ||||||
| @@ -1695,25 +1699,20 @@ rm -rf \$RPM_BUILD_ROOT | |||||||
| $(if testtag AX_USE_LIBTOOL; then | $(if testtag AX_USE_LIBTOOL; then | ||||||
| echo '/usr/%_lib/*.so.*' | echo '/usr/%_lib/*.so.*' | ||||||
| else | else | ||||||
| echo '/usr/bin/*' | echo '/usr/bin' | ||||||
| echo '/usr/share/applications/*' | echo '/usr/share/applications' | ||||||
| fi) | fi) | ||||||
| $(if testtag AX_USE_NODEJS AX_BUILD_HTML AX_BUILD_HTML_NPM; then | /usr/share/@PACKAGE_NAME@ | ||||||
| echo '/usr/share/@PACKAGE_NAME@' | $(if testtag AX_USE_ETC; then | ||||||
|  |  | ||||||
|  | cat <<EOF2 | ||||||
|  | %config | ||||||
|  | /etc/* | ||||||
|  |  | ||||||
|  | EOF2 | ||||||
| fi) | fi) | ||||||
| %doc | %doc | ||||||
| $(if testtag AX_USE_LIBTOOL; then | /usr/share/doc | ||||||
|   cat <<EOF2 |  | ||||||
| /usr/share/doc/packages/@PACKAGE_NAME@/AUTHORS |  | ||||||
| /usr/share/doc/packages/@PACKAGE_NAME@/COPYING |  | ||||||
| /usr/share/doc/packages/@PACKAGE_NAME@/ChangeLog |  | ||||||
| /usr/share/doc/packages/@PACKAGE_NAME@/INSTALL |  | ||||||
| /usr/share/doc/packages/@PACKAGE_NAME@/NEWS |  | ||||||
| /usr/share/doc/packages/@PACKAGE_NAME@/README |  | ||||||
| EOF2 |  | ||||||
| else |  | ||||||
|   echo '/usr/share' |  | ||||||
| fi) |  | ||||||
|  |  | ||||||
| $(if testtag AX_USE_LIBTOOL; then | $(if testtag AX_USE_LIBTOOL; then | ||||||
| cat <<EOF2 | cat <<EOF2 | ||||||
| @@ -1792,12 +1791,14 @@ ${HEADER}SUBDIRS =${SUBDIRS} | |||||||
|  |  | ||||||
| desktopdir = \${datadir}/applications | desktopdir = \${datadir}/applications | ||||||
| desktop_DATA = @PACKAGE_DESKTOP@ | desktop_DATA = @PACKAGE_DESKTOP@ | ||||||
| dist_pkgdata_DATA = @PACKAGE_ICON@ ax_check_qt.m4 bootstrap.sh		\\ | dist_pkgdata_DATA = @PACKAGE_ICON@ | ||||||
|  | dist_noinst_DATA = ax_check_qt.m4 bootstrap.sh				\\ | ||||||
|                    resolve-rpmbuilddeps.sh autogen.sh			\\ |                    resolve-rpmbuilddeps.sh autogen.sh			\\ | ||||||
|                     ax_cxx_compile_stdcxx_11.m4 build-in-docker.sh	\\ |                     ax_cxx_compile_stdcxx_11.m4 build-in-docker.sh	\\ | ||||||
|                     build-resource-file.sh				\\ |                     build-resource-file.sh				\\ | ||||||
|                     ax_init_standard_project.m4				\\ |                     ax_init_standard_project.m4				\\ | ||||||
|                     mac-create-app-bundle.sh resolve-debbuilddeps.sh    \\ |                     mac-create-app-bundle.sh resolve-debbuilddeps.sh    \\ | ||||||
|  |                     dependency-graph.sh template.sh                     \\ | ||||||
|                     sql-to-dot.sed |                     sql-to-dot.sed | ||||||
| dist_doc_DATA = AUTHORS NEWS README COPYING INSTALL ChangeLog | dist_doc_DATA = AUTHORS NEWS README COPYING INSTALL ChangeLog | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										171
									
								
								dependency-graph.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										171
									
								
								dependency-graph.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,171 @@ | |||||||
|  | #!/bin/bash -e | ||||||
|  |  | ||||||
|  | # template for bash scripts | ||||||
|  |  | ||||||
|  | # internal use only | ||||||
|  | append_msg() { | ||||||
|  |     if test $# -ne 0; then | ||||||
|  |         echo -en ":\e[0m \e[1m$*" | ||||||
|  |     fi | ||||||
|  |     echo -e "\e[0m" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write a notice | ||||||
|  | notice() { | ||||||
|  |     if test $# -eq 0; then | ||||||
|  |         return | ||||||
|  |     fi | ||||||
|  |     echo -e "\e[1m$*\e[0m" 1>&3 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write error message | ||||||
|  | error() { | ||||||
|  |     echo -en "\e[1;31merror" 1>&2 | ||||||
|  |     append_msg $* 1>&2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write a warning message | ||||||
|  | warning() { | ||||||
|  |     echo -en "\e[1;33mwarning" 1>&2 | ||||||
|  |     append_msg $* 1>&2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write a success message | ||||||
|  | success() { | ||||||
|  |     echo -en "\e[1;32msuccess" 1>&2 | ||||||
|  |     append_msg $* 1>&2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # commandline parameter evaluation | ||||||
|  | files=${0%/*}/configure.ac | ||||||
|  | short=0 | ||||||
|  | while test $# -gt 0; do | ||||||
|  |     case "$1" in | ||||||
|  |         (--short|-s) short=1;; | ||||||
|  |         (--help|-h) less <<EOF | ||||||
|  | SYNOPSIS | ||||||
|  |  | ||||||
|  |   $0 [OPTIONS] <files> | ||||||
|  |  | ||||||
|  | OPTIONS | ||||||
|  |  | ||||||
|  |   --help, -h                 show this help | ||||||
|  |   --short, -s                short graph with no external dependencies | ||||||
|  |  | ||||||
|  |   <files>                    list of zero or more configure.ac files | ||||||
|  |                              (default: ${files}) | ||||||
|  |  | ||||||
|  | DESCRIPTION | ||||||
|  |  | ||||||
|  |   Evaluates dependencies of all the given configure.ac file. By | ||||||
|  |   default takes the local configure.ac. Outputs a graphwiz dot file | ||||||
|  |   with the dependencies. Solid lines are required dependencies, dotted | ||||||
|  |   lines are optional dependencies. | ||||||
|  |  | ||||||
|  | EXAMPLE | ||||||
|  |  | ||||||
|  |   Evaluate all dependencies between all local subversion and git | ||||||
|  |   projects, if they are in the path ~/svn and ~/git: | ||||||
|  |  | ||||||
|  |     $0 ~/svn/*/configure.ac ~/git/*/configure.ac  | ||||||
|  |  | ||||||
|  | EOF | ||||||
|  |             exit;; | ||||||
|  |         (*) files=$*; break;; | ||||||
|  |     esac | ||||||
|  |     if test $# -eq 0; then | ||||||
|  |         error "missing parameter, try $0 --help"; exit 1 | ||||||
|  |     fi | ||||||
|  |     shift; | ||||||
|  | done | ||||||
|  |  | ||||||
|  | # run a command, print the result and abort in case of error | ||||||
|  | # option: --no-check: ignore the result, continue in case of error | ||||||
|  | run() { | ||||||
|  |     check=1 | ||||||
|  |     while test $# -gt 0; do | ||||||
|  |         case "$1" in | ||||||
|  |             (--no-check) check=0;; | ||||||
|  |             (*) break;; | ||||||
|  |         esac | ||||||
|  |         shift; | ||||||
|  |     done | ||||||
|  |     echo -en "\e[1m-> running:\e[0m $* ..." | ||||||
|  |     result=$($* 2>&1) | ||||||
|  |     res=$? | ||||||
|  |     if test $res -ne 0; then | ||||||
|  |         if test $check -eq 1; then | ||||||
|  |             error "failed with return code: $res" | ||||||
|  |             if test -n "$result"; then | ||||||
|  |                 echo "$result" | ||||||
|  |             fi | ||||||
|  |             exit 1 | ||||||
|  |         else | ||||||
|  |             warning "ignored return code: $res" | ||||||
|  |         fi | ||||||
|  |     else | ||||||
|  |         success | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # error handler | ||||||
|  | function traperror() { | ||||||
|  |     set +x | ||||||
|  |     local err=($1) # error status | ||||||
|  |     local line="$2" # LINENO | ||||||
|  |     local linecallfunc="$3" | ||||||
|  |     local command="$4" | ||||||
|  |     local funcstack="$5" | ||||||
|  |     for e in ${err[@]}; do | ||||||
|  |         if test -n "$e" -a "$e" != "0"; then | ||||||
|  |             error "line $line - command '$command' exited with status: $e (${err[@]})" | ||||||
|  |             if [ "${funcstack}" != "main" -o "$linecallfunc" != "0" ]; then | ||||||
|  |                 echo -n "   ... error at ${funcstack} " | ||||||
|  |                 if [ "$linecallfunc" != "" ]; then | ||||||
|  |                     echo -n "called at line $linecallfunc" | ||||||
|  |                 fi | ||||||
|  |                 echo | ||||||
|  |             fi | ||||||
|  |             exit $e | ||||||
|  |         fi | ||||||
|  |     done | ||||||
|  |     success | ||||||
|  |     exit 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # catch errors | ||||||
|  | trap 'traperror "$? ${PIPESTATUS[@]}" $LINENO $BASH_LINENO "$BASH_COMMAND" "${FUNCNAME[@]}" "${FUNCTION}"' ERR SIGINT INT TERM EXIT | ||||||
|  |  | ||||||
|  | ########################################################################################## | ||||||
|  |  | ||||||
|  | filter() { | ||||||
|  |     if test $short -eq 1; then | ||||||
|  |         all=$(cat) | ||||||
|  |         allowed=$(sed -n '/"\(.*\)" \[style=solid\];/{s//\1/;H};${x;s/\n//;s/\n/\\|/gp}' <<<"${all}") | ||||||
|  |         sed -n '/"\('"${allowed}"'\)" -> "\('"${allowed}"'\)"/p' <<<"${all}" | ||||||
|  |     else | ||||||
|  |         cat | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | echo "digraph G {" | ||||||
|  | if test $short -eq 0; then | ||||||
|  |     echo "node [style=dashed];" | ||||||
|  | fi | ||||||
|  | ( | ||||||
|  |     for file in $files; do | ||||||
|  |         if ! test -e $file; then | ||||||
|  |             error "file $file not found"; exit 1 | ||||||
|  |         fi | ||||||
|  |         sed -n ' | ||||||
|  |       /^ *m4_define(x_package_name, */ {s//"/;s/ *).*/"/;h;s/.*/& [style=solid];/p} | ||||||
|  |       /^ *AX_REQUIRE_QT/ {s/.*/"qt" -> /;G;s/\n//;s/.*/&;/p} | ||||||
|  |       /^ *AX_PKG_REQUIRE(\[\?\([^],)]\+\)\]\?, \[\?\([^],)]\+\)\]\?.*/ {s//"\2" -> /;G;s/\n//;s/.*/&;/p} | ||||||
|  |       /^ *AX_PKG_REQUIRE(\[\?\([^],)]\+\)\]\?.*/ {s//"\1" -> /;G;s/\n//;s/.*/&;/p} | ||||||
|  |       /^ *AX_CHECK_QT/ {s/.*/"qt" -> /;G;s/\n//;s/.*/& [style=dashed];/p} | ||||||
|  |       /^ *AX_PKG_CHECK(\[\?\([^],)]\+\)\]\?, \[\?\([^],)]\+\)\]\?.*/ {s//"\2" -> /;G;s/\n//;s/.*/& [style=dotted];/p} | ||||||
|  |       /^ *AX_PKG_CHECK(\[\?\([^],)]\+\)\]\?.*/ {s//"\1" -> /;G;s/\n//;s/.*/& [style=dotted];/p} | ||||||
|  |     ' $file | ||||||
|  |     done | ||||||
|  | ) | filter | ||||||
|  | echo "}" | ||||||
| @@ -33,6 +33,7 @@ | |||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <cassert> | #include <cassert> | ||||||
| #include <xml-cxx/xml.hxx> | #include <xml-cxx/xml.hxx> | ||||||
|  | #include <mrw/stdext.hxx> | ||||||
|  |  | ||||||
| #ifdef HAVE_CXXABI_H | #ifdef HAVE_CXXABI_H | ||||||
| #include <cxxabi.h> | #include <cxxabi.h> | ||||||
| @@ -151,11 +152,8 @@ class Command: public QObject { | |||||||
|     virtual bool isTestcase() { |     virtual bool isTestcase() { | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|     static void realMouseClick(Logger& log, QWebFrame* frame, QString selector) { |     static void realMouseClick(Logger& log, QWebFrame* frame, | ||||||
|       QWebElement element(find(frame, selector)); |                                Script* script, QString selector); | ||||||
|       if (element.isNull()) error(log, ElementNotFound(selector)); |  | ||||||
|       realMouseClick(element); |  | ||||||
|     } |  | ||||||
|     static void realMouseClick(const QWebElement& element) { |     static void realMouseClick(const QWebElement& element) { | ||||||
|       QWidget* web(element.webFrame()->page()->view()); |       QWidget* web(element.webFrame()->page()->view()); | ||||||
|       QRect elGeom=element.geometry(); |       QRect elGeom=element.geometry(); | ||||||
| @@ -248,8 +246,9 @@ class Command: public QObject { | |||||||
|       return element; |       return element; | ||||||
|     }     |     }     | ||||||
|     static QWebElement find1(QWebFrame* frame, QString selector, |     static QWebElement find1(QWebFrame* frame, QString selector, | ||||||
|                              int repeat = 5, int sleepsec = 1) { |                              int repeat = 2, int sleepsec = 1) { | ||||||
|       QWebElement element; |       QWebElement element; | ||||||
|  |       if (repeat<1) repeat=1; | ||||||
|       for (int i=0; i<repeat; ++i) { |       for (int i=0; i<repeat; ++i) { | ||||||
|         element = frame->findFirstElement(selector); |         element = frame->findFirstElement(selector); | ||||||
|         if (!element.isNull()) return element; |         if (!element.isNull()) return element; | ||||||
| @@ -257,7 +256,7 @@ class Command: public QObject { | |||||||
|           element = find1(childFrame, selector, 1, 0); |           element = find1(childFrame, selector, 1, 0); | ||||||
|           if (!element.isNull()) return element; |           if (!element.isNull()) return element; | ||||||
|         } |         } | ||||||
|         if (sleepsec) sleep(sleepsec); |         if (i+1<repeat && sleepsec) sleep(sleepsec); | ||||||
|       } |       } | ||||||
|       return element; |       return element; | ||||||
|     } |     } | ||||||
| @@ -855,7 +854,8 @@ class Script: public QObject { | |||||||
|     void ignore(const Script& o) { |     void ignore(const Script& o) { | ||||||
|       _ignore = o._ignore; |       _ignore = o._ignore; | ||||||
|     } |     } | ||||||
|     bool ignore(const QString& sig) { |     bool ignores(const QString& sig = QString()) { | ||||||
|  |       if (sig.isEmpty()) return !_ignore.empty(); | ||||||
|       return _ignore.contains(sig); |       return _ignore.contains(sig); | ||||||
|     } |     } | ||||||
|     void ignore(QStringList sigs = QStringList()) { |     void ignore(QStringList sigs = QStringList()) { | ||||||
| @@ -932,6 +932,9 @@ class Script: public QObject { | |||||||
|     void timeout(int t) { |     void timeout(int t) { | ||||||
|       _timeout = t; |       _timeout = t; | ||||||
|     } |     } | ||||||
|  |     int timeout() { | ||||||
|  |       return _timeout; | ||||||
|  |     } | ||||||
|     void defaultTimeout(int t) { |     void defaultTimeout(int t) { | ||||||
|       _defaultTimeout = t; |       _defaultTimeout = t; | ||||||
|     } |     } | ||||||
| @@ -995,7 +998,7 @@ class Script: public QObject { | |||||||
|                      SLOT(titleChanged(const QString&)))); |                      SLOT(titleChanged(const QString&)))); | ||||||
|       assert(connect(frame, SIGNAL(urlChanged(const QUrl&)), |       assert(connect(frame, SIGNAL(urlChanged(const QUrl&)), | ||||||
|                      SLOT(urlChanged(const QUrl&)))); |                      SLOT(urlChanged(const QUrl&)))); | ||||||
|       assert(connect(&_timer, SIGNAL(timeout()), SLOT(timeout()))); |       assert(connect(&_timer, SIGNAL(timeout()), SLOT(timedout()))); | ||||||
|     } |     } | ||||||
|     void removeSignals(QWebFrame* frame) { |     void removeSignals(QWebFrame* frame) { | ||||||
|       disconnect(dynamic_cast<NetworkAccessManager*> |       disconnect(dynamic_cast<NetworkAccessManager*> | ||||||
| @@ -1023,7 +1026,7 @@ class Script: public QObject { | |||||||
|                  this, SLOT(urlChanged(const QUrl&))); |                  this, SLOT(urlChanged(const QUrl&))); | ||||||
|       disconnect(frame, SIGNAL(urlChanged(const QUrl&)), |       disconnect(frame, SIGNAL(urlChanged(const QUrl&)), | ||||||
|                  this, SLOT(urlChanged(const QUrl&))); |                  this, SLOT(urlChanged(const QUrl&))); | ||||||
|       disconnect(&_timer, SIGNAL(timeout()), this, SLOT(timeout())); |       disconnect(&_timer, SIGNAL(timeout()), this, SLOT(timedout())); | ||||||
|     } |     } | ||||||
|   public Q_SLOTS: |   public Q_SLOTS: | ||||||
|     void log(QString text, Command* command = 0) { |     void log(QString text, Command* command = 0) { | ||||||
| @@ -1144,7 +1147,7 @@ class Script: public QObject { | |||||||
|       _signals.push(std::make_pair("urlChanged", |       _signals.push(std::make_pair("urlChanged", | ||||||
|                                    QStringList(url.toString()))); |                                    QStringList(url.toString()))); | ||||||
|     } |     } | ||||||
|     void timeout() { |     void timedout() { | ||||||
|       error(TimeOut()); |       error(TimeOut()); | ||||||
|     } |     } | ||||||
|   private: |   private: | ||||||
| @@ -1222,7 +1225,7 @@ class Do: public Command { | |||||||
|       Logger log(this, script); |       Logger log(this, script); | ||||||
|       QWebElement element(frame->documentElement()); |       QWebElement element(frame->documentElement()); | ||||||
|       if (_selector.size()) { |       if (_selector.size()) { | ||||||
|         element = find(frame, script->replacevars(_selector)); |         element = find(frame, script->replacevars(_selector), script->timeout()-1); | ||||||
|         if (element.isNull()) |         if (element.isNull()) | ||||||
|           error(log, ElementNotFound(script->replacevars(_selector))); |           error(log, ElementNotFound(script->replacevars(_selector))); | ||||||
|       } |       } | ||||||
| @@ -1305,7 +1308,7 @@ class Expect: public Command { | |||||||
|       Logger log(this, script); |       Logger log(this, script); | ||||||
|       QStringList args(script->replacevars(_signal._args)); |       QStringList args(script->replacevars(_signal._args)); | ||||||
|       if (_signal._signal=="load") { // special signal load |       if (_signal._signal=="load") { // special signal load | ||||||
|         while (!script->ignore("loadStarted") && script->checkSignal("loadStarted")) { |         while (!script->ignores("loadStarted") && script->checkSignal("loadStarted")) { | ||||||
|           log("ignore signal: loadStarted"); // ignore optional loadStarted |           log("ignore signal: loadStarted"); // ignore optional loadStarted | ||||||
|         } |         } | ||||||
|         if (!script->checkSignal("urlChanged", args)) |         if (!script->checkSignal("urlChanged", args)) | ||||||
| @@ -1532,7 +1535,7 @@ class Upload: public Command { | |||||||
|         if (files.size()==1) filename=files[0]; |         if (files.size()==1) filename=files[0]; | ||||||
|       } |       } | ||||||
|       page->setNextUploadFile(filename); |       page->setNextUploadFile(filename); | ||||||
|       realMouseClick(log, frame, script->replacevars(_selector)); |       realMouseClick(log, frame, script, script->replacevars(_selector)); | ||||||
|       if (page->uploadPrepared()) |       if (page->uploadPrepared()) | ||||||
|         error(log, SetFileUploadFailed(script->replacevars(_selector), filename)); |         error(log, SetFileUploadFailed(script->replacevars(_selector), filename)); | ||||||
|       return true; |       return true; | ||||||
| @@ -1576,7 +1579,7 @@ class Exists: public Command { | |||||||
|       QString selector(script->replacevars(_selector)); |       QString selector(script->replacevars(_selector)); | ||||||
|       QString text(script->replacevars(_text)); |       QString text(script->replacevars(_text)); | ||||||
|       QStringList notfound; |       QStringList notfound; | ||||||
|       QWebElement firstelement(find(frame, selector)); |       QWebElement firstelement(find(frame, selector, script->timeout()-1)); | ||||||
|       Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { |       Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { | ||||||
|         if (text.isEmpty()) return true; // just find element |         if (text.isEmpty()) return true; // just find element | ||||||
|         if (element.toOuterXml().indexOf(text)!=-1) return true; |         if (element.toOuterXml().indexOf(text)!=-1) return true; | ||||||
| @@ -1631,6 +1634,8 @@ class Not: public Command { | |||||||
|       Logger log(this, script); |       Logger log(this, script); | ||||||
|       QString selector(script->replacevars(_selector)); |       QString selector(script->replacevars(_selector)); | ||||||
|       QString text(script->replacevars(_text)); |       QString text(script->replacevars(_text)); | ||||||
|  |       QWebElement firstelement(find(frame, selector, | ||||||
|  |                                     mrw::max(mrw::min(script->timeout()/3, 10), 2))); | ||||||
|       Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { |       Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { | ||||||
|         if (text.isEmpty()) |         if (text.isEmpty()) | ||||||
|           error(log, AssertionFailed("element must not exists: "+selector)); |           error(log, AssertionFailed("element must not exists: "+selector)); | ||||||
| @@ -1828,12 +1833,12 @@ class Click: public Command { | |||||||
|       QString clicktarget(script->replacevars(_selector)); |       QString clicktarget(script->replacevars(_selector)); | ||||||
|       switch (_clicktype ? *_clicktype : script->clicktype()) { |       switch (_clicktype ? *_clicktype : script->clicktype()) { | ||||||
|         case Script::REAL_MOUSE_CLICK: { |         case Script::REAL_MOUSE_CLICK: { | ||||||
|           realMouseClick(log, frame, clicktarget); |           realMouseClick(log, frame, script, clicktarget); | ||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|         case Script::JAVASCRIPT_CLICK: |         case Script::JAVASCRIPT_CLICK: | ||||||
|         default: { |         default: { | ||||||
|           QWebElement element(find(frame, clicktarget)); |           QWebElement element(find(frame, clicktarget, script->timeout()-1)); | ||||||
|           if (element.isNull()) |           if (element.isNull()) | ||||||
|             error(log, ElementNotFound(clicktarget)); |             error(log, ElementNotFound(clicktarget)); | ||||||
|           _result = element.evaluateJavaScript("this.click();").toString(); |           _result = element.evaluateJavaScript("this.click();").toString(); | ||||||
| @@ -2145,7 +2150,8 @@ class SetValue: public Command { | |||||||
|     } |     } | ||||||
|     bool execute(Script* script, QWebFrame* frame) { |     bool execute(Script* script, QWebFrame* frame) { | ||||||
|       Logger log(this, script); |       Logger log(this, script); | ||||||
|       QWebElement element(find(frame, script->replacevars(_selector))); |       QWebElement element(find(frame, script->replacevars(_selector), | ||||||
|  |                                script->timeout()-1)); | ||||||
|       if (element.isNull()) |       if (element.isNull()) | ||||||
|         error(log, ElementNotFound(script->replacevars(_selector))); |         error(log, ElementNotFound(script->replacevars(_selector))); | ||||||
|       QString value(script->replacevars(_value)); |       QString value(script->replacevars(_value)); | ||||||
| @@ -2334,6 +2340,8 @@ class If: public CommandContainer { | |||||||
|       QString selector(script->replacevars(_variable)); |       QString selector(script->replacevars(_variable)); | ||||||
|       bool check(false); |       bool check(false); | ||||||
|       if (_cmp=="->") { |       if (_cmp=="->") { | ||||||
|  |         QWebElement firstelement(find(frame, selector, | ||||||
|  |                                       mrw::max(mrw::min(script->timeout()/3, 10), 2))); | ||||||
|         Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { |         Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { | ||||||
|           if (value.isEmpty() || // just find element |           if (value.isEmpty() || // just find element | ||||||
|               element.toOuterXml().indexOf(value)!=-1 || |               element.toOuterXml().indexOf(value)!=-1 || | ||||||
| @@ -2439,6 +2447,8 @@ class While: public CommandContainer { | |||||||
|       for (bool check(true); check;) { |       for (bool check(true); check;) { | ||||||
|         if (_cmp=="->") { |         if (_cmp=="->") { | ||||||
|           check = false; |           check = false; | ||||||
|  |           QWebElement firstelement(find(frame, selector, | ||||||
|  |                                         mrw::max(mrw::min(script->timeout()/3, 10), 2))); | ||||||
|           Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { |           Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { | ||||||
|             if (value.isEmpty() || // just find element |             if (value.isEmpty() || // just find element | ||||||
|                 element.toOuterXml().indexOf(value)!=-1 || |                 element.toOuterXml().indexOf(value)!=-1 || | ||||||
| @@ -2899,6 +2909,8 @@ class Case: public Command { | |||||||
|           log("terminate with default branch"); |           log("terminate with default branch"); | ||||||
|           check = true; |           check = true; | ||||||
|         } else if (condition.cmp=="->") { |         } else if (condition.cmp=="->") { | ||||||
|  |           QWebElement firstelement(find(frame, selector, | ||||||
|  |                                         mrw::max(mrw::min(script->timeout()/3, 10), 2))); | ||||||
|           Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { |           Q_FOREACH(QWebElement element, frame->findAllElements(selector)) { | ||||||
|             if (value.isEmpty() || // just find element |             if (value.isEmpty() || // just find element | ||||||
|                 element.toOuterXml().indexOf(value)!=-1 || |                 element.toOuterXml().indexOf(value)!=-1 || | ||||||
| @@ -3159,6 +3171,13 @@ inline Logger::~Logger() { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline void Command::realMouseClick(Logger& log, QWebFrame* frame, | ||||||
|  |                                     Script* script, QString selector) { | ||||||
|  |   QWebElement element(find(frame, selector, script->timeout()-1)); | ||||||
|  |   if (element.isNull()) error(log, ElementNotFound(selector)); | ||||||
|  |   realMouseClick(element); | ||||||
|  | } | ||||||
|  |  | ||||||
| inline std::shared_ptr<Script> Command::subParser(Script* parent, const QStringList& in, | inline std::shared_ptr<Script> Command::subParser(Script* parent, const QStringList& in, | ||||||
|                                                   const QString& file, |                                                   const QString& file, | ||||||
|                                                   int line, int indent) { |                                                   int line, int indent) { | ||||||
|   | |||||||
							
								
								
									
										121
									
								
								template.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										121
									
								
								template.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | #!/bin/bash -e | ||||||
|  |  | ||||||
|  | # template for bash scripts | ||||||
|  |  | ||||||
|  | # internal use only | ||||||
|  | append_msg() { | ||||||
|  |     if test $# -ne 0; then | ||||||
|  |         echo -en ":\e[0m \e[1m$*" | ||||||
|  |     fi | ||||||
|  |     echo -e "\e[0m" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write a notice | ||||||
|  | notice() { | ||||||
|  |     if test $# -eq 0; then | ||||||
|  |         return | ||||||
|  |     fi | ||||||
|  |     echo -e "\e[1m$*\e[0m" 1>&3 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write error message | ||||||
|  | error() { | ||||||
|  |     echo -en "\e[1;31merror" 1>&2 | ||||||
|  |     append_msg $* 1>&2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write a warning message | ||||||
|  | warning() { | ||||||
|  |     echo -en "\e[1;33mwarning" 1>&2 | ||||||
|  |     append_msg $* 1>&2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # write a success message | ||||||
|  | success() { | ||||||
|  |     echo -en "\e[1;32msuccess" 1>&2 | ||||||
|  |     append_msg $* 1>&2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # commandline parameter evaluation | ||||||
|  | while test $# -gt 0; do | ||||||
|  |     case "$1" in | ||||||
|  |         (--help|-h) less <<EOF | ||||||
|  | SYNOPSIS | ||||||
|  |  | ||||||
|  |   $0 [OPTIONS] | ||||||
|  |  | ||||||
|  | OPTIONS | ||||||
|  |  | ||||||
|  |   --help, -h                 show this help | ||||||
|  |  | ||||||
|  | DESCRIPTION | ||||||
|  |  | ||||||
|  | EOF | ||||||
|  |             exit;; | ||||||
|  |         (*) error "unknow option $1, try $0 --help"; exit 1;; | ||||||
|  |     esac | ||||||
|  |     if test $# -eq 0; then | ||||||
|  |         error "missing parameter, try $0 --help"; exit 1 | ||||||
|  |     fi | ||||||
|  |     shift; | ||||||
|  | done | ||||||
|  |  | ||||||
|  | # run a command, print the result and abort in case of error | ||||||
|  | # option: --no-check: ignore the result, continue in case of error | ||||||
|  | run() { | ||||||
|  |     check=1 | ||||||
|  |     while test $# -gt 0; do | ||||||
|  |         case "$1" in | ||||||
|  |             (--no-check) check=0;; | ||||||
|  |             (*) break;; | ||||||
|  |         esac | ||||||
|  |         shift; | ||||||
|  |     done | ||||||
|  |     echo -en "\e[1m-> running:\e[0m $* ..." | ||||||
|  |     result=$($* 2>&1) | ||||||
|  |     res=$? | ||||||
|  |     if test $res -ne 0; then | ||||||
|  |         if test $check -eq 1; then | ||||||
|  |             error "failed with return code: $res" | ||||||
|  |             if test -n "$result"; then | ||||||
|  |                 echo "$result" | ||||||
|  |             fi | ||||||
|  |             exit 1 | ||||||
|  |         else | ||||||
|  |             warning "ignored return code: $res" | ||||||
|  |         fi | ||||||
|  |     else | ||||||
|  |         success | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # error handler | ||||||
|  | function traperror() { | ||||||
|  |     set +x | ||||||
|  |     local err=($1) # error status | ||||||
|  |     local line="$2" # LINENO | ||||||
|  |     local linecallfunc="$3" | ||||||
|  |     local command="$4" | ||||||
|  |     local funcstack="$5" | ||||||
|  |     for e in ${err[@]}; do | ||||||
|  |         if test -n "$e" -a "$e" != "0"; then | ||||||
|  |             error "line $line - command '$command' exited with status: $e (${err[@]})" | ||||||
|  |             if [ "${funcstack}" != "main" -o "$linecallfunc" != "0" ]; then | ||||||
|  |                 echo -n "   ... error at ${funcstack} " | ||||||
|  |                 if [ "$linecallfunc" != "" ]; then | ||||||
|  |                     echo -n "called at line $linecallfunc" | ||||||
|  |                 fi | ||||||
|  |                 echo | ||||||
|  |             fi | ||||||
|  |             exit $e | ||||||
|  |         fi | ||||||
|  |     done | ||||||
|  |     success | ||||||
|  |     exit 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # catch errors | ||||||
|  | trap 'traperror "$? ${PIPESTATUS[@]}" $LINENO $BASH_LINENO "$BASH_COMMAND" "${FUNCNAME[@]}" "${FUNCTION}"' ERR SIGINT INT TERM EXIT | ||||||
|  |  | ||||||
|  | ########################################################################################## | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user