Skip to content

Commit

Permalink
Improve: Make the numeric parameter control keep precision when the i…
Browse files Browse the repository at this point in the history
…nput value is spinning up and down. (Issue #50)
  • Loading branch information
jsakamoto committed Sep 27, 2024
1 parent 70f1b4b commit b92b2d0
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 2 deletions.
22 changes: 20 additions & 2 deletions BlazingStory/Internals/Components/Inputs/NumberInput.razor
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,33 @@

private bool _InitialFocused;

private string? _PrevValue;

private int _PrevDecimalPartLen = 1;

protected override void OnParametersSet()
{
base.OnParametersSet();
if (this.AllowDecimalPoint)
{
if (this._PrevValue == this.Value) return;

var parts = this.Value?.Split('.') ?? [];
var hasDecimalPoint = parts.Length == 2;
var dicimalPartLen = (hasDecimalPoint ? parts[1] : "").Length;
this._Step = dicimalPartLen == 0 ? (hasDecimalPoint ? "0.1" : "1") : ("0." + new String('0', dicimalPartLen - 1) + "1");
var decimalPartLen = (hasDecimalPoint ? parts[1] : "").Length;

if (decimalPartLen < this._PrevDecimalPartLen && decimal.TryParse(this._PrevValue, out var prevValue) && decimal.TryParse(this.Value, out var value))
{
var stepValue = decimal.Parse(this._Step);
if (prevValue + stepValue == value || prevValue - stepValue == value)
{
decimalPartLen = this._PrevDecimalPartLen;
}
}

this._Step = decimalPartLen == 0 ? (hasDecimalPoint ? "0.1" : "1") : ("0." + new String('0', decimalPartLen - 1) + "1");
this._PrevValue = this.Value;
this._PrevDecimalPartLen = decimalPartLen;
}
else
{
Expand Down
113 changes: 113 additions & 0 deletions Tests/BlazingStory.Test/Internals/Components/Inputs/NumberInputTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using BlazingStory.Internals.Services;
using Bunit;
using Microsoft.AspNetCore.Components;

namespace BlazingStory.Test.Internals.Components.Inputs;

public class NumberInputTest
{
[Test]
public void NumberInput_Step_with_Empty_Test()
{
// Given
using var ctx = new Bunit.TestContext();

// When
var cut = ctx.RenderComponent<BlazingStory.Internals.Components.Inputs.NumberInput>(builder => builder
.Add(_ => _.AllowDecimalPoint, true)
.Add(_ => _.Value, ""));

// Then
cut.Find("input").GetAttribute("step").Is("1");
}

[Test]
public void NumberInput_Step_with_IntegerText_Test()
{
// Given
using var ctx = new Bunit.TestContext();

// When
var cut = ctx.RenderComponent<BlazingStory.Internals.Components.Inputs.NumberInput>(builder => builder
.Add(_ => _.AllowDecimalPoint, true)
.Add(_ => _.Value, "321"));

// Then
cut.Find("input").GetAttribute("step").Is("1");
}

[Test]
public void NumberInput_Step_with_DecimalText_Test()
{
// Given
using var ctx = new Bunit.TestContext();

// When
var cut = ctx.RenderComponent<BlazingStory.Internals.Components.Inputs.NumberInput>(builder => builder
.Add(_ => _.AllowDecimalPoint, true)
.Add(_ => _.Value, "1.234"));

// Then
cut.Find("input").GetAttribute("step").Is("0.001");
}

[Test]
public void NumberInput_Step_KeepPrecision_IncrementalSpin_Test()
{
// Given
using var ctx = new Bunit.TestContext();

// When: null value -> Then: the step is 1.
var cut = ctx.RenderComponent<BlazingStory.Internals.Components.Inputs.NumberInput>(builder => builder
.Add(_ => _.AllowDecimalPoint, true)
.Add(_ => _.Value, null));
cut.Find("input").GetAttribute("step").Is("1");

// When: input text "1.29" for each typing -> Then: the step changes 1, 0.1, and 0.01.
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1"));
cut.Find("input").GetAttribute("step").Is("1");
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1."));
cut.Find("input").GetAttribute("step").Is("0.1");
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.2"));
cut.Find("input").GetAttribute("step").Is("0.1");
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.29"));
cut.Find("input").GetAttribute("step").Is("0.01");

// When: emulate incremental spin button -> Then: keep the step even though the decimal point length is descreased.
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.3"));
cut.Find("input").GetAttribute("step").Is("0.01");

// When: redrawn was happened -> Then: keep the step.
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.3"));
cut.Find("input").GetAttribute("step").Is("0.01");

// When: emulate incremental spin button -> Then: keep the step.
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.31"));
cut.Find("input").GetAttribute("step").Is("0.01");
}

[Test]
public void NumberInput_Step_KeepPrecision_DecrementalSpin_Test()
{
// Given
using var ctx = new Bunit.TestContext();

// When: input "1.21" -> Then: the step is 0.01.
var cut = ctx.RenderComponent<BlazingStory.Internals.Components.Inputs.NumberInput>(builder => builder
.Add(_ => _.AllowDecimalPoint, true)
.Add(_ => _.Value, "1.21"));
cut.Find("input").GetAttribute("step").Is("0.01");

// When: emulate decremental spin button -> Then: keep the step even though the decimal point length is descreased.
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.2"));
cut.Find("input").GetAttribute("step").Is("0.01");

// When: redrawn was happened -> Then: keep the step.
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.2"));
cut.Find("input").GetAttribute("step").Is("0.01");

// When: emulate decremental spin button -> Then: keep the step.
cut.SetParametersAndRender(builder => builder.Add(_ => _.Value, "1.19"));
cut.Find("input").GetAttribute("step").Is("0.01");
}
}

0 comments on commit b92b2d0

Please sign in to comment.