Merge pull request #9651 from igorkorsukov/autobot/tc_6

Added TC6: UsingInspector Note
This commit is contained in:
Elnur Ismailzada 2021-11-03 08:12:15 -07:00 committed by GitHub
commit a1979d79c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 437 additions and 17 deletions

View file

@ -26,6 +26,7 @@ install(FILES
TC3_UsingNoteInputToolbar.js
TC4_UsingPalettes.js
TC5_UsingInstruments.js
TC6_UsingInspector_Note.js
DESTINATION ${Mscore_SHARE_NAME}${Mscore_INSTALL_NAME}autobotscripts
)
@ -36,6 +37,7 @@ install(FILES
steps/Palette.js
steps/Score.js
steps/Instruments.js
steps/Inspector.js
DESTINATION ${Mscore_SHARE_NAME}${Mscore_INSTALL_NAME}autobotscripts/steps
)

View file

@ -41,7 +41,7 @@ var testCase = {
{name: "Turn on note input", func: function() {
NoteInput.chooseDefaultMode()
}},
{name: "Put 1", func: function() {
{name: "Put", func: function() {
NoteInput.chooseNoteDuration("pad-note-64")
NoteInput.putNotes("note-c", 16)
api.autobot.seeChanges()

View file

@ -0,0 +1,315 @@
/*
* 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/>.
*/
var NewScore = require("steps/NewScore.js")
var NoteInput = require("steps/NoteInput.js")
var Inspector = require("steps/Inspector.js")
var Score = require("steps/Score.js")
var testCase = {
name: "TC6: Using inspector: Note",
description: "Let's check the functionality of the inspector: Note",
steps: [
{name: "Close score (if opened) and go to home to start", func: function() {
api.dispatcher.dispatch("file-close")
api.navigation.triggerControl("TopTool", "MainToolBar", "Home")
}},
{name: "Open New Score Dialog", func: function() {
NewScore.openNewScoreDialog()
}},
{name: "Create score", func: function() {
NewScore.сhooseInstrument("Woodwinds", "Flute")
NewScore.done()
}},
{name: "Open Inspector panel", func: function() {
Inspector.openInspectorPanel()
}},
{name: "Use General Panel", skip: false, func: function() {
// Normal visible note
api.shortcuts.activate("C") // put note
seeChanges()
// Unvisible note
api.shortcuts.activate("C") // put note
Score.prevChord() // select note (move back cursor)
Inspector.goToSection("General")
api.navigation.down() // go to visible
api.navigation.trigger() // make unvisible
seeChanges()
// Cue size note
Score.nextChord()
api.shortcuts.activate("C") // put note
Score.prevChord() // select note (move back cursor)
Inspector.goToSection("General")
api.navigation.down() // go to visible
api.navigation.right() // go to cue size
api.navigation.trigger() // make cue size
seeChanges()
// Unvisible rest
Score.nextChord()
Inspector.goToSection("General")
api.navigation.down() // go to visible
api.navigation.trigger() // make unvisible
seeChanges()
}},
{name: "Use Note Panel: Head", skip: false, func: function() {
// Hide notehead
Score.nextChord()
api.shortcuts.activate("C") // put note
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "HeadTab")
navigationDown(3) // got to Hide notehead
api.navigation.trigger()
seeChanges()
// Change notehead
for (var nh = 0; nh < 3; ++nh) {
Score.nextChord()
api.shortcuts.activate("C") // put note
Score.prevChord() // select note (move back cursor)
Inspector.goToSection("Note")
navigationDown(6 + nh) // got to notehead cell 2 + index
api.navigation.trigger()
seeChanges()
}
// Undo change notehead
Score.prevChord()
seeChanges()
Score.prevChord()
seeChanges()
Inspector.goToSection("Note")
navigationDown(5)
seeChangesLong()
api.navigation.trigger()
seeChanges()
// Dotted note position
Score.nextMeasure()
NoteInput.chooseNoteDuration("pad-note-8")
NoteInput.toggleDot("pad-dot")
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "DottedNoteAuto")
seeChanges()
// Later we will reset this
Score.nextChord()
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "DottedNoteUp")
seeChanges()
Score.nextChord()
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "DottedNoteDown")
seeChanges()
Score.nextChord()
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "DottedNoteUp")
seeChanges()
// Reset
Score.prevChord()
Score.prevChord()
api.navigation.goToControl("NavigationLeftPanel", "Note", "DottedNoteReset")
seeChangesLong()
api.navigation.trigger()
}},
{name: "Use Note Panel: Stem", skip: false, func: function() {
Score.nextMeasure()
NoteInput.chooseNoteDuration("pad-note-8")
api.shortcuts.activate("C")
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemTab") // show Stem tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "HideStem") // hide stem
seeChanges()
// Stem direction
// Up
Score.nextChord()
NoteInput.chooseNoteDuration("pad-note-4")
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemTab") // show Stem tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemDirectionUp")
seeChanges()
// Later we will reset this
Score.nextChord()
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemTab") // show Stem tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemDirectionUp")
seeChanges()
// Down
Score.nextChord()
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
Score.pitchDown(3)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemTab") // show Stem tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemDirectionDown")
seeChanges()
// Reset (change to Auto)
Score.prevChord()
Score.prevChord()
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemTab") // show Stem tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemDirectionAuto")
// Flag style
// Stem down
Score.nextMeasure()
NoteInput.chooseNoteDuration("pad-note-8")
api.shortcuts.activate("C")
NoteInput.chooseNoteDuration("pad-note-16")
Score.nextChord() // rest
Score.nextChord()
api.shortcuts.activate("C")
NoteInput.chooseNoteDuration("pad-note-32")
Score.nextChord() // rest
Score.nextChord()
api.shortcuts.activate("C")
seeChanges()
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "StemTab") // show Stem tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "FlagStyleStraight")
seeChangesVeryLong()
api.navigation.triggerControl("NavigationLeftPanel", "Note", "FlagStyleTraditional")
seeChangesVeryLong()
api.navigation.triggerControl("NavigationLeftPanel", "Note", "FlagStyleStraight")
seeChangesVeryLong()
}},
{name: "Use Note Panel: Beam", func: function() {
Score.nextMeasure()
NoteInput.chooseNoteDuration("pad-note-8")
// Begin
api.shortcuts.activate("C")
api.shortcuts.activate("C")
api.shortcuts.activate("C")
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "BeamTab") // show Beam tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "BeamTypeBegin")
seeChanges()
// Middle
Score.nextChord()
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "BeamTab") // show Beam tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "BeamTypeMiddle")
seeChanges()
// None
Score.nextChord()
api.shortcuts.activate("C")
seeChanges()
Score.prevChord() // select note (move back cursor)
api.navigation.triggerControl("NavigationLeftPanel", "Note", "BeamTab") // show Beam tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "BeamTypeNone")
seeChanges()
// Force Horizontal
// Not horizontal
Score.nextMeasure()
api.shortcuts.activate("C")
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
Score.pitchDown(3)
seeChanges()
// Horizontal
Score.nextChord() // rest
Score.nextChord()
api.shortcuts.activate("C")
api.shortcuts.activate("C")
Score.prevChord() // select note (move back cursor)
Score.pitchDown(3)
seeChanges()
api.navigation.triggerControl("NavigationLeftPanel", "Note", "BeamTab") // show Beam tab
api.navigation.triggerControl("NavigationLeftPanel", "Note", "ForceHorizontal")
}},
{name: "Save", func: function() {
api.autobot.saveProject("TC6_UsingInspector.mscz")
}},
{name: "Close", func: function() {
api.dispatcher.dispatch("file-close")
}},
{name: "Home", func: function() {
api.navigation.triggerControl("TopTool", "MainToolBar", "Home")
}},
{name: "Open last", func: function() {
api.navigation.goToControl("RecentScores", "RecentScores", "New score")
api.navigation.right()
api.navigation.trigger()
}},
{name: "Open Instruments panel", func: function() {
Instruments.openInstrumentsPanel()
}}
]
};
function main()
{
api.autobot.setInterval(1000)
api.autobot.runTestCase(testCase)
}
function seeChanges()
{
api.autobot.seeChanges()
}
function seeChangesLong()
{
api.autobot.sleep(1000)
}
function seeChangesVeryLong()
{
api.autobot.sleep(2000)
}
function navigationDown(count)
{
for (var i = 0; i < count; ++i) {
api.navigation.down()
}
}

