Browse Source

test framework part2

cl-refactor
arkpar 10 years ago
parent
commit
57e88359dc
  1. 23
      mix/CMakeLists.txt
  2. 5
      mix/ClientModel.cpp
  3. 2
      mix/ClientModel.h
  4. 51
      mix/MixApplication.cpp
  5. 8
      mix/MixApplication.h
  6. 41
      mix/QBasicNodeDefinition.cpp
  7. 12
      mix/QBasicNodeDefinition.h
  8. 1
      mix/QVariableDeclaration.cpp
  9. 5
      mix/QVariableDeclaration.h
  10. 36
      mix/QVariableDefinition.cpp
  11. 8
      mix/QVariableDefinition.h
  12. 29
      mix/main.cpp
  13. 1
      mix/qml.qrc
  14. 4
      mix/qml/Application.qml
  15. 5
      mix/qml/CallStack.qml
  16. 51
      mix/qml/CodeEditor.qml
  17. 1
      mix/qml/CodeEditorStyle.qml
  18. 15
      mix/qml/CodeEditorView.qml
  19. 2
      mix/qml/CommonSeparator.qml
  20. 12
      mix/qml/Debugger.qml
  21. 1
      mix/qml/DebuggerPaneStyle.qml
  22. 1
      mix/qml/DefaultLabel.qml
  23. 4
      mix/qml/DeploymentDialog.qml
  24. 30
      mix/qml/FilesSection.qml
  25. 72
      mix/qml/LogsPane.qml
  26. 1
      mix/qml/LogsPaneStyle.qml
  27. 1
      mix/qml/NewProjectDialog.qml
  28. 1
      mix/qml/ProjectFilesStyle.qml
  29. 21
      mix/qml/ProjectList.qml
  30. 1
      mix/qml/ProjectModel.qml
  31. 3
      mix/qml/Splitter.qml
  32. 6
      mix/qml/StateDialog.qml
  33. 1
      mix/qml/StateDialogStyle.qml
  34. 6
      mix/qml/StatusPane.qml
  35. 1
      mix/qml/StatusPaneStyle.qml
  36. 1
      mix/qml/Style.qml
  37. 6
      mix/qml/TransactionDialog.qml
  38. 16
      mix/qml/WebCodeEditor.qml
  39. 20
      mix/qml/WebPreview.qml
  40. 1
      mix/qml/WebPreviewStyle.qml
  41. 8
      mix/qml/qmldir
  42. 50
      mix/test/TestMain.cpp
  43. 51
      mix/test/TestMain.qml
  44. 113
      mix/test/TestService.cpp
  45. 52
      mix/test/TestService.h
  46. 52
      mix/test/qml/TestMain.qml
  47. 0
      mix/test/qml/TestTransactionDebug.qml
  48. 2
      mix/web.qrc

23
mix/CMakeLists.txt

