@@ -1819,11 +1819,84 @@ public async Task ProcessAsync_CallsGenerateTextBox_InputTypeDateTime_RendersAsD
18191819 Assert . Equal ( expectedTagName , output . TagName ) ;
18201820 }
18211821
1822+ [ Fact ]
1823+ public async Task ProcessAsync_CallsGenerateTextBox_InputTypeDateOnly_RendersAsDate ( )
1824+ {
1825+ // Arrange
1826+ var expectedAttributes = new TagHelperAttributeList
1827+ {
1828+ { "type" , "date" } , // Calculated; not passed to HtmlGenerator.
1829+ } ;
1830+ var expectedTagName = "not-input" ;
1831+
1832+ var context = new TagHelperContext (
1833+ tagName : "input" ,
1834+ allAttributes : new TagHelperAttributeList ( )
1835+ {
1836+ { "type" , "date" }
1837+ } ,
1838+ items : new Dictionary < object , object > ( ) ,
1839+ uniqueId : "test" ) ;
1840+
1841+ var output = new TagHelperOutput (
1842+ expectedTagName ,
1843+ attributes : new TagHelperAttributeList ( ) ,
1844+ getChildContentAsync : ( useCachedResult , encoder ) => Task . FromResult < TagHelperContent > (
1845+ new DefaultTagHelperContent ( ) ) )
1846+ {
1847+ TagMode = TagMode . SelfClosing ,
1848+ } ;
1849+
1850+ var htmlAttributes = new Dictionary < string , object >
1851+ {
1852+ { "type" , "date" }
1853+ } ;
1854+
1855+ var metadataProvider = TestModelMetadataProvider . CreateDefaultProvider ( ) ;
1856+
1857+ var htmlGenerator = new Mock < IHtmlGenerator > ( MockBehavior . Strict ) ;
1858+ var tagHelper = GetTagHelper (
1859+ htmlGenerator . Object ,
1860+ model : null ,
1861+ propertyName : "DateOnly" ,
1862+ metadataProvider : metadataProvider ) ;
1863+ tagHelper . ViewContext . Html5DateRenderingMode = Html5DateRenderingMode . Rfc3339 ;
1864+ tagHelper . InputTypeName = "date" ;
1865+ var tagBuilder = new TagBuilder ( "input" ) ;
1866+ htmlGenerator
1867+ . Setup ( mock => mock . GenerateTextBox (
1868+ tagHelper . ViewContext ,
1869+ tagHelper . For . ModelExplorer ,
1870+ tagHelper . For . Name ,
1871+ null , // value
1872+ @"{0:yyyy-MM-dd}" ,
1873+ htmlAttributes ) ) // htmlAttributes
1874+ . Returns ( tagBuilder )
1875+ . Verifiable ( ) ;
1876+
1877+ // Act
1878+ await tagHelper . ProcessAsync ( context , output ) ;
1879+
1880+ // Assert
1881+ htmlGenerator . Verify ( ) ;
1882+
1883+ Assert . Equal ( TagMode . SelfClosing , output . TagMode ) ;
1884+ Assert . Equal ( expectedAttributes , output . Attributes ) ;
1885+ Assert . Empty ( output . PreContent . GetContent ( ) ) ;
1886+ Assert . Equal ( string . Empty , output . Content . GetContent ( ) ) ;
1887+ Assert . Empty ( output . PostContent . GetContent ( ) ) ;
1888+ Assert . Equal ( expectedTagName , output . TagName ) ;
1889+ }
1890+
18221891 [ Theory ]
18231892 [ InlineData ( "Date" , Html5DateRenderingMode . CurrentCulture , "{0:d}" , "date" ) ] // Format from [DataType].
18241893 [ InlineData ( "Date" , Html5DateRenderingMode . Rfc3339 , "{0:yyyy-MM-dd}" , "date" ) ]
18251894 [ InlineData ( "DateTime" , Html5DateRenderingMode . CurrentCulture , null , "datetime-local" ) ]
18261895 [ InlineData ( "DateTime" , Html5DateRenderingMode . Rfc3339 , @"{0:yyyy-MM-ddTHH\:mm\:ss.fff}" , "datetime-local" ) ]
1896+ [ InlineData ( "DateOnlyDate" , Html5DateRenderingMode . CurrentCulture , "{0:d}" , "date" ) ] // Format from [DataType].
1897+ [ InlineData ( "DateOnlyDate" , Html5DateRenderingMode . Rfc3339 , "{0:yyyy-MM-dd}" , "date" ) ]
1898+ [ InlineData ( "DateOnly" , Html5DateRenderingMode . CurrentCulture , null , "text" ) ] // Format from [DataType].
1899+ [ InlineData ( "DateOnly" , Html5DateRenderingMode . Rfc3339 , null , "text" ) ]
18271900 [ InlineData ( "DateTimeOffset" , Html5DateRenderingMode . CurrentCulture , null , "text" ) ]
18281901 [ InlineData ( "DateTimeOffset" , Html5DateRenderingMode . Rfc3339 , @"{0:yyyy-MM-ddTHH\:mm\:ss.fffK}" , "text" ) ]
18291902 [ InlineData ( "DateTimeLocal" , Html5DateRenderingMode . CurrentCulture , null , "datetime-local" ) ]
@@ -1836,6 +1909,8 @@ public async Task ProcessAsync_CallsGenerateTextBox_InputTypeDateTime_RendersAsD
18361909 [ InlineData ( "Week" , Html5DateRenderingMode . Rfc3339 , null , "week" ) ]
18371910 [ InlineData ( "NullableDate" , Html5DateRenderingMode . Rfc3339 , "{0:yyyy-MM-dd}" , "date" ) ]
18381911 [ InlineData ( "NullableDateTime" , Html5DateRenderingMode . Rfc3339 , @"{0:yyyy-MM-ddTHH\:mm\:ss.fff}" , "datetime-local" ) ]
1912+ [ InlineData ( "NullableDateOnlyDate" , Html5DateRenderingMode . Rfc3339 , "{0:yyyy-MM-dd}" , "date" ) ]
1913+ [ InlineData ( "NullableDateOnly" , Html5DateRenderingMode . Rfc3339 , null , "text" ) ]
18391914 [ InlineData ( "NullableDateTimeOffset" , Html5DateRenderingMode . Rfc3339 , @"{0:yyyy-MM-ddTHH\:mm\:ss.fffK}" , "text" ) ]
18401915 public async Task ProcessAsync_CallsGenerateTextBox_AddsExpectedAttributesForRfc3339 (
18411916 string propertyName ,
@@ -1973,6 +2048,63 @@ public async Task ProcessAsync_CallsGenerateTextBox_ProducesExpectedValue_ForDat
19732048 Assert . Equal ( expectedType , output . TagName ) ;
19742049 }
19752050
2051+ // Html5DateRenderingMode.Rfc3339 is enabled by default.
2052+ [ Theory ]
2053+ [ InlineData ( "DateOnlyDate" , "2000-01-02" , "date" ) ]
2054+ [ InlineData ( "DateOnly" , "02/01/2000" , "text" ) ]
2055+ [ ReplaceCulture ]
2056+ public async Task ProcessAsync_CallsGenerateTextBox_ProducesExpectedValue_ForDateOnly (
2057+ string propertyName ,
2058+ string expectedValue ,
2059+ string expectedType )
2060+ {
2061+ // Arrange
2062+ var expectedAttributes = new TagHelperAttributeList
2063+ {
2064+ { "type" , expectedType } ,
2065+ { "id" , propertyName } ,
2066+ { "name" , propertyName } ,
2067+ { "value" , expectedValue } ,
2068+ } ;
2069+
2070+ var context = new TagHelperContext (
2071+ tagName : "input" ,
2072+ allAttributes : new TagHelperAttributeList (
2073+ Enumerable . Empty < TagHelperAttribute > ( ) ) ,
2074+ items : new Dictionary < object , object > ( ) ,
2075+ uniqueId : "test" ) ;
2076+
2077+ var output = new TagHelperOutput (
2078+ expectedType ,
2079+ attributes : new TagHelperAttributeList ( ) ,
2080+ getChildContentAsync : ( useCachedResult , encoder ) => Task . FromResult < TagHelperContent > (
2081+ new DefaultTagHelperContent ( ) ) )
2082+ {
2083+ TagMode = TagMode . SelfClosing ,
2084+ } ;
2085+
2086+ var metadataProvider = TestModelMetadataProvider . CreateDefaultProvider ( ) ;
2087+ var model = new DateOnly (
2088+ year : 2000 ,
2089+ month : 1 ,
2090+ day : 2 ) ;
2091+
2092+ var htmlGenerator = HtmlGeneratorUtilities . GetHtmlGenerator ( metadataProvider ) ;
2093+ var tagHelper = GetTagHelper (
2094+ htmlGenerator ,
2095+ model : model ,
2096+ propertyName : propertyName ,
2097+ metadataProvider : metadataProvider ) ;
2098+ tagHelper . ViewContext . Html5DateRenderingMode = Html5DateRenderingMode . Rfc3339 ;
2099+
2100+ // Act
2101+ await tagHelper . ProcessAsync ( context , output ) ;
2102+
2103+ // Assert
2104+ Assert . Equal ( expectedAttributes , output . Attributes ) ;
2105+ Assert . Equal ( expectedType , output . TagName ) ;
2106+ }
2107+
19762108 // Html5DateRenderingMode.Rfc3339 can be disabled.
19772109 [ Theory ]
19782110 [ InlineData ( "Date" , null , "02/01/2000" , "date" ) ]
@@ -2048,6 +2180,67 @@ public async Task ProcessAsync_CallsGenerateTextBox_ProducesExpectedValue_ForDat
20482180 Assert . Equal ( expectedType , output . TagName ) ;
20492181 }
20502182
2183+ // Html5DateRenderingMode.Rfc3339 can be disabled.
2184+ [ Theory ]
2185+ [ InlineData ( "DateOnlyDate" , null , "02/01/2000" , "date" ) ]
2186+ [ InlineData ( "DateOnlyDate" , "{0:d}" , "02/01/2000" , "date" ) ]
2187+ [ InlineData ( "DateOnly" , null , "02/01/2000" , "text" ) ]
2188+ [ ReplaceCulture ]
2189+ public async Task ProcessAsync_CallsGenerateTextBox_ProducesExpectedValue_ForDateOnlyNotRfc3339 (
2190+ string propertyName ,
2191+ string editFormatString ,
2192+ string expectedValue ,
2193+ string expectedType )
2194+ {
2195+ // Arrange
2196+ var expectedAttributes = new TagHelperAttributeList
2197+ {
2198+ { "type" , expectedType } ,
2199+ { "id" , propertyName } ,
2200+ { "name" , propertyName } ,
2201+ { "value" , expectedValue } ,
2202+ } ;
2203+
2204+ var context = new TagHelperContext (
2205+ tagName : "input" ,
2206+ allAttributes : new TagHelperAttributeList (
2207+ Enumerable . Empty < TagHelperAttribute > ( ) ) ,
2208+ items : new Dictionary < object , object > ( ) ,
2209+ uniqueId : "test" ) ;
2210+
2211+ var output = new TagHelperOutput (
2212+ expectedType ,
2213+ attributes : new TagHelperAttributeList ( ) ,
2214+ getChildContentAsync : ( useCachedResult , encoder ) => Task . FromResult < TagHelperContent > (
2215+ new DefaultTagHelperContent ( ) ) )
2216+ {
2217+ TagMode = TagMode . SelfClosing ,
2218+ } ;
2219+
2220+ var metadataProvider = TestModelMetadataProvider . CreateDefaultProvider ( ) ;
2221+
2222+ var model = new DateOnly (
2223+ year : 2000 ,
2224+ month : 1 ,
2225+ day : 2 ) ;
2226+
2227+ var htmlGenerator = HtmlGeneratorUtilities . GetHtmlGenerator ( metadataProvider ) ;
2228+ var tagHelper = GetTagHelper (
2229+ htmlGenerator ,
2230+ model : model ,
2231+ propertyName : propertyName ,
2232+ metadataProvider : metadataProvider ) ;
2233+ tagHelper . ViewContext . Html5DateRenderingMode = Html5DateRenderingMode . CurrentCulture ;
2234+ tagHelper . Format = editFormatString ;
2235+
2236+ // Act
2237+ await tagHelper . ProcessAsync ( context , output ) ;
2238+
2239+ // Assert
2240+ Assert . Equal ( expectedAttributes , output . Attributes ) ;
2241+ Assert . Equal ( expectedType , output . TagName ) ;
2242+ }
2243+
20512244 // Html5DateRenderingMode.Rfc3339 can be disabled.
20522245 [ Theory ]
20532246 [ InlineData ( "Month" , "month" ) ]
@@ -2184,13 +2377,23 @@ private class Model
21842377
21852378 public DateTime DateTime { get ; set ; }
21862379
2380+ [ DataType ( DataType . Date ) ]
2381+ public DateOnly DateOnlyDate { get ; set ; }
2382+
2383+ public DateOnly DateOnly { get ; set ; }
2384+
21872385 public DateTimeOffset DateTimeOffset { get ; set ; }
21882386
21892387 [ DataType ( DataType . Date ) ]
21902388 public DateTime ? NullableDate { get ; set ; }
21912389
21922390 public DateTime ? NullableDateTime { get ; set ; }
21932391
2392+ [ DataType ( DataType . Date ) ]
2393+ public DateOnly ? NullableDateOnlyDate { get ; set ; }
2394+
2395+ public DateOnly ? NullableDateOnly { get ; set ; }
2396+
21942397 public DateTimeOffset ? NullableDateTimeOffset { get ; set ; }
21952398
21962399 [ DataType ( "datetime-local" ) ]
0 commit comments