コード例 #1
0
        public async Task ConnectionWorkflow_ConnectionStep_WhenMissingCSharpPluginAndVBNetPlugin_AbortsWorkflowAndDisconnects()
        {
            // Arrange
            var connectionInfo             = new ConnectionInformation(new Uri("http://server"));
            ConnectionWorkflow testSubject = new ConnectionWorkflow(this.host, new RelayCommand(() => { }));
            var controller = new ConfigurableProgressController();

            this.sonarQubeServiceMock.Setup(x => x.GetAllProjectsAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new List <SonarQubeProject>());
            this.sonarQubeServiceMock.Setup(x => x.GetAllPluginsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(new List <SonarQubePlugin>());
            this.host.SetActiveSection(ConfigurableSectionController.CreateDefault());
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)this.host.ActiveSection.UserNotifications;
            var executionEvents = new ConfigurableProgressStepExecutionEvents();

            // Act
            await testSubject.ConnectionStepAsync(connectionInfo, controller, executionEvents, CancellationToken.None);

            // Assert
            controller.NumberOfAbortRequests.Should().Be(1);
            AssertServiceDisconnectCalled();
            executionEvents.AssertProgressMessages(
                connectionInfo.ServerUri.ToString(),
                Strings.ConnectionStepValidatinCredentials,
                Strings.DetectingSonarQubePlugins,
                Strings.ConnectionResultFailure);
            notifications.AssertNotification(NotificationIds.BadSonarQubePluginId, Strings.ServerHasNoSupportedPluginVersion);

            AssertCredentialsNotStored(); // Username and password are null
        }
コード例 #2
0
        public void ConnectionWorkflow_ConnectionStep_WhenMissingCSharpPluginAndVBNetPlugin_AbortsWorkflowAndDisconnects()
        {
            // Setup
            var connectionInfo             = new ConnectionInformation(new Uri("http://server"));
            ConnectionWorkflow testSubject = new ConnectionWorkflow(this.host, new RelayCommand(() => { }));
            var controller = new ConfigurableProgressController();

            this.sonarQubeService.AllowConnections         = true;
            this.sonarQubeService.ReturnProjectInformation = new ProjectInformation[0];
            this.sonarQubeService.ClearServerPlugins();
            this.host.SetActiveSection(ConfigurableSectionController.CreateDefault());
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)this.host.ActiveSection.UserNotifications;
            var executionEvents = new ConfigurableProgressStepExecutionEvents();

            // Act
            testSubject.ConnectionStep(controller, CancellationToken.None, connectionInfo, executionEvents);

            // Verify
            controller.AssertNumberOfAbortRequests(1);
            executionEvents.AssertProgressMessages(
                connectionInfo.ServerUri.ToString(),
                Strings.DetectingServerPlugins,
                Strings.ConnectionResultFailure);
            notifications.AssertNotification(NotificationIds.BadServerPluginId, Strings.ServerHasNoSupportedPluginVersion);
        }
コード例 #3
0
        public void StateManager_ClearBoundProject()
        {
            // Arrange
            var section = ConfigurableSectionController.CreateDefault();
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)section.UserNotifications;
            ConfigurableHost             host          = new ConfigurableHost();

            host.SetActiveSection(section);
            StateManager testSubject = this.CreateTestSubject(host);

            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            testSubject.ManagedState.ConnectedServers.Add(new ServerViewModel(new ConnectionInformation(new Uri("http://zzz1"))));
            testSubject.ManagedState.ConnectedServers.Add(new ServerViewModel(new ConnectionInformation(new Uri("http://zzz2"))));
            testSubject.ManagedState.ConnectedServers.ToList().ForEach(s => s.Projects.Add(new ProjectViewModel(s, new SonarQubeProject(Guid.NewGuid().ToString(), ""))));
            var allProjects = testSubject.ManagedState.ConnectedServers.SelectMany(s => s.Projects).ToList();

            testSubject.SetBoundProject(new Uri("http://zzz1"), null, allProjects.First().Project.Key);

            // Sanity
            testSubject.ManagedState.HasBoundProject.Should().BeTrue();

            // Act
            testSubject.ClearBoundProject();

            // Assert
            testSubject.ManagedState.HasBoundProject.Should().BeFalse();
            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
        }
