public void UpdateConnection_Disconnect_WpfCommandIsAvailableButNotExecutable_ServiceDisconnectedIsCalled() { // If the WPF command is available then it should be used to disconnect, // rather than calling service.Disconnect() directly. // Here, the command exists but is not executable. // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); int commandCallCount = 0; int commandCanExecuteCallCount = 0; var teSection = ConfigurableSectionController.CreateDefault(); teSection.DisconnectCommand = new Integration.WPF.RelayCommand( () => commandCallCount++, () => { commandCanExecuteCallCount++; return(false); }); host.SetActiveSection(teSection); ConfigureService(isConnected: true); ConfigureSolutionBinding(null); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: false); // Assert VerifyServiceConnect(Times.Never()); VerifyServiceDisconnect(Times.Once()); commandCanExecuteCallCount.Should().Be(1); commandCallCount.Should().Be(0); }
public void OnBindingStateChanged_NewConfiguration_EventRaised() { // Arrange var initialProject = new BoundSonarQubeProject( new Uri("http://localhost:9000"), "projectKey", organization: new SonarQubeOrganization("myOrgKey", "myOrgName")); // Set the current configuration used by the tracker ConfigureSolutionBinding(initialProject); var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); int solutionBindingChangedEventCount = 0; testSubject.SolutionBindingChanged += (obj, args) => { solutionBindingChangedEventCount++; }; // Now configure the provider to return a different configuration var newProject = new BoundSonarQubeProject( new Uri("http://localhost:9000"), "projectKey", organization: new SonarQubeOrganization("myOrgKey_DIFFERENT", "myOrgName")); ConfigureSolutionBinding(newProject); // Act - simulate the binding state changing in the Team explorer section. // The project configuration hasn't changed (it doesn't matter what properties // we pass here; they aren't used when raising the event.) host.VisualStateManager.SetBoundProject(new Uri("http://junk"), "any", "any"); // Assert // Different config so event should be raised solutionBindingChangedEventCount.Should().Be(1); }
public void UpdateConnection_Disconnect_WpfCommandIsAvailableAndExecutable_ServiceDisconnectedIsNotCalled() { // Wpf command is available and can be executed -> should be called instead of service.Disconnect() // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); int commandCallCount = 0; int commandCanExecuteCallCount = 0; var teSection = ConfigurableSectionController.CreateDefault(); teSection.DisconnectCommand = new Integration.WPF.RelayCommand( () => { commandCallCount++; isMockServiceConnected = false; }, () => { commandCanExecuteCallCount++; return(true); }); host.SetActiveSection(teSection); ConfigureService(isConnected: true); ConfigureSolutionBinding(null); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: false); // Assert VerifyServiceConnect(Times.Never()); VerifyServiceDisconnect(Times.Never()); commandCanExecuteCallCount.Should().Be(1); commandCallCount.Should().Be(1); }
public void ActiveSolutionBoundTracker_Unbound() { // Arrange host.VisualStateManager.ClearBoundProject(); // Act var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker); // Assert testSubject.IsActiveSolutionBound.Should().BeFalse("Unbound solution should report false activation"); this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); }
public void ActiveSolutionBoundTracker_Unbound() { // Setup host.VisualStateManager.ClearBoundProject(); // Act var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker); // Verify Assert.IsFalse(testSubject.IsActiveSolutionBound, "Unbound solution should report false activation"); this.errorListController.AssertRefreshCalled(1); this.errorListController.AssertResetCalled(0); }
public void ActiveSolutionBoundTracker_Initialisation_Bound() { // Arrange this.ConfigureSolutionBinding(new BoundSonarQubeProject()); // Act var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); // Assert testSubject.CurrentConfiguration.Mode.Should().Be(SonarLintMode.LegacyConnected, "Bound solution should report true activation"); this.errorListController.RefreshCalledCount.Should().Be(0); this.errorListController.ResetCalledCount.Should().Be(0); }
public void ActiveSolutionBoundTracker_Initialisation_Unbound() { // Arrange host.VisualStateManager.ClearBoundProject(); // Act var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); // Assert testSubject.CurrentConfiguration.Mode.Should().Be(SonarLintMode.Standalone, "Unbound solution should report false activation"); this.errorListController.RefreshCalledCount.Should().Be(0); this.errorListController.ResetCalledCount.Should().Be(0); }
public void ActiveSolutionBoundTracker_Bound() { // Arrange this.solutionBindingInformationProvider.SolutionBound = true; this.host.VisualStateManager.SetBoundProject(new ProjectInformation()); // Act var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker); // Assert testSubject.IsActiveSolutionBound.Should().BeTrue("Bound solution should report true activation"); this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); }
public void ActiveSolutionBoundTracker_Bound() { // Setup this.solutionBindingInformationProvider.SolutionBound = true; this.host.VisualStateManager.SetBoundProject(new ProjectInformation()); // Act var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker); // Verify Assert.IsTrue(testSubject.IsActiveSolutionBound, "Bound solution should report true activation"); this.errorListController.AssertRefreshCalled(1); this.errorListController.AssertResetCalled(0); }
public void ActiveSolutionBoundTracker_Initialisation_Bound() { // Arrange this.solutionBindingInformationProvider.SolutionBound = true; this.host.VisualStateManager.SetBoundProject(new SonarQubeProject("", "")); // Act var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, sonarLintOutputMock.Object); // Assert testSubject.IsActiveSolutionBound.Should().BeTrue("Bound solution should report true activation"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); }
public void SolutionBindingUpdated_WhenClearBoundProject_NotRaised() { // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); int callCount = 0; testSubject.SolutionBindingUpdated += (sender, e) => callCount++; // Act host.VisualStateManager.ClearBoundProject(); // Assert callCount.Should().Be(0); }
public void SolutionBindingUpdated_WhenSetBoundProject_Raised() { // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); int callCount = 0; testSubject.SolutionBindingUpdated += (sender, e) => callCount++; // Act host.VisualStateManager.SetBoundProject(new Uri("http://localhost"), null, "project123"); // Assert callCount.Should().Be(1); }
public void UpdateConnection_WasConnected_NewSolutionIsUnbound_DisconnectedCalled() { // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); ConfigureService(isConnected: true); ConfigureSolutionBinding(null); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: true); // Assert VerifyServiceConnect(Times.Never()); VerifyServiceDisconnect(Times.Once()); isMockServiceConnected.Should().Be(false); }
public void UpdateConnection_WasDisconnected_NewSolutionIsBound_ConnectCalled() { // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); ConfigureService(isConnected: false); ConfigureSolutionBinding(new BoundSonarQubeProject(new Uri("http://foo"), "projectKey")); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: true); // Assert VerifyServiceConnect(Times.Once()); VerifyServiceDisconnect(Times.Never()); isMockServiceConnected.Should().Be(true); }
public void UpdateConnection_WasDisconnected_NewSolutionIsUnbound_NoConnectOrDisconnectCalls() { // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, sonarLintOutputMock.Object); ConfigureService(isConnected: false); ConfigureSolutionBinding(null); // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Assert VerifyServiceConnect(Times.Never()); VerifyServiceDisconnect(Times.Never()); isMockServiceConnected.Should().Be(false); }
public void UpdateConnection_WasConnected_NewSolutionBound_ConnectedCalled() { // Note: we don't expect this to happen in practice - we should only // ever go from connected->disconnected, or disconnected->connected, // never connected->connected. However, we should handle it gracefully // just in case. // Arrange var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); ConfigureService(isConnected: true); ConfigureSolutionBinding(new BoundSonarQubeProject(new Uri("http://foo"), "projectKey")); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: true); // Assert VerifyServiceConnect(Times.Once()); VerifyServiceDisconnect(Times.Once()); isMockServiceConnected.Should().Be(true); }
public void OnBindingStateChanged_SameConfiguration_EventNotRaised() { // Arrange var boundProject = new BoundSonarQubeProject( new Uri("http://localhost:9000"), "projectKey", organization: new SonarQubeOrganization("myOrgKey", "myOrgName")); // Set the current configuration used by the tracker ConfigureSolutionBinding(boundProject); var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); int solutionBindingChangedEventCount = 0; testSubject.SolutionBindingChanged += (obj, args) => { solutionBindingChangedEventCount++; }; // Act - simulate the binding state changing in the Team explorer section. host.VisualStateManager.SetBoundProject(new Uri("http://junk"), "any", "any"); // Assert // Same config so event should not be raised solutionBindingChangedEventCount.Should().Be(0); }
public void ActiveSolutionBoundTracker_When_ConnectAsync_Throws_Write_To_Output() { // Arrange var sonarQubeServiceMock = new Mock <ISonarQubeService>(); this.host.SonarQubeService = sonarQubeServiceMock.Object; var activeSolutionBoundTracker = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, this.loggerMock.Object); // We want to directly jump to Connect sonarQubeServiceMock.SetupGet(x => x.IsConnected).Returns(false); ConfigureSolutionBinding(new BoundSonarQubeProject(new Uri("http://test"), "projectkey")); // ConnectAsync should throw sonarQubeServiceMock .SetupSequence(x => x.ConnectAsync(It.IsAny <ConnectionInformation>(), It.IsAny <CancellationToken>())) .Throws <Exception>() .Throws <TaskCanceledException>() .Throws(new HttpRequestException("http request", new Exception("something happened"))); // Act // Throwing errors will put the connection and binding out of sync, which // cause a Debug.Assert in the product code that we need to suppress using (new AssertIgnoreScope()) { this.activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: true); this.activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: false); this.activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: true); } // Assert this.loggerMock .Verify(x => x.WriteLine(It.Is <string>(s => s.StartsWith("SonarQube request failed:")), It.IsAny <object[]>()), Times.Exactly(2)); this.loggerMock .Verify(x => x.WriteLine(It.Is <string>(s => s.StartsWith("SonarQube request timed out or was canceled"))), Times.Once); }
public void ActiveSolutionBoundTracker_Changes() { var solutionBinding = new ConfigurableSolutionBindingSerializer { CurrentBinding = new BoundSonarQubeProject() }; this.serviceProvider.RegisterService(typeof(ISolutionBindingSerializer), solutionBinding); this.solutionBindingInformationProvider.SolutionBound = true; var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker); var reanalysisEventCalledCount = 0; testSubject.SolutionBindingChanged += (obj, args) => { reanalysisEventCalledCount++; }; // Sanity Assert.IsTrue(testSubject.IsActiveSolutionBound, "Initially bound"); this.errorListController.AssertRefreshCalled(1); this.errorListController.AssertResetCalled(0); Assert.AreEqual(0, reanalysisEventCalledCount, "No reanalysis forced"); // Case 1: Clear bound project solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = false; // Act host.VisualStateManager.ClearBoundProject(); // Verify Assert.IsFalse(testSubject.IsActiveSolutionBound, "Unbound solution should report false activation"); this.errorListController.AssertRefreshCalled(1); this.errorListController.AssertResetCalled(0); Assert.AreEqual(1, reanalysisEventCalledCount, "Unbind should trigger reanalysis"); // Case 2: Set bound project solutionBinding.CurrentBinding = new BoundSonarQubeProject(); this.solutionBindingInformationProvider.SolutionBound = true; // Act host.VisualStateManager.SetBoundProject(new ProjectInformation()); // Verify Assert.IsTrue(testSubject.IsActiveSolutionBound, "Bound solution should report true activation"); this.errorListController.AssertRefreshCalled(1); this.errorListController.AssertResetCalled(0); Assert.AreEqual(2, reanalysisEventCalledCount, "Bind should trigger reanalysis"); // Case 3: Solution unloaded solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = false; // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Verify Assert.IsFalse(testSubject.IsActiveSolutionBound, "Should respond to solution change event and report unbound"); this.errorListController.AssertRefreshCalled(2); this.errorListController.AssertResetCalled(0); Assert.AreEqual(3, reanalysisEventCalledCount, "Solution change should trigger reanalysis"); // Case 4: Solution loaded solutionBinding.CurrentBinding = new BoundSonarQubeProject(); this.solutionBindingInformationProvider.SolutionBound = true; // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Verify Assert.IsTrue(testSubject.IsActiveSolutionBound, "Bound respond to solution change event and report bound"); this.errorListController.AssertRefreshCalled(3); this.errorListController.AssertResetCalled(0); Assert.AreEqual(4, reanalysisEventCalledCount, "Solution change should trigger reanalysis"); // Case 5: Dispose and change // Act testSubject.Dispose(); solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = true; host.VisualStateManager.ClearBoundProject(); // Verify Assert.AreEqual(4, reanalysisEventCalledCount, "Once disposed should stop raising the event"); this.errorListController.AssertRefreshCalled(3); this.errorListController.AssertResetCalled(1); }
public void ActiveSolutionBoundTracker_Changes() { var boundProject = new BoundSonarQubeProject(new Uri("http://localhost:9000"), "key"); var solutionBinding = new ConfigurableSolutionBindingSerializer(); bool serviceIsConnected = false; var mockSqService = new Mock <ISonarQubeService>(); Expression <Func <ISonarQubeService, Task> > connectMethod = x => x.ConnectAsync(It.IsAny <ConnectionInformation>(), It.IsAny <CancellationToken>()); Expression <Action <ISonarQubeService> > disconnectMethod = x => x.Disconnect(); mockSqService.SetupGet(x => x.IsConnected).Returns(() => serviceIsConnected); mockSqService.Setup(disconnectMethod).Callback(() => serviceIsConnected = false).Verifiable(); mockSqService.Setup(connectMethod) .Returns(Task.Delay(0)) .Callback(() => serviceIsConnected = true).Verifiable(); this.host.SonarQubeService = mockSqService.Object; this.serviceProvider.RegisterService(typeof(ISolutionBindingSerializer), solutionBinding); solutionBinding.CurrentBinding = boundProject; this.solutionBindingInformationProvider.SolutionBound = true; var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker); var solutionBindingChangedEventCount = 0; testSubject.SolutionBindingChanged += (obj, args) => { solutionBindingChangedEventCount++; }; // Sanity testSubject.IsActiveSolutionBound.Should().BeTrue("Initially bound"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(0, "no events raised during construction"); // Case 1: Clear bound project solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = false; // Act host.VisualStateManager.ClearBoundProject(); // Assert testSubject.IsActiveSolutionBound.Should().BeFalse("Unbound solution should report false activation"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(1, "Unbind should trigger reanalysis"); // Connect not called // Disconnect not called mockSqService.Verify(disconnectMethod, Times.Never); mockSqService.Verify(connectMethod, Times.Never); // Case 2: Set bound project solutionBinding.CurrentBinding = boundProject; this.solutionBindingInformationProvider.SolutionBound = true; // Act host.VisualStateManager.SetBoundProject(new SonarQubeProject("", "")); // Assert testSubject.IsActiveSolutionBound.Should().BeTrue("Bound solution should report true activation"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(2, "Bind should trigger reanalysis"); // Notifications from the Team Explorer should not trigger connect/disconnect mockSqService.Verify(disconnectMethod, Times.Never); mockSqService.Verify(connectMethod, Times.Never); // Case 3: Solution unloaded solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = false; // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Assert testSubject.IsActiveSolutionBound.Should().BeFalse("Should respond to solution change event and report unbound"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(2); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(3, "Solution change should trigger reanalysis"); // Closing an unbound solution should not call disconnect/connect mockSqService.Verify(disconnectMethod, Times.Never); mockSqService.Verify(connectMethod, Times.Never); // Case 4: Load a bound solution solutionBinding.CurrentBinding = boundProject; this.solutionBindingInformationProvider.SolutionBound = true; // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Assert testSubject.IsActiveSolutionBound.Should().BeTrue("Bound respond to solution change event and report bound"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(3); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(4, "Solution change should trigger reanalysis"); // Loading a bound solution should call connect mockSqService.Verify(disconnectMethod, Times.Never); mockSqService.Verify(connectMethod, Times.Exactly(1)); // Case 5: Close a bound solution solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = false; // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Assert // TODO: this.errorListController.RefreshCalledCount.Should().Be(4); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(5, "Solution change should trigger reanalysis"); // Closing a bound solution should call disconnect mockSqService.Verify(disconnectMethod, Times.Exactly(1)); mockSqService.Verify(connectMethod, Times.Exactly(1)); // Case 6: Dispose and change // Act testSubject.Dispose(); solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = true; host.VisualStateManager.ClearBoundProject(); // Assert solutionBindingChangedEventCount.Should().Be(5, "Once disposed should stop raising the event"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(3); this.errorListController.ResetCalledCount.Should().Be(1); mockSqService.Verify(disconnectMethod, Times.Exactly(1)); mockSqService.Verify(connectMethod, Times.Exactly(1)); }
public void ActiveSolutionBoundTracker_Changes() { var solutionBinding = new ConfigurableSolutionBindingSerializer { CurrentBinding = new BoundSonarQubeProject() }; this.serviceProvider.RegisterService(typeof(ISolutionBindingSerializer), solutionBinding); this.solutionBindingInformationProvider.SolutionBound = true; var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker); var reanalysisEventCalledCount = 0; testSubject.SolutionBindingChanged += (obj, args) => { reanalysisEventCalledCount++; }; // Sanity testSubject.IsActiveSolutionBound.Should().BeTrue("Initially bound"); this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); reanalysisEventCalledCount.Should().Be(0, "No reanalysis forced"); // Case 1: Clear bound project solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = false; // Act host.VisualStateManager.ClearBoundProject(); // Assert testSubject.IsActiveSolutionBound.Should().BeFalse("Unbound solution should report false activation"); this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); reanalysisEventCalledCount.Should().Be(1, "Unbind should trigger reanalysis"); // Case 2: Set bound project solutionBinding.CurrentBinding = new BoundSonarQubeProject(); this.solutionBindingInformationProvider.SolutionBound = true; // Act host.VisualStateManager.SetBoundProject(new ProjectInformation()); // Assert testSubject.IsActiveSolutionBound.Should().BeTrue("Bound solution should report true activation"); this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); reanalysisEventCalledCount.Should().Be(2, "Bind should trigger reanalysis"); // Case 3: Solution unloaded solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = false; // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Assert testSubject.IsActiveSolutionBound.Should().BeFalse("Should respond to solution change event and report unbound"); this.errorListController.RefreshCalledCount.Should().Be(2); this.errorListController.ResetCalledCount.Should().Be(0); reanalysisEventCalledCount.Should().Be(3, "Solution change should trigger reanalysis"); // Case 4: Solution loaded solutionBinding.CurrentBinding = new BoundSonarQubeProject(); this.solutionBindingInformationProvider.SolutionBound = true; // Act activeSolutionTracker.SimulateActiveSolutionChanged(); // Assert testSubject.IsActiveSolutionBound.Should().BeTrue("Bound respond to solution change event and report bound"); this.errorListController.RefreshCalledCount.Should().Be(3); this.errorListController.ResetCalledCount.Should().Be(0); reanalysisEventCalledCount.Should().Be(4, "Solution change should trigger reanalysis"); // Case 5: Dispose and change // Act testSubject.Dispose(); solutionBinding.CurrentBinding = null; this.solutionBindingInformationProvider.SolutionBound = true; host.VisualStateManager.ClearBoundProject(); // Assert reanalysisEventCalledCount.Should().Be(4, "Once disposed should stop raising the event"); this.errorListController.RefreshCalledCount.Should().Be(3); this.errorListController.ResetCalledCount.Should().Be(1); }
public void ActiveSolutionBoundTracker_Changes() { var boundProject = new BoundSonarQubeProject(new Uri("http://localhost:9000"), "key"); ConfigureService(isConnected: false); ConfigureSolutionBinding(boundProject); var testSubject = new ActiveSolutionBoundTracker(this.host, this.activeSolutionTracker, loggerMock.Object); var solutionBindingChangedEventCount = 0; testSubject.SolutionBindingChanged += (obj, args) => { solutionBindingChangedEventCount++; }; // Sanity testSubject.CurrentConfiguration.Mode.Should().Be(SonarLintMode.LegacyConnected, "Initially bound"); this.errorListController.RefreshCalledCount.Should().Be(0); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(0, "no events raised during construction"); // Case 1: Clear bound project ConfigureSolutionBinding(null); // Act host.VisualStateManager.ClearBoundProject(); // Assert testSubject.CurrentConfiguration.Mode.Should().Be(SonarLintMode.Standalone, "Unbound solution should report false activation"); this.errorListController.RefreshCalledCount.Should().Be(0); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(1, "Unbind should trigger reanalysis"); VerifyServiceDisconnect(Times.Never()); VerifyServiceConnect(Times.Never()); // Case 2: Set bound project ConfigureSolutionBinding(boundProject); // Act host.VisualStateManager.SetBoundProject(new Uri("http://localhost"), null, "project123"); // Assert testSubject.CurrentConfiguration.Mode.Should().Be(SonarLintMode.LegacyConnected, "Bound solution should report true activation"); this.errorListController.RefreshCalledCount.Should().Be(0); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(2, "Bind should trigger reanalysis"); // Notifications from the Team Explorer should not trigger connect/disconnect VerifyServiceDisconnect(Times.Never()); VerifyServiceConnect(Times.Never()); // Case 3: Bound solution unloaded -> disconnect ConfigureSolutionBinding(null); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: false); // Assert testSubject.CurrentConfiguration.Mode.Should().Be(SonarLintMode.Standalone, "Should respond to solution change event and report unbound"); this.errorListController.RefreshCalledCount.Should().Be(1); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(3, "Solution change should trigger reanalysis"); // Closing an unbound solution should not call disconnect/connect VerifyServiceDisconnect(Times.Never()); VerifyServiceConnect(Times.Never()); // Case 4: Load a bound solution ConfigureSolutionBinding(boundProject); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: true); // Assert testSubject.CurrentConfiguration.Mode.Should().Be(SonarLintMode.LegacyConnected, "Bound respond to solution change event and report bound"); this.errorListController.RefreshCalledCount.Should().Be(2); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(4, "Solution change should trigger reanalysis"); // Loading a bound solution should call connect VerifyServiceDisconnect(Times.Never()); VerifyServiceConnect(Times.Once()); // Case 5: Close a bound solution ConfigureSolutionBinding(null); // Act activeSolutionTracker.SimulateActiveSolutionChanged(isSolutionOpen: false); // Assert // TODO: this.errorListController.RefreshCalledCount.Should().Be(4); this.errorListController.ResetCalledCount.Should().Be(0); solutionBindingChangedEventCount.Should().Be(5, "Solution change should trigger reanalysis"); // SonarQubeService.Disconnect should be called since the WPF DisconnectCommand is not available VerifyServiceDisconnect(Times.Once()); VerifyServiceConnect(Times.Once()); // Case 6: Dispose and change // Act testSubject.Dispose(); ConfigureSolutionBinding(boundProject); host.VisualStateManager.ClearBoundProject(); // Assert solutionBindingChangedEventCount.Should().Be(5, "Once disposed should stop raising the event"); // TODO: this.errorListController.RefreshCalledCount.Should().Be(3); this.errorListController.ResetCalledCount.Should().Be(1); // SonarQubeService.Disconnect should be called since the WPF DisconnectCommand is not available VerifyServiceDisconnect(Times.Once()); VerifyServiceConnect(Times.Once()); }