mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-04-05 22:01:04 +00:00
1428 lines
57 KiB
C#
1428 lines
57 KiB
C#
using Bunit;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using Xunit;
|
|
|
|
namespace Radzen.Blazor.Tests
|
|
{
|
|
public class DatePickerTests
|
|
{
|
|
[Fact]
|
|
public void DatePicker_Renders_CssClass()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
Assert.Contains(@$"rz-datepicker", component.Markup);
|
|
Assert.Contains(@$"rz-calendar", component.Markup);
|
|
Assert.Contains(@$"rz-calendar-header", component.Markup);
|
|
Assert.Contains(@$"rz-calendar-view", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_ShowTimeParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ShowTime, true));
|
|
|
|
Assert.Contains(@$"rz-timepicker", component.Markup);
|
|
Assert.Contains(@$"rz-hour-picker", component.Markup);
|
|
Assert.Contains(@$"rz-minute-picker", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_ShowSecondsParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add<bool>(p => p.ShowTime, true);
|
|
parameters.Add<bool>(p => p.ShowSeconds, true);
|
|
});
|
|
|
|
Assert.Contains(@$"rz-timepicker", component.Markup);
|
|
Assert.Contains(@$"rz-hour-picker", component.Markup);
|
|
Assert.Contains(@$"rz-minute-picker", component.Markup);
|
|
Assert.Contains(@$"rz-second-picker", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_ShowTimeOkButtonParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add<bool>(p => p.ShowTime, true);
|
|
parameters.Add<bool>(p => p.ShowTimeOkButton, true);
|
|
});
|
|
|
|
Assert.Contains(@$"rz-timepicker", component.Markup);
|
|
Assert.Contains(@$"rz-hour-picker", component.Markup);
|
|
Assert.Contains(@$"rz-minute-picker", component.Markup);
|
|
Assert.Contains(@$"<span class=""rz-button-text"">Ok</span>", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_DateFormatParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var format = "d";
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.DateFormat, format);
|
|
parameters.Add<object>(p => p.Value, DateTime.Now);
|
|
});
|
|
|
|
Assert.Contains(@$"value=""{string.Format("{0:" + format + "}", DateTime.Now)}""", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_HourFormatParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add<bool>(p => p.ShowTime, true);
|
|
parameters.Add(p => p.HourFormat, "12");
|
|
});
|
|
|
|
Assert.Contains(@$"rz-ampm-picker", component.Markup);
|
|
Assert.Contains(@$"rzi-chevron-up", component.Markup);
|
|
Assert.Contains(@$"rzi-chevron-down", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_TimeOnlyParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add<bool>(p => p.ShowTime, true);
|
|
parameters.Add<bool>(p => p.TimeOnly, true);
|
|
});
|
|
|
|
Assert.DoesNotContain(@$"rz-calendar-header", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_AllowClearParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add<object>(p => p.Value, DateTime.Now);
|
|
parameters.Add<bool>(p => p.AllowClear, true);
|
|
});
|
|
|
|
Assert.Contains(@$"<button type=""button"" class=""notranslate rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_TabIndexParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var value = 1;
|
|
|
|
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.TabIndex, value));
|
|
|
|
Assert.Contains(@$"tabindex=""{value}""", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_EmptyCssClass_WhenValueIsEmpty()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, null));
|
|
|
|
Assert.Contains(@$"rz-state-empty", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_DoesNotRender_EmptyCssClass_WhenValueIsNotEmpty()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, DateTime.Now));
|
|
|
|
Assert.DoesNotContain(@$"rz-state-empty", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_DisabledParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Disabled, true));
|
|
|
|
Assert.Contains(@$"disabled", component.Markup);
|
|
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_ReadOnlyParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var value = true;
|
|
|
|
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, value));
|
|
|
|
Assert.Contains(@$"readonly", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_StyleParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var value = "width:20px";
|
|
|
|
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
|
|
|
Assert.Contains(@$"style=""{value}""", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_UnmatchedParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
|
|
|
Assert.Contains(@$"autofocus", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NotRaises_ChangeEventOnNextMonth()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
component.Find(".rz-calendar-next-icon").Click();
|
|
|
|
Assert.False(raised);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NotRaises_ValueChangedEventOnNextMonth()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
component.Find(".rz-calendar-next-icon").Click();
|
|
|
|
Assert.False(raised);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NotRaises_ChangeEventOnPrevMonth()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
component.Find(".rz-calendar-prev-icon").Click();
|
|
|
|
Assert.False(raised);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NotRaises_ValueChangedEventOnPrevMonth()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
component.Find(".rz-calendar-prev-icon").Click();
|
|
|
|
Assert.False(raised);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Raises_ValueChangedEvent_Returns_PreviousDateOnInputOnDisabledDates()
|
|
{
|
|
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
|
|
DateTime previousDay = DateTime.Today.AddDays(-1);
|
|
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
|
|
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
|
|
});
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
// initialize DateTimeValue
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
|
|
inputElement.Change(previousDay.AddDays(-1));
|
|
|
|
// try to enter disabled date
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
|
|
inputElement.Change(DateTime.Today);
|
|
|
|
Assert.True(raised);
|
|
Assert.Equal(previousDay, (DateTime)newValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Clears_InputOnDisabledDates()
|
|
{
|
|
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
|
|
DateTime previousDay = DateTime.Today.AddDays(-1);
|
|
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
|
|
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
|
|
});
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
// initialize DateTimeValue
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
|
|
inputElement.Change(previousDay.AddDays(-1));
|
|
|
|
// try to enter disabled date
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
|
|
inputElement.Change(DateTime.Today);
|
|
|
|
Assert.True(raised);
|
|
Assert.Null(newValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Parses_Input_Using_DateFormat()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.DateFormat, "ddMM");
|
|
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
string input = "3012";
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
|
|
inputElement.Change(input);
|
|
|
|
Assert.True(raised);
|
|
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
|
|
}
|
|
|
|
|
|
[Fact]
|
|
public void DatePicker_Parses_Input_Using_ParseInput()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
|
|
|
|
Func<string, DateTime?> customParseInput = (input) =>
|
|
{
|
|
if (DateTime.TryParseExact(input, "ddMM", null, DateTimeStyles.None, out var result))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.ParseInput, customParseInput);
|
|
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
string input = "3012";
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
|
|
inputElement.Change(input);
|
|
|
|
Assert.True(raised);
|
|
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
|
|
}
|
|
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_Blank_WhenValueIsMaxValue()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, DateTime.MaxValue);
|
|
});
|
|
|
|
Assert.Contains(@$"rz-state-empty", component.Markup);
|
|
Assert.Contains(@$"value=""""", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_Blank_WhenValueIsMinValue()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, DateTime.MinValue);
|
|
});
|
|
|
|
Assert.Contains(@$"rz-state-empty", component.Markup);
|
|
Assert.Contains(@$"value=""""", component.Markup);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(DateTimeKind.Local)]
|
|
[InlineData(DateTimeKind.Unspecified)]
|
|
[InlineData(DateTimeKind.Utc)]
|
|
public void DatePicker_Respects_DateTimeKind(DateTimeKind kind)
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(x => x.Kind, kind);
|
|
parameters.Add(x => x.ShowTime, true);
|
|
});
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
|
|
component.SetParametersAndRender(parameters =>
|
|
{
|
|
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
component.Find(".rz-calendar-next-icon").Click();
|
|
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
|
|
|
|
Assert.True(raised);
|
|
Assert.Equal(kind, ((DateTime)newValue).Kind);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Renders_FooterTemplate()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
string actionsTemplate = "<input type=\"button\" value=\"Test\" />";
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, DateTime.MinValue);
|
|
parameters.Add(p => p.FooterTemplate, actionsTemplate);
|
|
});
|
|
|
|
Assert.Contains(actionsTemplate, component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Converts_DateTimeOffSet_FromUtc_ToLocal()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var valueUtc = DateTimeOffset.UtcNow;
|
|
var kind = DateTimeKind.Local;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Kind, kind);
|
|
parameters.Add(p => p.Value, valueUtc);
|
|
});
|
|
|
|
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
|
|
Assert.Equal(valueUtc.LocalDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Converts_DateTimeOffSet_Local_ToUtc()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var valueUtc = DateTimeOffset.Now;
|
|
var kind = DateTimeKind.Utc;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Kind, kind);
|
|
parameters.Add(p => p.Value, valueUtc);
|
|
});
|
|
|
|
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
|
|
Assert.Equal(valueUtc.UtcDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Displays_Calender_Icon()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
Assert.Contains(@$"rzi-calendar", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Displays_Schedule_Icon()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.TimeOnly, true);
|
|
});
|
|
|
|
Assert.Contains(@$"rzi-time", component.Markup);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Supports_DateOnly()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
DateOnly? dateOnly = new DateOnly(2024, 1, 31);
|
|
DateOnly? valueChangedValue = null!;
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateOnly?>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, dateOnly);
|
|
parameters.Add(p => p.ValueChanged, args => { valueChangedValue = args; });
|
|
});
|
|
|
|
Assert.False(component.Instance.ShowTime);
|
|
var input = component.Find("input");
|
|
input.GetAttribute("value").MarkupMatches(dateOnly.ToString());
|
|
|
|
// update to new value
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
DateOnly? enteredValue = new DateOnly(2024, 2, 28);
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(enteredValue.Value.ToShortDateString());
|
|
inputElement.Change(enteredValue);
|
|
|
|
input.GetAttribute("value").MarkupMatches(enteredValue.ToString());
|
|
Assert.Equal(enteredValue, component.Instance.Value);
|
|
Assert.Equal(enteredValue, valueChangedValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Supports_TimeOnly()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
TimeOnly? timeOnly = new TimeOnly(23, 59, 59);
|
|
TimeOnly? valueChangedValue = null!;
|
|
var component = ctx.RenderComponent<RadzenDatePicker<TimeOnly>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, timeOnly);
|
|
parameters.Add(p => p.ValueChanged, args => { valueChangedValue = args; });
|
|
});
|
|
|
|
Assert.True(component.Instance.TimeOnly);
|
|
Assert.True(component.Instance.ShowTime);
|
|
var input = component.Find("input");
|
|
input.GetAttribute("value").MarkupMatches(timeOnly.ToString());
|
|
|
|
// update to new value
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
TimeOnly? enteredValue = new TimeOnly(1, 4, 5);
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(enteredValue.Value.ToLongTimeString());
|
|
inputElement.Change(enteredValue);
|
|
|
|
input.GetAttribute("value").MarkupMatches(enteredValue.ToString());
|
|
Assert.Equal(enteredValue, component.Instance.Value);
|
|
Assert.Equal(enteredValue, valueChangedValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_ShowCalendarWeek_WeekNumberAddedInAdditionalColumn()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
|
|
{
|
|
parameter.Add(p => p.ShowCalendarWeek, true);
|
|
});
|
|
|
|
Assert.Contains(@$"rz-calendar-week-number", component.Markup);
|
|
Assert.Equal(8, component.FindAll(".rz-calendar-view th").Count());
|
|
// check header and week number column
|
|
Assert.Single(component.FindAll("th.rz-datepicker-week-number"));
|
|
Assert.Equal(6, component.FindAll("td.rz-calendar-week-number").Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_ShowCalendarWeekFalse_NoAdditionalColumn()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
|
|
{
|
|
parameter.Add(p => p.ShowCalendarWeek, false);
|
|
});
|
|
|
|
Assert.DoesNotContain(@$"rz-calendar-week-number", component.Markup);
|
|
Assert.Equal(7, component.FindAll(".rz-calendar-view th").Count());
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_ShowCalendarWeekWithCustomTitle_TitleCorrectlyRendered()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
|
|
{
|
|
parameter.Add(p => p.ShowCalendarWeek, true);
|
|
parameter.Add(p => p.CalendarWeekTitle, "Wk");
|
|
});
|
|
|
|
var weekNumberHeader = component.Find(".rz-calendar-view th.rz-datepicker-week-number");
|
|
Assert.Contains("Wk", weekNumberHeader.InnerHtml);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Multiple_Selects_IEnumerableDateTime()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
IEnumerable<DateTime> emitted = null;
|
|
var initial = new DateTime(2024, 1, 1);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTime>>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Multiple, true);
|
|
parameters.Add(p => p.InitialViewDate, initial);
|
|
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
|
|
});
|
|
|
|
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "10").ParentElement.Click());
|
|
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "12").ParentElement.Click());
|
|
|
|
Assert.NotNull(emitted);
|
|
var list = emitted.ToList();
|
|
Assert.Equal(2, list.Count);
|
|
Assert.Contains(new DateTime(2024, 1, 10), list.Select(d => d.Date));
|
|
Assert.Contains(new DateTime(2024, 1, 12), list.Select(d => d.Date));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Multiple_Selects_IEnumerableNullableDateTime()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
IEnumerable<DateTime?> emitted = null;
|
|
var initial = new DateTime(2024, 2, 1);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTime?>>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Multiple, true);
|
|
parameters.Add(p => p.InitialViewDate, initial);
|
|
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
|
|
});
|
|
|
|
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "3").ParentElement.Click());
|
|
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "14").ParentElement.Click());
|
|
|
|
Assert.NotNull(emitted);
|
|
var list = emitted.ToList();
|
|
Assert.Equal(2, list.Count);
|
|
Assert.Contains(new DateTime(2024, 2, 3), list.Select(d => d.Value.Date));
|
|
Assert.Contains(new DateTime(2024, 2, 14), list.Select(d => d.Value.Date));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Multiple_Emits_IEnumerableDateTimeOffsetNullable_WithUtcKind()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
IEnumerable<DateTimeOffset?> emitted = null;
|
|
var initial = new DateTime(2024, 3, 1);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTimeOffset?>>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Multiple, true);
|
|
parameters.Add(p => p.InitialViewDate, initial);
|
|
parameters.Add(p => p.Kind, DateTimeKind.Utc);
|
|
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
|
|
});
|
|
|
|
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "5").ParentElement.Click());
|
|
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "20").ParentElement.Click());
|
|
|
|
Assert.NotNull(emitted);
|
|
var list = emitted.ToList();
|
|
Assert.Equal(2, list.Count);
|
|
Assert.All(list, dto => Assert.Equal(TimeSpan.Zero, dto.Value.Offset));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Multiple_Emits_IEnumerableDateOnlyAndTimeOnlyNullable()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
IEnumerable<DateOnly?> emittedDates = null;
|
|
IEnumerable<TimeOnly?> emittedTimes = null;
|
|
var initial = new DateTime(2024, 4, 1);
|
|
|
|
var compDates = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateOnly?>>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Multiple, true);
|
|
parameters.Add(p => p.InitialViewDate, initial);
|
|
parameters.Add(p => p.ValueChanged, args => { emittedDates = args; });
|
|
});
|
|
|
|
compDates.InvokeAsync(() => compDates.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "7").ParentElement.Click());
|
|
compDates.InvokeAsync(() => compDates.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "9").ParentElement.Click());
|
|
|
|
Assert.NotNull(emittedDates);
|
|
var dateList = emittedDates.ToList();
|
|
Assert.Equal(2, dateList.Count);
|
|
Assert.Contains(new DateOnly(2024, 4, 7), dateList.Select(d => d.Value));
|
|
Assert.Contains(new DateOnly(2024, 4, 9), dateList.Select(d => d.Value));
|
|
|
|
// TimeOnly? emission should produce midnight times for selected dates
|
|
var compTimes = ctx.RenderComponent<RadzenDatePicker<IEnumerable<TimeOnly?>>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Multiple, true);
|
|
parameters.Add(p => p.InitialViewDate, initial);
|
|
parameters.Add(p => p.ValueChanged, args => { emittedTimes = args; });
|
|
});
|
|
|
|
compTimes.InvokeAsync(() => compTimes.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "1").ParentElement.Click());
|
|
compTimes.InvokeAsync(() => compTimes.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "2").ParentElement.Click());
|
|
|
|
Assert.NotNull(emittedTimes);
|
|
var timeList = emittedTimes.ToList();
|
|
Assert.Equal(2, timeList.Count);
|
|
Assert.All(timeList, t => Assert.Equal(new TimeOnly(0, 0, 0), t.Value));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_WithoutOkButton_TimeChange_ImmediatelyCommits()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var changeCount = 0;
|
|
DateTime? lastChangeValue = null;
|
|
DateTime? lastValueChanged = null;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, false);
|
|
parameters.Add(p => p.Value, new DateTime(2024, 6, 15, 10, 30, 0));
|
|
parameters.Add(p => p.Change, args => { changeCount++; lastChangeValue = args; });
|
|
parameters.Add(p => p.ValueChanged, args => { lastValueChanged = args; });
|
|
});
|
|
|
|
component.Find(".rz-hour-picker .rz-numeric-up").Click();
|
|
|
|
Assert.Equal(1, changeCount);
|
|
Assert.NotNull(lastChangeValue);
|
|
Assert.Equal(11, lastChangeValue.Value.Hour);
|
|
Assert.NotNull(lastValueChanged);
|
|
Assert.Equal(11, lastValueChanged.Value.Hour);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_WithoutOkButton_DayClick_ImmediatelyCommits()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var changeRaised = false;
|
|
DateTime? lastValueChanged = null;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, false);
|
|
parameters.Add(p => p.Value, new DateTime(2024, 6, 15, 10, 30, 0));
|
|
parameters.Add(p => p.Change, args => { changeRaised = true; });
|
|
parameters.Add(p => p.ValueChanged, args => { lastValueChanged = args; });
|
|
});
|
|
|
|
component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "20").ParentElement.Click();
|
|
|
|
Assert.True(changeRaised);
|
|
Assert.NotNull(lastValueChanged);
|
|
Assert.Equal(20, lastValueChanged.Value.Day);
|
|
Assert.Equal(10, lastValueChanged.Value.Hour);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_WithOkButton_TimeChange_RevertsOnClose()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var initialDate = new DateTime(2024, 6, 15, 10, 30, 0);
|
|
var valueChangedCount = 0;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, true);
|
|
parameters.Add(p => p.Value, initialDate);
|
|
parameters.Add(p => p.ValueChanged, args => { valueChangedCount++; });
|
|
});
|
|
|
|
var hourInput = component.Find(".rz-hour-picker input");
|
|
Assert.Equal("10", hourInput.GetAttribute("value"));
|
|
|
|
component.Find(".rz-hour-picker .rz-numeric-up").Click();
|
|
|
|
hourInput = component.Find(".rz-hour-picker input");
|
|
Assert.Equal("11", hourInput.GetAttribute("value"));
|
|
Assert.Equal(0, valueChangedCount);
|
|
|
|
component.InvokeAsync(() => component.Instance.Close());
|
|
|
|
hourInput = component.Find(".rz-hour-picker input");
|
|
Assert.Equal("10", hourInput.GetAttribute("value"));
|
|
|
|
var input = component.Find(".rz-inputtext");
|
|
Assert.Contains("10", input.GetAttribute("value"));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_WithOkButton_TimeChange_CommitsOnOk()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
DateTime? lastValueChanged = null;
|
|
DateTime? lastChangeValue = null;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, true);
|
|
parameters.Add(p => p.Value, new DateTime(2024, 6, 15, 10, 30, 0));
|
|
parameters.Add(p => p.ValueChanged, args => { lastValueChanged = args; });
|
|
parameters.Add(p => p.Change, args => { lastChangeValue = args; });
|
|
});
|
|
|
|
component.Find(".rz-hour-picker .rz-numeric-up").Click();
|
|
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
|
|
|
|
Assert.NotNull(lastValueChanged);
|
|
Assert.Equal(11, lastValueChanged.Value.Hour);
|
|
Assert.NotNull(lastChangeValue);
|
|
Assert.Equal(11, lastChangeValue.Value.Hour);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_WithOkButton_DayCommits_ThenTimeRevertsOnClose()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
DateTime? lastValueChanged = null;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, true);
|
|
parameters.Add(p => p.Value, new DateTime(2024, 6, 15, 10, 30, 0));
|
|
parameters.Add(p => p.ValueChanged, args => { lastValueChanged = args; });
|
|
});
|
|
|
|
component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "20").ParentElement.Click();
|
|
|
|
Assert.NotNull(lastValueChanged);
|
|
Assert.Equal(20, lastValueChanged.Value.Day);
|
|
Assert.Equal(10, lastValueChanged.Value.Hour);
|
|
|
|
component.Find(".rz-hour-picker .rz-numeric-up").Click();
|
|
|
|
component.InvokeAsync(() => component.Instance.Close());
|
|
|
|
var input = component.Find(".rz-inputtext");
|
|
Assert.Contains("10", input.GetAttribute("value"));
|
|
Assert.Contains("20", input.GetAttribute("value"));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_WithOkButton_OnPopupClose_RevertsTimeChange()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var initialDate = new DateTime(2024, 6, 15, 10, 30, 0);
|
|
DateTime? lastValueChanged = null;
|
|
var valueChangedCount = 0;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, true);
|
|
parameters.Add(p => p.Value, initialDate);
|
|
parameters.Add(p => p.ValueChanged, args => { valueChangedCount++; lastValueChanged = args; });
|
|
});
|
|
|
|
component.Find(".rz-hour-picker .rz-numeric-up").Click();
|
|
|
|
var countBeforeClose = valueChangedCount;
|
|
|
|
component.InvokeAsync(() => component.Instance.OnPopupClose());
|
|
|
|
Assert.Equal(countBeforeClose, valueChangedCount);
|
|
|
|
var input = component.Find("input");
|
|
Assert.Contains("10", input.GetAttribute("value"));
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_OkClick_Fires_OnOkButtonClick()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var okClickRaised = false;
|
|
DateTime? okClickValue = null;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, true);
|
|
parameters.Add(p => p.OkClick, args => { okClickRaised = true; okClickValue = args; });
|
|
});
|
|
|
|
component.Find(".rz-calendar-next-icon").Click();
|
|
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
|
|
|
|
Assert.True(okClickRaised);
|
|
Assert.NotNull(okClickValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_OkClick_DoesNotFire_OnDaySelection()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var okClickRaised = false;
|
|
var changeRaised = false;
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.ShowTimeOkButton, true);
|
|
parameters.Add(p => p.Change, args => { changeRaised = true; });
|
|
parameters.Add(p => p.OkClick, args => { okClickRaised = true; });
|
|
});
|
|
|
|
component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "15").ParentElement.Click();
|
|
|
|
Assert.True(changeRaised);
|
|
Assert.False(okClickRaised);
|
|
}
|
|
[Fact]
|
|
public void DatePicker_Renders_ImmediateParameter()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
parameters.Add(p => p.Immediate, true));
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
Assert.Contains("oninput", inputElement.ToMarkup());
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_DoesNotRender_OninputWhenNotImmediate()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
Assert.DoesNotContain("oninput", inputElement.ToMarkup());
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Immediate_Raises_ChangeOnValidInput()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var raised = false;
|
|
object newValue = null;
|
|
var testDate = new DateTime(2025, 6, 15);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Immediate, true);
|
|
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(testDate.ToShortDateString());
|
|
inputElement.Input(testDate.ToShortDateString());
|
|
|
|
Assert.True(raised);
|
|
Assert.Equal(testDate, ((DateTime?)newValue)?.Date);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Immediate_DoesNotUpdateOnInvalidInput()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var initialDate = new DateTime(2025, 6, 15);
|
|
var changeCount = 0;
|
|
|
|
// Use non-nullable DateTime so ParseDate does not clear the value on invalid input
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Immediate, true);
|
|
parameters.Add(p => p.Value, initialDate);
|
|
parameters.Add(p => p.Change, args => { changeCount++; });
|
|
});
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
// Simulate partial/invalid input
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult("abc");
|
|
inputElement.Input("abc");
|
|
|
|
// ParseDateImmediate ignores invalid input; ParseDate also reverts to FormattedValue for non-nullable.
|
|
// Value should remain unchanged.
|
|
Assert.Equal(initialDate, component.Instance.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_Immediate_Raises_ValueChangedOnValidInput()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var raised = false;
|
|
DateTime? newValue = null;
|
|
var testDate = new DateTime(2025, 3, 20);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Immediate, true);
|
|
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
|
});
|
|
|
|
var inputElement = component.Find(".rz-inputtext");
|
|
|
|
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(testDate.ToShortDateString());
|
|
inputElement.Input(testDate.ToShortDateString());
|
|
|
|
Assert.True(raised);
|
|
Assert.Equal(testDate, newValue?.Date);
|
|
}
|
|
[Fact]
|
|
public void DatePicker_NonGregorianCalendar_Renders_CorrectDayNumbers()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
// Thai Buddhist calendar: same months/days as Gregorian, year offset by +543
|
|
var thaiCulture = new CultureInfo("th-TH");
|
|
var testDate = new DateTime(2024, 4, 3);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, testDate);
|
|
parameters.Add(p => p.Culture, thaiCulture);
|
|
parameters.Add(p => p.Inline, true);
|
|
});
|
|
|
|
var dayCells = component.FindAll("td span.rz-state-default");
|
|
var dayNumbers = dayCells.Select(c => c.TextContent.Trim()).Where(t => !string.IsNullOrEmpty(t)).ToList();
|
|
|
|
// April has 30 days — day numbers 1-30 should appear
|
|
Assert.Contains("1", dayNumbers);
|
|
Assert.Contains("3", dayNumbers);
|
|
Assert.Contains("30", dayNumbers);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NonGregorianCalendar_ActiveDay_IsCorrect()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var thaiCulture = new CultureInfo("th-TH");
|
|
// April 3, 2024 Gregorian = day 3 in Thai Buddhist calendar (same day)
|
|
var testDate = new DateTime(2024, 4, 3);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, testDate);
|
|
parameters.Add(p => p.Culture, thaiCulture);
|
|
parameters.Add(p => p.Inline, true);
|
|
});
|
|
|
|
var activeDay = component.Find("span.rz-state-active");
|
|
Assert.Equal("3", activeDay.TextContent.Trim());
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NonGregorianCalendar_MonthDropdown_ShowsCorrectMonth()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var thaiCulture = new CultureInfo("th-TH");
|
|
var testDate = new DateTime(2024, 4, 3);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, testDate);
|
|
parameters.Add(p => p.Culture, thaiCulture);
|
|
parameters.Add(p => p.Inline, true);
|
|
});
|
|
|
|
// Month dropdown should show the Thai name for April (month 4)
|
|
var monthDropdown = component.Find(".rz-calendar-month-dropdown");
|
|
var monthName = thaiCulture.DateTimeFormat.GetMonthName(4);
|
|
Assert.Contains(monthName, monthDropdown.InnerHtml);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NonGregorianCalendar_YearDropdown_ShowsCalendarYear()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var thaiCulture = new CultureInfo("th-TH");
|
|
// 2024 Gregorian = 2567 Thai Buddhist
|
|
var testDate = new DateTime(2024, 4, 3);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, testDate);
|
|
parameters.Add(p => p.Culture, thaiCulture);
|
|
parameters.Add(p => p.Inline, true);
|
|
});
|
|
|
|
var yearDropdown = component.Find(".rz-calendar-year-dropdown");
|
|
Assert.Contains("2567", yearDropdown.InnerHtml);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NonGregorianCalendar_OtherMonthDays_MarkedCorrectly()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var thaiCulture = new CultureInfo("th-TH");
|
|
var testDate = new DateTime(2024, 4, 3);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, testDate);
|
|
parameters.Add(p => p.Culture, thaiCulture);
|
|
parameters.Add(p => p.Inline, true);
|
|
});
|
|
|
|
var currentMonthCells = component.FindAll("td:not(.rz-calendar-other-month):not(.rz-calendar-week-number)");
|
|
Assert.True(currentMonthCells.Count > 0);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NonGregorianCalendar_DayClick_SetsCorrectValue()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var thaiCulture = new CultureInfo("th-TH");
|
|
var testDate = new DateTime(2024, 4, 1);
|
|
|
|
DateTime? changedValue = null;
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, testDate);
|
|
parameters.Add(p => p.Culture, thaiCulture);
|
|
parameters.Add(p => p.Inline, true);
|
|
parameters.Add(p => p.ValueChanged, (DateTime v) => { changedValue = v; });
|
|
});
|
|
|
|
// Click on day "10"
|
|
var dayCells = component.FindAll("td[role='button'] span.rz-state-default");
|
|
var day10 = dayCells.FirstOrDefault(c => c.TextContent.Trim() == "10" && !c.ClassList.Contains("rz-calendar-other-month"));
|
|
|
|
if (day10 != null)
|
|
{
|
|
day10.ParentElement!.Click();
|
|
|
|
Assert.NotNull(changedValue);
|
|
Assert.Equal(new DateTime(2024, 4, 10).Date, changedValue!.Value.Date);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NonGregorianCalendar_FormattedValue_UsesCalendarYear()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var thaiCulture = new CultureInfo("th-TH");
|
|
var testDate = new DateTime(2024, 4, 3);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, testDate);
|
|
parameters.Add(p => p.Culture, thaiCulture);
|
|
});
|
|
|
|
// The formatted value should use Thai Buddhist year 2567
|
|
var formattedValue = component.Instance.FormattedValue;
|
|
Assert.False(string.IsNullOrEmpty(formattedValue));
|
|
Assert.Contains("2567", formattedValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_ShowTime_MinToday_DoesNotDisableToday()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var today = DateTime.Now;
|
|
var min = new DateTime(today.Year, today.Month, today.Day, 14, 0, 0);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, today);
|
|
parameters.Add(p => p.ShowTime, true);
|
|
parameters.Add(p => p.Min, min);
|
|
});
|
|
|
|
// Find today's cell - it should not have rz-state-disabled
|
|
var todayCell = component.FindAll("td span.rz-calendar-today");
|
|
Assert.NotEmpty(todayCell);
|
|
Assert.DoesNotContain("rz-state-disabled", todayCell.First().ClassName);
|
|
}
|
|
|
|
[Fact]
|
|
public void DatePicker_NoShowTime_MinToday_DisablesToday()
|
|
{
|
|
using var ctx = new TestContext();
|
|
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
|
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
|
|
|
var today = DateTime.Now;
|
|
var min = new DateTime(today.Year, today.Month, today.Day, 14, 0, 0);
|
|
|
|
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
|
{
|
|
parameters.Add(p => p.Value, today);
|
|
parameters.Add(p => p.Min, min);
|
|
});
|
|
|
|
// Without ShowTime, today should be disabled since midnight < 14:00
|
|
var todayCell = component.FindAll("td span.rz-calendar-today");
|
|
Assert.NotEmpty(todayCell);
|
|
Assert.Contains("rz-state-disabled", todayCell.First().ClassName);
|
|
}
|
|
}
|
|
}
|