1. from datetime import date
    
  2. 
    
  3. from django.forms import DateField, Form, SelectDateWidget
    
  4. from django.test import ignore_warnings, override_settings
    
  5. from django.utils import translation
    
  6. from django.utils.dates import MONTHS_AP
    
  7. from django.utils.deprecation import RemovedInDjango50Warning
    
  8. 
    
  9. from .base import WidgetTest
    
  10. 
    
  11. 
    
  12. class SelectDateWidgetTest(WidgetTest):
    
  13.     maxDiff = None
    
  14.     widget = SelectDateWidget(
    
  15.         years=(
    
  16.             "2007",
    
  17.             "2008",
    
  18.             "2009",
    
  19.             "2010",
    
  20.             "2011",
    
  21.             "2012",
    
  22.             "2013",
    
  23.             "2014",
    
  24.             "2015",
    
  25.             "2016",
    
  26.         ),
    
  27.     )
    
  28. 
    
  29.     def test_render_empty(self):
    
  30.         self.check_html(
    
  31.             self.widget,
    
  32.             "mydate",
    
  33.             "",
    
  34.             html=(
    
  35.                 """
    
  36.             <select name="mydate_month" id="id_mydate_month">
    
  37.                 <option selected value="">---</option>
    
  38.                 <option value="1">January</option>
    
  39.                 <option value="2">February</option>
    
  40.                 <option value="3">March</option>
    
  41.                 <option value="4">April</option>
    
  42.                 <option value="5">May</option>
    
  43.                 <option value="6">June</option>
    
  44.                 <option value="7">July</option>
    
  45.                 <option value="8">August</option>
    
  46.                 <option value="9">September</option>
    
  47.                 <option value="10">October</option>
    
  48.                 <option value="11">November</option>
    
  49.                 <option value="12">December</option>
    
  50.             </select>
    
  51. 
    
  52.             <select name="mydate_day" id="id_mydate_day">
    
  53.                 <option selected value="">---</option>
    
  54.                 <option value="1">1</option>
    
  55.                 <option value="2">2</option>
    
  56.                 <option value="3">3</option>
    
  57.                 <option value="4">4</option>
    
  58.                 <option value="5">5</option>
    
  59.                 <option value="6">6</option>
    
  60.                 <option value="7">7</option>
    
  61.                 <option value="8">8</option>
    
  62.                 <option value="9">9</option>
    
  63.                 <option value="10">10</option>
    
  64.                 <option value="11">11</option>
    
  65.                 <option value="12">12</option>
    
  66.                 <option value="13">13</option>
    
  67.                 <option value="14">14</option>
    
  68.                 <option value="15">15</option>
    
  69.                 <option value="16">16</option>
    
  70.                 <option value="17">17</option>
    
  71.                 <option value="18">18</option>
    
  72.                 <option value="19">19</option>
    
  73.                 <option value="20">20</option>
    
  74.                 <option value="21">21</option>
    
  75.                 <option value="22">22</option>
    
  76.                 <option value="23">23</option>
    
  77.                 <option value="24">24</option>
    
  78.                 <option value="25">25</option>
    
  79.                 <option value="26">26</option>
    
  80.                 <option value="27">27</option>
    
  81.                 <option value="28">28</option>
    
  82.                 <option value="29">29</option>
    
  83.                 <option value="30">30</option>
    
  84.                 <option value="31">31</option>
    
  85.             </select>
    
  86. 
    
  87.             <select name="mydate_year" id="id_mydate_year">
    
  88.                 <option selected value="">---</option>
    
  89.                 <option value="2007">2007</option>
    
  90.                 <option value="2008">2008</option>
    
  91.                 <option value="2009">2009</option>
    
  92.                 <option value="2010">2010</option>
    
  93.                 <option value="2011">2011</option>
    
  94.                 <option value="2012">2012</option>
    
  95.                 <option value="2013">2013</option>
    
  96.                 <option value="2014">2014</option>
    
  97.                 <option value="2015">2015</option>
    
  98.                 <option value="2016">2016</option>
    
  99.             </select>
    
  100.             """
    
  101.             ),
    
  102.         )
    
  103. 
    
  104.     def test_render_none(self):
    
  105.         """
    
  106.         Rendering the None or '' values should yield the same output.
    
  107.         """
    
  108.         self.assertHTMLEqual(
    
  109.             self.widget.render("mydate", None),
    
  110.             self.widget.render("mydate", ""),
    
  111.         )
    
  112. 
    
  113.     def test_render_string(self):
    
  114.         self.check_html(
    
  115.             self.widget,
    
  116.             "mydate",
    
  117.             "2010-04-15",
    
  118.             html=(
    
  119.                 """
    
  120.             <select name="mydate_month" id="id_mydate_month">
    
  121.                 <option value="">---</option>
    
  122.                 <option value="1">January</option>
    
  123.                 <option value="2">February</option>
    
  124.                 <option value="3">March</option>
    
  125.                 <option value="4" selected>April</option>
    
  126.                 <option value="5">May</option>
    
  127.                 <option value="6">June</option>
    
  128.                 <option value="7">July</option>
    
  129.                 <option value="8">August</option>
    
  130.                 <option value="9">September</option>
    
  131.                 <option value="10">October</option>
    
  132.                 <option value="11">November</option>
    
  133.                 <option value="12">December</option>
    
  134.             </select>
    
  135. 
    
  136.             <select name="mydate_day" id="id_mydate_day">
    
  137.                 <option value="">---</option>
    
  138.                 <option value="1">1</option>
    
  139.                 <option value="2">2</option>
    
  140.                 <option value="3">3</option>
    
  141.                 <option value="4">4</option>
    
  142.                 <option value="5">5</option>
    
  143.                 <option value="6">6</option>
    
  144.                 <option value="7">7</option>
    
  145.                 <option value="8">8</option>
    
  146.                 <option value="9">9</option>
    
  147.                 <option value="10">10</option>
    
  148.                 <option value="11">11</option>
    
  149.                 <option value="12">12</option>
    
  150.                 <option value="13">13</option>
    
  151.                 <option value="14">14</option>
    
  152.                 <option value="15" selected>15</option>
    
  153.                 <option value="16">16</option>
    
  154.                 <option value="17">17</option>
    
  155.                 <option value="18">18</option>
    
  156.                 <option value="19">19</option>
    
  157.                 <option value="20">20</option>
    
  158.                 <option value="21">21</option>
    
  159.                 <option value="22">22</option>
    
  160.                 <option value="23">23</option>
    
  161.                 <option value="24">24</option>
    
  162.                 <option value="25">25</option>
    
  163.                 <option value="26">26</option>
    
  164.                 <option value="27">27</option>
    
  165.                 <option value="28">28</option>
    
  166.                 <option value="29">29</option>
    
  167.                 <option value="30">30</option>
    
  168.                 <option value="31">31</option>
    
  169.             </select>
    
  170. 
    
  171.             <select name="mydate_year" id="id_mydate_year">
    
  172.                 <option value="">---</option>
    
  173.                 <option value="2007">2007</option>
    
  174.                 <option value="2008">2008</option>
    
  175.                 <option value="2009">2009</option>
    
  176.                 <option value="2010" selected>2010</option>
    
  177.                 <option value="2011">2011</option>
    
  178.                 <option value="2012">2012</option>
    
  179.                 <option value="2013">2013</option>
    
  180.                 <option value="2014">2014</option>
    
  181.                 <option value="2015">2015</option>
    
  182.                 <option value="2016">2016</option>
    
  183.             </select>
    
  184.             """
    
  185.             ),
    
  186.         )
    
  187. 
    
  188.     def test_render_datetime(self):
    
  189.         self.assertHTMLEqual(
    
  190.             self.widget.render("mydate", date(2010, 4, 15)),
    
  191.             self.widget.render("mydate", "2010-04-15"),
    
  192.         )
    
  193. 
    
  194.     def test_render_invalid_date(self):
    
  195.         """
    
  196.         Invalid dates should still render the failed date.
    
  197.         """
    
  198.         self.check_html(
    
  199.             self.widget,
    
  200.             "mydate",
    
  201.             "2010-02-31",
    
  202.             html=(
    
  203.                 """
    
  204.             <select name="mydate_month" id="id_mydate_month">
    
  205.                 <option value="">---</option>
    
  206.                 <option value="1">January</option>
    
  207.                 <option value="2" selected>February</option>
    
  208.                 <option value="3">March</option>
    
  209.                 <option value="4">April</option>
    
  210.                 <option value="5">May</option>
    
  211.                 <option value="6">June</option>
    
  212.                 <option value="7">July</option>
    
  213.                 <option value="8">August</option>
    
  214.                 <option value="9">September</option>
    
  215.                 <option value="10">October</option>
    
  216.                 <option value="11">November</option>
    
  217.                 <option value="12">December</option>
    
  218.             </select>
    
  219. 
    
  220.             <select name="mydate_day" id="id_mydate_day">
    
  221.                 <option value="">---</option>
    
  222.                 <option value="1">1</option>
    
  223.                 <option value="2">2</option>
    
  224.                 <option value="3">3</option>
    
  225.                 <option value="4">4</option>
    
  226.                 <option value="5">5</option>
    
  227.                 <option value="6">6</option>
    
  228.                 <option value="7">7</option>
    
  229.                 <option value="8">8</option>
    
  230.                 <option value="9">9</option>
    
  231.                 <option value="10">10</option>
    
  232.                 <option value="11">11</option>
    
  233.                 <option value="12">12</option>
    
  234.                 <option value="13">13</option>
    
  235.                 <option value="14">14</option>
    
  236.                 <option value="15">15</option>
    
  237.                 <option value="16">16</option>
    
  238.                 <option value="17">17</option>
    
  239.                 <option value="18">18</option>
    
  240.                 <option value="19">19</option>
    
  241.                 <option value="20">20</option>
    
  242.                 <option value="21">21</option>
    
  243.                 <option value="22">22</option>
    
  244.                 <option value="23">23</option>
    
  245.                 <option value="24">24</option>
    
  246.                 <option value="25">25</option>
    
  247.                 <option value="26">26</option>
    
  248.                 <option value="27">27</option>
    
  249.                 <option value="28">28</option>
    
  250.                 <option value="29">29</option>
    
  251.                 <option value="30">30</option>
    
  252.                 <option value="31" selected>31</option>
    
  253.             </select>
    
  254. 
    
  255.             <select name="mydate_year" id="id_mydate_year">
    
  256.                 <option value="">---</option>
    
  257.                 <option value="2007">2007</option>
    
  258.                 <option value="2008">2008</option>
    
  259.                 <option value="2009">2009</option>
    
  260.                 <option value="2010" selected>2010</option>
    
  261.                 <option value="2011">2011</option>
    
  262.                 <option value="2012">2012</option>
    
  263.                 <option value="2013">2013</option>
    
  264.                 <option value="2014">2014</option>
    
  265.                 <option value="2015">2015</option>
    
  266.                 <option value="2016">2016</option>
    
  267.             </select>
    
  268.             """
    
  269.             ),
    
  270.         )
    
  271. 
    
  272.     def test_custom_months(self):
    
  273.         widget = SelectDateWidget(months=MONTHS_AP, years=("2013",))
    
  274.         self.check_html(
    
  275.             widget,
    
  276.             "mydate",
    
  277.             "",
    
  278.             html=(
    
  279.                 """
    
  280.             <select name="mydate_month" id="id_mydate_month">
    
  281.                 <option selected value="">---</option>
    
  282.                 <option value="1">Jan.</option>
    
  283.                 <option value="2">Feb.</option>
    
  284.                 <option value="3">March</option>
    
  285.                 <option value="4">April</option>
    
  286.                 <option value="5">May</option>
    
  287.                 <option value="6">June</option>
    
  288.                 <option value="7">July</option>
    
  289.                 <option value="8">Aug.</option>
    
  290.                 <option value="9">Sept.</option>
    
  291.                 <option value="10">Oct.</option>
    
  292.                 <option value="11">Nov.</option>
    
  293.                 <option value="12">Dec.</option>
    
  294.             </select>
    
  295. 
    
  296.             <select name="mydate_day" id="id_mydate_day">
    
  297.                 <option selected value="">---</option>
    
  298.                 <option value="1">1</option>
    
  299.                 <option value="2">2</option>
    
  300.                 <option value="3">3</option>
    
  301.                 <option value="4">4</option>
    
  302.                 <option value="5">5</option>
    
  303.                 <option value="6">6</option>
    
  304.                 <option value="7">7</option>
    
  305.                 <option value="8">8</option>
    
  306.                 <option value="9">9</option>
    
  307.                 <option value="10">10</option>
    
  308.                 <option value="11">11</option>
    
  309.                 <option value="12">12</option>
    
  310.                 <option value="13">13</option>
    
  311.                 <option value="14">14</option>
    
  312.                 <option value="15">15</option>
    
  313.                 <option value="16">16</option>
    
  314.                 <option value="17">17</option>
    
  315.                 <option value="18">18</option>
    
  316.                 <option value="19">19</option>
    
  317.                 <option value="20">20</option>
    
  318.                 <option value="21">21</option>
    
  319.                 <option value="22">22</option>
    
  320.                 <option value="23">23</option>
    
  321.                 <option value="24">24</option>
    
  322.                 <option value="25">25</option>
    
  323.                 <option value="26">26</option>
    
  324.                 <option value="27">27</option>
    
  325.                 <option value="28">28</option>
    
  326.                 <option value="29">29</option>
    
  327.                 <option value="30">30</option>
    
  328.                 <option value="31">31</option>
    
  329.             </select>
    
  330. 
    
  331.             <select name="mydate_year" id="id_mydate_year">
    
  332.                 <option selected value="">---</option>
    
  333.                 <option value="2013">2013</option>
    
  334.             </select>
    
  335.             """
    
  336.             ),
    
  337.         )
    
  338. 
    
  339.     def test_selectdate_required(self):
    
  340.         class GetNotRequiredDate(Form):
    
  341.             mydate = DateField(widget=SelectDateWidget, required=False)
    
  342. 
    
  343.         class GetRequiredDate(Form):
    
  344.             mydate = DateField(widget=SelectDateWidget, required=True)
    
  345. 
    
  346.         self.assertFalse(GetNotRequiredDate().fields["mydate"].widget.is_required)
    
  347.         self.assertTrue(GetRequiredDate().fields["mydate"].widget.is_required)
    
  348. 
    
  349.     def test_selectdate_empty_label(self):
    
  350.         w = SelectDateWidget(years=("2014",), empty_label="empty_label")
    
  351. 
    
  352.         # Rendering the default state with empty_label set as string.
    
  353.         self.assertInHTML(
    
  354.             '<option selected value="">empty_label</option>',
    
  355.             w.render("mydate", ""),
    
  356.             count=3,
    
  357.         )
    
  358. 
    
  359.         w = SelectDateWidget(
    
  360.             years=("2014",), empty_label=("empty_year", "empty_month", "empty_day")
    
  361.         )
    
  362. 
    
  363.         # Rendering the default state with empty_label tuple.
    
  364.         self.assertHTMLEqual(
    
  365.             w.render("mydate", ""),
    
  366.             """
    
  367.             <select name="mydate_month" id="id_mydate_month">
    
  368.                 <option selected value="">empty_month</option>
    
  369.                 <option value="1">January</option>
    
  370.                 <option value="2">February</option>
    
  371.                 <option value="3">March</option>
    
  372.                 <option value="4">April</option>
    
  373.                 <option value="5">May</option>
    
  374.                 <option value="6">June</option>
    
  375.                 <option value="7">July</option>
    
  376.                 <option value="8">August</option>
    
  377.                 <option value="9">September</option>
    
  378.                 <option value="10">October</option>
    
  379.                 <option value="11">November</option>
    
  380.                 <option value="12">December</option>
    
  381.             </select>
    
  382. 
    
  383.             <select name="mydate_day" id="id_mydate_day">
    
  384.                 <option selected value="">empty_day</option>
    
  385.                 <option value="1">1</option>
    
  386.                 <option value="2">2</option>
    
  387.                 <option value="3">3</option>
    
  388.                 <option value="4">4</option>
    
  389.                 <option value="5">5</option>
    
  390.                 <option value="6">6</option>
    
  391.                 <option value="7">7</option>
    
  392.                 <option value="8">8</option>
    
  393.                 <option value="9">9</option>
    
  394.                 <option value="10">10</option>
    
  395.                 <option value="11">11</option>
    
  396.                 <option value="12">12</option>
    
  397.                 <option value="13">13</option>
    
  398.                 <option value="14">14</option>
    
  399.                 <option value="15">15</option>
    
  400.                 <option value="16">16</option>
    
  401.                 <option value="17">17</option>
    
  402.                 <option value="18">18</option>
    
  403.                 <option value="19">19</option>
    
  404.                 <option value="20">20</option>
    
  405.                 <option value="21">21</option>
    
  406.                 <option value="22">22</option>
    
  407.                 <option value="23">23</option>
    
  408.                 <option value="24">24</option>
    
  409.                 <option value="25">25</option>
    
  410.                 <option value="26">26</option>
    
  411.                 <option value="27">27</option>
    
  412.                 <option value="28">28</option>
    
  413.                 <option value="29">29</option>
    
  414.                 <option value="30">30</option>
    
  415.                 <option value="31">31</option>
    
  416.             </select>
    
  417. 
    
  418.             <select name="mydate_year" id="id_mydate_year">
    
  419.                 <option selected value="">empty_year</option>
    
  420.                 <option value="2014">2014</option>
    
  421.             </select>
    
  422.             """,
    
  423.         )
    
  424. 
    
  425.         with self.assertRaisesMessage(
    
  426.             ValueError, "empty_label list/tuple must have 3 elements."
    
  427.         ):
    
  428.             SelectDateWidget(years=("2014",), empty_label=("not enough", "values"))
    
  429. 
    
  430.     @translation.override("nl")
    
  431.     def test_l10n(self):
    
  432.         w = SelectDateWidget(
    
  433.             years=(
    
  434.                 "2007",
    
  435.                 "2008",
    
  436.                 "2009",
    
  437.                 "2010",
    
  438.                 "2011",
    
  439.                 "2012",
    
  440.                 "2013",
    
  441.                 "2014",
    
  442.                 "2015",
    
  443.                 "2016",
    
  444.             )
    
  445.         )
    
  446.         self.assertEqual(
    
  447.             w.value_from_datadict(
    
  448.                 {"date_year": "2010", "date_month": "8", "date_day": "13"}, {}, "date"
    
  449.             ),
    
  450.             "13-08-2010",
    
  451.         )
    
  452. 
    
  453.         self.assertHTMLEqual(
    
  454.             w.render("date", "13-08-2010"),
    
  455.             """
    
  456.             <select name="date_day" id="id_date_day">
    
  457.                 <option value="">---</option>
    
  458.                 <option value="1">1</option>
    
  459.                 <option value="2">2</option>
    
  460.                 <option value="3">3</option>
    
  461.                 <option value="4">4</option>
    
  462.                 <option value="5">5</option>
    
  463.                 <option value="6">6</option>
    
  464.                 <option value="7">7</option>
    
  465.                 <option value="8">8</option>
    
  466.                 <option value="9">9</option>
    
  467.                 <option value="10">10</option>
    
  468.                 <option value="11">11</option>
    
  469.                 <option value="12">12</option>
    
  470.                 <option value="13" selected>13</option>
    
  471.                 <option value="14">14</option>
    
  472.                 <option value="15">15</option>
    
  473.                 <option value="16">16</option>
    
  474.                 <option value="17">17</option>
    
  475.                 <option value="18">18</option>
    
  476.                 <option value="19">19</option>
    
  477.                 <option value="20">20</option>
    
  478.                 <option value="21">21</option>
    
  479.                 <option value="22">22</option>
    
  480.                 <option value="23">23</option>
    
  481.                 <option value="24">24</option>
    
  482.                 <option value="25">25</option>
    
  483.                 <option value="26">26</option>
    
  484.                 <option value="27">27</option>
    
  485.                 <option value="28">28</option>
    
  486.                 <option value="29">29</option>
    
  487.                 <option value="30">30</option>
    
  488.                 <option value="31">31</option>
    
  489.             </select>
    
  490. 
    
  491.             <select name="date_month" id="id_date_month">
    
  492.                 <option value="">---</option>
    
  493.                 <option value="1">januari</option>
    
  494.                 <option value="2">februari</option>
    
  495.                 <option value="3">maart</option>
    
  496.                 <option value="4">april</option>
    
  497.                 <option value="5">mei</option>
    
  498.                 <option value="6">juni</option>
    
  499.                 <option value="7">juli</option>
    
  500.                 <option value="8" selected>augustus</option>
    
  501.                 <option value="9">september</option>
    
  502.                 <option value="10">oktober</option>
    
  503.                 <option value="11">november</option>
    
  504.                 <option value="12">december</option>
    
  505.             </select>
    
  506. 
    
  507.             <select name="date_year" id="id_date_year">
    
  508.                 <option value="">---</option>
    
  509.                 <option value="2007">2007</option>
    
  510.                 <option value="2008">2008</option>
    
  511.                 <option value="2009">2009</option>
    
  512.                 <option value="2010" selected>2010</option>
    
  513.                 <option value="2011">2011</option>
    
  514.                 <option value="2012">2012</option>
    
  515.                 <option value="2013">2013</option>
    
  516.                 <option value="2014">2014</option>
    
  517.                 <option value="2015">2015</option>
    
  518.                 <option value="2016">2016</option>
    
  519.             </select>
    
  520.             """,
    
  521.         )
    
  522. 
    
  523.         # Even with an invalid date, the widget should reflect the entered
    
  524.         # value.
    
  525.         self.assertEqual(w.render("mydate", "2010-02-30").count("selected"), 3)
    
  526. 
    
  527.         # Years before 1900 should work.
    
  528.         w = SelectDateWidget(years=("1899",))
    
  529.         self.assertEqual(
    
  530.             w.value_from_datadict(
    
  531.                 {"date_year": "1899", "date_month": "8", "date_day": "13"}, {}, "date"
    
  532.             ),
    
  533.             "13-08-1899",
    
  534.         )
    
  535.         # And years before 1000 (demonstrating the need for
    
  536.         # sanitize_strftime_format).
    
  537.         w = SelectDateWidget(years=("0001",))
    
  538.         self.assertEqual(
    
  539.             w.value_from_datadict(
    
  540.                 {"date_year": "0001", "date_month": "8", "date_day": "13"}, {}, "date"
    
  541.             ),
    
  542.             "13-08-0001",
    
  543.         )
    
  544. 
    
  545.     # RemovedInDjango50Warning: When the deprecation ends, remove
    
  546.     # @ignore_warnings and USE_L10N=False. The test should remain because
    
  547.     # format-related settings will take precedence over locale-dictated
    
  548.     # formats.
    
  549.     @ignore_warnings(category=RemovedInDjango50Warning)
    
  550.     @override_settings(USE_L10N=False, DATE_INPUT_FORMATS=["%d.%m.%Y"])
    
  551.     def test_custom_input_format(self):
    
  552.         w = SelectDateWidget(years=("0001", "1899", "2009", "2010"))
    
  553.         for values, expected_value in (
    
  554.             (("0001", "8", "13"), "13.08.0001"),
    
  555.             (("1899", "7", "11"), "11.07.1899"),
    
  556.             (("2009", "3", "7"), "07.03.2009"),
    
  557.         ):
    
  558.             with self.subTest(values=values):
    
  559.                 data = {
    
  560.                     "field_%s" % field: value
    
  561.                     for field, value in zip(("year", "month", "day"), values)
    
  562.                 }
    
  563.                 self.assertEqual(
    
  564.                     w.value_from_datadict(data, {}, "field"), expected_value
    
  565.                 )
    
  566.                 expected_dict = {
    
  567.                     field: int(value)
    
  568.                     for field, value in zip(("year", "month", "day"), values)
    
  569.                 }
    
  570.                 self.assertEqual(w.format_value(expected_value), expected_dict)
    
  571. 
    
  572.     def test_format_value(self):
    
  573.         valid_formats = [
    
  574.             "2000-1-1",
    
  575.             "2000-10-15",
    
  576.             "2000-01-01",
    
  577.             "2000-01-0",
    
  578.             "2000-0-01",
    
  579.             "2000-0-0",
    
  580.             "0-01-01",
    
  581.             "0-01-0",
    
  582.             "0-0-01",
    
  583.             "0-0-0",
    
  584.         ]
    
  585.         for value in valid_formats:
    
  586.             year, month, day = (int(x) or "" for x in value.split("-"))
    
  587.             with self.subTest(value=value):
    
  588.                 self.assertEqual(
    
  589.                     self.widget.format_value(value),
    
  590.                     {"day": day, "month": month, "year": year},
    
  591.                 )
    
  592. 
    
  593.         invalid_formats = [
    
  594.             "2000-01-001",
    
  595.             "2000-001-01",
    
  596.             "2-01-01",
    
  597.             "20-01-01",
    
  598.             "200-01-01",
    
  599.             "20000-01-01",
    
  600.         ]
    
  601.         for value in invalid_formats:
    
  602.             with self.subTest(value=value):
    
  603.                 self.assertEqual(
    
  604.                     self.widget.format_value(value),
    
  605.                     {"day": None, "month": None, "year": None},
    
  606.                 )
    
  607. 
    
  608.     def test_value_from_datadict(self):
    
  609.         tests = [
    
  610.             (("2000", "12", "1"), "2000-12-01"),
    
  611.             (("", "12", "1"), "0-12-1"),
    
  612.             (("2000", "", "1"), "2000-0-1"),
    
  613.             (("2000", "12", ""), "2000-12-0"),
    
  614.             (("", "", "", ""), None),
    
  615.             ((None, "12", "1"), None),
    
  616.             (("2000", None, "1"), None),
    
  617.             (("2000", "12", None), None),
    
  618.         ]
    
  619.         for values, expected in tests:
    
  620.             with self.subTest(values=values):
    
  621.                 data = {}
    
  622.                 for field_name, value in zip(("year", "month", "day"), values):
    
  623.                     if value is not None:
    
  624.                         data["field_%s" % field_name] = value
    
  625.                 self.assertEqual(
    
  626.                     self.widget.value_from_datadict(data, {}, "field"), expected
    
  627.                 )
    
  628. 
    
  629.     def test_value_omitted_from_data(self):
    
  630.         self.assertIs(self.widget.value_omitted_from_data({}, {}, "field"), True)
    
  631.         self.assertIs(
    
  632.             self.widget.value_omitted_from_data({"field_month": "12"}, {}, "field"),
    
  633.             False,
    
  634.         )
    
  635.         self.assertIs(
    
  636.             self.widget.value_omitted_from_data({"field_year": "2000"}, {}, "field"),
    
  637.             False,
    
  638.         )
    
  639.         self.assertIs(
    
  640.             self.widget.value_omitted_from_data({"field_day": "1"}, {}, "field"), False
    
  641.         )
    
  642.         data = {"field_day": "1", "field_month": "12", "field_year": "2000"}
    
  643.         self.assertIs(self.widget.value_omitted_from_data(data, {}, "field"), False)
    
  644. 
    
  645.     @override_settings(USE_THOUSAND_SEPARATOR=True)
    
  646.     def test_years_rendered_without_separator(self):
    
  647.         widget = SelectDateWidget(years=(2007,))
    
  648.         self.check_html(
    
  649.             widget,
    
  650.             "mydate",
    
  651.             "",
    
  652.             html=(
    
  653.                 """
    
  654.             <select name="mydate_month" id="id_mydate_month">
    
  655.                 <option selected value="">---</option>
    
  656.                 <option value="1">January</option>
    
  657.                 <option value="2">February</option>
    
  658.                 <option value="3">March</option>
    
  659.                 <option value="4">April</option>
    
  660.                 <option value="5">May</option>
    
  661.                 <option value="6">June</option>
    
  662.                 <option value="7">July</option>
    
  663.                 <option value="8">August</option>
    
  664.                 <option value="9">September</option>
    
  665.                 <option value="10">October</option>
    
  666.                 <option value="11">November</option>
    
  667.                 <option value="12">December</option>
    
  668.             </select>
    
  669.             <select name="mydate_day" id="id_mydate_day">
    
  670.                 <option selected value="">---</option>
    
  671.                 <option value="1">1</option>
    
  672.                 <option value="2">2</option>
    
  673.                 <option value="3">3</option>
    
  674.                 <option value="4">4</option>
    
  675.                 <option value="5">5</option>
    
  676.                 <option value="6">6</option>
    
  677.                 <option value="7">7</option>
    
  678.                 <option value="8">8</option>
    
  679.                 <option value="9">9</option>
    
  680.                 <option value="10">10</option>
    
  681.                 <option value="11">11</option>
    
  682.                 <option value="12">12</option>
    
  683.                 <option value="13">13</option>
    
  684.                 <option value="14">14</option>
    
  685.                 <option value="15">15</option>
    
  686.                 <option value="16">16</option>
    
  687.                 <option value="17">17</option>
    
  688.                 <option value="18">18</option>
    
  689.                 <option value="19">19</option>
    
  690.                 <option value="20">20</option>
    
  691.                 <option value="21">21</option>
    
  692.                 <option value="22">22</option>
    
  693.                 <option value="23">23</option>
    
  694.                 <option value="24">24</option>
    
  695.                 <option value="25">25</option>
    
  696.                 <option value="26">26</option>
    
  697.                 <option value="27">27</option>
    
  698.                 <option value="28">28</option>
    
  699.                 <option value="29">29</option>
    
  700.                 <option value="30">30</option>
    
  701.                 <option value="31">31</option>
    
  702.             </select>
    
  703.             <select name="mydate_year" id="id_mydate_year">
    
  704.                 <option selected value="">---</option>
    
  705.                 <option value="2007">2007</option>
    
  706.             </select>
    
  707.             """
    
  708.             ),
    
  709.         )
    
  710. 
    
  711.     def test_fieldset(self):
    
  712.         class TestForm(Form):
    
  713.             template_name = "forms_tests/use_fieldset.html"
    
  714.             field = DateField(widget=self.widget)
    
  715. 
    
  716.         form = TestForm()
    
  717.         self.assertIs(self.widget.use_fieldset, True)
    
  718.         self.assertHTMLEqual(
    
  719.             '<div><fieldset><legend for="id_field_month">Field:</legend>'
    
  720.             '<select name="field_month" required id="id_field_month">'
    
  721.             '<option value="1">January</option><option value="2">February</option>'
    
  722.             '<option value="3">March</option><option value="4">April</option>'
    
  723.             '<option value="5">May</option><option value="6">June</option>'
    
  724.             '<option value="7">July</option><option value="8">August</option>'
    
  725.             '<option value="9">September</option><option value="10">October</option>'
    
  726.             '<option value="11">November</option><option value="12">December</option>'
    
  727.             '</select><select name="field_day" required id="id_field_day">'
    
  728.             '<option value="1">1</option><option value="2">2</option>'
    
  729.             '<option value="3">3</option><option value="4">4</option>'
    
  730.             '<option value="5">5</option><option value="6">6</option>'
    
  731.             '<option value="7">7</option><option value="8">8</option>'
    
  732.             '<option value="9">9</option><option value="10">10</option>'
    
  733.             '<option value="11">11</option><option value="12">12</option>'
    
  734.             '<option value="13">13</option><option value="14">14</option>'
    
  735.             '<option value="15">15</option><option value="16">16</option>'
    
  736.             '<option value="17">17</option><option value="18">18</option>'
    
  737.             '<option value="19">19</option><option value="20">20</option>'
    
  738.             '<option value="21">21</option><option value="22">22</option>'
    
  739.             '<option value="23">23</option><option value="24">24</option>'
    
  740.             '<option value="25">25</option><option value="26">26</option>'
    
  741.             '<option value="27">27</option><option value="28">28</option>'
    
  742.             '<option value="29">29</option><option value="30">30</option>'
    
  743.             '<option value="31">31</option></select>'
    
  744.             '<select name="field_year" required id="id_field_year">'
    
  745.             '<option value="2007">2007</option><option value="2008">2008</option>'
    
  746.             '<option value="2009">2009</option><option value="2010">2010</option>'
    
  747.             '<option value="2011">2011</option><option value="2012">2012</option>'
    
  748.             '<option value="2013">2013</option><option value="2014">2014</option>'
    
  749.             '<option value="2015">2015</option><option value="2016">2016</option>'
    
  750.             "</select></fieldset></div>",
    
  751.             form.render(),
    
  752.         )