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 ;
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 ;
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 ;
2016-11-05 10:56:52 -07:00
private static event EventHandler unregisterEvents ;
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
{
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Queue... Menu" ) ;
2017-02-01 10:12:31 -08:00
testRunner . Delay ( 1 ) ;
2017-06-14 09:56:51 -07:00
testRunner . 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
}
2016-09-19 09:38:20 -07:00
public static void SignOut ( AutomationRunner testRunner )
{
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "User Options Menu" ) ;
testRunner . ClickByName ( "Sign Out Menu Item" ) ;
2017-02-01 10:12:31 -08:00
testRunner . Delay ( . 5 ) ;
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" ) ) ;
}
public static void WaitForReloadAll ( this AutomationRunner testRunner , Action reloadAllAction )
{
// Wire up a block and release mechanism to wait until the sign in process has completed
AutoResetEvent resetEvent = new AutoResetEvent ( false ) ;
ApplicationController . Instance . DoneReloadingAll . RegisterEvent ( ( s , e ) = > resetEvent . Set ( ) , ref unregisterEvents ) ;
// 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
unregisterEvents ( null , null ) ;
// Wait for any post DoneReloadingAll code to finish up and return
2017-02-01 10:12:31 -08:00
testRunner . Delay ( . 2 ) ;
2016-09-19 09:38:20 -07:00
}
2016-01-13 17:02:41 -08: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
2016-07-29 16:44:00 -07:00
} ;
2018-01-26 17:53:54 -08:00
public static void ExpandEditTool ( this AutomationRunner testRunner , string expandCheckboxButtonName )
{
var mirrorPanel = testRunner . GetWidgetByName ( expandCheckboxButtonName , out _ ) ;
var checkBox = mirrorPanel . Children < ExpandCheckboxButton > ( ) . FirstOrDefault ( ) ;
if ( checkBox ? . Checked ! = true )
{
testRunner . ClickByName ( expandCheckboxButtonName ) ;
}
}
2017-03-15 16:17:06 -07:00
public static void Select3DPart ( this AutomationRunner testRunner , string partNameToSelect )
{
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" ) ;
}
2017-07-11 08:10:57 -07:00
testRunner . DragDropByName ( "InteractionLayer" , "InteractionLayer" , offsetDrop : new Agg . Point2D ( 10 , 15 ) , mouseButtons : MouseButtons . Right ) ;
2017-03-15 16:17:06 -07:00
testRunner . Delay ( 1 ) ;
testRunner . ClickByName ( partNameToSelect ) ;
}
2018-02-08 15:42:07 -08:00
public static void 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 ) ;
2018-02-08 15:42:07 -08:00
}
2018-04-19 08:02:21 -07:00
public static void OpenEmptyPartTab ( this AutomationRunner testRunner )
2018-04-19 07:58:03 -07:00
{
2018-10-17 17:26:29 -07:00
// Latest product starts at empty part tab
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 ) ;
}
}
2017-06-02 19:57:15 -07:00
public static Emulator LaunchAndConnectToPrinterEmulator ( this AutomationRunner testRunner , string make = "Airwolf 3D" , string model = "HD" , bool runSlow = false )
2016-09-14 15:50:24 -07:00
{
2018-02-08 15:42:07 -08:00
SystemWindow systemWindow ;
2018-10-10 12:15:30 -07:00
testRunner . GetWidgetByName ( "Hardware Tab" , out 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
2017-06-04 09:01:56 -07:00
testRunner . AddAndSelectPrinter ( make , model ) ;
2016-09-19 14:46:47 -07:00
2017-07-01 18:25:53 -07:00
// Force the configured printer to use the emulator driver
2018-10-05 09:24:57 -07:00
ApplicationController . Instance . ActivePrinter . Settings . SetValue ( "driver_type" , "Emulator" ) ;
2016-09-14 15:50:24 -07:00
2016-09-19 14:46:47 -07:00
// edit the com port
2017-12-28 09:02:44 -08:00
testRunner . SwitchToPrinterSettings ( ) ;
2017-09-22 23:28:00 -07:00
var serialPortDropDown = testRunner . GetWidgetByName ( "com_port Field" , out _ , 1 ) ;
2017-01-06 16:54:34 -08:00
2017-12-15 20:24:58 -08:00
testRunner . WaitFor ( ( ) = > serialPortDropDown . Enabled ) ; // Wait until the serialPortDropDown is ready to click it. Ensures the printer is loaded.
2016-09-19 14:46:47 -07:00
2017-09-22 23:28:00 -07:00
testRunner . ClickByName ( "com_port Field" ) ;
2016-09-19 14:46:47 -07:00
2017-07-01 18:25:53 -07:00
testRunner . ClickByName ( "Emulator Menu Item" ) ;
2016-09-19 14:46:47 -07:00
// connect to the created printer
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Connect to printer button" ) ;
2016-09-19 14:46:47 -07:00
2017-06-14 14:02:29 -07:00
testRunner . WaitForName ( "Disconnect from printer button" ) ;
2016-09-19 14:46:47 -07: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
2017-02-01 10:20:50 -08:00
public static void CancelPrint ( this AutomationRunner testRunner )
{
2017-12-14 21:59:41 -08:00
// TODO: Improve this to more accurately find the print task row and click its Stop button
testRunner . ClickByName ( "Stop Task Button" ) ;
2017-02-01 10:20:50 -08:00
if ( testRunner . WaitForName ( "Yes Button" , 1 ) )
{
testRunner . ClickByName ( "Yes Button" ) ;
}
}
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
emulator . ZPositionChanged + = ( s , e ) = >
{
// 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'
if ( emulator . ZPosition > = heightAtTargetLayer )
{
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 )
{
// delete printer
2017-08-30 16:43:58 -07:00
testRunner . ClickByName ( "Printer Overflow Menu" ) ;
testRunner . ClickByName ( "Delete Printer Menu Item" ) ;
2016-11-05 11:12:20 -07:00
2017-06-14 09:56:51 -07:00
testRunner . WaitForReloadAll ( ( ) = > testRunner . ClickByName ( "Yes Button" ) ) ;
2016-09-08 14:20:39 -07:00
}
2018-10-10 13:33:16 -07:00
public static void 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
2018-04-20 12:01:22 -07:00
// make sure we wait for MC to be up and running
testRunner . WaitforDraw ( systemWindow ) ;
2018-10-10 12:15:30 -07:00
// Click 'Add Printer' if not on screen
2018-10-11 17:24:42 -07:00
if ( ! testRunner . NameExists ( "Select Make" , 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
testRunner . ClickByName ( "Hardware Tab" ) ;
testRunner . ClickByName ( "Create Printer" ) ;
}
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
}
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Select Make" ) ;
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > testRunner . WidgetExists < PopupWidget > ( ) ) ;
2016-09-26 15:59:29 -07:00
testRunner . Type ( make ) ;
2016-10-17 11:04:39 -07:00
testRunner . Type ( "{Enter}" ) ;
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > ! testRunner . WidgetExists < PopupWidget > ( ) ) ;
2017-12-07 12:23:28 -08:00
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Select Model" ) ;
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > testRunner . WidgetExists < PopupWidget > ( ) ) ;
2016-12-12 17:33:02 -08:00
testRunner . Type ( model ) ;
testRunner . Type ( "{Enter}" ) ;
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > ! testRunner . WidgetExists < PopupWidget > ( ) ) ;
2016-08-29 17:13:45 -07:00
2016-11-15 15:02:34 -08:00
// An unpredictable period of time will pass between Clicking Save, everything reloading and us returning to the caller.
// Block until ReloadAll has completed then close and return to the caller, at which point hopefully everything is reloaded.
2018-10-17 17:38:49 -07:00
testRunner . ClickByName ( "Next Button" ) ;
2016-08-29 17:13:45 -07:00
2018-02-20 19:20:53 -08:00
testRunner . WaitFor ( ( ) = > testRunner . WidgetExists < SetupStepComPortOne > ( ) ) ;
2017-06-14 09:56:51 -07:00
testRunner . ClickByName ( "Cancel Wizard Button" ) ;
2018-02-20 19:20:53 -08:00
testRunner . WaitFor ( ( ) = > ! testRunner . WidgetExists < SetupStepComPortOne > ( ) ) ;
2016-01-13 10:26:17 -08:00
}
2018-10-11 21:47:19 -07:00
public static void SwitchToHardwareTab ( this AutomationRunner testRunner )
2017-06-04 16:16:07 -07:00
{
2018-10-11 17:24:42 -07:00
testRunner . ClickByName ( "Hardware Tab" ) ;
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++}" ) ;
2016-09-20 09:39:57 -07:00
ApplicationDataStorage . Instance . OverrideAppDataLocation ( tempFolderPath ) ;
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 ) )
{
File . WriteAllText ( mcpPath , JsonConvert . SerializeObject ( new ManifestFile ( )
2016-09-20 14:32:22 -07:00
{
ProjectFiles = new System . Collections . Generic . List < PrintItem > ( )
} , Formatting . Indented ) ) ;
2015-10-22 18:23:22 -07:00
}
var queueItemData = JsonConvert . DeserializeObject < ManifestFile > ( File . ReadAllText ( mcpPath ) ) ;
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 ) ;
}
2018-04-15 14:43:11 -07:00
public static void OpenUserPopupMenu ( this AutomationRunner testRunner )
{
testRunner . ClickByName ( "User Options Menu" ) ;
}
2016-12-01 13:25:17 -08:00
public static void 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
testRunner . EnsureFoldersVisible ( ) ;
switch ( libraryRowItemName )
{
case "Calibration Parts Row Item Collection" :
case "Cloud Library Row Item Collection" :
case "Print Queue Row Item Collection" :
case "Local Library Row Item Collection" :
2018-10-10 22:32:08 -07:00
if ( ! testRunner . NameExists ( "Library Row Item Collection" ) )
{
testRunner . ClickByName ( "Bread Crumb Button Home" ) ;
testRunner . Delay ( ) ;
}
2018-05-04 12:58:38 -07:00
// If visible, navigate into Libraries container before opening target
2018-06-26 11:06:32 -07:00
if ( testRunner . NameExists ( "Library Row Item Collection" ) )
2018-05-04 12:58:38 -07:00
{
testRunner . DoubleClickByName ( "Library Row Item Collection" ) ;
}
break ;
}
2017-05-20 17:47:36 -07:00
testRunner . DoubleClickByName ( libraryRowItemName ) ;
2015-09-01 16:03:29 -07:00
}
2017-10-14 10:53:42 -07:00
public static void EnsureFoldersVisible ( this AutomationRunner testRunner )
2017-08-30 16:43:58 -07:00
{
2018-10-10 22:32:08 -07:00
var checkBox = ( ExpandCheckboxButton ) testRunner . GetWidgetByName ( "Show Folders Toggle" , out _ , secondsToWait : 0.2 ) ;
if ( checkBox ? . Checked = = false )
2017-08-30 16:43:58 -07:00
{
2017-12-08 11:32:05 -08:00
var resetEvent = new AutoResetEvent ( false ) ;
// Wire up event listener
2018-10-24 21:20:56 -07:00
var listView = testRunner . GetWidgetByName ( "LibraryView" , out _ ) as LibraryListView ;
2017-12-08 11:32:05 -08:00
EventHandler contentReloaded = ( s , e ) = >
{
resetEvent . Set ( ) ;
} ;
listView . ContentReloaded + = contentReloaded ;
// Start reload
2017-08-30 16:43:58 -07:00
testRunner . ClickByName ( "Show Folders Toggle" ) ;
2017-12-07 14:54:41 -08:00
2017-12-08 11:32:05 -08:00
// Wait for reload
resetEvent . WaitOne ( ) ;
// Release event listener
listView . ContentReloaded - = contentReloaded ;
}
2017-08-30 16:43:58 -07:00
}
2018-10-10 22:32:08 -07:00
public static void 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
{
2018-10-10 22:32:08 -07:00
testRunner . ClickByName ( "Add Content Menu" ) ;
2017-06-18 10:02:34 -07:00
}
2018-10-10 22:32:08 -07:00
}
2017-06-18 10:02:34 -07:00
2018-10-10 22:32:08 -07:00
public static void NavigateToLibraryHome ( this AutomationRunner testRunner )
{
testRunner . EnsureContentMenuOpen ( ) ;
testRunner . ClickByName ( "Bread Crumb Button Home" ) ;
2017-06-18 10:02:34 -07:00
testRunner . Delay ( . 5 ) ;
}
2018-04-07 11:21:02 -07:00
public static void InvokeLibraryAddDialog ( this AutomationRunner testRunner )
{
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
testRunner . ClickByName ( "Add Menu Item" ) ;
}
public static void InvokeLibraryCreateFolderDialog ( this AutomationRunner testRunner )
{
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
testRunner . ClickByName ( "Create Folder Menu Item" ) ;
}
2018-10-05 14:21:55 -07:00
public static string CreateChildFolder ( this AutomationRunner testRunner , string folderName )
{
testRunner . InvokeLibraryCreateFolderDialog ( ) ;
testRunner . WaitForName ( "InputBoxPage Action Button" ) ;
testRunner . Type ( folderName ) ;
testRunner . ClickByName ( "InputBoxPage Action Button" ) ;
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 ) ;
}
2017-12-06 17:23:21 -08:00
testRunner . Type ( textValue ) ;
2017-12-06 15:21:18 -08:00
testRunner . Type ( "{Enter}" ) ;
2017-12-15 20:29:16 -08:00
testRunner . WaitForWidgetDisappear ( "Automation Dialog TextEdit" , 5 ) ;
2017-12-06 15:21:18 -08:00
}
2017-10-27 14:19:26 -07:00
public static void AddItemToBedplate ( 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 ) ;
}
testRunner . ClickByName ( "Print Library Overflow Menu" ) ;
2017-10-31 11:22:58 -07:00
var view3D = testRunner . GetWidgetByName ( "View3DWidget" , out _ ) as View3DWidget ;
var scene = view3D . InteractionLayer . Scene ;
var preAddCount = scene . Children . Count ( ) ;
2018-10-12 17:25:00 -07:00
testRunner . ClickByName ( "Add to Bed Menu Item" ) ;
2017-10-31 11:22:58 -07:00
// wait for the object to be added
2017-12-15 20:24:58 -08:00
testRunner . 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
}
2017-06-04 08:57:17 -07:00
}
2017-06-06 18:19:02 -07:00
public static void SaveBedplateToFolder ( this AutomationRunner testRunner , string newFileName , string folderName )
{
2018-10-10 22:32:08 -07:00
testRunner . ClickByName ( "Save SplitButton" , offset : new Point2D ( 8 , 0 ) ) ;
2017-06-06 18:19:02 -07:00
testRunner . ClickByName ( "Save As Menu Item" ) ;
testRunner . Delay ( 1 ) ;
testRunner . Type ( newFileName ) ;
testRunner . NavigateToFolder ( folderName ) ;
2017-12-21 10:39:17 -08:00
testRunner . ClickByName ( "Accept Button" ) ;
2017-06-06 18:19:02 -07:00
// Give the SaveAs window time to close before returning to the caller
testRunner . Delay ( 2 ) ;
}
2017-09-16 17:58:46 -07:00
public static void WaitForPrintFinished ( this AutomationRunner testRunner , int maxSeconds = 500 )
2017-06-02 21:20:56 -07:00
{
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > ApplicationController . Instance . ActivePrinter . Connection . CommunicationState = = CommunicationStates . FinishedPrint , maxSeconds ) ;
2017-09-16 17:58:46 -07:00
}
public static void WaitForCommunicationStateDisconnected ( this AutomationRunner testRunner , int maxSeconds = 500 )
{
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > ApplicationController . Instance . ActivePrinter . 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
2017-12-06 15:21:18 -08: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
2018-10-03 12:27:03 -07:00
AggContext . Config . ProviderTypes . SystemWindowProvider = "MatterHackers.Agg.UI.OpenGLWinformsWindowProvider, agg_platform_win32" ;
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
2017-08-20 02:34:39 -07:00
AggContext . StaticData = new FileSystemStaticData ( 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" ) ;
2016-12-07 15:24:48 -08: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 ) ;
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 ,
2017-10-05 18:04:45 -07:00
closeWindow : ( ) = >
2017-06-11 09:58:25 -07:00
{
2017-10-05 18:04:45 -07:00
if ( ApplicationController . Instance . ActivePrinter . Connection . CommunicationState = = CommunicationStates . Printing )
{
ApplicationController . Instance . ActivePrinter . Connection . Disable ( ) ;
}
2017-12-16 19:09:25 -08:00
rootSystemWindow . Close ( ) ;
2017-10-05 18:04:45 -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
2017-09-23 00:26:50 -07:00
public static void StartSlicing ( this AutomationRunner testRunner )
{
testRunner . ClickByName ( "Generate Gcode Button" ) ;
}
2017-12-14 16:19:22 -08:00
/// <summary>
/// Switch to the primary SliceSettings tab
/// </summary>
/// <param name="testRunner"></param>
public static void OpenPrintPopupMenu ( this AutomationRunner testRunner )
2016-09-20 14:32:22 -07:00
{
2017-12-14 16:19:22 -08:00
var printerConnection = ApplicationController . Instance . ActivePrinter . Connection ;
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
2017-12-15 08:54:59 -08:00
// Wait for button to become enabled
var printerPopup = testRunner . GetWidgetByName ( "PrintPopupMenu" , out _ ) ;
2017-12-15 19:28:25 -08:00
testRunner . WaitFor ( ( ) = > printerPopup . Enabled ) ;
2017-12-15 08:54:59 -08:00
2018-10-18 08:19:20 -07:00
// check if the print menu is already open
if ( ! testRunner . NameExists ( "Advanced Section" , . 2 ) )
2018-07-12 11:51:47 -07:00
{
2018-10-18 08:19:20 -07:00
// open it
testRunner . ClickByName ( "PrintPopupMenu" ) ;
if ( ! testRunner . NameExists ( "Layer(s) To Pause Field" , . 2 ) )
{
testRunner . ClickByName ( "Advanced Section" ) ;
}
2018-07-12 11:51:47 -07:00
}
2017-12-14 16:19:22 -08:00
}
2017-06-02 19:39:29 -07:00
2017-12-14 16:19:22 -08:00
/// <summary>
/// Open the Print popup menu and click the Start Print button
/// </summary>
/// <param name="testRunner"></param>
public static void StartPrint ( this AutomationRunner testRunner )
{
testRunner . OpenPrintPopupMenu ( ) ;
testRunner . ClickByName ( "Start Print Button" ) ;
}
2017-06-09 20:12:25 -07:00
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>
/// <param name="testRunner"></param>
public static void SwitchToSliceSettings ( this AutomationRunner testRunner )
{
EnsurePrinterSidebarOpen ( testRunner ) ;
2018-01-07 16:38:43 -08:00
testRunner . ClickByName ( "Slice Settings Tab" ) ;
2017-12-14 16:19:22 -08:00
testRunner . ClickByName ( "General Tab" ) ;
}
2018-10-18 08:19:20 -07:00
public static void Complete9StepLeveling ( this AutomationRunner testRunner , int numUpClicks = 1 )
2018-10-03 12:28:23 -07:00
{
// Helper methods
bool headerExists ( string headerText )
{
var header = testRunner . GetWidgetByName ( "HeaderRow" , out _ ) ;
var textWidget = header . Children < TextWidget > ( ) . FirstOrDefault ( ) ;
return textWidget ? . Text . StartsWith ( headerText ) ? ? false ;
}
void waitForPage ( string headerText )
{
testRunner . WaitFor ( ( ) = > headerExists ( headerText ) ) ;
Assert . IsTrue ( headerExists ( headerText ) , "Expected page not found: " + headerText ) ;
}
void waitForPageAndAdvance ( string headerText )
{
waitForPage ( headerText ) ;
testRunner . ClickByName ( "Next Button" ) ;
}
2018-10-18 08:19:20 -07:00
testRunner . Delay ( ) ;
testRunner . WaitFor ( ( ) = > headerExists ( "Initial Printer Setup" ) ) ;
if ( headerExists ( "Initial Printer Setup" ) )
{
// do print leveling steps
waitForPageAndAdvance ( "Initial Printer Setup" ) ;
}
2018-10-03 12:28:23 -07:00
waitForPageAndAdvance ( "Print Leveling Overview" ) ;
waitForPageAndAdvance ( "Homing The Printer" ) ;
waitForPageAndAdvance ( "Waiting For Printer To Heat" ) ;
for ( int i = 0 ; i < 3 ; i + + )
{
var section = ( i * 3 ) + 1 ;
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
waitForPage ( $"Step {section} of 9" ) ;
testRunner . ClickByName ( "Next Button" ) ;
waitForPage ( $"Step {section + 1} of 9" ) ;
testRunner . ClickByName ( "Next Button" ) ;
waitForPage ( $"Step {section + 2} of 9" ) ;
testRunner . ClickByName ( "Next Button" ) ;
}
testRunner . ClickByName ( "Done Button" ) ;
}
2017-12-28 09:02:44 -08:00
/// <summary>
/// Switch to printer settings
/// </summary>
/// <param name="testRunner"></param>
public static void SwitchToPrinterSettings ( this AutomationRunner testRunner )
{
2018-10-25 07:35:49 -07:00
EnsurePrinterSidebarOpen ( testRunner ) ;
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
{
testRunner . ClickByName ( "Printer Overflow Menu" ) ;
testRunner . ClickByName ( "Configure Printer Menu Item" ) ;
}
2017-12-28 09:02:44 -08:00
testRunner . ClickByName ( "Printer Tab" ) ;
}
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" ) ;
}
2018-02-08 15:42:07 -08:00
public static SliceSettingData NavigateToSliceSettingsField ( this AutomationRunner testRunner , string userLevel , string slicerConfigName )
2018-01-07 14:53:42 -08:00
{
2018-01-13 18:54:40 -08:00
var rootLevel = SettingsOrganizer . Instance . UserLevels [ userLevel ] ;
2018-01-07 14:53:42 -08:00
2018-01-13 18:54:40 -08:00
var settingData = SettingsOrganizer . Instance . GetSettingsData ( slicerConfigName ) ;
2018-01-07 14:53:42 -08:00
var subGroup = rootLevel . GetContainerForSetting ( slicerConfigName ) ;
2018-01-13 18:13:29 -08:00
var category = subGroup . 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
var foundWidget = testRunner . GetWidgetByName ( subGroup . Name + " Panel" , out _ ) ;
if ( foundWidget ! = null )
{
var containerCheckBox = foundWidget . Descendants < ExpandCheckboxButton > ( ) . First ( ) ;
if ( ! containerCheckBox . Checked )
{
containerCheckBox . Checked = true ;
testRunner . Delay ( ) ;
}
}
return settingData ;
}
public static void SelectSliceSettingsField ( this AutomationRunner testRunner , string userLevel , string slicerConfigName )
{
var settingData = NavigateToSliceSettingsField ( testRunner , userLevel , slicerConfigName ) ;
2018-01-07 14:53:42 -08:00
// Click field
testRunner . ClickByName ( $"{settingData.PresentationName} Field" ) ;
}
2017-12-14 16:19:22 -08:00
/// <summary>
/// Switch to Printer -> Controls
/// </summary>
/// <param name="testRunner"></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
EnsurePrinterSidebarOpen ( testRunner ) ;
2018-09-10 10:42:18 -07:00
if ( ! testRunner . NameExists ( "Controls Tab" , 0.2 ) )
{
testRunner . ClickByName ( "Printer Overflow Menu" ) ;
testRunner . ClickByName ( "Show Controls Menu Item" ) ;
}
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>
/// <param name="testRunner"></param>
public static void SwitchToTerminalTab ( this AutomationRunner testRunner )
{
// Change to Printer Controls
EnsurePrinterSidebarOpen ( testRunner ) ;
if ( ! testRunner . NameExists ( "Terminal Tab" , 0.2 ) )
{
testRunner . ClickByName ( "Printer Overflow Menu" ) ;
testRunner . ClickByName ( "Show Terminal Menu Item" ) ;
}
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>
/// <param name="testRunner"></param>
public static void SwitchToGCodeTab ( this AutomationRunner testRunner )
{
testRunner . ClickByName ( "Layers3D Button" ) ;
// TODO: Remove workaround needed to force GCode options to appear {{
testRunner . AddItemToBedplate ( ) ;
testRunner . ClickByName ( "Generate Gcode Button" ) ;
// TODO: Remove workaround needed to force GCode options to appear }}
}
2017-12-14 16:19:22 -08:00
private static void EnsurePrinterSidebarOpen ( AutomationRunner testRunner )
2017-06-13 13:22:22 -07:00
{
// If the sidebar exists, we need to expand and pin it
if ( testRunner . WaitForName ( "Slice Settings Sidebar" , 0.2 ) )
{
testRunner . ClickByName ( "Slice Settings Sidebar" ) ;
testRunner . ClickByName ( "Pin Settings Button" ) ;
}
}
2017-06-04 08:22:04 -07:00
/// <summary>
/// Adds the given asset names to the local library and validates the result
/// </summary>
/// <param name="testRunner"></param>
/// <param name="assetNames">The test assets to add to the library</param>
2018-11-02 07:35:26 -07:00
public static void 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 ) ;
2017-09-23 12:23:48 -07:00
Assert . IsTrue ( testRunner . WaitForName ( $"Row Item {friendlyName}" ) , $"{friendlyName} part should exist after adding" ) ;
2017-06-04 08:22:04 -07:00
}
}
2017-06-06 18:42:44 -07:00
/// <summary>
/// Control clicks each specified item
/// </summary>
/// <param name="testRunner"></param>
/// <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 ) ;
}
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
{
private static readonly string configPath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) , "MHTest.config" ) ;
/// <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 ;
if ( ! File . Exists ( configPath ) )
{
config = new TestAutomationConfig ( ) ;
config . Save ( ) ;
}
else
{
config = JsonConvert . DeserializeObject < TestAutomationConfig > ( File . ReadAllText ( configPath ) ) ;
}
return config ;
}
/// <summary>
/// Persist the current settings to the 'MHTest.config' in the user profile - %userprofile%\MHTest.config
/// </summary>
public void Save ( )
{
File . WriteAllText ( configPath , JsonConvert . SerializeObject ( this , Formatting . Indented ) ) ;
}
}
2015-05-07 19:57:33 -07:00
}