added autobot run script testcase

This commit is contained in:
Igor Korsukov 2021-10-06 15:02:17 +02:00
parent e274a2f35e
commit 98b4bb41c7
11 changed files with 213 additions and 19 deletions

View file

@ -92,6 +92,8 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/internal/api/autobotapi.h
${CMAKE_CURRENT_LIST_DIR}/internal/api/dispatcherapi.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/api/dispatcherapi.h
${CMAKE_CURRENT_LIST_DIR}/internal/api/navigationapi.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/api/navigationapi.h
${CMAKE_CURRENT_LIST_DIR}/view/autobotmodel.cpp
${CMAKE_CURRENT_LIST_DIR}/view/autobotmodel.h
${CMAKE_CURRENT_LIST_DIR}/view/abfilesmodel.cpp

View file

@ -42,6 +42,7 @@
#include "internal/api/logapi.h"
#include "internal/api/autobotapi.h"
#include "internal/api/dispatcherapi.h"
#include "internal/api/navigationapi.h"
using namespace mu::autobot;
using namespace mu::api;
@ -79,10 +80,11 @@ void AutobotModule::resolveImports()
}
auto api = modularity::ioc()->resolve<IApiRegister>(moduleName());
if (ar) {
if (api) {
api->regApiCreator("global", "api.log", new ApiCreator<LogApi>());
api->regApiCreator("autobot", "api.autobot", new ApiCreator<AutobotApi>());
api->regApiCreator("autobot", "api.dispatcher", new ApiCreator<DispatcherApi>());
api->regApiCreator("autobot", "api.navigation", new ApiCreator<NavigationApi>());
}
}

View file

@ -22,7 +22,6 @@
#include "autobotapi.h"
#include <QTimer>
#include <QEventLoop>
#include "log.h"
@ -55,13 +54,47 @@ void AutobotApi::setInterval(int msec)
m_intervalMsec = msec;
}
void AutobotApi::setTestCase(const QString& name)
void AutobotApi::runTestCase(QJSValue testCase)
{
LOGD() << "test case: " << name;
m_testCase.testCase = testCase;
m_testCase.steps = testCase.property("steps");
m_testCase.stepsCount = m_testCase.steps.property("length").toInt();
m_testCase.currentStepIdx = -1;
nextStep();
if (m_testCase.currentStepIdx < m_testCase.stepsCount) {
m_testCase.loop.exec();
}
}
void AutobotApi::step(const QString& name)
void AutobotApi::nextStep()
{
LOGD() << "step: " << name;
sleep(m_intervalMsec);
m_testCase.currentStepIdx += 1;
if (m_testCase.currentStepIdx >= m_testCase.stepsCount) {
return;
}
QTimer::singleShot(m_intervalMsec, [this]() {
QJSValue step = m_testCase.steps.property(m_testCase.currentStepIdx);
QJSValue func = step.property("func");
QJSValue wait = step.property("wait");
bool isWait = wait.isUndefined() ? true : wait.toBool();
if (!isWait) {
nextStep();
}
func.call();
if (isWait) {
nextStep();
}
m_testCase.finishedCount += 1;
if (m_testCase.finishedCount == m_testCase.stepsCount) {
m_testCase.loop.quit();
}
});
}

View file

@ -22,6 +22,9 @@
#ifndef MU_API_AUTOBOTAPI_H
#define MU_API_AUTOBOTAPI_H
#include <QJSValue>
#include <QEventLoop>
#include "apiobject.h"
#include "modularity/ioc.h"
@ -39,15 +42,29 @@ class AutobotApi : public ApiObject
public:
explicit AutobotApi(IApiEngine* e);
Q_INVOKABLE void setInterval(int msec);
Q_INVOKABLE void runTestCase(QJSValue testCase);
Q_INVOKABLE bool openProject(const QString& name);
Q_INVOKABLE void sleep(int msec);
Q_INVOKABLE void setInterval(int msec);
Q_INVOKABLE void setTestCase(const QString& name);
Q_INVOKABLE void step(const QString& name);
private:
struct TestCase
{
QJSValue testCase;
QJSValue steps;
int stepsCount = 0;
int currentStepIdx = -1;
int finishedCount = 0;
QEventLoop loop;
};
void nextStep();
int m_intervalMsec = 1000;
TestCase m_testCase;
};
}

View file

