2015-05-07 19:57:33 -07:00
/ *
2018-10-10 22:32:08 -07:00
Copyright ( c ) 2018 , Lars Brubaker , John Lewin
2015-05-07 19:57:33 -07:00
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
2016-09-20 09:39:57 -07:00
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
using System.Linq ;
using System.Reflection ;
2016-11-05 10:56:52 -07:00
using System.Threading ;
2016-10-25 06:17:37 -07:00
using System.Threading.Tasks ;
2016-09-20 09:39:57 -07:00
using MatterHackers.Agg ;
2015-05-07 19:57:33 -07:00
using MatterHackers.Agg.Image ;
2017-08-20 02:34:39 -07:00
using MatterHackers.Agg.Platform ;
2015-05-26 11:59:56 -07:00
using MatterHackers.Agg.UI ;
2015-08-18 13:01:29 -07:00
using MatterHackers.GuiAutomation ;
2017-10-27 14:19:26 -07:00
using MatterHackers.MatterControl.CustomWidgets ;
2015-08-25 11:56:21 -07:00
using MatterHackers.MatterControl.DataStorage ;
2018-03-27 09:24:02 -07:00
using MatterHackers.MatterControl.Library ;
2017-10-31 11:22:58 -07:00
using MatterHackers.MatterControl.PartPreviewWindow ;
2017-06-02 21:20:56 -07:00
using MatterHackers.MatterControl.PrinterCommunication ;
2018-03-27 09:24:02 -07:00
using MatterHackers.MatterControl.PrinterCommunication.Io ;
2017-12-07 14:54:41 -08:00
using MatterHackers.MatterControl.PrinterControls.PrinterConnections ;
2019-05-14 15:41:53 -07:00
using MatterHackers.MatterControl.PrintLibrary ;
2018-04-20 12:01:22 -07:00
using MatterHackers.MatterControl.SettingsManagement ;
2016-11-04 10:23:29 -07:00
using MatterHackers.MatterControl.SlicerConfiguration ;
2017-01-10 12:24:01 -08:00
using MatterHackers.PrinterEmulator ;
2015-10-22 18:23:22 -07:00
using Newtonsoft.Json ;
2015-08-22 16:14:31 -07:00
using NUnit.Framework ;
2018-10-19 15:53:16 -07:00
using SQLiteWin32 ;
2015-05-07 19:57:33 -07:00
2016-05-11 09:13:56 -07:00
namespace MatterHackers.MatterControl.Tests.Automation
2015-05-07 19:57:33 -07:00
{
2016-05-11 09:13:56 -07:00
[TestFixture, Category("MatterControl.UI.Automation")]
2015-09-01 10:26:14 -07:00
public static class MatterControlUtilities
2015-05-07 19:57:33 -07:00
{
private static bool saveImagesForDebug = true ;
2020-07-18 08:37:40 -07:00
private static event EventHandler UnregisterEvents ;
2016-11-05 10:56:52 -07:00
2015-12-22 11:34:04 -08:00
private static int testID = 0 ;
private static string runName = DateTime . Now . ToString ( "yyyy-MM-ddTHH-mm-ss" ) ;
2017-12-08 19:02:41 -08:00
public static string PathToDownloadsSubFolder = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) , "Downloads" , "-Temporary" ) ;
2017-12-16 19:09:25 -08:00
private static SystemWindow rootSystemWindow ;
2016-12-01 13:25:17 -08:00
public static void RemoveAllFromQueue ( this AutomationRunner testRunner )
2015-08-18 13:01:29 -07:00
{
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Queue... Menu" )
. Delay ( 1 )
. ClickByName ( " Remove All Menu Item" ) ;
2015-08-20 10:24:28 -07:00
}
2016-01-13 17:02:41 -08:00
public static void CreateDownloadsSubFolder ( )
2017-12-08 19:18:28 -08:00
{
if ( Directory . Exists ( PathToDownloadsSubFolder ) )
{
foreach ( string filePath in Directory . GetFiles ( PathToDownloadsSubFolder ) )
{
File . Delete ( filePath ) ;
}
}
else
2017-12-08 19:19:22 -08:00
{
Directory . CreateDirectory ( PathToDownloadsSubFolder ) ;
}
2017-12-08 19:18:28 -08:00
}
2018-03-27 09:24:02 -07:00
2016-09-30 16:03:57 -07:00
public static void DeleteDownloadsSubFolder ( )
2016-01-13 17:02:41 -08:00
{
2016-09-30 16:03:57 -07:00
Directory . Delete ( PathToDownloadsSubFolder , true ) ;
2016-01-13 17:02:41 -08:00
}
2019-01-03 14:34:06 -08:00
public static void SignOutUser ( this AutomationRunner testRunner )
2016-09-19 09:38:20 -07:00
{
2019-01-03 14:34:31 -08:00
testRunner . ClickSignOut ( ) ;
2016-09-23 14:16:39 -07:00
2016-11-05 10:56:52 -07:00
// Rather than waiting a fixed amount of time, we wait for the ReloadAll to complete before returning
testRunner . WaitForReloadAll ( ( ) = > testRunner . ClickByName ( "Yes Button" ) ) ;
}
2019-01-03 14:34:31 -08:00
public static void ClickSignOut ( this AutomationRunner testRunner )
{
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "User Options Menu" )
. ClickByName ( "Sign Out Menu Item" )
. Delay ( . 5 ) ;
2019-01-03 14:34:31 -08:00
}
2022-02-06 08:22:31 -08:00
public static AutomationRunner AddPrimitivePartsToBed ( this AutomationRunner testRunner , IEnumerable < string > partNames , bool multiSelect = false )
{
// Passing in true for multiselect will simulate holding down control when clicking on each part. This will create a
// selection group that is added to the plate as one scene part.
// Open the library pane to force display of the overflow menu and add a widget for it to the widget hierarchy.
// We need this menu widget to trigger the Add to Bed menu item.
const string containerName = "Primitives Row Item Collection" ;
testRunner . NavigateToFolder ( containerName ) ;
var partCount = 0 ;
foreach ( var partName in partNames )
{
Keyboard . SetKeyDownState ( Keys . ControlKey , multiSelect ) ;
foreach ( var result in testRunner . GetWidgetsByName ( partName ) )
{
// Opening the primitive parts library folder causes a second set of primitive part widgets to be created.
// The first set is hidden behind the expanded library pane and targeting them for a click will cause the
// automation runner to click in the wrong spots. Finding the correct widgets to target is a little complicated
// because of the layers of wrapping widgets but the widgets in the first set (which we don't want to target)
// are direct descendents of a ListContentView so we can eliminate those and assume whatever is left over are
// the widgets we want.
var partWidget = result . Widget as ListViewItemBase ;
if ( partWidget . Parent . Name = = "Library ListContentView" )
{
continue ;
}
if ( ! partWidget . IsSelected )
{
testRunner . ClickWidget ( partWidget ) ;
}
partCount + = 1 ;
}
}
if ( multiSelect )
{
// Release control key so additional operations work normally.
Keyboard . SetKeyDownState ( Keys . ControlKey , false ) ;
}
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
var view3D = testRunner . GetWidgetByName ( "View3DWidget" , out _ ) as View3DWidget ;
var scene = view3D . Object3DControlLayer . Scene ;
var preAddCount = scene . Children . Count ;
var postAddCount = preAddCount + ( multiSelect ? 1 : partCount ) ;
testRunner . ClickByName ( "Add to Bed Menu Item" )
// wait for the objects to be added
. WaitFor ( ( ) = > scene . Children . Count = = postAddCount ) ;
// wait for the objects to be done loading
var insertionGroup = scene . Children . LastOrDefault ( ) as InsertionGroupObject3D ;
if ( insertionGroup ! = null )
{
testRunner . WaitFor ( ( ) = > scene . Children . LastOrDefault ( ) as InsertionGroupObject3D ! = null , 10 ) ;
}
return testRunner ;
}
2020-08-09 08:23:22 -07:00
public static void ChangeSettings ( this AutomationRunner testRunner ,
IEnumerable < ( string key , string value ) > settings ,
PrinterConfig printer )
{
bool needReload = false ;
foreach ( var setting in settings )
{
if ( printer . Settings . GetValue ( setting . key ) ! = setting . value
2020-12-30 09:03:02 -08:00
& & PrinterSettings . SettingsData [ setting . key ] . UiUpdate ! = SliceSettingData . UiUpdateRequired . None )
2020-08-09 08:23:22 -07:00
{
needReload = true ;
break ;
}
}
if ( needReload )
{
testRunner . WaitForReloadAll ( ( ) = >
{
foreach ( var setting in settings )
{
printer . Settings . SetValue ( setting . key , setting . value ) ;
}
} ) ;
}
else
{
foreach ( var setting in settings )
{
printer . Settings . SetValue ( setting . key , setting . value ) ;
}
}
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner WaitForReloadAll ( this AutomationRunner testRunner , Action reloadAllAction )
2016-11-05 10:56:52 -07:00
{
// Wire up a block and release mechanism to wait until the sign in process has completed
AutoResetEvent resetEvent = new AutoResetEvent ( false ) ;
2020-07-18 08:37:40 -07:00
ApplicationController . Instance . DoneReloadingAll . RegisterEvent ( ( s , e ) = > resetEvent . Set ( ) , ref UnregisterEvents ) ;
2016-11-05 10:56:52 -07:00
// Start the procedure that begins a ReloadAll event in MatterControl
reloadAllAction ( ) ;
2016-12-06 18:52:25 -08:00
// Wait up to 10 seconds for the DoneReloadingAll event
resetEvent . WaitOne ( 10 * 1000 ) ;
2016-11-05 10:56:52 -07:00
// Remove our DoneReloadingAll listener
2020-07-18 08:37:40 -07:00
UnregisterEvents ( null , null ) ;
2016-11-05 10:56:52 -07:00
// Wait for any post DoneReloadingAll code to finish up and return
2017-02-01 10:12:31 -08:00
testRunner . Delay ( . 2 ) ;
2021-02-18 10:40:44 -08:00
return testRunner ;
2016-09-19 09:38:20 -07:00
}
2016-01-13 17:02:41 -08:00
2020-07-18 08:37:40 -07:00
public static AutomationRunner WaitForPage ( this AutomationRunner testRunner , string headerText )
2019-05-14 15:12:30 -07:00
{
// Helper methods
bool HeaderExists ( string text )
{
var header = testRunner . GetWidgetByName ( "HeaderRow" , out _ ) ;
var textWidget = header . Children < TextWidget > ( ) . FirstOrDefault ( ) ;
return textWidget ? . Text . StartsWith ( text ) ? ? false ;
}
testRunner . WaitFor ( ( ) = > HeaderExists ( headerText ) ) ;
Assert . IsTrue ( HeaderExists ( headerText ) , "Expected page not found: " + headerText ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
}
2019-05-14 15:12:30 -07:00
2015-12-31 12:57:00 -08:00
public static string PathToExportGcodeFolder
{
2018-11-02 07:33:44 -07:00
get = > TestContext . CurrentContext . ResolveProjectPath ( 4 , "Tests" , "TestData" , "ExportedGcode" , runName ) ;
2015-12-31 12:57:00 -08:00
}
2016-01-13 17:02:41 -08:00
public static string GetTestItemPath ( string queueItemToLoad )
2015-10-23 09:57:26 -07:00
{
2016-09-22 08:52:15 -07:00
return TestContext . CurrentContext . ResolveProjectPath ( 4 , "Tests" , "TestData" , "QueueItems" , queueItemToLoad ) ;
2015-10-23 09:57:26 -07:00
}
2017-12-14 21:59:41 -08:00
public static void CloseMatterControl ( this AutomationRunner testRunner )
2015-08-20 10:24:28 -07:00
{
2017-12-16 19:09:25 -08:00
rootSystemWindow ? . Close ( ) ;
2015-08-18 13:01:29 -07:00
}
2015-08-20 18:42:34 -07:00
2016-07-29 16:44:00 -07:00
public enum PrepAction
{
2018-10-10 22:46:49 -07:00
CloseSignInAndPrinterSelect
2020-07-18 08:37:40 -07:00
}
;
2016-07-29 16:44:00 -07:00
2021-06-11 11:23:15 -07:00
public static AutomationRunner ExpandEditTool ( this AutomationRunner testRunner , string expandCheckboxButtonName )
2018-01-26 17:53:54 -08:00
{
var mirrorPanel = testRunner . GetWidgetByName ( expandCheckboxButtonName , out _ ) ;
var checkBox = mirrorPanel . Children < ExpandCheckboxButton > ( ) . FirstOrDefault ( ) ;
if ( checkBox ? . Checked ! = true )
{
testRunner . ClickByName ( expandCheckboxButtonName ) ;
}
2021-06-11 11:23:15 -07:00
return testRunner ;
2018-01-26 17:53:54 -08:00
}
2021-06-11 11:23:15 -07:00
public static AutomationRunner Select3DPart ( this AutomationRunner testRunner , string partNameToSelect )
2017-03-15 16:17:06 -07:00
{
2017-12-06 17:23:21 -08:00
if ( testRunner . NameExists ( "3D View Edit" , . 2 ) )
2017-03-15 16:17:06 -07:00
{
testRunner . ClickByName ( "3D View Edit" ) ;
}
2020-07-18 08:37:40 -07:00
2021-06-11 11:23:15 -07:00
return testRunner . ClickByName ( partNameToSelect ) ;
2017-03-15 16:17:06 -07:00
}
2022-02-04 14:51:41 -08:00
public static AutomationRunner ClickDiscardChanges ( this AutomationRunner testRunner )
{
return testRunner . ClickByName ( "No Button" ) ;
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner WaitForFirstDraw ( this AutomationRunner testRunner )
2016-07-29 16:44:00 -07:00
{
2018-10-29 21:47:03 -07:00
testRunner . GetWidgetByName ( "PartPreviewContent" , out SystemWindow systemWindow , 10 ) ;
2017-12-20 15:43:21 -08:00
// make sure we wait for MC to be up and running
testRunner . WaitforDraw ( systemWindow ) ;
2021-02-18 10:40:44 -08:00
return testRunner ;
2018-02-08 15:42:07 -08:00
}
2022-02-03 17:21:51 -08:00
public static AutomationRunner OpenPartTab ( this AutomationRunner testRunner , bool removeDefaultPhil = true )
2018-04-19 07:58:03 -07:00
{
2018-12-07 14:05:03 -08:00
SystemWindow systemWindow ;
testRunner . GetWidgetByName ( "Hardware Tab" , out systemWindow , 10 ) ;
testRunner . WaitforDraw ( systemWindow ) ;
// close the welcome message
2022-02-03 08:41:57 -08:00
if ( testRunner . WaitForName ( "Start New Design" ) )
2018-11-29 14:26:27 -08:00
{
2022-01-07 16:30:46 -08:00
testRunner . ClickByName ( "Start New Design" ) ;
2018-11-29 14:26:27 -08:00
}
2021-06-11 11:23:15 -07:00
2022-02-03 17:21:51 -08:00
if ( removeDefaultPhil )
{
testRunner . VerifyAndRemovePhil ( ) ;
}
2022-01-20 17:52:42 -08:00
2021-06-11 11:23:15 -07:00
return testRunner ;
2016-07-29 16:44:00 -07:00
}
2017-05-21 16:29:00 -07:00
public static void ChangeToQueueContainer ( this AutomationRunner testRunner )
{
testRunner . NavigateToFolder ( "Print Queue Row Item Collection" ) ;
}
2017-12-06 17:23:21 -08:00
public class PrintEmulatorProcess : Process
2016-10-26 07:27:16 -07:00
{
protected override void Dispose ( bool disposing )
{
2016-12-07 13:21:53 -08:00
try
{
this . Kill ( ) ;
}
2018-10-10 22:46:49 -07:00
catch
{
}
2016-12-07 13:21:53 -08:00
2016-10-26 07:27:16 -07:00
base . Dispose ( disposing ) ;
}
}
2021-01-31 08:47:36 -08:00
public static Emulator LaunchAndConnectToPrinterEmulator ( this AutomationRunner testRunner ,
string make = "Airwolf 3D" ,
string model = "HD" ,
bool runSlow = false ,
bool pinSettingsOpen = true )
2016-09-14 15:50:24 -07:00
{
2019-01-03 17:52:24 -08:00
var hardwareTab = testRunner . GetWidgetByName ( "Hardware Tab" , out SystemWindow systemWindow , 10 ) ;
2018-02-08 15:42:07 -08:00
// make sure we wait for MC to be up and running
testRunner . WaitforDraw ( systemWindow ) ;
2016-09-20 09:39:57 -07:00
// Load the TestEnv config
var config = TestAutomationConfig . Load ( ) ;
2016-09-19 14:46:47 -07:00
2017-12-15 19:21:50 -08:00
// Override the heat up time
2017-12-15 18:19:36 -08:00
Emulator . DefaultHeatUpTime = config . HeatupTime ;
2017-12-15 19:21:50 -08:00
2018-07-12 22:49:39 -07:00
// Override the temp stabilization time
2017-12-15 19:21:50 -08:00
WaitForTempStream . WaitAfterReachTempTime = config . TempStabilizationTime ;
2016-09-20 09:39:57 -07:00
// Create the printer
2020-07-18 08:37:40 -07:00
testRunner . AddAndSelectPrinter ( make , model )
2021-02-21 07:46:51 -08:00
. SwitchToPrinterSettings ( pinSettingsOpen )
. GetWidgetByName ( "com_port Field" , out GuiWidget serialPortDropDown , out _ )
// Wait until the serialPortDropDown is ready to click it. Ensures the printer is loaded.
. WaitFor ( ( ) = > serialPortDropDown . Enabled )
. ClickByName ( "com_port Field" )
2020-07-18 08:37:40 -07:00
. ClickByName ( "Emulator Menu Item" )
. ClickByName ( "Connect to printer button" ) // connect to the created printer
. WaitForName ( "Disconnect from printer button" ) ;
2016-09-19 14:46:47 -07:00
2019-05-29 10:33:36 -07:00
// replace the old behavior of clicking the 'Already Loaded' button by setting to filament_has_been_loaded.
ApplicationController . Instance . ActivePrinters . First ( ) . Settings . SetValue ( SettingsKey . filament_has_been_loaded , "1" ) ;
2018-11-05 12:05:09 -08:00
2017-07-01 18:25:53 -07:00
// Access through static instance must occur after Connect has occurred and the port has spun up
Emulator . Instance . RunSlow = runSlow ;
return Emulator . Instance ;
2017-12-06 17:23:21 -08:00
}
2016-09-14 15:50:24 -07:00
2020-07-18 08:37:40 -07:00
public static AutomationRunner CancelPrint ( this AutomationRunner testRunner )
2017-02-01 10:20:50 -08:00
{
2019-04-30 10:47:54 -07:00
// If the pause/resume dialog is open, dismiss it before canceling the print
2020-07-18 08:37:40 -07:00
if ( testRunner . NamedWidgetExists ( "Yes Button" ) )
2017-02-01 10:20:50 -08:00
{
testRunner . ClickByName ( "Yes Button" ) ;
}
2019-04-30 10:47:54 -07:00
2020-07-18 08:37:40 -07:00
testRunner . WaitForWidgetEnabled ( "Print Progress Dial" , 15 )
. WaitForWidgetEnabled ( "Stop Task Button" )
. ClickByName ( "Stop Task Button" )
. WaitForName ( "Ok Button" , 10 ) ; // Wait for and dismiss the new PrintCompleted dialog
2020-05-16 08:34:06 -07:00
2020-10-25 20:47:12 -07:00
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
2017-02-01 10:20:50 -08:00
}
2017-12-14 21:59:41 -08:00
public static void WaitForLayer ( this Emulator emulator , PrinterSettings printerSettings , int layerNumber , double secondsToWait = 30 )
{
var resetEvent = new AutoResetEvent ( false ) ;
var heightAtTargetLayer = printerSettings . GetValue < double > ( SettingsKey . layer_height ) * layerNumber ;
// Wait for emulator to hit target layer
2019-05-02 09:11:17 -07:00
emulator . DestinationChanged + = ( s , e ) = >
2017-12-14 21:59:41 -08:00
{
// Wait for print to start, then slow down the emulator and continue. Failing to slow down frequently causes a timing issue where the print
// finishes before we make it down to 'CloseMatterControlViaUi' and thus no prompt to close appears and the test fails when clicking 'Yes Button'
2019-05-02 09:11:17 -07:00
if ( emulator . Destination . Z > = heightAtTargetLayer )
2017-12-14 21:59:41 -08:00
{
resetEvent . Set ( ) ;
}
} ;
resetEvent . WaitOne ( ( int ) ( secondsToWait * 1000 ) ) ;
}
2016-03-03 16:57:43 -08:00
public static bool CompareExpectedSliceSettingValueWithActualVaue ( string sliceSetting , string expectedValue )
{
2018-01-18 14:39:59 -08:00
foreach ( string iniPath in Directory . GetFiles ( ApplicationDataStorage . Instance . GCodeOutputPath , "*.ini" ) )
2016-03-03 16:57:43 -08:00
{
2016-11-04 10:23:29 -07:00
var settings = PrinterSettingsLayer . LoadFromIni ( iniPath ) ;
2018-01-18 14:39:59 -08:00
if ( settings . TryGetValue ( sliceSetting , out string currentValue ) )
2016-11-04 10:23:29 -07:00
{
return currentValue . Trim ( ) = = expectedValue ;
2016-03-03 16:57:43 -08:00
}
}
return false ;
}
2016-09-08 14:20:39 -07:00
public static void DeleteSelectedPrinter ( AutomationRunner testRunner )
{
2018-11-21 10:58:52 -08:00
// Click 'Delete Printer' menu item
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Printer Overflow Menu" )
. ClickByName ( "Delete Printer Menu Item" )
// Confirm Delete
. WaitForName ( "HeaderRow" ) ;
2018-11-21 10:58:52 -08:00
testRunner . ClickByName ( "Yes Button" ) ;
2016-09-08 14:20:39 -07:00
}
2020-07-18 08:37:40 -07:00
public static AutomationRunner AddAndSelectPrinter ( this AutomationRunner testRunner , string make = "Airwolf 3D" , string model = "HD" )
2016-01-13 10:26:17 -08:00
{
2018-10-29 21:47:03 -07:00
testRunner . GetWidgetByName ( "PartPreviewContent" , out SystemWindow systemWindow , 10 ) ;
2018-10-11 17:24:42 -07:00
2020-07-18 08:37:40 -07:00
testRunner . WaitforDraw ( systemWindow ) // make sure we wait for MC to be up and running
. EnsureWelcomePageClosed ( ) ; // close the welcome message
2018-04-20 12:01:22 -07:00
2020-07-03 16:32:44 -07:00
if ( testRunner . NamedWidgetExists ( "Cancel Wizard Button" ) )
{
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
}
2018-11-29 10:02:47 -08:00
2018-10-10 12:15:30 -07:00
// Click 'Add Printer' if not on screen
2019-05-14 15:41:53 -07:00
if ( ! testRunner . NameExists ( "AddPrinterWidget" , 0.2 ) )
2017-06-04 16:16:07 -07:00
{
2018-10-18 17:25:56 -07:00
if ( ! testRunner . NameExists ( "Create Printer" , 0.2 ) )
2018-10-18 14:44:58 -07:00
{
// go to the start page
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Hardware Tab" )
. ClickByName ( "Create Printer" ) ;
2018-10-18 14:44:58 -07:00
}
else
{
2018-10-18 17:25:56 -07:00
if ( testRunner . NameExists ( "Print Button" , . 2 ) )
{
testRunner . ClickByName ( "Print Button" ) ;
}
else
{
testRunner . ClickByName ( "Create Printer" ) ;
}
2018-10-18 14:44:58 -07:00
}
2017-06-04 16:16:07 -07:00
}
2019-05-14 15:41:53 -07:00
// Wait for the tree to load before filtering
testRunner . WaitFor ( ( ) = >
{
var widget = testRunner . GetWidgetByName ( "AddPrinterWidget" , out _ ) as AddPrinterWidget ;
return widget . TreeLoaded ;
} ) ;
2017-12-07 12:23:28 -08:00
2019-05-14 15:41:53 -07:00
// Apply filter
2020-07-18 08:37:40 -07:00
testRunner . ClickByName ( "Search" )
. Type ( model )
. Type ( "{Enter}" )
. Delay ( )
. ClickByName ( $"Node{make}{model}" ) // Click printer node
. ClickByName ( "Next Button" ) // Continue to next page
. Delay ( )
. WaitFor ( ( ) = > testRunner . ChildExists < SetupStepComPortOne > ( ) ) ;
testRunner . ClickByName ( "Cancel Wizard Button" )
. WaitFor ( ( ) = > ! testRunner . ChildExists < SetupStepComPortOne > ( ) ) ;
2019-04-30 18:51:04 -07:00
2022-01-20 17:52:42 -08:00
testRunner . VerifyAndRemovePhil ( ) ;
return testRunner ;
}
public static AutomationRunner VerifyAndRemovePhil ( this AutomationRunner testRunner )
{
var view3D = testRunner . GetWidgetByName ( "View3DWidget" , out _ , 3 ) as View3DWidget ;
var scene = view3D . Object3DControlLayer . Scene ;
testRunner . WaitFor ( ( ) = > scene . Children . Count = = 1 ) ;
Assert . AreEqual ( 1 , scene . Children . Count , "Should have a Phil on the bed" ) ;
testRunner . WaitFor ( ( ) = > scene . Children . First ( ) . Name = = "Phil A Ment.stl" ) ;
Assert . AreEqual ( "Phil A Ment.stl" , scene . Children . First ( ) . Name ) ;
testRunner . Type ( "^a" ) ; // clear the selection (type a space)
testRunner . WaitFor ( ( ) = > scene . SelectedItem ! = null ) ;
testRunner . Type ( "{BACKSPACE}" ) ;
testRunner . WaitFor ( ( ) = > scene . Children . Count = = 0 ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
2016-01-13 10:26:17 -08:00
}
2020-12-17 17:30:19 -08:00
public static AutomationRunner CloneAndSelectPrinter ( this AutomationRunner testRunner , string profileName )
{
testRunner . GetWidgetByName ( "PartPreviewContent" , out SystemWindow systemWindow , 10 ) ;
testRunner . WaitforDraw ( systemWindow ) // make sure we wait for MC to be up and running
. EnsureWelcomePageClosed ( ) ; // close the welcome message
if ( testRunner . NamedWidgetExists ( "Cancel Wizard Button" ) )
{
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
}
// go to the start page
testRunner . ClickByName ( "Hardware Tab" )
. ClickByName ( "Import Printer Button" ) ;
2020-12-18 18:07:37 -08:00
string profilePath = TestContext . CurrentContext . ResolveProjectPath ( 4 , "Tests" , "TestData" , "TestProfiles" , profileName + ".printer" ) ;
2020-12-17 17:30:19 -08:00
// Apply filter
2020-12-18 18:07:37 -08:00
testRunner . ClickByName ( "Profile Path Widget" ) // Continue to next page
2020-12-17 17:30:19 -08:00
. Type ( Path . GetFullPath ( profilePath ) ) // open the right file
2020-12-18 18:07:37 -08:00
. Type ( "{Tab}" )
2020-12-17 17:30:19 -08:00
. ClickByName ( "Import Button" ) // Continue to next page
2020-12-18 18:07:37 -08:00
. ClickByName ( "Cancel Wizard Button" )
. DoubleClickByName ( profileName + " Node" )
. WaitForName ( "PrintPopupMenu" ) ;
2020-12-17 17:30:19 -08:00
return testRunner ;
}
2020-07-18 08:37:40 -07:00
public static AutomationRunner EnsureWelcomePageClosed ( this AutomationRunner testRunner )
2018-12-19 17:29:36 -08:00
{
2022-02-07 11:08:13 -08:00
testRunner . WaitFor ( ( ) = > testRunner . NameExists ( "Cancel Wizard Button" ) ) ;
2018-12-19 17:29:36 -08:00
// Close the WelcomePage window if active
2022-02-07 11:08:13 -08:00
if ( testRunner . NameExists ( "Cancel Wizard Button" , 1 ) )
2018-12-19 17:29:36 -08:00
{
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
}
2020-07-18 08:37:40 -07:00
testRunner . WaitFor ( ( ) = > ! testRunner . NameExists ( "Cancel Wizard Button" , . 1 ) ) ;
return testRunner ;
2018-12-19 17:29:36 -08:00
}
2018-12-24 11:23:51 -08:00
public static void WaitForAndCancelPrinterSetupPage ( this AutomationRunner testRunner )
{
testRunner . WaitFor ( ( ) = >
{
return testRunner . GetWidgetByName ( "HeaderRow" , out _ ) is GuiWidget headerRow
& & headerRow . Parents < DialogPage > ( ) . FirstOrDefault ( ) is SetupStepMakeModelName ;
} ) ;
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner SwitchToHardwareTab ( this AutomationRunner testRunner )
2017-06-04 16:16:07 -07:00
{
2018-10-11 17:24:42 -07:00
testRunner . ClickByName ( "Hardware Tab" ) ;
2021-02-18 10:40:44 -08:00
return testRunner ;
2017-06-04 16:16:07 -07:00
}
2015-09-01 10:26:14 -07:00
private static void OutputImage ( ImageBuffer imageToOutput , string fileName )
2015-05-07 19:57:33 -07:00
{
if ( saveImagesForDebug )
{
ImageTgaIO . Save ( imageToOutput , fileName ) ;
}
}
2015-09-01 10:26:14 -07:00
private static void OutputImage ( GuiWidget widgetToOutput , string fileName )
2015-05-07 19:57:33 -07:00
{
if ( saveImagesForDebug )
{
OutputImage ( widgetToOutput . BackBuffer , fileName ) ;
}
}
2015-09-01 10:26:14 -07:00
private static void OutputImages ( GuiWidget control , GuiWidget test )
2015-05-07 19:57:33 -07:00
{
OutputImage ( control , "image-control.tga" ) ;
OutputImage ( test , "image-test.tga" ) ;
}
2015-08-25 11:56:21 -07:00
2015-12-22 11:34:04 -08:00
/// <summary>
/// Overrides the AppData location, ensuring each test starts with a fresh MatterControl database.
/// </summary>
2016-09-20 09:39:57 -07:00
public static void OverrideAppDataLocation ( string matterControlDirectory )
2015-08-25 11:56:21 -07:00
{
2016-09-20 14:32:22 -07:00
string tempFolderPath = Path . Combine ( matterControlDirectory , "Tests" , "temp" , runName , $"Test{testID++}" ) ;
2018-12-18 17:05:53 -08:00
ApplicationDataStorage . Instance . OverrideAppDataLocation ( tempFolderPath , ( ) = > DesktopSqlite . CreateInstance ( ) ) ;
2015-08-25 11:56:21 -07:00
}
2015-10-22 18:23:22 -07:00
public static void AddItemsToQueue ( string queueItemFolderToLoad )
{
2016-09-23 14:16:39 -07:00
// Default location of mcp file
2015-10-22 18:23:22 -07:00
string mcpPath = Path . Combine ( ApplicationDataStorage . ApplicationUserDataPath , "data" , "default.mcp" ) ;
Directory . CreateDirectory ( Path . GetDirectoryName ( mcpPath ) ) ;
if ( ! File . Exists ( mcpPath ) )
{
2022-02-17 08:08:24 -08:00
File . WriteAllText ( mcpPath , JsonConvert . SerializeObject ( new LegacyQueueFiles ( )
2016-09-20 14:32:22 -07:00
{
2020-08-09 08:23:22 -07:00
ProjectFiles = new List < PrintItem > ( )
2016-09-20 14:32:22 -07:00
} , Formatting . Indented ) ) ;
2015-10-22 18:23:22 -07:00
}
2022-02-17 08:08:24 -08:00
var queueItemData = JsonConvert . DeserializeObject < LegacyQueueFiles > ( File . ReadAllText ( mcpPath ) ) ;
2015-10-22 18:23:22 -07:00
string queueData = Path . Combine ( ApplicationDataStorage . ApplicationUserDataPath , "data" , "testitems" ) ;
2016-09-23 14:16:39 -07:00
// Create empty TestParts folder
2015-10-22 18:23:22 -07:00
Directory . CreateDirectory ( queueData ) ;
2016-09-22 08:52:15 -07:00
string queueItemsDirectory = TestContext . CurrentContext . ResolveProjectPath ( 5 , "MatterControl" , "Tests" , "TestData" , "QueueItems" , queueItemFolderToLoad ) ;
2015-12-22 11:34:04 -08:00
2016-09-22 08:52:15 -07:00
foreach ( string file in Directory . GetFiles ( queueItemsDirectory ) )
2015-10-22 18:23:22 -07:00
{
string newFilePath = Path . Combine ( queueData , Path . GetFileName ( file ) ) ;
File . Copy ( file , newFilePath , true ) ;
queueItemData . ProjectFiles . Add ( new PrintItem ( )
2016-09-22 08:52:15 -07:00
{
FileLocation = newFilePath ,
Name = Path . GetFileNameWithoutExtension ( file ) ,
DateAdded = DateTime . Now
} ) ;
2015-10-22 18:23:22 -07:00
}
File . WriteAllText ( mcpPath , JsonConvert . SerializeObject ( queueItemData , Formatting . Indented ) ) ;
Assert . IsTrue ( queueItemData ! = null & & queueItemData . ProjectFiles . Count > 0 ) ;
}
2021-06-11 11:23:15 -07:00
public static AutomationRunner OpenUserPopupMenu ( this AutomationRunner testRunner )
2018-04-15 14:43:11 -07:00
{
2021-06-11 11:23:15 -07:00
return testRunner . ClickByName ( "User Options Menu" ) ;
2018-04-15 14:43:11 -07:00
}
2020-07-18 08:37:40 -07:00
public static AutomationRunner ClickButton ( this AutomationRunner testRunner , string buttonName , string buttonText , double maxWait = 5 )
{
testRunner . WaitForName ( buttonName , maxWait , predicate : ( w ) = > w . Children . FirstOrDefault ( ) . Text = = buttonText ) ;
2021-06-11 11:23:15 -07:00
return testRunner . ClickByName ( buttonName ) ;
2020-07-18 08:37:40 -07:00
}
public static AutomationRunner ClickResumeButton ( this AutomationRunner testRunner ,
PrinterConfig printer ,
bool resume ,
int expectedLayer )
2020-07-16 07:59:57 -07:00
{
var buttonName = resume ? "Yes Button" : "No Button" ;
2020-07-18 08:37:40 -07:00
var buttonText = resume ? "Resume" : "OK" ;
testRunner . WaitForName ( buttonName , 90 , predicate : ( w ) = > w . Children . FirstOrDefault ( ) . Text = = buttonText ) ;
Assert . AreEqual ( expectedLayer ,
printer . Connection . CurrentlyPrintingLayer ,
$"Expected the paused layer to be {expectedLayer} but was {printer.Connection.CurrentlyPrintingLayer}." ) ;
2020-07-16 07:59:57 -07:00
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( buttonName )
. WaitFor ( ( ) = > ! testRunner . NameExists ( buttonName ) , 2 ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
2020-07-16 07:59:57 -07:00
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner NavigateToFolder ( this AutomationRunner testRunner , string libraryRowItemName )
2015-09-01 16:03:29 -07:00
{
2018-10-10 22:32:08 -07:00
testRunner . EnsureContentMenuOpen ( ) ;
2018-05-04 12:58:38 -07:00
2022-02-04 14:51:41 -08:00
if ( ! testRunner . NameExists ( libraryRowItemName , . 2 ) )
2018-05-04 12:58:38 -07:00
{
2022-02-04 14:51:41 -08:00
// go back to the home section
testRunner . ClickByName ( "Bread Crumb Button Home" )
. Delay ( ) ;
2018-12-23 20:18:56 -08:00
2022-02-04 14:51:41 -08:00
switch ( libraryRowItemName )
{
case "SD Card Row Item Collection" :
if ( ApplicationController . Instance . DragDropData . View3DWidget ? . Printer is PrinterConfig printer )
{
testRunner . DoubleClickByName ( $"{printer.PrinterName} Row Item Collection" )
. Delay ( ) ;
}
2018-12-23 20:18:56 -08:00
2022-02-04 14:51:41 -08:00
break ;
2018-12-23 20:18:56 -08:00
2022-02-04 14:51:41 -08:00
case "Calibration Parts Row Item Collection" :
case "Primitives Row Item Collection" :
// If visible, navigate into Libraries container before opening target
2022-02-03 08:41:57 -08:00
testRunner . DoubleClickByName ( "Design Apps Row Item Collection" )
2021-02-18 10:40:44 -08:00
. Delay ( ) ;
2022-02-04 14:51:41 -08:00
break ;
2018-05-04 12:58:38 -07:00
2022-02-04 14:51:41 -08:00
case "Downloads Row Item Collection" :
testRunner . DoubleClickByName ( "Computer Row Item Collection" )
2022-02-03 08:41:57 -08:00
. Delay ( ) ;
2022-02-04 14:51:41 -08:00
break ;
case "Cloud Library Row Item Collection" :
case "Print Queue Row Item Collection" :
case "Local Library Row Item Collection" :
break ;
}
2018-05-04 12:58:38 -07:00
}
2017-05-20 17:47:36 -07:00
testRunner . DoubleClickByName ( libraryRowItemName ) ;
2021-02-18 10:40:44 -08:00
return testRunner ;
2015-09-01 16:03:29 -07:00
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner EnsureContentMenuOpen ( this AutomationRunner testRunner )
2017-06-18 10:02:34 -07:00
{
2018-10-10 22:32:08 -07:00
if ( ! testRunner . WaitForName ( "FolderBreadCrumbWidget" , secondsToWait : 0.2 ) )
2017-06-18 10:02:34 -07:00
{
2022-02-04 14:51:41 -08:00
testRunner . ClickByName ( "Add Content Menu" )
. Delay ( ) ;
2017-06-18 10:02:34 -07:00
}
2021-02-18 10:40:44 -08:00
return testRunner ;
2018-10-10 22:32:08 -07:00
}
2017-06-18 10:02:34 -07:00
2018-12-24 10:52:53 -08:00
public static void OpenRequiredSetupAndConfigureMaterial ( this AutomationRunner testRunner )
{
// Complete new material selection requirement
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "PrintPopupMenu" )
. ClickByName ( "SetupPrinter" )
// Configure ABS as selected material
// testRunner.ClickByName("Material DropDown List")
// testRunner.ClickByName("ABS Menu")
2018-12-30 10:53:02 -08:00
2021-02-18 10:40:44 -08:00
// Currently material selection is not required, simply act of clicking 'Select' clears setup required
. ClickByName ( "Already Loaded Button" ) ;
2018-12-24 10:52:53 -08:00
}
2021-06-11 11:23:15 -07:00
public static AutomationRunner NavigateToLibraryHome ( this AutomationRunner testRunner )
2018-10-10 22:32:08 -07:00
{
2021-06-11 11:23:15 -07:00
return testRunner . EnsureContentMenuOpen ( )
2021-02-18 10:40:44 -08:00
. ClickByName ( "Bread Crumb Button Home" )
. Delay ( . 5 ) ;
2017-06-18 10:02:34 -07:00
}
2018-04-07 11:21:02 -07:00
public static void InvokeLibraryAddDialog ( this AutomationRunner testRunner )
{
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Print Library Overflow Menu" )
. ClickByName ( "Add Menu Item" ) ;
2018-04-07 11:21:02 -07:00
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner InvokeLibraryCreateFolderDialog ( this AutomationRunner testRunner )
2018-04-07 11:21:02 -07:00
{
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Print Library Overflow Menu" )
. ClickByName ( "Create Folder... Menu Item" ) ;
return testRunner ;
2018-04-07 11:21:02 -07:00
}
2018-10-05 14:21:55 -07:00
public static string CreateChildFolder ( this AutomationRunner testRunner , string folderName )
{
2021-02-18 10:40:44 -08:00
testRunner . InvokeLibraryCreateFolderDialog ( )
. WaitForName ( "InputBoxPage Action Button" ) ;
testRunner . Type ( folderName )
. ClickByName ( "InputBoxPage Action Button" ) ;
2018-10-05 14:21:55 -07:00
string folderID = $"{folderName} Row Item Collection" ;
Assert . IsTrue ( testRunner . WaitForName ( folderID ) , $"{folderName} exists" ) ;
return folderID ;
}
2017-12-06 15:21:18 -08:00
/// <summary>
/// Types the specified text into the dialog and sends {Enter} to complete the interaction
/// </summary>
/// <param name="testRunner">The TestRunner to interact with</param>
/// <param name="textValue">The text to type</param>
2017-12-09 14:20:25 -08:00
public static void CompleteDialog ( this AutomationRunner testRunner , string textValue , double secondsToWait = 2 )
2017-12-06 15:21:18 -08:00
{
// AutomationDialog requires no delay
2017-12-06 17:23:21 -08:00
if ( AggContext . FileDialogs is AutomationDialogProvider )
{
// Wait for text widget to have focus
var widget = testRunner . GetWidgetByName ( "Automation Dialog TextEdit" , out _ , 5 ) ;
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > widget . ContainsFocus ) ;
2017-12-06 17:23:21 -08:00
}
else
2017-12-06 15:21:18 -08:00
{
testRunner . Delay ( secondsToWait ) ;
}
2021-02-18 10:40:44 -08:00
testRunner . Type ( textValue )
. Type ( "{Enter}" )
. WaitForWidgetDisappear ( "Automation Dialog TextEdit" , 5 ) ;
2017-12-06 15:21:18 -08:00
}
2021-06-06 22:18:29 -07:00
public static AutomationRunner AddItemToBed ( this AutomationRunner testRunner , string containerName = "Calibration Parts Row Item Collection" , string partName = "Row Item Calibration - Box.stl" )
2017-06-02 19:40:10 -07:00
{
2017-11-01 13:57:45 -07:00
if ( ! testRunner . NameExists ( partName , 1 ) & & ! string . IsNullOrEmpty ( containerName ) )
2017-10-26 15:05:46 -07:00
{
testRunner . NavigateToFolder ( containerName ) ;
}
2017-06-02 19:40:10 -07:00
2017-10-27 14:19:26 -07:00
var partWidget = testRunner . GetWidgetByName ( partName , out _ ) as ListViewItemBase ;
if ( ! partWidget . IsSelected )
{
testRunner . ClickByName ( partName ) ;
}
2020-07-16 07:59:57 -07:00
2017-10-27 14:19:26 -07:00
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
2017-10-31 11:22:58 -07:00
var view3D = testRunner . GetWidgetByName ( "View3DWidget" , out _ ) as View3DWidget ;
2020-09-11 19:59:14 -07:00
var scene = view3D . Object3DControlLayer . Scene ;
2017-10-31 11:22:58 -07:00
var preAddCount = scene . Children . Count ( ) ;
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Add to Bed Menu Item" )
// wait for the object to be added
. WaitFor ( ( ) = > scene . Children . Count = = preAddCount + 1 ) ;
2017-10-31 11:22:58 -07:00
// wait for the object to be done loading
2018-06-21 21:02:37 -07:00
var insertionGroup = scene . Children . LastOrDefault ( ) as InsertionGroupObject3D ;
2017-12-06 17:23:21 -08:00
if ( insertionGroup ! = null )
2017-10-31 11:22:58 -07:00
{
2018-06-21 21:02:37 -07:00
testRunner . WaitFor ( ( ) = > scene . Children . LastOrDefault ( ) as InsertionGroupObject3D ! = null , 10 ) ;
2017-10-31 11:22:58 -07:00
}
2020-07-18 08:37:40 -07:00
return testRunner ;
2017-06-04 08:57:17 -07:00
}
2021-06-11 11:23:15 -07:00
public static AutomationRunner SaveBedplateToFolder ( this AutomationRunner testRunner , string newFileName , string folderName )
2017-06-06 18:19:02 -07:00
{
2021-09-14 10:22:13 -07:00
return testRunner . ClickByName ( "Save Menu SplitButton" , offset : new Point2D ( 30 , 0 ) )
2021-02-18 10:40:44 -08:00
. ClickByName ( "Save As Menu Item" )
. Delay ( 1 )
. Type ( newFileName )
. NavigateToFolder ( folderName )
. ClickByName ( "Accept Button" )
// Give the SaveAs window time to close before returning to the caller
. Delay ( 2 ) ;
2017-06-06 18:19:02 -07:00
}
2020-07-18 08:37:40 -07:00
public static AutomationRunner WaitForPrintFinished ( this AutomationRunner testRunner , PrinterConfig printer , int maxSeconds = 500 )
2017-06-02 21:20:56 -07:00
{
2018-11-30 12:53:43 -08:00
testRunner . WaitFor ( ( ) = > printer . Connection . CommunicationState = = CommunicationStates . FinishedPrint , maxSeconds ) ;
2019-04-29 16:43:59 -07:00
// click the ok button on the print complete dialog
2020-10-25 20:47:12 -07:00
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
2017-09-16 17:58:46 -07:00
}
2018-11-30 13:04:25 -08:00
/// <summary>
/// Gets a reference to the first and only active printer. Throws if called when multiple active printers exists
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2018-11-30 13:04:25 -08:00
/// <returns>The first active printer</returns>
2018-11-30 12:53:43 -08:00
public static PrinterConfig FirstPrinter ( this AutomationRunner testRunner )
2017-09-16 17:58:46 -07:00
{
2018-12-07 18:41:32 -08:00
Assert . AreEqual ( 1 , ApplicationController . Instance . ActivePrinters . Count ( ) , "FirstPrinter() is only valid in single printer scenarios" ) ;
2018-11-30 13:04:25 -08:00
2018-11-30 12:53:43 -08:00
return ApplicationController . Instance . ActivePrinters . First ( ) ;
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner CloseFirstPrinterTab ( this AutomationRunner testRunner )
2018-12-26 16:16:19 -08:00
{
// Close all printer tabs
var mainViewWidget = testRunner . GetWidgetByName ( "PartPreviewContent" , out _ ) as MainViewWidget ;
if ( mainViewWidget . TabControl . AllTabs . First ( t = > t . TabContent is PrinterTabPage ) is GuiWidget widget )
{
var closeWidget = widget . Descendants < ImageWidget > ( ) . First ( ) ;
Assert . AreEqual ( "Close Tab Button" , closeWidget . Name , "Expected widget ('Close Tab Button') not found" ) ;
testRunner . ClickWidget ( closeWidget ) ;
2022-02-06 08:22:31 -08:00
// close the save dialog
testRunner . ClickByName ( "No Button" ) ;
2018-12-26 16:16:19 -08:00
}
2021-02-18 10:40:44 -08:00
return testRunner ;
2018-12-26 16:16:19 -08:00
}
2018-11-30 12:53:43 -08:00
public static void WaitForCommunicationStateDisconnected ( this AutomationRunner testRunner , PrinterConfig printer , int maxSeconds = 500 )
{
testRunner . WaitFor ( ( ) = > printer . Connection . CommunicationState = = CommunicationStates . Disconnected , maxSeconds ) ;
2017-06-02 21:20:56 -07:00
}
2016-10-25 06:17:37 -07:00
public static async Task RunTest (
AutomationTest testMethod ,
2016-09-20 14:32:22 -07:00
string staticDataPathOverride = null ,
double maxTimeToRun = 60 ,
2016-08-02 09:47:26 -07:00
QueueTemplate queueItemFolderToAdd = QueueTemplate . None ,
2017-12-06 17:23:21 -08:00
int overrideWidth = - 1 ,
2016-10-07 13:49:01 -07:00
int overrideHeight = - 1 ,
string defaultTestImages = null )
2015-09-04 11:28:01 -07:00
{
2016-10-17 11:02:40 -07:00
// Walk back a step in the stack and output the callers name
2020-07-18 08:37:40 -07:00
// StackTrace st = new StackTrace(false);
// Debug.WriteLine("\r\n ***** Running automation test: {0} {1} ", st.GetFrames().Skip(1).First().GetMethod().Name, DateTime.Now);
2016-10-17 11:02:40 -07:00
2015-09-04 11:28:01 -07:00
if ( staticDataPathOverride = = null )
{
2016-09-20 09:39:57 -07:00
// Popping one directory above MatterControl, then back down into MatterControl ensures this works in MCCentral as well and MatterControl
staticDataPathOverride = TestContext . CurrentContext . ResolveProjectPath ( 5 , "MatterControl" , "StaticData" ) ;
2015-09-04 11:28:01 -07:00
}
2015-12-22 11:34:04 -08:00
2016-10-17 11:02:40 -07:00
#if DEBUG
string outputDirectory = "Debug" ;
#else
string outputDirectory = "Release" ;
#endif
2017-12-05 18:05:18 -08:00
Environment . CurrentDirectory = TestContext . CurrentContext . ResolveProjectPath ( 5 , "MatterControl" , "bin" , outputDirectory ) ;
// Override the default SystemWindow type without config.json
2020-07-18 08:37:40 -07:00
// AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.Agg.UI.OpenGLWinformsWindowProvider, agg_platform_win32";
2018-12-10 14:26:29 -08:00
AggContext . Config . ProviderTypes . SystemWindowProvider = "MatterHackers.MatterControl.WinformsSingleWindowProvider, MatterControl.Winforms" ;
2016-10-17 11:02:40 -07:00
2015-09-04 11:28:01 -07:00
#if ! __ANDROID__
// Set the static data to point to the directory of MatterControl
2020-11-25 07:39:36 -08:00
StaticData . RootPath = staticDataPathOverride ;
2015-09-04 11:28:01 -07:00
#endif
2016-09-20 09:39:57 -07:00
// Popping one directory above MatterControl, then back down into MatterControl ensures this works in MCCentral as well and MatterControl
MatterControlUtilities . OverrideAppDataLocation ( TestContext . CurrentContext . ResolveProjectPath ( 5 , "MatterControl" ) ) ;
2015-10-22 18:23:22 -07:00
2015-12-22 11:34:04 -08:00
if ( queueItemFolderToAdd ! = QueueTemplate . None )
2015-10-22 18:23:22 -07:00
{
2017-06-04 17:39:30 -07:00
MatterControlUtilities . AddItemsToQueue ( queueItemFolderToAdd . ToString ( ) ) ;
2015-10-22 18:23:22 -07:00
}
2015-09-04 11:28:01 -07:00
2016-10-19 11:49:52 -07:00
if ( defaultTestImages = = null )
{
defaultTestImages = TestContext . CurrentContext . ResolveProjectPath ( 4 , "Tests" , "TestData" , "TestImages" ) ;
}
2016-12-02 10:52:33 -08:00
UserSettings . Instance . set ( UserSettingsKey . ThumbnailRenderingMode , "orthographic" ) ;
2020-07-18 08:37:40 -07:00
// GL.HardwareAvailable = false;
2016-10-19 13:27:27 -07:00
var config = TestAutomationConfig . Load ( ) ;
2017-12-06 17:23:21 -08:00
if ( config . UseAutomationDialogs )
{
AggContext . Config . ProviderTypes . DialogProvider = "MatterHackers.Agg.Platform.AutomationDialogProvider, GuiAutomation" ;
}
2017-12-06 09:14:32 -08:00
2016-12-13 10:20:12 -08:00
// Extract mouse speed from config
AutomationRunner . TimeToMoveMouse = config . TimeToMoveMouse ;
2017-12-06 17:23:21 -08:00
AutomationRunner . UpDelaySeconds = config . MouseUpDelay ;
2016-12-13 10:20:12 -08:00
2018-08-02 18:49:49 -07:00
// Automation runner must do as much as program.cs to spin up platform
2018-09-05 14:33:42 -07:00
string platformFeaturesProvider = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl.Winforms" ;
2018-08-02 18:49:49 -07:00
AppContext . Platform = AggContext . CreateInstanceFrom < INativePlatformFeatures > ( platformFeaturesProvider ) ;
2018-12-18 17:05:13 -08:00
AppContext . Platform . InitPluginFinder ( ) ;
2018-08-02 18:49:49 -07:00
AppContext . Platform . ProcessCommandline ( ) ;
2017-12-18 22:03:17 -08:00
var ( width , height ) = RootSystemWindow . GetStartupBounds ( ) ;
rootSystemWindow = Application . LoadRootWindow (
2018-03-27 09:24:02 -07:00
overrideWidth = = - 1 ? width : overrideWidth ,
2017-12-18 22:03:17 -08:00
overrideHeight = = - 1 ? height : overrideHeight ) ;
2017-12-16 19:09:25 -08:00
2018-04-20 12:01:22 -07:00
OemSettings . Instance . ShowShopButton = false ;
2018-09-04 17:15:35 -07:00
if ( ! config . UseAutomationMouse )
{
AutomationRunner . InputMethod = new WindowsInputMethods ( ) ;
}
2017-10-05 18:04:45 -07:00
await AutomationRunner . ShowWindowAndExecuteTests (
2017-12-16 19:09:25 -08:00
rootSystemWindow ,
2017-12-06 17:23:21 -08:00
testMethod ,
maxTimeToRun ,
defaultTestImages ,
2022-02-04 14:51:41 -08:00
closeWindow : ( testRunner ) = >
2017-06-11 09:58:25 -07:00
{
2019-07-06 08:00:03 -07:00
foreach ( var printer in ApplicationController . Instance . ActivePrinters )
2018-12-30 10:53:02 -08:00
{
2018-11-30 12:53:43 -08:00
if ( printer . Connection . CommunicationState = = CommunicationStates . Printing )
{
printer . Connection . Disable ( ) ;
}
2017-10-05 18:04:45 -07:00
}
2017-12-16 19:09:25 -08:00
rootSystemWindow . Close ( ) ;
2022-02-04 14:51:41 -08:00
testRunner . Delay ( ) ;
if ( testRunner . NameExists ( "No Button" ) )
{
testRunner . ClickDiscardChanges ( ) ;
}
2019-07-06 08:00:03 -07:00
} ) ;
2015-09-04 11:28:01 -07:00
}
2016-08-01 13:53:28 -07:00
2016-08-01 14:22:16 -07:00
public static void LibraryEditSelectedItem ( AutomationRunner testRunner )
{
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Edit Menu Item" ) ;
2017-02-01 10:12:31 -08:00
testRunner . Delay ( 1 ) ; // wait for the new window to open
2016-08-01 14:22:16 -07:00
}
2016-08-01 17:21:31 -07:00
2017-06-03 13:29:36 -07:00
public static void LibraryRenameSelectedItem ( this AutomationRunner testRunner )
2016-08-01 17:21:31 -07:00
{
2017-06-03 13:29:36 -07:00
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Rename Menu Item" ) ;
2016-08-01 17:21:31 -07:00
}
2017-06-06 18:52:13 -07:00
public static void LibraryRemoveSelectedItem ( this AutomationRunner testRunner )
2016-08-01 17:21:31 -07:00
{
2017-06-03 13:29:36 -07:00
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Remove Menu Item" ) ;
2018-04-25 16:42:40 -07:00
testRunner . ClickByName ( "Yes Button" ) ;
2016-08-01 17:21:31 -07:00
}
2017-06-03 13:29:36 -07:00
2018-10-05 14:22:11 -07:00
public static void LibraryMoveSelectedItem ( this AutomationRunner testRunner )
{
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
testRunner . ClickByName ( "Move Menu Item" ) ;
}
2016-09-20 09:39:57 -07:00
public static string ResolveProjectPath ( this TestContext context , int stepsToProjectRoot , params string [ ] relativePathSteps )
{
string assemblyPath = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) ;
var allPathSteps = new List < string > { assemblyPath } ;
allPathSteps . AddRange ( Enumerable . Repeat ( ".." , stepsToProjectRoot ) ) ;
if ( relativePathSteps . Any ( ) )
{
allPathSteps . AddRange ( relativePathSteps ) ;
}
return Path . GetFullPath ( Path . Combine ( allPathSteps . ToArray ( ) ) ) ;
}
2016-09-21 15:34:53 -07:00
/// <summary>
/// Set the working directory to the location of the executing assembly. This is essentially the Nunit2 behavior
/// </summary>
/// <param name="context"></param>
public static void SetCompatibleWorkingDirectory ( this TestContext context )
{
Environment . CurrentDirectory = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) ;
}
2016-09-20 14:32:22 -07:00
2020-07-18 08:37:40 -07:00
public static AutomationRunner StartSlicing ( this AutomationRunner testRunner )
2017-09-23 00:26:50 -07:00
{
testRunner . ClickByName ( "Generate Gcode Button" ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
2017-09-23 00:26:50 -07:00
}
2020-07-18 08:37:40 -07:00
public static AutomationRunner OpenPrintPopupMenu ( this AutomationRunner testRunner )
2016-09-20 14:32:22 -07:00
{
2018-11-21 19:24:20 -08:00
var printerConnection = ApplicationController . Instance . DragDropData . View3DWidget . Printer . Connection ;
2017-12-14 16:19:22 -08:00
2017-12-14 21:59:41 -08:00
if ( printerConnection . CommunicationState ! = CommunicationStates . Connected
& & printerConnection . CommunicationState ! = CommunicationStates . FinishedPrint )
2017-12-14 16:19:22 -08:00
{
testRunner . ClickByName ( "Connect to printer button" ) ;
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > printerConnection . CommunicationState = = CommunicationStates . Connected ) ;
2017-12-14 16:19:22 -08:00
}
2017-06-12 20:35:48 -07:00
2019-04-30 16:45:56 -07:00
// Open PopupMenu
2019-04-30 16:00:23 -07:00
testRunner . ClickByName ( "PrintPopupMenu" ) ;
2019-04-30 16:45:56 -07:00
// Wait for child control
testRunner . WaitForName ( "Start Print Button" ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
2017-12-14 16:19:22 -08:00
}
2017-06-02 19:39:29 -07:00
2021-02-18 10:40:44 -08:00
public static AutomationRunner WaitForLayerAndResume ( this AutomationRunner testRunner , PrinterConfig printer , int indexToWaitFor )
{
testRunner . WaitForName ( "Yes Button" , 15 ) ;
// Wait for layer
testRunner . WaitFor ( ( ) = > printer . Bed . ActiveLayerIndex + 1 = = indexToWaitFor , 10 , 500 ) ;
Assert . AreEqual ( indexToWaitFor , printer . Bed . ActiveLayerIndex + 1 , "Active layer index does not match expected" ) ;
testRunner . ClickByName ( "Yes Button" ) ;
testRunner . Delay ( ) ;
return testRunner ;
}
2017-12-14 16:19:22 -08:00
/// <summary>
/// Open the Print popup menu and click the Start Print button
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner we are using.</param>
2020-11-17 14:39:29 -08:00
/// <param name="printer">The printer to run the print on.</param>
2020-07-18 08:37:40 -07:00
/// <param name="pauseAtLayers">The string to write into the pause field in the print menu.</param>
2020-08-09 08:23:22 -07:00
/// <returns>The automation runner to allow fluid design</returns>
public static AutomationRunner StartPrint ( this AutomationRunner testRunner ,
PrinterConfig printer ,
string pauseAtLayers = null )
2017-12-14 16:19:22 -08:00
{
2019-04-30 16:00:23 -07:00
// Open popup
testRunner . OpenPrintPopupMenu ( ) ;
if ( pauseAtLayers ! = null )
{
testRunner . OpenPrintPopupAdvanced ( ) ;
testRunner . ClickByName ( "Layer(s) To Pause Field" ) ;
testRunner . Type ( pauseAtLayers ) ;
}
2020-11-17 14:39:29 -08:00
if ( testRunner . NameExists ( "SetupPrinter" , . 2 ) )
2020-08-08 22:39:08 -07:00
{
2020-08-09 08:23:22 -07:00
if ( printer . Settings . GetValue < bool > ( SettingsKey . use_z_probe ) )
{
testRunner . ClickByName ( "SetupPrinter" )
. ClickByName ( "Already Loaded Button" )
. ClickByName ( "Cancel Wizard Button" )
. OpenPrintPopupMenu ( ) ;
}
else
{
testRunner . ClickByName ( "SetupPrinter" )
. ClickByName ( "Already Loaded Button" )
. ClickByName ( "Cancel Wizard Button" )
. OpenPrintPopupMenu ( ) ;
}
2020-08-08 22:39:08 -07:00
}
2017-12-14 16:19:22 -08:00
testRunner . ClickByName ( "Start Print Button" ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
}
2020-11-17 14:39:29 -08:00
/// <summary>
/// Open the Print popup menu and click the Start Print button
/// </summary>
/// <param name="testRunner">The AutomationRunner we are using.</param>
/// <param name="printer">The printer to run the print on.</param>
/// <param name="exportedGCode">The exported gcode is loaded and put into this variable.</param>
/// <returns>The automation runner to allow fluid design</returns>
public static AutomationRunner ExportPrintAndLoadGCode ( this AutomationRunner testRunner ,
PrinterConfig printer ,
out string exportedGCode )
{
// Open popup
testRunner . OpenPrintPopupMenu ( ) ;
if ( testRunner . NameExists ( "SetupPrinter" ) )
{
testRunner . ClickByName ( "SetupPrinter" )
. ClickByName ( "Already Loaded Button" )
. ClickByName ( "Cancel Wizard Button" )
. OpenPrintPopupMenu ( ) ;
}
2021-03-16 11:02:21 -07:00
testRunner . ClickByName ( "Export GCode Button" ) ;
2020-11-17 14:39:29 -08:00
// wait for the export to finish
throw new NotImplementedException ( ) ;
exportedGCode = "" ;
return testRunner ;
}
2020-07-18 08:37:40 -07:00
public static AutomationRunner WaitForPause ( this AutomationRunner testRunner , PrinterConfig printer , int expectedLayer )
{
testRunner . WaitForName ( "Yes Button" , 15 , predicate : ( w ) = > w . Children . FirstOrDefault ( ) . Text = = "Resume" ) ;
// validate the current layer
if ( expectedLayer ! = printer . Connection . CurrentlyPrintingLayer )
{
throw new Exception ( $"Expected the paused layer to be {expectedLayer} but was {printer.Connection.CurrentlyPrintingLayer}." ) ;
}
return testRunner ;
2017-12-14 16:19:22 -08:00
}
2017-06-09 20:12:25 -07:00
2019-04-30 16:00:23 -07:00
public static void OpenPrintPopupAdvanced ( this AutomationRunner testRunner )
{
// Expand advanced panel if needed
if ( ! testRunner . NameExists ( "Layer(s) To Pause Field" , . 2 ) )
{
testRunner . ClickByName ( "Advanced Section" ) ;
}
// wait for child
testRunner . WaitForName ( "Layer(s) To Pause Field" ) ;
}
2017-12-14 16:19:22 -08:00
public static void OpenGCode3DOverflowMenu ( this AutomationRunner testRunner )
{
var button = testRunner . GetWidgetByName ( "Layers3D Button" , out _ ) as ICheckbox ;
if ( ! button . Checked )
{
testRunner . ClickByName ( "Layers3D Button" ) ;
}
testRunner . ClickByName ( "View3D Overflow Menu" ) ;
2016-09-20 14:32:22 -07:00
}
2017-06-04 08:22:04 -07:00
2017-12-14 16:19:22 -08:00
/// <summary>
/// Switch to the primary SliceSettings tab
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2021-02-18 10:40:44 -08:00
public static AutomationRunner SwitchToSliceSettings ( this AutomationRunner testRunner )
2017-12-14 16:19:22 -08:00
{
2021-01-31 08:47:36 -08:00
OpenSettingsSidebar ( testRunner ) ;
2018-01-07 16:38:43 -08:00
2020-05-16 08:34:06 -07:00
testRunner . WaitForWidgetEnabled ( "Slice Settings Tab" ) ;
2018-01-07 16:38:43 -08:00
testRunner . ClickByName ( "Slice Settings Tab" ) ;
2021-02-18 10:40:44 -08:00
return testRunner ;
2017-12-14 16:19:22 -08:00
}
2020-07-18 08:37:40 -07:00
public static AutomationRunner WaitForPageAndAdvance ( this AutomationRunner testRunner , string headerText )
2018-10-03 12:28:23 -07:00
{
2020-07-18 08:37:40 -07:00
testRunner . WaitForPage ( headerText )
. ClickByName ( "Next Button" ) ;
2018-10-03 12:28:23 -07:00
2020-07-18 08:37:40 -07:00
return testRunner ;
}
2018-10-03 12:28:23 -07:00
2020-07-18 08:37:40 -07:00
public static AutomationRunner Complete9StepLeveling ( this AutomationRunner testRunner , int numUpClicks = 1 )
{
testRunner . Delay ( )
. WaitForPageAndAdvance ( "Print Leveling Overview" )
. WaitForPageAndAdvance ( "Heating the printer" ) ;
2018-10-03 12:28:23 -07:00
for ( int i = 0 ; i < 3 ; i + + )
{
var section = ( i * 3 ) + 1 ;
2019-05-14 15:12:30 -07:00
testRunner . WaitForPage ( $"Step {section} of 9" ) ;
2018-10-18 08:19:20 -07:00
for ( int j = 0 ; j < numUpClicks ; j + + )
{
testRunner . Delay ( ) ;
testRunner . ClickByName ( "Move Z positive" ) ;
}
2018-10-03 12:28:23 -07:00
2020-07-18 08:37:40 -07:00
testRunner . WaitForPage ( $"Step {section} of 9" )
. ClickByName ( "Next Button" )
. WaitForPage ( $"Step {section + 1} of 9" )
. ClickByName ( "Next Button" )
. WaitForPage ( $"Step {section + 2} of 9" )
. ClickByName ( "Next Button" ) ;
2018-10-03 12:28:23 -07:00
}
2020-07-18 08:37:40 -07:00
testRunner . ClickByName ( "Done Button" )
. Delay ( ) ;
2018-11-05 12:05:09 -08:00
2019-04-30 16:49:34 -07:00
if ( testRunner . NameExists ( "Already Loaded Button" , 0.2 ) )
2018-11-05 12:05:09 -08:00
{
testRunner . ClickByName ( "Already Loaded Button" ) ;
}
2019-04-15 21:04:48 -07:00
// Close the staged wizard window
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
2020-07-18 08:37:40 -07:00
return testRunner ;
2018-10-03 12:28:23 -07:00
}
2017-12-28 09:02:44 -08:00
/// <summary>
/// Switch to printer settings
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2021-01-31 08:47:36 -08:00
public static AutomationRunner SwitchToPrinterSettings ( this AutomationRunner testRunner , bool pinSettingsOpen = true )
2017-12-28 09:02:44 -08:00
{
2021-01-31 08:47:36 -08:00
testRunner . OpenSettingsSidebar ( pinSettingsOpen ) ;
2017-12-28 09:02:44 -08:00
2018-04-20 12:01:22 -07:00
if ( ! testRunner . NameExists ( "Printer Tab" , 0.1 ) )
2018-04-05 16:16:43 -07:00
{
2020-10-03 17:57:53 -07:00
testRunner . ClickByName ( "Printer Overflow Menu" )
2020-11-25 07:39:36 -08:00
. ClickByName ( "Show Printer Menu Item" ) ;
2021-01-31 08:47:36 -08:00
if ( ! pinSettingsOpen )
{
// close the menu
testRunner . ClickByName ( "Printer Overflow Menu" ) ;
}
2018-04-05 16:16:43 -07:00
}
2020-07-18 08:37:40 -07:00
2021-01-31 08:47:36 -08:00
if ( pinSettingsOpen )
{
return testRunner . ClickByName ( "Printer Tab" ) ;
}
else
{
return testRunner . ClickByName ( "Printer Sidebar" ) ;
}
2017-12-28 09:02:44 -08:00
}
2018-01-24 17:49:16 -08:00
public static void InlineTitleEdit ( this AutomationRunner testRunner , string controlName , string replaceString )
{
testRunner . ClickByName ( controlName + " Edit" ) ;
testRunner . ClickByName ( controlName + " Field" ) ;
var textWidget = testRunner . GetWidgetByName ( controlName + " Field" , out _ ) ;
textWidget . Text = replaceString ;
testRunner . ClickByName ( controlName + " Save" ) ;
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner NavigateToSliceSettingsField ( this AutomationRunner testRunner , string slicerConfigName )
2018-01-07 14:53:42 -08:00
{
2019-01-06 13:19:01 -08:00
var settingData = PrinterSettings . SettingsData [ slicerConfigName ] ;
2018-01-07 14:53:42 -08:00
2020-06-21 13:41:37 -07:00
var group = settingData . OrganizerGroup ;
2018-01-07 14:53:42 -08:00
2020-06-21 13:41:37 -07:00
var category = group . Category ;
2018-01-07 14:53:42 -08:00
// Click tab
testRunner . ClickByName ( category . Name + " Tab" ) ;
2018-02-08 15:42:07 -08:00
// Open the subGroup if required
2020-12-31 09:33:43 -08:00
var foundWidget = testRunner . GetWidgetByName ( group . Name + " Panel" , out _ , . 1 ) ;
if ( foundWidget = = null )
{
// turn on advanced mode and try to get it again
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Slice Settings Overflow Menu" )
. ClickByName ( "Advanced Menu Item" ) ;
2020-12-31 09:33:43 -08:00
foundWidget = testRunner . GetWidgetByName ( group . Name + " Panel" , out _ ) ;
}
2018-02-08 15:42:07 -08:00
if ( foundWidget ! = null )
{
var containerCheckBox = foundWidget . Descendants < ExpandCheckboxButton > ( ) . First ( ) ;
if ( ! containerCheckBox . Checked )
{
containerCheckBox . Checked = true ;
testRunner . Delay ( ) ;
}
}
2021-02-18 10:40:44 -08:00
return testRunner ;
2018-02-08 15:42:07 -08:00
}
2021-01-30 08:49:06 -08:00
public static string SettingWidgetName ( this string slicerConfigName )
{
var settingData = PrinterSettings . SettingsData [ slicerConfigName ] ;
// Click field
return $"{settingData.PresentationName} Field" ;
}
2021-02-18 10:40:44 -08:00
public static AutomationRunner SelectSliceSettingsField ( this AutomationRunner testRunner , string slicerConfigName )
2018-02-08 15:42:07 -08:00
{
2021-01-31 18:33:34 -08:00
testRunner . NavigateToSliceSettingsField ( slicerConfigName ) ;
2018-01-07 14:53:42 -08:00
// Click field
2021-01-30 08:49:06 -08:00
var widgetName = SettingWidgetName ( slicerConfigName ) ;
2020-12-31 09:33:43 -08:00
var foundWidget = testRunner . GetWidgetByName ( widgetName , out _ , . 2 , onlyVisible : false ) ;
if ( foundWidget = = null )
{
// turn on advanced mode and try to get it again
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Slice Settings Overflow Menu" )
. ClickByName ( "Advanced Menu Item" ) ;
2021-01-31 18:33:34 -08:00
foundWidget = testRunner . GetWidgetByName ( widgetName , out _ , 20 , onlyVisible : false ) ;
2020-12-31 09:33:43 -08:00
}
2020-06-22 15:57:06 -07:00
foreach ( var scrollable in foundWidget . Parents < ScrollableWidget > ( ) )
{
scrollable . ScrollIntoView ( foundWidget ) ;
}
testRunner . ClickByName ( widgetName ) ;
2021-02-18 10:40:44 -08:00
return testRunner ;
2018-01-07 14:53:42 -08:00
}
2017-12-14 16:19:22 -08:00
/// <summary>
/// Switch to Printer -> Controls
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2017-06-13 13:22:22 -07:00
public static void SwitchToControlsTab ( this AutomationRunner testRunner )
2017-12-14 16:19:22 -08:00
{
// Change to Printer Controls
2021-01-31 08:47:36 -08:00
OpenSettingsSidebar ( testRunner ) ;
2018-09-10 10:42:18 -07:00
if ( ! testRunner . NameExists ( "Controls Tab" , 0.2 ) )
{
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Printer Overflow Menu" )
. ClickByName ( "Show Controls Menu Item" ) ;
2018-09-10 10:42:18 -07:00
}
2017-12-14 16:19:22 -08:00
testRunner . ClickByName ( "Controls Tab" ) ;
}
2018-09-10 10:42:18 -07:00
/// <summary>
/// Switch to Printer -> Terminal
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2018-09-10 10:42:18 -07:00
public static void SwitchToTerminalTab ( this AutomationRunner testRunner )
{
// Change to Printer Controls
2021-01-31 08:47:36 -08:00
OpenSettingsSidebar ( testRunner ) ;
2018-09-10 10:42:18 -07:00
if ( ! testRunner . NameExists ( "Terminal Tab" , 0.2 ) )
{
2021-02-18 10:40:44 -08:00
testRunner . ClickByName ( "Printer Overflow Menu" )
. ClickByName ( "Show Terminal Menu Item" ) ;
2018-09-10 10:42:18 -07:00
}
testRunner . ClickByName ( "Terminal Tab" ) ;
}
2018-03-13 08:42:37 -07:00
/// <summary>
/// Switch to Printer -> GCode Tab - NOTE: as a short term hack this helper as adds content to the bed and slices to ensure GCode view options appear as expected
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2018-03-13 08:42:37 -07:00
public static void SwitchToGCodeTab ( this AutomationRunner testRunner )
{
testRunner . ClickByName ( "Layers3D Button" ) ;
// TODO: Remove workaround needed to force GCode options to appear {{
2021-06-06 22:18:29 -07:00
testRunner . AddItemToBed ( )
2021-02-18 10:40:44 -08:00
. ClickByName ( "Generate Gcode Button" ) ;
2018-03-13 08:42:37 -07:00
// TODO: Remove workaround needed to force GCode options to appear }}
}
2021-01-31 08:47:36 -08:00
public static void OpenSettingsSidebar ( this AutomationRunner testRunner , bool pinOpen = true )
2017-06-13 13:22:22 -07:00
{
2021-01-31 18:33:34 -08:00
// If the sidebar exists, we need to expand and pin it
if ( testRunner . NameExists ( "Slice Settings Sidebar" , . 1 ) )
{
testRunner . ClickByName ( "Slice Settings Sidebar" ) ;
}
2021-01-31 08:47:36 -08:00
if ( pinOpen
& & UserSettings . Instance . get ( UserSettingsKey . SliceSettingsTabPinned ) ! = "true" )
2017-06-13 13:22:22 -07:00
{
2021-01-31 08:47:36 -08:00
testRunner . ClickByName ( "Pin Settings Button" ) ;
2017-06-13 13:22:22 -07:00
}
}
2017-06-04 08:22:04 -07:00
/// <summary>
/// Adds the given asset names to the local library and validates the result
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2017-06-04 08:22:04 -07:00
/// <param name="assetNames">The test assets to add to the library</param>
2021-02-18 10:40:44 -08:00
public static AutomationRunner AddTestAssetsToLibrary ( this AutomationRunner testRunner , IEnumerable < string > assetNames , string targetLibrary = "Local Library Row Item Collection" )
2017-06-04 08:22:04 -07:00
{
// Switch to the Local Library tab
2018-11-02 07:35:26 -07:00
testRunner . NavigateToFolder ( targetLibrary ) ;
2017-06-04 08:22:04 -07:00
2017-09-23 12:23:48 -07:00
// Assert that the requested items are *not* in the list
2017-06-04 08:22:04 -07:00
foreach ( string assetName in assetNames )
{
string friendlyName = Path . GetFileNameWithoutExtension ( assetName ) ;
2017-12-06 17:23:21 -08:00
Assert . IsFalse ( testRunner . WaitForName ( $"Row Item {friendlyName}" , . 1 ) , $"{friendlyName} part should not exist at test start" ) ;
2017-06-04 08:22:04 -07:00
}
// Add Library item
2018-04-07 11:21:02 -07:00
testRunner . InvokeLibraryAddDialog ( ) ;
2017-12-06 17:23:21 -08:00
// Generate the full, quoted paths for the requested assets
string fullQuotedAssetPaths = string . Join ( " " , assetNames . Select ( name = > $"\" { MatterControlUtilities . GetTestItemPath ( name ) } \ "" ) ) ;
testRunner . CompleteDialog ( fullQuotedAssetPaths ) ;
2017-06-04 08:22:04 -07:00
2017-09-23 12:23:48 -07:00
// Assert that the added items *are* in the list
2017-06-04 08:22:04 -07:00
foreach ( string assetName in assetNames )
{
string friendlyName = Path . GetFileNameWithoutExtension ( assetName ) ;
2018-11-02 09:00:25 -07:00
string fileName = Path . GetFileName ( assetName ) ;
// Look for either expected format (print queue differs from libraries)
Assert . IsTrue (
testRunner . WaitForName ( $"Row Item {friendlyName}" , 2 )
| | testRunner . WaitForName ( $"Row Item {fileName}" , 2 ) ,
$"{friendlyName} part should exist after adding" ) ;
2017-06-04 08:22:04 -07:00
}
2021-02-18 10:40:44 -08:00
return testRunner ;
2017-06-04 08:22:04 -07:00
}
2017-06-06 18:42:44 -07:00
/// <summary>
/// Control clicks each specified item
/// </summary>
2020-07-18 08:37:40 -07:00
/// <param name="testRunner">The AutomationRunner in use</param>
2017-06-06 18:42:44 -07:00
/// <param name="widgetNames">The widgets to click</param>
public static void SelectListItems ( this AutomationRunner testRunner , params string [ ] widgetNames )
{
// Control click all items
Keyboard . SetKeyDownState ( Keys . ControlKey , down : true ) ;
2017-12-06 17:23:21 -08:00
foreach ( var widgetName in widgetNames )
2017-06-06 18:42:44 -07:00
{
testRunner . ClickByName ( widgetName ) ;
}
2020-07-18 08:37:40 -07:00
2017-06-06 18:42:44 -07:00
Keyboard . SetKeyDownState ( Keys . ControlKey , down : false ) ;
}
2016-09-20 14:32:22 -07:00
}
2015-12-22 11:34:04 -08:00
/// <summary>
/// Represents a queue template folder on disk (located at Tests/TestData/QueueItems) that should be synced into the default
/// queue during test init. The enum name and folder name *must* be the same in order to function
/// </summary>
public enum QueueTemplate
{
None ,
2018-10-03 18:19:35 -07:00
Three_Queue_Items ,
ReSliceParts
2015-12-22 11:34:04 -08:00
}
2016-09-20 09:39:57 -07:00
public class TestAutomationConfig
{
2020-07-18 08:37:40 -07:00
private static readonly string ConfigPath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) , "MHTest.config" ) ;
2016-09-20 09:39:57 -07:00
/// <summary>
/// The ClientToken used by tests to emulate an external client
/// </summary>
public string TestEnvClientToken { get ; set ; }
2016-12-13 10:20:12 -08:00
/// <summary>
/// The number of seconds to move the mouse when going to a new position.
/// </summary>
public double TimeToMoveMouse { get ; set ; } = . 5 ;
2018-04-30 15:10:05 -07:00
/// <summary>
2018-07-12 22:49:39 -07:00
/// Determines if we use actual system file dialogs or simulated file dialogs.
2018-04-30 15:10:05 -07:00
/// </summary>
public bool UseAutomationDialogs { get ; set ; } = true ;
2017-12-06 15:19:23 -08:00
2018-04-30 15:10:05 -07:00
public bool UseAutomationMouse { get ; set ; } = true ;
2017-12-06 15:19:23 -08:00
2017-12-06 17:23:21 -08:00
public double MouseUpDelay { get ; set ; } = 0.2 ;
2017-12-15 18:19:36 -08:00
/// <summary>
/// The number of seconds the emulator should take to heat up and given target
/// </summary>
public double HeatupTime { get ; set ; } = 0.5 ;
2017-12-15 19:21:50 -08:00
/// <summary>
2018-03-27 09:24:02 -07:00
/// The number of seconds to wait after reaching the target temp before continuing. Analogous to
2017-12-15 19:21:50 -08:00
/// firmware dwell time for temperature stabilization
/// </summary>
public double TempStabilizationTime { get ; set ; } = 0.5 ;
2017-12-06 15:19:23 -08:00
public static TestAutomationConfig Load ( )
2016-09-20 09:39:57 -07:00
{
TestAutomationConfig config = null ;
2020-07-18 08:37:40 -07:00
if ( ! File . Exists ( ConfigPath ) )
2016-09-20 09:39:57 -07:00
{
config = new TestAutomationConfig ( ) ;
config . Save ( ) ;
}
else
{
2020-07-18 08:37:40 -07:00
config = JsonConvert . DeserializeObject < TestAutomationConfig > ( File . ReadAllText ( ConfigPath ) ) ;
2016-09-20 09:39:57 -07:00
}
return config ;
}
/// <summary>
/// Persist the current settings to the 'MHTest.config' in the user profile - %userprofile%\MHTest.config
/// </summary>
public void Save ( )
{
2020-07-18 08:37:40 -07:00
File . WriteAllText ( ConfigPath , JsonConvert . SerializeObject ( this , Formatting . Indented ) ) ;
2016-09-20 09:39:57 -07:00
}
}
2015-05-07 19:57:33 -07:00
}