コード例 #4
0
        public void StateManager_SetProjectsUIThread_With_BoundProjectKey()
        {
            // Arrange
            var section = ConfigurableSectionController.CreateDefault();
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)section.UserNotifications;
            ConfigurableHost             host          = new ConfigurableHost();
            StateManager testSubject = this.CreateTestSubject(host);

            host.VisualStateManager = testSubject;
            section.ViewModel.State = testSubject.ManagedState;
            host.SetActiveSection(section);

            var connection1 = new ConnectionInformation(new Uri("http://127.0.0.1"));
            var projects    = new[] { new SonarQubeProject("project1", ""), new SonarQubeProject("project2", "") };

            // Case 1 - projects does not contain BoundProjectKey
            testSubject.BoundProjectKey = "missing_project";
            testSubject.SetProjects(connection1, projects);

            // Assert
            var message = notifications.AssertNotification(NotificationIds.FailedToFindBoundProjectKeyId);

            message.Should().MatchRegex("\\[.+\\]\\(\\)"); // Contains the hyperlink syntax [text]()
            notifications.AssertNotification(NotificationIds.FailedToFindBoundProjectKeyId, section.ReconnectCommand);

            // Case 2 - projects contains BoundProjectKey
            testSubject.BoundProjectKey = "project1";
            testSubject.SetProjects(connection1, projects);

            // Assert
            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
        }
コード例 #5
0
        public void ConnectionController_ShowNuGetWarning()
        {
            // Arrange
            ConnectionController testSubject = new ConnectionController(this.host, this.connectionProvider,
                                                                        this.connectionWorkflowMock.Object);

            this.host.SetActiveSection(ConfigurableSectionController.CreateDefault());
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)this.host.ActiveSection.UserNotifications;

            this.connectionProvider.ConnectionInformationToReturn = null;
            var progressEvents = new ConfigurableProgressEvents();

            // Case 1: do NOT show
            // Arrange
            this.settings.ShowServerNuGetTrustWarning = false;

            // Act
            testSubject.SetConnectionInProgress(progressEvents);
            progressEvents.SimulateFinished(ProgressControllerResult.Succeeded);

            // Assert
            notifications.AssertNoNotification(NotificationIds.WarnServerTrustId);

            // Case 2: show, but canceled
            // Arrange
            this.settings.ShowServerNuGetTrustWarning = false;

            // Act
            testSubject.SetConnectionInProgress(progressEvents);
            progressEvents.SimulateFinished(ProgressControllerResult.Cancelled);

            // Assert
            notifications.AssertNoNotification(NotificationIds.WarnServerTrustId);

            // Case 3: show, but failed
            // Arrange
            this.settings.ShowServerNuGetTrustWarning = false;

            // Act
            testSubject.SetConnectionInProgress(progressEvents);
            progressEvents.SimulateFinished(ProgressControllerResult.Failed);

            // Assert
            notifications.AssertNoNotification(NotificationIds.WarnServerTrustId);

            // Test Case 4: show, succeeded
            // Arrange
            this.settings.ShowServerNuGetTrustWarning = true;

            // Act
            testSubject.SetConnectionInProgress(progressEvents);
            progressEvents.SimulateFinished(ProgressControllerResult.Succeeded);

            // Assert
            notifications.AssertNotification(NotificationIds.WarnServerTrustId, Strings.ServerNuGetTrustWarningMessage);
        }