@ -0,0 +1,81 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "navigationapi.h"
#include "log.h"
using namespace mu::api;
NavigationApi::NavigationApi(IApiEngine* e)
: ApiObject(e)
{
}
void NavigationApi::nextPanel()
{
dispatcher()->dispatch("nav-next-panel");
}
void NavigationApi::prevPanel()
{
dispatcher()->dispatch("nav-prev-panel");
}
void NavigationApi::right()
{
dispatcher()->dispatch("nav-right");
}
void NavigationApi::left()
{
dispatcher()->dispatch("nav-left");
}
void NavigationApi::up()
{
dispatcher()->dispatch("nav-up");
}
void NavigationApi::down()
{
dispatcher()->dispatch("nav-down");
}
bool NavigationApi::goToControlByName(const QString& section, const QString& panel, const QString& contol)
{
bool ok = navigation()->requestActivateByName(section.toStdString(), panel.toStdString(), contol.toStdString());
return ok;
}
void NavigationApi::triggerCurrentControl()
{
dispatcher()->dispatch("nav-trigger-control");
}
bool NavigationApi::triggerControlByName(const QString& section, const QString& panel, const QString& contol)
{
bool ok = goToControlByName(section, panel, contol);
if (ok) {
triggerCurrentControl();
}
return ok;
}

View file

@ -0,0 +1,55 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MU_API_NAVIGATIONAPI_H
#define MU_API_NAVIGATIONAPI_H
#include <QString>
#include "apiobject.h"
#include "modularity/ioc.h"
#include "actions/iactionsdispatcher.h"
#include "ui/inavigationcontroller.h"
namespace mu::api {
class NavigationApi : public ApiObject
{
Q_OBJECT
INJECT(api, actions::IActionsDispatcher, dispatcher)
INJECT(api, ui::INavigationController, navigation)
public:
explicit NavigationApi(IApiEngine* e);
Q_INVOKABLE void nextPanel();
Q_INVOKABLE void prevPanel();
Q_INVOKABLE void right();
Q_INVOKABLE void left();
Q_INVOKABLE void up();
Q_INVOKABLE void down();
Q_INVOKABLE bool goToControlByName(const QString& section, const QString& panel, const QString& contol);
Q_INVOKABLE void triggerCurrentControl();
Q_INVOKABLE bool triggerControlByName(const QString& section, const QString& panel, const QString& contol);
};
}
#endif // MU_API_NAVIGATIONAPI_H

View file

@ -36,6 +36,7 @@ class ScriptApi : public QObject
Q_PROPERTY(QJSValue log READ log CONSTANT)
Q_PROPERTY(QJSValue autobot READ autobot CONSTANT)
Q_PROPERTY(QJSValue dispatcher READ dispatcher CONSTANT)
Q_PROPERTY(QJSValue navigation READ navigation CONSTANT)
INJECT(api, IApiRegister, apiRegister)
@ -45,6 +46,7 @@ public:
QJSValue log() const { return api("api.log"); }
QJSValue autobot() const { return api("api.autobot"); }
QJSValue dispatcher() const { return api("api.dispatcher"); }
QJSValue navigation() const { return api("api.navigation"); }
private:

View file

@ -1038,7 +1038,7 @@ void NavigationController::doTriggerControl()
bool NavigationController::requestActivateByName(const std::string& sectName, const std::string& panelName, const std::string& controlName)
{
INavigationSection* section = findByName(m_sections, QString::fromStdString(sectName));
if (section) {
if (!section) {
LOGE() << "not found section with name: " << sectName;
return false;
}
@ -1050,16 +1050,16 @@ bool NavigationController::requestActivateByName(const std::string& sectName, co
}
INavigationControl* control = findByName(panel->controls(), QString::fromStdString(controlName));
if (!panel) {
if (!control) {
LOGE() << "not found control with name: " << controlName << ", panel: " << panelName << ", section: " << sectName;
return false;
}
onActiveRequested(section, panel, control);
onActiveRequested(section, panel, control, true);
return true;
}
void NavigationController::onActiveRequested(INavigationSection* sect, INavigationPanel* panel, INavigationControl* ctrl)
void NavigationController::onActiveRequested(INavigationSection* sect, INavigationPanel* panel, INavigationControl* ctrl, bool force)
{
TRACEFUNC;
@ -1071,13 +1071,13 @@ void NavigationController::onActiveRequested(INavigationSection* sect, INavigati
//! NOTE If there is no active section,
//! we may not be using keyboard navigation, so ignore the request.
if (!activeSec) {
if (!force && !activeSec) {
return;
}
bool isChanged = false;
if (activeSec != sect) {
if (activeSec && activeSec != sect) {
doDeactivateSection(activeSec);
}

View file

@ -88,7 +88,7 @@ private:
void onEscape();
void doTriggerControl();
void onActiveRequested(INavigationSection* sect, INavigationPanel* panel, INavigationControl* ctrl);
void onActiveRequested(INavigationSection* sect, INavigationPanel* panel, INavigationControl* ctrl, bool force = false);
void doActivateSection(INavigationSection* sect, bool isActivateLastPanel = false);
void doDeactivateSection(INavigationSection* sect);

View file

@ -122,7 +122,7 @@ Item {
onNavigationActived: {
prv.currentItemNavigationIndex = [navigation.row, navigation.column]
item.clicked()
item.clicked(null)
}
StyledTextLabel {

View file

@ -37,6 +37,8 @@ StyledDialogView {
contentWidth: 1024
resizable: true
objectName: "NewScoreDialog"
NewScoreModel {
id: newScoreModel
}