using Avalonia;
using Avalonia.Controls;
using Avalonia.Headless.XUnit;
using Avalonia.Threading;
using IFSRenderer.AvaloniaShell.Controls;
using Xunit;
namespace IFSRenderer.AvaloniaShell.Tests;
/// <summary>
/// "fog is not supposed to be capped at 1".
/// </summary>
/// <remarks>
/// <para>
/// A maximum the canonical does not declare is a correctness bug, not a cosmetic one: it puts
/// values the original can reach permanently out of reach, and it changes what a given slider
/// position means. The port shipped a batch of invented ranges; they were corrected once, but
/// Fog effect was missed because its cap of 1 looks plausible.
/// </para>
/// <para>
/// Each expectation below cites the canonical view-model that declares — or declines to
/// declare — the bound.
/// </para>
/// </remarks>
public class SliderRangeTests
{
private static MainWindow Ready()
{
(MainWindow window, _) = MainWindowHarness.Start();
window.Measure(new Size(1500, 900));
window.Arrange(new Rect(0, 0, 1500, 900));
Dispatcher.UIThread.RunJobs();
return window;
}
private static ValueSlider Slider(MainWindow w, string name)
{
var s = w.FindControl<ValueSlider>(name);
Assert.NotNull(s);
return s;
}
/// <summary>IFSViewModel.cs:107-116 — MinValue 0, and no maximum.</summary>
[AvaloniaFact]
public void Fog_effect_has_no_upper_bound()
{
ValueSlider fog = Slider(Ready(), "FogSlider");
Assert.Equal(0, fog.MinValue);
Assert.Null(fog.MaxValue);
}
/// <summary>
/// The parameters the canonical deliberately leaves open-ended. Capping any of these makes
/// part of the original's range unreachable.
/// </summary>
[AvaloniaTheory]
// ToneMappingViewModel: brightness, gamma, gamma threshold and vibrancy declare no maximum.
[InlineData("BrightnessSlider")]
[InlineData("GammaSlider")]
[InlineData("GammaThresholdSlider")]
[InlineData("VibrancySlider")]
// CameraSettingsViewModel.cs:166-192 — aperture and focus distance are unbounded above.
[InlineData("ApertureSlider")]
[InlineData("FocusSlider")]
// QualitySettingsViewModel — warmup has a minimum but no maximum.
[InlineData("WarmupSlider")]
// IteratorViewModel — weights, colour speed, mix and add are all open-ended.
[InlineData("ItStartWeight")]
[InlineData("ItWeight")]
[InlineData("ItColorSpeed")]
[InlineData("ItMix")]
[InlineData("ItAdd")]
public void Open_ended_parameters_declare_no_maximum(string name)
{
ValueSlider slider = Slider(Ready(), name);
Assert.Null(slider.MaxValue);
}
/// <summary>
/// The bounds the canonical DOES declare, so a future "unbound everything" sweep cannot
/// quietly remove a real constraint.
/// </summary>
[AvaloniaTheory]
[InlineData("FovSlider", 1.0, 179.0)] // CameraSettingsViewModel.cs:157-158
[InlineData("QualitySlider", 1.0, 50.0)] // QualitySettingsViewModel.cs:73-74
[InlineData("SyntropySlider", 10.0, 1000000.0)] // QualitySettingsViewModel.cs:124-125
[InlineData("FilterRadiusSlider", 0.0, 3.0)] // QualitySettingsViewModel.cs:148-149
[InlineData("DeRadiusSlider", 0.0, 20.0)] // QualitySettingsViewModel.cs:84-85
[InlineData("DePowerSlider", 0.0, 1.0)] // QualitySettingsViewModel.cs:95-96
[InlineData("DeThresholdSlider", 0.0, 1.0)] // QualitySettingsViewModel.cs:106-107
[InlineData("ItColorIndex", 0.0, 1.0)] // IteratorViewModel.cs:92-93
public void Bounded_parameters_keep_the_canonical_range(string name, double min, double max)
{
ValueSlider slider = Slider(Ready(), name);
Assert.Equal(min, slider.MinValue);
Assert.Equal(max, slider.MaxValue);
}
}