コード例 #6
0
        private async Task ConnectionWorkflow_ConnectionStep_WhenXPluginAndNoXProject_AbortsWorkflowAndDisconnects(string projectName, string projectKind,
                                                                                                                   params MinimumSupportedSonarQubePlugin[] minimumSupportedSonarQubePlugins)
        {
            // Arrange
            var connectionInfo = new ConnectionInformation(new Uri("http://server"));
            var projects       = new List <SonarQubeProject> {
                new SonarQubeProject("project1", "")
            };

            this.sonarQubeServiceMock.Setup(x => x.GetAllProjectsAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(projects);
            this.sonarQubeServiceMock.Setup(x => x.GetAllPluginsAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(minimumSupportedSonarQubePlugins.Select(p => new SonarQubePlugin(p.Key, p.MinimumVersion)).ToList());
            this.projectSystemHelper.Projects = new[] { new ProjectMock(projectName)
                                                        {
                                                            ProjectKind = projectKind
                                                        } };
            bool projectChangedCallbackCalled = false;

            this.host.TestStateManager.SetProjectsAction = (c, p) =>
            {
                projectChangedCallbackCalled = true;
                c.Should().Be(connectionInfo, "Unexpected connection");
                CollectionAssert.AreEqual(projects, p.ToArray(), "Unexpected projects");
            };

            var    controller        = new ConfigurableProgressController();
            var    executionEvents   = new ConfigurableProgressStepExecutionEvents();
            string connectionMessage = connectionInfo.ServerUri.ToString();
            var    testSubject       = new ConnectionWorkflow(this.host, new RelayCommand(AssertIfCalled));
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)this.host.ActiveSection.UserNotifications;

            // Act
            await testSubject.ConnectionStepAsync(connectionInfo, controller, executionEvents, CancellationToken.None);

            // Assert
            controller.NumberOfAbortRequests.Should().Be(1);
            AssertServiceDisconnectCalled();
            executionEvents.AssertProgressMessages(
                connectionInfo.ServerUri.ToString(),
                Strings.ConnectionStepValidatinCredentials,
                Strings.DetectingSonarQubePlugins,
                Strings.ConnectionResultFailure);
            projectChangedCallbackCalled.Should().BeFalse("ConnectedProjectsCallaback was called");

            var languageList = string.Join(", ", minimumSupportedSonarQubePlugins.SelectMany(x => x.Languages.Select(l => l.Name)));

            notifications.AssertNotification(NotificationIds.BadSonarQubePluginId, string.Format(Strings.OnlySupportedPluginsHaveNoProjectInSolution, languageList));

            AssertCredentialsNotStored(); // Username and password are null
        }
コード例 #7
0
        private void ConnectionWorkflow_ConnectionStep_WhenXPluginAndNoXProject_AbortsWorkflowAndDisconnects(string projectName, string projectKind, MinimumSupportedServerPlugin minimumSupportedServerPlugin)
        {
            // Arrange
            var connectionInfo = new ConnectionInformation(new Uri("http://server"));
            var projects       = new ProjectInformation[] { new ProjectInformation {
                                                                Key = "project1"
                                                            } };

            this.sonarQubeService.ReturnProjectInformation = projects;
            this.sonarQubeService.ClearServerPlugins();
            this.sonarQubeService.RegisterServerPlugin(new ServerPlugin {
                Key = minimumSupportedServerPlugin.Key, Version = minimumSupportedServerPlugin.MinimumVersion
            });
            this.projectSystemHelper.Projects = new[] { new ProjectMock(projectName)
                                                        {
                                                            ProjectKind = projectKind
                                                        } };
            bool projectChangedCallbackCalled = false;

            this.host.TestStateManager.SetProjectsAction = (c, p) =>
            {
                projectChangedCallbackCalled = true;
                c.Should().Be(connectionInfo, "Unexpected connection");
                CollectionAssert.AreEqual(projects, p.ToArray(), "Unexpected projects");
            };

            var    controller        = new ConfigurableProgressController();
            var    executionEvents   = new ConfigurableProgressStepExecutionEvents();
            string connectionMessage = connectionInfo.ServerUri.ToString();
            var    testSubject       = new ConnectionWorkflow(this.host, new RelayCommand(AssertIfCalled));
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)this.host.ActiveSection.UserNotifications;

            // Act
            testSubject.ConnectionStep(controller, CancellationToken.None, connectionInfo, executionEvents);

            // Assert
            controller.NumberOfAbortRequests.Should().Be(1);
            executionEvents.AssertProgressMessages(
                connectionInfo.ServerUri.ToString(),
                Strings.ConnectionStepValidatinCredentials,
                Strings.DetectingServerPlugins,
                Strings.ConnectionResultFailure);
            projectChangedCallbackCalled.Should().BeFalse("ConnectedProjectsCallaback was called");
            notifications.AssertNotification(NotificationIds.BadServerPluginId, string.Format(Strings.OnlySupportedPluginHasNoProjectInSolution, minimumSupportedServerPlugin.Language.Name));
        }
