Move MatterControl source code into a subdirectory
This commit is contained in:
parent
2c6e34243a
commit
70af2d9ae8
2007 changed files with 13 additions and 8 deletions
|
|
@ -0,0 +1,195 @@
|
|||
using MatterHackers.Agg;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.VectorMath;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class CameraFittingUtilTests
|
||||
{
|
||||
private const string CoinName = "MatterControl - Coin.stl";
|
||||
|
||||
static Task DoZoomToSelectionTest(bool ortho, bool wideObject)
|
||||
{
|
||||
return MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab(removeDefaultPhil: wideObject);
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
if (wideObject)
|
||||
AddCoinToBed(testRunner, scene);
|
||||
|
||||
if (ortho)
|
||||
{
|
||||
testRunner.ClickByName("Projection mode button");
|
||||
Assert.IsTrue(!view3D.TrackballTumbleWidget.PerspectiveMode);
|
||||
testRunner.Delay(1);
|
||||
Assert.IsTrue(!view3D.TrackballTumbleWidget.PerspectiveMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(view3D.TrackballTumbleWidget.PerspectiveMode);
|
||||
}
|
||||
|
||||
Vector3[] lookAtDirFwds = new Vector3[] {
|
||||
new Vector3(0, 0, -1),
|
||||
new Vector3(0, 0, 1),
|
||||
new Vector3(0, 1, 0),
|
||||
new Vector3(1, 1, 0),
|
||||
new Vector3(-1, -1, 0),
|
||||
new Vector3(0, 1, 1),
|
||||
new Vector3(1, 1, 1),
|
||||
new Vector3(0, 1, -1),
|
||||
new Vector3(1, 1, -1),
|
||||
};
|
||||
|
||||
const int topI = 0;
|
||||
const int bottomI = 1;
|
||||
|
||||
for (int i = 0; i < lookAtDirFwds.Length; ++i)
|
||||
{
|
||||
Vector3 lookAtDirFwd = lookAtDirFwds[i];
|
||||
Vector3 lookAtDirRight = (i == topI ? -Vector3.UnitY : i == bottomI ? Vector3.UnitY : -Vector3.UnitZ).Cross(lookAtDirFwd);
|
||||
Vector3 lookAtDirUp = lookAtDirRight.Cross(lookAtDirFwd).GetNormal();
|
||||
|
||||
var look = Matrix4X4.LookAt(Vector3.Zero, lookAtDirFwd, lookAtDirUp);
|
||||
|
||||
view3D.TrackballTumbleWidget.AnimateRotation(look);
|
||||
testRunner.Delay(0.5);
|
||||
|
||||
testRunner.ClickByName("Zoom to selection button");
|
||||
testRunner.Delay(0.5);
|
||||
|
||||
var part = testRunner.GetObjectByName(wideObject ? CoinName : "Phil A Ment.stl", out _) as IObject3D;
|
||||
AxisAlignedBoundingBox worldspaceAABB = part.GetAxisAlignedBoundingBox();
|
||||
|
||||
Vector2 viewportSize = new Vector2(view3D.TrackballTumbleWidget.Width, view3D.TrackballTumbleWidget.Height);
|
||||
RectangleDouble rect = view3D.TrackballTumbleWidget.WorldspaceAabbToBottomScreenspaceRectangle(worldspaceAABB);
|
||||
Vector2 screenspacePositionOfWorldspaceCenter = view3D.TrackballTumbleWidget.WorldspaceToBottomScreenspace(worldspaceAABB.Center).Xy;
|
||||
double marginPixels = CameraFittingUtil.MarginScale * Math.Min(viewportSize.X, viewportSize.Y);
|
||||
|
||||
const double pixelTolerance = 1e-3;
|
||||
|
||||
// Check that the full object is visible.
|
||||
Assert.IsTrue(rect.Left > -pixelTolerance);
|
||||
Assert.IsTrue(rect.Bottom > -pixelTolerance);
|
||||
Assert.IsTrue(rect.Right < viewportSize.X + pixelTolerance);
|
||||
Assert.IsTrue(rect.Top < viewportSize.Y + pixelTolerance);
|
||||
|
||||
// Check for centering.
|
||||
|
||||
bool isPerspectiveFittingWithinMargin =
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.Sphere ||
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.CenterOnWorldspaceAABB ||
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.CenterOnViewspaceAABB ||
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.IntersectionOfBoundingPlanesWithApproxCentering ||
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.IntersectionOfBoundingPlanesWithPerfectCentering;
|
||||
|
||||
// Tightly bounded. At least one axis should be bounded by the margin.
|
||||
bool isPerspectiveFittingBoundedByMargin =
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.IntersectionOfBoundingPlanesWithApproxCentering ||
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.IntersectionOfBoundingPlanesWithPerfectCentering;
|
||||
|
||||
bool perspectiveFittingWillCenterTheAABBCenter =
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.Sphere ||
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.CenterOnWorldspaceAABB ||
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.CenterOnViewspaceAABB;
|
||||
|
||||
bool perspectiveFittingWillCenterTheScreenspaceAABB =
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm == CameraFittingUtil.EPerspectiveFittingAlgorithm.IntersectionOfBoundingPlanesWithPerfectCentering;
|
||||
|
||||
// Always get the same result.
|
||||
bool isPerspectiveFittingStable =
|
||||
CameraFittingUtil.PerspectiveFittingAlgorithm != CameraFittingUtil.EPerspectiveFittingAlgorithm.TrialAndError;
|
||||
|
||||
bool isXWorldspaceCentered = MathHelper.AlmostEqual(viewportSize.X / 2, screenspacePositionOfWorldspaceCenter.X, pixelTolerance);
|
||||
bool isYWorldspaceCentered = MathHelper.AlmostEqual(viewportSize.Y / 2, screenspacePositionOfWorldspaceCenter.Y, pixelTolerance);
|
||||
|
||||
bool isXMarginBounded = MathHelper.AlmostEqual(rect.Left, marginPixels, 1e-3) && MathHelper.AlmostEqual(rect.Right, viewportSize.X - marginPixels, pixelTolerance);
|
||||
bool isYMarginBounded = MathHelper.AlmostEqual(rect.Bottom, marginPixels, 1e-3) && MathHelper.AlmostEqual(rect.Top, viewportSize.Y - marginPixels, pixelTolerance);
|
||||
|
||||
bool isXWithinMargin = rect.Left > marginPixels - 1 && rect.Right < viewportSize.X - (marginPixels - 1);
|
||||
bool isYWithinMargin = rect.Bottom > marginPixels - 1 && rect.Top < viewportSize.Y - (marginPixels - 1);
|
||||
|
||||
bool isXScreenspaceCentered = MathHelper.AlmostEqual(viewportSize.X / 2, (rect.Left + rect.Right) / 2, pixelTolerance);
|
||||
bool isYScreenspaceCentered = MathHelper.AlmostEqual(viewportSize.Y / 2, (rect.Bottom + rect.Top) / 2, pixelTolerance);
|
||||
|
||||
if (ortho)
|
||||
{
|
||||
// Ortho fitting will always center the screenspace AABB and the center of the object AABB.
|
||||
Assert.IsTrue(isXWorldspaceCentered && isYWorldspaceCentered);
|
||||
Assert.IsTrue(isXMarginBounded || isYMarginBounded);
|
||||
Assert.IsTrue(isXWithinMargin && isYWithinMargin);
|
||||
Assert.IsTrue(isXScreenspaceCentered && isYScreenspaceCentered);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isPerspectiveFittingWithinMargin)
|
||||
Assert.IsTrue(isXWithinMargin && isYWithinMargin);
|
||||
|
||||
if (isPerspectiveFittingBoundedByMargin)
|
||||
Assert.IsTrue(isXMarginBounded || isYMarginBounded);
|
||||
|
||||
if (perspectiveFittingWillCenterTheAABBCenter)
|
||||
Assert.IsTrue(isXWorldspaceCentered && isYWorldspaceCentered);
|
||||
|
||||
if (perspectiveFittingWillCenterTheScreenspaceAABB)
|
||||
Assert.IsTrue(isXScreenspaceCentered && isYScreenspaceCentered);
|
||||
}
|
||||
|
||||
if (ortho || isPerspectiveFittingStable)
|
||||
{
|
||||
testRunner.ClickByName("Zoom to selection button");
|
||||
testRunner.Delay(1);
|
||||
|
||||
RectangleDouble rect2 = view3D.TrackballTumbleWidget.WorldspaceAabbToBottomScreenspaceRectangle(worldspaceAABB);
|
||||
Assert.IsTrue(rect2.Equals(rect, pixelTolerance));
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 60 * 3, overrideWidth: 1300, overrideHeight: 800);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public Task OrthographicZoomToSelectionWide()
|
||||
{
|
||||
return DoZoomToSelectionTest(true, true);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public Task OrthographicZoomToSelectionTall()
|
||||
{
|
||||
return DoZoomToSelectionTest(true, false);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public Task PerspectiveZoomToSelectionWide()
|
||||
{
|
||||
return DoZoomToSelectionTest(false, true);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public Task PerspectiveZoomToSelectionTall()
|
||||
{
|
||||
return DoZoomToSelectionTest(false, false);
|
||||
}
|
||||
|
||||
private static void AddCoinToBed(AutomationRunner testRunner, InteractiveScene scene)
|
||||
{
|
||||
testRunner.AddItemToBed(partName: "Row Item MatterControl - Coin.stl")
|
||||
.Delay(.1)
|
||||
.ClickByName(CoinName, offset: new Point2D(-4, 0));
|
||||
Assert.IsNotNull(scene.SelectedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Copyright (c) 2014, Lars Brubaker
|
||||
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.
|
||||
*/
|
||||
|
||||
using MatterHackers.Agg.UI;
|
||||
using NUnit.Framework;
|
||||
using System.Threading.Tasks;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation")]
|
||||
public class CreateLibraryFolder
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task CreateFolderStartsWithTextFieldFocusedAndEditable()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
testRunner.NavigateToFolder("Local Library Row Item Collection");
|
||||
testRunner.InvokeLibraryCreateFolderDialog();
|
||||
|
||||
testRunner.Delay(.5);
|
||||
testRunner.Type("Test Text");
|
||||
testRunner.Delay(.5);
|
||||
|
||||
var textWidgetMH = testRunner.GetWidgetByName("InputBoxPage TextEditWidget", out _) as ThemedTextEditWidget;
|
||||
|
||||
Assert.IsTrue(textWidgetMH != null, "Found Text Widget");
|
||||
Assert.IsTrue(textWidgetMH.Text == "Test Text", "Had the right text");
|
||||
|
||||
testRunner.ClickByName("Cancel Wizard Button");
|
||||
testRunner.Delay(.5);
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.DesignTools;
|
||||
using MatterHackers.MatterControl.DesignTools.Operations;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.VectorMath;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture]
|
||||
public class SheetDataTests
|
||||
{
|
||||
[Test]
|
||||
public void Calculations()
|
||||
{
|
||||
var sheetData = new SheetData(4, 4);
|
||||
|
||||
void Test(string cell, string expression, string expected)
|
||||
{
|
||||
sheetData[cell].Expression = expression;
|
||||
sheetData.Recalculate();
|
||||
Assert.AreEqual(expected, sheetData.GetCellValue(cell));
|
||||
}
|
||||
|
||||
// simple multiply retrived upper and lower case
|
||||
Test("A1", "=4*2", "8");
|
||||
Test("a1", "=4*2", "8");
|
||||
|
||||
// make sure functions are working, max in this case
|
||||
Test("a2", "=max(4, 5)", "5");
|
||||
|
||||
// make sure cell references are working
|
||||
Test("a3", "=a1+a2", "13");
|
||||
|
||||
// complex formulas are working
|
||||
Test("a4", "=((4+5)/3+7)/5", "2");
|
||||
|
||||
// complex formulas with references are working
|
||||
Test("b1", "=(a4+a3)*.5", "7.5");
|
||||
|
||||
// constants work, like pi
|
||||
Test("b2", "=pi", "3.141592653589793");
|
||||
|
||||
// check that we get string data back unmodified
|
||||
Test("b3", "hello", "hello");
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class PrimitiveAndSheetsTests
|
||||
{
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
StaticData.RootPath = MatterControlUtilities.StaticDataPath;
|
||||
MatterControlUtilities.OverrideAppDataLocation(MatterControlUtilities.RootPath);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public void SheetEditorLayoutAndNavigation()
|
||||
{
|
||||
var systemWindow = new SystemWindow(800, 600)
|
||||
{
|
||||
Name = "Main Window",
|
||||
};
|
||||
|
||||
InternalTextEditWidget.AddTextWidgetRightClickMenu(ApplicationController.Instance.MenuTheme);
|
||||
|
||||
AutomationRunner.TimeToMoveMouse = .1;
|
||||
|
||||
var sheetData = new SheetData(5, 5);
|
||||
var undoBuffer = new UndoBuffer();
|
||||
var theme = ApplicationController.Instance.Theme;
|
||||
var sheetEditor = new SheetEditorWidget(sheetData, null, undoBuffer, theme);
|
||||
|
||||
systemWindow.AddChild(sheetEditor);
|
||||
|
||||
AutomationRunner.ShowWindowAndExecuteTests(systemWindow, testRunner =>
|
||||
{
|
||||
testRunner.Delay(1);
|
||||
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
2000);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DimensionsWorkWhenNoSheet()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var primitive = "Cube";
|
||||
var primitiveName = "Row Item " + primitive;
|
||||
testRunner.DoubleClickByName(primitiveName);
|
||||
|
||||
// Get View3DWidget
|
||||
View3DWidget view3D = testRunner.GetWidgetByName("View3DWidget", out var window, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.WaitForName(primitive);
|
||||
Assert.AreEqual(1, scene.Children.Count, "Should have 1 part");
|
||||
|
||||
var cube = testRunner.GetObjectByName(primitive, out _) as CubeObject3D;
|
||||
|
||||
Assert.AreEqual(20, cube.Width.Value(cube), .001);
|
||||
|
||||
// Select scene object
|
||||
testRunner.Select3DPart(primitive);
|
||||
|
||||
// Scale it wider
|
||||
testRunner.DragDropByName("ScaleWidthRight",
|
||||
"ScaleWidthRight",
|
||||
offsetDrag: new Point2D(0, 0),
|
||||
offsetDrop: new Point2D(0, 10));
|
||||
Assert.Greater(cube.Width.Value(cube), 20.0);
|
||||
|
||||
testRunner.ClickByName("3D View Undo");
|
||||
Assert.AreEqual(20, cube.Width.Value(cube), .0001);
|
||||
|
||||
// try scaling by text entry
|
||||
testRunner.ClickByName("ScaleWidthLeft")
|
||||
.ClickByName("XValueDisplay")
|
||||
//.Assert(() => testRunner.GetWidgetByName("XValueDisplay", out var _).ContainsFocus, "Focus") // Sometimes, when the moves over to XValueDisplay, XValueDisplay just isn't there.
|
||||
.Type("35")
|
||||
//.Assert(() => ((CustomWidgets.InlineEditControl)testRunner.GetWidgetByName("XValueDisplay", out var _)).Value == 35, "text")
|
||||
.Type("{Enter}");
|
||||
//.WaitFor(() => 35 == cube.Width.Value(cube));
|
||||
|
||||
/*if (35 != cube.Width.Value(cube))
|
||||
{
|
||||
System.Diagnostics.Debugger.Launch();
|
||||
System.Diagnostics.Debugger.Break();
|
||||
}*/
|
||||
|
||||
// NOTE: Happened once: Expected: 35, But was: 20.0d
|
||||
// This can happen when running only this test, and alt-tabbing frequently.
|
||||
// Failure again after platform focus fix.
|
||||
// This can happen when running only this test, and not alt-tabbing frequently.
|
||||
// Failure can happen in original .NET Framework MatterControl testing too.
|
||||
// Possible cause is OnMouseMove(MatterHackers.Agg.UI.MouseEventArgs) (MatterHackers.MatterControl.PartPreviewWindow.Object3DControlsLayer) not updating the hover control in time.
|
||||
Assert.AreEqual(35, cube.Width.Value(cube));
|
||||
|
||||
testRunner.ClickByName("3D View Undo");
|
||||
Assert.AreEqual(20, cube.Width.Value(cube), .0001);
|
||||
|
||||
// try scaling by text entry of an equation
|
||||
testRunner.ClickByName("Width Field")
|
||||
.Type("=40 + 5")
|
||||
.Type("{Enter}");
|
||||
|
||||
Assert.AreEqual(45, cube.Width.Value(cube));
|
||||
|
||||
// Select Nothing
|
||||
testRunner.ClickByName("View3DWidget");
|
||||
testRunner.SelectNone();
|
||||
Assert.AreEqual(null, scene.SelectedItem);
|
||||
// and re-select the object
|
||||
testRunner.SelectAll();
|
||||
Assert.AreEqual(1, scene.Children.Count);
|
||||
Assert.AreEqual(cube, scene.SelectedItem);
|
||||
|
||||
// now that has an equation in the width it should not have an x edge controls
|
||||
Assert.IsFalse(testRunner.NameExists("ScaleWidthRight", .2));
|
||||
|
||||
testRunner.ClickByName("3D View Undo");
|
||||
Assert.AreEqual(20, cube.Width.Value(cube), .0001);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300, maxTimeToRun: 60);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ScaleObjectWorksWithAndWithoutSheet()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var primitive = "Cube";
|
||||
var primitiveName = "Row Item " + primitive;
|
||||
testRunner.DoubleClickByName(primitiveName);
|
||||
|
||||
// Get View3DWidget
|
||||
View3DWidget view3D = testRunner.GetWidgetByName("View3DWidget", out _, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.WaitForName(primitive);
|
||||
Assert.AreEqual(1, scene.Children.Count, "Should have 1 part");
|
||||
|
||||
var cube = testRunner.GetObjectByName(primitive, out _) as CubeObject3D;
|
||||
|
||||
Assert.AreEqual(20, cube.Width.Value(cube));
|
||||
|
||||
// Select scene object and add a scale
|
||||
testRunner.Select3DPart(primitive)
|
||||
.ClickByName("Scale Inner SplitButton")
|
||||
.ClickByName("Width Edit")
|
||||
.Type("25")
|
||||
.Type("{Enter}")
|
||||
.Delay();
|
||||
|
||||
var scale = testRunner.GetObjectByName("Scale", out _) as ScaleObject3D_3;
|
||||
var scaleAabb = scale.GetAxisAlignedBoundingBox(Matrix4X4.Identity);
|
||||
Assert.AreEqual(25, scaleAabb.XSize);
|
||||
|
||||
// add a scale to the object
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300, maxTimeToRun: 60);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public void SheetEditorNavigationTests()
|
||||
{
|
||||
var systemWindow = new SystemWindow(800, 600)
|
||||
{
|
||||
Name = "Main Window",
|
||||
};
|
||||
|
||||
InternalTextEditWidget.AddTextWidgetRightClickMenu(ApplicationController.Instance.MenuTheme);
|
||||
|
||||
AutomationRunner.TimeToMoveMouse = .1;
|
||||
|
||||
var theme = ApplicationController.Instance.Theme;
|
||||
var container = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
HAnchor = HAnchor.Stretch,
|
||||
VAnchor = VAnchor.Stretch,
|
||||
};
|
||||
systemWindow.AddChild(container);
|
||||
|
||||
var sheetData = new SheetData(5, 5);
|
||||
var undoBuffer = new UndoBuffer();
|
||||
var sheetEditorWidget = new SheetEditorWidget(sheetData, null, undoBuffer, theme);
|
||||
|
||||
container.AddChild(sheetEditorWidget);
|
||||
|
||||
systemWindow.RunTest(testRunner =>
|
||||
{
|
||||
//testRunner.Delay(60);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
2000);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RunnerX
|
||||
{
|
||||
public static Task RunTest(this SystemWindow systemWindow, AutomationTest automationTest, int timeout)
|
||||
{
|
||||
return AutomationRunner.ShowWindowAndExecuteTests(systemWindow, automationTest, timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation")]
|
||||
public class ExportGcodeFromExportWindow
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ExportAsGcode()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw()
|
||||
.AddAndSelectPrinter("Airwolf 3D", "HD")
|
||||
//Navigate to Downloads Library Provider
|
||||
.NavigateToFolder("Queue Row Item Collection")
|
||||
.InvokeLibraryAddDialog();
|
||||
|
||||
//Get parts to add
|
||||
string rowItemPath = MatterControlUtilities.GetTestItemPath("Batman.stl");
|
||||
testRunner.Delay()
|
||||
.Type(MatterControlUtilities.GetTestItemPath("Batman.stl"))
|
||||
.Delay()
|
||||
.Type("{Enter}")
|
||||
//Get test results
|
||||
.ClickByName("Row Item Batman.stl")
|
||||
.ClickByName("Print Library Overflow Menu")
|
||||
.ClickByName("Export Menu Item")
|
||||
.WaitForName("Export Item Window");
|
||||
|
||||
string gcodeOutputPath = MatterControlUtilities.PathToExportGcodeFolder;
|
||||
Directory.CreateDirectory(gcodeOutputPath);
|
||||
string fullPathToGcodeFile = Path.Combine(gcodeOutputPath, "Batman");
|
||||
|
||||
testRunner.ClickByName("Machine File (G-Code) Button")
|
||||
.ClickByName("Export Button")
|
||||
.Delay()
|
||||
.Type(fullPathToGcodeFile)
|
||||
.Type("{Enter}")
|
||||
.Assert(() => File.Exists(fullPathToGcodeFile + ".gcode"), "Exported file not found");
|
||||
|
||||
// add an item to the bed, and export it to gcode
|
||||
fullPathToGcodeFile = Path.Combine(gcodeOutputPath, "Cube");
|
||||
testRunner.AddItemToBed()
|
||||
.ClickByName("PrintPopupMenu")
|
||||
.ClickByName("Export GCode Button")
|
||||
.Type(fullPathToGcodeFile)
|
||||
.Type("{Enter}")
|
||||
.Assert(() => File.Exists(fullPathToGcodeFile + ".gcode"), "Exported file not found");
|
||||
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ExportDesignTabAsSTL()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
// save from design tab
|
||||
var gcodeOutputPath = MatterControlUtilities.PathToExportGcodeFolder;
|
||||
var fullPathToGcodeFile = Path.Combine(gcodeOutputPath, "Cube2");
|
||||
Directory.CreateDirectory(gcodeOutputPath);
|
||||
testRunner.EnsureWelcomePageClosed()
|
||||
.ClickByName("Create New")
|
||||
.AddItemToBed()
|
||||
.ClickByName("Bed Options Menu")
|
||||
.ClickByName("Export Menu Item")
|
||||
.WaitForName("Export Item Window");
|
||||
|
||||
testRunner.ClickByName("STL File Button")
|
||||
.ClickByName("Export Button")
|
||||
.Delay()
|
||||
.Type(fullPathToGcodeFile)
|
||||
.Type("{Enter}")
|
||||
.WaitFor(() => File.Exists(fullPathToGcodeFile + ".stl"), 10);
|
||||
|
||||
testRunner.WaitFor(() => File.Exists(fullPathToGcodeFile + ".stl"), 10);
|
||||
Assert.IsTrue(File.Exists(fullPathToGcodeFile + ".stl"), "Exported file not found");
|
||||
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ExportStreamG92HandlingTest()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
testRunner.CloneAndSelectPrinter("No Retraction after Purge");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
//Navigate to Downloads Library Provider
|
||||
testRunner.NavigateToFolder("Queue Row Item Collection");
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
|
||||
//Get parts to add
|
||||
string rowItemPath = MatterControlUtilities.GetTestItemPath("Batman.stl");
|
||||
testRunner.Delay()
|
||||
.Type(MatterControlUtilities.GetTestItemPath("Batman.stl"))
|
||||
.Delay()
|
||||
.Type("{Enter}");
|
||||
|
||||
//Get test results
|
||||
testRunner.ClickByName("Row Item Batman.stl")
|
||||
.ClickByName("Print Library Overflow Menu")
|
||||
.ClickByName("Export Menu Item")
|
||||
.WaitForName("Export Item Window");
|
||||
|
||||
testRunner.ClickByName("Machine File (G-Code) Button")
|
||||
.ClickByName("Export Button");
|
||||
|
||||
string gcodeOutputPath = MatterControlUtilities.PathToExportGcodeFolder;
|
||||
|
||||
Directory.CreateDirectory(gcodeOutputPath);
|
||||
|
||||
string fullPathToGcodeFile = Path.Combine(gcodeOutputPath, "Batman");
|
||||
testRunner.Type(fullPathToGcodeFile);
|
||||
testRunner.Type("{Enter}");
|
||||
|
||||
var filename = fullPathToGcodeFile + ".gcode";
|
||||
testRunner.WaitFor(() => File.Exists(filename), 10)
|
||||
.WaitFor(() => !IsFileLocked(filename), 1000)
|
||||
.Delay(2);
|
||||
|
||||
// validate that the actual printer output has the right lines
|
||||
var expectedLines = new string[]
|
||||
{
|
||||
"G28 ; home all axes",
|
||||
"M280 P0 S160",
|
||||
"G4 P400",
|
||||
"M280 P0 S90",
|
||||
"M109 S205",
|
||||
"G1 X5 Y5 Z3.13 F1800",
|
||||
"G92 E0 ; Purge line",
|
||||
"G1 X5.83 Z3.04 E0.833 F900",
|
||||
"G1 X6.67 Z2.96 E1.667",
|
||||
"G1 X7.5 Z2.87 E2.5",
|
||||
"G1 X8.33 Z2.79 E3.333",
|
||||
"G1 X9.17 Z2.7 E4.167",
|
||||
"G1 X10 Z2.62 E5",
|
||||
"G92 E0 ; Purge line",
|
||||
"G1 E-2 F2400",
|
||||
"M75 ; start print timer",
|
||||
};
|
||||
|
||||
var actualLines = File.ReadAllLines(filename);
|
||||
ValidateLinesStartingWithFirstExpected(expectedLines, actualLines);
|
||||
|
||||
// make sure the file has the expected header
|
||||
|
||||
return Task.FromResult(0);
|
||||
}, maxTimeToRun: 200);
|
||||
}
|
||||
|
||||
private bool IsFileLocked(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (FileStream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None))
|
||||
{
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
//the file is unavailable because it is:
|
||||
//still being written to
|
||||
//or being processed by another thread
|
||||
//or does not exist (has already been processed)
|
||||
return true;
|
||||
}
|
||||
|
||||
//file is not locked
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ValidateLinesStartingWithFirstExpected(string[] expectedLines, string[] actualLines)
|
||||
{
|
||||
// search actual lines until we find the first expectedLine
|
||||
for (int i = 0; i < actualLines.Length; i++)
|
||||
{
|
||||
if (actualLines[i] == expectedLines[0])
|
||||
{
|
||||
for (int j = 0; j < expectedLines.Length; j++)
|
||||
{
|
||||
Assert.AreEqual(expectedLines[j], actualLines[i + j], "All lines should match");
|
||||
// Debug.WriteLine("\"" + actualLines[i + j] + "\",");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Did not find the first expected line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class HardwareLevelingUITests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task HasHardwareLevelingHidesLevelingSettings()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
// Add printer that has hardware leveling
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
|
||||
testRunner.SwitchToPrinterSettings();
|
||||
testRunner.ClickByName("Features SliceSettingsTab");
|
||||
testRunner.ClickByName("Slice Settings Overflow Menu");
|
||||
testRunner.ClickByName("Advanced Menu Item");
|
||||
Assert.IsFalse(testRunner.WaitForName("print_leveling_solution Row", .5), "Print leveling should not exist for an Airwolf HD");
|
||||
|
||||
// Add printer that does not have hardware leveling
|
||||
testRunner.AddAndSelectPrinter("3D Factory", "MendelMax 1.5");
|
||||
|
||||
testRunner.SwitchToPrinterSettings();
|
||||
testRunner.ClickByName("Features SliceSettingsTab");
|
||||
testRunner.ClickByName("Slice Settings Overflow Menu");
|
||||
testRunner.ClickByName("Advanced Menu Item");
|
||||
Assert.IsTrue(testRunner.WaitForName("print_leveling_solution Row"), "Print leveling should exist for a 3D Factory MendelMax");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideHeight: 800);
|
||||
}
|
||||
|
||||
// NOTE: This test once failed, due to timing probably.
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task SoftwareLevelingTest()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// make a jump start printer
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator("JumpStart", "V1", runSlow: false))
|
||||
{
|
||||
// make sure it is showing the correct button
|
||||
testRunner.OpenPrintPopupMenu();
|
||||
|
||||
var startPrintButton = testRunner.GetWidgetByName("Start Print Button", out _);
|
||||
|
||||
Assert.IsFalse(startPrintButton.Enabled, "Start Print should not be enabled");
|
||||
|
||||
testRunner.ClickByName("SetupPrinter");
|
||||
|
||||
testRunner.Complete9StepLeveling();
|
||||
|
||||
// Satisfy non-empty bed requirement
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
testRunner.OpenPrintPopupMenu();
|
||||
|
||||
// make sure the button has changed to start print
|
||||
startPrintButton = testRunner.GetWidgetByName("Start Print Button", out _);
|
||||
Assert.IsTrue(startPrintButton.Enabled, "Start Print should be enabled after running printer setup");
|
||||
Assert.IsFalse(testRunner.WaitForName("SetupPrinter", .5), "Finish Setup should not be visible after leveling the printer");
|
||||
|
||||
// reset to defaults and make sure print leveling is cleared
|
||||
testRunner.SwitchToSliceSettings();
|
||||
|
||||
testRunner.WaitForReloadAll(() =>
|
||||
{
|
||||
testRunner.ClickByName("Printer Overflow Menu");
|
||||
testRunner.ClickByName("Reset to Defaults... Menu Item");
|
||||
testRunner.ClickByName("Yes Button");
|
||||
});
|
||||
|
||||
testRunner.OpenPrintPopupMenu();
|
||||
|
||||
// make sure it is showing the correct button
|
||||
Assert.IsTrue(testRunner.WaitForName("SetupPrinter"), "Setup... should be visible after reset to Defaults");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 90); // NOTE: This test got stuck in ClickByName("Yes Button") -> WaitforDraw. It appears to be because WaitforDraw waited for a closed window to redraw itself.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
Copyright (c) 2017, Lars Brubaker, John Lewin
|
||||
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.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.UI;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Ignore("Product code still needs to be implemented"), Category("MatterControl.UI.Automation")]
|
||||
public class LibraryActionTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ClickOnExportButton()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
// Tests that clicking the queue export button with a single item selected opens export item window
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
//Make sure that the export window does not exist
|
||||
bool exportWindowExists1 = testRunner.WaitForName("Export Item Window", 0);
|
||||
Assert.IsTrue(exportWindowExists1 == false, "Export window does not exist");
|
||||
|
||||
testRunner.NavigateToFolder("Queue Row Item Collection");
|
||||
testRunner.ClickByName("Queue Export Button");
|
||||
SystemWindow containingWindow;
|
||||
GuiWidget exportWindow = testRunner.GetWidgetByName("Export Item Window", out containingWindow, 5);
|
||||
Assert.IsTrue(exportWindow != null, "Export window does exist");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, queueItemFolderToAdd: QueueTemplate.Three_Queue_Items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms the Export to Zip feature compresses and exports to a zip file and that file imports without issue
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ExportToZipImportFromZip()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
// Ensure output file does not exist
|
||||
string exportZipPath = MatterControlUtilities.GetTestItemPath("TestExportZip.zip");
|
||||
if (File.Exists(exportZipPath))
|
||||
{
|
||||
File.Delete(exportZipPath);
|
||||
}
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
Assert.AreEqual(4, QueueData.Instance.ItemCount, "Queue should initially have 4 items");
|
||||
|
||||
// Invoke Queue -> Export to Zip dialog
|
||||
testRunner.ClickByName("Queue... Menu");
|
||||
testRunner.Delay(.2);
|
||||
testRunner.ClickByName(" Export to Zip Menu Item");
|
||||
testRunner.Delay(2);
|
||||
testRunner.Type(exportZipPath);
|
||||
testRunner.Delay(2);
|
||||
testRunner.Type("{Enter}");
|
||||
|
||||
testRunner.WaitFor(() => File.Exists(exportZipPath));
|
||||
Assert.IsTrue(File.Exists(exportZipPath), "Queue was exported to zip file, file exists on disk at expected path");
|
||||
|
||||
// Import the exported zip file and confirm the Queue Count increases by 3
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
testRunner.Delay(1);
|
||||
testRunner.Type(exportZipPath);
|
||||
testRunner.Delay(1);
|
||||
testRunner.Type("{Enter}");
|
||||
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == 8);
|
||||
Assert.AreEqual(8, QueueData.Instance.ItemCount, "All parts imported successfully from exported zip");
|
||||
|
||||
testRunner.Delay(.3);
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(exportZipPath))
|
||||
{
|
||||
File.Delete(exportZipPath);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, queueItemFolderToAdd: QueueTemplate.Three_Queue_Items);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Ignore("Test now works as expected but product does not implement expected functionality")]
|
||||
public async Task QueueExportIsDisabledIfEmpty()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.ClickByName("Queue... Menu");
|
||||
|
||||
var exportButton = testRunner.GetWidgetByName(" Export to Zip Menu Item", out _, 5);
|
||||
Assert.IsNotNull(exportButton, "Export button should exist");
|
||||
Assert.IsTrue(exportButton.Enabled, "Export button should be enabled");
|
||||
|
||||
testRunner.ClickByName(" Remove All Menu Item");
|
||||
|
||||
testRunner.Delay(1);
|
||||
|
||||
testRunner.ClickByName("Queue... Menu");
|
||||
testRunner.WaitFor(() => !exportButton.Enabled, 4);
|
||||
Assert.IsFalse(exportButton.Enabled, "Export button should be disabled after Queue Menu -> Remove All");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Ignore("Not Finished")]
|
||||
public async Task ClickCreatePartSheetButton()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.ChangeToQueueContainer();
|
||||
|
||||
bool queueEmpty = true;
|
||||
int queueItemCount = QueueData.Instance.ItemCount;
|
||||
|
||||
if (queueItemCount == 3)
|
||||
{
|
||||
queueEmpty = false;
|
||||
}
|
||||
|
||||
Assert.IsTrue(queueEmpty == false);
|
||||
testRunner.ClickByName("Queue... Menu");
|
||||
testRunner.Delay(.2);
|
||||
testRunner.ClickByName(" Create Part Sheet Menu Item");
|
||||
testRunner.Delay(2);
|
||||
|
||||
string pathToSavePartSheet = MatterControlUtilities.GetTestItemPath("CreatePartSheet");
|
||||
string validatePartSheetPath = Path.Combine("..", "..", "..", "TestData", "QueueItems", "CreatePartSheet.pdf");
|
||||
|
||||
testRunner.Type(pathToSavePartSheet);
|
||||
testRunner.Delay(1);
|
||||
testRunner.Type("{Enter}");
|
||||
testRunner.Delay(1);
|
||||
testRunner.Delay(5);
|
||||
|
||||
bool partSheetCreated = File.Exists(validatePartSheetPath);
|
||||
|
||||
testRunner.Delay(2);
|
||||
Assert.IsTrue(partSheetCreated == true);
|
||||
|
||||
if (File.Exists(validatePartSheetPath))
|
||||
{
|
||||
File.Delete(validatePartSheetPath);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, queueItemFolderToAdd: QueueTemplate.Three_Queue_Items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
Copyright (c) 2017, John Lewin
|
||||
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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.Tests.Automation;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterControl.Tests.MatterControl
|
||||
{
|
||||
[TestFixture, Category("LibraryContainerTests")]
|
||||
public class LibraryContainerTests
|
||||
{
|
||||
[SetUp]
|
||||
public static void Setup()
|
||||
{
|
||||
StaticData.RootPath = MatterControlUtilities.StaticDataPath;
|
||||
MatterControlUtilities.OverrideAppDataLocation(MatterControlUtilities.RootPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public Task TestExistsForEachContainerType()
|
||||
{
|
||||
// Find all test methods on this test class
|
||||
var thisClassMethods = this.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
// Find and validate all ILibraryContainer types, skipping abstract classes
|
||||
foreach (var containerType in PluginFinder.FindTypes<ILibraryContainer>().Where(fieldType => !fieldType.IsAbstract))
|
||||
{
|
||||
string expectedTestName = $"{containerType.Name}Test";
|
||||
Assert.AreEqual(
|
||||
1,
|
||||
thisClassMethods.Where(m => m.Name == expectedTestName).Count(),
|
||||
"Test for LibraryContainer missing, not yet created or typo'd - Expected: " + expectedTestName);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task NoContentChangedOnLoad()
|
||||
{
|
||||
bool onIdlePumpActive = true;
|
||||
|
||||
var uiPump = Task.Run(() =>
|
||||
{
|
||||
while (onIdlePumpActive)
|
||||
{
|
||||
UiThread.InvokePendingActions();
|
||||
Thread.Sleep(10);
|
||||
};
|
||||
|
||||
Console.Write("Exiting");
|
||||
});
|
||||
|
||||
// Find and validate all ILibraryContainer types, skipping abstract classes
|
||||
foreach (var containerType in PluginFinder.FindTypes<ILibraryContainer>().Where(fieldType => !fieldType.IsAbstract))
|
||||
{
|
||||
var args = new List<object>();
|
||||
|
||||
if (containerType == typeof(FileSystemContainer))
|
||||
{
|
||||
args.Add(MatterControlUtilities.RootPath);
|
||||
}
|
||||
else if (containerType == typeof(RootLibraryContainer))
|
||||
{
|
||||
// TODO: Not sure how to test RootLibrary given content loads after MatterControl init is finished, skipping for now
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Activator.CreateInstance(containerType, args.ToArray()) is ILibraryContainer libraryContainer)
|
||||
{
|
||||
if (libraryContainer is ZipMemoryContainer zipContainer)
|
||||
{
|
||||
zipContainer.Path = Path.Combine(MatterControlUtilities.RootPath, "Tests", "TestData", "TestParts", "Batman.zip");
|
||||
zipContainer.RelativeDirectory = Path.GetDirectoryName(zipContainer.Path);
|
||||
}
|
||||
|
||||
int changedCount = 0;
|
||||
libraryContainer.ContentChanged += (s, e) =>
|
||||
{
|
||||
changedCount++;
|
||||
};
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
libraryContainer.Load();
|
||||
});
|
||||
|
||||
// Allow time for invalid additional reloads
|
||||
await Task.Delay(300);
|
||||
|
||||
// Verify Reload is called;
|
||||
Assert.AreEqual(0, changedCount, "Expected reload count not hit - container should fire reload event after acquiring content");
|
||||
}
|
||||
}
|
||||
|
||||
onIdlePumpActive = false;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task AddFiresContentChangedEvent()
|
||||
{
|
||||
string filePath = Path.Combine(MatterControlUtilities.RootPath, "Tests", "TestData", "TestParts", "Batman.stl");
|
||||
|
||||
bool onIdlePumpActive = true;
|
||||
|
||||
var uiPump = Task.Run(() =>
|
||||
{
|
||||
while (onIdlePumpActive)
|
||||
{
|
||||
UiThread.InvokePendingActions();
|
||||
Thread.Sleep(10);
|
||||
};
|
||||
|
||||
Console.Write("Exiting");
|
||||
});
|
||||
|
||||
Type writable = typeof(ILibraryWritableContainer);
|
||||
|
||||
// Find and validate all ILibraryContainer types, skipping abstract classes
|
||||
foreach (var containerType in PluginFinder.FindTypes<ILibraryContainer>().Where(fieldType => !fieldType.IsAbstract))
|
||||
{
|
||||
var args = new List<object>();
|
||||
|
||||
if (containerType == typeof(FileSystemContainer))
|
||||
{
|
||||
Directory.CreateDirectory(ApplicationDataStorage.Instance.ApplicationTempDataPath);
|
||||
args.Add(ApplicationDataStorage.Instance.ApplicationTempDataPath);
|
||||
}
|
||||
else if (containerType == typeof(RootLibraryContainer)
|
||||
|| !writable.IsAssignableFrom(containerType))
|
||||
{
|
||||
// TODO: Not sure how to test RootLibrary given content loads after MatterControl init is finished, skipping for now
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Activator.CreateInstance(containerType, args.ToArray()) is ILibraryWritableContainer libraryContainer)
|
||||
{
|
||||
if (!libraryContainer.AllowAction(ContainerActions.AddItems))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (libraryContainer is ZipMemoryContainer zipContainer)
|
||||
{
|
||||
zipContainer.Path = Path.Combine(MatterControlUtilities.RootPath, "Tests", "TestData", "TestParts", "Batman.zip");
|
||||
zipContainer.RelativeDirectory = Path.GetDirectoryName(zipContainer.Path);
|
||||
}
|
||||
|
||||
int changedCount = 0;
|
||||
libraryContainer.ContentChanged += (s, e) =>
|
||||
{
|
||||
changedCount++;
|
||||
};
|
||||
|
||||
var waitUntil = DateTime.Now.AddSeconds(15);
|
||||
|
||||
var result = Task.Run(() =>
|
||||
{
|
||||
libraryContainer.Load();
|
||||
libraryContainer.Add(new[] { new FileSystemFileItem(filePath) });
|
||||
});
|
||||
|
||||
// Wait for reload
|
||||
while (DateTime.Now <= waitUntil)
|
||||
{
|
||||
if (changedCount > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
await Task.Delay(200);
|
||||
}
|
||||
|
||||
// Allow time for invalid additional reloads
|
||||
await Task.Delay(300);
|
||||
|
||||
Console.WriteLine($"ContentChanged for {containerType.Name}");
|
||||
|
||||
// Verify Reload is called;
|
||||
Assert.AreEqual(1, changedCount, $"Expected reload count for {containerType.Name} not hit - container should fire reload event after acquiring content");
|
||||
}
|
||||
}
|
||||
|
||||
onIdlePumpActive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.UI.Tests;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation")]
|
||||
public class LibraryDownloadsTests
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
MatterControlUtilities.CreateDownloadsSubFolder();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
MatterControlUtilities.DeleteDownloadsSubFolder();
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DownloadsAddButtonAddsMultipleFiles()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
// Navigate to Downloads Library Provider
|
||||
testRunner.NavigateToFolder("Downloads Row Item Collection");
|
||||
testRunner.NavigateToFolder("-Temporary Row Item Collection");
|
||||
|
||||
// Add both files to the FileOpen dialog
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
testRunner.CompleteDialog(
|
||||
string.Format(
|
||||
"\"{0}\";\"{1}\"",
|
||||
MatterControlUtilities.GetTestItemPath("Fennec_Fox.stl"),
|
||||
MatterControlUtilities.GetTestItemPath("Batman.stl")),
|
||||
5);
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Fennec_Fox.stl", 2), "Fennec Fox item exists");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Batman.stl", 2), "Batman item exists");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DownloadsAddButtonAddsAMFFiles()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
// Navigate to Downloads Library Provider
|
||||
testRunner.NavigateToFolder("Downloads Row Item Collection");
|
||||
testRunner.NavigateToFolder("-Temporary Row Item Collection");
|
||||
|
||||
// Add AMF part items to Downloads and then type paths into file dialog
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
testRunner.CompleteDialog(MatterControlUtilities.GetTestItemPath("Rook.amf"), 4);
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Rook.amf"), "Rook item exists");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DownloadsAddButtonAddsZipFiles()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
// Navigate to Downloads Library Provider
|
||||
testRunner.NavigateToFolder("Downloads Row Item Collection");
|
||||
testRunner.NavigateToFolder("-Temporary Row Item Collection");
|
||||
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
testRunner.CompleteDialog(MatterControlUtilities.GetTestItemPath("Test.zip"), 4);
|
||||
|
||||
testRunner.DoubleClickByName("Test.zip Row Item Collection");
|
||||
|
||||
testRunner.DoubleClickByName("TestCompress.zip Row Item Collection");
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Chinese Dragon.stl", 2), "Chinese Dragon item exists");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item chichen-itza_pyramid.stl", 2), "chichen-itza item exists");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Circle Calibration.stl", 2), "Circle Calibration item exists");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RenameDownloadsPrintItem()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
// Navigate to Downloads Library Provider
|
||||
testRunner.NavigateToFolder("Downloads Row Item Collection");
|
||||
testRunner.NavigateToFolder("-Temporary Row Item Collection");
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
|
||||
testRunner.CompleteDialog(MatterControlUtilities.GetTestItemPath("Batman.stl"), 2);
|
||||
|
||||
// Rename added item
|
||||
testRunner.ClickByName("Row Item Batman.stl");
|
||||
|
||||
testRunner.LibraryRenameSelectedItem();
|
||||
|
||||
testRunner.WaitForName("InputBoxPage Action Button");
|
||||
testRunner.Type("Batman Renamed");
|
||||
|
||||
testRunner.ClickByName("InputBoxPage Action Button");
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Batman Renamed.stl", 2));
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task CreateFolder()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
//Navigate to Downloads Library Provider
|
||||
testRunner.NavigateToFolder("Downloads Row Item Collection");
|
||||
testRunner.NavigateToFolder("-Temporary Row Item Collection");
|
||||
|
||||
testRunner.CreateChildFolder("New Folder");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
// Most of these tests are disabled. Local Library needs to be added by InitializeLibrary() (MatterHackers.MatterControl.ApplicationController).
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class LocalLibraryTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task LocalLibraryAddButtonAddSingleItemToLibrary()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
testRunner.AddTestAssetsToLibrary(new[] { "Batman.stl" });
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task LocalLibraryAddButtonAddsMultipleItemsToLibrary()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
testRunner.AddTestAssetsToLibrary(new[] { "Rook.amf", "Batman.stl" });
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task LocalLibraryAddButtonAddAMFToLibrary()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
testRunner.AddTestAssetsToLibrary(new[] { "Rook.amf" });
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1024, overrideHeight: 800);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ParentFolderRefreshedOnPathPop()
|
||||
{
|
||||
// Expected: When descending into a child folder and moving items into the parent, popping the path to the parent should refresh and show the moved content
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
// Navigate to Local Library
|
||||
testRunner.NavigateToFolder("Local Library Row Item Collection");
|
||||
|
||||
string folderID = testRunner.CreateChildFolder("New Folder");
|
||||
|
||||
testRunner.DoubleClickByName(folderID);
|
||||
|
||||
// Add Library item
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
testRunner.Delay(2);
|
||||
testRunner.Type(MatterControlUtilities.GetTestItemPath("Batman.stl"));
|
||||
testRunner.Delay(1);
|
||||
testRunner.Type("{Enter}");
|
||||
|
||||
string newFileID = "Row Item Batman";
|
||||
|
||||
testRunner.ClickByName(newFileID);
|
||||
|
||||
testRunner.LibraryMoveSelectedItem();
|
||||
|
||||
testRunner.NavigateToFolder("Local Library Row Item Collection");
|
||||
|
||||
// Click Move
|
||||
testRunner.ClickByName("Accept Button");
|
||||
|
||||
// Wait for closed window/closed row
|
||||
testRunner.WaitForWidgetDisappear("Move Item Window", 5);
|
||||
testRunner.WaitForWidgetDisappear("Row Item Batman", 2);
|
||||
|
||||
// Return to the Local Library folder
|
||||
testRunner.ClickByName("Library Up Button");
|
||||
|
||||
// Assert that the expected item appears in the parent after popping the path
|
||||
testRunner.ClickByName(newFileID);
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task LocalLibraryAddButtonAddZipToLibrary()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
// Navigate to Local Library
|
||||
testRunner.NavigateToFolder("Local Library Row Item Collection");
|
||||
|
||||
// Make sure that Item does not exist before the test begins
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item Batman", 1), "Batman part should not exist at test start");
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item 2013-01-25 Mouthpiece V2", 1), "Mouthpiece part should not exist at test start");
|
||||
|
||||
// Add Library item
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
testRunner.Delay(2);
|
||||
testRunner.Type(MatterControlUtilities.GetTestItemPath("Batman.zip"));
|
||||
testRunner.Delay(1);
|
||||
testRunner.Type("{Enter}");
|
||||
|
||||
testRunner.WaitForName("Batman.zip Row Item Collection");
|
||||
|
||||
testRunner.DoubleClickByName("Batman.zip Row Item Collection");
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Batman.stl"), "Batman part should exist after adding");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item 2013-01-25_Mouthpiece_v2.stl"), "Mouthpiece part should exist after adding");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DoubleClickSwitchesToOpenTab()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
MatterControlUtilities.CreateDownloadsSubFolder();
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.AddItemToBed()
|
||||
.ClickByName("Save Menu SplitButton", offset: new Agg.Point2D(30, 0))
|
||||
.ClickByName("Save As Menu Item")
|
||||
.NavigateToFolder("Downloads Row Item Collection")
|
||||
.NavigateToFolder("-Temporary Row Item Collection")
|
||||
.ClickByName("Design Name Edit Field")
|
||||
.Type("Cube Design")
|
||||
.ClickByName("Accept Button");
|
||||
|
||||
var mainViewWidget = ApplicationController.Instance.MainView;
|
||||
var tabControl = mainViewWidget.TabControl;
|
||||
Assert.AreEqual(5, mainViewWidget.TabControl.AllTabs.Count());
|
||||
|
||||
// open the design for editing
|
||||
testRunner.ClickByName("Library Tab")
|
||||
.NavigateToFolder("Downloads Row Item Collection")
|
||||
.NavigateToFolder("-Temporary Row Item Collection")
|
||||
.DoubleClickByName("Row Item Cube Design.mcx")
|
||||
.WaitFor(() => mainViewWidget.TabControl.AllTabs.Count() == 6);
|
||||
|
||||
// we have opened a new tab
|
||||
Assert.AreEqual(6, mainViewWidget.TabControl.AllTabs.Count());
|
||||
// we are on the design tab
|
||||
Assert.AreEqual(5, tabControl.SelectedTabIndex);
|
||||
Assert.AreEqual("New Design", tabControl.SelectedTabKey);
|
||||
|
||||
// double click it again and prove that it goes to the currently open tab
|
||||
testRunner.ClickByName("Library Tab")
|
||||
.DoubleClickByName("Row Item Cube Design.mcx");
|
||||
|
||||
// we have not opened a new tab
|
||||
Assert.AreEqual(6, mainViewWidget.TabControl.AllTabs.Count());
|
||||
// we are on the design tab
|
||||
Assert.AreEqual(5, tabControl.SelectedTabIndex);
|
||||
|
||||
// rename in the library tab
|
||||
// assert tab name has change
|
||||
|
||||
// rename from the tab
|
||||
// assert name in library tab has changed
|
||||
MatterControlUtilities.DeleteDownloadsSubFolder();
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RenameButtonRenamesLocalLibraryFolder()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
// Navigate to Local Library
|
||||
testRunner.NavigateToFolder("Local Library Row Item Collection");
|
||||
|
||||
// Create New Folder
|
||||
string folderID = testRunner.CreateChildFolder("New Folder");
|
||||
|
||||
testRunner.ClickByName(folderID);
|
||||
testRunner.Delay(.2);
|
||||
|
||||
testRunner.LibraryRenameSelectedItem();
|
||||
|
||||
testRunner.Delay(.5);
|
||||
testRunner.Type("Renamed Library Folder");
|
||||
|
||||
testRunner.ClickByName("InputBoxPage Action Button");
|
||||
testRunner.Delay(.2);
|
||||
|
||||
// Make sure the renamed Library Folder exists
|
||||
Assert.IsTrue(testRunner.WaitForName("Renamed Library Folder Row Item Collection"), "Renamed folder should exist");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RemoveButtonClickedRemovesSingleItem()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.AddTestAssetsToLibrary(new[] { "Rook.amf" });
|
||||
|
||||
// Select and remove item
|
||||
testRunner.ClickByName("Row Item Rook");
|
||||
testRunner.LibraryRemoveSelectedItem();
|
||||
|
||||
// Make sure that the item has been removed
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item Rook", .5));
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RemoveButtonClickedRemovesMultipleItems()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.AddTestAssetsToLibrary(new[] { "Rook.amf", "Batman.stl" });
|
||||
|
||||
// Select both items
|
||||
testRunner.SelectListItems("Row Item Rook", "Row Item Batman");
|
||||
|
||||
// Remove items
|
||||
testRunner.LibraryRemoveSelectedItem();
|
||||
testRunner.Delay(1);
|
||||
|
||||
// Make sure both selected items are removed
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item Rook", 1), "Rook part should *not* exist after remove");
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item Batman", 1), "Batman part *not* exist after remove");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<RuntimeIdentifier>win</RuntimeIdentifier>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
|
||||
<RootNamespace>$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
|
||||
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
|
||||
<PackageId>$(AssemblyName)</PackageId>
|
||||
<Version>$(VersionPrefix)$(OutputPath)</Version>
|
||||
<Authors>$(AssemblyName)</Authors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
|
||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.410601">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\MatterControl.Tests\MatterControl\MatterControlUtilities.cs">
|
||||
<Link>MatterControlUtilities.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MatterControl.Common\MatterControl.Common.csproj" />
|
||||
<ProjectReference Include="..\..\MatterControl.csproj" />
|
||||
<ProjectReference Include="..\..\MatterControl.MeshOperations\MatterControl.MeshOperations.csproj" />
|
||||
<ProjectReference Include="..\..\MatterControl.Printing\MatterControl.Printing.csproj" />
|
||||
<ProjectReference Include="..\..\MatterControl.Winforms\MatterControl.Winforms.csproj" />
|
||||
<ProjectReference Include="..\..\MatterControlLib\MatterControlLib.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\agg\Agg.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\DataConverters3D\DataConverters3D.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\GuiAutomation\GuiAutomation.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\Gui\Gui.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\PlatformWin32\PlatformWin32.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\PolygonMesh\PolygonMesh.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\RenderOpenGl\RenderOpenGl.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\Tests\Agg.Tests\Agg.Tests.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\agg-sharp\VectorMath\VectorMath.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\MatterSlice\MatterSliceLib\MatterSliceLib.csproj" />
|
||||
<ProjectReference Include="..\..\Submodules\MatterSlice\Tests\MatterSlice.Tests\MatterSlice.Tests.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="SlicingTests.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright (c) 2017, John Lewin
|
||||
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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.MatterControl.Library;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class MatterControlTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ThumbnailGenerationMode()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(async (testRunner) =>
|
||||
{
|
||||
// Automation tests should initialize with orthographic thumbnails
|
||||
var item = new FileSystemFileItem(MatterControlUtilities.GetTestItemPath("Rook.amf"));
|
||||
var provider = ApplicationController.Instance.Library.GetContentProvider(item);
|
||||
|
||||
// Generate thumbnail
|
||||
var stopWatch = Stopwatch.StartNew();
|
||||
await provider.GetThumbnail(item, 400, 400);
|
||||
|
||||
Assert.Less(stopWatch.ElapsedMilliseconds, 2000, "Elapsed thumbnail generation for Rook.amf should be less than 2 seconds for expected orthographic mode");
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ViewGenerateSupportMenu()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
|
||||
testRunner.ClickByName("Support SplitButton");
|
||||
testRunner.ClickByName("Generate Support Button");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task PrinterTabRemainsAfterReloadAll()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
// Add Guest printers
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
Assert.AreEqual(
|
||||
1,
|
||||
ApplicationController.Instance.ActivePrinters.Count(),
|
||||
"One printer should exist after Airwolf add");
|
||||
|
||||
testRunner.SwitchToSliceSettings();
|
||||
|
||||
// Move to Adhesion tab
|
||||
testRunner.SelectSliceSettingsField(SettingsKey.skirts);
|
||||
|
||||
// Click Brim toggle field forcing ReloadAll
|
||||
testRunner.WaitForReloadAll(() =>
|
||||
{
|
||||
testRunner.ClickByName("Create Brim Field");
|
||||
ApplicationController.Instance.ReloadAll();
|
||||
});
|
||||
|
||||
// Ensure tabs remain
|
||||
Assert.AreEqual(
|
||||
1,
|
||||
ApplicationController.Instance.ActivePrinters.Count(),
|
||||
"One printer should exist after Airwolf add");
|
||||
|
||||
testRunner.Delay(1);
|
||||
|
||||
Assert.AreEqual(
|
||||
1,
|
||||
ApplicationController.Instance.MainView.TabControl.AllTabs.Select(t => t.TabContent).OfType<PrinterTabPage>().Count(),
|
||||
"One printer tab should exist after ReloadAll");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.UI;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation")]
|
||||
public class ShowTerminalButtonClickedOpensTerminal
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ClickingShowTerminalButtonOpensTerminal()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
|
||||
Assert.IsFalse(testRunner.WaitForName("TerminalWidget", 0.5), "Terminal Window should not exist");
|
||||
|
||||
// when we start up a new session the Terminal Sidebar should not be present
|
||||
Assert.IsFalse(testRunner.WaitForName("Terminal Sidebar", 0.5), "Terminal Sidebar should not exist");
|
||||
|
||||
testRunner.SwitchToTerminalTab();
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("TerminalWidget"), "Terminal Window should exists after Show Terminal button is clicked");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
668
original/Tests/MatterControl.AutomationTests/PartPreviewTests.cs
Normal file
668
original/Tests/MatterControl.AutomationTests/PartPreviewTests.cs
Normal file
|
|
@ -0,0 +1,668 @@
|
|||
/*
|
||||
Copyright (c) 2022, Lars Brubaker
|
||||
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.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.DesignTools;
|
||||
using MatterHackers.MatterControl.DesignTools.Operations;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.VectorMath;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class PartPreviewTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task CopyButtonMakesCopyOfPart()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
// Get View3DWidget
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.WaitForName("Calibration - Box.stl");
|
||||
Assert.AreEqual(1, scene.Children.Count, "Should have 1 part before copy");
|
||||
|
||||
// Select scene object
|
||||
testRunner.Select3DPart("Calibration - Box.stl")
|
||||
// Click Copy button and count Scene.Children
|
||||
.ClickByName("Duplicate Button")
|
||||
.Assert(() => scene.Children.Count == 2, "Should have 2 parts after copy");
|
||||
|
||||
// Click Copy button a second time and count Scene.Children
|
||||
testRunner.ClickByName("Duplicate Button");
|
||||
testRunner.Assert(() => scene.Children.Count == 3, "Should have 3 parts after 2nd copy");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300, maxTimeToRun: 60);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task AddMultiplePartsMultipleTimes()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var parts = new[]
|
||||
{
|
||||
"Row Item Cone",
|
||||
"Row Item Sphere",
|
||||
"Row Item Torus"
|
||||
};
|
||||
testRunner.AddPrimitivePartsToBed(parts, multiSelect: true);
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.WaitForName("Selection");
|
||||
Assert.AreEqual(1, scene.Children.Count, $"Should have 1 scene item after first AddToBed");
|
||||
|
||||
testRunner.ClickByName("Print Library Overflow Menu");
|
||||
testRunner.ClickByName("Add to Bed Menu Item");
|
||||
testRunner.WaitForName("Selection");
|
||||
Assert.AreEqual(parts.Length + 1, scene.Children.Count, $"Should have {parts.Length + 1} scene items after second AddToBed");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300, maxTimeToRun: 60);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task AddingImageConverterWorks()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
testRunner.AddItemToBed("Primitives Row Item Collection", "Row Item Image Converter");
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.Assert(() => scene.Children.Count == 1, $"Should have 1 scene item after first AddToBed")
|
||||
.Assert(() => scene.Descendants().Where(i => i is ImageObject3D).Any(), $"Should have 1 scene item after first AddToBed");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300, maxTimeToRun: 60);
|
||||
}
|
||||
|
||||
// NOTE: On GLFW, this test appears to fail due to the (lack of) behavior in PressModifierKeys.
|
||||
[Test, ChildProcessTest]
|
||||
public static async Task ControlClickInDesignTreeView()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var parts = new[]
|
||||
{
|
||||
"Row Item Cube",
|
||||
"Row Item Half Cylinder",
|
||||
"Row Item Half Wedge",
|
||||
"Row Item Pyramid"
|
||||
};
|
||||
testRunner.AddPrimitivePartsToBed(parts, multiSelect: false);
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
var designTree = testRunner.GetWidgetByName("DesignTree", out _, 3) as TreeView;
|
||||
Assert.AreEqual(scene.Children.Count, FetchTreeNodes().Count, "Scene part count should equal tree node count");
|
||||
|
||||
// Open up some room in the design tree view panel for adding group and selection nodes.
|
||||
var splitter = designTree.Parents<Splitter>().First();
|
||||
var splitterBar = splitter.Children.Where(child => child.GetType().Name == "SplitterBar").First();
|
||||
var treeNodes = FetchTreeNodes();
|
||||
var cubeNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Cube").Single();
|
||||
var expandBy = cubeNode.Size.Y * 4d;
|
||||
testRunner.DragWidget(splitterBar, new Point2D(0, expandBy)).Drop();
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify control-click isn't broken in library view.
|
||||
var moreParts = new[]
|
||||
{
|
||||
"Row Item Sphere",
|
||||
"Row Item Wedge"
|
||||
};
|
||||
testRunner.AddPrimitivePartsToBed(moreParts, multiSelect: true);
|
||||
var partCount = parts.Length + moreParts.Length;
|
||||
|
||||
Assert.IsTrue(scene.Children.Any(child => child is SelectionGroupObject3D), "Scene should have a selection child");
|
||||
treeNodes = FetchTreeNodes();
|
||||
Assert.IsFalse(treeNodes.Where(node => node.Tag is SelectionGroupObject3D).Any());
|
||||
Assert.AreEqual(treeNodes.Count, partCount, "Design tree should show all parts");
|
||||
Assert.AreEqual(
|
||||
scene.Children.Sum(child =>
|
||||
{
|
||||
if (child is SelectionGroupObject3D selection)
|
||||
{
|
||||
return selection.Children.Count;
|
||||
}
|
||||
return 1;
|
||||
}),
|
||||
treeNodes.Count,
|
||||
"Number of parts in scene should equal number of nodes in design view");
|
||||
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify rectangle drag select on bed creates a selection group in scene only.
|
||||
//
|
||||
// Rotate bed to top-down view so it's easier to select parts.
|
||||
var top = Matrix4X4.LookAt(Vector3.Zero, new Vector3(0, 0, -1), new Vector3(0, 1, 0));
|
||||
view3D.TrackballTumbleWidget.AnimateRotation(top);
|
||||
|
||||
testRunner.Delay()
|
||||
.ClickByName("Pyramid")
|
||||
.Delay()
|
||||
.RectangleSelectParts(view3D.Object3DControlLayer, new[] { "Cube", "Pyramid" })
|
||||
.Delay();
|
||||
|
||||
Assert.AreEqual(partCount - 3, scene.Children.Count, "Scene should have {0} children after drag rectangle select", partCount - 3);
|
||||
Assert.IsTrue(scene.Children.Any(child => child is SelectionGroupObject3D), "Scene should have a selection child after drag rectangle select");
|
||||
Assert.AreEqual(4, scene.SelectedItem.Children.Count, "4 parts should be selected");
|
||||
Assert.IsTrue(
|
||||
new HashSet<string>(scene.SelectedItem.Children.Select(child => child.Name)).SetEquals(new[] { "Cube", "Half Wedge", "Half Cylinder", "Pyramid" }),
|
||||
"Cube, Half Cylinder, Half Wedge, Pyramid should be selected");
|
||||
treeNodes = FetchTreeNodes();
|
||||
Assert.IsFalse(treeNodes.Where(node => node.Tag is SelectionGroupObject3D).Any());
|
||||
Assert.AreEqual(
|
||||
scene.Children.Sum(child =>
|
||||
{
|
||||
if (child is SelectionGroupObject3D selection)
|
||||
{
|
||||
return selection.Children.Count;
|
||||
}
|
||||
return 1;
|
||||
}),
|
||||
treeNodes.Count,
|
||||
"Number of parts in scene should equal number of nodes in design view afte drag rectangle select");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify shift-clicking on parts on bed creates a selection group.
|
||||
testRunner
|
||||
.ClickByName("Sphere")
|
||||
.ClickByName("Half Cylinder")
|
||||
.PressModifierKeys(AutomationRunner.ModifierKeys.Shift)
|
||||
.ClickByName("Pyramid")
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Shift);
|
||||
Assert.AreEqual(partCount - 1, scene.Children.Count, "Should have {0} children after selection", partCount - 1);
|
||||
Assert.IsTrue(scene.Children.Any(child => child is SelectionGroupObject3D), "Selection group should be child of scene");
|
||||
Assert.IsFalse(scene.Children.Any(child => child.Name == "Half Cylinder" || child.Name == "Pyramid"), "Half Cylinder and Pyramid should be removed as direct children of scene");
|
||||
Assert.IsNull(designTree.SelectedNode, "Design tree shouldn't have a selected node when multiple parts are selected");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify grouping parts creates a group.
|
||||
testRunner.ClickByName("Group Button");
|
||||
Assert.AreEqual(partCount - 1, scene.Children.Count, "Should have {0} parts after group", partCount - 1);
|
||||
Assert.IsInstanceOf<GroupHolesAppliedObject3D>(scene.SelectedItem, "Scene selection should be group");
|
||||
Assert.IsInstanceOf<GroupHolesAppliedObject3D>(designTree.SelectedNode.Tag, "Group should be selected in design tree");
|
||||
Assert.AreSame(scene.SelectedItem, designTree.SelectedNode.Tag, "Same group object should be selected in scene and design tree");
|
||||
|
||||
treeNodes = FetchTreeNodes();
|
||||
Assert.AreEqual(scene.Children.Count, treeNodes.Count, "Scene part count should equal tree node count after group");
|
||||
Assert.IsTrue(treeNodes.Any(node => node.Tag is GroupHolesAppliedObject3D), "Design tree should have node for group");
|
||||
Assert.AreSame(designTree.SelectedNode.Tag, treeNodes.Single(node => node.Tag is GroupHolesAppliedObject3D).Tag, "Selected node in design tree should be group node");
|
||||
|
||||
var groupNode = treeNodes.Where(node => node.Tag is GroupHolesAppliedObject3D).Single();
|
||||
Assert.AreEqual(2, groupNode.Nodes.Count, "Group should have 2 parts");
|
||||
Assert.IsTrue(
|
||||
new HashSet<string>(groupNode.Nodes.Select(node => ((IObject3D)node.Tag).Name)).SetEquals(new[] {"Half Cylinder", "Pyramid"}),
|
||||
"Half Cylinder and Pyramind should be grouped");
|
||||
|
||||
var singleItemNodes = treeNodes
|
||||
.Where(node => !(node.Tag is GroupHolesAppliedObject3D))
|
||||
.Where(node => !(node.Tag is SelectionGroupObject3D))
|
||||
.ToList();
|
||||
var singleItemNames = new HashSet<string>(singleItemNodes.Select(item => ((IObject3D)item.Tag).Name));
|
||||
|
||||
Assert.AreEqual(partCount - 2, singleItemNodes.Count, "There should be {0} single item nodes in the design tree", partCount - 2);
|
||||
Assert.IsTrue(singleItemNames.SetEquals(new[] {"Cube", "Half Wedge", "Sphere", "Wedge"}), "Cube, Half Wedge, Sphere, Wedge should be single items");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify using the design tree to create a selection group.
|
||||
var halfWedgeNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Half Wedge").Single();
|
||||
var sphereNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Sphere").Single();
|
||||
testRunner.ClickWidget(halfWedgeNode)
|
||||
.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(sphereNode)
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
Assert.AreEqual(partCount - 2, scene.Children.Count, "Should have {0} parts after selection", partCount - 2);
|
||||
Assert.IsNull(designTree.SelectedNode, "Design tree shouldn't have a selected node after creating selection in design tree");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify control-clicking a part in the group does not get added to the selection group. Only top-level nodes can be
|
||||
// selected.
|
||||
treeNodes = FetchTreeNodes();
|
||||
groupNode = treeNodes.Where(node => node.Tag is GroupHolesAppliedObject3D).Single();
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(groupNode.Nodes.Last())
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
Assert.AreEqual(
|
||||
scene.Children.Sum(child =>
|
||||
{
|
||||
if (child is SelectionGroupObject3D selection)
|
||||
{
|
||||
return selection.Children.Count;
|
||||
}
|
||||
return 1;
|
||||
}),
|
||||
treeNodes.Count,
|
||||
"Scene part count should equal design tree node count after control-click on group child");
|
||||
Assert.IsInstanceOf<SelectionGroupObject3D>(scene.SelectedItem, "Selection shouldn't change after control-click on group child");
|
||||
Assert.AreEqual(2, scene.SelectedItem.Children.Count, "Selection should have 2 parts after control-click on group child");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify adding group to selection.
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(groupNode.TitleBar)
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
Assert.AreEqual(partCount - 3, scene.Children.Count, "Scene should have {0} children after control-clicking group", partCount - 3);
|
||||
Assert.IsInstanceOf<SelectionGroupObject3D>(scene.SelectedItem, "Selected item should be a selection group after control-clicking on group");
|
||||
Assert.AreEqual(3, scene.SelectedItem.Children.Count, "Selection should have 3 items after control-clicking on group");
|
||||
Assert.IsTrue(
|
||||
new HashSet<string>(scene.SelectedItem.Children.Select(child => child.Name)).SetEquals(new[] {"Half Wedge", "Sphere", "Half Cylinder, Pyramid" }),
|
||||
"Selection should have Group, Half Wedge, Sphere");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify control-clicking on a part in the selection removes it from the selection.
|
||||
treeNodes = FetchTreeNodes();
|
||||
halfWedgeNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Half Wedge").Single();
|
||||
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(halfWedgeNode)
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
|
||||
Assert.IsInstanceOf<SelectionGroupObject3D>(scene.SelectedItem, "Selection group should exist after removing a child");
|
||||
Assert.AreEqual(2, scene.SelectedItem.Children.Count, "Selection should have 2 parts after removing a child");
|
||||
Assert.IsTrue(
|
||||
new HashSet<string>(scene.SelectedItem.Children.Select(child => child.Name)).SetEquals(new[] { "Half Cylinder, Pyramid", "Sphere"}),
|
||||
"Group and Sphere should be in selection after removing a child");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify control-clicking on second-to-last part in the selection removes it from the selection
|
||||
// and destroys selection group.
|
||||
treeNodes = FetchTreeNodes();
|
||||
groupNode = treeNodes.Where(node => node.Tag is GroupHolesAppliedObject3D).Single();
|
||||
sphereNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Sphere").Single();
|
||||
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(sphereNode)
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
|
||||
treeNodes = FetchTreeNodes();
|
||||
Assert.AreEqual(scene.Children.Count, treeNodes.Count, "Scene part count should equal design tree node count after removing penultimate child");
|
||||
Assert.IsNotInstanceOf<SelectionGroupObject3D>(scene.SelectedItem, "Selection group shouldn't exist after removing penultimate child");
|
||||
Assert.AreSame(groupNode.Tag, scene.SelectedItem, "Selection should be group after removing penultimate child");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify control-clicking on a part in the group that's part of the selection doesn't change the selection.
|
||||
halfWedgeNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Half Wedge").Single();
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(halfWedgeNode)
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
|
||||
treeNodes = FetchTreeNodes();
|
||||
sphereNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Sphere").Single();
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(sphereNode)
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
|
||||
treeNodes = FetchTreeNodes();
|
||||
groupNode = treeNodes.Where(node => node.Tag is GroupHolesAppliedObject3D).Single();
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(groupNode.Nodes.Last())
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
|
||||
Assert.IsInstanceOf<SelectionGroupObject3D>(scene.SelectedItem, "Selection shouldn't change after control-click on selection group child");
|
||||
Assert.AreEqual(3, scene.SelectedItem.Children.Count, "Selection should have 3 parts after control-click on selection group child");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify clicking on a top-level node that's not in the selection group unselects all the parts in the group
|
||||
// and selects the part associated with the clicked node.
|
||||
treeNodes = FetchTreeNodes();
|
||||
var wedgeNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Wedge").Single();
|
||||
testRunner.ClickWidget(wedgeNode);
|
||||
Assert.AreEqual(partCount - 1, scene.Children.Count, "Should be {0} parts in the scene after selecting wedge", partCount - 1);
|
||||
Assert.AreSame(scene.SelectedItem, wedgeNode.Tag, "Wedge should be selected");
|
||||
Assert.IsFalse(scene.Children.Any(child => child is SelectionGroupObject3D), "Selection group should go away when another part is selected");
|
||||
Assert.AreSame(scene.SelectedItem, designTree.SelectedNode.Tag, "The same part should be selected in the scene and design tree");
|
||||
|
||||
treeNodes = FetchTreeNodes();
|
||||
wedgeNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Wedge").Single();
|
||||
Assert.AreSame(designTree.SelectedNode, wedgeNode, "Wedge node should be selected in design tree");
|
||||
Assert.IsFalse(treeNodes.Any(node => node.Tag is SelectionGroupObject3D), "Selection group shouldn't exist in design tree after selecting wedge");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify that shift-clicking a part on the bed makes a selection group with a part that's been selected through
|
||||
// the design tree.
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Shift)
|
||||
.ClickByName("Half Wedge")
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Shift);
|
||||
Assert.AreEqual(partCount - 2, scene.Children.Count, "Scene should have {0} children after selecting half wedge", partCount - 2);
|
||||
Assert.IsNull(designTree.SelectedNode, "Selected node in design tree should be null after selecting half wedge");
|
||||
Assert.IsInstanceOf<SelectionGroupObject3D>(scene.SelectedItem, "Should have a selection group after selecting half wedge");
|
||||
Assert.IsTrue(
|
||||
new HashSet<string>(scene.SelectedItem.Children.Select(child => child.Name)).SetEquals(new [] {"Wedge", "Half Wedge"}),
|
||||
"Half Wedge and Wedge should be in selection");
|
||||
|
||||
//===========================================================================================//
|
||||
// Verify that control-click on a top-level part adds to an existing selection.
|
||||
treeNodes = FetchTreeNodes();
|
||||
sphereNode = treeNodes.Where(node => ((IObject3D)node.Tag).Name == "Sphere").Single();
|
||||
testRunner.PressModifierKeys(AutomationRunner.ModifierKeys.Control)
|
||||
.ClickWidget(sphereNode)
|
||||
.ReleaseModifierKeys(AutomationRunner.ModifierKeys.Control);
|
||||
Assert.AreEqual(partCount - 3, scene.Children.Count, "Scene should have {0} children after selecting sphere", partCount - 3);
|
||||
Assert.IsInstanceOf<SelectionGroupObject3D>(scene.SelectedItem, "Selection in scene should be selection group after adding sphere");
|
||||
Assert.IsTrue(
|
||||
new HashSet<string>(scene.SelectedItem.Children.Select(child => child.Name)).SetEquals(new [] {"Wedge", "Half Wedge", "Sphere"}),
|
||||
"Half Wedge, Sphere, Wedge should be in selection");
|
||||
|
||||
//===========================================================================================//
|
||||
// Done
|
||||
|
||||
return Task.CompletedTask;
|
||||
|
||||
// The nodes in the design tree are regenerated after certain events and must
|
||||
// be fetched anew.
|
||||
List<TreeNode> FetchTreeNodes() =>
|
||||
designTree.Children
|
||||
.Where(child => child is ScrollingArea)
|
||||
.First()
|
||||
.Children
|
||||
.Where(child => child is FlowLayoutWidget)
|
||||
.First()
|
||||
.Children
|
||||
.Select(child => (TreeNode)child)
|
||||
.ToList();
|
||||
}, overrideWidth: 1300, maxTimeToRun: 110);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DesignTabFileOperations()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab(false);
|
||||
|
||||
// Get View3DWidget
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out SystemWindow systemWindow, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
var tempFilaname = "Temp Test Save.mcx";
|
||||
var tempFullPath = Path.Combine(ApplicationDataStorage.Instance.DownloadsDirectory, tempFilaname);
|
||||
|
||||
// delete the temp file if it exists in the Downloads folder
|
||||
void DeleteTempFile()
|
||||
{
|
||||
if (File.Exists(tempFullPath))
|
||||
{
|
||||
File.Delete(tempFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteTempFile();
|
||||
|
||||
testRunner.Assert(() => scene.Children.Count == 1, "Should have 1 part (the phil)")
|
||||
// Make sure the tab is named 'New Design'
|
||||
.Assert(() => systemWindow.GetVisibleWigetWithText("New Design") != null, "Must have New Design")
|
||||
// add a new part to the bed
|
||||
.AddItemToBed()
|
||||
// Click the save button
|
||||
.ClickByName("Save")
|
||||
// Cancle the save as
|
||||
.ClickByName("Cancel Wizard Button")
|
||||
// Make sure the tab is named 'New Design'
|
||||
.Assert(() => systemWindow.GetVisibleWigetWithText("New Design") != null, "Have a new design tab")
|
||||
// Click the close tab button
|
||||
.ClickByName("Close Tab Button")
|
||||
// Select Cancel
|
||||
.ClickByName("Cancel Button")
|
||||
// Make sure the tab is named 'New Design'
|
||||
.Assert(() => systemWindow.GetVisibleWigetWithText("New Design") != null, "Still have design tab")
|
||||
// Click the close tab button
|
||||
.ClickByName("Close Tab Button")
|
||||
// Select 'Save'
|
||||
.ClickByName("Yes Button")
|
||||
// Cancel the 'Save As'
|
||||
.ClickByName("Cancel Wizard Button")
|
||||
// Make sure the window is still open and the tab is named 'New Design'
|
||||
.Assert(() => systemWindow.GetVisibleWigetWithText("New Design") != null, "still have desin tab")
|
||||
// Click the save button
|
||||
.ClickByName("Save")
|
||||
// Save a temp file to the downloads folder
|
||||
.DoubleClickByName("Computer Row Item Collection")
|
||||
.DoubleClickByName("Downloads Row Item Collection")
|
||||
.ClickByName("Design Name Edit Field")
|
||||
.Type(tempFilaname)
|
||||
.ClickByName("Accept Button")
|
||||
// Verify it is there
|
||||
.Assert(() => File.Exists(tempFullPath), "Must save the file")
|
||||
// And that the tab got the name
|
||||
.Assert(() => systemWindow.GetVisibleWigetWithText(tempFilaname) != null, "Tab was renamed")
|
||||
// and the tooltip is right
|
||||
.Assert(() => systemWindow.GetVisibleWigetWithText(tempFilaname).ToolTipText == tempFullPath, "Correct tool tip name")
|
||||
// Add a part to the bed
|
||||
.AddItemToBed()
|
||||
// Click the close tab button (we have an edit so it should show the save request)
|
||||
.ClickByName("Close Tab Button")
|
||||
// Click the 'Cancel'
|
||||
.ClickByName("Cancel Button")
|
||||
// Click the 'Save' button
|
||||
.ClickByName("Save")
|
||||
// Click the close button (now we have no edit it should cancel without request)
|
||||
.ClickByName("Close Tab Button");
|
||||
|
||||
// Verify the tab closes without requesting save
|
||||
testRunner.Assert(() => systemWindow.GetVisibleWigetWithText(tempFilaname) == null, "The tab should have closed");
|
||||
|
||||
// delete the temp file if it exists in the Downloads folder
|
||||
DeleteTempFile();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 60);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task GroupAndUngroup()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
// Get View3DWidget and count Scene.Children before Copy button is clicked
|
||||
View3DWidget view3D = testRunner.GetWidgetByName("View3DWidget", out _, 3) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Assert expected start count
|
||||
Assert.AreEqual(1, scene.Children.Count, "Should have one part before copy");
|
||||
|
||||
// Select scene object
|
||||
testRunner.Select3DPart("Calibration - Box.stl");
|
||||
|
||||
for (int i = 2; i <= 6; i++)
|
||||
{
|
||||
testRunner.ClickByName("Duplicate Button")
|
||||
.Assert(() => scene.Children.Count == i, $"Should have {i} parts after copy");
|
||||
}
|
||||
|
||||
// Get MeshGroupCount before Group is clicked
|
||||
Assert.AreEqual(6, scene.Children.Count, "Scene should have 6 parts after copy loop");
|
||||
|
||||
// Duplicate button moved to new container - move focus back to View3DWidget so CTRL-A below is seen by expected control
|
||||
testRunner.Select3DPart("Calibration - Box.stl")
|
||||
// select all
|
||||
.Type("^a")
|
||||
.ClickByName("Group Button")
|
||||
.Assert(() => scene.Children.Count == 1, $"Should have 1 parts after group");
|
||||
|
||||
testRunner.ClickByName("Ungroup Button")
|
||||
.Assert(() => scene.Children.Count == 6, $"Should have 6 parts after ungroup");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RemoveButtonRemovesParts()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.Select3DPart("Calibration - Box.stl");
|
||||
|
||||
Assert.AreEqual(1, scene.Children.Count, "There should be 1 part on the bed after AddDefaultFileToBedplate()");
|
||||
|
||||
// Add 5 items
|
||||
for (int i = 0; i <= 4; i++)
|
||||
{
|
||||
testRunner.ClickByName("Duplicate Button")
|
||||
.Delay(.5);
|
||||
}
|
||||
|
||||
Assert.AreEqual(6, scene.Children.Count, "There should be 6 parts on the bed after the copy loop");
|
||||
|
||||
// Remove an item
|
||||
testRunner.ClickByName("Remove Button");
|
||||
|
||||
// Confirm
|
||||
Assert.AreEqual(5, scene.Children.Count, "There should be 5 parts on the bed after remove");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task SaveAsToQueue()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
|
||||
testRunner.Select3DPart("Calibration - Box.stl");
|
||||
|
||||
int expectedCount = QueueData.Instance.ItemCount + 1;
|
||||
|
||||
testRunner.SaveBedplateToFolder("Test PartA.mcx", "Queue Row Item Collection")
|
||||
.NavigateToLibraryHome()
|
||||
.NavigateToFolder("Queue Row Item Collection");
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Test PartA.mcx"), "The part we added should be in the library");
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should increase by one after Save operation");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task SaveAsToLocalLibrary()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
|
||||
testRunner.Select3DPart("Calibration - Box.stl");
|
||||
|
||||
int expectedCount = QueueData.Instance.ItemCount + 1;
|
||||
|
||||
testRunner.SaveBedplateToFolder("Test PartB", "Local Library Row Item Collection")
|
||||
.NavigateToLibraryHome()
|
||||
.NavigateToFolder("Local Library Row Item Collection");
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Test PartB"), "The part we added should be in the library");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class WidgetExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Search the widget stack for a widget that is both visible on screen and has it's text set to the visibleText string
|
||||
/// </summary>
|
||||
/// <param name="widget">The root widget to search</param>
|
||||
/// <param name="">the name to search for</param>
|
||||
/// <returns></returns>
|
||||
public static GuiWidget GetVisibleWigetWithText(this GuiWidget widget, string visibleText)
|
||||
{
|
||||
if (widget.ActuallyVisibleOnScreen())
|
||||
{
|
||||
if (widget.Text == visibleText)
|
||||
{
|
||||
return widget;
|
||||
}
|
||||
|
||||
foreach(var child in widget.Children)
|
||||
{
|
||||
var childWithText = GetVisibleWigetWithText(child, visibleText);
|
||||
if (childWithText != null)
|
||||
{
|
||||
return childWithText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
278
original/Tests/MatterControl.AutomationTests/PrintQueueTests.cs
Normal file
278
original/Tests/MatterControl.AutomationTests/PrintQueueTests.cs
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
Copyright (c) 2017, Lars Brubaker, John Lewin
|
||||
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.
|
||||
*/
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
// Most of these tests are disabled. Local Library and Queue needs to be added by InitializeLibrary() (MatterHackers.MatterControl.ApplicationController).
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class PrintQueueTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task AddOneItemToQueue()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// Expected = initial + 1
|
||||
int expectedCount = QueueData.Instance.ItemCount + 1;
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.ChangeToQueueContainer();
|
||||
|
||||
// Click Add button and select files
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
|
||||
// Open Fennec_Fox
|
||||
testRunner.CompleteDialog(MatterControlUtilities.GetTestItemPath("Fennec_Fox.stl"));
|
||||
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should increase by 1 when adding 1 item");
|
||||
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Fennec_Fox.stl"), "Named widget should exist after add(Fennec_Fox)");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task AddTwoItemsToQueue()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// Expected = initial + 2;
|
||||
int expectedCount = QueueData.Instance.ItemCount + 2;
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.ChangeToQueueContainer();
|
||||
|
||||
// Click Add button and select files
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
|
||||
// Open Fennec_Fox, Batman files
|
||||
testRunner.CompleteDialog(
|
||||
string.Format(
|
||||
"\"{0}\";\"{1}\"",
|
||||
MatterControlUtilities.GetTestItemPath("Fennec_Fox.stl"),
|
||||
MatterControlUtilities.GetTestItemPath("Batman.stl")),
|
||||
secondsToWait: 2);
|
||||
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - two parts added and queue count increases by two
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should increase by 2 when adding 2 items");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Fennec_Fox.stl"), "Named widget should exist after add(Fennec_Fox)");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Batman.stl"), "Named widget should exist after add(Batman)");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RemoveButtonRemovesSingleItem()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
int expectedCount = QueueData.Instance.ItemCount - 1;
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.NavigateToFolder("Queue Row Item Collection");
|
||||
|
||||
// Select both items
|
||||
testRunner.SelectListItems("Row Item 2013-01-25_Mouthpiece_v2.stl");
|
||||
|
||||
// Remove item
|
||||
testRunner.LibraryRemoveSelectedItem();
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount, 500);
|
||||
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should decrease by one after clicking Remove");
|
||||
|
||||
// Make sure selected item was removed
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item 2013-01-25_Mouthpiece_v2.stl", .5), "Mouthpiece part should *not* exist after remove");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, queueItemFolderToAdd: QueueTemplate.Three_Queue_Items);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RemoveButtonRemovesMultipleItems()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
int expectedCount = QueueData.Instance.ItemCount - 2;
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.NavigateToFolder("Queue Row Item Collection");
|
||||
|
||||
// Select both items
|
||||
testRunner.SelectListItems("Row Item Batman.stl", "Row Item 2013-01-25_Mouthpiece_v2.stl");
|
||||
|
||||
// Remove items
|
||||
testRunner.LibraryRemoveSelectedItem();
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount, 500);
|
||||
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should decrease by two after clicking Remove");
|
||||
|
||||
// Make sure both selected items are removed
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item Batman.stl", .5), "Batman part should *not* exist after remove");
|
||||
Assert.IsFalse(testRunner.WaitForName("Row Item 2013-01-25_Mouthpiece_v2.stl", .5), "Mouthpiece part should *not* exist after remove");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, queueItemFolderToAdd: QueueTemplate.Three_Queue_Items);
|
||||
}
|
||||
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DragTo3DViewAddsItem()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
testRunner.AddTestAssetsToLibrary(new[] { "Batman.stl" });
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
Assert.AreEqual(0, scene.Children.Count, "The scene should have zero items before drag/drop");
|
||||
|
||||
testRunner.DragDropByName("Row Item Batman", "Object3DControlLayer");
|
||||
Assert.AreEqual(1, scene.Children.Count, "The scene should have one item after drag/drop");
|
||||
|
||||
testRunner.Delay(.2);
|
||||
|
||||
testRunner.DragDropByName("Row Item Batman", "Object3DControlLayer");
|
||||
Assert.AreEqual(2, scene.Children.Count, "The scene should have two items after drag/drop");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, queueItemFolderToAdd: QueueTemplate.Three_Queue_Items);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task AddAmfFile()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// Expected = initial + 1
|
||||
int expectedCount = QueueData.Instance.ItemCount + 1;
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.ChangeToQueueContainer();
|
||||
|
||||
// Click Add button and select files
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
|
||||
// Open Rook
|
||||
testRunner.CompleteDialog(
|
||||
MatterControlUtilities.GetTestItemPath("Rook.amf"));
|
||||
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should increase by 1 when adding 1 item");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Rook.amf"), "Named widget should exist after add(Rook)");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task AddStlFile()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// Expected = initial + 1
|
||||
int expectedCount = QueueData.Instance.ItemCount + 1;
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.ChangeToQueueContainer();
|
||||
|
||||
// Click Add button and select files
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
|
||||
// Open Batman
|
||||
testRunner.CompleteDialog(
|
||||
MatterControlUtilities.GetTestItemPath("Batman.stl"));
|
||||
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should increase by 1 when adding 1 item");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item Batman.stl"), "Named widget should exist after add(Batman)");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task AddGCodeFile()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// Expected = initial + 1
|
||||
int expectedCount = QueueData.Instance.ItemCount + 1;
|
||||
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
testRunner.ChangeToQueueContainer();
|
||||
|
||||
// Click Add button and select files
|
||||
testRunner.InvokeLibraryAddDialog();
|
||||
|
||||
// Open chichen-itza_pyramid
|
||||
testRunner.CompleteDialog(
|
||||
MatterControlUtilities.GetTestItemPath("chichen-itza_pyramid.gcode"));
|
||||
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
Assert.AreEqual(expectedCount, QueueData.Instance.ItemCount, "Queue count should increase by 1 when adding 1 item");
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item chichen-itza_pyramid.gcode"), "Named widget should exist after add(chichen-itza)");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.PrinterCommunication.Io;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.PrinterEmulator;
|
||||
using MatterHackers.VectorMath;
|
||||
using NUnit.Framework;
|
||||
using static MatterHackers.MatterControl.PrinterCommunication.PrinterConnection;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation")]
|
||||
public class PrinterConnectionTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task PrinterDisconnectedOnTabClose()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// Create and connect to Airwolf via emulator port
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
// Ensure connected
|
||||
Assert.AreEqual(CommunicationStates.Connected, printer.Connection.CommunicationState, "Printer should be Connected after LaunchAndConnectToPrinterEmulator");
|
||||
|
||||
// Close Printer
|
||||
testRunner.CloseFirstPrinterTab();
|
||||
|
||||
// Ensure disconnected
|
||||
testRunner.WaitFor(() => printer.Connection.CommunicationState == PrinterCommunication.CommunicationStates.Disconnected);
|
||||
Assert.AreEqual(CommunicationStates.Disconnected, printer.Connection.CommunicationState, "Printer should be Disconnected after closing printer tab");
|
||||
|
||||
Assert.AreEqual(0, ReadThread.NumRunning, "No ReadThread instances should be running when only printer Disconnected");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class PrinterNameChangeTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task NameChangeOnlyEffectsOnePrinter()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
// Add Guest printers
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
|
||||
var printer1 = testRunner.FirstPrinter();
|
||||
|
||||
testRunner.AddAndSelectPrinter("BCN3D", "Sigma");
|
||||
|
||||
var printer2 = ApplicationController.Instance.ActivePrinters.Last();
|
||||
|
||||
string newName0 = "Updated name 0";
|
||||
string newName1 = "Updated name 1";
|
||||
var printerTab0 = testRunner.GetWidgetByName("3D View Tab 0", out _) as ChromeTab;
|
||||
var printerTab1 = testRunner.GetWidgetByName("3D View Tab 1", out _) as ChromeTab;
|
||||
|
||||
// switch back to airwolf tab
|
||||
testRunner.ClickByName("3D View Tab 0")
|
||||
.SwitchToPrinterSettings()
|
||||
.InlineTitleEdit("Printer Name", newName0);
|
||||
|
||||
Assert.AreEqual(newName0, printerTab0.Text);
|
||||
Assert.AreEqual("BCN3D Sigma", printerTab1.Text);
|
||||
|
||||
// switch back to BCN tab
|
||||
testRunner.ClickByName("3D View Tab 1")
|
||||
.SwitchToPrinterSettings()
|
||||
.InlineTitleEdit("Printer Name", newName1);
|
||||
|
||||
Assert.AreEqual(newName1, printerTab1.Text);
|
||||
Assert.AreEqual(newName0, printerTab0.Text, "Name did not change");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task NameChangePersists()
|
||||
{
|
||||
// Ensures that printer model changes are applied correctly and observed by the view
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should exist after add");
|
||||
|
||||
testRunner.SwitchToPrinterSettings();
|
||||
|
||||
// Change the printer name
|
||||
string newName = "Updated name";
|
||||
testRunner.InlineTitleEdit("Printer Name", newName);
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
string printerID = printer.Settings.ID;
|
||||
|
||||
// Wait for change
|
||||
testRunner.WaitFor(() => newName == ProfileManager.Instance[printerID].Name);
|
||||
|
||||
// Validate that the model reflects the new name
|
||||
Assert.AreEqual(newName, ProfileManager.Instance[printerID].Name, "ActiveProfile has updated name");
|
||||
|
||||
// Validate that the treeview reflects the new name
|
||||
testRunner.SwitchToHardwareTab();
|
||||
Assert.IsTrue(testRunner.WaitForName(newName + " Node"), "Widget with updated printer name exists");
|
||||
|
||||
// Validate that the tab reflects the new name
|
||||
var printerTab = testRunner.GetWidgetByName("3D View Tab 0", out _) as ChromeTab;
|
||||
Assert.AreEqual(newName, printerTab.Text);
|
||||
|
||||
// Validate that the settings layer reflects the new name
|
||||
Assert.AreEqual(newName, printer.PrinterName);
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
799
original/Tests/MatterControl.AutomationTests/PrintingTests.cs
Normal file
799
original/Tests/MatterControl.AutomationTests/PrintingTests.cs
Normal file
|
|
@ -0,0 +1,799 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.PrinterCommunication.Io;
|
||||
using MatterHackers.MatterControl.PrintHistory;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.PrinterEmulator;
|
||||
using MatterHackers.VectorMath;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class PrintingTests
|
||||
{
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task CompletingPrintTurnsoffHeat()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForName("Cancel Wizard Button", 1);
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should be defined after add");
|
||||
|
||||
testRunner.SelectSliceSettingsField(SettingsKey.end_gcode);
|
||||
|
||||
testRunner.Type("^a");
|
||||
testRunner.Type("{BACKSPACE}");
|
||||
testRunner.Type("G28");
|
||||
|
||||
testRunner.SelectSliceSettingsField(SettingsKey.start_gcode);
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
// TODO: Failure persisting GCode / MultilineTextField value
|
||||
// Expected string length 3 but was 2.Strings differ at index 0.
|
||||
// Shift-G is being swallowed by something.
|
||||
|
||||
// Validate GCode fields persist values
|
||||
Assert.AreEqual(
|
||||
"G28",
|
||||
printer.Settings.GetValue(SettingsKey.end_gcode),
|
||||
"Failure persisting GCode/MultilineTextField value");
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
// Shorten the delay so the test runs in a reasonable time
|
||||
printer.Connection.TimeToHoldTemperature = 5;
|
||||
|
||||
testRunner.StartPrint(printer);
|
||||
|
||||
// Wait for print to finish
|
||||
testRunner.WaitForPrintFinished(printer);
|
||||
|
||||
// Wait for expected temp
|
||||
testRunner.WaitFor(() => printer.Connection.GetActualHotendTemperature(0) <= 0, 10);
|
||||
Assert.Less(printer.Connection.GetActualHotendTemperature(0), 30);
|
||||
|
||||
// Wait for expected temp
|
||||
testRunner.WaitFor(() => printer.Connection.ActualBedTemperature <= 10);
|
||||
Assert.Less(printer.Connection.ActualBedTemperature, 10);
|
||||
|
||||
// Make sure we can run this whole thing again
|
||||
testRunner.StartPrint(printer);
|
||||
|
||||
// Wait for print to finish
|
||||
testRunner.WaitForPrintFinished(printer);
|
||||
|
||||
// Wait for expected temp
|
||||
testRunner.WaitFor(() => printer.Connection.GetActualHotendTemperature(0) <= 0, 10);
|
||||
Assert.Less(printer.Connection.GetActualHotendTemperature(0), 30);
|
||||
|
||||
// Wait for expected temp
|
||||
testRunner.WaitFor(() => printer.Connection.ActualBedTemperature <= 10);
|
||||
Assert.Less(printer.Connection.ActualBedTemperature, 10);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 95);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task PulseLevelingTest()
|
||||
{
|
||||
// Validates the Pulse profile requires leveling and it works as expected
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
AutomationRunner.TimeToMoveMouse = .2;
|
||||
testRunner.WaitForName("Cancel Wizard Button", 1);
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator("Pulse", "A-134"))
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should be defined after add");
|
||||
|
||||
testRunner.OpenPrintPopupMenu()
|
||||
.ClickByName("SetupPrinter")
|
||||
.Complete9StepLeveling()
|
||||
.AddItemToBed();
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
var currentSettings = printer.Settings;
|
||||
currentSettings.SetValue(SettingsKey.pause_gcode, "");
|
||||
currentSettings.SetValue(SettingsKey.resume_gcode, "");
|
||||
|
||||
testRunner.StartPrint(printer, pauseAtLayers: "2");
|
||||
|
||||
testRunner.WaitForName("Yes Button", 20); // the yes button is 'Resume'
|
||||
|
||||
// the user types in the pause layer 1 based and we are 0 based, so we should be on: user 2, printer 1.
|
||||
Assert.AreEqual(1, printer.Connection.CurrentlyPrintingLayer);
|
||||
|
||||
// assert the leveling is working
|
||||
Assert.AreEqual(11.25, emulator.Destination.Z);
|
||||
|
||||
testRunner.CancelPrint();
|
||||
|
||||
// now run leveling again and make sure we get the same result
|
||||
testRunner.SwitchToControlsTab();
|
||||
testRunner.ClickByName("Printer Calibration Button");
|
||||
|
||||
testRunner.ClickByName("Print Leveling Row");
|
||||
|
||||
testRunner.Complete9StepLeveling(2);
|
||||
|
||||
testRunner.StartPrint(printer, pauseAtLayers: "2");
|
||||
|
||||
testRunner.WaitForName("Yes Button", 20); // the yes button is 'Resume'
|
||||
|
||||
// the user types in the pause layer 1 based and we are 0 based, so we should be on: user 2, printer 1.
|
||||
Assert.AreEqual(1, printer.Connection.CurrentlyPrintingLayer);
|
||||
// assert the leveling is working
|
||||
Assert.AreEqual(12.25, emulator.Destination.Z);
|
||||
|
||||
// NOTE: System.Exception : WaitForWidgetEnabled Failed: Named GuiWidget not found [Print Progress Dial]
|
||||
// Might be fixed in CancelPrint now.
|
||||
testRunner.CancelPrint();
|
||||
|
||||
// now modify the leveling data manually and assert that it is applied when printing
|
||||
testRunner.SwitchToControlsTab();
|
||||
|
||||
testRunner.ClickByName("Printer Calibration Button");
|
||||
|
||||
testRunner.ClickByName("Edit Leveling Data Button");
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var name = $"z Position {i}";
|
||||
testRunner.ClickByName(name);
|
||||
testRunner.Type("^a"); // select all
|
||||
testRunner.Type("5");
|
||||
}
|
||||
|
||||
testRunner.ClickByName("Save Leveling Button");
|
||||
|
||||
testRunner.ClickByName("Cancel Wizard Button");
|
||||
|
||||
testRunner.StartPrint(printer, pauseAtLayers: "2");
|
||||
|
||||
testRunner.WaitForName("Yes Button", 20); // the yes button is 'Resume'
|
||||
|
||||
// the user types in the pause layer 1 based and we are 0 based, so we should be on: user 2, printer 1.
|
||||
Assert.AreEqual(1, printer.Connection.CurrentlyPrintingLayer);
|
||||
|
||||
// assert the leveling is working
|
||||
Assert.AreEqual(5.25, emulator.Destination.Z);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 230);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public void ExpectedEmulatorResponses()
|
||||
{
|
||||
// TODO: Emulator behavior should emulate actual printer firmware and use configuration rather than M104/M109 sends to set extruder count
|
||||
//
|
||||
// Quirky emulator returns single extruder M105 responses until after the first M104, at which point it extends its extruder count to match
|
||||
string M105ResponseBeforeM104 = "ok T:27.0 / 0.0";
|
||||
string M105ResponseAfterM104 = "ok T0:27.0 / 0.0 T1:27.0 / 0.0";
|
||||
|
||||
string[] test1 = new string[]
|
||||
{
|
||||
"N1 M110 N1 * 125",
|
||||
"ok",
|
||||
"N2 M114 * 37",
|
||||
"X:0.00 Y: 0.00 Z: 0.00 E: 0.00 Count X: 0.00 Y: 0.00 Z: 0.00",
|
||||
"ok",
|
||||
"N3 M105 * 36",
|
||||
M105ResponseBeforeM104,
|
||||
"N1 M110 N1*125",
|
||||
"ok",
|
||||
"N2 M115 * 36",
|
||||
"MatterControl Printer Emulator",
|
||||
"Commands:",
|
||||
" SLOW // make the emulator simulate actual printing speeds (default)",
|
||||
" FAST // run as fast as possible",
|
||||
" THROWERROR // generate a simulated error for testing",
|
||||
"Emulating:",
|
||||
"FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:https://github.com/MarlinFirmware/Marlin PROTOCOL_VERSION:1.0 MACHINE_TYPE:Framelis v1 EXTRUDER_COUNT:1 UUID:155f84b5-d4d7-46f4-9432-667e6876f37a",
|
||||
"ok",
|
||||
"N3 M104 T0 S0 * 34",
|
||||
"ok",
|
||||
"N4 M104 T1 S0 * 36",
|
||||
"ok",
|
||||
"N5 M105 * 34",
|
||||
M105ResponseAfterM104,
|
||||
"N6 M105 * 45",
|
||||
"Error:checksum mismatch, Last Line: 5",
|
||||
"Resend: 6",
|
||||
"ok",
|
||||
"N6 M105 * 33",
|
||||
M105ResponseAfterM104,
|
||||
"N7 M105 * 32",
|
||||
M105ResponseAfterM104,
|
||||
"N8 M105 * 47",
|
||||
M105ResponseAfterM104,
|
||||
"N9 M105 * 46",
|
||||
M105ResponseAfterM104,
|
||||
"N10 M105 * 22",
|
||||
M105ResponseAfterM104,
|
||||
"N11 M105 * 23",
|
||||
M105ResponseAfterM104,
|
||||
"N12 M105 * 20",
|
||||
M105ResponseAfterM104,
|
||||
"N13 M105 * 21",
|
||||
M105ResponseAfterM104,
|
||||
"N14 M105 * 18",
|
||||
M105ResponseAfterM104,
|
||||
"N15 M105 * 19",
|
||||
M105ResponseAfterM104,
|
||||
"N16 M105 * 16",
|
||||
M105ResponseAfterM104,
|
||||
"N17 M105 * 40",
|
||||
"Error:checksum mismatch, Last Line: 16",
|
||||
"Resend: 17",
|
||||
"ok",
|
||||
"N17 M105 * 17",
|
||||
M105ResponseAfterM104,
|
||||
};
|
||||
|
||||
string[] test2 = new string[]
|
||||
{
|
||||
"N1 M110 N1*125",
|
||||
"ok",
|
||||
"N1 M110 N1*125",
|
||||
"ok",
|
||||
"N1 M110 N1*125",
|
||||
"ok",
|
||||
"N2 M114*37",
|
||||
"X:0.00 Y: 0.00 Z: 0.00 E: 0.00 Count X: 0.00 Y: 0.00 Z: 0.00",
|
||||
"ok",
|
||||
};
|
||||
|
||||
SimulatePrint(test1);
|
||||
SimulatePrint(test2);
|
||||
}
|
||||
|
||||
private static void SimulatePrint(string[] sendRecieveLog)
|
||||
{
|
||||
using (var emulator = new Emulator())
|
||||
{
|
||||
emulator.HasHeatedBed = false;
|
||||
|
||||
int lineIndex = 0;
|
||||
while (lineIndex < sendRecieveLog.Length)
|
||||
{
|
||||
var sentCommand = sendRecieveLog[lineIndex];
|
||||
string response = emulator.GetCorrectResponse(sentCommand);
|
||||
lineIndex++;
|
||||
var lines = response.Split('\n');
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(lines[i]))
|
||||
{
|
||||
Assert.AreEqual(sendRecieveLog[lineIndex], lines[i]);
|
||||
lineIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task PrinterRequestsResumeWorkingAsExpected()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should be defined after add");
|
||||
|
||||
// print a part
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
testRunner.StartPrint(testRunner.FirstPrinter(), pauseAtLayers: "2;6");
|
||||
|
||||
// turn on line error simulation
|
||||
emulator.SimulateLineErrors = true;
|
||||
|
||||
// close the pause dialog pop-up (resume)
|
||||
testRunner.WaitForName("Yes Button", 20); // the yes button is 'Resume'
|
||||
testRunner.ClickByName("Yes Button");
|
||||
|
||||
// simulate board reboot
|
||||
emulator.SimulateReboot();
|
||||
|
||||
// close the pause dialog pop-up (resume)
|
||||
testRunner.Delay(3);
|
||||
testRunner.WaitForName("Yes Button", 20);
|
||||
testRunner.ClickByName("Yes Button");
|
||||
|
||||
// Wait for done
|
||||
testRunner.WaitForPrintFinished(testRunner.FirstPrinter());
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 90 * 2); // Once timed out at 90.
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task PrinterDeletedWhilePrinting()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should exist after add");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
// print a part
|
||||
testRunner.AddItemToBed();
|
||||
testRunner.StartPrint(printer, pauseAtLayers: "2");
|
||||
ProfileManager.DebugPrinterDelete = true;
|
||||
|
||||
// Wait for pause dialog
|
||||
testRunner.ClickResumeButton(printer, true, 1);
|
||||
|
||||
// Wait for done
|
||||
testRunner.WaitForPrintFinished(printer);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 180);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task PrinterRecoveryTest()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should exist after add");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
printer.Settings.SetValue(SettingsKey.recover_is_enabled, "1");
|
||||
printer.Settings.SetValue(SettingsKey.has_hardware_leveling, "0");
|
||||
|
||||
Assert.IsTrue(printer.Connection.RecoveryIsEnabled);
|
||||
|
||||
// print a part
|
||||
testRunner.AddItemToBed()
|
||||
.StartPrint(printer, pauseAtLayers: "2;4;6")
|
||||
.ClickResumeButton(printer, true, 1) // Resume
|
||||
.ClickResumeButton(printer, false, 3) // close the pause dialog pop-up do not resume
|
||||
.ClickByName("Disconnect from printer button")
|
||||
.ClickByName("Yes Button") // accept the disconnect
|
||||
//.ClickByName("Cancel Wizard Button") // click the close on the collect info dialog
|
||||
.ClickByName("Connect to printer button") // Reconnect
|
||||
.WaitFor(() => printer.Connection.CommunicationState == CommunicationStates.Connected);
|
||||
|
||||
// Assert that recovery happens
|
||||
Assert.IsTrue(PrintRecovery.RecoveryAvailable(printer), "Recovery should be enabled after Disconnect while printing");
|
||||
|
||||
// Recover the print
|
||||
testRunner.ClickButton("Yes Button", "Recover Print")
|
||||
.ClickResumeButton(printer, true, 5) // The first pause that we get after recovery should be layer 6.
|
||||
.WaitForPrintFinished(printer);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 180);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task TemperatureTowerWorks()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should exist after add");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
bool foundTemp = false;
|
||||
printer.Connection.LineSent += (s, e) =>
|
||||
{
|
||||
if (e.Contains("M104 S222.2"))
|
||||
{
|
||||
foundTemp = true;
|
||||
}
|
||||
};
|
||||
|
||||
// print a part
|
||||
testRunner.AddItemToBed()
|
||||
.AddItemToBed("Scripting Row Item Collection", "Row Item Set Temperature")
|
||||
.DragDropByName("MoveInZControl", "MoveInZControl", offsetDrag: new Point2D(0, 0), offsetDrop: new Point2D(0, 10))
|
||||
.ClickByName("Temperature Edit")
|
||||
.Type("222.2")
|
||||
.StartPrint(printer)
|
||||
.WaitFor(() => printer.Connection.CommunicationState == CommunicationStates.FinishedPrint, 60);
|
||||
// TODO: finish export test
|
||||
//.ExportPrintAndLoadGCode(printer, out string gcode);
|
||||
|
||||
Assert.IsTrue(foundTemp);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 180);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task RecoveryT1NoProbe()
|
||||
{
|
||||
await ExtruderT1RecoveryTest("Airwolf 3D", "HD");
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task RecoveryT1WithProbe()
|
||||
{
|
||||
await ExtruderT1RecoveryTest("FlashForge", "Creator Dual");
|
||||
}
|
||||
|
||||
public async Task ExtruderT1RecoveryTest(string make, string model)
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator(make, model))
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should exist after add");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
testRunner.ChangeSettings(
|
||||
new (string, string)[]
|
||||
{
|
||||
(SettingsKey.recover_is_enabled, "1"),
|
||||
(SettingsKey.extruder_count, "2"),
|
||||
(SettingsKey.has_hardware_leveling, "0"),
|
||||
}, printer);
|
||||
|
||||
Assert.IsTrue(printer.Connection.RecoveryIsEnabled);
|
||||
|
||||
// print a part
|
||||
testRunner.AddItemToBed()
|
||||
.ClickByName("ItemMaterialButton")
|
||||
.ClickByName("Material 2 Button")
|
||||
.StartPrint(printer, pauseAtLayers: "2;3;4;5");
|
||||
|
||||
testRunner.ClickResumeButton(printer, true, 1); // Resume
|
||||
// make sure we are printing with extruder 2 (T1)
|
||||
Assert.AreEqual(0, printer.Connection.GetTargetHotendTemperature(0));
|
||||
Assert.Greater(printer.Connection.GetTargetHotendTemperature(1), 0);
|
||||
|
||||
testRunner.ClickResumeButton(printer, false, 2) // close the pause dialog pop-up do not resume
|
||||
.ClickByName("Disconnect from printer button")
|
||||
.ClickByName("Yes Button") // Are you sure?
|
||||
.ClickByName("Connect to printer button") // Reconnect
|
||||
.WaitFor(() => printer.Connection.CommunicationState == CommunicationStates.Connected);
|
||||
|
||||
// Assert that recovery happens
|
||||
Assert.IsTrue(PrintRecovery.RecoveryAvailable(printer), "Recovery should be enabled after Disconnect while printing");
|
||||
|
||||
// Recover the print
|
||||
testRunner.ClickButton("Yes Button", "Recover Print");
|
||||
|
||||
// The first pause that we get after recovery should be layer 4 (index 3).
|
||||
testRunner.ClickResumeButton(printer, true, 3);
|
||||
// make sure we are printing with extruder 2 (T1)
|
||||
Assert.AreEqual(0, printer.Connection.GetTargetHotendTemperature(0));
|
||||
Assert.Greater(printer.Connection.GetTargetHotendTemperature(1), 0);
|
||||
|
||||
testRunner.ClickResumeButton(printer, true, 4);
|
||||
|
||||
testRunner.WaitForPrintFinished(printer);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 180);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task TuningAdjustmentsDefaultToOneAndPersists()
|
||||
{
|
||||
double targetExtrusionRate = 1.5;
|
||||
double targetFeedRate = 2;
|
||||
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForName("Cancel Wizard Button");
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should be defined after add");
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
testRunner.SwitchToControlsTab();
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
testRunner.StartPrint(printer)
|
||||
.ScrollIntoView("Extrusion Multiplier NumberEdit")
|
||||
.ScrollIntoView("Feed Rate NumberEdit");
|
||||
|
||||
testRunner.PausePrint();
|
||||
|
||||
// Tuning values should default to 1 when missing
|
||||
ConfirmExpectedSpeeds(testRunner, 1, 1, "Initial case");
|
||||
|
||||
testRunner.Delay()
|
||||
.ClickByName("Extrusion Multiplier NumberEdit")
|
||||
.Type(targetExtrusionRate.ToString())
|
||||
.ClickByName("Feed Rate NumberEdit")
|
||||
.Type(targetFeedRate.ToString())
|
||||
// Force focus away from the feed rate field, causing an persisted update
|
||||
.ClickByName("Extrusion Multiplier NumberEdit");
|
||||
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "After setting TextEdit values");
|
||||
|
||||
// Wait for slicing to complete before setting target values
|
||||
testRunner.WaitFor(() => printer.Connection.DetailedPrintingState == DetailedPrintingState.Printing, 8);
|
||||
testRunner.Delay();
|
||||
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "While printing");
|
||||
|
||||
testRunner.ResumePrint();
|
||||
|
||||
// Wait up to 60 seconds for the print to finish
|
||||
testRunner.WaitForPrintFinished(printer, 60);
|
||||
|
||||
// Values should match entered values
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "After print finished");
|
||||
|
||||
testRunner.StartPrint(printer) // Restart the print
|
||||
.Delay(1);
|
||||
|
||||
// Values should match entered values
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "After print restarted");
|
||||
|
||||
testRunner.CancelPrint()
|
||||
.Delay(1);
|
||||
|
||||
// Values should match entered values
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "After canceled print");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideHeight: 900, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task TuningAdjustmentControlsBoundToStreamValues()
|
||||
{
|
||||
double targetExtrusionRate = 1.5;
|
||||
double targetFeedRate = 2;
|
||||
|
||||
double initialExtrusionRate = 0.6;
|
||||
double initialFeedRate = 0.7;
|
||||
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForName("Cancel Wizard Button");
|
||||
|
||||
// Then validate that they are picked up
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should be defined after add");
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
testRunner.SwitchToControlsTab();
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
// Set custom adjustment values
|
||||
printer.Settings.SetValue(SettingsKey.feedrate_ratio, initialFeedRate.ToString());
|
||||
printer.Settings.SetValue(SettingsKey.extrusion_ratio, initialExtrusionRate.ToString());
|
||||
|
||||
var printFinishedResetEvent = new AutoResetEvent(false);
|
||||
printer.Connection.PrintFinished += (s, e) => printFinishedResetEvent.Set();
|
||||
|
||||
testRunner.StartPrint(printer);
|
||||
|
||||
testRunner.PausePrint();
|
||||
|
||||
var container = testRunner.GetWidgetByName("ManualPrinterControls.ControlsContainer", out _, 5);
|
||||
|
||||
// Scroll the widget into view
|
||||
var scrollable = container.Parents<ManualPrinterControls>().FirstOrDefault() as ScrollableWidget;
|
||||
var width = scrollable.Width;
|
||||
|
||||
// Workaround needed to scroll to the bottom of the Controls panel
|
||||
// scrollable.ScrollPosition = new Vector2();
|
||||
scrollable.ScrollPosition = new Vector2(0, 30);
|
||||
|
||||
// Workaround to force layout to fix problems with size of Tuning Widgets after setting ScrollPosition manually
|
||||
scrollable.Width = width - 1;
|
||||
scrollable.Width = width;
|
||||
|
||||
// Tuning values should match
|
||||
ConfirmExpectedSpeeds(testRunner, initialExtrusionRate, initialFeedRate, "Initial case");
|
||||
|
||||
testRunner.Delay();
|
||||
testRunner.ClickByName("Extrusion Multiplier NumberEdit");
|
||||
testRunner.Type(targetExtrusionRate.ToString());
|
||||
|
||||
testRunner.ClickByName("Feed Rate NumberEdit");
|
||||
testRunner.Type(targetFeedRate.ToString());
|
||||
|
||||
// Force focus away from the feed rate field, causing an persisted update
|
||||
testRunner.ClickByName("Extrusion Multiplier NumberEdit");
|
||||
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "After setting TextEdit values");
|
||||
|
||||
// Wait for slicing to complete before setting target values
|
||||
testRunner.WaitFor(() => printer.Connection.DetailedPrintingState == DetailedPrintingState.Printing, 8);
|
||||
testRunner.Delay();
|
||||
|
||||
// Values should remain after print completes
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "While printing");
|
||||
|
||||
testRunner.ResumePrint();
|
||||
|
||||
// Wait for printing to complete
|
||||
printFinishedResetEvent.WaitOne();
|
||||
|
||||
testRunner.WaitForPrintFinished(printer);
|
||||
|
||||
// Values should match entered values
|
||||
testRunner.StartPrint(printer);
|
||||
testRunner.WaitFor(() => printer.Connection.CommunicationState == CommunicationStates.Printing, 15);
|
||||
|
||||
// Values should match entered values
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "While reprinting");
|
||||
|
||||
testRunner.CancelPrint();
|
||||
testRunner.WaitFor(() => printer.Connection.CommunicationState == CommunicationStates.Connected, 15);
|
||||
|
||||
// Values should match entered values
|
||||
ConfirmExpectedSpeeds(testRunner, targetExtrusionRate, targetFeedRate, "After cancel");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideHeight: 900, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task CloseShouldNotStopSDPrint()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForName("Cancel Wizard Button");
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator(runSlow: true))
|
||||
{
|
||||
testRunner.NavigateToFolder("SD Card Row Item Collection");
|
||||
|
||||
testRunner.ClickByName("Row Item Item 1.gcode");
|
||||
|
||||
testRunner.ClickByName("Print Library Overflow Menu");
|
||||
testRunner.ClickByName("Print Menu Item");
|
||||
|
||||
testRunner.Delay(2);
|
||||
|
||||
int tempChangedCount = 0;
|
||||
int fanChangedCount = 0;
|
||||
emulator.ExtruderTemperatureChanged += (s, e) =>
|
||||
{
|
||||
tempChangedCount++;
|
||||
};
|
||||
emulator.FanSpeedChanged += (s, e) =>
|
||||
{
|
||||
fanChangedCount++;
|
||||
};
|
||||
|
||||
testRunner.CloseMatterControl();
|
||||
|
||||
testRunner.ClickByName("Yes Button");
|
||||
|
||||
testRunner.Delay(2);
|
||||
Assert.AreEqual(0, tempChangedCount, "We should not change this while exiting an sd card print.");
|
||||
Assert.AreEqual(0, fanChangedCount, "We should not change this while exiting an sd card print.");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 90);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task CancelingPrintTurnsHeatAndFanOff()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForName("Cancel Wizard Button");
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
var resetEvent = new AutoResetEvent(false);
|
||||
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should exist after add");
|
||||
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
testRunner.StartPrint(printer);
|
||||
|
||||
int fanChangedCount = 0;
|
||||
emulator.FanSpeedChanged += (s, e) =>
|
||||
{
|
||||
fanChangedCount++;
|
||||
};
|
||||
|
||||
emulator.WaitForLayer(printer.Settings, 2);
|
||||
emulator.RunSlow = true;
|
||||
|
||||
// Click close but cancel
|
||||
testRunner.CloseMatterControl();
|
||||
testRunner.ClickByName("No Button");
|
||||
|
||||
// Wait for close
|
||||
testRunner.WaitForWidgetDisappear("Yes Button", 4);
|
||||
testRunner.Delay(2);
|
||||
|
||||
// Confirm abort
|
||||
Assert.IsFalse(AppContext.RootSystemWindow.HasBeenClosed, "Canceling Close dialog should *not* close MatterControl");
|
||||
|
||||
// Close MatterControl and cancel print
|
||||
testRunner.CloseMatterControl();
|
||||
testRunner.ClickByName("Yes Button");
|
||||
|
||||
// Wait for Disconnected CommunicationState which occurs after PrinterConnection.Disable()
|
||||
testRunner.WaitForCommunicationStateDisconnected(printer, maxSeconds: 30);
|
||||
|
||||
// Wait for close
|
||||
testRunner.WaitForWidgetDisappear("Yes Button", 4);
|
||||
testRunner.Delay(2);
|
||||
|
||||
// Confirm close
|
||||
Assert.IsTrue(AppContext.RootSystemWindow.HasBeenClosed, "Confirming Close dialog *should* close MatterControl");
|
||||
|
||||
// Wait for M106 change
|
||||
testRunner.WaitFor(() => fanChangedCount > 0, 15, 500);
|
||||
|
||||
// Assert expected temp targets and fan transitions
|
||||
Assert.AreEqual(0, (int) emulator.CurrentExtruder.TargetTemperature, "Unexpected target temperature - MC close should call Connection.Disable->TurnOffBedAndExtruders to shutdown heaters");
|
||||
Assert.AreEqual(0, (int) emulator.HeatedBed.TargetTemperature, "Unexpected target temperature - MC close should call Connection.Disable->TurnOffBedAndExtruders to shutdown heaters");
|
||||
Assert.AreEqual(1, fanChangedCount, "Unexpected fan speed change count - MC close should call Connection.Disable which shuts down fans via M106");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideHeight: 900, maxTimeToRun: 90);
|
||||
}
|
||||
|
||||
private static void ConfirmExpectedSpeeds(AutomationRunner testRunner, double targetExtrusionRate, double targetFeedRate, string scope)
|
||||
{
|
||||
SolidSlider slider;
|
||||
|
||||
// Assert the UI has the expected values
|
||||
slider = testRunner.GetWidgetByName("Extrusion Multiplier Slider", out _) as SolidSlider;
|
||||
testRunner.WaitFor(() => targetExtrusionRate == slider.Value);
|
||||
|
||||
Assert.AreEqual(targetExtrusionRate, slider.Value, $"Unexpected Extrusion Rate Slider Value - {scope}");
|
||||
|
||||
slider = testRunner.GetWidgetByName("Feed Rate Slider", out _) as SolidSlider;
|
||||
testRunner.WaitFor(() => targetFeedRate == slider.Value);
|
||||
Assert.AreEqual(targetFeedRate, slider.Value, $"Unexpected Feed Rate Slider Value - {scope}");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
// Assert the changes took effect on the model
|
||||
testRunner.WaitFor(() => targetExtrusionRate == printer.Connection.ExtrusionMultiplierStream.ExtrusionRatio);
|
||||
Assert.AreEqual(targetExtrusionRate, printer.Connection.ExtrusionMultiplierStream.ExtrusionRatio, $"Unexpected Extrusion Rate - {scope}");
|
||||
|
||||
testRunner.WaitFor(() => targetFeedRate == printer.Connection.FeedRateMultiplierStream.FeedRateRatio);
|
||||
Assert.AreEqual(targetFeedRate, printer.Connection.FeedRateMultiplierStream.FeedRateRatio, $"Unexpected Feed Rate - {scope}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("MatterControl.AutomationTests")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("MatterHackers, Inc.")]
|
||||
[assembly: AssemblyProduct("MatterControl.AutomationTests")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("418e7058-92ee-4329-86ba-ac26b65afb25")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
// https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1416
|
||||
[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")]
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"profiles": {
|
||||
"MatterControl.AutomationTests": {
|
||||
"commandName": "Project",
|
||||
"nativeDebugging": true
|
||||
}
|
||||
}
|
||||
}
|
||||
160
original/Tests/MatterControl.AutomationTests/ReSliceTests.cs
Normal file
160
original/Tests/MatterControl.AutomationTests/ReSliceTests.cs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
Copyright (c) 2014, Lars Brubaker
|
||||
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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.MatterControl.VersionManagement;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation")]
|
||||
public class ReSliceTests
|
||||
{
|
||||
// [Test, Category("Emulator"), Ignore("WIP")]
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task ReSliceHasCorrectEPositions()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
// testRunner.ClickByName("Connection Wizard Skip Sign In Button");
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
ApplicationController.Instance.Allow32BitReSlice = true;
|
||||
var printer = testRunner.FirstPrinter();
|
||||
printer.Settings.SetValue(SettingsKey.enable_line_splitting, "0");
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Add a callback to check that every line has an extruder
|
||||
// distance greater than the largest distance minus the max retraction
|
||||
// amount and less than some amount that is reasonable
|
||||
double lastAbsoluteEPosition = 0;
|
||||
double largestAbsoluteEPosition = 0;
|
||||
double largestRetraction = 0;
|
||||
|
||||
emulator.EPositionChanged += (e, s) =>
|
||||
{
|
||||
largestAbsoluteEPosition = Math.Max(largestAbsoluteEPosition, emulator.CurrentExtruder.AbsoluteEPosition);
|
||||
var delta = emulator.CurrentExtruder.AbsoluteEPosition - lastAbsoluteEPosition;
|
||||
if (delta < largestRetraction)
|
||||
{
|
||||
largestRetraction = delta;
|
||||
}
|
||||
|
||||
double printerRetraction = 7 + .1; // the airwolf has a retraction of 7 mm
|
||||
Assert.GreaterOrEqual(delta, -printerRetraction, "We should never move back more than the retraction amount");
|
||||
Assert.GreaterOrEqual(emulator.CurrentExtruder.AbsoluteEPosition, largestAbsoluteEPosition - printerRetraction, "Never go back more than the retraction amount");
|
||||
Assert.LessOrEqual(emulator.CurrentExtruder.AbsoluteEPosition, lastAbsoluteEPosition + 10, "We should never move up more than 10 mm");
|
||||
lastAbsoluteEPosition = emulator.CurrentExtruder.AbsoluteEPosition;
|
||||
};
|
||||
|
||||
// Add a cube to the bed
|
||||
testRunner.NavigateToFolder("Queue Row Item Collection")
|
||||
.ClickByName("Row Item cube_20x20x20.stl")
|
||||
.ClickByName("Print Library Overflow Menu")
|
||||
.ClickByName("Add to Bed Menu Item")
|
||||
.Delay()
|
||||
.ClickByName("Print Library Overflow Menu")
|
||||
.Delay()
|
||||
.ClickByName("Add to Bed Menu Item")
|
||||
.Delay()
|
||||
// start the print
|
||||
.StartPrint(printer, pauseAtLayers: "50;60")
|
||||
// Wait for pause
|
||||
// the yes button is 'Resume'
|
||||
// NOTE: ClickByName Failed: Named GuiWidget not found [No Button]
|
||||
// It appears that printing can just take too long.
|
||||
// This might be fixed by using a semaphore in MatterHackers.PrinterEmulator.Emulator.
|
||||
.ClickByName("No Button", secondsToWait: 80)
|
||||
// Delete the cube
|
||||
.ClickByName("Bed Options Menu")
|
||||
.ClickByName("Clear Bed Menu Item")
|
||||
.Delay();
|
||||
// ensure there is nothing on the bed
|
||||
Assert.AreEqual(0, scene.Children.Count);
|
||||
|
||||
// Add a cylinder
|
||||
testRunner.NavigateToFolder("Queue Row Item Collection")
|
||||
.ClickByName("Row Item cylinder_5x20.stl")
|
||||
.ClickByName("Print Library Overflow Menu")
|
||||
.ClickByName("Add to Bed Menu Item")
|
||||
.ClickByName("Add Content Menu")
|
||||
// re-slice the part
|
||||
.ClickByName("Re-Slice Button")
|
||||
// The change to new g-code
|
||||
.ClickByName("Switch Button", secondsToWait: 10)
|
||||
// and resume the print
|
||||
.ClickByName("Resume Task Button")
|
||||
// Wait for next pause
|
||||
.ClickByName("No Button", secondsToWait: 80)
|
||||
// Switch back to the cube
|
||||
// Delete the cylinder
|
||||
.ClickByName("Bed Options Menu")
|
||||
.ClickByName("Clear Bed Menu Item");
|
||||
|
||||
// ensure there is nothing on the bed
|
||||
Assert.AreEqual(0, scene.Children.Count);
|
||||
|
||||
// add the cube
|
||||
testRunner.NavigateToFolder("Queue Row Item Collection")
|
||||
.ClickByName("Row Item cube_20x20x20.stl")
|
||||
.ClickByName("Print Library Overflow Menu")
|
||||
.ClickByName("Add to Bed Menu Item")
|
||||
.ClickByName("Add Content Menu")
|
||||
// re-slice the part
|
||||
.ClickByName("Re-Slice Button")
|
||||
.ClickByName("Switch Button", secondsToWait: 10)
|
||||
// and resume the print
|
||||
.ClickByName("Resume Task Button")
|
||||
// Wait for done
|
||||
.WaitForPrintFinished(printer);
|
||||
|
||||
// this will make sure we turned off line splitting and had good data about the extruder position
|
||||
Assert.AreEqual(-7, largestRetraction, "Airwolf HD has a retraction of 7mm, make sure we had one");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
maxTimeToRun: 390,
|
||||
queueItemFolderToAdd: QueueTemplate.ReSliceParts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,581 @@
|
|||
/*
|
||||
Copyright (c) 2022, Lars Brubaker, John Lewin
|
||||
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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.VectorMath;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class SceneUndoRedoCopyTests
|
||||
{
|
||||
private const string CoinName = "MatterControl - Coin.stl";
|
||||
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
StaticData.RootPath = MatterControlUtilities.StaticDataPath;
|
||||
MatterControlUtilities.OverrideAppDataLocation(MatterControlUtilities.RootPath);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task CopyRemoveUndoRedo()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Initialize
|
||||
testRunner.AddItemToBed();
|
||||
|
||||
testRunner.Select3DPart("Calibration - Box.stl")
|
||||
.WaitForName("Duplicate Button");
|
||||
Assert.AreEqual(1, scene.Children.Count, "Should have 1 part before copy");
|
||||
|
||||
for (int i = 0; i <= 4; i++)
|
||||
{
|
||||
testRunner.ClickByName("Duplicate Button");
|
||||
testRunner.WaitFor(() => scene.Children.Count == i + 2);
|
||||
Assert.AreEqual(i + 2, scene.Children.Count);
|
||||
}
|
||||
|
||||
testRunner.ClickByName("Remove Button");
|
||||
testRunner.WaitFor(() => scene.Children.Count == 5);
|
||||
Assert.AreEqual(5, scene.Children.Count, "Should have 5 parts after Remove");
|
||||
|
||||
testRunner.ClickByName("3D View Undo");
|
||||
testRunner.WaitFor(() => scene.Children.Count == 6);
|
||||
Assert.AreEqual(6, scene.Children.Count, "Should have 6 parts after Undo");
|
||||
|
||||
testRunner.ClickByName("3D View Redo");
|
||||
testRunner.WaitFor(() => scene.Children.Count == 5);
|
||||
Assert.AreEqual(5, scene.Children.Count, "Should have 5 parts after Redo");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task UndoRedoCopy()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab()
|
||||
.AddItemToBed();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.Select3DPart("Calibration - Box.stl");
|
||||
|
||||
Assert.AreEqual(1, scene.Children.Count, "There should be 1 part on the bed after AddDefaultFileToBedplate()");
|
||||
|
||||
// Add 5 items
|
||||
for (int i = 0; i <= 4; i++)
|
||||
{
|
||||
testRunner.ClickByName("Duplicate Button");
|
||||
testRunner.Delay(.5);
|
||||
}
|
||||
|
||||
Assert.AreEqual(6, scene.Children.Count, "There should be 6 parts on the bed after the copy loop");
|
||||
|
||||
// Perform and validate 5 undos
|
||||
for (int x = 0; x <= 4; x++)
|
||||
{
|
||||
int meshCountBeforeUndo = scene.Children.Count;
|
||||
testRunner.ClickByName("3D View Undo");
|
||||
|
||||
testRunner.WaitFor(() => scene.Children.Count == meshCountBeforeUndo - 1);
|
||||
Assert.AreEqual(scene.Children.Count, meshCountBeforeUndo - 1);
|
||||
}
|
||||
|
||||
testRunner.Delay(.2);
|
||||
|
||||
// Perform and validate 5 redoes
|
||||
for (int z = 0; z <= 4; z++)
|
||||
{
|
||||
int meshCountBeforeRedo = scene.Children.Count;
|
||||
testRunner.ClickByName("3D View Redo");
|
||||
|
||||
testRunner.WaitFor(() => meshCountBeforeRedo + 1 == scene.Children.Count);
|
||||
Assert.AreEqual(meshCountBeforeRedo + 1, scene.Children.Count);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ValidateDoUndoOnUnGroupSingleMesh()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Initialize
|
||||
testRunner.AddItemToBed(partName: "Row Item MH Logo.stl")
|
||||
.Delay(.1)
|
||||
.ClickByName("MH Logo.stl");
|
||||
Assert.IsNotNull(scene.SelectedItem);
|
||||
testRunner.WaitFor(() => scene.Children.Count() == 1);
|
||||
Assert.AreEqual(1, scene.Children.Count());
|
||||
|
||||
// test un-group single mesh
|
||||
testRunner.RunDoUndoTest(
|
||||
scene,
|
||||
() =>
|
||||
{
|
||||
// Set focus
|
||||
testRunner.ClickByName("View3DWidget")
|
||||
// Ungroup
|
||||
.SelectAll()
|
||||
.ClickByName("Ungroup Button")
|
||||
// Blur
|
||||
.SelectNone()
|
||||
// Assert
|
||||
.WaitFor(() => scene.Children.Count() == 3);
|
||||
Assert.AreEqual(3, scene.Children.Count());
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ValidateDoUndoOnGroup2Items()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Initialize
|
||||
AddBoxABoxBToBed(testRunner, scene);
|
||||
Assert.AreEqual(2, scene.Children.Count());
|
||||
|
||||
// test group 2 objects
|
||||
testRunner.RunDoUndoTest(
|
||||
scene,
|
||||
() =>
|
||||
{
|
||||
// Select all
|
||||
testRunner.ClickByName("View3DWidget")
|
||||
.SelectAll()
|
||||
// Group items
|
||||
.ClickByName("Group Button")
|
||||
// Clear selection
|
||||
.SelectNone()
|
||||
// Assert
|
||||
.WaitFor(() => scene.SelectedItem == null)
|
||||
.WaitFor(() => scene.Children.Count() == 1);
|
||||
Assert.AreEqual(1, scene.Children.Count());
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ValidateDoUndoUnGroup2Items()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Initialize
|
||||
AddBoxABoxBToBed(testRunner, scene);
|
||||
Assert.AreEqual(2, scene.Children.Count());
|
||||
Assert.AreEqual(3, scene.DescendantsAndSelf().Count(), "The scene and the 2 objects");
|
||||
|
||||
// Select all
|
||||
testRunner.ClickByName("View3DWidget")
|
||||
.SelectAll()
|
||||
// Group
|
||||
.ClickByName("Group Button")
|
||||
// Blur
|
||||
.SelectNone()
|
||||
.WaitFor(() => scene.Children.Count() == 1);
|
||||
Assert.AreEqual(1, scene.Children.Count());
|
||||
// group object can now process holes so it is a source object and has an extra object in it.
|
||||
Assert.AreEqual(5, scene.DescendantsAndSelf().Count(), "The scene, the group and the 2 objects");
|
||||
|
||||
// test un-group 2 grouped objects
|
||||
testRunner.RunDoUndoTest(
|
||||
scene,
|
||||
() =>
|
||||
{
|
||||
// Ungroup
|
||||
testRunner.SelectAll();
|
||||
testRunner.ClickByName("Ungroup Button");
|
||||
|
||||
// Blur
|
||||
testRunner.SelectNone();
|
||||
testRunner.WaitFor(() => scene.Children.Count() == 2);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(2, scene.Children.Count());
|
||||
Assert.AreEqual(3, scene.DescendantsAndSelf().Count(), "The scene and the 2 objects");
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ValidateDoUndoMirror()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Initialize
|
||||
AddCoinToBed(testRunner, scene);
|
||||
|
||||
// test mirror operations
|
||||
testRunner.RunDoUndoTest(
|
||||
scene,
|
||||
() =>
|
||||
{
|
||||
// Mirror
|
||||
testRunner.RightClickByName(CoinName, offset: new Point2D(-5, 0))
|
||||
.ClickByName("Modify Menu Item")
|
||||
.ClickByName("Transform Menu Item")
|
||||
.ClickByName("Mirror Menu Item")
|
||||
.ClickByName("Mirror On DropDownList");
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
// NOTE: This test once failed on GLFW. Could be timing or accidental input.
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ValidateDoUndoTranslateXY()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Initialize
|
||||
AddCoinToBed(testRunner, scene);
|
||||
|
||||
// NOTE: Test failed with this once:
|
||||
// Should be same (6): ' "Matrix": "[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,-10.000661239027977,-19.05065578967333,-5.421010862427522E-17,1.0]",
|
||||
// ' ' "Matrix": "[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,2.999338760972023,-24.00067986547947,-5.421010862427522E-17,1.0]",
|
||||
// Expected: True
|
||||
// But was: False
|
||||
// UndoTestExtensionMethods.SceneFilesAreSame(String fileName1, String fileName2, Boolean expectedResult) line 474
|
||||
// UndoTestExtensionMethods.AssertUndoRedo(AutomationRunner testRunner, InteractiveScene scene, String scenePath, String preOperationPath, String postOperationPath, Int32 preOperationDescendantCount, Int32 postOperationDescendantCount) line 541
|
||||
// UndoTestExtensionMethods.RunDoUndoTest(AutomationRunner testRunner, InteractiveScene scene, Action performOperation) line 453
|
||||
|
||||
// test drag x y translation
|
||||
testRunner.RunDoUndoTest(
|
||||
scene,
|
||||
() =>
|
||||
{
|
||||
// Drag in XY
|
||||
var part = testRunner.GetObjectByName(CoinName, out _) as IObject3D;
|
||||
var start = part.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center;
|
||||
testRunner.DragDropByName(CoinName, CoinName, offsetDrag: new Point2D(-4, 0), offsetDrop: new Point2D(40, 0));
|
||||
var end = part.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center;
|
||||
|
||||
// NOTE: Test failed with this once: Expected: greater than 15.399987526237965d, But was: 15.399987526237965d
|
||||
// ClickWidget now waits for 2 redraws in case there is more deferred processing.
|
||||
|
||||
// Assert
|
||||
Assert.Greater(end.X, start.X);
|
||||
Assert.Less(end.Y, start.Y);
|
||||
Assert.True(Math.Abs(end.Z - start.Z) < .001);
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
// Parallel testing of this single test.
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY1() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY2() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY3() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY4() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY5() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY6() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY7() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY8() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXY9() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXYa() => await ValidateDoUndoTranslateXY();
|
||||
//[Test, ChildProcessTest] public async Task ValidateDoUndoTranslateXYb() => await ValidateDoUndoTranslateXY();
|
||||
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ValidateDoUndoTranslateZ()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(testRunner =>
|
||||
{
|
||||
testRunner.OpenPartTab();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
// Initialize
|
||||
AddCoinToBed(testRunner, scene);
|
||||
|
||||
// test z translation
|
||||
testRunner.RunDoUndoTest(
|
||||
scene,
|
||||
() =>
|
||||
{
|
||||
// Drag in Z
|
||||
var part = testRunner.GetObjectByName(CoinName, out _) as IObject3D;
|
||||
var startZ = part.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center.Z;
|
||||
testRunner.DragDropByName("MoveInZControl", "MoveInZControl", offsetDrag: new Point2D(0, 0), offsetDrop: new Point2D(0, 40))
|
||||
.Delay();
|
||||
var endZ = part.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center.Z;
|
||||
|
||||
// Assert
|
||||
Assert.Greater(endZ, startZ);
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1300);
|
||||
}
|
||||
|
||||
private static void AddBoxABoxBToBed(AutomationRunner testRunner, InteractiveScene scene)
|
||||
{
|
||||
var item = "Calibration - Box.stl";
|
||||
// NOTE: Test once failed here. Probably due to timing.
|
||||
testRunner.AddItemToBed()
|
||||
.Delay(.1)
|
||||
// move the first one over
|
||||
.DragDropByName(item, item, offsetDrop: new Point2D(40, 40));
|
||||
var part = testRunner.GetObjectByName(item, out _) as IObject3D;
|
||||
part.Name = "BoxA";
|
||||
|
||||
testRunner.AddItemToBed()
|
||||
.Delay(.1);
|
||||
|
||||
part = testRunner.GetObjectByName(item, out _) as IObject3D;
|
||||
part.Name = "BoxB";
|
||||
}
|
||||
|
||||
private static void AddCoinToBed(AutomationRunner testRunner, InteractiveScene scene)
|
||||
{
|
||||
testRunner.AddItemToBed(partName: "Row Item MatterControl - Coin.stl")
|
||||
.Delay(.1)
|
||||
// TODO: assert the part is centered on the bed
|
||||
.ClickByName(CoinName, offset: new Point2D(-4, 0));
|
||||
Assert.IsNotNull(scene.SelectedItem);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UndoTestExtensionMethods
|
||||
{
|
||||
public static void RunDoUndoTest(this AutomationRunner testRunner, InteractiveScene scene, Action performOperation)
|
||||
{
|
||||
string scenePath = Path.Combine(MatterControlUtilities.RootPath, "Tests", "temp", "undo_test_scene_" + Path.GetRandomFileName());
|
||||
|
||||
Directory.CreateDirectory(scenePath);
|
||||
Object3D.AssetsPath = Path.Combine(scenePath, "Assets");
|
||||
|
||||
Object3D.AssetsPath = Path.Combine(scenePath, "Assets");
|
||||
|
||||
// save the scene
|
||||
string preOperationPath = Path.Combine(scenePath, "preOperation.mcx");
|
||||
scene.Save(preOperationPath);
|
||||
|
||||
var preOperationDescendantCount = scene.DescendantsAndSelf().Count();
|
||||
|
||||
// Do the operation
|
||||
performOperation();
|
||||
|
||||
var postOperationDescendantCount = scene.DescendantsAndSelf().Count();
|
||||
|
||||
// save the scene
|
||||
string postOperationPath = Path.Combine(scenePath, scenePath, "postOperation.mcx");
|
||||
scene.Save(postOperationPath);
|
||||
|
||||
Assert.AreEqual(postOperationDescendantCount, scene.DescendantsAndSelf().Count());
|
||||
|
||||
// assert new save is different
|
||||
SceneFilesAreSame(postOperationPath, preOperationPath, false);
|
||||
|
||||
// select the part
|
||||
testRunner.Type("^a"); // clear the selection (type a space)
|
||||
testRunner.WaitFor(() => scene.SelectedItem != null);
|
||||
Assert.IsNotNull(scene.SelectedItem);
|
||||
|
||||
// with the part selected
|
||||
AssertUndoRedo(
|
||||
testRunner,
|
||||
scene,
|
||||
scenePath,
|
||||
preOperationPath,
|
||||
postOperationPath,
|
||||
preOperationDescendantCount,
|
||||
postOperationDescendantCount);
|
||||
|
||||
// unselect the part
|
||||
testRunner.Type(" ") // clear the selection (type a space)
|
||||
.WaitFor(() => scene.SelectedItem == null);
|
||||
Assert.IsNull(scene.SelectedItem);
|
||||
|
||||
// with the part unselected
|
||||
AssertUndoRedo(
|
||||
testRunner,
|
||||
scene,
|
||||
scenePath,
|
||||
preOperationPath,
|
||||
postOperationPath,
|
||||
preOperationDescendantCount,
|
||||
postOperationDescendantCount);
|
||||
}
|
||||
|
||||
private static void SceneFilesAreSame(string fileName1, string fileName2, bool expectedResult)
|
||||
{
|
||||
bool areSame = true;
|
||||
string[] fileContent1 = File.ReadAllLines(fileName1);
|
||||
string[] fileContent2 = File.ReadAllLines(fileName2);
|
||||
|
||||
for (int i = 0; i < Math.Min(fileContent1.Length, fileContent2.Length); i++)
|
||||
{
|
||||
areSame &= ValidateSceneLine(fileContent1[i], fileContent2[i]);
|
||||
if (expectedResult)
|
||||
{
|
||||
Assert.IsTrue(areSame, $"Should be same ({i}): '{fileContent1[i]}' '{fileContent2[i]}");
|
||||
}
|
||||
}
|
||||
|
||||
areSame &= fileContent1.Length == fileContent2.Length;
|
||||
if (expectedResult)
|
||||
{
|
||||
Assert.IsTrue(areSame, $"Should be same length: '{fileName1}' '{fileName2}");
|
||||
}
|
||||
|
||||
Assert.IsTrue(expectedResult == areSame, $"Should be different: '{fileName1}' '{fileName2}");
|
||||
}
|
||||
|
||||
private static bool ValidateSceneLine(string v1, string v2)
|
||||
{
|
||||
if (v1 == v2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (v1.Contains("Matrix")
|
||||
&& v2.Contains("Matrix"))
|
||||
{
|
||||
double[] test = new double[] { 0, 1, 2, 3 };
|
||||
var expected = JsonConvert.SerializeObject(test, Formatting.Indented);
|
||||
|
||||
// Figure out if the value content of these lines are equivalent.
|
||||
var data1 = v1.Substring(v1.IndexOf('['), v1.IndexOf(']') - v1.IndexOf('[') + 1);
|
||||
var matrix1 = new Matrix4X4(JsonConvert.DeserializeObject<double[]>(data1));
|
||||
|
||||
var data2 = v2.Substring(v2.IndexOf('['), v2.IndexOf(']') - v2.IndexOf('[') + 1);
|
||||
var matrix2 = new Matrix4X4(JsonConvert.DeserializeObject<double[]>(data2));
|
||||
|
||||
if (matrix1.Equals(matrix2, .001))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void AssertUndoRedo(AutomationRunner testRunner,
|
||||
InteractiveScene scene,
|
||||
string scenePath, string preOperationPath, string postOperationPath,
|
||||
int preOperationDescendantCount, int postOperationDescendantCount)
|
||||
{
|
||||
var preUndoDescendantsCount = scene.DescendantsAndSelf().Count();
|
||||
|
||||
// do an undo
|
||||
testRunner.ClickByName("3D View Undo");
|
||||
|
||||
testRunner.WaitFor(() => preOperationDescendantCount == scene.DescendantsAndSelf().Count());
|
||||
Assert.AreEqual(preOperationDescendantCount, scene.DescendantsAndSelf().Count());
|
||||
|
||||
// save the undo data
|
||||
string undoScenePath = Path.Combine(scenePath, "undoScene.mcx");
|
||||
var totalSceneItems = scene.DescendantsAndSelf().Count();
|
||||
var selectedItem = scene.SelectedItem;
|
||||
|
||||
Object3D.AssetsPath = Path.Combine(scenePath, "Assets");
|
||||
|
||||
scene.Save(undoScenePath);
|
||||
Assert.AreEqual(totalSceneItems, scene.DescendantsAndSelf().Count());
|
||||
Assert.AreEqual(selectedItem, scene.SelectedItem);
|
||||
|
||||
// After undo action, validate the persisted undoScene with the original 'before do' scene
|
||||
SceneFilesAreSame(preOperationPath, undoScenePath, true);
|
||||
|
||||
// now redo the undo
|
||||
testRunner.ClickByName("3D View Redo");
|
||||
|
||||
testRunner.WaitFor(() => postOperationDescendantCount == scene.DescendantsAndSelf().Count());
|
||||
Assert.AreEqual(postOperationDescendantCount, scene.DescendantsAndSelf().Count());
|
||||
|
||||
// save the redo
|
||||
string redoScenePath = Path.Combine(scenePath, "redoScene.mcx");
|
||||
scene.Save(redoScenePath);
|
||||
|
||||
// After redo action, validate the persisted redoScene with the original 'after do' scene
|
||||
SceneFilesAreSame(postOperationPath, redoScenePath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,780 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)]
|
||||
public class SliceSetingsTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RaftEnabledPassedToSliceEngine()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw()
|
||||
.AddAndSelectPrinter()
|
||||
.AddTestAssetsToLibrary(new[] { "Rook.amf" })
|
||||
.AddItemToBed("", "Row Item Rook")
|
||||
.SwitchToSliceSettings()
|
||||
.SelectSliceSettingsField(SettingsKey.create_raft)
|
||||
.WaitForReloadAll(() => testRunner.StartSlicing())
|
||||
.WaitFor(() => MatterControlUtilities.CompareExpectedSliceSettingValueWithActualVaue("enableRaft", "True"), 10);
|
||||
|
||||
// Call compare slice settings method here
|
||||
Assert.IsTrue(MatterControlUtilities.CompareExpectedSliceSettingValueWithActualVaue("enableRaft", "True"));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1224, overrideHeight: 800);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task RelativeRetractionExecutesCorrectly()
|
||||
{
|
||||
// NOTE: This test once timed out at 120, but took 38.4s when run on its own.
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForName("Cancel Wizard Button");
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator("Other", "Other"))
|
||||
{
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
var farthestE = 0.0;
|
||||
printer.Connection.LineReceived += (e, line) =>
|
||||
{
|
||||
// make sure the extrusion never goes back very far
|
||||
Assert.Greater(printer.Connection.CurrentExtruderDestination, farthestE - 10);
|
||||
farthestE = Math.Max(farthestE, printer.Connection.CurrentExtruderDestination);
|
||||
};
|
||||
|
||||
testRunner.AddItemToBed()
|
||||
.StartPrint(printer)
|
||||
.WaitFor(() => printer.Connection.Printing, 60) // wait for the print to start
|
||||
.WaitFor(() => !printer.Connection.Printing, 60); // wait for the print to finish
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task PauseOnLayerTest()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForName("Cancel Wizard Button");
|
||||
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
testRunner.AddItemToBed()
|
||||
.StartPrint(printer, pauseAtLayers: "4;2;a;not;6")
|
||||
.WaitForLayerAndResume(printer, 2)
|
||||
.WaitForLayerAndResume(printer, 4)
|
||||
.WaitForLayerAndResume(printer, 6)
|
||||
.WaitForPrintFinished(printer);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task OemSettingsChangeOfferedToUserTest()
|
||||
{
|
||||
await MatterControlUtilities.RunTest(async (testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
var expectedWarningName = ValidationErrors.SettingsUpdateAvailable + " Row";
|
||||
|
||||
// open the print menu and prove no oem message
|
||||
testRunner.OpenPrintPopupMenu();
|
||||
Assert.IsFalse(testRunner.NameExists(expectedWarningName, 1));
|
||||
// close the menu
|
||||
testRunner.ClickByName("PartPreviewContent")
|
||||
.WaitFor(() => !testRunner.NamedWidgetExists("Start Print Button"))
|
||||
// test again in case we have not downloaded the profile the first time
|
||||
.OpenPrintPopupMenu();
|
||||
Assert.IsFalse(testRunner.NameExists(expectedWarningName, 1));
|
||||
// close the menu
|
||||
testRunner.ClickByName("PartPreviewContent")
|
||||
.WaitFor(() => !testRunner.NamedWidgetExists("Start Print Button"));
|
||||
|
||||
Assert.AreEqual(0, (await ProfileManager.GetChangedOemSettings(printer)).Count());
|
||||
|
||||
// change some oem settings
|
||||
printer.Settings.SetValue(SettingsKey.layer_height, ".213", printer.Settings.OemLayer);
|
||||
printer.Settings.SetValue(SettingsKey.first_layer_height, ".213", printer.Settings.OemLayer);
|
||||
|
||||
Assert.AreEqual(2, (await ProfileManager.GetChangedOemSettings(printer)).Count());
|
||||
|
||||
// open menu again and check that warning is now visible
|
||||
testRunner.OpenPrintPopupMenu()
|
||||
.ClickByName(ValidationErrors.SettingsUpdateAvailable + " Button")
|
||||
.ClickByName(SettingsKey.layer_height + " Update");
|
||||
|
||||
Assert.AreEqual(1, (await ProfileManager.GetChangedOemSettings(printer)).Count());
|
||||
|
||||
testRunner.ClickByName("Cancel Wizard Button");
|
||||
|
||||
testRunner.OpenPrintPopupMenu();
|
||||
Assert.IsTrue(testRunner.NameExists(expectedWarningName, 1));
|
||||
|
||||
// close the menu
|
||||
testRunner.ClickByName("PartPreviewContent")
|
||||
.WaitFor(() => !testRunner.NamedWidgetExists("Start Print Button"))
|
||||
// open the menu button
|
||||
.ClickByName("Printer Overflow Menu")
|
||||
.ClickByName("Update Settings... Menu Item")
|
||||
.ClickByName(SettingsKey.first_layer_height + " Update");
|
||||
|
||||
// accept the last option
|
||||
Assert.AreEqual(0, (await ProfileManager.GetChangedOemSettings(printer)).Count());
|
||||
}
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task MenuStaysOpenOnRebuildSettings()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
// open the print menu and prove no oem message
|
||||
testRunner.OpenPrintPopupMenu();
|
||||
var supportWidegtName = SettingsKey.create_per_layer_support.SettingWidgetName();
|
||||
Assert.IsTrue(testRunner.NameExists(supportWidegtName, 1), "support option is visible");
|
||||
// toggle supports
|
||||
var supportButton = testRunner.GetWidgetByName(supportWidegtName, out _) as ICheckbox;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
testRunner.ClickByName(supportWidegtName)
|
||||
.WaitFor(() => supportButton.Checked)
|
||||
.ClickByName(supportWidegtName)
|
||||
.WaitFor(() => !supportButton.Checked);
|
||||
}
|
||||
Assert.IsTrue(testRunner.NameExists(supportWidegtName, 1), "Print menu should still be open after toggle supports");
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task SettingsStayOpenOnRebuildSettings()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator(pinSettingsOpen: false))
|
||||
{
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
testRunner.OpenSettingsSidebar(false);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
testRunner.Delay()
|
||||
.ClickByName("Slice Settings Overflow Menu")
|
||||
.Delay()
|
||||
.ClickByName("Advanced Menu Item")
|
||||
.Delay()
|
||||
.ClickByName("Slice Settings Overflow Menu")
|
||||
.Delay()
|
||||
.ClickByName("Simple Menu Item");
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest, Category("Emulator")]
|
||||
public async Task CancelWorksAsExpected()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should exist after add");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
printer.Settings.SetValue(SettingsKey.cancel_gcode, "G28 ; Cancel GCode");
|
||||
|
||||
testRunner.AddItemToBed()
|
||||
.StartPrint(printer, pauseAtLayers: "2")
|
||||
// Wait for the Ok button
|
||||
.WaitForName("Yes Button", 30);
|
||||
emulator.RunSlow = true;
|
||||
testRunner.ClickByName("Yes Button")
|
||||
// Cancel the Printing task
|
||||
.ClickByName("Stop Task Button")
|
||||
// Wait for and assert that printing has been canceled
|
||||
.WaitFor(() => printer.Connection.CommunicationState == PrinterCommunication.CommunicationStates.Connected);
|
||||
Assert.AreEqual(printer.Connection.CommunicationState, PrinterCommunication.CommunicationStates.Connected);
|
||||
|
||||
// Assert that two G28s were output to the terminal
|
||||
int g28Count = printer.Connection.TerminalLog.AllLines().Where(line => line.Contains("G28")).Count();
|
||||
Assert.AreEqual(2, g28Count, "The terminal log should contain one G28 from Start-GCode and one G28 from Cancel-GCode");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test /* Test will fail if screen size is and "HeatBeforeHoming" falls below the fold */, ChildProcessTest]
|
||||
public async Task ClearingCheckBoxClearsUserOverride()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw()
|
||||
.AddAndSelectPrinter("Airwolf 3D", "HD")
|
||||
// Navigate to Local Library
|
||||
.SwitchToPrinterSettings()
|
||||
.ClickByName("Features SliceSettingsTab");
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
CheckAndUncheckSetting(testRunner, printer, SettingsKey.heat_extruder_before_homing, false);
|
||||
|
||||
CheckAndUncheckSetting(testRunner, printer, SettingsKey.has_fan, true);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1224, overrideHeight: 900, maxTimeToRun: 600);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DualExtrusionShowsCorrectHotendData()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
using (var emulator = testRunner.LaunchAndConnectToPrinterEmulator())
|
||||
{
|
||||
testRunner.ClickByName("Features SliceSettingsTab");
|
||||
|
||||
// only 1 hotend and 1 extruder
|
||||
Assert.IsTrue(testRunner.NameExists("Hotend 0"));
|
||||
Assert.IsTrue(testRunner.NameExists("Bed TemperatureWidget"));
|
||||
Assert.IsFalse(testRunner.NameExists("Hotend 1", .1));
|
||||
|
||||
testRunner.ClickByName("Hotend 0");
|
||||
|
||||
// assert the temp is set when we first open (it comes from the material)
|
||||
ThemedNumberEdit tempWidget = testRunner.GetWidgetByName("Temperature Input", out _) as ThemedNumberEdit;
|
||||
Assert.AreEqual(240, (int)tempWidget.Value);
|
||||
|
||||
// change material
|
||||
var dropDownLists = testRunner.GetWidgetsByName("Hotend Preset Selector");
|
||||
Assert.AreEqual(1, dropDownLists.Count, "There is one. The slice settings and the pop out.");
|
||||
DropDownList materialSelector = dropDownLists[0].Widget as DropDownList;
|
||||
Assert.AreEqual("", materialSelector.SelectedValue);
|
||||
|
||||
testRunner.ClickByName("Hotend Preset Selector")
|
||||
.ClickByName("HIPS Menu");
|
||||
|
||||
// check the extruder count
|
||||
var extrudeButtons = testRunner.GetWidgetsByName("Extrude Button");
|
||||
Assert.AreEqual(1, extrudeButtons.Count, "There should be just one.");
|
||||
|
||||
int hipsGoalTemp = 220;
|
||||
testRunner.Delay();
|
||||
|
||||
// assert the temp changed to a new temp
|
||||
Assert.AreEqual(hipsGoalTemp,(int) tempWidget.Value, "The goal temp should match the material temp");
|
||||
// and the printer heat is off
|
||||
Assert.AreEqual(0, (int) emulator.CurrentExtruder.TargetTemperature, "The printer should report the heaters are off");
|
||||
|
||||
// turn on the heater
|
||||
testRunner.ClickByName("Toggle Heater")
|
||||
.Delay(1);
|
||||
|
||||
// assert the printer is heating
|
||||
Assert.AreEqual(hipsGoalTemp, (int)emulator.CurrentExtruder.TargetTemperature, "The printer should report the expected goal temp");
|
||||
|
||||
// turn off the heater
|
||||
testRunner.ClickByName("Toggle Heater")
|
||||
.Delay(1);
|
||||
|
||||
// assert the printer is off
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature, "The printer should report the heaters are off");
|
||||
|
||||
// type in a temp when the heating is off
|
||||
testRunner.ClickByName("Temperature Input")
|
||||
.Type("110")
|
||||
.Type("{Enter}")
|
||||
.Delay();
|
||||
|
||||
// assert the printer is off
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// and the heat toggle is showing on
|
||||
ICheckbox heatToggle = testRunner.GetWidgetByName("Toggle Heater", out _) as ICheckbox;
|
||||
Assert.IsFalse(heatToggle.Checked);
|
||||
|
||||
// turn it on
|
||||
testRunner.ClickByName("Toggle Heater");
|
||||
Assert.AreEqual(110, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// adjust when on
|
||||
testRunner.ClickByName("Temperature Input")
|
||||
.Type("104")
|
||||
.Type("{Enter}")
|
||||
.Delay();
|
||||
Assert.AreEqual(104, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// type in 0 and have the heater turn off
|
||||
testRunner.ClickByName("Temperature Input")
|
||||
.Type("^a")
|
||||
.Type("0")
|
||||
.Type("{Enter}")
|
||||
.Delay()
|
||||
// type in 60 and have the heater turn on
|
||||
.ClickByName("Temperature Input")
|
||||
.Type("^a")
|
||||
.Type("60")
|
||||
.Type("{Enter}")
|
||||
.Delay()
|
||||
.ClickByName("Toggle Heater");
|
||||
Assert.AreEqual(60, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// click the remove override and have it change to default temp
|
||||
// NOTE: Got test failure twice: The printer should report the expected goal temp
|
||||
// Expected: 220
|
||||
// But was: 60
|
||||
// Even though WaitFor was used. Maybe the emulator is just delayed sometimes.
|
||||
// Adding Math.Round anyway. And more waiting.
|
||||
testRunner.ClickByName("Restore temperature")
|
||||
.WaitFor(() => hipsGoalTemp == (int)Math.Round(emulator.CurrentExtruder.TargetTemperature), maxSeconds: 10);
|
||||
Assert.AreEqual(hipsGoalTemp, (int)Math.Round(emulator.CurrentExtruder.TargetTemperature), "The printer should report the expected goal temp");
|
||||
|
||||
// type in 60 and have the heater turn on
|
||||
testRunner.ClickByName("Temperature Input")
|
||||
.Type("^a")
|
||||
.Type("60")
|
||||
.Type("{Enter}")
|
||||
.Delay();
|
||||
Assert.AreEqual(60, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// type in 0 and have the heater turn off
|
||||
testRunner.ClickByName("Temperature Input")
|
||||
.Type("^a")
|
||||
.Type("0")
|
||||
.Type("{Enter}")
|
||||
.Delay();
|
||||
|
||||
// assert the printer is not heating
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
// and the on toggle is showing off
|
||||
Assert.IsFalse(heatToggle.Checked);
|
||||
|
||||
// test that the load filament button works and closes correctly
|
||||
testRunner.ClickByName("Temperature Input")
|
||||
.Type("^a")
|
||||
.Type("104")
|
||||
.Type("{Enter}")
|
||||
.Delay()
|
||||
.ClickByName("Load Filament Button")
|
||||
.ClickByName("Load Filament");
|
||||
Assert.AreEqual(104, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
testRunner.Delay()
|
||||
.ClickByName("Cancel Wizard Button")
|
||||
.Delay();
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
testRunner.ClickByName("Hotend 0")
|
||||
.ClickByName("Load Filament Button")
|
||||
.ClickByName("Load Filament")
|
||||
.Delay();
|
||||
Assert.AreEqual(104, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
var systemWindow = testRunner.GetWidgetByName("Cancel Wizard Button", out SystemWindow containingWindow);
|
||||
// close the window through windows (alt-f4)
|
||||
testRunner.Type("%{F4}");
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// Switch back to the general tab
|
||||
testRunner.ClickByName("General SliceSettingsTab")
|
||||
.SelectSliceSettingsField(SettingsKey.extruder_count)
|
||||
.Type("2")
|
||||
.Type("{Enter}");
|
||||
|
||||
// there are now 2 hotends and 2 extruders
|
||||
Assert.IsTrue(testRunner.NameExists("Hotend 0"));
|
||||
Assert.IsTrue(testRunner.NameExists("Hotend 1"));
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
SetCheckBoxSetting(testRunner, printer, SettingsKey.extruders_share_temperature, true);
|
||||
|
||||
// there is one hotend and 2 extruders
|
||||
Assert.IsTrue(testRunner.NameExists("Hotend 0"));
|
||||
Assert.IsFalse(testRunner.NameExists("Hotend 1", .1));
|
||||
|
||||
testRunner.ClickByName("Hotend 0");
|
||||
|
||||
extrudeButtons = testRunner.GetWidgetsByName("Extrude Button");
|
||||
Assert.AreEqual(2, extrudeButtons.Count, "Now there should be two.");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public void SliceSettingsOrganizerSupportsKeyLookup()
|
||||
{
|
||||
StaticData.RootPath = MatterControlUtilities.StaticDataPath;
|
||||
|
||||
var organizer = PrinterSettings.Layout;
|
||||
|
||||
var userLevel = organizer.AllSliceSettings;
|
||||
Assert.IsNotNull(userLevel);
|
||||
|
||||
// Confirm expected keys
|
||||
Assert.IsTrue(userLevel.ContainsKey("bed_temperature"));
|
||||
Assert.IsTrue(organizer.AllSliceSettings.ContainsKey("bed_temperature"));
|
||||
Assert.IsTrue(organizer.AllPrinterSettings.ContainsKey("extruder_count"));
|
||||
|
||||
// Confirm non-existent key
|
||||
Assert.IsFalse(userLevel.ContainsKey("non_existing_setting"));
|
||||
Assert.IsFalse(organizer.AllSliceSettings.ContainsKey("non_existing_setting"));
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task SwitchingMaterialsCausesSettingsChangedEvents()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter();
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
printer.Settings.OemLayer[SettingsKey.layer_height] = ".2";
|
||||
|
||||
int layerHeightChangedCount = 0;
|
||||
|
||||
PrinterSettings.AnyPrinterSettingChanged += (s, stringEvent) =>
|
||||
{
|
||||
if (stringEvent != null)
|
||||
{
|
||||
if (stringEvent.Data == SettingsKey.layer_height)
|
||||
{
|
||||
layerHeightChangedCount++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Navigate to Local Library
|
||||
testRunner.SwitchToSliceSettings();
|
||||
|
||||
// Navigate to General Tab -> Layers / Surface Tab
|
||||
testRunner.SelectSliceSettingsField(SettingsKey.layer_height);
|
||||
Assert.AreEqual(0, layerHeightChangedCount, "No change to layer height yet.");
|
||||
|
||||
var theme = ApplicationController.Instance.Theme;
|
||||
var indicator = testRunner.GetWidgetByName("Layer Thickness OverrideIndicator", out _);
|
||||
|
||||
Assert.AreEqual(Color.Transparent, indicator.BackgroundColor);
|
||||
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("Fine Menu")
|
||||
.Delay(.5);
|
||||
Assert.AreEqual(1, layerHeightChangedCount, "Changed to fine.");
|
||||
Assert.AreEqual(theme.PresetColors.QualityPreset, indicator.BackgroundColor);
|
||||
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("Standard Menu")
|
||||
.Delay(.5);
|
||||
Assert.AreEqual(2, layerHeightChangedCount, "Changed to standard.");
|
||||
Assert.AreEqual(theme.PresetColors.QualityPreset, indicator.BackgroundColor);
|
||||
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("- none - Menu Item")
|
||||
.Delay(.5);
|
||||
Assert.AreEqual(Color.Transparent, indicator.BackgroundColor);
|
||||
Assert.AreEqual(3, layerHeightChangedCount, "Changed to - none -.");
|
||||
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("Standard Menu")
|
||||
.Delay(.5);
|
||||
Assert.AreEqual(4, layerHeightChangedCount, "Changed to standard.");
|
||||
Assert.AreEqual(theme.PresetColors.QualityPreset, indicator.BackgroundColor);
|
||||
|
||||
// TODO: delete one of the settings
|
||||
// asserts that the deleted setting has been removed from the list
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 1000);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task ValidateSaveMenuItemLabels()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
|
||||
// Navigate to Slice Settings Tab and make sure Layer Thickness row is visible
|
||||
testRunner.SwitchToSliceSettings()
|
||||
.NavigateToSliceSettingsField(SettingsKey.layer_height);
|
||||
|
||||
// Set Quality to "Coarse" and Material to "ABS"
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("Coarse Menu")
|
||||
.ClickByName("Material")
|
||||
.ClickByName("ABS Menu")
|
||||
.RightClickByName("Layer Thickness OverrideIndicator", offset: new Point2D(30, 0))
|
||||
.ClickByName("Save to Menu Item")
|
||||
.Delay(.5);
|
||||
Assert.IsTrue(testRunner.NameExists("Quality Setting 'Coarse' Menu Item"));
|
||||
Assert.IsTrue(testRunner.NameExists("Material Setting 'ABS' Menu Item"));
|
||||
|
||||
// Set Quality to "Fine" and Material to "BENDLAY"
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("Fine Menu")
|
||||
.ClickByName("Material")
|
||||
.ClickByName("BENDLAY Menu")
|
||||
.RightClickByName("Layer Thickness OverrideIndicator", offset: new Point2D(30, 0))
|
||||
.ClickByName("Save to Menu Item")
|
||||
.Delay(.5);
|
||||
Assert.IsTrue(testRunner.NameExists("Quality Setting 'Fine' Menu Item"));
|
||||
Assert.IsTrue(testRunner.NameExists("Material Setting 'BENDLAY' Menu Item"));
|
||||
|
||||
// Set Quality to none
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("- none - Menu Item")
|
||||
.RightClickByName("Layer Thickness OverrideIndicator", offset: new Point2D(30, 0))
|
||||
.ClickByName("Save to Menu Item")
|
||||
.Delay(.5);
|
||||
Assert.IsTrue(testRunner.NameExists("Quality Setting Menu Item"));
|
||||
Assert.IsTrue(testRunner.NameExists("Material Setting 'BENDLAY' Menu Item"));
|
||||
|
||||
// Set Quality to "Standard" and Material to none
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("Standard Menu")
|
||||
.ClickByName("Material")
|
||||
.ClickByName("- none - Menu Item")
|
||||
.RightClickByName("Layer Thickness OverrideIndicator", offset: new Point2D(30, 0))
|
||||
.ClickByName("Save to Menu Item")
|
||||
.Delay(.5);
|
||||
Assert.IsTrue(testRunner.NameExists("Quality Setting 'Standard' Menu Item"));
|
||||
Assert.IsTrue(testRunner.NameExists("Material Setting Menu Item"));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 1000);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task DeleteProfileWorksForGuest()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
// assert no profiles
|
||||
Assert.AreEqual(0, ProfileManager.Instance.ActiveProfiles.Count());
|
||||
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD");
|
||||
|
||||
// assert one profile
|
||||
Assert.AreEqual(1, ProfileManager.Instance.ActiveProfiles.Count(), "One profile should exist after add");
|
||||
|
||||
MatterControlUtilities.DeleteSelectedPrinter(testRunner);
|
||||
|
||||
// assert no profiles
|
||||
Assert.AreEqual(0, ProfileManager.Instance.ActiveProfiles.Count(), "No profiles should exist after delete");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, overrideWidth: 1224, overrideHeight: 900);
|
||||
}
|
||||
|
||||
private static void SetCheckBoxSetting(AutomationRunner testRunner, PrinterConfig printer, string settingToChange, bool valueToSet)
|
||||
{
|
||||
var settingsData = PrinterSettings.SettingsData[settingToChange];
|
||||
string checkBoxName = $"{settingsData.PresentationName} Field";
|
||||
|
||||
Assert.IsTrue(printer.Settings.GetValue<bool>(settingToChange) != valueToSet);
|
||||
|
||||
//testRunner.ScrollIntoView(checkBoxName);
|
||||
//testRunner.ClickByName(checkBoxName);
|
||||
testRunner.SelectSliceSettingsField(settingToChange)
|
||||
// give some time for the ui to update if necessary
|
||||
.Delay(2);
|
||||
|
||||
Assert.IsTrue(printer.Settings.GetValue<bool>(settingToChange) == valueToSet);
|
||||
}
|
||||
|
||||
private static void CheckAndUncheckSetting(AutomationRunner testRunner, PrinterConfig printer, string settingToChange, bool expected)
|
||||
{
|
||||
// Assert that the checkbox is currently unchecked, and there is no user override
|
||||
Assert.IsFalse(printer.Settings.UserLayer.ContainsKey(settingToChange));
|
||||
|
||||
// Click the checkbox
|
||||
SetCheckBoxSetting(testRunner, printer, settingToChange, !expected);
|
||||
|
||||
// Assert the checkbox is checked and the user override is set
|
||||
Assert.IsTrue(printer.Settings.UserLayer.ContainsKey(settingToChange));
|
||||
|
||||
// make sure the setting is still open in case of a reload all
|
||||
testRunner.NavigateToSliceSettingsField(settingToChange)
|
||||
// Click the cancel user override button
|
||||
.ClickByName("Restore " + settingToChange)
|
||||
.Delay(2);
|
||||
|
||||
// Assert the checkbox is unchecked and there is no user override
|
||||
Assert.IsTrue(printer.Settings.GetValue<bool>(settingToChange) == expected);
|
||||
Assert.IsFalse(printer.Settings.UserLayer.ContainsKey(settingToChange));
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task HasHeatedBedCheckedHidesBedTemperatureOptions()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw()
|
||||
.AddAndSelectPrinter("Airwolf 3D", "HD")
|
||||
// Navigate to Settings Tab and make sure Bed Temp Text box is visible
|
||||
.SwitchToSliceSettings()
|
||||
.ClickByName("Slice Settings Overflow Menu")
|
||||
.ClickByName("Advanced Menu Item")
|
||||
.Delay()
|
||||
.SelectSliceSettingsField(SettingsKey.bed_temperature)
|
||||
.SelectSliceSettingsField(SettingsKey.temperature)
|
||||
// Uncheck Has Heated Bed checkbox and make sure Bed Temp Textbox is not visible
|
||||
.SwitchToPrinterSettings()
|
||||
//.SelectSliceSettingsField(SettingsKey.has_heated_bed) // NOTE: Happened once: System.Exception : ClickByName Failed: Named GuiWidget not found [Hardware SliceSettingsTab]
|
||||
//.Delay(1.0) // Wait for reload reliably:
|
||||
.WaitForReloadAll(() => testRunner.SelectSliceSettingsField(SettingsKey.has_heated_bed))
|
||||
.SwitchToSliceSettings()
|
||||
.NavigateToSliceSettingsField(SettingsKey.temperature);
|
||||
|
||||
Assert.IsFalse(testRunner.WaitForName("Bed Temperature Textbox", .5), "Filament -> Bed Temp should not be visible after Heated Bed unchecked");
|
||||
|
||||
// Make sure Bed Temperature Options are not visible in printer controls
|
||||
testRunner.SwitchToControlsTab();
|
||||
|
||||
Assert.IsFalse(testRunner.WaitForName("Bed Temperature Controls Widget", .5), "Controls -> Bed Temp should not be visible after Heated Bed unchecked");
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public async Task QualitySettingsStayAsOverrides()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.WaitForFirstDraw();
|
||||
|
||||
// Add Guest printers
|
||||
testRunner.AddAndSelectPrinter("Airwolf 3D", "HD")
|
||||
.SwitchToSliceSettings();
|
||||
|
||||
var printer = testRunner.FirstPrinter();
|
||||
|
||||
testRunner.SelectSliceSettingsField(SettingsKey.layer_height)
|
||||
.Type(".5")
|
||||
// Force lose focus
|
||||
.SelectSliceSettingsField(SettingsKey.first_layer_height)
|
||||
.WaitFor(() => printer.Settings.GetValue<double>(SettingsKey.layer_height) == 0.5);
|
||||
|
||||
Assert.AreEqual(printer.Settings.GetValue<double>(SettingsKey.layer_height).ToString(), "0.5", "Layer height is what we set it to");
|
||||
|
||||
testRunner.ClickByName("Quality")
|
||||
.ClickByName("Fine Menu");
|
||||
|
||||
testRunner.WaitFor(() => printer.Settings.GetValue<double>(SettingsKey.layer_height) == 0.1);
|
||||
Assert.AreEqual(printer.Settings.GetValue<double>(SettingsKey.layer_height).ToString(), "0.1", "Layer height is the fine override");
|
||||
|
||||
// Close Airwolf
|
||||
testRunner.CloseFirstPrinterTab();
|
||||
|
||||
// Assert printer counts
|
||||
Assert.AreEqual(1, ProfileManager.Instance.ActiveProfiles.Count(), "ProfileManager should have 1 profile after Airwolf close");
|
||||
Assert.AreEqual(0, ApplicationController.Instance.ActivePrinters.Count(), "Zero printers should be active after Airwolf close");
|
||||
|
||||
testRunner.AddAndSelectPrinter("BCN3D", "Sigma");
|
||||
|
||||
// Assert printer counts
|
||||
Assert.AreEqual(2, ProfileManager.Instance.ActiveProfiles.Count(), "ProfileManager has 2 profiles");
|
||||
Assert.AreEqual(1, ApplicationController.Instance.ActivePrinters.Count(), "One printer should be active after BCN add");
|
||||
|
||||
// Close BCN
|
||||
testRunner.CloseFirstPrinterTab()
|
||||
// Reopen Airwolf
|
||||
.SwitchToHardwareTab()
|
||||
.DoubleClickByName("Airwolf 3D HD Node")
|
||||
.Delay(0.2);
|
||||
|
||||
printer = testRunner.FirstPrinter();
|
||||
|
||||
testRunner.WaitFor(() => printer.Settings.GetValue<double>(SettingsKey.layer_height) == 0.1);
|
||||
Assert.AreEqual(printer.Settings.GetValue<double>(SettingsKey.layer_height).ToString(), "0.1", "Layer height is the fine override");
|
||||
|
||||
// Switch to Slice Settings Tab
|
||||
testRunner.ClickByName("Slice Settings Tab")
|
||||
.ClickByName("Quality")
|
||||
.ClickByName("- none - Menu Item")
|
||||
.WaitFor(() => printer.Settings.GetValue<double>(SettingsKey.layer_height) == 0.5);
|
||||
|
||||
Assert.AreEqual(printer.Settings.GetValue<double>(SettingsKey.layer_height).ToString(), "0.5", "Layer height is what we set it to");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, maxTimeToRun: 120);
|
||||
}
|
||||
|
||||
[Test, ChildProcessTest]
|
||||
public void CopyFromTest()
|
||||
{
|
||||
StaticData.RootPath = MatterControlUtilities.StaticDataPath;
|
||||
MatterControlUtilities.OverrideAppDataLocation(MatterControlUtilities.RootPath);
|
||||
|
||||
var settings = new PrinterSettings();
|
||||
settings.ID = "12345-print";
|
||||
settings.SetValue(SettingsKey.auto_connect, "1");
|
||||
settings.SetValue(SettingsKey.com_port, "some_com_port");
|
||||
settings.SetValue(SettingsKey.cancel_gcode, "hello world");
|
||||
|
||||
settings.Macros.Add(new GCodeMacro() { Name = "Macro1", GCode = "G28 ; Home Printer" });
|
||||
|
||||
settings.StagedUserSettings["retract_restart_extra_time_to_apply"] = "4";
|
||||
settings.StagedUserSettings["retract_restart_extra"] = "0.3";
|
||||
settings.StagedUserSettings["bridge_fan_speed"] = "50";
|
||||
|
||||
var sha1 = settings.ComputeSHA1();
|
||||
|
||||
var clone = new PrinterSettings();
|
||||
clone.CopyFrom(settings);
|
||||
|
||||
Assert.AreEqual(settings.ToJson(), clone.ToJson(), "Cloned settings via CopyFrom should equal source");
|
||||
Assert.AreEqual(sha1, clone.ComputeSHA1(), "Cloned settings via CopyFrom should equal source");
|
||||
}
|
||||
|
||||
private void CloseAllPrinterTabs(AutomationRunner testRunner)
|
||||
{
|
||||
// Close all printer tabs
|
||||
var mainViewWidget = testRunner.GetWidgetByName("PartPreviewContent", out _) as MainViewWidget;
|
||||
foreach (var tab in mainViewWidget.TabControl.AllTabs.Where(t => t.TabContent is PrinterTabPage).ToList())
|
||||
{
|
||||
if (tab is GuiWidget widget)
|
||||
{
|
||||
var closeWidget = widget.Descendants<ImageWidget>().First();
|
||||
closeWidget.InvokeClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
71
original/Tests/MatterControl.AutomationTests/SlicingTests.cs
Normal file
71
original/Tests/MatterControl.AutomationTests/SlicingTests.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.PolygonMesh;
|
||||
using MatterHackers.Agg.UI;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.GuiAutomation;
|
||||
using MatterHackers.Agg.PlatformAbstract;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using System.IO;
|
||||
using MatterHackers.MatterControl.CreatorPlugins;
|
||||
using MatterHackers.Agg.UI.Tests;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MatterHackers.MatterControl.UI
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI"), RunInApplicationDomain]
|
||||
public class SlicingTests
|
||||
{
|
||||
|
||||
[Test, RequiresSTA, RunInApplicationDomain]
|
||||
public void Slicing()
|
||||
{
|
||||
// Run a copy of MatterControl
|
||||
Action<AutomationTesterHarness> testToRun = (AutomationTesterHarness resultsHarness) =>
|
||||
{
|
||||
AutomationRunner testRunner = new AutomationRunner(MatterControlUtilities.DefaultTestImages);
|
||||
{
|
||||
|
||||
//Navigate to Local Library
|
||||
MatterControlUtilities.SelectAndAddPrinter(testRunner, "Airwolf 3D", "HD", true);
|
||||
|
||||
testRunner.ClickByName("Library Tab");
|
||||
|
||||
MatterControlUtilities.NavigateToFolder(testRunner, "Local Library Row Item Collection");
|
||||
testRunner.Wait(1);
|
||||
testRunner.ClickByName("Row Item Calibration - Box");
|
||||
testRunner.ClickByName("Row Item Calibration - Box Print Button");
|
||||
testRunner.Wait(1);
|
||||
testRunner.ClickByName("Layer View Tab");
|
||||
testRunner.Wait(1);
|
||||
testRunner.ClickByName("SettingsAndControls");
|
||||
testRunner.Wait(1);
|
||||
testRunner.ClickByName("Settings Tab");
|
||||
testRunner.Wait(1.1);
|
||||
testRunner.ClickByName("Skirt and Raft Tab");
|
||||
testRunner.Wait(1);
|
||||
testRunner.ClickByName("Create Raft Checkbox");
|
||||
testRunner.Wait(1);
|
||||
testRunner.ClickByName("Generate Gcode Button");
|
||||
testRunner.Wait(1.5);
|
||||
|
||||
|
||||
|
||||
|
||||
MatterControlUtilities.CloseMatterControl(testRunner);
|
||||
}
|
||||
};
|
||||
|
||||
AutomationTesterHarness testHarness = MatterControlUtilities.RunTest(testToRun);
|
||||
|
||||
Assert.IsTrue(testHarness.AllTestsPassed);
|
||||
Assert.IsTrue(testHarness.TestCount == 3); // make sure we ran all our tests
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using NUnit.Framework;
|
||||
using TestInvoker;
|
||||
|
||||
namespace MatterHackers.MatterControl.Tests.Automation
|
||||
{
|
||||
[TestFixture, Category("MatterControl.UI.Automation")]
|
||||
public class SqLiteLibraryProviderTests
|
||||
{
|
||||
[Test, ChildProcessTest]
|
||||
public async Task LibraryQueueViewRefreshesOnAddItem()
|
||||
{
|
||||
await MatterControlUtilities.RunTest((testRunner) =>
|
||||
{
|
||||
testRunner.OpenPartTab()
|
||||
.AddItemToBed();
|
||||
|
||||
var view3D = testRunner.GetWidgetByName("View3DWidget", out _) as View3DWidget;
|
||||
var scene = view3D.Object3DControlLayer.Scene;
|
||||
|
||||
testRunner.WaitFor(() => scene.SelectedItem != null);
|
||||
Assert.IsNotNull(scene.SelectedItem, "Expect part selection after Add to Bed action");
|
||||
|
||||
testRunner.ClickByName("Duplicate Button")
|
||||
// wait for the copy to finish
|
||||
.Delay(.1)
|
||||
.ClickByName("Remove Button")
|
||||
.SaveBedplateToFolder("0Test Part", "Local Library Row Item Collection")
|
||||
// Click Home -> Local Library
|
||||
.NavigateToLibraryHome()
|
||||
.NavigateToFolder("Local Library Row Item Collection");
|
||||
|
||||
// ensure that it is now in the library folder (that the folder updated)
|
||||
Assert.IsTrue(testRunner.WaitForName("Row Item 0Test Part"), "The part we added should be in the library");
|
||||
|
||||
testRunner.Delay(.5);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}, queueItemFolderToAdd: QueueTemplate.Three_Queue_Items, overrideWidth: 1300);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue