Add Switch.Microsoft.AspNetCore.Mvc.UseDateTimeTypeForDateTimeOffset quirks mode
- patch recipients can use switch to undo the #6648 fix
This commit is contained in:
parent
6041c6b966
commit
fd9cb08790
|
|
@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
[HtmlTargetElement("input", Attributes = ForAttributeName, TagStructure = TagStructure.WithoutEndTag)]
|
||||
public class InputTagHelper : TagHelper
|
||||
{
|
||||
internal const string UseDateTimeLocalTypeForDateTimeOffsetSwitch = "Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset";
|
||||
private const string ForAttributeName = "asp-for";
|
||||
private const string FormatAttributeName = "asp-format";
|
||||
|
||||
|
|
@ -63,6 +64,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
{ "time", "{0:HH:mm:ss.fff}" },
|
||||
};
|
||||
|
||||
static InputTagHelper()
|
||||
{
|
||||
if (AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled) && enabled)
|
||||
{
|
||||
_defaultInputTypes.Remove(nameof(DateTimeOffset));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="InputTagHelper"/>.
|
||||
/// </summary>
|
||||
|
|
@ -393,8 +402,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
{
|
||||
// Rfc3339 mode _may_ override EditFormatString in a limited number of cases. Happens only when
|
||||
// EditFormatString has a default format i.e. came from a [DataType] attribute.
|
||||
//
|
||||
// First condition may occur when Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset
|
||||
// is true in extremely rare cases: The <input/> element for a DateTimeOffset expression must have
|
||||
// type ="text". Checking the switch again to remove that case.
|
||||
if (string.Equals("text", inputType) &&
|
||||
string.Equals(nameof(DateTimeOffset), inputTypeHint, StringComparison.OrdinalIgnoreCase))
|
||||
string.Equals(nameof(DateTimeOffset), inputTypeHint, StringComparison.OrdinalIgnoreCase) &&
|
||||
!(AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled) &&
|
||||
enabled))
|
||||
{
|
||||
// Auto-select a format that round-trips Offset and sub-Second values in a DateTimeOffset. Not
|
||||
// done if user chose the "text" type in .cshtml file or with data annotations i.e. when
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
{
|
||||
public class TemplateRenderer
|
||||
{
|
||||
public const string IEnumerableOfIFormFileName = "IEnumerable`" + nameof(IFormFile);
|
||||
internal const string UseDateTimeLocalTypeForDateTimeOffsetSwitch = "Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset";
|
||||
private const string DisplayTemplateViewPath = "DisplayTemplates";
|
||||
private const string EditorTemplateViewPath = "EditorTemplates";
|
||||
public const string IEnumerableOfIFormFileName = "IEnumerable`" + nameof(IFormFile);
|
||||
|
||||
private static readonly Dictionary<string, Func<IHtmlHelper, IHtmlContent>> _defaultDisplayActions =
|
||||
new Dictionary<string, Func<IHtmlHelper, IHtmlContent>>(StringComparer.OrdinalIgnoreCase)
|
||||
|
|
@ -75,6 +76,14 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
private readonly string _templateName;
|
||||
private readonly bool _readOnly;
|
||||
|
||||
static TemplateRenderer()
|
||||
{
|
||||
if (AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled) && enabled)
|
||||
{
|
||||
_defaultEditorActions.Remove(nameof(DateTimeOffset));
|
||||
}
|
||||
}
|
||||
|
||||
public TemplateRenderer(
|
||||
IViewEngine viewEngine,
|
||||
IViewBufferScope bufferScope,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
|
|
@ -10,6 +11,8 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public class HtmlHelperOptionsTest : IClassFixture<MvcTestFixture<RazorWebSite.Startup>>
|
||||
{
|
||||
private const string UseDateTimeLocalTypeForDateTimeOffsetSwitch = "Switch.Microsoft.AspNetCore.Mvc.UseDateTimeLocalTypeForDateTimeOffset";
|
||||
|
||||
public HtmlHelperOptionsTest(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
|
|
@ -21,14 +24,17 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
public async Task AppWideDefaultsInViewAndPartialView()
|
||||
{
|
||||
// Arrange
|
||||
AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
var expectedType = enabled ? "datetime-local" : "text";
|
||||
var expectedOffset = enabled ? string.Empty : "+00:00";
|
||||
var expected =
|
||||
@"<div class=""validation-summary-errors""><validationSummaryElement>MySummary</validationSummaryElement>
|
||||
$@"<div class=""validation-summary-errors""><validationSummaryElement>MySummary</validationSummaryElement>
|
||||
<ul><li>A model error occurred.</li>
|
||||
</ul></div>
|
||||
<validationMessageElement class=""field-validation-error"">An error occurred.</validationMessageElement>
|
||||
<input id=""Prefix!Property1"" name=""Prefix.Property1"" type=""text"" value="""" />
|
||||
<div class=""editor-label""><label for=""MyDate"">MyDate</label></div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" id=""MyDate"" name=""MyDate"" type=""text"" value=""2000-01-02T03:04:05.060+00:00"" /> </div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" id=""MyDate"" name=""MyDate"" type=""{expectedType}"" value=""2000-01-02T03:04:05.060{expectedOffset}"" /> </div>
|
||||
|
||||
<div class=""validation-summary-errors""><validationSummaryElement>MySummary</validationSummaryElement>
|
||||
<ul><li>A model error occurred.</li>
|
||||
|
|
@ -36,7 +42,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
<validationMessageElement class=""field-validation-error"">An error occurred.</validationMessageElement>
|
||||
<input id=""Prefix!Property1"" name=""Prefix.Property1"" type=""text"" value="""" />
|
||||
<div class=""editor-label""><label for=""MyDate"">MyDate</label></div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" id=""MyDate"" name=""MyDate"" type=""text"" value=""2000-01-02T03:04:05.060+00:00"" /> </div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" id=""MyDate"" name=""MyDate"" type=""{expectedType}"" value=""2000-01-02T03:04:05.060{expectedOffset}"" /> </div>
|
||||
|
||||
False";
|
||||
|
||||
|
|
@ -52,14 +58,16 @@ False";
|
|||
public async Task OverrideAppWideDefaultsInViewAndPartialView()
|
||||
{
|
||||
// Arrange
|
||||
AppContext.TryGetSwitch(UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
var expectedType = enabled ? "datetime-local" : "text";
|
||||
var expected =
|
||||
@"<div class=""validation-summary-errors""><ValidationSummaryInView>MySummary</ValidationSummaryInView>
|
||||
$@"<div class=""validation-summary-errors""><ValidationSummaryInView>MySummary</ValidationSummaryInView>
|
||||
<ul><li>A model error occurred.</li>
|
||||
</ul></div>
|
||||
<ValidationInView class=""field-validation-error"" data-valmsg-for=""Error"" data-valmsg-replace=""true"">An error occurred.</ValidationInView>
|
||||
<input id=""Prefix!Property1"" name=""Prefix.Property1"" type=""text"" value="""" />
|
||||
<div class=""editor-label""><label for=""MyDate"">MyDate</label></div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" data-val=""true"" data-val-required=""The MyDate field is required."" id=""MyDate"" name=""MyDate"" type=""text"" value=""02/01/2000 03:04:05 +00:00"" /> <ValidationInView class=""field-validation-valid"" data-valmsg-for=""MyDate"" data-valmsg-replace=""true""></ValidationInView></div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" data-val=""true"" data-val-required=""The MyDate field is required."" id=""MyDate"" name=""MyDate"" type=""{expectedType}"" value=""02/01/2000 03:04:05 +00:00"" /> <ValidationInView class=""field-validation-valid"" data-valmsg-for=""MyDate"" data-valmsg-replace=""true""></ValidationInView></div>
|
||||
|
||||
True
|
||||
<div class=""validation-summary-errors""><ValidationSummaryInPartialView>MySummary</ValidationSummaryInPartialView>
|
||||
|
|
@ -68,7 +76,7 @@ True
|
|||
<ValidationInPartialView class=""field-validation-error"" data-valmsg-for=""Error"" data-valmsg-replace=""true"">An error occurred.</ValidationInPartialView>
|
||||
<input id=""Prefix!Property1"" name=""Prefix.Property1"" type=""text"" value="""" />
|
||||
<div class=""editor-label""><label for=""MyDate"">MyDate</label></div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" id=""MyDate"" name=""MyDate"" type=""text"" value=""02/01/2000 03:04:05 +00:00"" /> <ValidationInPartialView class=""field-validation-valid"" data-valmsg-for=""MyDate"" data-valmsg-replace=""true""></ValidationInPartialView></div>
|
||||
<div class=""editor-field""><input class=""text-box single-line"" id=""MyDate"" name=""MyDate"" type=""{expectedType}"" value=""02/01/2000 03:04:05 +00:00"" /> <ValidationInPartialView class=""field-validation-valid"" data-valmsg-for=""MyDate"" data-valmsg-replace=""true""></ValidationInPartialView></div>
|
||||
|
||||
True";
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
{
|
||||
public class InputTagHelperTest
|
||||
{
|
||||
public static TheoryData MultiAttributeCheckBoxData
|
||||
public static TheoryData<TagHelperAttributeList, string> MultiAttributeCheckBoxData
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
@ -386,10 +386,22 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
Assert.Equal(expectedTagName, output.TagName);
|
||||
}
|
||||
|
||||
public static TheoryData<string, string> Process_GeneratesFormattedOutputData
|
||||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(InputTagHelper.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
return new TheoryData<string, string>
|
||||
{
|
||||
{ "datetime", "datetime" },
|
||||
{ null, enabled ? "datetime-local" : "text" },
|
||||
{ "hidden", "hidden" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("datetime", "datetime")]
|
||||
[InlineData(null, "text")]
|
||||
[InlineData("hidden", "hidden")]
|
||||
[MemberData(nameof(Process_GeneratesFormattedOutputData))]
|
||||
public void Process_GeneratesFormattedOutput(string specifiedType, string expectedType)
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -1206,20 +1218,43 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
|||
Assert.Equal(expectedTagName, output.TagName);
|
||||
}
|
||||
|
||||
public static TheoryData<string, Html5DateRenderingMode, string, string> ProcessAsync_CallsGenerateTextBox_AddsExpectedAttributesForRfc3339Data
|
||||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(InputTagHelper.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
var expectedK = enabled ? string.Empty : "K";
|
||||
return new TheoryData<string, Html5DateRenderingMode, string, string>
|
||||
{
|
||||
{ "Date", Html5DateRenderingMode.CurrentCulture, "{0:d}", "date" }, // Format from [DataType].
|
||||
{ "Date", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-dd}", "date" },
|
||||
{ "DateTime", Html5DateRenderingMode.CurrentCulture, null, "datetime-local" },
|
||||
{ "DateTime", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local" },
|
||||
{ "DateTimeOffset", Html5DateRenderingMode.CurrentCulture, null, enabled ? "datetime-local" : "text" },
|
||||
{
|
||||
"DateTimeOffset",
|
||||
Html5DateRenderingMode.Rfc3339,
|
||||
$"{{0:yyyy-MM-ddTHH:mm:ss.fff{expectedK}}}",
|
||||
enabled ? "datetime-local" : "text"
|
||||
},
|
||||
{ "DateTimeLocal", Html5DateRenderingMode.CurrentCulture, null, "datetime-local" },
|
||||
{ "DateTimeLocal", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local" },
|
||||
{ "Time", Html5DateRenderingMode.CurrentCulture, "{0:t}", "time" }, // Format from [DataType].
|
||||
{ "Time", Html5DateRenderingMode.Rfc3339, "{0:HH:mm:ss.fff}", "time" },
|
||||
{ "NullableDate", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-dd}", "date" },
|
||||
{ "NullableDateTime", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local" },
|
||||
{
|
||||
"NullableDateTimeOffset",
|
||||
Html5DateRenderingMode.Rfc3339,
|
||||
$"{{0:yyyy-MM-ddTHH:mm:ss.fff{expectedK}}}",
|
||||
enabled ? "datetime-local" : "text"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Date", Html5DateRenderingMode.CurrentCulture, "{0:d}", "date")] // Format from [DataType].
|
||||
[InlineData("Date", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-dd}", "date")]
|
||||
[InlineData("DateTime", Html5DateRenderingMode.CurrentCulture, null, "datetime-local")]
|
||||
[InlineData("DateTime", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local")]
|
||||
[InlineData("DateTimeOffset", Html5DateRenderingMode.CurrentCulture, null, "text")]
|
||||
[InlineData("DateTimeOffset", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fffK}", "text")]
|
||||
[InlineData("DateTimeLocal", Html5DateRenderingMode.CurrentCulture, null, "datetime-local")]
|
||||
[InlineData("DateTimeLocal", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local")]
|
||||
[InlineData("Time", Html5DateRenderingMode.CurrentCulture, "{0:t}", "time")] // Format from [DataType].
|
||||
[InlineData("Time", Html5DateRenderingMode.Rfc3339, "{0:HH:mm:ss.fff}", "time")]
|
||||
[InlineData("NullableDate", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-dd}", "date")]
|
||||
[InlineData("NullableDateTime", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local")]
|
||||
[InlineData("NullableDateTimeOffset", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fffK}", "text")]
|
||||
[MemberData(nameof(ProcessAsync_CallsGenerateTextBox_AddsExpectedAttributesForRfc3339Data))]
|
||||
public async Task ProcessAsync_CallsGenerateTextBox_AddsExpectedAttributesForRfc3339(
|
||||
string propertyName,
|
||||
Html5DateRenderingMode dateRenderingMode,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(TemplateRenderer.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
|
||||
// Tests use string properties and fall back to text template (no type attribute) when quirk is enabled.
|
||||
var dateTimeOffsetType = enabled ? string.Empty : " type='text'";
|
||||
return new TheoryData<string, string>
|
||||
{
|
||||
{ null, "__TextBox__ class='text-box single-line'" },
|
||||
|
|
@ -53,8 +57,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
|||
{ "datetime", "__TextBox__ class='text-box single-line' type='datetime-local'" },
|
||||
{ "DateTime-local", "__TextBox__ class='text-box single-line' type='datetime-local'" },
|
||||
{ "DATETIME-LOCAL", "__TextBox__ class='text-box single-line' type='datetime-local'" },
|
||||
{ "datetimeoffset", "__TextBox__ class='text-box single-line' type='text'" },
|
||||
{ "DateTimeOffset", "__TextBox__ class='text-box single-line' type='text'" },
|
||||
{ "datetimeoffset", $"__TextBox__ class='text-box single-line'{dateTimeOffsetType}" },
|
||||
{ "DateTimeOffset", $"__TextBox__ class='text-box single-line'{dateTimeOffsetType}" },
|
||||
{ "Time", "__TextBox__ class='text-box single-line' type='time'" },
|
||||
{ "time", "__TextBox__ class='text-box single-line' type='time'" },
|
||||
{ "Byte", "__TextBox__ class='text-box single-line' type='number'" },
|
||||
|
|
@ -774,9 +778,12 @@ Environment.NewLine;
|
|||
{
|
||||
// Arrange
|
||||
var requiredMessage = ValidationAttributeUtil.GetRequiredErrorMessage("DateTimeOffset");
|
||||
AppContext.TryGetSwitch(TemplateRenderer.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
var expectedOffset = enabled ? string.Empty : "+00:00";
|
||||
var expectedInput = "<input class=\"HtmlEncode[[text-box single-line]]\" data-val=\"HtmlEncode[[true]]\" " +
|
||||
$"data-val-required=\"HtmlEncode[[{requiredMessage}]]\" id=\"HtmlEncode[[FieldPrefix]]\" " +
|
||||
"name=\"HtmlEncode[[FieldPrefix]]\" type=\"HtmlEncode[[datetime]]\" value=\"HtmlEncode[[2000-01-02T03:04:05.060+00:00]]\" />";
|
||||
"name=\"HtmlEncode[[FieldPrefix]]\" type=\"HtmlEncode[[datetime]]\" " +
|
||||
$"value=\"HtmlEncode[[2000-01-02T03:04:05.060{expectedOffset}]]\" />";
|
||||
|
||||
var offset = TimeSpan.FromHours(0);
|
||||
var model = new DateTimeOffset(
|
||||
|
|
@ -814,14 +821,32 @@ Environment.NewLine;
|
|||
Assert.Equal(expectedInput, HtmlContentUtilities.HtmlContentToString(result));
|
||||
}
|
||||
|
||||
public static TheoryData<string, string, string, string> Editor_FindsCorrectDateOrTimeTemplateData
|
||||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(TemplateRenderer.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
var expectedOffset = enabled ? string.Empty : "-05:00";
|
||||
return new TheoryData<string, string, string, string>
|
||||
{
|
||||
{ null, null, $"2000-01-02T03:04:05.060{expectedOffset}", enabled ? "datetime-local" : "text" },
|
||||
{ "date", "{0:d}", "2000-01-02", "date" },
|
||||
{ "datetime", null, "2000-01-02T03:04:05.060", "datetime-local" },
|
||||
{ "datetime-local", null, "2000-01-02T03:04:05.060", "datetime-local" },
|
||||
{
|
||||
"DateTimeOffset",
|
||||
"{0:o}",
|
||||
$"2000-01-02T03:04:05.060{expectedOffset}",
|
||||
enabled ? "datetime-local" : "text"
|
||||
},
|
||||
{ "time", "{0:t}", "03:04:05.060", "time" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Html5DateRenderingMode.Rfc3339 is enabled by default.
|
||||
[Theory]
|
||||
[InlineData(null, null, "2000-01-02T03:04:05.060-05:00", "text")]
|
||||
[InlineData("date", "{0:d}", "2000-01-02", "date")]
|
||||
[InlineData("datetime", null, "2000-01-02T03:04:05.060", "datetime-local")]
|
||||
[InlineData("datetime-local", null, "2000-01-02T03:04:05.060", "datetime-local")]
|
||||
[InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.060-05:00", "text")]
|
||||
[InlineData("time", "{0:t}", "03:04:05.060", "time")]
|
||||
[MemberData(nameof(Editor_FindsCorrectDateOrTimeTemplateData))]
|
||||
public void Editor_FindsCorrectDateOrTimeTemplate(
|
||||
string dataTypeName,
|
||||
string editFormatString,
|
||||
|
|
@ -875,14 +900,26 @@ Environment.NewLine;
|
|||
Assert.Equal(expectedInput, HtmlContentUtilities.HtmlContentToString(result));
|
||||
}
|
||||
|
||||
public static TheoryData<string, string, string, string> Editor_FindsCorrectDateOrTimeTemplate_NotRfc3339Data
|
||||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(TemplateRenderer.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
return new TheoryData<string, string, string, string>
|
||||
{
|
||||
{ null, null, "02/01/2000 03:04:05 -05:00", enabled ? "datetime-local" : "text" },
|
||||
{ "date", "{0:d}", "02/01/2000", "date" },
|
||||
{ "datetime", null, "02/01/2000 03:04:05 -05:00", "datetime-local" },
|
||||
{ "datetime-local", null, "02/01/2000 03:04:05 -05:00", "datetime-local" },
|
||||
{ "DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.0600000-05:00", enabled ? "datetime-local" : "text" },
|
||||
{ "time", "{0:t}", "03:04", "time" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Html5DateRenderingMode.Rfc3339 can be disabled.
|
||||
[Theory]
|
||||
[InlineData(null, null, "02/01/2000 03:04:05 -05:00", "text")]
|
||||
[InlineData("date", "{0:d}", "02/01/2000", "date")]
|
||||
[InlineData("datetime", null, "02/01/2000 03:04:05 -05:00", "datetime-local")]
|
||||
[InlineData("datetime-local", null, "02/01/2000 03:04:05 -05:00", "datetime-local")]
|
||||
[InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.0600000-05:00", "text")]
|
||||
[InlineData("time", "{0:t}", "03:04", "time")]
|
||||
[MemberData(nameof(Editor_FindsCorrectDateOrTimeTemplate_NotRfc3339Data))]
|
||||
[ReplaceCulture]
|
||||
public void Editor_FindsCorrectDateOrTimeTemplate_NotRfc3339(
|
||||
string dataTypeName,
|
||||
|
|
@ -939,14 +976,32 @@ Environment.NewLine;
|
|||
Assert.Equal(expectedInput, HtmlContentUtilities.HtmlContentToString(result));
|
||||
}
|
||||
|
||||
public static TheoryData<string, string, string, string> Editor_FindsCorrectDateOrTimeTemplate_ForDateTimeData
|
||||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(TemplateRenderer.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
var expectedZ = enabled ? string.Empty : "Z";
|
||||
return new TheoryData<string, string, string, string>
|
||||
{
|
||||
{ null, null, "2000-01-02T03:04:05.060", "datetime-local" },
|
||||
{ "date", "{0:d}", "2000-01-02", "date" },
|
||||
{ "datetime", null, "2000-01-02T03:04:05.060", "datetime-local" },
|
||||
{ "datetime-local", null, "2000-01-02T03:04:05.060", "datetime-local" },
|
||||
{
|
||||
"DateTimeOffset",
|
||||
"{0:o}",
|
||||
$"2000-01-02T03:04:05.060{expectedZ}",
|
||||
enabled ? "datetime-local" : "text"
|
||||
},
|
||||
{ "time", "{0:t}", "03:04:05.060", "time" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Html5DateRenderingMode.Rfc3339 is enabled by default.
|
||||
[Theory]
|
||||
[InlineData(null, null, "2000-01-02T03:04:05.060", "datetime-local")]
|
||||
[InlineData("date", "{0:d}", "2000-01-02", "date")]
|
||||
[InlineData("datetime", null, "2000-01-02T03:04:05.060", "datetime-local")]
|
||||
[InlineData("datetime-local", null, "2000-01-02T03:04:05.060", "datetime-local")]
|
||||
[InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.060Z", "text")]
|
||||
[InlineData("time", "{0:t}", "03:04:05.060", "time")]
|
||||
[MemberData(nameof(Editor_FindsCorrectDateOrTimeTemplate_ForDateTimeData))]
|
||||
public void Editor_FindsCorrectDateOrTimeTemplate_ForDateTime(
|
||||
string dataTypeName,
|
||||
string editFormatString,
|
||||
|
|
@ -999,14 +1054,26 @@ Environment.NewLine;
|
|||
Assert.Equal(expectedInput, HtmlContentUtilities.HtmlContentToString(result));
|
||||
}
|
||||
|
||||
public static TheoryData<string, string, string, string> Editor_FindsCorrectDateOrTimeTemplate_ForDateTimeNotRfc3339Data
|
||||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(TemplateRenderer.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
return new TheoryData<string, string, string, string>
|
||||
{
|
||||
{ null, null, "02/01/2000 03:04:05", "datetime-local" },
|
||||
{ "date", "{0:d}", "02/01/2000", "date" },
|
||||
{ "datetime", null, "02/01/2000 03:04:05", "datetime-local" },
|
||||
{ "datetime-local", null, "02/01/2000 03:04:05", "datetime-local" },
|
||||
{ "DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.0600000Z", enabled ? "datetime-local" : "text" },
|
||||
{ "time", "{0:t}", "03:04", "time" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Html5DateRenderingMode.Rfc3339 can be disabled.
|
||||
[Theory]
|
||||
[InlineData(null, null, "02/01/2000 03:04:05", "datetime-local")]
|
||||
[InlineData("date", "{0:d}", "02/01/2000", "date")]
|
||||
[InlineData("datetime", null, "02/01/2000 03:04:05", "datetime-local")]
|
||||
[InlineData("datetime-local", null, "02/01/2000 03:04:05", "datetime-local")]
|
||||
[InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.0600000Z", "text")]
|
||||
[InlineData("time", "{0:t}", "03:04", "time")]
|
||||
[MemberData(nameof(Editor_FindsCorrectDateOrTimeTemplate_ForDateTimeNotRfc3339Data))]
|
||||
[ReplaceCulture]
|
||||
public void Editor_FindsCorrectDateOrTimeTemplate_ForDateTimeNotRfc3339(
|
||||
string dataTypeName,
|
||||
|
|
@ -1062,17 +1129,29 @@ Environment.NewLine;
|
|||
Assert.Equal(expectedInput, HtmlContentUtilities.HtmlContentToString(result));
|
||||
}
|
||||
|
||||
public static TheoryData<string, Html5DateRenderingMode, string> Editor_AppliesNonDefaultEditFormatData
|
||||
{
|
||||
get
|
||||
{
|
||||
AppContext.TryGetSwitch(TemplateRenderer.UseDateTimeLocalTypeForDateTimeOffsetSwitch, out var enabled);
|
||||
return new TheoryData<string, Html5DateRenderingMode, string>
|
||||
{
|
||||
{ null, Html5DateRenderingMode.CurrentCulture, enabled ? "datetime-local" : "text" },
|
||||
{ null, Html5DateRenderingMode.Rfc3339, enabled ? "datetime-local" : "text" },
|
||||
{ "date", Html5DateRenderingMode.CurrentCulture, "date" },
|
||||
{ "date", Html5DateRenderingMode.Rfc3339, "date" },
|
||||
{ "datetime", Html5DateRenderingMode.CurrentCulture, "datetime-local" },
|
||||
{ "datetime", Html5DateRenderingMode.Rfc3339, "datetime-local" },
|
||||
{ "datetime-local", Html5DateRenderingMode.CurrentCulture, "datetime-local" },
|
||||
{ "datetime-local", Html5DateRenderingMode.Rfc3339, "datetime-local" },
|
||||
{ "time", Html5DateRenderingMode.CurrentCulture, "time" },
|
||||
{ "time", Html5DateRenderingMode.Rfc3339, "time" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, Html5DateRenderingMode.CurrentCulture, "text")]
|
||||
[InlineData(null, Html5DateRenderingMode.Rfc3339, "text")]
|
||||
[InlineData("date", Html5DateRenderingMode.CurrentCulture, "date")]
|
||||
[InlineData("date", Html5DateRenderingMode.Rfc3339, "date")]
|
||||
[InlineData("datetime", Html5DateRenderingMode.CurrentCulture, "datetime-local")]
|
||||
[InlineData("datetime", Html5DateRenderingMode.Rfc3339, "datetime-local")]
|
||||
[InlineData("datetime-local", Html5DateRenderingMode.CurrentCulture, "datetime-local")]
|
||||
[InlineData("datetime-local", Html5DateRenderingMode.Rfc3339, "datetime-local")]
|
||||
[InlineData("time", Html5DateRenderingMode.CurrentCulture, "time")]
|
||||
[InlineData("time", Html5DateRenderingMode.Rfc3339, "time")]
|
||||
[MemberData(nameof(Editor_AppliesNonDefaultEditFormatData))]
|
||||
public void Editor_AppliesNonDefaultEditFormat(string dataTypeName, Html5DateRenderingMode renderingMode, string expectedType)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
Loading…
Reference in New Issue