コード例 #8
0
        public void BindingController_SetBindingInProgress_Notifications()
        {
            // Arrange
            ServerViewModel serverVM = CreateServerViewModel();

            serverVM.SetProjects(new[]
            {
                new ProjectInformation {
                    Key = "key1"
                }
            });
            ProjectViewModel  projectVM   = serverVM.Projects.ToArray()[0];
            BindingController testSubject = this.PrepareCommandForExecution();
            var section = ConfigurableSectionController.CreateDefault();

            this.host.SetActiveSection(section);
            var progressEvents = new ConfigurableProgressEvents();

            this.host.ActiveSection.UserNotifications.ShowNotificationError("Need to make sure that this is clear once started", NotificationIds.FailedToBindId, new RelayCommand(() => { }));
            ConfigurableUserNotification userNotifications = (ConfigurableUserNotification)section.UserNotifications;

            foreach (ProgressControllerResult result in Enum.GetValues(typeof(ProgressControllerResult)).OfType <ProgressControllerResult>())
            {
                // Act - start
                testSubject.SetBindingInProgress(progressEvents, projectVM.ProjectInformation);

                // Assert
                userNotifications.AssertNoNotification(NotificationIds.FailedToBindId);

                // Act - finish
                progressEvents.SimulateFinished(result);

                // Assert
                if (result == ProgressControllerResult.Succeeded)
                {
                    userNotifications.AssertNoNotification(NotificationIds.FailedToBindId);
                }
                else
                {
                    userNotifications.AssertNotification(NotificationIds.FailedToBindId, Strings.FailedToToBindSolution);
                }
            }
        }
コード例 #9
0
        public async Task ConnectionWorkflow_ConnectionStep_WhenPluginOkAndNoProjects_AbortsWorkflowAndDisconnects()
        {
            // Arrange
            var connectionInfo = new ConnectionInformation(new Uri("http://server"));
            var projects       = new List <SonarQubeProject> {
                new SonarQubeProject("project1", "")
            };

            this.sonarQubeServiceMock.Setup(x => x.GetAllProjectsAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(projects);
            bool projectChangedCallbackCalled = false;

            this.host.TestStateManager.SetProjectsAction = (c, p) =>
            {
                projectChangedCallbackCalled = true;
                c.Should().Be(connectionInfo, "Unexpected connection");
                CollectionAssert.AreEqual(projects, p.ToArray(), "Unexpected projects");
            };

            var    controller        = new ConfigurableProgressController();
            var    executionEvents   = new ConfigurableProgressStepExecutionEvents();
            string connectionMessage = connectionInfo.ServerUri.ToString();
            var    testSubject       = new ConnectionWorkflow(this.host, new RelayCommand(AssertIfCalled));
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)this.host.ActiveSection.UserNotifications;

            // Act
            await testSubject.ConnectionStepAsync(connectionInfo, controller, executionEvents, CancellationToken.None);

            // Assert
            controller.NumberOfAbortRequests.Should().Be(1);
            AssertServiceDisconnectCalled();
            executionEvents.AssertProgressMessages(
                connectionInfo.ServerUri.ToString(),
                Strings.ConnectionStepValidatinCredentials,
                Strings.DetectingSonarQubePlugins,
                Strings.ConnectionResultFailure);
            projectChangedCallbackCalled.Should().BeFalse("ConnectedProjectsCallaback was called");
            notifications.AssertNotification(NotificationIds.BadSonarQubePluginId, Strings.SolutionContainsNoSupportedProject);

            AssertCredentialsNotStored(); // Username and password are null
        }
コード例 #10
0
        public void StateManager_SetBoundProject()
        {
            // Arrange
            var section = ConfigurableSectionController.CreateDefault();
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)section.UserNotifications;
            ConfigurableHost             host          = new ConfigurableHost();

            host.SetActiveSection(section);
            StateManager testSubject = this.CreateTestSubject(host);

            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            var conn = new ConnectionInformation(new Uri("http://xyz"))
            {
                Organization = new SonarQubeOrganization("org1", "org1 name")
            };
            var projects = new[] { new SonarQubeProject("111", ""), new SonarQubeProject("222", "") };

            testSubject.SetProjects(conn, projects);
            TransferableVisualState state = testSubject.ManagedState;
            bool hasBoundProjectChanged   = false;

            state.PropertyChanged += (o, e) =>
            {
                e.PropertyName.Should().Be(nameof(state.HasBoundProject));
                hasBoundProjectChanged = true;
            };

            // Act
            testSubject.SetBoundProject(conn.ServerUri, "org1", "222");

            // Assert
            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
            var serverVM   = state.ConnectedServers.Single();
            var project0VM = serverVM.Projects.Single(p => p.Project == projects[0]);
            var project1VM = serverVM.Projects.Single(p => p.Project == projects[1]);

            project1VM.IsBound.Should().BeTrue();
            project0VM.IsBound.Should().BeFalse();
            testSubject.ManagedState.HasBoundProject.Should().BeTrue("Expected a bound project");
            hasBoundProjectChanged.Should().BeTrue("HasBoundProject expected to change");
        }