View file

@ -0,0 +1,40 @@
/*
* 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/>.
*/
function doOpenInspectorPanel()
{
api.navigation.triggerControl("NavigationLeftPanel", "PanelTabs", "Properties")
}
function doGoToSection(name)
{
api.navigation.goToControl("NavigationLeftPanel", name, name)
}
module.exports = {
openInspectorPanel: doOpenInspectorPanel,
goToSection: function(name)
{
doGoToSection(name)
}
}

View file

@ -27,6 +27,24 @@ module.exports = {
api.shortcuts.activate("Right")
},
prevChord: function()
{
api.navigation.goToControl("NotationView", "ScoreView", "Score")
api.shortcuts.activate("Left")
},
nextMeasure: function()
{
api.navigation.goToControl("NotationView", "ScoreView", "Score")
api.shortcuts.activate("Ctrl+Right")
},
prevMeasure: function()
{
api.navigation.goToControl("NotationView", "ScoreView", "Score")
api.shortcuts.activate("Ctrl+Left")
},
appendMeasures: function(count)
{
api.navigation.goToControl("NotationView", "ScoreView", "Score")
@ -36,5 +54,23 @@ module.exports = {
api.autobot.sleep(1)
}
}
}
},
pitchDown: function(count)
{
count = count ?? 1;
api.navigation.goToControl("NotationView", "ScoreView", "Score")
for (var i = 0; i < count; ++i) {
api.shortcuts.activate("Down")
}
},
pitchUp: function(count)
{
count = count ?? 1;
api.navigation.goToControl("NotationView", "ScoreView", "Score")
for (var i = 0; i < count; ++i) {
api.shortcuts.activate("Up")
}
},
}