@ -16,7 +16,7 @@ include_directories(${Boost_INCLUDE_DIRS})
include_directories(BEFORE ..)
find_package (Qt5WebEngine QUIET)
qt5_add_resources(UI_RESOURCES res.qrc qml.qrc test.qrc)
qt5_add_resources(UI_RESOURCES res.qrc qml.qrc)
file(GLOB HEADERS "*.h")
@ -37,16 +37,12 @@ eth_add_executable(${EXECUTABLE}
UI_RESOURCES ${UI_RESOURCES}
)
find_package(Qt5QuickTest REQUIRED)
find_package(Qt5Test REQUIRED)
set(LIBRARIES "Qt5::Core;Qt5::Gui;Qt5::Widgets;Qt5::Network;Qt5::Quick;Qt5::Qml;webthree;ethereum;evm;ethcore;devcrypto;solidity;evmcore;devcore;jsqrc;web3jsonrpc")
if (${ETH_HAVE_WEBENGINE})
add_definitions(-DETH_HAVE_WEBENGINE)
list(APPEND LIBRARIES "Qt5::WebEngine")
endif()
list(APPEND LIBRARIES "Qt5::QuickTest")
list(APPEND LIBRARIES "Qt5::Test")
target_link_libraries(${EXECUTABLE} ${LIBRARIES})
@ -57,15 +53,22 @@ eth_install_executable(${EXECUTABLE}
#add qml asnd stdc files to project tree in Qt creator
file(GLOB_RECURSE QMLFILES "qml/*.*")
file(GLOB_RECURSE TESTFILE "test/*.*")
file(GLOB_RECURSE TESTFILES "test/qml/*.*")
file(GLOB_RECURSE SOLFILES "stdc/*.*")
add_custom_target(mix_qml SOURCES ${QMLFILES} ${SOLFILES} ${TESTFILES})
#test target
#set(TEST_EXECUTABLE mix_test)
#qt5_add_resources(UI_RESOURCES test.qrc)
#add_executable(${TEST_EXECUTABLE} ${UI_RESOURCES} ${SRC_LIST} ${HEADERS})
find_package(Qt5QuickTest REQUIRED)
find_package(Qt5Test REQUIRED)
set(TEST_EXECUTABLE mix_test)
list(APPEND LIBRARIES "Qt5::QuickTest")
list(APPEND LIBRARIES "Qt5::Test")
list(REMOVE_ITEM SRC_LIST "./main.cpp")
aux_source_directory(test SRC_LIST)
file(GLOB HEADERS "test/*.h")
add_executable(${TEST_EXECUTABLE} ${UI_RESOURCES} ${SRC_LIST} ${HEADERS})
target_link_libraries(${TEST_EXECUTABLE} ${LIBRARIES})
set_target_properties(${TEST_EXECUTABLE} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)

5
mix/ClientModel.cpp

@ -90,6 +90,7 @@ ClientModel::ClientModel():
ClientModel::~ClientModel()
{
m_runFuture.waitForFinished();
}
QString ClientModel::apiCall(QString const& _message)
@ -113,7 +114,7 @@ void ClientModel::mine()
m_mining = true;
emit miningStarted();
emit miningStateChanged();
QtConcurrent::run([=]()
m_runFuture = QtConcurrent::run([=]()
{
try
{
@ -206,7 +207,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
emit runStateChanged();
//run sequence
QtConcurrent::run([=]()
m_runFuture = QtConcurrent::run([=]()
{
try
{

2
mix/ClientModel.h

@ -27,6 +27,7 @@
#include <map>
#include <QString>
#include <QVariantMap>
#include <QFuture>
#include "MachineStates.h"
namespace dev
@ -203,6 +204,7 @@ private:
std::atomic<bool> m_running;
std::atomic<bool> m_mining;
QFuture<void> m_runFuture;
std::unique_ptr<MixClient> m_client;
std::unique_ptr<RpcConnector> m_rpcConnector;
std::unique_ptr<Web3Server> m_web3Server;

51
mix/MixApplication.cpp

@ -24,9 +24,6 @@
#include <QUrl>
#include <QIcon>
#include <QFont>
#include <QtTest/QSignalSpy>
#include <QElapsedTimer>
#include <QtTest/QTest>
#ifdef ETH_HAVE_WEBENGINE
#include <QtWebEngine/QtWebEngine>
#endif
@ -50,45 +47,10 @@ ApplicationService::ApplicationService()
m_systemPointSize = f.pointSize();
}
#include <QMetaMethod>
bool ApplicationService::waitForSignal(QObject* _item, QString _signalName, int _timeout)
{
QSignalSpy spy(_item, ("2" + _signalName.toStdString()).c_str());
QMetaObject const* mo = _item->metaObject();
QStringList methods;
for(int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
if (mo->method(i).methodType() == QMetaMethod::Signal) {
methods << QString::fromLatin1(mo->method(i).methodSignature());
}
}
QElapsedTimer timer;
timer.start();
while (!spy.size()) {
int remaining = _timeout - int(timer.elapsed());
if (remaining <= 0)
break;
QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QTest::qSleep(10);
}
return spy.size();
}
MixApplication::MixApplication(int& _argc, char* _argv[]):
QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine())
{
initialize();
//m_engine->load(QUrl("qrc:/qml/main.qml"));
m_engine->load(QUrl("qrc:/test/TestMain.qml"));
m_engine->load(QUrl("qrc:/qml/Application.qml"));
if (!m_engine->rootObjects().empty())
{
QWindow *window = qobject_cast<QWindow*>(m_engine->rootObjects().at(0));
@ -100,6 +62,17 @@ MixApplication::MixApplication(int& _argc, char* _argv[]):
void MixApplication::initialize()
{
#if __linux
//work around ubuntu appmenu-qt5 bug
//https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853
putenv((char*)"QT_QPA_PLATFORMTHEME=");
putenv((char*)"QSG_RENDER_LOOP=threaded");
#endif
#if (defined(_WIN32) || defined(_WIN64))
if (!getenv("OPENSSL_CONF"))
putenv((char*)"OPENSSL_CONF=c:\\");
#endif
setOrganizationName(tr("Ethereum"));
setOrganizationDomain(tr("ethereum.org"));
setApplicationName(tr("Mix"));

8
mix/MixApplication.h

@ -37,12 +37,16 @@ class ApplicationService: public QObject
{
Q_OBJECT
Q_PROPERTY(int systemPointSize READ systemPointSize CONSTANT)
Q_PROPERTY(bool haveWebEngine READ haveWebEngine CONSTANT)
public:
ApplicationService();
int systemPointSize() const { return m_systemPointSize; }
public slots:
bool waitForSignal(QObject* _item, QString _signalName, int _timeout);
#ifdef ETH_HAVE_WEBENGINE
bool haveWebEngine() const { return true; }
#else
bool haveWebEngine() const { return false; }
#endif
private:
int m_systemPointSize = 0;

41
mix/QBasicNodeDefinition.cpp

@ -0,0 +1,41 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QBasicNodeDefinition.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/
#include "QBasicNodeDefinition.h"
#include <libsolidity/AST.h>
namespace dev
{
namespace mix
{
QBasicNodeDefinition::QBasicNodeDefinition(QObject* _parent, solidity::Declaration const* _d):
QObject(_parent), m_name(QString::fromStdString(_d->getName()))
{
}
QBasicNodeDefinition::QBasicNodeDefinition(QObject* _parent, std::string const& _name):
QObject(_parent), m_name(QString::fromStdString(_name))
{
}
}
}

12
mix/QBasicNodeDefinition.h

@ -21,11 +21,17 @@
#pragma once
#include <string>
#include <QObject>
#include <libsolidity/AST.h>
namespace dev
{
namespace solidity
{
class Declaration;
}
namespace mix
{
@ -37,8 +43,8 @@ class QBasicNodeDefinition: public QObject
public:
QBasicNodeDefinition(QObject* _parent = nullptr): QObject(_parent) {}
~QBasicNodeDefinition() {}
QBasicNodeDefinition(QObject* _parent, solidity::Declaration const* _d): QObject(_parent), m_name(QString::fromStdString(_d->getName())) {}
QBasicNodeDefinition(QObject* _parent, std::string const& _name): QObject(_parent), m_name(QString::fromStdString(_name)) {}
QBasicNodeDefinition(QObject* _parent, solidity::Declaration const* _d);
QBasicNodeDefinition(QObject* _parent, std::string const& _name);
/// Get the name of the node.
QString name() const { return m_name; }

1
mix/QVariableDeclaration.cpp

@ -21,6 +21,7 @@
*/
#include "QVariableDeclaration.h"
#include <libsolidity/AST.h>
#include "CodeModel.h"
namespace dev

5
mix/QVariableDeclaration.h

@ -26,14 +26,15 @@
#pragma once
namespace dev
{
namespace solidity
{
class Type;
class VariableDeclaration;
}
namespace dev
{
namespace mix
{

36
mix/QVariableDefinition.cpp

@ -0,0 +1,36 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QVariableDefinition.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/
#include "QVariableDefinition.h"
#include <libdevcore/CommonJS.h>
namespace dev
{
namespace mix
{
QString QVariableDefinition::encodeValueAsString()
{
return QString::fromStdString(dev::toHex(encodeValue()));
}
}
}

8
mix/QVariableDefinition.h

@ -21,14 +21,14 @@
#pragma once
#include <QAbstractListModel>
#include "QBigInt.h"
#include "QVariableDeclaration.h"
#include <QObject>
#include <libdevcore/Common.h>
namespace dev
{
namespace mix
{
class QVariableDeclaration;
class QVariableDefinition: public QObject
{
@ -54,7 +54,7 @@ public:
/// Decode the return value @a _rawValue.
virtual void decodeValue(dev::bytes const& _rawValue) = 0;
/// returns String representation of the encoded value.
Q_INVOKABLE QString encodeValueAsString() { return QString::fromStdString(dev::toHex(encodeValue())); }
Q_INVOKABLE QString encodeValueAsString();
protected:
QString m_value;

29
mix/main.cpp

@ -22,40 +22,19 @@
#include <iostream>
#include <stdlib.h>
#include <boost/exception/exception.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include "MixApplication.h"
#include "Exceptions.h"
#include <QtQuickTest/quicktest.h>
using namespace dev::mix;
int main(int _argc, char* _argv[])
{
#ifdef ETH_HAVE_WEBENGINE
Q_INIT_RESOURCE(js);
#endif
#if __linux
//work around ubuntu appmenu-qt5 bug
//https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853
putenv((char*)"QT_QPA_PLATFORMTHEME=");
putenv((char*)"QSG_RENDER_LOOP=threaded");
#endif
#if (defined(_WIN32) || defined(_WIN64))
if (!getenv("OPENSSL_CONF"))
putenv((char*)"OPENSSL_CONF=c:\\");
#endif
try
{
//
MixApplication::initialize();
//MixApplication app(_argc, _argv);
return quick_test_main(_argc, _argv, "mix", "/home/arkady/src/cpp-ethereum/mix/test/TestMain.qml");
//MixApplication app(_argc, _argv);
//return app.exec();
MixApplication app(_argc, _argv);
return app.exec();
}
catch (boost::exception const& _e)
{

1
mix/qml.qrc

@ -60,6 +60,5 @@
<file>qml/js/ProjectModel.js</file>
<file>qml/js/QEtherHelper.js</file>
<file>qml/js/TransactionHelper.js</file>
<file>qml/qmldir</file>
</qresource>
</RCC>

4
mix/qml/Application.qml

@ -55,6 +55,10 @@ ApplicationWindow {
id: clipboard
}
Style {
id: appStyle
}
Connections {
target: mainApplication
onClosing:

5
mix/qml/CallStack.qml

@ -2,7 +2,6 @@ import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
import "."
DebugInfoList
{
@ -37,7 +36,7 @@ DebugInfoList
anchors.leftMargin: 5
color: "#4a4a4a"
text: styleData.row;
font.pointSize: DebuggerPaneStyle.general.basicFontSize
font.pointSize: dbgStyle.general.basicFontSize
width: parent.width - 5
elide: Text.ElideRight
}
@ -58,7 +57,7 @@ DebugInfoList
color: "#4a4a4a"
text: styleData.value;
elide: Text.ElideRight
font.pointSize: DebuggerPaneStyle.general.basicFontSize
font.pointSize: dbgStyle.general.basicFontSize
}
}
}

51
mix/qml/CodeEditor.qml

@ -24,31 +24,36 @@ Item {
id: contentView
width: parent.width
height: parent.height * 0.7
Rectangle {
id: lineColumn
property int rowHeight: codeEditor.font.pixelSize + 3
color: "#202020"
width: 50
height: parent.height
Column {
y: -codeEditor.flickableItem.contentY + 4
width: parent.width
Repeater {
model: Math.max(codeEditor.lineCount + 2, (lineColumn.height/lineColumn.rowHeight))
delegate: Text {
id: text
color: codeEditor.textColor
font: codeEditor.font
width: lineColumn.width - 4
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
height: lineColumn.rowHeight
renderType: Text.NativeRendering
text: index + 1
}
CodeEditorStyle {
id: style
}
Rectangle {
id: lineColumn
property int rowHeight: codeEditor.font.pixelSize + 3
color: "#202020"
width: 50
height: parent.height
Column {
y: -codeEditor.flickableItem.contentY + 4
width: parent.width
Repeater {
model: Math.max(codeEditor.lineCount + 2, (lineColumn.height/lineColumn.rowHeight))
delegate: Text {
id: text
color: codeEditor.textColor
font: codeEditor.font
width: lineColumn.width - 4
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
height: lineColumn.rowHeight
renderType: Text.NativeRendering
text: index + 1
}
}
}
}
TextArea {
id: codeEditor
@ -66,7 +71,7 @@ Item {
height: parent.height
font.family: "Monospace"
font.pointSize: CodeEditorStyle.general.basicFontSize
font.pointSize: style.general.basicFontSize
width: parent.width
tabChangesFocus: false

1
mix/qml/CodeEditorStyle.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

15
mix/qml/CodeEditorView.qml

@ -10,6 +10,7 @@ Item {
signal documentEdit(string documentId)
signal breakpointsChanged(string documentId)
signal isCleanChanged(var isClean, string documentId)
signal loadComplete
function getDocumentText(documentId) {
for (var i = 0; i < editorListModel.count; i++) {
@ -43,6 +44,9 @@ Item {
function doLoadDocument(editor, document) {
var data = fileIo.readFile(document.path);
editor.onLoadComplete.connect(function() {
loadComplete();
});
editor.onEditorTextChanged.connect(function() {
documentEdit(document.documentId);
if (document.isContract)
@ -160,6 +164,11 @@ Item {
}
}
CodeEditorStyle
{
id: style;
}
MessageDialog
{
id: messageDialog
@ -177,12 +186,16 @@ Item {
Repeater {
id: editors
model: editorListModel
onItemRemoved: {
console.log("unloaded");
item.item.unloaded = true;
}
delegate: Loader {
id: loader
active: false
asynchronous: true
anchors.fill: parent
source: "CodeEditor.qml"
source: appService.haveWebEngine ? "WebCodeEditor.qml" : "CodeEditor.qml"
visible: (index >= 0 && index < editorListModel.count && currentDocumentId === editorListModel.get(index).documentId)
property bool changed: false
onVisibleChanged: {

2
mix/qml/CommonSeparator.qml

@ -4,6 +4,6 @@ import "."
Rectangle
{
height: 1
color: Style.generic.layout.separatorColor
color: appStyle.generic.layout.separatorColor
}

12
mix/qml/Debugger.qml

@ -65,6 +65,10 @@ Rectangle {
Debugger.setBreakpoints(bp);
}
DebuggerPaneStyle {
id: dbgStyle
}
Connections {
target: clientModel
onDebugDataReady: {
@ -422,7 +426,7 @@ Rectangle {
color: "#b2b3ae"
text: styleData.value.split(' ')[0]
font.family: "monospace"
font.pointSize: DebuggerPaneStyle.general.basicFontSize
font.pointSize: dbgStyle.general.basicFontSize
wrapMode: Text.NoWrap
id: id
}
@ -432,7 +436,7 @@ Rectangle {
color: styleData.selected ? "white" : "black"
font.family: "monospace"
text: styleData.value.replace(styleData.value.split(' ')[0], '')
font.pointSize: DebuggerPaneStyle.general.basicFontSize
font.pointSize: dbgStyle.general.basicFontSize
}
}
}
@ -505,7 +509,7 @@ Rectangle {
font.family: "monospace"
color: "#4a4a4a"
text: styleData.row;
font.pointSize: DebuggerPaneStyle.general.basicFontSize
font.pointSize: dbgStyle.general.basicFontSize
}
}
@ -523,7 +527,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
color: "#4a4a4a"
text: styleData.value
font.pointSize: DebuggerPaneStyle.general.basicFontSize
font.pointSize: dbgStyle.general.basicFontSize
}
}
}

1
mix/qml/DebuggerPaneStyle.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

1
mix/qml/DefaultLabel.qml

@ -1,6 +1,5 @@
import QtQuick 2.0
import QtQuick.Controls 1.1
import "."
Label {
text: text

4
mix/qml/DeploymentDialog.qml

@ -31,7 +31,7 @@ Window {
property string currentAccount
property alias gasToUse: gasToUseInput.text
color: Style.generic.layout.backgroundColor
color: appStyle.generic.layout.backgroundColor
function close()
{
@ -329,7 +329,7 @@ Window {
anchors.verticalCenter: parent.verticalCenter;
anchors.left: applicationUrlEth.right
font.italic: true
font.pointSize: Style.absoluteSize(-1)
font.pointSize: appStyle.absoluteSize(-1)
}
}
}

30
mix/qml/FilesSection.qml

@ -18,21 +18,21 @@ Rectangle
property string sectionName;
property variant selManager;
property int index;
color: index % 2 === 0 ? "transparent" : ProjectFilesStyle.title.background
color: index % 2 === 0 ? "transparent" : projectFilesStyle.title.background
function hiddenHeightTopLevel()
{
return section.state === "hidden" ? ProjectFilesStyle.documentsList.height : ProjectFilesStyle.documentsList.fileNameHeight * model.count + ProjectFilesStyle.documentsList.height;
return section.state === "hidden" ? projectFilesStyle.documentsList.height : projectFilesStyle.documentsList.fileNameHeight * model.count + projectFilesStyle.documentsList.height;
}
function hiddenHeightRepeater()
{
return section.state === "hidden" ? 0 : ProjectFilesStyle.documentsList.fileNameHeight * wrapperItem.model.count;
return section.state === "hidden" ? 0 : projectFilesStyle.documentsList.fileNameHeight * wrapperItem.model.count;
}
function hiddenHeightElement()
{
return section.state === "hidden" ? 0 : ProjectFilesStyle.documentsList.fileNameHeight;
return section.state === "hidden" ? 0 : projectFilesStyle.documentsList.fileNameHeight;
}
function getDocumentIndex(documentId)
@ -68,7 +68,7 @@ Rectangle
{
anchors.top: parent.top
id: rowCol
height: ProjectFilesStyle.documentsList.height
height: projectFilesStyle.documentsList.height
Layout.fillWidth: true
@ -88,15 +88,15 @@ Rectangle
id: section
text: sectionName
anchors.left: parent.left
anchors.leftMargin: ProjectFilesStyle.general.leftMargin
color: ProjectFilesStyle.documentsList.sectionColor
anchors.leftMargin: projectFilesStyle.general.leftMargin
color: projectFilesStyle.documentsList.sectionColor
font.family: boldFont.name
font.pointSize: ProjectFilesStyle.documentsList.sectionFontSize
font.pointSize: projectFilesStyle.documentsList.sectionFontSize
states: [
State {
name: "hidden"
PropertyChanges { target: filesList; visible: false; }
PropertyChanges { target: rowCol; Layout.minimumHeight: ProjectFilesStyle.documentsList.height; Layout.maximumHeight: ProjectFilesStyle.documentsList.height; height: ProjectFilesStyle.documentsList.height; }
PropertyChanges { target: rowCol; Layout.minimumHeight: projectFilesStyle.documentsList.height; Layout.maximumHeight: projectFilesStyle.documentsList.height; height: projectFilesStyle.documentsList.height; }
PropertyChanges { target: imgArrow; source: "qrc:/qml/img/closedtriangleindicator_filesproject.png" }
}
]
@ -138,7 +138,7 @@ Rectangle
Layout.preferredHeight: wrapperItem.hiddenHeightElement()
Layout.maximumHeight: wrapperItem.hiddenHeightElement()
height: wrapperItem.hiddenHeightElement()
color: isSelected ? ProjectFilesStyle.documentsList.highlightColor : "transparent"
color: isSelected ? projectFilesStyle.documentsList.highlightColor : "transparent"
property bool isSelected
property bool renameMode
@ -147,15 +147,15 @@ Rectangle
anchors.verticalCenter: parent.verticalCenter
anchors.fill: parent
anchors.left: parent.left
anchors.leftMargin: ProjectFilesStyle.general.leftMargin + 2
anchors.leftMargin: projectFilesStyle.general.leftMargin + 2
Text {
id: nameText
height: parent.height
visible: !renameMode
color: rootItem.isSelected ? ProjectFilesStyle.documentsList.selectedColor : ProjectFilesStyle.documentsList.color
color: rootItem.isSelected ? projectFilesStyle.documentsList.selectedColor : projectFilesStyle.documentsList.color
text: name;
font.family: fileNameFont.name
font.pointSize: ProjectFilesStyle.documentsList.fontSize
font.pointSize: projectFilesStyle.documentsList.fontSize
verticalAlignment: Text.AlignVCenter
Connections
@ -182,7 +182,7 @@ Rectangle
DefaultLabel {
id: editStatusLabel
visible: false
color: rootItem.isSelected ? ProjectFilesStyle.documentsList.selectedColor : ProjectFilesStyle.documentsList.color
color: rootItem.isSelected ? projectFilesStyle.documentsList.selectedColor : projectFilesStyle.documentsList.color
verticalAlignment: Text.AlignVCenter
text: "*"
width: 10
@ -196,7 +196,7 @@ Rectangle
visible: renameMode
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: ProjectFilesStyle.general.leftMargin
anchors.leftMargin: projectFilesStyle.general.leftMargin
MouseArea {
id: textMouseArea
anchors.fill: parent

72
mix/qml/LogsPane.qml

@ -3,7 +3,6 @@ import QtQuick.Layouts 1.0
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.3
import org.ethereum.qml.SortFilterProxyModel 1.0
import "."
Rectangle
{
@ -13,11 +12,16 @@ Rectangle
logsModel.insert(0, { "type": _type, "date": Qt.formatDateTime(new Date(), "hh:mm:ss dd.MM.yyyy"), "content": _content, "level": _level });
}
LogsPaneStyle {
id: logStyle
}
id: root
anchors.fill: parent
radius: 5
color: LogsPaneStyle.generic.layout.backgroundColor
border.color: LogsPaneStyle.generic.layout.borderColor
border.width: LogsPaneStyle.generic.layout.borderWidth
color: logStyle.generic.layout.backgroundColor
border.color: logStyle.generic.layout.borderColor
border.width: logStyle.generic.layout.borderWidth
ColumnLayout {
z: 2
height: parent.height
@ -26,14 +30,14 @@ Rectangle
Row
{
id: rowAction
Layout.preferredHeight: LogsPaneStyle.generic.layout.headerHeight
height: LogsPaneStyle.generic.layout.headerHeight
anchors.leftMargin: LogsPaneStyle.generic.layout.leftMargin
Layout.preferredHeight: logStyle.generic.layout.headerHeight
height: logStyle.generic.layout.headerHeight
anchors.leftMargin: logStyle.generic.layout.leftMargin
anchors.left: parent.left
spacing: LogsPaneStyle.generic.layout.headerButtonSpacing
spacing: logStyle.generic.layout.headerButtonSpacing
Button
{
height: LogsPaneStyle.generic.layout.headerButtonHeight
height: logStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
action: clearAction
iconSource: "qrc:/qml/img/broom.png"
@ -50,7 +54,7 @@ Rectangle
Button
{
height: LogsPaneStyle.generic.layout.headerButtonHeight
height: logStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
action: copytoClipBoardAction
iconSource: "qrc:/qml/img/copy.png"
@ -81,7 +85,7 @@ Rectangle
ToolButton {
id: javascriptButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
height: logStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
checked: true
onCheckedChanged: {
@ -93,9 +97,9 @@ Rectangle
label:
Item {
DefaultLabel {
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
color: LogsPaneStyle.generic.layout.logLabelColor
font.family: logStyle.generic.layout.logLabelFont
font.pointSize: appStyle.absoluteSize(-3)
color: logStyle.generic.layout.logLabelColor
anchors.centerIn: parent
text: qsTr("JavaScript")
}
@ -106,7 +110,7 @@ Rectangle
ToolButton {
id: runButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
height: logStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
checked: true
onCheckedChanged: {
@ -118,9 +122,9 @@ Rectangle
label:
Item {
DefaultLabel {
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
color: LogsPaneStyle.generic.layout.logLabelColor
font.family: logStyle.generic.layout.logLabelFont
font.pointSize: appStyle.absoluteSize(-3)
color: logStyle.generic.layout.logLabelColor
anchors.centerIn: parent
text: qsTr("Run")
}
@ -131,7 +135,7 @@ Rectangle
ToolButton {
id: stateButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
height: logStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
checked: true
onCheckedChanged: {
@ -143,8 +147,8 @@ Rectangle
label:
Item {
DefaultLabel {
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
font.family: logStyle.generic.layout.logLabelFont
font.pointSize: appStyle.absoluteSize(-3)
color: "#5391d8"
anchors.centerIn: parent
text: qsTr("State")
@ -156,7 +160,7 @@ Rectangle
ToolButton {
id: compilationButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
height: logStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
checked: false
onCheckedChanged: {
@ -168,8 +172,8 @@ Rectangle
label:
Item {
DefaultLabel {
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
font.family: logStyle.generic.layout.logLabelFont
font.pointSize: appStyle.absoluteSize(-3)
color: "#5391d8"
anchors.centerIn: parent
text: qsTr("Compilation")
@ -181,11 +185,11 @@ Rectangle
DefaultTextField
{
id: searchBox
height: LogsPaneStyle.generic.layout.headerButtonHeight
height: logStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
width: LogsPaneStyle.generic.layout.headerInputWidth
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
width: logStyle.generic.layout.headerInputWidth
font.family: logStyle.generic.layout.logLabelFont
font.pointSize: appStyle.absoluteSize(-3)
font.italic: true
onTextChanged: {
proxyModel.search(text);
@ -255,21 +259,21 @@ Rectangle
{
role: "date"
title: qsTr("date")
width: LogsPaneStyle.generic.layout.dateWidth
width: logStyle.generic.layout.dateWidth
delegate: itemDelegate
}
TableViewColumn
{
role: "type"
title: qsTr("type")
width: LogsPaneStyle.generic.layout.typeWidth
width: logStyle.generic.layout.typeWidth
delegate: itemDelegate
}
TableViewColumn
{
role: "content"
title: qsTr("content")
width: LogsPaneStyle.generic.layout.contentWidth
width: logStyle.generic.layout.contentWidth
delegate: itemDelegate
}
@ -277,7 +281,7 @@ Rectangle
Rectangle {
width: logsTable.width - 4
height: 17
color: styleData.alternate ? "transparent" : LogsPaneStyle.generic.layout.logAlternateColor
color: styleData.alternate ? "transparent" : logStyle.generic.layout.logAlternateColor
}
}
}
@ -286,8 +290,8 @@ Rectangle
id: itemDelegate
DefaultLabel {
text: styleData.value;
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-1)
font.family: logStyle.generic.layout.logLabelFont
font.pointSize: appStyle.absoluteSize(-1)
color: {
if (proxyModel.get(styleData.row).level === "error")
return "red";

1
mix/qml/LogsPaneStyle.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

1
mix/qml/NewProjectDialog.qml

@ -15,6 +15,7 @@ Window {
property alias projectTitle: titleField.text
readonly property string projectPath: "file://" + pathField.text
property alias pathFieldText: pathField.text
signal accepted
function open() {

1
mix/qml/ProjectFilesStyle.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

21
mix/qml/ProjectList.qml

@ -8,6 +8,11 @@ import "."
Item {
property bool renameMode: false;
ProjectFilesStyle {
id: projectFilesStyle
}
ColumnLayout {
anchors.fill: parent
id: filesCol
@ -20,8 +25,8 @@ Item {
Rectangle
{
color: ProjectFilesStyle.title.background
height: ProjectFilesStyle.title.height
color: projectFilesStyle.title.background
height: projectFilesStyle.title.height
Layout.fillWidth: true
Image {
id: projectIcon
@ -37,14 +42,14 @@ Item {
Text
{
id: projectTitle
color: ProjectFilesStyle.title.color
color: projectFilesStyle.title.color
text: projectModel.projectTitle
anchors.verticalCenter: parent.verticalCenter
visible: !projectModel.isEmpty;
anchors.left: parent.left
anchors.leftMargin: ProjectFilesStyle.general.leftMargin
anchors.leftMargin: projectFilesStyle.general.leftMargin
font.family: srcSansProLight.name
font.pointSize: ProjectFilesStyle.title.fontSize
font.pointSize: projectFilesStyle.title.fontSize
font.weight: Font.Light
}
@ -54,7 +59,7 @@ Item {
anchors.right: parent.right
anchors.rightMargin: 15
font.family: srcSansProLight.name
font.pointSize: ProjectFilesStyle.title.fontSize
font.pointSize: projectFilesStyle.title.fontSize
anchors.verticalCenter: parent.verticalCenter
font.weight: Font.Light
}
@ -64,14 +69,14 @@ Item {
{
Layout.fillWidth: true
height: 3
color: ProjectFilesStyle.documentsList.background
color: projectFilesStyle.documentsList.background
}
Rectangle
{
Layout.fillWidth: true
Layout.fillHeight: true
color: ProjectFilesStyle.documentsList.background
color: projectFilesStyle.documentsList.background
ColumnLayout
{

1
mix/qml/ProjectModel.qml

@ -44,6 +44,7 @@ Item {
property var stateListModel: projectStateListModel.model
property CodeEditorView codeEditor: null
property var unsavedFiles: []
property alias newProjectDialog: newProjectDialog
//interface
function saveAll() { ProjectModelCode.saveAll(); }

3
mix/qml/Splitter.qml

@ -9,6 +9,3 @@ SplitView
color: "#cccccc"
}
}

6
mix/qml/StateDialog.qml

@ -17,7 +17,7 @@ Window {
height: 480
title: qsTr("Edit State")
visible: false
color: StateDialogStyle.generic.backgroundColor
color: stateDialogStyle.generic.backgroundColor
property alias stateTitle: titleField.text
property alias isDefault: defaultCheckBox.checked
@ -71,6 +71,10 @@ Window {
return item;
}
StateDialogStyle {
id: stateDialogStyle
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 10

1
mix/qml/StateDialogStyle.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

6
mix/qml/StatusPane.qml

@ -50,6 +50,10 @@ Rectangle {
logPane.push("error", type, text);
}
StatusPaneStyle {
id: statusPaneStyle
}
Connections {
target: webPreview
onJavaScriptMessage:
@ -137,7 +141,7 @@ Rectangle {
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
font.pointSize: StatusPaneStyle.general.statusFontSize
font.pointSize: statusPaneStyle.general.statusFontSize
height: 15
font.family: "sans serif"
objectName: "status"

1
mix/qml/StatusPaneStyle.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

1
mix/qml/Style.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

6
mix/qml/TransactionDialog.qml

@ -13,7 +13,7 @@ Window {
width: 520
height: 500;
visible: false
color: StateDialogStyle.generic.backgroundColor
color: transactionDialogStyle.generic.backgroundColor
title: qsTr("Edit Transaction")
property int transactionIndex
property alias gas: gasValueEdit.gasValue;
@ -164,6 +164,10 @@ Window {
return item;
}
StateDialogStyle {
id: transactionDialogStyle
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 10

16
mix/qml/WebCodeEditor.qml

@ -7,12 +7,14 @@ import QtWebEngine.experimental 1.0
import "js/ErrorLocationFormater.js" as ErrorLocationFormater
Item {
signal editorTextChanged
signal breakpointsChanged
signal editorTextChanged
signal loadComplete
property bool isClean: true
property string currentText: ""
property string currentMode: ""
property bool initialized: false
property bool unloaded: false
property var currentBreakpoints: [];
function setText(text, mode) {
@ -78,7 +80,7 @@ Item {
onLoadingChanged:
{
if (!loading) {
if (!loading && !unloaded && editorBrowser) {
initialized = true;
setText(currentText, currentMode);
runJavaScript("getTextChanged()", function(result) { });
@ -87,19 +89,19 @@ Item {
if (currentMode === "solidity")
{
codeModel.onCompilationComplete.connect(function(){
runJavaScript("compilationComplete()", function(result) { });
editorBrowser.runJavaScript("compilationComplete()", function(result) { });
});
codeModel.onCompilationError.connect(function(error){
var errorInfo = ErrorLocationFormater.extractErrorInfo(error, false);
if (errorInfo.line && errorInfo.column)
runJavaScript("compilationError('" + errorInfo.line + "', '" + errorInfo.column + "', '" + errorInfo.errorDetail + "')", function(result) { });
editorBrowser.runJavaScript("compilationError('" + errorInfo.line + "', '" + errorInfo.column + "', '" + errorInfo.errorDetail + "')", function(result) { });
else
runJavaScript("compilationComplete()", function(result) { });
editorBrowser.runJavaScript("compilationComplete()", function(result) { });
});
}
parent.changeGeneration();
loadComplete();
}
}
@ -110,6 +112,8 @@ Item {
running: false
repeat: true
onTriggered: {
if (unloaded)
return;
editorBrowser.runJavaScript("getTextChanged()", function(result) {
if (result === true) {
editorBrowser.runJavaScript("getText()" , function(textValue) {

20
mix/qml/WebPreview.qml

@ -60,6 +60,10 @@ Item {
setPreviewUrl(urlInput.text);
}
WebPreviewStyle {
id: webPreviewStyle
}
Connections {
target: mainApplication
onLoaded: {
@ -182,7 +186,7 @@ Item {
Rectangle
{
anchors.leftMargin: 4
color: WebPreviewStyle.general.headerBackgroundColor
color: webPreviewStyle.general.headerBackgroundColor
Layout.preferredWidth: parent.width
Layout.preferredHeight: 32
Row {
@ -229,7 +233,7 @@ Item {
{
width: 1
height: parent.height - 10
color: WebPreviewStyle.general.separatorColor
color: webPreviewStyle.general.separatorColor
anchors.verticalCenter: parent.verticalCenter
}
@ -250,7 +254,7 @@ Item {
{
width: 1
height: parent.height - 10
color: WebPreviewStyle.general.separatorColor
color: webPreviewStyle.general.separatorColor
anchors.verticalCenter: parent.verticalCenter
}
@ -284,7 +288,7 @@ Item {
{
Layout.preferredHeight: 1
Layout.preferredWidth: parent.width
color: WebPreviewStyle.general.separatorColor
color: webPreviewStyle.general.separatorColor
}
Splitter
@ -354,9 +358,9 @@ Item {
id: expressionInput
width: parent.width - 15
height: 20
font.family: WebPreviewStyle.general.fontName
font.family: webPreviewStyle.general.fontName
font.italic: true
font.pointSize: Style.absoluteSize(-3)
font.pointSize: appStyle.absoluteSize(-3)
anchors.verticalCenter: parent.verticalCenter
property var history: []
@ -416,8 +420,8 @@ Item {
id: resultTextArea
width: expressionPanel.width
wrapMode: Text.Wrap
font.family: WebPreviewStyle.general.fontName
font.pointSize: Style.absoluteSize(-3)
font.family: webPreviewStyle.general.fontName
font.pointSize: appStyle.absoluteSize(-3)
backgroundVisible: true
style: TextAreaStyle {
backgroundColor: "#f0f0f0"

1
mix/qml/WebPreviewStyle.qml

@ -1,4 +1,3 @@
pragma Singleton
import QtQuick 2.0
QtObject {

8
mix/qml/qmldir

@ -1,8 +0,0 @@
singleton Style 1.0 Style.qml
singleton StateDialogStyle 1.0 StateDialogStyle.qml
singleton ProjectFilesStyle 1.0 ProjectFilesStyle.qml
singleton DebuggerPaneStyle 1.0 DebuggerPaneStyle.qml
singleton StateStyle 1.0 StateStyle.qml
singleton StatusPaneStyle 1.0 StatusPaneStyle.qml
singleton WebPreviewStyle 1.0 WebPreviewStyle.qml
singleton LogsPaneStyle 1.0 LogsPaneStyle.qml

50
mix/test/TestMain.cpp

@ -0,0 +1,50 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <iostream>
#include <stdlib.h>
#include <quicktest.h>
#include <QtQml>
#include "MixApplication.h"
#include "Exceptions.h"
#include "TestService.h"
using namespace dev::mix;
int main(int _argc, char* _argv[])
{
try
{
MixApplication::initialize();
qmlRegisterType<TestService>("org.ethereum.qml.TestService", 1, 0, "TestService");
return quick_test_main(_argc, _argv, "mix", _argv[1]);
}
catch (boost::exception const& _e)
{
std::cerr << boost::diagnostic_information(_e);
}
catch (std::exception const& _e)
{
std::cerr << _e.what();
}
}

51
mix/test/TestMain.qml

@ -1,51 +0,0 @@
import QtQuick 2.2
import QtTest 1.1
//import Qt.test.qtestroot 1.0
import "../qml"
TestCase
{
Item
{
id: helper
function findChild(item, childId) {
if (item.children) {
var searchString = "button"
for (var idx in item.children) {
var currentItem = item.children[idx]
if (currentItem.id.match("^"+childId) === childId)
return currentItem;
return findChild(currentItem, childId);
}
}
}
}
function test_t1()
{
waitForRendering(mainApplication.mainContent, 10000);
mainApplication.projectModel.createProject();
var projectDlg = helper.findChild(mainApplication, "newProjectDialog");
if (mainApplication.appService.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000))
console.log("compiled");
}
function runTest()
{
waitForRendering(mainApplication.mainContent, 10000);
console.log("runtest");
mousePress(mainApplication, 10, 10);
}
Application {
id: mainApplication
}
}

113
mix/test/TestService.cpp

@ -0,0 +1,113 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TestService.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
* Ethereum IDE client.
*/
#include "TestService.h"
#include <QtTest/QSignalSpy>
#include <QElapsedTimer>
#include <QtTest/QTest>
#include <QtTest/qtestkeyboard.h>
namespace dev
{
namespace mix
{
bool TestService::waitForSignal(QObject* _item, QString _signalName, int _timeout)
{
QSignalSpy spy(_item, ("2" + _signalName.toStdString()).c_str());
QMetaObject const* mo = _item->metaObject();
QStringList methods;
for(int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
if (mo->method(i).methodType() == QMetaMethod::Signal) {
methods << QString::fromLatin1(mo->method(i).methodSignature());
}
}
QElapsedTimer timer;
timer.start();
while (!spy.size()) {
int remaining = _timeout - int(timer.elapsed());
if (remaining <= 0)
break;
QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
QTest::qSleep(10);
}
return spy.size();
}
bool TestService::keyPress(int _key, int _modifiers, int _delay)
{
QWindow *window = eventWindow();
QTest::keyPress(window, Qt::Key(_key), Qt::KeyboardModifiers(_modifiers), _delay);
return true;
}
bool TestService::keyRelease(int _key, int _modifiers, int _delay)
{
QWindow *window = eventWindow();
QTest::keyRelease(window, Qt::Key(_key), Qt::KeyboardModifiers(_modifiers), _delay);
return true;
}
bool TestService::keyClick(int _key, int _modifiers, int _delay)
{
QWindow *window = eventWindow();
QTest::keyClick(window, Qt::Key(_key), Qt::KeyboardModifiers(_modifiers), _delay);
return true;
}
bool TestService::keyPressChar(QString const& _character, int _modifiers, int _delay)
{
QTEST_ASSERT(_character.length() == 1);
QWindow *window = eventWindow();
QTest::keyPress(window, _character[0].toLatin1(), Qt::KeyboardModifiers(_modifiers), _delay);
return true;
}
bool TestService::keyReleaseChar(QString const& _character, int _modifiers, int _delay)
{
QTEST_ASSERT(_character.length() == 1);
QWindow *window = eventWindow();
QTest::keyRelease(window, _character[0].toLatin1(), Qt::KeyboardModifiers(_modifiers), _delay);
return true;
}
bool TestService::keyClickChar(QString const& _character, int _modifiers, int _delay)
{
QTEST_ASSERT(_character.length() == 1);
QWindow *window = eventWindow();
QTest::keyClick(window, _character[0].toLatin1(), Qt::KeyboardModifiers(_modifiers), _delay);
return true;
}
QWindow* TestService::eventWindow()
{
return 0;
}
}
}

52
mix/test/TestService.h

@ -0,0 +1,52 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TestService.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
* Ethereum IDE client.
*/
#pragma once
#include <QObject>
class QWindow;
namespace dev
{
namespace mix
{
class TestService: public QObject
{
Q_OBJECT
public slots:
bool waitForSignal(QObject* _item, QString _signalName, int _timeout);
bool keyPress(int _key, int _modifiers, int _delay);
bool keyRelease(int _key, int _modifiers, int _delay);
bool keyClick(int _key, int _modifiers, int _delay);
bool keyPressChar(QString const& _character, int _modifiers, int _delay);
bool keyReleaseChar(QString const& _character, int _modifiers, int _delay);
bool keyClickChar(QString const& _character, int _modifiers, int _delay);
private:
QWindow* eventWindow();
};
}
}

52
mix/test/qml/TestMain.qml

@ -0,0 +1,52 @@
import QtQuick 2.2
import QtTest 1.1
import org.ethereum.qml.TestService 1.0
import "../../qml"
TestCase
{
id: tc
TestService
{
id: ts
function typeString(str)
{
for (var c in str)
ts.keyClickChar(c, Qt.NoModifier, 20);
}
}
function test_t1()
{
waitForRendering(mainApplication.mainContent, 10000);
mainApplication.projectModel.createProject();
var projectDlg = mainApplication.projectModel.newProjectDialog;
projectDlg.projectTitle = "TestProject";
projectDlg.pathFieldText = "/tmp/MixTest"; //TODO: get platform temp path
projectDlg.acceptAndClose();
ts.waitForSignal(mainApplication.mainContent.codeEditor, "loadComplete()", 5000)
ts.keyClickChar("A", Qt.ControlModifier, 20);
ts.typeString("CCC");
if (ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000))
console.log("compiled");
ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000);
}
function runTest()
{
waitForRendering(mainApplication.mainContent, 10000);
console.log("runtest");
mousePress(mainApplication, 10, 10);
}
Application
{
id: mainApplication
}
}

0
mix/test/TestTransactionDebug.qml → mix/test/qml/TestTransactionDebug.qml

2
mix/web.qrc

@ -8,7 +8,7 @@
<file>qml/html/cm/codemirror.js</file>
<file>qml/html/cm/javascript.js</file>
<file>qml/html/cm/matchbrackets.js</file>
<file alias="qml/CodeEditor.qml">qml/WebCodeEditor.qml</file>
<file>qml/WebCodeEditor.qml</file>
<file>qml/html/codeeditor.js</file>
<file>qml/html/cm/fullscreen.css</file>
<file>qml/html/cm/fullscreen.js</file>

Loading…
Cancel
Save