コード例 #11
0
        public void StateManager_SetBoundProject()
        {
            // Setup
            var section = ConfigurableSectionController.CreateDefault();
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)section.UserNotifications;
            ConfigurableHost             host          = new ConfigurableHost();

            host.SetActiveSection(section);
            StateManager testSubject = this.CreateTestSubject(host);

            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            var conn     = new ConnectionInformation(new Uri("http://xyz"));
            var projects = new[] { new ProjectInformation(), new ProjectInformation() };

            testSubject.SetProjects(conn, projects);
            TransferableVisualState state = testSubject.ManagedState;
            bool hasBoundProjectChanged   = false;

            state.PropertyChanged += (o, e) =>
            {
                Assert.AreEqual(nameof(state.HasBoundProject), e.PropertyName);
                hasBoundProjectChanged = true;
            };

            // Act
            testSubject.SetBoundProject(projects[1]);

            // Verify
            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
            var serverVM   = state.ConnectedServers.Single();
            var project0VM = serverVM.Projects.Single(p => p.ProjectInformation == projects[0]);
            var project1VM = serverVM.Projects.Single(p => p.ProjectInformation == projects[1]);

            Assert.IsTrue(project1VM.IsBound, "Expected to be bound");
            Assert.IsFalse(project0VM.IsBound, "Not expected to be bound");
            Assert.IsTrue(testSubject.ManagedState.HasBoundProject, "Expected a bound project");
            Assert.IsTrue(hasBoundProjectChanged, "HasBoundProject expected to change");
        }
コード例 #12
0
        public void ConnectionWorkflow_ConnectionStep_WhenPluginOkAndNoProjects_AbortsWorkflowAndDisconnects()
        {
            // Arrange
            var connectionInfo = new ConnectionInformation(new Uri("http://server"));
            var projects       = new ProjectInformation[] { new ProjectInformation {
                                                                Key = "project1"
                                                            } };

            this.sonarQubeService.ReturnProjectInformation = projects;
            bool projectChangedCallbackCalled = false;

            this.host.TestStateManager.SetProjectsAction = (c, p) =>
            {
                projectChangedCallbackCalled = true;
                c.Should().Be(connectionInfo, "Unexpected connection");
                CollectionAssert.AreEqual(projects, p.ToArray(), "Unexpected projects");
            };

            var    controller        = new ConfigurableProgressController();
            var    executionEvents   = new ConfigurableProgressStepExecutionEvents();
            string connectionMessage = connectionInfo.ServerUri.ToString();
            var    testSubject       = new ConnectionWorkflow(this.host, new RelayCommand(AssertIfCalled));
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)this.host.ActiveSection.UserNotifications;

            // Act
            testSubject.ConnectionStep(controller, CancellationToken.None, connectionInfo, executionEvents);

            // Assert
            controller.NumberOfAbortRequests.Should().Be(1);
            executionEvents.AssertProgressMessages(
                connectionInfo.ServerUri.ToString(),
                Strings.ConnectionStepValidatinCredentials,
                Strings.DetectingServerPlugins,
                Strings.ConnectionResultFailure);
            projectChangedCallbackCalled.Should().BeFalse("ConnectedProjectsCallaback was called");
            notifications.AssertNotification(NotificationIds.BadServerPluginId, Strings.SolutionContainsNoSupportedProject);
        }
コード例 #13
0
        public void BindingController_SetBindingInProgress_Notifications()
        {
            // Arrange
            var bindingArgs = new BindCommandArgs("key2", "", new ConnectionInformation(new Uri("http://myUri")));

            BindingController testSubject = this.PrepareCommandForExecution();
            var section = ConfigurableSectionController.CreateDefault();

            this.host.SetActiveSection(section);
            var progressEvents = new ConfigurableProgressEvents();

            this.host.ActiveSection.UserNotifications.ShowNotificationError("Need to make sure that this is clear once started", NotificationIds.FailedToBindId, new RelayCommand(() => { }));
            ConfigurableUserNotification userNotifications = (ConfigurableUserNotification)section.UserNotifications;

            foreach (ProgressControllerResult result in Enum.GetValues(typeof(ProgressControllerResult)).OfType <ProgressControllerResult>())
            {
                // Act - start
                testSubject.SetBindingInProgress(progressEvents, bindingArgs);

                // Assert
                userNotifications.AssertNoNotification(NotificationIds.FailedToBindId);

                // Act - finish
                progressEvents.SimulateFinished(result);

                // Assert
                if (result == ProgressControllerResult.Succeeded)
                {
                    userNotifications.AssertNoNotification(NotificationIds.FailedToBindId);
                }
                else
                {
                    userNotifications.AssertNotification(NotificationIds.FailedToBindId, Strings.FailedToToBindSolution);
                }
            }
        }