View file

@ -55,7 +55,7 @@ using Scripts = std::vector<Script>;
// --- TestCase ---
//! NOTE Scripts with test cases must have a global variable with the name specified in the constant
static const char* TESTCASE_JS_GLOBALNAME("testCase");
constexpr const char* TESTCASE_JS_GLOBALNAME = "testCase";
struct Step
{
@ -70,8 +70,11 @@ struct Step
if (jsret.isError()) {
QString fileName = jsret.property("fileName").toString();
int line = jsret.property("lineNumber").toInt();
return make_ret(Ret::Code::UnknownError,
QString("File: %1, Exception at line: %2, %3").arg(fileName).arg(line).arg(jsret.toString()));
QString err = jsret.toString();
if (err == "Error: abort") {
return make_ret(Ret::Code::Cancel, QString("script is aborted"));
}
return make_ret(Ret::Code::UnknownError, QString("File: %1, Exception at line: %2, %3").arg(fileName).arg(line).arg(err));
}
return Ret(Ret::Code::Ok);
@ -114,6 +117,7 @@ enum class StepStatus {
Paused,
Finished,
Skipped,
Aborted,
Error
};
}

View file

@ -122,6 +122,9 @@ void TestCaseReport::onStepStatusChanged(const QString& name, StepStatus status,
} break;
case StepStatus::Paused:
return;
case StepStatus::Aborted: {
m_stream << " abort step: " << name << Qt::endl;
} break;
case StepStatus::Error: {
m_stream << " error step: " << name << Qt::endl;
} break;

View file

@ -118,7 +118,8 @@ void TestCaseRunner::nextStep(bool byInterval)
Ret ret = step.exec();
if (!ret) {
LOGE() << "failed exec step: " << name << ", err: " << ret.toString();
m_stepStatusChanged.send(step.name(), StepStatus::Error);
StepStatus status = static_cast<Ret::Code>(ret.code()) == Ret::Code::Cancel ? StepStatus::Aborted : StepStatus::Error;
m_stepStatusChanged.send(step.name(), status);
doAbort();
return;
}

View file

@ -123,6 +123,7 @@ void TestCaseRunModel::updateStep(const QString& name, const StepStatus& stepSta
case StepStatus::Paused: return "Paused";
case StepStatus::Finished: return "Finished";
case StepStatus::Skipped: return "Skipped";
case StepStatus::Aborted: return "Aborted";
case StepStatus::Error: return "Error (see log)";
}
return "";

View file

@ -60,6 +60,10 @@ void UiContextResolver::init()
}
notifyAboutContextChanged();
});
navigationController()->navigationChanged().onNotify(this, [this]() {
notifyAboutContextChanged();
});
}
void UiContextResolver::notifyAboutContextChanged()
@ -88,8 +92,15 @@ UiContext UiContextResolver::currentUiContext() const
return context::UiCtxUnknown;
}
if (m_notationViewFocusedCounter > 0) {
return context::UiCtxNotationFocused;
INavigationSection* activeSection = navigationController()->activeSection();
if (activeSection) {
if (activeSection->name() == NOTATION_NAVIGATION_SECTION) {
return context::UiCtxNotationFocused;
}
} else {
if (m_notationViewFocusedCounter > 0) {
return context::UiCtxNotationFocused;
}
}
return context::UiCtxNotationOpened;

View file

@ -36,6 +36,7 @@ class UiContextResolver : public IUiContextResolver, public async::Asyncable
INJECT(context, framework::IInteractive, interactive)
INJECT(context, playback::IPlaybackController, playbackController)
INJECT(context, IGlobalContext, globalContext)
INJECT(context, ui::INavigationController, navigationController)
public:
UiContextResolver() = default;

View file

@ -43,13 +43,18 @@ FocusScope {
}
}
Component.onCompleted: navCtrl.enabled = true
Component.onDestruction: navCtrl.enabled = false
//! NOTE ListView can destroy delegates, but not delete objects,
// they remain in memory (this is done for optimization, for reusing delegate objects).
// In this case, navigation controls also remain in memory and in the navigation tree.
// But they should at least be turned off.
property bool completed: false
Component.onCompleted: root.completed = true
Component.onDestruction: root.completed = false
NavigationControl {
id: navCtrl
name: root.objectName
enabled: root.enabled && root.visible
enabled: root.enabled && root.visible && root.completed
onActiveChanged: {
if (navCtrl.active) {

View file

@ -44,7 +44,7 @@ InspectorPropertyView {
text: modelData["text"] ?? ""
iconCode: modelData["iconCode"] ?? IconCode.NONE
navigation.name: root.navigationName + " Value " + index
navigation.name: root.navigationName + (Boolean(text) ? text : modelData["title"])
navigation.panel: root.navigationPanel
navigation.row: root.navigationRowStart + 1 + index
navigation.accessible.name: root.titleText + " " + (Boolean(text) ? text : modelData["title"])

View file

@ -99,7 +99,7 @@ Column {
FlatButton {
anchors.fill: parent
navigation.name: root.navigationName + " Reset Button"
navigation.name: root.navigationName + "Reset"
navigation.panel: root.navigationPanel
navigation.row: root.navigationRowStart
navigation.accessible.name: qsTrc("inspector", "Reset \"%1\" to default value").arg(root.titleText)

View file

@ -67,6 +67,7 @@ FocusableItem {
titleText: qsTrc("inspector", "Dotted note position")
propertyItem: root.model ? root.model.dotPosition : null
navigationName: "DottedNote"
navigationPanel: root.navigationPanel
navigationRowStart: noteHeadSection.navigationRowEnd + 1

View file

@ -57,7 +57,7 @@ FocusableItem {
checked: root.stemModel && !isIndeterminate && root.beamModel ? root.stemModel.isStemHidden.value && root.beamModel.isBeamHidden.value : false
text: qsTrc("inspector", "Hide stem (also hides beam)")
navigation.name: "HideStemCheckBox"
navigation.name: "HideStem"
navigation.panel: root.navigationPanel
navigation.row: root.navigationRowStart + 1
@ -74,7 +74,7 @@ FocusableItem {
titleText: qsTrc("inspector", "Stem direction")
propertyItem: root.stemModel ? root.stemModel.stemDirection : null
navigationName: "StemDirectionGroup"
navigationName: "StemDirection"
navigationPanel: root.navigationPanel
navigationRowStart: root.navigationRowStart + 2
@ -114,7 +114,7 @@ FocusableItem {
delegate: FlatRadioButton {
height: 70
navigation.name: "FlagStyleGroup"
navigation.name: "FlagStyle" + modelData.text
navigation.panel: root.navigationPanel
navigation.row: flagStyleGroup.navigationRowStart + index
navigation.accessible.name: flagStyleLabel.text + " " + modelData.text

View file

@ -78,7 +78,7 @@ InspectorPropertyView {
hint: modelData["hint"] ?? ""
background.radius: gridView.cellRadius
navigation.name: hint
navigation.name: "BeamType" + hint
navigation.panel: root.navigationPanel
navigation.row: root.navigationRowStart + 1 + index
navigation.accessible.name: hint