public void ExecuteCommand(DynamoModel.RecordableCommand command, string uniqueId, string extensionName) { // log that the command is being executed if (dynamoModel.DebugSettings.VerboseLogging) { dynamoModel.Logger.Log("Command: " + command); } var extnDetails = string.Format( "ExtensionCommandExecutive ( UniqueId: {0}, Name: {1}, commandTypeName: {2} )", uniqueId, extensionName, command.GetType().Name); Log(LogMessage.Info(extnDetails)); try { // run the command dynamoModel.ExecuteCommand(command); } catch (Exception e) { // clean up or show failure messages Log(LogMessage.Error(string.Format("{0}, from {1}", e.Message, extnDetails))); } }
private static XmlDocument RunCommandLineArgs(DynamoModel model, StartupUtils.CommandLineArguments cmdLineArgs) { var evalComplete = false; if (string.IsNullOrEmpty(cmdLineArgs.OpenFilePath)) { return(null); } if (!(string.IsNullOrEmpty(cmdLineArgs.CommandFilePath))) { Console.WriteLine("commandFilePath option is only available when running DynamoSandbox, not DynamoCLI"); } if (!(string.IsNullOrEmpty(cmdLineArgs.GeometryFilePath))) { Console.WriteLine("geometryFilePath option is only available when running DynamoWPFCLI, not DynamoCLI"); } cmdLineArgs.ImportedPaths.ToList().ForEach(path => { ImportAssembly(model, path); }); model.OpenFileFromPath(cmdLineArgs.OpenFilePath, true); Console.WriteLine("loaded file"); model.EvaluationCompleted += (o, args) => { evalComplete = true; }; // Build a list of states, by default there is only a single state `default` // If the desire is to have additional states you can add logic here to build // up a list and iterate through each state in the list using the loop below. // This must be done after potentially loading states from an external file. var stateNames = new List <String>(); stateNames.Add("default"); XmlDocument doc = null; foreach (var stateName in stateNames) { // Graph execution model.ExecuteCommand(new DynamoModel.RunCancelCommand(false, false)); while (evalComplete == false) { Thread.Sleep(250); } //if verbose was true, then print all nodes to the console if (!String.IsNullOrEmpty(cmdLineArgs.Verbose)) { doc = CreateXMLDoc(model); } evalComplete = false; } return(doc); }
public void CollapsedGroupDisplaysWarningIfNodeInWarningState() { // Adding a dummy node to the workspace var dummyNode = new DummyNode(); DynamoModel model = GetModel(); model.ExecuteCommand(new DynamoModel.CreateNodeCommand(dummyNode, 0, 0, true, true)); NodeViewModel dummyNodeViewModel = ViewModel.CurrentSpaceViewModel.Nodes .FirstOrDefault(x => x.NodeModel.GUID == dummyNode.GUID); ViewModel.Model.CurrentWorkspace.AddAndRegisterNode(dummyNode, false); //verify the node was created Assert.AreEqual(1, ViewModel.Model.CurrentWorkspace.Nodes.Count()); //Select the node for group DynamoSelection.Instance.Selection.Add(dummyNode); //Create a Group around that node ViewModel.AddAnnotationCommand.Execute(null); var annotation = ViewModel.Model.CurrentWorkspace.Annotations.FirstOrDefault(); var annotationViewModel = ViewModel.CurrentSpaceViewModel.Annotations.FirstOrDefault(); //Check if the group is created Assert.IsNotNull(annotation); //Clear the selection DynamoSelection.Instance.ClearSelection(); // Collapses the group annotationViewModel.IsExpanded = false; NodeModel dummyNodeModel = dummyNodeViewModel.NodeModel; var topLeft = new Point(dummyNodeViewModel.X, dummyNodeViewModel.Y); var botRight = new Point(dummyNodeViewModel.X + dummyNodeModel.Width, dummyNodeViewModel.Y + dummyNodeModel.Height); if (dummyNodeViewModel.ErrorBubble == null) { dummyNodeViewModel.ErrorBubble = new InfoBubbleViewModel(ViewModel); } InfoBubbleViewModel infoBubbleViewModel = dummyNodeViewModel.ErrorBubble; // The collection of messages the node receives ObservableCollection <InfoBubbleDataPacket> nodeMessages = infoBubbleViewModel.NodeMessages; nodeMessages.Add(new InfoBubbleDataPacket(InfoBubbleViewModel.Style.Warning, topLeft, botRight, "Warning", InfoBubbleViewModel.Direction.Top)); Assert.AreEqual(ElementState.Warning, annotationViewModel.AnnotationModel.GroupState); }
public void IteratorsDisplayWhenMoreThanOneMessage() { // Arrange OpenModel(@"core\Home.dyn"); var info1 = "Info 1"; var info2 = "Info 2"; var dummyNode = new DummyNode(); DynamoModel model = GetModel(); model.ExecuteCommand(new DynamoModel.CreateNodeCommand(dummyNode, 0, 0, true, true)); NodeViewModel dummyNodeViewModel = ViewModel.CurrentSpaceViewModel.Nodes .FirstOrDefault(x => x.NodeModel.GUID == dummyNode.GUID); if (dummyNodeViewModel.ErrorBubble == null) { dummyNodeViewModel.ErrorBubble = new InfoBubbleViewModel(ViewModel); } NodeModel dummyNodeModel = dummyNodeViewModel.NodeModel; var topLeft = new Point(dummyNodeModel.X, dummyNodeModel.Y); var botRight = new Point(dummyNodeModel.X + dummyNodeModel.Width, dummyNodeModel.Y + dummyNodeModel.Height); InfoBubbleViewModel infoBubbleViewModel = dummyNodeViewModel.ErrorBubble; // The collection of messages the node receives ObservableCollection <InfoBubbleDataPacket> nodeMessages = infoBubbleViewModel.NodeMessages; // Act Assert.IsFalse(infoBubbleViewModel.NodeInfoIteratorVisible); InfoBubbleDataPacket infoBubbleDataPacket1 = new InfoBubbleDataPacket(InfoBubbleViewModel.Style.Info, topLeft, botRight, info1, InfoBubbleViewModel.Direction.Top); nodeMessages.Add(infoBubbleDataPacket1); Assert.IsFalse(infoBubbleViewModel.NodeInfoIteratorVisible); InfoBubbleDataPacket infoBubbleDataPacket2 = new InfoBubbleDataPacket(InfoBubbleViewModel.Style.Info, topLeft, botRight, info2, InfoBubbleViewModel.Direction.Top); nodeMessages.Add(infoBubbleDataPacket2); Assert.IsTrue(infoBubbleViewModel.NodeInfoIteratorVisible); infoBubbleViewModel.DismissMessageCommand.Execute(infoBubbleDataPacket1); Assert.IsFalse(infoBubbleViewModel.NodeInfoIteratorVisible); }
/// <summary> /// Rewires nodes and newly placed watch node between them. /// </summary> /// <param name="dynamoModel"></param> /// <param name="startNode"></param> /// <param name="endNode"></param> /// <param name="watchNodeModel"></param> private void WireNewNode( DynamoModel dynamoModel, NodeModel startNode, NodeModel endNode, NodeModel watchNodeModel, ConnectorModel connector, IEnumerable <Point> connectorPinLocations, List <ModelBase> allCreatedModels, List <ModelBase> allDeletedModels) { (int startIndex, int endIndex) = GetPortIndex(connector); // Connect startNode and watch node dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(startNode.GUID, startIndex, PortType.Output, DynamoModel.MakeConnectionCommand.Mode.Begin)); dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(watchNodeModel.GUID, 0, PortType.Input, DynamoModel.MakeConnectionCommand.Mode.End)); // Connect watch node and endNode dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(watchNodeModel.GUID, 0, PortType.Output, DynamoModel.MakeConnectionCommand.Mode.Begin)); dynamoModel.ExecuteCommand(new DynamoModel.MakeConnectionCommand(endNode.GUID, endIndex, PortType.Input, DynamoModel.MakeConnectionCommand.Mode.End)); PlacePinsOnWires(startNode, watchNodeModel, connector, connectorPinLocations, allCreatedModels, allDeletedModels); }
public void LinterManagerStoresRuleEvaluationResults() { // Arrange var evaluationResultsBefore = model.LinterManager.RuleEvaluationResults.ToList(); SetupNodeNameChangedRule(mockRule); mockExtension.Object.AddLinterRule(mockRule.Object); // Act var failureNode = new DummyNode(); model.ExecuteCommand(new DynamoModel.CreateNodeCommand(failureNode, 0, 0, false, false)); // When setting a linter as the active linter, that linters Activate() gets called // which will initialize the rules using the init function. As we only have one mock rule // that checks if the node name is "NewNodeName" no failed evaluation results should be created here. model.LinterManager.ActiveLinter = model.LinterManager.AvailableLinters .Where(x => x.Id == MOCK_GUID) .FirstOrDefault(); // Update graph nodes name to trigger the node rule evaluation failureNode.Name = "NewNodeName"; // Assert CollectionAssert.IsEmpty(evaluationResultsBefore); Assert.That(model.LinterManager.RuleEvaluationResults.Count == 1); Assert.That(model.LinterManager.RuleEvaluationResults. Any(x => x.RuleId == MOCK_RULE_ID)); Assert.That(model.LinterManager.RuleEvaluationResults. Any(x => x is NodeRuleEvaluationResult)); Assert.That(model.LinterManager.RuleEvaluationResults. Where(x => x is NodeRuleEvaluationResult). Cast <NodeRuleEvaluationResult>(). Any(x => x.NodeId == failureNode.GUID.ToString())); }
public void NodeWarningBarVisibility() { OpenModel(@"core\Home.dyn"); var info = "Information"; // Arrange var dummyNode = new DummyNode(); DynamoModel model = GetModel(); model.ExecuteCommand(new DynamoModel.CreateNodeCommand(dummyNode, 0, 0, true, true)); NodeViewModel dummyNodeViewModel = ViewModel.CurrentSpaceViewModel.Nodes .FirstOrDefault(x => x.NodeModel.GUID == dummyNode.GUID); NodeModel dummyNodeModel = dummyNodeViewModel.NodeModel; if (dummyNodeViewModel.ErrorBubble == null) { dummyNodeViewModel.ErrorBubble = new InfoBubbleViewModel(ViewModel); } InfoBubbleViewModel infoBubbleViewModel = dummyNodeViewModel.ErrorBubble; ObservableCollection <InfoBubbleDataPacket> nodeMessages = infoBubbleViewModel.NodeMessages; // Assert Assert.IsFalse(dummyNodeViewModel.NodeWarningBarVisible); // Act InfoBubbleDataPacket infoBubbleDataPacket = new InfoBubbleDataPacket ( InfoBubbleViewModel.Style.Info, new Point(dummyNodeModel.X, dummyNodeModel.Y), new Point(dummyNodeModel.X + dummyNodeModel.Width, dummyNodeModel.Y + dummyNodeModel.Height), info, InfoBubbleViewModel.Direction.Top ); nodeMessages.Add(infoBubbleDataPacket); Assert.IsTrue(infoBubbleViewModel.NodeInfoVisible); infoBubbleViewModel.DismissMessageCommand.Execute(infoBubbleDataPacket); Assert.IsFalse(dummyNodeViewModel.NodeWarningBarVisible); }
public void CanDismissUserFacingMessages() { OpenModel(@"core\Home.dyn"); var info1 = "Dismissed Info 1"; // Arrange var dummyNode = new DummyNode(); DynamoModel model = GetModel(); model.ExecuteCommand(new DynamoModel.CreateNodeCommand(dummyNode, 0, 0, true, true)); NodeViewModel dummyNodeViewModel = ViewModel.CurrentSpaceViewModel.Nodes .FirstOrDefault(x => x.NodeModel.GUID == dummyNode.GUID); NodeModel dummyNodeModel = dummyNodeViewModel.NodeModel; var topLeft = new Point(dummyNodeModel.X, dummyNodeModel.Y); var botRight = new Point(dummyNodeModel.X + dummyNodeModel.Width, dummyNodeModel.Y + dummyNodeModel.Height); if (dummyNodeViewModel.ErrorBubble == null) { dummyNodeViewModel.ErrorBubble = new InfoBubbleViewModel(ViewModel); } InfoBubbleViewModel infoBubbleViewModel = dummyNodeViewModel.ErrorBubble; // The collection of messages the node receives ObservableCollection <InfoBubbleDataPacket> nodeMessages = infoBubbleViewModel.NodeMessages; // Act InfoBubbleDataPacket infoBubbleDataPacket = new InfoBubbleDataPacket(InfoBubbleViewModel.Style.Info, topLeft, botRight, info1, InfoBubbleViewModel.Direction.Top); nodeMessages.Add(infoBubbleDataPacket); Assert.AreEqual(1, infoBubbleViewModel.NodeInfoToDisplay.Count); Assert.AreEqual(0, infoBubbleViewModel.DismissedMessages.Count); Assert.IsTrue(infoBubbleViewModel.NodeInfoVisible); infoBubbleViewModel.DismissMessageCommand.Execute(infoBubbleDataPacket); // Assert Assert.AreEqual(0, infoBubbleViewModel.NodeInfoToDisplay.Count); Assert.AreEqual(1, infoBubbleViewModel.DismissedMessages.Count); Assert.AreEqual(info1, infoBubbleViewModel.DismissedMessages.First().Message); }
/// <summary> /// Places watch node at the midpoint of the connector /// </summary> internal List <ModelBase> PlaceWatchNode(ConnectorModel connector, IEnumerable <Point> connectorPinLocations, List <ModelBase> allDeletedModels) { var createdModels = new List <ModelBase>(); NodeModel startNode = ViewModel.ConnectorModel.Start.Owner; NodeModel endNode = ViewModel.ConnectorModel.End.Owner; this.Dispatcher.Invoke(() => { var watchNode = new Watch(); var nodeX = CurrentPosition.X - (watchNode.Width / 2); var nodeY = CurrentPosition.Y - (watchNode.Height / 2); DynamoModel.ExecuteCommand(new DynamoModel.CreateNodeCommand(watchNode, nodeX, nodeY, false, false)); createdModels.Add(watchNode); WireNewNode(DynamoModel, startNode, endNode, watchNode, connector, connectorPinLocations, createdModels, allDeletedModels); }); return(createdModels); }
private void OnPlaybackTimerTick(object sender, EventArgs e) { var timer = (DispatcherTimer)sender; timer.Stop(); // Stop the timer before command completes. if (loadedCommands.Count <= 0) // There's nothing else for playback. { if (ExitAfterPlayback == false) { // The playback is done, but the command file indicates that // Dynamo should not be shutdown after the playback, so here // we simply invalidate the timer. // playbackTimer = null; ChangeStateInternal(State.Stopped); } else { // The command file requires Dynamo be shutdown after all // commands has been played back. If that's the case, we'll // reconfigure the callback to a shutdown timer, and then // change its interval to the duration specified earlier. // playbackTimer.Tick -= OnPlaybackTimerTick; playbackTimer.Tick += OnShutdownTimerTick; var interval = TimeSpan.FromMilliseconds(PauseAfterPlayback); playbackTimer.Interval = interval; playbackTimer.Start(); // Start shutdown timer. ChangeStateInternal(State.ShuttingDown); } return; } // Remove the first command from the loaded commands. DynamoModel.RecordableCommand nextCommand = loadedCommands[0]; loadedCommands.RemoveAt(0); // Update the cached command references. PreviousCommand = CurrentCommand; CurrentCommand = nextCommand; if (nextCommand is DynamoModel.PausePlaybackCommand) { var command = nextCommand as DynamoModel.PausePlaybackCommand; PauseCommandPlayback(command.PauseDurationInMs); return; } try { // Execute the command, this may take a while longer than the timer // inverval (usually very short), that's why the timer was stopped // before the command execution starts. After the command is done, // the timer is then resumed for the next command in queue. // owningDynamoModel.ExecuteCommand(nextCommand); } catch (Exception exception) { // An exception is thrown while playing back a command. Remove any // pending commands and allow the "playbackTimer" to continue with // its next tick. Proper shutdown sequence will be initialized // when the "playbackTimer" tries to pick up the next command and // realized that there is no more commands waiting. // loadedCommands.Clear(); PlaybackException = exception; } timer.Start(); }
private static XmlDocument RunCommandLineArgs(DynamoModel model, StartupUtils.CommandLineArguments cmdLineArgs) { var evalComplete = false; if (string.IsNullOrEmpty(cmdLineArgs.OpenFilePath)) { return(null); } if (!(string.IsNullOrEmpty(cmdLineArgs.CommandFilePath))) { Console.WriteLine("commandFilePath option is only available when running DynamoSandbox, not DynamoCLI"); } model.OpenFileFromPath(cmdLineArgs.OpenFilePath, true); Console.WriteLine("loaded file"); model.EvaluationCompleted += (o, args) => { evalComplete = true; }; // Build a list of states, by default there is only a single state `default` // If the desire is to have additional states you can add logic here to build // up a list and iterate through each state in the list using the loop below. // This must be done after potentially loading states from an external file. var stateNames = new List <String>(); stateNames.Add("default"); var outputresults = new List <Dictionary <Guid, List <object> > >(); XmlDocument doc = null; foreach (var stateName in stateNames) { // Graph execution model.ExecuteCommand(new DynamoModel.RunCancelCommand(false, false)); while (evalComplete == false) { Thread.Sleep(250); } //if verbose was true, then print all nodes to the console if (!String.IsNullOrEmpty(cmdLineArgs.Verbose)) { doc = new XmlDocument(); var resultsdict = new Dictionary <Guid, List <object> >(); foreach (var node in model.CurrentWorkspace.Nodes) { var portvalues = new List <object>(); foreach (var port in node.OutPorts) { var value = node.GetValue(port.Index, model.EngineController); if (value.IsCollection) { portvalues.Add(GetStringRepOfCollection(value)); } else { portvalues.Add(value.StringData); } } resultsdict.Add(node.GUID, portvalues); } outputresults.Add(resultsdict); populateXmlDocWithResults(doc, outputresults); } evalComplete = false; } return(doc); }
private static XmlDocument RunCommandLineArgs(DynamoModel model, StartupUtils.CommandLineArguments cmdLineArgs) { var evalComplete = false; if (string.IsNullOrEmpty(cmdLineArgs.OpenFilePath)) { return(null); } if (!(string.IsNullOrEmpty(cmdLineArgs.CommandFilePath))) { Console.WriteLine("commandFilePath option is only available when running DynamoSandbox, not DynamoCLI"); } model.OpenFileFromPath(cmdLineArgs.OpenFilePath, true); Console.WriteLine("loaded file"); model.EvaluationCompleted += (o, args) => { evalComplete = true; }; if (!string.IsNullOrEmpty(cmdLineArgs.PresetFilePath)) { //first load the openfile nodegraph var originalGraphdoc = XmlHelper.CreateDocument("tempworkspace"); originalGraphdoc.Load(cmdLineArgs.OpenFilePath); var graph = NodeGraph.LoadGraphFromXml(originalGraphdoc, model.NodeFactory); //then load the presetsfile nodegraph (this should only contain presets), var presetsDoc = XmlHelper.CreateDocument("presetstempworkspace"); presetsDoc.Load(cmdLineArgs.PresetFilePath); //when we load the presets we need to pass in the nodeModels from the original graph var presets = NodeGraph.LoadPresetsFromXml(presetsDoc, graph.Nodes); //load the presets contained in the presetsfile into the workspace, model.CurrentWorkspace.ImportPresets(presets); } //build a list of states, for now, none, a single state, or all of them //this must be done after potentially loading states from external file var stateNames = new List <String>(); if (!string.IsNullOrEmpty(cmdLineArgs.PresetStateID)) { if (cmdLineArgs.PresetStateID == "all") { foreach (var state in model.CurrentWorkspace.Presets) { stateNames.Add(state.Name); } } else { stateNames.Add(cmdLineArgs.PresetStateID); } } else { stateNames.Add("default"); } var outputresults = new List <Dictionary <Guid, List <object> > >(); XmlDocument doc = null; foreach (var stateName in stateNames) { Guid stateGuid = Guid.Empty; var state = model.CurrentWorkspace.Presets.Where(x => x.Name == stateName).FirstOrDefault(); if (state != null) { stateGuid = state.GUID; } model.ExecuteCommand(new DynamoModel.ApplyPresetCommand(model.CurrentWorkspace.Guid, stateGuid)); model.ExecuteCommand(new DynamoModel.RunCancelCommand(false, false)); while (evalComplete == false) { Thread.Sleep(250); } //if verbose was true, then print all nodes to the console if (!String.IsNullOrEmpty(cmdLineArgs.Verbose)) { doc = new XmlDocument(); var resultsdict = new Dictionary <Guid, List <object> >(); foreach (var node in model.CurrentWorkspace.Nodes) { var portvalues = new List <object>(); foreach (var port in node.OutPorts) { var value = node.GetValue(port.Index, model.EngineController); if (value.IsCollection) { portvalues.Add(GetStringRepOfCollection(value)); } else { portvalues.Add(value.StringData); } } resultsdict.Add(node.GUID, portvalues); } outputresults.Add(resultsdict); populateXmlDocWithResults(doc, outputresults); } evalComplete = false; } return(doc); }
public void CanAddUserFacingMessagesToNode() { // Arrange OpenModel(@"core\Home.dyn"); var info1 = "Info 1"; var warning1 = "Warning 1"; var error1 = "Error 1"; var dummyNode = new DummyNode(); DynamoModel model = GetModel(); model.ExecuteCommand(new DynamoModel.CreateNodeCommand(dummyNode, 0, 0, true, true)); NodeViewModel dummyNodeViewModel = ViewModel.CurrentSpaceViewModel.Nodes .FirstOrDefault(x => x.NodeModel.GUID == dummyNode.GUID); NodeModel dummyNodeModel = dummyNodeViewModel.NodeModel; var topLeft = new Point(dummyNodeModel.X, dummyNodeModel.Y); var botRight = new Point(dummyNodeModel.X + dummyNodeModel.Width, dummyNodeModel.Y + dummyNodeModel.Height); if (dummyNodeViewModel.ErrorBubble == null) { dummyNodeViewModel.ErrorBubble = new InfoBubbleViewModel(ViewModel); } InfoBubbleViewModel infoBubbleViewModel = dummyNodeViewModel.ErrorBubble; // The collection of messages the node receives ObservableCollection <InfoBubbleDataPacket> nodeMessages = infoBubbleViewModel.NodeMessages; // The collections of messages the node displays to the user ObservableCollection <InfoBubbleDataPacket> userFacingInfo = infoBubbleViewModel.NodeInfoToDisplay; ObservableCollection <InfoBubbleDataPacket> userFacingWarnings = infoBubbleViewModel.NodeWarningsToDisplay; ObservableCollection <InfoBubbleDataPacket> userFacingErrors = infoBubbleViewModel.NodeErrorsToDisplay; // Act Assert.AreEqual(0, userFacingInfo.Count); Assert.AreEqual(0, userFacingWarnings.Count); Assert.AreEqual(0, userFacingErrors.Count); Assert.IsFalse(infoBubbleViewModel.NodeInfoVisible); Assert.IsFalse(infoBubbleViewModel.NodeWarningsVisible); Assert.IsFalse(infoBubbleViewModel.NodeErrorsVisible); nodeMessages.Add(new InfoBubbleDataPacket(InfoBubbleViewModel.Style.Info, topLeft, botRight, info1, InfoBubbleViewModel.Direction.Top)); nodeMessages.Add(new InfoBubbleDataPacket(InfoBubbleViewModel.Style.Warning, topLeft, botRight, warning1, InfoBubbleViewModel.Direction.Top)); nodeMessages.Add(new InfoBubbleDataPacket(InfoBubbleViewModel.Style.Error, topLeft, botRight, error1, InfoBubbleViewModel.Direction.Top)); // Assert Assert.AreEqual(1, userFacingInfo.Count); Assert.AreEqual(1, userFacingWarnings.Count); Assert.AreEqual(1, userFacingErrors.Count); Assert.IsTrue(infoBubbleViewModel.NodeInfoVisible); Assert.IsTrue(infoBubbleViewModel.NodeWarningsVisible); Assert.IsTrue(infoBubbleViewModel.NodeErrorsVisible); Assert.IsFalse(infoBubbleViewModel.NodeInfoIteratorVisible); Assert.IsFalse(infoBubbleViewModel.NodeWarningsIteratorVisible); Assert.IsFalse(infoBubbleViewModel.NodeErrorsIteratorVisible); Assert.IsFalse(infoBubbleViewModel.NodeInfoShowMoreButtonVisible); Assert.IsFalse(infoBubbleViewModel.NodeWarningsShowMoreButtonVisible); Assert.IsFalse(infoBubbleViewModel.NodeErrorsShowMoreButtonVisible); Assert.AreEqual(info1, userFacingInfo.First().Message); Assert.AreEqual(warning1, userFacingWarnings.First().Message); Assert.AreEqual(error1, userFacingErrors.First().Message); }