improved waiting for elements: defaults to timeout-1 if element should be there, defaults to timeout/3 if element is optional

master
Marc Wäckerlin 7 years ago
parent 248d3b5032
commit 605c4eea79
  1. 2
      COPYING
  2. 2
      INSTALL
  3. 6
      ax_check_qt.m4
  4. 3
      ax_init_standard_project.m4
  5. 39
      bootstrap.sh
  6. 171
      dependency-graph.sh
  7. 55
      src/commands.hxx
  8. 121
      template.sh

@ -1 +1 @@
/usr/share/automake-1.13/COPYING /usr/share/automake-1.15/COPYING

@ -1 +1 @@
/usr/share/automake-1.13/INSTALL /usr/share/automake-1.15/INSTALL

@ -274,9 +274,9 @@ AC_DEFUN([AX_QT_NO_KEYWORDS], [
]) ])
AC_DEFUN([AX_INIT_QT], [ AC_DEFUN([AX_INIT_QT], [
test -f src/makefile.in && cat >> src/makefile.in <<EOF if test -n "${AX_ADDITIONAL_QT_RULES_HACK}"; then
#### HERE test -f src/makefile.in && cat >> src/makefile.in <<EOF
${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}])
]) ])

@ -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
fi)
%doc cat <<EOF2
$(if testtag AX_USE_LIBTOOL; then %config
cat <<EOF2 /etc/*
/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 EOF2
else
echo '/usr/share'
fi) fi)
%doc
/usr/share/doc
$(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@
resolve-rpmbuilddeps.sh autogen.sh \\ dist_noinst_DATA = ax_check_qt.m4 bootstrap.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

@ -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) {

@ -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
##########################################################################################
Loading…
Cancel
Save