using Annulus;
using Azimuth;
using Glass.UnitTests.Materials;
using System;
using System.Collections.Generic;
using System.Globalization;
using UnitTestSharp;
namespace Glass.UnitTests
{
public class NumberFieldTests : TestFixture
{
public static readonly NumberGrid ZeroToHundred = new NumberGrid { Max = 100 };
///
/// A field with a default behavior and no material or bounds.
///
public static NumberField NewUnstyledField(NumberField.Data data)
{
return new NumberField(new NumberFieldBehavior(), data);
}
///
/// A 100x40 field at (10, 10) with 20x20 buttons: its label spans x 10-90, its button column x 90-110.
///
public static NumberField NewField(NumberGrid grid)
{
var field = new NumberField(new NumberFieldBehavior(), new NumberField.Data { Grid = grid })
{
NumberFieldMaterial = new NumberFieldMaterial
{
IncrementButton = Glass.UnitTests.NumberFieldMaterialTests.FixedSizeButton(20, 20),
DecrementButton = Glass.UnitTests.NumberFieldMaterialTests.FixedSizeButton(20, 20),
},
};
field.Bounds = Rect.FromPositionAndSize(new Vector(10, 10), new Vector(100, 40));
return field;
}
public static NumberField NewField() => NewField(ZeroToHundred);
public static MouseState At(Scalar x, Scalar y) => new MouseState { Position = new Vector(x, y) };
public static readonly MouseState OnTheLabel = At(50, 30);
public static readonly MouseState OnTheButtons = At(100, 30);
///
/// Presses on the label at x 50 and drags to , leaving the scrub in progress.
///
public static void ScrubTo(NumberField field, Scalar x)
{
field.MouseDown(OnTheLabel, MouseButtonFlags.Left);
field.MouseMove(At(x, 30));
}
public class CtorTests : TestFixture
{
public void KeepsTheBehaviorItWasGiven()
{
var behavior = new NumberFieldBehavior();
CheckEqual(behavior, new NumberField(behavior, new NumberField.Data()).Behavior);
}
public void NullBehavior_Throws()
{
CheckThrow(typeof(ArgumentNullException));
new NumberField(null, new NumberField.Data());
}
public void InvalidGrid_Throws()
{
CheckThrow(typeof(ArgumentException));
NewUnstyledField(new NumberField.Data { Grid = new NumberGrid { Max = 1, Resolution = 0.3m } });
}
public void TakesTheDatasGridAndFormat()
{
var grid = new NumberGrid { Max = 10, Resolution = 0.5m };
Func format = (value, culture) => "custom";
var field = NewUnstyledField(new NumberField.Data { Grid = grid, Format = format });
CheckEqual(grid, field.Grid);
CheckEqual(format, field.Format);
}
public void Value_IsSnappedOntoTheDatasGridNotTheDefaultOne()
{
var field = NewUnstyledField(new NumberField.Data { Grid = ZeroToHundred, Value = 50.4m });
CheckEqual(50, field.Value);
}
public void ValueOutsideTheDatasGrid_IsClampedIntoIt()
{
var field = NewUnstyledField(new NumberField.Data { Grid = ZeroToHundred, Value = 250 });
CheckEqual(100, field.Value);
}
public void LabelShowsTheValueInTheBehaviorsCultureAndTheDatasFormat()
{
var field = new NumberField(
new NumberFieldBehavior { Culture = CultureInfo.GetCultureInfo("fr-FR") },
new NumberField.Data
{
Grid = new NumberGrid { Max = 10, Resolution = 0.5m },
Value = 1.5m,
Format = (value, culture) => value.ToString("F1", culture) + " MW",
});
CheckEqual("1,5 MW", field.DisplayText);
}
public void ButtonsReflectTheStartingValue()
{
var field = NewUnstyledField(new NumberField.Data { Grid = ZeroToHundred, Value = 100 });
CheckFalse(field.IncrementButton.Enabled);
Check(field.DecrementButton.Enabled);
}
public void DefaultData_IsZeroOnTheDefaultGrid()
{
var field = NewUnstyledField(new NumberField.Data());
CheckEqual(0, field.Value);
CheckEqual(new NumberGrid(), field.Grid);
CheckEqual("0", field.DisplayText);
}
}
public class GridTests : TestFixture
{
public void InvalidGrid_ThrowsWithoutApplyingAnyOfIt()
{
var field = NewField();
try
{
field.Grid = new NumberGrid { Max = 1, Resolution = 0.3m };
}
catch (ArgumentException)
{
}
CheckEqual(ZeroToHundred, field.Grid);
}
public void InvalidGrid_Throws()
{
var field = NewField();
CheckThrow(typeof(ArgumentException));
field.Grid = new NumberGrid { Max = 1, Resolution = 0.3m };
}
public void ValueOutsideTheNewRange_IsSnappedIntoIt()
{
var field = NewField();
field.Value = 50;
field.Grid = new NumberGrid { Max = 10 };
CheckEqual(10, field.Value);
}
public void ResnappingTheValue_RaisesOnValueChanged()
{
var field = NewField();
field.Value = 50;
decimal? raisedWith = null;
field.OnValueChanged += (_, __, valueNow) => raisedWith = valueNow;
field.Grid = new NumberGrid { Max = 10 };
CheckEqual(10, raisedWith);
}
public void ResnappingTheValue_RaisesOnceTheFieldShowsTheNewGrid()
{
var field = NewField();
field.Value = 50;
string shownWhenRaised = null;
bool incrementEnabledWhenRaised = true;
field.OnValueChanged += (numberField, _, __) =>
{
shownWhenRaised = numberField.DisplayText;
incrementEnabledWhenRaised = numberField.IncrementButton.Enabled;
};
field.Grid = new NumberGrid { Max = 10, Resolution = 0.5m };
CheckEqual("10.0", shownWhenRaised);
CheckFalse(incrementEnabledWhenRaised);
}
public void ValueSurvivingTheSnap_DoesNotRaiseOnValueChanged()
{
var field = NewField();
field.Value = 5;
int raised = 0;
field.OnValueChanged += (_, __, ___) => ++raised;
field.Grid = new NumberGrid { Max = 10 };
CheckEqual(0, raised);
}
public void MoreDecimalPlaces_RefreshesTheLabelEvenWithTheValueUnchanged()
{
var field = NewField();
field.Value = 5;
field.Grid = new NumberGrid { Max = 10, Resolution = 0.01m };
CheckEqual("5.00", field.DisplayText);
}
public void WideningPastTheValue_ReenablesTheIncrementButton()
{
var field = NewField();
field.Value = 100;
field.Grid = new NumberGrid { Max = 200 };
Check(field.IncrementButton.Enabled);
}
}
public class ValueTests : TestFixture
{
public void IsSnappedOntoTheGrid()
{
var field = NewField(new NumberGrid { Max = 10, Resolution = 0.5m });
field.Value = 2.7m;
CheckEqual(2.5m, field.Value);
}
public void IsClampedIntoRange()
{
var field = NewField();
field.Value = 250;
CheckEqual(100, field.Value);
}
public void Change_RaisesOnValueChangedWithTheFieldAndBothValues()
{
var field = NewField();
field.Value = 7;
NumberField raisedBy = null;
decimal? raisedBefore = null;
decimal? raisedNow = null;
field.OnValueChanged += (numberField, valueBefore, valueNow) =>
{
raisedBy = numberField;
raisedBefore = valueBefore;
raisedNow = valueNow;
};
field.Value = 42;
CheckEqual(field, raisedBy);
CheckEqual(7, raisedBefore);
CheckEqual(42, raisedNow);
}
public void Change_RaisesOnceTheFieldShowsTheNewValue()
{
var field = NewField();
string shownWhenRaised = null;
bool incrementEnabledWhenRaised = true;
field.OnValueChanged += (numberField, _, __) =>
{
shownWhenRaised = numberField.DisplayText;
incrementEnabledWhenRaised = numberField.IncrementButton.Enabled;
};
field.Value = 100;
CheckEqual("100", shownWhenRaised);
CheckFalse(incrementEnabledWhenRaised);
}
public void SnappingBackToTheCurrentValue_DoesNotRaiseOnValueChanged()
{
var field = NewField(new NumberGrid { Max = 10, Resolution = 0.5m });
field.Value = 2.5m;
int raised = 0;
field.OnValueChanged += (_, __, ___) => ++raised;
field.Value = 2.6m;
CheckEqual(0, raised);
}
public void Change_UpdatesDisplayText()
{
var field = NewField();
field.Value = 42;
CheckEqual("42", field.DisplayText);
}
public void AtMax_DisablesOnlyTheIncrementButton()
{
var field = NewField();
field.Value = 100;
CheckFalse(field.IncrementButton.Enabled);
Check(field.DecrementButton.Enabled);
}
public void BetweenTheBounds_EnablesBothButtons()
{
var field = NewField();
field.Value = 50;
Check(field.IncrementButton.Enabled);
Check(field.DecrementButton.Enabled);
}
}
///
/// Records each OnValueChanged as "before->now".
///
public static List RecordValueChanges(NumberField field)
{
var returnMe = new List();
field.OnValueChanged += (_, valueBefore, valueNow) => returnMe.Add($"{valueBefore}->{valueNow}");
return returnMe;
}
public class RaisesValueChangedWhileScrubbingTests : TestFixture
{
public static NumberField NewFieldAtFifty(bool raisesValueChangedWhileScrubbing)
{
var field = NewField();
field.Value = 50;
field.RaisesValueChangedWhileScrubbing = raisesValueChangedWhileScrubbing;
return field;
}
public void DefaultsToTrue()
{
Check(NewField().RaisesValueChangedWhileScrubbing);
}
public void True_RaisesEachStepAsItHappens()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: true);
List changes = RecordValueChanges(field);
ScrubTo(field, 58);
field.MouseMove(At(66, 30));
CheckEqual(new[] { "50->51", "51->52" }, changes);
}
public void False_RaisesNothingMidScrub()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: false);
List changes = RecordValueChanges(field);
ScrubTo(field, 58);
field.MouseMove(At(66, 30));
CheckEqual(0, changes.Count);
CheckEqual(52, field.Value);
}
public void False_RaisesTheNetChangeOnceOnRelease()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: false);
List changes = RecordValueChanges(field);
ScrubTo(field, 58);
field.MouseMove(At(66, 30));
field.MouseUp(At(66, 30), MouseButtonFlags.Left);
CheckEqual(new[] { "50->52" }, changes);
}
public void False_ReleasedBackWhereItStarted_RaisesNothing()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: false);
List changes = RecordValueChanges(field);
ScrubTo(field, 66);
field.MouseMove(At(50, 30));
field.MouseUp(At(50, 30), MouseButtonFlags.Left);
CheckEqual(0, changes.Count);
}
public void False_Cancelled_RaisesNothing()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: false);
List changes = RecordValueChanges(field);
ScrubTo(field, 66);
field.CancelMouseInput();
CheckEqual(0, changes.Count);
CheckEqual(50, field.Value);
}
public void False_CancelledOntoANarrowedGrid_RaisesTheChangeFromTheStart()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: false);
List changes = RecordValueChanges(field);
ScrubTo(field, 66);
field.Grid = new NumberGrid { Max = 10 };
field.CancelMouseInput();
CheckEqual(new[] { "50->10" }, changes);
}
public void True_Cancelled_RaisesTheRevert()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: true);
List changes = RecordValueChanges(field);
ScrubTo(field, 58);
field.CancelMouseInput();
CheckEqual(new[] { "50->51", "51->50" }, changes);
}
public void False_ChangesOutsideAScrub_StillRaise()
{
var field = NewFieldAtFifty(raisesValueChangedWhileScrubbing: false);
List changes = RecordValueChanges(field);
field.Value = 60;
field.StepBy(1);
CheckEqual(new[] { "50->60", "60->61" }, changes);
}
}
public class OnScrubFinishedTests : TestFixture
{
public void Release_RaisesTheFieldAndTheNetChange()
{
var field = NewField();
field.Value = 50;
NumberField raisedBy = null;
string raisedWith = null;
field.OnScrubFinished += (numberField, valueBefore, valueNow) =>
{
raisedBy = numberField;
raisedWith = $"{valueBefore}->{valueNow}";
};
ScrubTo(field, 66);
field.MouseUp(At(66, 30), MouseButtonFlags.Left);
CheckEqual(field, raisedBy);
CheckEqual("50->52", raisedWith);
}
public void RaisedAfterTheNetOnValueChanged()
{
var field = NewField();
field.RaisesValueChangedWhileScrubbing = false;
var raised = new List();
field.OnValueChanged += (_, __, ___) => raised.Add(nameof(NumberField.OnValueChanged));
field.OnScrubFinished += (_, __, ___) => raised.Add(nameof(NumberField.OnScrubFinished));
ScrubTo(field, 58);
field.MouseUp(At(58, 30), MouseButtonFlags.Left);
CheckEqual(new[] { nameof(NumberField.OnValueChanged), nameof(NumberField.OnScrubFinished) }, raised);
}
public void ReleasedBackWhereItStarted_IsNotRaised()
{
var field = NewField();
int raised = 0;
field.OnScrubFinished += (_, __, ___) => ++raised;
ScrubTo(field, 66);
field.MouseMove(At(50, 30));
field.MouseUp(At(50, 30), MouseButtonFlags.Left);
CheckEqual(0, raised);
}
public void Cancelled_IsNotRaised()
{
var field = NewField();
int raised = 0;
field.OnScrubFinished += (_, __, ___) => ++raised;
ScrubTo(field, 66);
field.CancelMouseInput();
CheckEqual(0, raised);
}
}
public class NumberFieldDataTests : TestFixture
{
public void Getter_ReflectsChangesMadeThroughTheOtherProperties()
{
var field = NewField();
Func format = (value, culture) => "custom";
field.Value = 7;
field.Format = format;
NumberField.Data data = field.NumberFieldData;
CheckEqual(ZeroToHundred, data.Grid);
CheckEqual(7, data.Value);
CheckEqual(format, data.Format);
}
public void Setter_SnapsTheValueOntoTheNewGridRatherThanTheOld()
{
var field = NewField(new NumberGrid { Max = 10 });
field.NumberFieldData = new NumberField.Data { Grid = ZeroToHundred, Value = 50 };
CheckEqual(50, field.Value);
CheckEqual(ZeroToHundred, field.Grid);
}
public void Setter_AppliesTheFormat()
{
var field = NewField();
field.NumberFieldData = new NumberField.Data
{
Grid = ZeroToHundred,
Format = (value, culture) => value + " MW",
};
CheckEqual("0 MW", field.DisplayText);
}
public void Setter_RaisesOnValueChangedOnceWithTheOldAndNewValues()
{
var field = NewField(new NumberGrid { Max = 10 });
field.Value = 5;
int raised = 0;
decimal? raisedBefore = null;
decimal? raisedNow = null;
field.OnValueChanged += (_, valueBefore, valueNow) =>
{
++raised;
raisedBefore = valueBefore;
raisedNow = valueNow;
};
field.NumberFieldData = new NumberField.Data { Grid = ZeroToHundred, Value = 50 };
CheckEqual(1, raised);
CheckEqual(5, raisedBefore);
CheckEqual(50, raisedNow);
}
public void UnchangedValue_RefreshesTheLabelWithoutRaisingOnValueChanged()
{
var field = NewField();
field.Value = 5;
int raised = 0;
field.OnValueChanged += (_, __, ___) => ++raised;
field.NumberFieldData = new NumberField.Data
{
Grid = new NumberGrid { Max = 10, Resolution = 0.5m },
Value = 5,
};
CheckEqual(0, raised);
CheckEqual("5.0", field.DisplayText);
}
public void InvalidGrid_ThrowsWithoutApplyingAnyOfIt()
{
var field = NewField();
field.Value = 7;
try
{
field.NumberFieldData = new NumberField.Data
{
Grid = new NumberGrid { Max = 1, Resolution = 0.3m },
Value = 1,
Format = (value, culture) => "custom",
};
}
catch (ArgumentException)
{
}
CheckEqual(ZeroToHundred, field.Grid);
CheckEqual(7, field.Value);
CheckNull(field.Format);
}
}
public class BehaviorTests : TestFixture
{
public static NumberField NewFieldShowingOneAndAHalf(NumberFieldBehavior behavior)
{
var field = NewField(new NumberGrid { Max = 10, Resolution = 0.5m });
field.Value = 1.5m;
field.Behavior = behavior;
return field;
}
public void Null_Throws()
{
var field = NewField();
CheckThrow(typeof(ArgumentNullException));
field.Behavior = null;
}
public void Assigning_ReformatsTheLabelAtOnce()
{
var field = NewFieldShowingOneAndAHalf(
new NumberFieldBehavior { Culture = CultureInfo.GetCultureInfo("fr-FR") });
CheckEqual("1,5", field.DisplayText);
}
public void CultureChangedAfterAssigning_ShowsFromTheNextValueChange()
{
var behavior = new NumberFieldBehavior();
var field = NewFieldShowingOneAndAHalf(behavior);
behavior.Culture = CultureInfo.GetCultureInfo("fr-FR");
field.Value = 2;
CheckEqual("2,0", field.DisplayText);
}
public void ScrubDistanceChangedAfterAssigning_AppliesToTheNextScrub()
{
var behavior = new NumberFieldBehavior();
var field = NewField();
field.Behavior = behavior;
behavior.ScrubDistancePerStep = 4;
ScrubTo(field, 58);
CheckEqual(2, field.Value);
}
}
public class FormatTests : TestFixture
{
public void Unset_ShowsGridDecimalPlacesDigits()
{
var field = NewField(new NumberGrid { Max = 1, Resolution = 0.001m });
field.Value = 0.5m;
CheckEqual("0.500", field.DisplayText);
}
public void Custom_ReplacesTheDefaultAndReformatsTheLabel()
{
var field = NewField();
field.Value = 7;
field.Format = (value, culture) => value + " MW";
CheckEqual("7 MW", field.DisplayText);
}
public void Custom_IsHandedBehaviorsCulture()
{
CultureInfo french = CultureInfo.GetCultureInfo("fr-FR");
var field = NewField();
field.Behavior = new NumberFieldBehavior { Culture = french };
CultureInfo handed = null;
field.Format = (value, culture) =>
{
handed = culture;
return "";
};
CheckEqual(french, handed);
}
public void ClearedBackToNull_RestoresTheDefault()
{
var field = NewField();
field.Value = 7;
field.Format = (value, culture) => "custom";
field.Format = null;
CheckEqual("7", field.DisplayText);
}
}
public class NumberFieldMaterialTests : TestFixture
{
static readonly Material Background = new Material { DebugName = "background" };
static readonly TextMaterial LabelTemplate = TextMaterialTests.UnmarginedText("template");
static readonly ButtonMaterial Increment = new ButtonMaterial(new Material { DebugName = "increment" });
static readonly ButtonMaterial Decrement = new ButtonMaterial(new Material { DebugName = "decrement" });
static readonly NumberFieldMaterial FullSet = new NumberFieldMaterial
{
Background = Background,
Label = LabelTemplate,
IncrementButton = Increment,
DecrementButton = Decrement,
};
public void Setter_AssignsTheBackgroundAndButtonsDirectly()
{
var field = NewUnstyledField(new NumberField.Data());
field.NumberFieldMaterial = FullSet;
CheckEqual(Background, field.Material);
CheckEqual(Increment, field.IncrementButton.ButtonMaterial);
CheckEqual(Decrement, field.DecrementButton.ButtonMaterial);
}
public void Setter_GivesTheLabelACopyOfTheTemplateShowingTheValue()
{
var field = NewUnstyledField(new NumberField.Data { Grid = ZeroToHundred, Value = 42 });
field.NumberFieldMaterial = FullSet;
var labelMaterial = (TextMaterial)field.Label.Material;
CheckNotEqual(LabelTemplate, labelMaterial);
CheckEqual("42", labelMaterial.Text.ToString());
}
public void ValueChanges_ReachTheCopyButNotTheTemplate()
{
var field = NewUnstyledField(new NumberField.Data { Grid = ZeroToHundred });
field.NumberFieldMaterial = FullSet;
field.Value = 42;
CheckEqual("42", ((TextMaterial)field.Label.Material).Text.ToString());
CheckEqual("template", LabelTemplate.Text.ToString());
}
public void BackgroundWithABorder_InsetsTheChildrenImmediately()
{
var field = NewField();
NumberFieldMaterial material = field.NumberFieldMaterial;
material.Background = new Material { BorderSize = new Rect.BorderSize(5) };
field.NumberFieldMaterial = material;
CheckEqual(Rect.FromPositionAndSize(Vector.Zero, new Vector(70, 30)), field.Label.Bounds);
}
public void NoLabelTemplate_LeavesTheLabelWithoutAMaterial()
{
var field = NewUnstyledField(new NumberField.Data());
field.NumberFieldMaterial = new NumberFieldMaterial();
CheckNull(field.Label.Material);
}
public void Getter_RoundTripsWhatTheSetterAssigned()
{
var field = NewUnstyledField(new NumberField.Data());
field.NumberFieldMaterial = FullSet;
CheckEqual(FullSet, field.NumberFieldMaterial);
}
}
public class MaterialTests : TestFixture
{
public void BackgroundBorder_InsetsTheChildrenImmediately()
{
var field = NewField();
field.Material = new Material { BorderSize = new Rect.BorderSize(5) };
CheckEqual(Rect.FromPositionAndSize(Vector.Zero, new Vector(70, 30)), field.Label.Bounds);
}
}
public class LayoutTests : TestFixture
{
public void LabelFillsWhatTheButtonColumnLeaves()
{
CheckEqual(Rect.FromPositionAndSize(Vector.Zero, new Vector(80, 40)), NewField().Label.Bounds);
}
public void IncrementButton_TakesTheTopHalfOfTheColumn()
{
CheckEqual(Rect.FromPositionAndSize(new Vector(80, 0), new Vector(20, 20)),
NewField().IncrementButton.Bounds);
}
public void DecrementButton_TakesTheBottomHalfOfTheColumn()
{
CheckEqual(Rect.FromPositionAndSize(new Vector(80, 20), new Vector(20, 20)),
NewField().DecrementButton.Bounds);
}
public void ColumnWiderThanTheField_IsClampedToIt()
{
var field = NewField();
field.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(15, 40));
CheckEqual(15, field.IncrementButton.Bounds.Width);
CheckEqual(0, field.Label.Bounds.Width);
}
public void ChangingAButtonMaterial_RelaysOutImmediately()
{
var field = NewField();
field.DecrementButton.ButtonMaterial = Glass.UnitTests.NumberFieldMaterialTests.FixedSizeButton(30, 20);
CheckEqual(70, field.Label.Bounds.Width);
}
}
public class PreferredBoundsSizeTests : TestFixture
{
///
/// NewField's 20px button column, with a label of 3x50px monospace glyphs.
///
public static NumberField NewFieldWithALabel(NumberGrid grid)
{
var field = NewField(grid);
NumberFieldMaterial material = field.NumberFieldMaterial;
material.Label = TextMaterialTests.UnmarginedText("", glyphWidth: 3, glyphHeight: 50);
field.NumberFieldMaterial = material;
return field;
}
public void MinWider_FitsTheLabelAtMin()
{
var field = NewFieldWithALabel(new NumberGrid { Min = -100, Max = 5 });
// "-100" is four glyphs beside the button column, and the glyphs outgrow the column's 40px.
CheckEqual(new Vector(32, 50), field.PreferredBoundsSize);
}
public void MaxWider_FitsTheLabelAtMax()
{
var field = NewFieldWithALabel(new NumberGrid { Min = 5, Max = 10000 });
CheckEqual(new Vector(35, 50), field.PreferredBoundsSize);
}
public void CustomFormat_IsWhatGetsMeasured()
{
var field = NewFieldWithALabel(new NumberGrid { Max = 5 });
field.Format = (value, culture) => value + " MW";
CheckEqual(new Vector(32, 50), field.PreferredBoundsSize);
}
public void NoLabelTemplate_IsJustTheButtonColumn()
{
CheckEqual(new Vector(20, 40), NewField().PreferredBoundsSize);
}
}
public class StepByTests : TestFixture
{
public void MovesAlongTheStepLattice()
{
var field = NewField(new NumberGrid { Max = 100, Step = 5 });
field.Value = 3;
field.StepBy(2);
CheckEqual(10, field.Value);
}
public void ClampsAtTheEnds()
{
var field = NewField();
field.StepBy(-3);
CheckEqual(0, field.Value);
}
}
public class IncrementButtonClickTests : TestFixture
{
public void StepsUpOnce()
{
var field = NewField(new NumberGrid { Max = 100, Step = 5 });
field.IncrementButton.Click(new MouseState(), MouseButtonFlags.Left);
CheckEqual(5, field.Value);
}
}
public class DecrementButtonClickTests : TestFixture
{
public void StepsDownOnce()
{
var field = NewField(new NumberGrid { Max = 100, Step = 5 });
field.Value = 50;
field.DecrementButton.Click(new MouseState(), MouseButtonFlags.Left);
CheckEqual(45, field.Value);
}
}
public class EnabledTests : TestFixture
{
public void SettingFalse_DisablesBothButtons()
{
var field = NewField();
field.Value = 50;
field.Enabled = false;
CheckFalse(field.IncrementButton.Enabled);
CheckFalse(field.DecrementButton.Enabled);
}
public void SettingTrueAgain_KeepsAButtonAtItsBoundDisabled()
{
var field = NewField();
field.Enabled = false;
field.Enabled = true;
Check(field.IncrementButton.Enabled);
CheckFalse(field.DecrementButton.Enabled);
}
}
public class MouseWheelTests : TestFixture
{
public void AwayFromTheUser_StepsUp()
{
var field = NewField();
CheckTrue(field.MouseWheel(new MouseState(), notches: 2));
CheckEqual(2, field.Value);
}
public void TowardTheUser_StepsDown()
{
var field = NewField();
field.Value = 50;
field.MouseWheel(new MouseState(), notches: -1);
CheckEqual(49, field.Value);
}
public void PartialNotches_AddUpToAStep()
{
var field = NewField();
field.MouseWheel(new MouseState(), notches: 0.5);
CheckEqual(0, field.Value);
field.MouseWheel(new MouseState(), notches: 0.5);
CheckEqual(1, field.Value);
}
public void AlreadyAtTheLimit_StillClaimsTheWheel()
{
var field = NewField();
CheckTrue(field.MouseWheel(new MouseState(), notches: -1));
}
public void SingleValueGrid_DeclinesIt()
{
var field = NewField(new NumberGrid { Min = 5, Max = 5 });
CheckFalse(field.MouseWheel(new MouseState(), notches: 1));
}
public void Disabled_DeclinesItAndStaysPut()
{
var field = NewField();
field.Enabled = false;
CheckFalse(field.MouseWheel(new MouseState(), notches: 1));
CheckEqual(0, field.Value);
}
}
public class MouseDownTests : TestFixture
{
public void LeftOnTheLabel_IsClaimed()
{
CheckTrue(NewField().MouseDown(OnTheLabel, MouseButtonFlags.Left));
}
public void JustInsideTheLabelsRightEdge_IsClaimed()
{
CheckTrue(NewField().MouseDown(At(85, 30), MouseButtonFlags.Left));
}
public void OnTheButtonColumn_IsDeclined()
{
CheckFalse(NewField().MouseDown(OnTheButtons, MouseButtonFlags.Left));
}
public void RightOnTheLabel_IsDeclined()
{
CheckFalse(NewField().MouseDown(OnTheLabel, MouseButtonFlags.Right));
}
public void Disabled_IsDeclined()
{
var field = NewField();
field.Enabled = false;
CheckFalse(field.MouseDown(OnTheLabel, MouseButtonFlags.Left));
}
public void SingleValueGrid_IsDeclined()
{
var field = NewField(new NumberGrid { Min = 5, Max = 5 });
CheckFalse(field.MouseDown(OnTheLabel, MouseButtonFlags.Left));
}
}
public class MouseMoveTests : TestFixture
{
public void OneScrubDistanceRight_StepsUpOnce()
{
var field = NewField();
ScrubTo(field, 58);
CheckEqual(1, field.Value);
}
public void UnderHalfAScrubDistance_LeavesTheValue()
{
var field = NewField();
ScrubTo(field, 53);
CheckEqual(0, field.Value);
}
public void Leftward_StepsDown()
{
var field = NewField();
field.Value = 50;
ScrubTo(field, 26);
CheckEqual(47, field.Value);
}
public void DraggingBack_ReturnsExactlyToTheStart()
{
var field = NewField();
field.Value = 50;
ScrubTo(field, 90);
field.MouseMove(At(50, 30));
CheckEqual(50, field.Value);
}
public void Upward_StepsUp()
{
var field = NewField();
field.Value = 50;
field.MouseDown(OnTheLabel, MouseButtonFlags.Left);
field.MouseMove(At(50, 22));
CheckEqual(51, field.Value);
}
public void Downward_StepsDown()
{
var field = NewField();
field.Value = 50;
field.MouseDown(OnTheLabel, MouseButtonFlags.Left);
field.MouseMove(At(50, 54));
CheckEqual(47, field.Value);
}
public void DiagonalUpAndRight_CountsBothAxes()
{
var field = NewField();
field.Value = 50;
field.MouseDown(OnTheLabel, MouseButtonFlags.Left);
field.MouseMove(At(58, 22));
CheckEqual(52, field.Value);
}
public void DiagonalDownAndRight_CancelsOut()
{
var field = NewField();
field.Value = 50;
field.MouseDown(OnTheLabel, MouseButtonFlags.Left);
field.MouseMove(At(90, 70));
CheckEqual(50, field.Value);
}
public void DraggingBackVertically_ReturnsExactlyToTheStart()
{
var field = NewField();
field.Value = 50;
field.MouseDown(OnTheLabel, MouseButtonFlags.Left);
field.MouseMove(At(50, -10));
field.MouseMove(At(50, 30));
CheckEqual(50, field.Value);
}
public void PushingPastMaxUpward_TurningBackDownRespondsAtOnce()
{
var field = NewField(new NumberGrid { Max = 3 });
field.MouseDown(OnTheLabel, MouseButtonFlags.Left);
field.MouseMove(At(50, -70));
field.MouseMove(At(50, -62));
CheckEqual(2, field.Value);
}
public void ScrubDistancePerStep_SetsTheScale()
{
var field = NewField();
field.Behavior = new NumberFieldBehavior { ScrubDistancePerStep = 4 };
ScrubTo(field, 58);
CheckEqual(2, field.Value);
}
public void PushingPastMax_TurningBackRespondsAtOnce()
{
var field = NewField(new NumberGrid { Max = 3 });
ScrubTo(field, 150);
field.MouseMove(At(142, 30));
CheckEqual(2, field.Value);
}
public void PushingPastMin_TurningBackRespondsAtOnce()
{
var field = NewField(new NumberGrid { Max = 3 });
field.Value = 3;
ScrubTo(field, -50);
field.MouseMove(At(-42, 30));
CheckEqual(1, field.Value);
}
public void WithoutAScrub_IsDeclined()
{
CheckFalse(NewField().MouseMove(OnTheLabel));
}
}
public class MouseUpTests : TestFixture
{
public void EndsTheScrub()
{
var field = NewField();
ScrubTo(field, 58);
CheckTrue(field.MouseUp(At(58, 30), MouseButtonFlags.Left));
field.MouseMove(At(90, 30));
CheckEqual(1, field.Value);
}
public void RightReleaseMidScrub_KeepsScrubbing()
{
var field = NewField();
ScrubTo(field, 58);
field.MouseUp(At(58, 30), MouseButtonFlags.Right);
field.MouseMove(At(66, 30));
CheckEqual(2, field.Value);
}
public void WithoutAScrub_IsDeclined()
{
CheckFalse(NewField().MouseUp(OnTheLabel, MouseButtonFlags.Left));
}
}
public class CancelMouseInputTests : TestFixture
{
public void MidScrub_PutsTheValueBackAndEndsTheScrub()
{
var field = NewField();
field.Value = 50;
ScrubTo(field, 90);
field.CancelMouseInput();
field.MouseMove(At(10, 30));
CheckEqual(50, field.Value);
}
public void GridNarrowedMidScrub_PutsTheValueBackWithinTheNewGrid()
{
var field = NewField();
field.Value = 50;
ScrubTo(field, 90);
field.Grid = new NumberGrid { Max = 10 };
field.CancelMouseInput();
CheckEqual(10, field.Value);
}
public void WithoutAScrub_LeavesTheValue()
{
var field = NewField();
field.Value = 50;
field.CancelMouseInput();
CheckEqual(50, field.Value);
}
}
public class CursorAtTests : TestFixture
{
private sealed class SentinelCursor : Cursor
{
}
public void OverTheLabel_IsTheScrubCursor()
{
var cursor = new SentinelCursor();
var field = NewField();
field.ScrubCursor = cursor;
CheckEqual(cursor, field.CursorAt(OnTheLabel));
}
public void OverTheButtons_IsNull()
{
var field = NewField();
field.ScrubCursor = new SentinelCursor();
CheckNull(field.CursorAt(OnTheButtons));
}
public void MidScrubOffTheLabel_StaysTheScrubCursor()
{
var cursor = new SentinelCursor();
var field = NewField();
field.ScrubCursor = cursor;
ScrubTo(field, 500);
CheckEqual(cursor, field.CursorAt(At(500, 30)));
}
public void Disabled_IsNull()
{
var field = NewField();
field.ScrubCursor = new SentinelCursor();
field.Enabled = false;
CheckNull(field.CursorAt(OnTheLabel));
}
public void SingleValueGrid_IsNull()
{
var field = NewField(new NumberGrid { Min = 5, Max = 5 });
field.ScrubCursor = new SentinelCursor();
CheckNull(field.CursorAt(OnTheLabel));
}
}
}
}