コード例 #14
0
        public void StateManager_SetProjectsUIThread()
        {
            // Arrange
            var section = ConfigurableSectionController.CreateDefault();
            ConfigurableUserNotification notifications = (ConfigurableUserNotification)section.UserNotifications;
            ConfigurableHost             host          = new ConfigurableHost();
            StateManager testSubject = this.CreateTestSubject(host);

            host.VisualStateManager = testSubject;
            section.ViewModel.State = testSubject.ManagedState;
            var connection1 = new ConnectionInformation(new Uri("http://127.0.0.1"));
            var connection2 = new ConnectionInformation(new Uri("http://127.0.0.2"));
            var projects    = new[] { new SonarQubeProject("", ""), new SonarQubeProject("", "") };

            host.SetActiveSection(section);
            ServerViewModel serverVM;

            // Act + Assert
            // Case 1 - not connected to server (indicated by null)
            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            testSubject.SetProjects(connection1, null);

            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
            VerifyConnectSectionViewModelIsNotConnected(section.ViewModel, connection1);
            VerifyConnectSectionViewModelIsNotConnected(section.ViewModel, connection2);
            VerifyConnectSectionViewModelHasNoBoundProjects(section.ViewModel);

            // Case 2 - connection1, empty project collection
            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            testSubject.SetProjects(connection1, new SonarQubeProject[0]);

            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
            serverVM = VerifyConnectSectionViewModelIsConnectedAndHasNoProjects(section.ViewModel, connection1);
            serverVM.ShowAllProjects.Should().BeTrue("Expected show all projects");
            VerifySectionCommands(section, serverVM);
            VerifyConnectSectionViewModelIsNotConnected(section.ViewModel, connection2);
            VerifyConnectSectionViewModelHasNoBoundProjects(section.ViewModel);

            // Case 3 - connection1, non-empty project collection
            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            testSubject.SetProjects(connection1, projects);

            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
            serverVM = VerifyConnectSectionViewModelIsConnectedAndHasProjects(section.ViewModel, connection1, projects);
            VerifySectionCommands(section, serverVM);
            VerifyConnectSectionViewModelIsNotConnected(section.ViewModel, connection2);
            VerifyConnectSectionViewModelHasNoBoundProjects(section.ViewModel);
            serverVM.ShowAllProjects.Should().BeTrue("Expected show all projects to be true when adding new SonarQubeProjects");

            // Case 4 - connection2, change projects
            testSubject.SetProjects(connection1, projects);
            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            testSubject.SetProjects(connection2, projects);

            notifications.AssertNoNotification(NotificationIds.FailedToFindBoundProjectKeyId);
            serverVM = VerifyConnectSectionViewModelIsConnectedAndHasProjects(section.ViewModel, connection1, projects);
            VerifySectionCommands(section, serverVM);
            serverVM = VerifyConnectSectionViewModelIsConnectedAndHasProjects(section.ViewModel, connection2, projects);
            VerifySectionCommands(section, serverVM);
            VerifyConnectSectionViewModelHasNoBoundProjects(section.ViewModel);
            serverVM.ShowAllProjects.Should().BeTrue("Expected show all projects to be true when changing projects");

            // Case 5 - connection1 & connection2, once detached (connected or not), are reset, changes still being tracked
            host.ClearActiveSection();
            testSubject.SetProjects(connection1, projects);
            testSubject.SetProjects(connection2, projects);
            // Act
            section.UserNotifications.ShowNotificationError("message", NotificationIds.FailedToFindBoundProjectKeyId, null);
            host.SetActiveSection(section);
            // Assert
            notifications.AssertNotification(NotificationIds.FailedToFindBoundProjectKeyId);
            serverVM = VerifyConnectSectionViewModelIsConnectedAndHasProjects(section.ViewModel, connection1, projects);
            VerifySectionCommands(section, serverVM);
            serverVM = VerifyConnectSectionViewModelIsConnectedAndHasProjects(section.ViewModel, connection2, projects);
            VerifySectionCommands(section, serverVM);
            VerifyConnectSectionViewModelHasNoBoundProjects(section.ViewModel);
        }