diff --git a/src/ServiceControl.Config.Tests/ServiceControlAddScreenLoadedTests.cs b/src/ServiceControl.Config.Tests/ServiceControlAddScreenLoadedTests.cs index 3c97a982ec..cf18a3c496 100644 --- a/src/ServiceControl.Config.Tests/ServiceControlAddScreenLoadedTests.cs +++ b/src/ServiceControl.Config.Tests/ServiceControlAddScreenLoadedTests.cs @@ -2,6 +2,7 @@ { using System; using System.ComponentModel; + using System.Linq; using NUnit.Framework; using ServiceControlInstaller.Engine.Configuration.ServiceControl; using UI.InstanceAdd; @@ -277,5 +278,86 @@ public void Full_text_search_on_bodies_is_enabled() Assert.That(viewModel.AuditEnableFullTextSearchOnBodies.Value, Is.EqualTo(true)); } } + + [Test] + public void Instance_sections_are_expanded_by_default() + { + var viewModel = new ServiceControlAddViewModel(); + + using (Assert.EnterMultipleScope()) + { + Assert.That(viewModel.IsServiceControlExpanded, Is.True); + Assert.That(viewModel.IsServiceControlAuditExpanded, Is.True); + } + } + + [Test] + public void Integrated_ServicePulse_is_enabled_by_default() + { + var viewModel = new ServiceControlAddViewModel(); + + using (Assert.EnterMultipleScope()) + { + Assert.That(viewModel.ErrorEnableIntegratedServicePulseOptions, Is.Not.Empty); + Assert.That(viewModel.ErrorEnableIntegratedServicePulse.Value, Is.True); + } + } + + [Test] + public void Integrated_ServicePulse_can_be_disabled() + { + var viewModel = new ServiceControlAddViewModel(); + + var offOption = viewModel.ErrorEnableIntegratedServicePulseOptions.First(o => !o.Value); + viewModel.ServiceControl.EnableIntegratedServicePulse = offOption; + + Assert.That(viewModel.ErrorEnableIntegratedServicePulse.Value, Is.False); + } + + [Test] + public void Audit_only_configuration_has_no_validation_errors_for_error_fields() + { + var viewModel = new ServiceControlAddViewModel(() => []) + { + InstallErrorInstance = false, + InstallAuditInstance = true, + SubmitAttempted = true + }; + + var notifyErrorInfo = (INotifyDataErrorInfo)viewModel; + + using (Assert.EnterMultipleScope()) + { + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.ErrorInstanceName)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.ErrorHostName)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.ErrorPortNumber)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.ErrorDestinationPath)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.ErrorLogPath)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.ErrorDatabasePath)), Is.Empty); + } + } + + [Test] + public void Error_only_configuration_has_no_validation_errors_for_audit_fields() + { + var viewModel = new ServiceControlAddViewModel(() => []) + { + InstallErrorInstance = true, + InstallAuditInstance = false, + SubmitAttempted = true + }; + + var notifyErrorInfo = (INotifyDataErrorInfo)viewModel; + + using (Assert.EnterMultipleScope()) + { + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.AuditInstanceName)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.AuditHostName)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.AuditPortNumber)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.AuditDestinationPath)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.AuditLogPath)), Is.Empty); + Assert.That(notifyErrorInfo.GetErrors(nameof(viewModel.AuditDatabasePath)), Is.Empty); + } + } } } diff --git a/src/ServiceControl.Config.Tests/SetupModeTests.cs b/src/ServiceControl.Config.Tests/SetupModeTests.cs new file mode 100644 index 0000000000..9d64da6d6b --- /dev/null +++ b/src/ServiceControl.Config.Tests/SetupModeTests.cs @@ -0,0 +1,51 @@ +namespace ServiceControl.Config.Tests +{ + using NUnit.Framework; + using UI.Shell; + + [TestFixture] + class SetupModeTests + { + [TestCase(SetupMode.ErrorHandling, true, false, false)] + [TestCase(SetupMode.ErrorAndAudit, true, true, false)] + [TestCase(SetupMode.AuditOnly, false, true, false)] + [TestCase(SetupMode.MonitoringOnly, false, false, true)] + public void Scenario_selects_the_instances_to_install(SetupMode mode, bool serviceControl, bool audit, bool monitoring) + { + using (Assert.EnterMultipleScope()) + { + Assert.That(mode.InstallsServiceControl(), Is.EqualTo(serviceControl)); + Assert.That(mode.InstallsAudit(), Is.EqualTo(audit)); + Assert.That(mode.InstallsMonitoring(), Is.EqualTo(monitoring)); + } + } + + [TestCase(SetupMode.ErrorHandling)] + [TestCase(SetupMode.ErrorAndAudit)] + [TestCase(SetupMode.AuditOnly)] + [TestCase(SetupMode.MonitoringOnly)] + public void Every_scenario_installs_at_least_one_instance(SetupMode mode) + { + // The Next button is always enabled, so no scenario may resolve to nothing. + Assert.That(mode.InstallsServiceControl() || mode.InstallsAudit() || mode.InstallsMonitoring(), Is.True); + } + + [TestCase(SetupMode.ErrorHandling)] + [TestCase(SetupMode.ErrorAndAudit)] + public void Integrated_ServicePulse_follows_the_choice_when_an_error_instance_is_installed(SetupMode mode) + { + using (Assert.EnterMultipleScope()) + { + Assert.That(mode.InstallsServicePulse(wanted: true), Is.True); + Assert.That(mode.InstallsServicePulse(wanted: false), Is.False); + } + } + + [TestCase(SetupMode.AuditOnly)] + [TestCase(SetupMode.MonitoringOnly)] + public void Integrated_ServicePulse_is_never_installed_without_an_error_instance(SetupMode mode) + { + Assert.That(mode.InstallsServicePulse(wanted: true), Is.False); + } + } +} diff --git a/src/ServiceControl.Config/Commands/AddServiceControlInstanceCommand.cs b/src/ServiceControl.Config/Commands/AddServiceControlInstanceCommand.cs index c8ce21013e..2b9bb7a74d 100644 --- a/src/ServiceControl.Config/Commands/AddServiceControlInstanceCommand.cs +++ b/src/ServiceControl.Config/Commands/AddServiceControlInstanceCommand.cs @@ -1,6 +1,8 @@ -namespace ServiceControl.Config.Commands +namespace ServiceControl.Config.Commands { using System; + using System.Linq; + using System.Threading; using System.Threading.Tasks; using Framework; using Framework.Commands; @@ -18,17 +20,32 @@ public AddServiceControlInstanceCommand(IServiceControlWindowManager windowManag public override async Task ExecuteAsync(object obj) { - if (!await commandChecks.CanAddInstance(true)) + await ExecuteWithOptions(installError: true, installAudit: true, installServicePulse: true); + } + + public async Task ExecuteWithOptions(bool installError, bool installAudit, bool installServicePulse, CancellationToken cancellationToken = default) + { + if (!await commandChecks.CanAddInstance(true, cancellationToken)) { return; } var instanceViewModel = addInstance(); - await windowManager.ShowInnerDialog(instanceViewModel); + instanceViewModel.InstallErrorInstance = installError; + instanceViewModel.InstallAuditInstance = installAudit; + + if (installError) + { + // The options list always carries both an On and an Off entry. + instanceViewModel.ServiceControl.EnableIntegratedServicePulse = instanceViewModel.ServiceControl + .EnableIntegratedServicePulseOptions.First(o => o.Value == installServicePulse); + } + + await windowManager.ShowInnerDialog(instanceViewModel, cancellationToken: cancellationToken); } readonly Func addInstance; readonly IServiceControlWindowManager windowManager; readonly ScmuCommandChecks commandChecks; } -} \ No newline at end of file +} diff --git a/src/ServiceControl.Config/UI/AdvancedOptions/ServiceControlAdvancedView.xaml b/src/ServiceControl.Config/UI/AdvancedOptions/ServiceControlAdvancedView.xaml index 00da1aaecd..f5e16d6643 100644 --- a/src/ServiceControl.Config/UI/AdvancedOptions/ServiceControlAdvancedView.xaml +++ b/src/ServiceControl.Config/UI/AdvancedOptions/ServiceControlAdvancedView.xaml @@ -46,7 +46,7 @@ Visibility="{Binding InMaintenanceMode, Converter={StaticResource boolToVisInverted}}" Margin="0,0,0,20" > - Enter database maintenance mode to access to RavenDB Management Studio. While in this mode all message processing is disabled and the REST API is unavailable. This will prevent ServicePulse and ServiceInsight connecting to this instance. + Enter database maintenance mode to access to RavenDB Management Studio. While in this mode all message processing is disabled and the REST API is unavailable. This will prevent ServicePulse connecting to this instance. - This instance is in database maintenance mode. All message processing is disabled and the REST API is unavailable.ServicePulse and ServiceInsight cannot connect to this instance while it is in maintenance mode.Launch + This instance is in database maintenance mode. All message processing is disabled and the REST API is unavailable.ServicePulse cannot connect to this instance while it is in maintenance mode.Launch RavenDB Management Studio diff --git a/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddView.xaml b/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddView.xaml index 2e0edd5bfe..8b34111dc8 100644 --- a/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddView.xaml +++ b/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddView.xaml @@ -73,34 +73,14 @@ Converter={StaticResource boolToVis}}" /> - - - - - - - - - - - - - - + + + @@ -261,34 +241,17 @@ ItemsSource="{Binding ErrorEnableIntegratedServicePulseOptions}" SelectedValue="{Binding ErrorEnableIntegratedServicePulse}" /> - - + - - - - - - - - - - - - + + + @@ -458,8 +421,7 @@ ItemsSource="{Binding AuditEnableFullTextSearchOnBodiesOptions}" SelectedValue="{Binding AuditEnableFullTextSearchOnBodies}" /> - - + diff --git a/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddViewModel.cs b/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddViewModel.cs index 0b9621251b..02ddc46a89 100644 --- a/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddViewModel.cs +++ b/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlAddViewModel.cs @@ -396,9 +396,9 @@ public string AuditDatabasePath public TimeSpanUnits AuditRetentionUnits => ServiceControlAudit.AuditRetentionUnits; - public bool IsServiceControlExpanded { get; set; } + public bool IsServiceControlExpanded { get; set; } = true; - public bool IsServiceControlAuditExpanded { get; set; } + public bool IsServiceControlAuditExpanded { get; set; } = true; public double AuditRetention { diff --git a/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlEditorViewModel.cs b/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlEditorViewModel.cs index 05a9f44501..603d4d0252 100644 --- a/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlEditorViewModel.cs +++ b/src/ServiceControl.Config/UI/InstanceAdd/ServiceControlEditorViewModel.cs @@ -36,8 +36,6 @@ public virtual void OnSelectedTransportChanged() // Needs to exist in base class for Fody to call it so it can be executed in superclass } - public bool OneInstanceTypeSelected => InstallErrorInstance || InstallAuditInstance; - public string TransportWarning => SelectedTransport?.Help; public string ConnectionString { get; set; } diff --git a/src/ServiceControl.Config/UI/NoInstances/NoInstancesView.xaml b/src/ServiceControl.Config/UI/NoInstances/NoInstancesView.xaml index a602496fcc..6721feccc1 100644 --- a/src/ServiceControl.Config/UI/NoInstances/NoInstancesView.xaml +++ b/src/ServiceControl.Config/UI/NoInstances/NoInstancesView.xaml @@ -1,4 +1,4 @@ - - - - - - - -