1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @emails react-core
    
  8.  */
    
  9. 
    
  10. 'use strict';
    
  11. 
    
  12. // Fix JSDOM. setAttribute is supposed to throw on things that can't be implicitly toStringed.
    
  13. const setAttribute = Element.prototype.setAttribute;
    
  14. Element.prototype.setAttribute = function (name, value) {
    
  15.   // eslint-disable-next-line react-internal/safe-string-coercion
    
  16.   return setAttribute.call(this, name, '' + value);
    
  17. };
    
  18. 
    
  19. describe('ReactDOMSelect', () => {
    
  20.   let React;
    
  21.   let ReactDOM;
    
  22.   let ReactDOMServer;
    
  23.   let ReactTestUtils;
    
  24. 
    
  25.   const noop = function () {};
    
  26. 
    
  27.   beforeEach(() => {
    
  28.     jest.resetModules();
    
  29.     React = require('react');
    
  30.     ReactDOM = require('react-dom');
    
  31.     ReactDOMServer = require('react-dom/server');
    
  32.     ReactTestUtils = require('react-dom/test-utils');
    
  33.   });
    
  34. 
    
  35.   it('should allow setting `defaultValue`', () => {
    
  36.     const stub = (
    
  37.       <select defaultValue="giraffe">
    
  38.         <option value="monkey">A monkey!</option>
    
  39.         <option value="giraffe">A giraffe!</option>
    
  40.         <option value="gorilla">A gorilla!</option>
    
  41.       </select>
    
  42.     );
    
  43.     const options = stub.props.children;
    
  44.     const container = document.createElement('div');
    
  45.     const node = ReactDOM.render(stub, container);
    
  46. 
    
  47.     expect(node.value).toBe('giraffe');
    
  48. 
    
  49.     // Changing `defaultValue` should do nothing.
    
  50.     ReactDOM.render(
    
  51.       <select defaultValue="gorilla">{options}</select>,
    
  52.       container,
    
  53.     );
    
  54.     expect(node.value).toEqual('giraffe');
    
  55.   });
    
  56. 
    
  57.   it('should not throw with `defaultValue` and without children', () => {
    
  58.     const stub = <select defaultValue="dummy" />;
    
  59. 
    
  60.     expect(() => {
    
  61.       ReactTestUtils.renderIntoDocument(stub);
    
  62.     }).not.toThrow();
    
  63.   });
    
  64. 
    
  65.   it('should not control when using `defaultValue`', () => {
    
  66.     const el = (
    
  67.       <select defaultValue="giraffe">
    
  68.         <option value="monkey">A monkey!</option>
    
  69.         <option value="giraffe">A giraffe!</option>
    
  70.         <option value="gorilla">A gorilla!</option>
    
  71.       </select>
    
  72.     );
    
  73.     const container = document.createElement('div');
    
  74.     const node = ReactDOM.render(el, container);
    
  75. 
    
  76.     expect(node.value).toBe('giraffe');
    
  77. 
    
  78.     node.value = 'monkey';
    
  79.     ReactDOM.render(el, container);
    
  80.     // Uncontrolled selects shouldn't change the value after first mounting
    
  81.     expect(node.value).toEqual('monkey');
    
  82.   });
    
  83. 
    
  84.   it('should allow setting `defaultValue` with multiple', () => {
    
  85.     const stub = (
    
  86.       <select multiple={true} defaultValue={['giraffe', 'gorilla']}>
    
  87.         <option value="monkey">A monkey!</option>
    
  88.         <option value="giraffe">A giraffe!</option>
    
  89.         <option value="gorilla">A gorilla!</option>
    
  90.       </select>
    
  91.     );
    
  92.     const options = stub.props.children;
    
  93.     const container = document.createElement('div');
    
  94.     const node = ReactDOM.render(stub, container);
    
  95. 
    
  96.     expect(node.options[0].selected).toBe(false); // monkey
    
  97.     expect(node.options[1].selected).toBe(true); // giraffe
    
  98.     expect(node.options[2].selected).toBe(true); // gorilla
    
  99. 
    
  100.     // Changing `defaultValue` should do nothing.
    
  101.     ReactDOM.render(
    
  102.       <select multiple={true} defaultValue={['monkey']}>
    
  103.         {options}
    
  104.       </select>,
    
  105.       container,
    
  106.     );
    
  107. 
    
  108.     expect(node.options[0].selected).toBe(false); // monkey
    
  109.     expect(node.options[1].selected).toBe(true); // giraffe
    
  110.     expect(node.options[2].selected).toBe(true); // gorilla
    
  111.   });
    
  112. 
    
  113.   it('should allow setting `value`', () => {
    
  114.     const stub = (
    
  115.       <select value="giraffe" onChange={noop}>
    
  116.         <option value="monkey">A monkey!</option>
    
  117.         <option value="giraffe">A giraffe!</option>
    
  118.         <option value="gorilla">A gorilla!</option>
    
  119.       </select>
    
  120.     );
    
  121.     const options = stub.props.children;
    
  122.     const container = document.createElement('div');
    
  123.     const node = ReactDOM.render(stub, container);
    
  124. 
    
  125.     expect(node.value).toBe('giraffe');
    
  126. 
    
  127.     // Changing the `value` prop should change the selected option.
    
  128.     ReactDOM.render(
    
  129.       <select value="gorilla" onChange={noop}>
    
  130.         {options}
    
  131.       </select>,
    
  132.       container,
    
  133.     );
    
  134.     expect(node.value).toEqual('gorilla');
    
  135.   });
    
  136. 
    
  137.   it('should default to the first non-disabled option', () => {
    
  138.     const stub = (
    
  139.       <select defaultValue="">
    
  140.         <option disabled={true}>Disabled</option>
    
  141.         <option disabled={true}>Still Disabled</option>
    
  142.         <option>0</option>
    
  143.         <option disabled={true}>Also Disabled</option>
    
  144.       </select>
    
  145.     );
    
  146.     const container = document.createElement('div');
    
  147.     const node = ReactDOM.render(stub, container);
    
  148.     expect(node.options[0].selected).toBe(false);
    
  149.     expect(node.options[2].selected).toBe(true);
    
  150.   });
    
  151. 
    
  152.   it('should allow setting `value` to __proto__', () => {
    
  153.     const stub = (
    
  154.       <select value="__proto__" onChange={noop}>
    
  155.         <option value="monkey">A monkey!</option>
    
  156.         <option value="__proto__">A giraffe!</option>
    
  157.         <option value="gorilla">A gorilla!</option>
    
  158.       </select>
    
  159.     );
    
  160.     const options = stub.props.children;
    
  161.     const container = document.createElement('div');
    
  162.     const node = ReactDOM.render(stub, container);
    
  163. 
    
  164.     expect(node.value).toBe('__proto__');
    
  165. 
    
  166.     // Changing the `value` prop should change the selected option.
    
  167.     ReactDOM.render(
    
  168.       <select value="gorilla" onChange={noop}>
    
  169.         {options}
    
  170.       </select>,
    
  171.       container,
    
  172.     );
    
  173.     expect(node.value).toEqual('gorilla');
    
  174.   });
    
  175. 
    
  176.   it('should not throw with `value` and without children', () => {
    
  177.     const stub = <select value="dummy" onChange={noop} />;
    
  178. 
    
  179.     expect(() => {
    
  180.       ReactTestUtils.renderIntoDocument(stub);
    
  181.     }).not.toThrow();
    
  182.   });
    
  183. 
    
  184.   it('should allow setting `value` with multiple', () => {
    
  185.     const stub = (
    
  186.       <select multiple={true} value={['giraffe', 'gorilla']} onChange={noop}>
    
  187.         <option value="monkey">A monkey!</option>
    
  188.         <option value="giraffe">A giraffe!</option>
    
  189.         <option value="gorilla">A gorilla!</option>
    
  190.       </select>
    
  191.     );
    
  192.     const options = stub.props.children;
    
  193.     const container = document.createElement('div');
    
  194.     const node = ReactDOM.render(stub, container);
    
  195. 
    
  196.     expect(node.options[0].selected).toBe(false); // monkey
    
  197.     expect(node.options[1].selected).toBe(true); // giraffe
    
  198.     expect(node.options[2].selected).toBe(true); // gorilla
    
  199. 
    
  200.     // Changing the `value` prop should change the selected options.
    
  201.     ReactDOM.render(
    
  202.       <select multiple={true} value={['monkey']} onChange={noop}>
    
  203.         {options}
    
  204.       </select>,
    
  205.       container,
    
  206.     );
    
  207. 
    
  208.     expect(node.options[0].selected).toBe(true); // monkey
    
  209.     expect(node.options[1].selected).toBe(false); // giraffe
    
  210.     expect(node.options[2].selected).toBe(false); // gorilla
    
  211.   });
    
  212. 
    
  213.   it('should allow setting `value` to __proto__ with multiple', () => {
    
  214.     const stub = (
    
  215.       <select multiple={true} value={['__proto__', 'gorilla']} onChange={noop}>
    
  216.         <option value="monkey">A monkey!</option>
    
  217.         <option value="__proto__">A __proto__!</option>
    
  218.         <option value="gorilla">A gorilla!</option>
    
  219.       </select>
    
  220.     );
    
  221.     const options = stub.props.children;
    
  222.     const container = document.createElement('div');
    
  223.     const node = ReactDOM.render(stub, container);
    
  224. 
    
  225.     expect(node.options[0].selected).toBe(false); // monkey
    
  226.     expect(node.options[1].selected).toBe(true); // __proto__
    
  227.     expect(node.options[2].selected).toBe(true); // gorilla
    
  228. 
    
  229.     // Changing the `value` prop should change the selected options.
    
  230.     ReactDOM.render(
    
  231.       <select multiple={true} value={['monkey']} onChange={noop}>
    
  232.         {options}
    
  233.       </select>,
    
  234.       container,
    
  235.     );
    
  236. 
    
  237.     expect(node.options[0].selected).toBe(true); // monkey
    
  238.     expect(node.options[1].selected).toBe(false); // __proto__
    
  239.     expect(node.options[2].selected).toBe(false); // gorilla
    
  240.   });
    
  241. 
    
  242.   it('should not select other options automatically', () => {
    
  243.     const stub = (
    
  244.       <select multiple={true} value={['12']} onChange={noop}>
    
  245.         <option value="1">one</option>
    
  246.         <option value="2">two</option>
    
  247.         <option value="12">twelve</option>
    
  248.       </select>
    
  249.     );
    
  250.     const node = ReactTestUtils.renderIntoDocument(stub);
    
  251. 
    
  252.     expect(node.options[0].selected).toBe(false); // one
    
  253.     expect(node.options[1].selected).toBe(false); // two
    
  254.     expect(node.options[2].selected).toBe(true); // twelve
    
  255.   });
    
  256. 
    
  257.   it('should reset child options selected when they are changed and `value` is set', () => {
    
  258.     const stub = <select multiple={true} value={['a', 'b']} onChange={noop} />;
    
  259.     const container = document.createElement('div');
    
  260.     const node = ReactDOM.render(stub, container);
    
  261. 
    
  262.     ReactDOM.render(
    
  263.       <select multiple={true} value={['a', 'b']} onChange={noop}>
    
  264.         <option value="a">a</option>
    
  265.         <option value="b">b</option>
    
  266.         <option value="c">c</option>
    
  267.       </select>,
    
  268.       container,
    
  269.     );
    
  270. 
    
  271.     expect(node.options[0].selected).toBe(true); // a
    
  272.     expect(node.options[1].selected).toBe(true); // b
    
  273.     expect(node.options[2].selected).toBe(false); // c
    
  274.   });
    
  275. 
    
  276.   it('should allow setting `value` with `objectToString`', () => {
    
  277.     const objectToString = {
    
  278.       animal: 'giraffe',
    
  279.       toString: function () {
    
  280.         return this.animal;
    
  281.       },
    
  282.     };
    
  283. 
    
  284.     const el = (
    
  285.       <select multiple={true} value={[objectToString]} onChange={noop}>
    
  286.         <option value="monkey">A monkey!</option>
    
  287.         <option value="giraffe">A giraffe!</option>
    
  288.         <option value="gorilla">A gorilla!</option>
    
  289.       </select>
    
  290.     );
    
  291.     const container = document.createElement('div');
    
  292.     const node = ReactDOM.render(el, container);
    
  293. 
    
  294.     expect(node.options[0].selected).toBe(false); // monkey
    
  295.     expect(node.options[1].selected).toBe(true); // giraffe
    
  296.     expect(node.options[2].selected).toBe(false); // gorilla
    
  297. 
    
  298.     // Changing the `value` prop should change the selected options.
    
  299.     objectToString.animal = 'monkey';
    
  300. 
    
  301.     const el2 = (
    
  302.       <select multiple={true} value={[objectToString]}>
    
  303.         <option value="monkey">A monkey!</option>
    
  304.         <option value="giraffe">A giraffe!</option>
    
  305.         <option value="gorilla">A gorilla!</option>
    
  306.       </select>
    
  307.     );
    
  308.     ReactDOM.render(el2, container);
    
  309. 
    
  310.     expect(node.options[0].selected).toBe(true); // monkey
    
  311.     expect(node.options[1].selected).toBe(false); // giraffe
    
  312.     expect(node.options[2].selected).toBe(false); // gorilla
    
  313.   });
    
  314. 
    
  315.   it('should allow switching to multiple', () => {
    
  316.     const stub = (
    
  317.       <select defaultValue="giraffe">
    
  318.         <option value="monkey">A monkey!</option>
    
  319.         <option value="giraffe">A giraffe!</option>
    
  320.         <option value="gorilla">A gorilla!</option>
    
  321.       </select>
    
  322.     );
    
  323.     const options = stub.props.children;
    
  324.     const container = document.createElement('div');
    
  325.     const node = ReactDOM.render(stub, container);
    
  326. 
    
  327.     expect(node.options[0].selected).toBe(false); // monkey
    
  328.     expect(node.options[1].selected).toBe(true); // giraffe
    
  329.     expect(node.options[2].selected).toBe(false); // gorilla
    
  330. 
    
  331.     // When making it multiple, giraffe and gorilla should be selected
    
  332.     ReactDOM.render(
    
  333.       <select multiple={true} defaultValue={['giraffe', 'gorilla']}>
    
  334.         {options}
    
  335.       </select>,
    
  336.       container,
    
  337.     );
    
  338. 
    
  339.     expect(node.options[0].selected).toBe(false); // monkey
    
  340.     expect(node.options[1].selected).toBe(true); // giraffe
    
  341.     expect(node.options[2].selected).toBe(true); // gorilla
    
  342.   });
    
  343. 
    
  344.   it('should allow switching from multiple', () => {
    
  345.     const stub = (
    
  346.       <select multiple={true} defaultValue={['giraffe', 'gorilla']}>
    
  347.         <option value="monkey">A monkey!</option>
    
  348.         <option value="giraffe">A giraffe!</option>
    
  349.         <option value="gorilla">A gorilla!</option>
    
  350.       </select>
    
  351.     );
    
  352.     const options = stub.props.children;
    
  353.     const container = document.createElement('div');
    
  354.     const node = ReactDOM.render(stub, container);
    
  355. 
    
  356.     expect(node.options[0].selected).toBe(false); // monkey
    
  357.     expect(node.options[1].selected).toBe(true); // giraffe
    
  358.     expect(node.options[2].selected).toBe(true); // gorilla
    
  359. 
    
  360.     // When removing multiple, defaultValue is applied again, being omitted
    
  361.     // means that "monkey" will be selected
    
  362.     ReactDOM.render(
    
  363.       <select defaultValue="gorilla">{options}</select>,
    
  364.       container,
    
  365.     );
    
  366. 
    
  367.     expect(node.options[0].selected).toBe(false); // monkey
    
  368.     expect(node.options[1].selected).toBe(false); // giraffe
    
  369.     expect(node.options[2].selected).toBe(true); // gorilla
    
  370.   });
    
  371. 
    
  372.   it('does not select an item when size is initially set to greater than 1', () => {
    
  373.     const stub = (
    
  374.       <select size="2">
    
  375.         <option value="monkey">A monkey!</option>
    
  376.         <option value="giraffe">A giraffe!</option>
    
  377.         <option value="gorilla">A gorilla!</option>
    
  378.       </select>
    
  379.     );
    
  380.     const container = document.createElement('div');
    
  381.     const select = ReactDOM.render(stub, container);
    
  382. 
    
  383.     expect(select.options[0].selected).toBe(false);
    
  384.     expect(select.options[1].selected).toBe(false);
    
  385.     expect(select.options[2].selected).toBe(false);
    
  386. 
    
  387.     expect(select.value).toBe('');
    
  388.     expect(select.selectedIndex).toBe(-1);
    
  389.   });
    
  390. 
    
  391.   it('should remember value when switching to uncontrolled', () => {
    
  392.     const stub = (
    
  393.       <select value={'giraffe'} onChange={noop}>
    
  394.         <option value="monkey">A monkey!</option>
    
  395.         <option value="giraffe">A giraffe!</option>
    
  396.         <option value="gorilla">A gorilla!</option>
    
  397.       </select>
    
  398.     );
    
  399.     const options = stub.props.children;
    
  400.     const container = document.createElement('div');
    
  401.     const node = ReactDOM.render(stub, container);
    
  402. 
    
  403.     expect(node.options[0].selected).toBe(false); // monkey
    
  404.     expect(node.options[1].selected).toBe(true); // giraffe
    
  405.     expect(node.options[2].selected).toBe(false); // gorilla
    
  406. 
    
  407.     ReactDOM.render(<select>{options}</select>, container);
    
  408. 
    
  409.     expect(node.options[0].selected).toBe(false); // monkey
    
  410.     expect(node.options[1].selected).toBe(true); // giraffe
    
  411.     expect(node.options[2].selected).toBe(false); // gorilla
    
  412.   });
    
  413. 
    
  414.   it('should remember updated value when switching to uncontrolled', () => {
    
  415.     const stub = (
    
  416.       <select value={'giraffe'} onChange={noop}>
    
  417.         <option value="monkey">A monkey!</option>
    
  418.         <option value="giraffe">A giraffe!</option>
    
  419.         <option value="gorilla">A gorilla!</option>
    
  420.       </select>
    
  421.     );
    
  422.     const options = stub.props.children;
    
  423.     const container = document.createElement('div');
    
  424.     const node = ReactDOM.render(stub, container);
    
  425. 
    
  426.     ReactDOM.render(
    
  427.       <select value="gorilla" onChange={noop}>
    
  428.         {options}
    
  429.       </select>,
    
  430.       container,
    
  431.     );
    
  432. 
    
  433.     expect(node.options[0].selected).toBe(false); // monkey
    
  434.     expect(node.options[1].selected).toBe(false); // giraffe
    
  435.     expect(node.options[2].selected).toBe(true); // gorilla
    
  436. 
    
  437.     ReactDOM.render(<select>{options}</select>, container);
    
  438. 
    
  439.     expect(node.options[0].selected).toBe(false); // monkey
    
  440.     expect(node.options[1].selected).toBe(false); // giraffe
    
  441.     expect(node.options[2].selected).toBe(true); // gorilla
    
  442.   });
    
  443. 
    
  444.   it('should support server-side rendering', () => {
    
  445.     const stub = (
    
  446.       <select value="giraffe" onChange={noop}>
    
  447.         <option value="monkey">A monkey!</option>
    
  448.         <option value="giraffe">A giraffe!</option>
    
  449.         <option value="gorilla">A gorilla!</option>
    
  450.       </select>
    
  451.     );
    
  452.     const container = document.createElement('div');
    
  453.     container.innerHTML = ReactDOMServer.renderToString(stub);
    
  454.     const options = container.firstChild.options;
    
  455.     expect(options[0].value).toBe('monkey');
    
  456.     expect(options[0].selected).toBe(false);
    
  457.     expect(options[1].value).toBe('giraffe');
    
  458.     expect(options[1].selected).toBe(true);
    
  459.     expect(options[2].value).toBe('gorilla');
    
  460.     expect(options[2].selected).toBe(false);
    
  461.   });
    
  462. 
    
  463.   it('should support server-side rendering with defaultValue', () => {
    
  464.     const stub = (
    
  465.       <select defaultValue="giraffe">
    
  466.         <option value="monkey">A monkey!</option>
    
  467.         <option value="giraffe">A giraffe!</option>
    
  468.         <option value="gorilla">A gorilla!</option>
    
  469.       </select>
    
  470.     );
    
  471.     const container = document.createElement('div');
    
  472.     container.innerHTML = ReactDOMServer.renderToString(stub);
    
  473.     const options = container.firstChild.options;
    
  474.     expect(options[0].value).toBe('monkey');
    
  475.     expect(options[0].selected).toBe(false);
    
  476.     expect(options[1].value).toBe('giraffe');
    
  477.     expect(options[1].selected).toBe(true);
    
  478.     expect(options[2].value).toBe('gorilla');
    
  479.     expect(options[2].selected).toBe(false);
    
  480.   });
    
  481. 
    
  482.   it('should support server-side rendering with dangerouslySetInnerHTML', () => {
    
  483.     const stub = (
    
  484.       <select defaultValue="giraffe">
    
  485.         <option
    
  486.           value="monkey"
    
  487.           dangerouslySetInnerHTML={{
    
  488.             __html: 'A monkey!',
    
  489.           }}>
    
  490.           {undefined}
    
  491.         </option>
    
  492.         <option
    
  493.           value="giraffe"
    
  494.           dangerouslySetInnerHTML={{
    
  495.             __html: 'A giraffe!',
    
  496.           }}>
    
  497.           {null}
    
  498.         </option>
    
  499.         <option
    
  500.           value="gorilla"
    
  501.           dangerouslySetInnerHTML={{
    
  502.             __html: 'A gorilla!',
    
  503.           }}
    
  504.         />
    
  505.       </select>
    
  506.     );
    
  507.     const container = document.createElement('div');
    
  508.     container.innerHTML = ReactDOMServer.renderToString(stub);
    
  509.     const options = container.firstChild.options;
    
  510.     expect(options[0].value).toBe('monkey');
    
  511.     expect(options[0].selected).toBe(false);
    
  512.     expect(options[1].value).toBe('giraffe');
    
  513.     expect(options[1].selected).toBe(true);
    
  514.     expect(options[2].value).toBe('gorilla');
    
  515.     expect(options[2].selected).toBe(false);
    
  516.   });
    
  517. 
    
  518.   it('should support server-side rendering with multiple', () => {
    
  519.     const stub = (
    
  520.       <select multiple={true} value={['giraffe', 'gorilla']} onChange={noop}>
    
  521.         <option value="monkey">A monkey!</option>
    
  522.         <option value="giraffe">A giraffe!</option>
    
  523.         <option value="gorilla">A gorilla!</option>
    
  524.       </select>
    
  525.     );
    
  526.     const container = document.createElement('div');
    
  527.     container.innerHTML = ReactDOMServer.renderToString(stub);
    
  528.     const options = container.firstChild.options;
    
  529.     expect(options[0].value).toBe('monkey');
    
  530.     expect(options[0].selected).toBe(false);
    
  531.     expect(options[1].value).toBe('giraffe');
    
  532.     expect(options[1].selected).toBe(true);
    
  533.     expect(options[2].value).toBe('gorilla');
    
  534.     expect(options[2].selected).toBe(true);
    
  535.   });
    
  536. 
    
  537.   it('should not control defaultValue if re-adding options', () => {
    
  538.     const container = document.createElement('div');
    
  539. 
    
  540.     const node = ReactDOM.render(
    
  541.       <select multiple={true} defaultValue={['giraffe']}>
    
  542.         <option key="monkey" value="monkey">
    
  543.           A monkey!
    
  544.         </option>
    
  545.         <option key="giraffe" value="giraffe">
    
  546.           A giraffe!
    
  547.         </option>
    
  548.         <option key="gorilla" value="gorilla">
    
  549.           A gorilla!
    
  550.         </option>
    
  551.       </select>,
    
  552.       container,
    
  553.     );
    
  554. 
    
  555.     expect(node.options[0].selected).toBe(false); // monkey
    
  556.     expect(node.options[1].selected).toBe(true); // giraffe
    
  557.     expect(node.options[2].selected).toBe(false); // gorilla
    
  558. 
    
  559.     ReactDOM.render(
    
  560.       <select multiple={true} defaultValue={['giraffe']}>
    
  561.         <option key="monkey" value="monkey">
    
  562.           A monkey!
    
  563.         </option>
    
  564.         <option key="gorilla" value="gorilla">
    
  565.           A gorilla!
    
  566.         </option>
    
  567.       </select>,
    
  568.       container,
    
  569.     );
    
  570. 
    
  571.     expect(node.options[0].selected).toBe(false); // monkey
    
  572.     expect(node.options[1].selected).toBe(false); // gorilla
    
  573. 
    
  574.     ReactDOM.render(
    
  575.       <select multiple={true} defaultValue={['giraffe']}>
    
  576.         <option key="monkey" value="monkey">
    
  577.           A monkey!
    
  578.         </option>
    
  579.         <option key="giraffe" value="giraffe">
    
  580.           A giraffe!
    
  581.         </option>
    
  582.         <option key="gorilla" value="gorilla">
    
  583.           A gorilla!
    
  584.         </option>
    
  585.       </select>,
    
  586.       container,
    
  587.     );
    
  588. 
    
  589.     expect(node.options[0].selected).toBe(false); // monkey
    
  590.     expect(node.options[1].selected).toBe(false); // giraffe
    
  591.     expect(node.options[2].selected).toBe(false); // gorilla
    
  592.   });
    
  593. 
    
  594.   it('should support options with dynamic children', () => {
    
  595.     const container = document.createElement('div');
    
  596. 
    
  597.     let node;
    
  598. 
    
  599.     function App({value}) {
    
  600.       return (
    
  601.         <select value={value} ref={n => (node = n)} onChange={noop}>
    
  602.           <option key="monkey" value="monkey">
    
  603.             A monkey {value === 'monkey' ? 'is chosen' : null}!
    
  604.           </option>
    
  605.           <option key="giraffe" value="giraffe">
    
  606.             A giraffe {value === 'giraffe' && 'is chosen'}!
    
  607.           </option>
    
  608.           <option key="gorilla" value="gorilla">
    
  609.             A gorilla {value === 'gorilla' && 'is chosen'}!
    
  610.           </option>
    
  611.         </select>
    
  612.       );
    
  613.     }
    
  614. 
    
  615.     ReactDOM.render(<App value="monkey" />, container);
    
  616.     expect(node.options[0].selected).toBe(true); // monkey
    
  617.     expect(node.options[1].selected).toBe(false); // giraffe
    
  618.     expect(node.options[2].selected).toBe(false); // gorilla
    
  619. 
    
  620.     ReactDOM.render(<App value="giraffe" />, container);
    
  621.     expect(node.options[0].selected).toBe(false); // monkey
    
  622.     expect(node.options[1].selected).toBe(true); // giraffe
    
  623.     expect(node.options[2].selected).toBe(false); // gorilla
    
  624.   });
    
  625. 
    
  626.   it('should warn if value is null', () => {
    
  627.     expect(() =>
    
  628.       ReactTestUtils.renderIntoDocument(
    
  629.         <select value={null}>
    
  630.           <option value="test" />
    
  631.         </select>,
    
  632.       ),
    
  633.     ).toErrorDev(
    
  634.       '`value` prop on `select` should not be null. ' +
    
  635.         'Consider using an empty string to clear the component or `undefined` ' +
    
  636.         'for uncontrolled components.',
    
  637.     );
    
  638. 
    
  639.     ReactTestUtils.renderIntoDocument(
    
  640.       <select value={null}>
    
  641.         <option value="test" />
    
  642.       </select>,
    
  643.     );
    
  644.   });
    
  645. 
    
  646.   it('should warn if selected is set on <option>', () => {
    
  647.     function App() {
    
  648.       return (
    
  649.         <select>
    
  650.           <option selected={true} />
    
  651.           <option selected={true} />
    
  652.         </select>
    
  653.       );
    
  654.     }
    
  655. 
    
  656.     expect(() => ReactTestUtils.renderIntoDocument(<App />)).toErrorDev(
    
  657.       'Use the `defaultValue` or `value` props on <select> instead of ' +
    
  658.         'setting `selected` on <option>.',
    
  659.     );
    
  660. 
    
  661.     ReactTestUtils.renderIntoDocument(<App />);
    
  662.   });
    
  663. 
    
  664.   it('should warn if value is null and multiple is true', () => {
    
  665.     expect(() =>
    
  666.       ReactTestUtils.renderIntoDocument(
    
  667.         <select value={null} multiple={true}>
    
  668.           <option value="test" />
    
  669.         </select>,
    
  670.       ),
    
  671.     ).toErrorDev(
    
  672.       '`value` prop on `select` should not be null. ' +
    
  673.         'Consider using an empty array when `multiple` is ' +
    
  674.         'set to `true` to clear the component or `undefined` ' +
    
  675.         'for uncontrolled components.',
    
  676.     );
    
  677. 
    
  678.     ReactTestUtils.renderIntoDocument(
    
  679.       <select value={null} multiple={true}>
    
  680.         <option value="test" />
    
  681.       </select>,
    
  682.     );
    
  683.   });
    
  684. 
    
  685.   it('should refresh state on change', () => {
    
  686.     const stub = (
    
  687.       <select value="giraffe" onChange={noop}>
    
  688.         <option value="monkey">A monkey!</option>
    
  689.         <option value="giraffe">A giraffe!</option>
    
  690.         <option value="gorilla">A gorilla!</option>
    
  691.       </select>
    
  692.     );
    
  693.     const container = document.createElement('div');
    
  694.     document.body.appendChild(container);
    
  695. 
    
  696.     try {
    
  697.       const node = ReactDOM.render(stub, container);
    
  698. 
    
  699.       node.dispatchEvent(
    
  700.         new Event('change', {bubbles: true, cancelable: false}),
    
  701.       );
    
  702. 
    
  703.       expect(node.value).toBe('giraffe');
    
  704.     } finally {
    
  705.       document.body.removeChild(container);
    
  706.     }
    
  707.   });
    
  708. 
    
  709.   it('should warn if value and defaultValue props are specified', () => {
    
  710.     expect(() =>
    
  711.       ReactTestUtils.renderIntoDocument(
    
  712.         <select value="giraffe" defaultValue="giraffe" readOnly={true}>
    
  713.           <option value="monkey">A monkey!</option>
    
  714.           <option value="giraffe">A giraffe!</option>
    
  715.           <option value="gorilla">A gorilla!</option>
    
  716.         </select>,
    
  717.       ),
    
  718.     ).toErrorDev(
    
  719.       'Select elements must be either controlled or uncontrolled ' +
    
  720.         '(specify either the value prop, or the defaultValue prop, but not ' +
    
  721.         'both). Decide between using a controlled or uncontrolled select ' +
    
  722.         'element and remove one of these props. More info: ' +
    
  723.         'https://reactjs.org/link/controlled-components',
    
  724.     );
    
  725. 
    
  726.     ReactTestUtils.renderIntoDocument(
    
  727.       <select value="giraffe" defaultValue="giraffe" readOnly={true}>
    
  728.         <option value="monkey">A monkey!</option>
    
  729.         <option value="giraffe">A giraffe!</option>
    
  730.         <option value="gorilla">A gorilla!</option>
    
  731.       </select>,
    
  732.     );
    
  733.   });
    
  734. 
    
  735.   it('should not warn about missing onChange in uncontrolled textareas', () => {
    
  736.     const container = document.createElement('div');
    
  737.     ReactDOM.render(<select />, container);
    
  738.     ReactDOM.unmountComponentAtNode(container);
    
  739.     ReactDOM.render(<select value={undefined} />, container);
    
  740.   });
    
  741. 
    
  742.   it('should be able to safely remove select onChange', () => {
    
  743.     function changeView() {
    
  744.       ReactDOM.unmountComponentAtNode(container);
    
  745.     }
    
  746. 
    
  747.     const container = document.createElement('div');
    
  748.     const stub = (
    
  749.       <select value="giraffe" onChange={changeView}>
    
  750.         <option value="monkey">A monkey!</option>
    
  751.         <option value="giraffe">A giraffe!</option>
    
  752.         <option value="gorilla">A gorilla!</option>
    
  753.       </select>
    
  754.     );
    
  755.     const node = ReactDOM.render(stub, container);
    
  756. 
    
  757.     expect(() => ReactTestUtils.Simulate.change(node)).not.toThrow();
    
  758.   });
    
  759. 
    
  760.   it('should select grandchild options nested inside an optgroup', () => {
    
  761.     const stub = (
    
  762.       <select value="b" onChange={noop}>
    
  763.         <optgroup label="group">
    
  764.           <option value="a">a</option>
    
  765.           <option value="b">b</option>
    
  766.           <option value="c">c</option>
    
  767.         </optgroup>
    
  768.       </select>
    
  769.     );
    
  770.     const container = document.createElement('div');
    
  771.     const node = ReactDOM.render(stub, container);
    
  772. 
    
  773.     expect(node.options[0].selected).toBe(false); // a
    
  774.     expect(node.options[1].selected).toBe(true); // b
    
  775.     expect(node.options[2].selected).toBe(false); // c
    
  776.   });
    
  777. 
    
  778.   it('should allow controlling `value` in a nested render', () => {
    
  779.     let selectNode;
    
  780. 
    
  781.     class Parent extends React.Component {
    
  782.       state = {
    
  783.         value: 'giraffe',
    
  784.       };
    
  785. 
    
  786.       componentDidMount() {
    
  787.         this._renderNested();
    
  788.       }
    
  789. 
    
  790.       componentDidUpdate() {
    
  791.         this._renderNested();
    
  792.       }
    
  793. 
    
  794.       _handleChange(event) {
    
  795.         this.setState({value: event.target.value});
    
  796.       }
    
  797. 
    
  798.       _renderNested() {
    
  799.         ReactDOM.render(
    
  800.           <select
    
  801.             onChange={this._handleChange.bind(this)}
    
  802.             ref={n => (selectNode = n)}
    
  803.             value={this.state.value}>
    
  804.             <option value="monkey">A monkey!</option>
    
  805.             <option value="giraffe">A giraffe!</option>
    
  806.             <option value="gorilla">A gorilla!</option>
    
  807.           </select>,
    
  808.           this._nestingContainer,
    
  809.         );
    
  810.       }
    
  811. 
    
  812.       render() {
    
  813.         return <div ref={n => (this._nestingContainer = n)} />;
    
  814.       }
    
  815.     }
    
  816. 
    
  817.     const container = document.createElement('div');
    
  818. 
    
  819.     document.body.appendChild(container);
    
  820. 
    
  821.     ReactDOM.render(<Parent />, container);
    
  822. 
    
  823.     expect(selectNode.value).toBe('giraffe');
    
  824. 
    
  825.     selectNode.value = 'gorilla';
    
  826. 
    
  827.     let nativeEvent = document.createEvent('Event');
    
  828.     nativeEvent.initEvent('input', true, true);
    
  829.     selectNode.dispatchEvent(nativeEvent);
    
  830. 
    
  831.     expect(selectNode.value).toEqual('gorilla');
    
  832. 
    
  833.     nativeEvent = document.createEvent('Event');
    
  834.     nativeEvent.initEvent('change', true, true);
    
  835.     selectNode.dispatchEvent(nativeEvent);
    
  836. 
    
  837.     expect(selectNode.value).toEqual('gorilla');
    
  838. 
    
  839.     document.body.removeChild(container);
    
  840.   });
    
  841. 
    
  842.   it('should not select first option by default when multiple is set and no defaultValue is set', () => {
    
  843.     const stub = (
    
  844.       <select multiple={true} onChange={noop}>
    
  845.         <option value="a">a</option>
    
  846.         <option value="b">b</option>
    
  847.         <option value="c">c</option>
    
  848.       </select>
    
  849.     );
    
  850.     const container = document.createElement('div');
    
  851.     const node = ReactDOM.render(stub, container);
    
  852. 
    
  853.     expect(node.options[0].selected).toBe(false); // a
    
  854.     expect(node.options[1].selected).toBe(false); // b
    
  855.     expect(node.options[2].selected).toBe(false); // c
    
  856.   });
    
  857. 
    
  858.   describe('When given a Symbol value', () => {
    
  859.     it('treats initial Symbol value as missing', () => {
    
  860.       let node;
    
  861. 
    
  862.       expect(() => {
    
  863.         node = ReactTestUtils.renderIntoDocument(
    
  864.           <select onChange={noop} value={Symbol('foobar')}>
    
  865.             <option value={Symbol('foobar')}>A Symbol!</option>
    
  866.             <option value="monkey">A monkey!</option>
    
  867.             <option value="giraffe">A giraffe!</option>
    
  868.           </select>,
    
  869.         );
    
  870.       }).toErrorDev('Invalid value for prop `value`');
    
  871. 
    
  872.       expect(node.value).toBe('A Symbol!');
    
  873.     });
    
  874. 
    
  875.     it('treats updated Symbol value as missing', () => {
    
  876.       let node;
    
  877. 
    
  878.       expect(() => {
    
  879.         node = ReactTestUtils.renderIntoDocument(
    
  880.           <select onChange={noop} value="monkey">
    
  881.             <option value={Symbol('foobar')}>A Symbol!</option>
    
  882.             <option value="monkey">A monkey!</option>
    
  883.             <option value="giraffe">A giraffe!</option>
    
  884.           </select>,
    
  885.         );
    
  886.       }).toErrorDev('Invalid value for prop `value`');
    
  887. 
    
  888.       expect(node.value).toBe('monkey');
    
  889. 
    
  890.       node = ReactTestUtils.renderIntoDocument(
    
  891.         <select onChange={noop} value={Symbol('foobar')}>
    
  892.           <option value={Symbol('foobar')}>A Symbol!</option>
    
  893.           <option value="monkey">A monkey!</option>
    
  894.           <option value="giraffe">A giraffe!</option>
    
  895.         </select>,
    
  896.       );
    
  897. 
    
  898.       expect(node.value).toBe('A Symbol!');
    
  899.     });
    
  900. 
    
  901.     it('treats initial Symbol defaultValue as an empty string', () => {
    
  902.       let node;
    
  903. 
    
  904.       expect(() => {
    
  905.         node = ReactTestUtils.renderIntoDocument(
    
  906.           <select defaultValue={Symbol('foobar')}>
    
  907.             <option value={Symbol('foobar')}>A Symbol!</option>
    
  908.             <option value="monkey">A monkey!</option>
    
  909.             <option value="giraffe">A giraffe!</option>
    
  910.           </select>,
    
  911.         );
    
  912.       }).toErrorDev('Invalid value for prop `value`');
    
  913. 
    
  914.       expect(node.value).toBe('A Symbol!');
    
  915.     });
    
  916. 
    
  917.     it('treats updated Symbol defaultValue as an empty string', () => {
    
  918.       let node;
    
  919. 
    
  920.       expect(() => {
    
  921.         node = ReactTestUtils.renderIntoDocument(
    
  922.           <select defaultValue="monkey">
    
  923.             <option value={Symbol('foobar')}>A Symbol!</option>
    
  924.             <option value="monkey">A monkey!</option>
    
  925.             <option value="giraffe">A giraffe!</option>
    
  926.           </select>,
    
  927.         );
    
  928.       }).toErrorDev('Invalid value for prop `value`');
    
  929. 
    
  930.       expect(node.value).toBe('monkey');
    
  931. 
    
  932.       node = ReactTestUtils.renderIntoDocument(
    
  933.         <select defaultValue={Symbol('foobar')}>
    
  934.           <option value={Symbol('foobar')}>A Symbol!</option>
    
  935.           <option value="monkey">A monkey!</option>
    
  936.           <option value="giraffe">A giraffe!</option>
    
  937.         </select>,
    
  938.       );
    
  939. 
    
  940.       expect(node.value).toBe('A Symbol!');
    
  941.     });
    
  942.   });
    
  943. 
    
  944.   describe('When given a function value', () => {
    
  945.     it('treats initial function value as missing', () => {
    
  946.       let node;
    
  947. 
    
  948.       expect(() => {
    
  949.         node = ReactTestUtils.renderIntoDocument(
    
  950.           <select onChange={noop} value={() => {}}>
    
  951.             <option value={() => {}}>A function!</option>
    
  952.             <option value="monkey">A monkey!</option>
    
  953.             <option value="giraffe">A giraffe!</option>
    
  954.           </select>,
    
  955.         );
    
  956.       }).toErrorDev('Invalid value for prop `value`');
    
  957. 
    
  958.       expect(node.value).toBe('A function!');
    
  959.     });
    
  960. 
    
  961.     it('treats initial function defaultValue as an empty string', () => {
    
  962.       let node;
    
  963. 
    
  964.       expect(() => {
    
  965.         node = ReactTestUtils.renderIntoDocument(
    
  966.           <select defaultValue={() => {}}>
    
  967.             <option value={() => {}}>A function!</option>
    
  968.             <option value="monkey">A monkey!</option>
    
  969.             <option value="giraffe">A giraffe!</option>
    
  970.           </select>,
    
  971.         );
    
  972.       }).toErrorDev('Invalid value for prop `value`');
    
  973. 
    
  974.       expect(node.value).toBe('A function!');
    
  975.     });
    
  976. 
    
  977.     it('treats updated function value as an empty string', () => {
    
  978.       let node;
    
  979. 
    
  980.       expect(() => {
    
  981.         node = ReactTestUtils.renderIntoDocument(
    
  982.           <select onChange={noop} value="monkey">
    
  983.             <option value={() => {}}>A function!</option>
    
  984.             <option value="monkey">A monkey!</option>
    
  985.             <option value="giraffe">A giraffe!</option>
    
  986.           </select>,
    
  987.         );
    
  988.       }).toErrorDev('Invalid value for prop `value`');
    
  989. 
    
  990.       expect(node.value).toBe('monkey');
    
  991. 
    
  992.       node = ReactTestUtils.renderIntoDocument(
    
  993.         <select onChange={noop} value={() => {}}>
    
  994.           <option value={() => {}}>A function!</option>
    
  995.           <option value="monkey">A monkey!</option>
    
  996.           <option value="giraffe">A giraffe!</option>
    
  997.         </select>,
    
  998.       );
    
  999. 
    
  1000.       expect(node.value).toBe('A function!');
    
  1001.     });
    
  1002. 
    
  1003.     it('treats updated function defaultValue as an empty string', () => {
    
  1004.       let node;
    
  1005. 
    
  1006.       expect(() => {
    
  1007.         node = ReactTestUtils.renderIntoDocument(
    
  1008.           <select defaultValue="monkey">
    
  1009.             <option value={() => {}}>A function!</option>
    
  1010.             <option value="monkey">A monkey!</option>
    
  1011.             <option value="giraffe">A giraffe!</option>
    
  1012.           </select>,
    
  1013.         );
    
  1014.       }).toErrorDev('Invalid value for prop `value`');
    
  1015. 
    
  1016.       expect(node.value).toBe('monkey');
    
  1017. 
    
  1018.       node = ReactTestUtils.renderIntoDocument(
    
  1019.         <select defaultValue={() => {}}>
    
  1020.           <option value={() => {}}>A function!</option>
    
  1021.           <option value="monkey">A monkey!</option>
    
  1022.           <option value="giraffe">A giraffe!</option>
    
  1023.         </select>,
    
  1024.       );
    
  1025. 
    
  1026.       expect(node.value).toBe('A function!');
    
  1027.     });
    
  1028.   });
    
  1029. 
    
  1030.   describe('When given a Temporal.PlainDate-like value', () => {
    
  1031.     class TemporalLike {
    
  1032.       valueOf() {
    
  1033.         // Throwing here is the behavior of ECMAScript "Temporal" date/time API.
    
  1034.         // See https://tc39.es/proposal-temporal/docs/plaindate.html#valueOf
    
  1035.         throw new TypeError('prod message');
    
  1036.       }
    
  1037.       toString() {
    
  1038.         return '2020-01-01';
    
  1039.       }
    
  1040.     }
    
  1041. 
    
  1042.     it('throws when given a Temporal.PlainDate-like value (select)', () => {
    
  1043.       const test = () => {
    
  1044.         ReactTestUtils.renderIntoDocument(
    
  1045.           <select onChange={noop} value={new TemporalLike()}>
    
  1046.             <option value="2020-01-01">like a Temporal.PlainDate</option>
    
  1047.             <option value="monkey">A monkey!</option>
    
  1048.             <option value="giraffe">A giraffe!</option>
    
  1049.           </select>,
    
  1050.         );
    
  1051.       };
    
  1052.       expect(() =>
    
  1053.         expect(test).toThrowError(new TypeError('prod message')),
    
  1054.       ).toErrorDev(
    
  1055.         'Form field values (value, checked, defaultValue, or defaultChecked props)' +
    
  1056.           ' must be strings, not TemporalLike. ' +
    
  1057.           'This value must be coerced to a string before using it here.',
    
  1058.       );
    
  1059.     });
    
  1060. 
    
  1061.     it('throws when given a Temporal.PlainDate-like value (option)', () => {
    
  1062.       const test = () => {
    
  1063.         ReactTestUtils.renderIntoDocument(
    
  1064.           <select onChange={noop} value="2020-01-01">
    
  1065.             <option value={new TemporalLike()}>
    
  1066.               like a Temporal.PlainDate
    
  1067.             </option>
    
  1068.             <option value="monkey">A monkey!</option>
    
  1069.             <option value="giraffe">A giraffe!</option>
    
  1070.           </select>,
    
  1071.         );
    
  1072.       };
    
  1073.       expect(() =>
    
  1074.         expect(test).toThrowError(new TypeError('prod message')),
    
  1075.       ).toErrorDev(
    
  1076.         'The provided `value` attribute is an unsupported type TemporalLike.' +
    
  1077.           ' This value must be coerced to a string before using it here.',
    
  1078.       );
    
  1079.     });
    
  1080. 
    
  1081.     it('throws when given a Temporal.PlainDate-like value (both)', () => {
    
  1082.       const test = () => {
    
  1083.         ReactTestUtils.renderIntoDocument(
    
  1084.           <select onChange={noop} value={new TemporalLike()}>
    
  1085.             <option value={new TemporalLike()}>
    
  1086.               like a Temporal.PlainDate
    
  1087.             </option>
    
  1088.             <option value="monkey">A monkey!</option>
    
  1089.             <option value="giraffe">A giraffe!</option>
    
  1090.           </select>,
    
  1091.         );
    
  1092.       };
    
  1093.       expect(() =>
    
  1094.         expect(test).toThrowError(new TypeError('prod message')),
    
  1095.       ).toErrorDev(
    
  1096.         'The provided `value` attribute is an unsupported type TemporalLike.' +
    
  1097.           ' This value must be coerced to a string before using it here.',
    
  1098.       );
    
  1099.     });
    
  1100. 
    
  1101.     it('throws with updated Temporal.PlainDate-like value (select)', () => {
    
  1102.       ReactTestUtils.renderIntoDocument(
    
  1103.         <select onChange={noop} value="monkey">
    
  1104.           <option value="2020-01-01">like a Temporal.PlainDate</option>
    
  1105.           <option value="monkey">A monkey!</option>
    
  1106.           <option value="giraffe">A giraffe!</option>
    
  1107.         </select>,
    
  1108.       );
    
  1109.       const test = () => {
    
  1110.         ReactTestUtils.renderIntoDocument(
    
  1111.           <select onChange={noop} value={new TemporalLike()}>
    
  1112.             <option value="2020-01-01">like a Temporal.PlainDate</option>
    
  1113.             <option value="monkey">A monkey!</option>
    
  1114.             <option value="giraffe">A giraffe!</option>
    
  1115.           </select>,
    
  1116.         );
    
  1117.       };
    
  1118.       expect(() =>
    
  1119.         expect(test).toThrowError(new TypeError('prod message')),
    
  1120.       ).toErrorDev(
    
  1121.         'Form field values (value, checked, defaultValue, or defaultChecked props)' +
    
  1122.           ' must be strings, not TemporalLike. ' +
    
  1123.           'This value must be coerced to a string before using it here.',
    
  1124.       );
    
  1125.     });
    
  1126. 
    
  1127.     it('throws with updated Temporal.PlainDate-like value (option)', () => {
    
  1128.       ReactTestUtils.renderIntoDocument(
    
  1129.         <select onChange={noop} value="2020-01-01">
    
  1130.           <option value="donkey">like a Temporal.PlainDate</option>
    
  1131.           <option value="monkey">A monkey!</option>
    
  1132.           <option value="giraffe">A giraffe!</option>
    
  1133.         </select>,
    
  1134.       );
    
  1135.       const test = () => {
    
  1136.         ReactTestUtils.renderIntoDocument(
    
  1137.           <select onChange={noop} value="2020-01-01">
    
  1138.             <option value={new TemporalLike()}>
    
  1139.               like a Temporal.PlainDate
    
  1140.             </option>
    
  1141.             <option value="monkey">A monkey!</option>
    
  1142.             <option value="giraffe">A giraffe!</option>
    
  1143.           </select>,
    
  1144.         );
    
  1145.       };
    
  1146.       expect(() =>
    
  1147.         expect(test).toThrowError(new TypeError('prod message')),
    
  1148.       ).toErrorDev(
    
  1149.         'The provided `value` attribute is an unsupported type TemporalLike.' +
    
  1150.           ' This value must be coerced to a string before using it here.',
    
  1151.       );
    
  1152.     });
    
  1153. 
    
  1154.     it('throws with updated Temporal.PlainDate-like value (both)', () => {
    
  1155.       ReactTestUtils.renderIntoDocument(
    
  1156.         <select onChange={noop} value="donkey">
    
  1157.           <option value="donkey">like a Temporal.PlainDate</option>
    
  1158.           <option value="monkey">A monkey!</option>
    
  1159.           <option value="giraffe">A giraffe!</option>
    
  1160.         </select>,
    
  1161.       );
    
  1162.       const test = () => {
    
  1163.         ReactTestUtils.renderIntoDocument(
    
  1164.           <select onChange={noop} value={new TemporalLike()}>
    
  1165.             <option value={new TemporalLike()}>
    
  1166.               like a Temporal.PlainDate
    
  1167.             </option>
    
  1168.             <option value="monkey">A monkey!</option>
    
  1169.             <option value="giraffe">A giraffe!</option>
    
  1170.           </select>,
    
  1171.         );
    
  1172.       };
    
  1173.       expect(() =>
    
  1174.         expect(test).toThrowError(new TypeError('prod message')),
    
  1175.       ).toErrorDev(
    
  1176.         'The provided `value` attribute is an unsupported type TemporalLike.' +
    
  1177.           ' This value must be coerced to a string before using it here.',
    
  1178.       );
    
  1179.     });
    
  1180. 
    
  1181.     it('throws when given a Temporal.PlainDate-like defaultValue (select)', () => {
    
  1182.       const test = () => {
    
  1183.         ReactTestUtils.renderIntoDocument(
    
  1184.           <select onChange={noop} defaultValue={new TemporalLike()}>
    
  1185.             <option value="2020-01-01">like a Temporal.PlainDate</option>
    
  1186.             <option value="monkey">A monkey!</option>
    
  1187.             <option value="giraffe">A giraffe!</option>
    
  1188.           </select>,
    
  1189.         );
    
  1190.       };
    
  1191.       expect(() =>
    
  1192.         expect(test).toThrowError(new TypeError('prod message')),
    
  1193.       ).toErrorDev(
    
  1194.         'Form field values (value, checked, defaultValue, or defaultChecked props)' +
    
  1195.           ' must be strings, not TemporalLike. ' +
    
  1196.           'This value must be coerced to a string before using it here.',
    
  1197.       );
    
  1198.     });
    
  1199. 
    
  1200.     it('throws when given a Temporal.PlainDate-like defaultValue (option)', () => {
    
  1201.       const test = () => {
    
  1202.         ReactTestUtils.renderIntoDocument(
    
  1203.           <select onChange={noop} defaultValue="2020-01-01">
    
  1204.             <option value={new TemporalLike()}>
    
  1205.               like a Temporal.PlainDate
    
  1206.             </option>
    
  1207.             <option value="monkey">A monkey!</option>
    
  1208.             <option value="giraffe">A giraffe!</option>
    
  1209.           </select>,
    
  1210.         );
    
  1211.       };
    
  1212.       expect(() =>
    
  1213.         expect(test).toThrowError(new TypeError('prod message')),
    
  1214.       ).toErrorDev(
    
  1215.         'The provided `value` attribute is an unsupported type TemporalLike.' +
    
  1216.           ' This value must be coerced to a string before using it here.',
    
  1217.       );
    
  1218.     });
    
  1219. 
    
  1220.     it('throws when given a Temporal.PlainDate-like value (both)', () => {
    
  1221.       const test = () => {
    
  1222.         ReactTestUtils.renderIntoDocument(
    
  1223.           <select onChange={noop} defaultValue={new TemporalLike()}>
    
  1224.             <option value={new TemporalLike()}>
    
  1225.               like a Temporal.PlainDate
    
  1226.             </option>
    
  1227.             <option value="monkey">A monkey!</option>
    
  1228.             <option value="giraffe">A giraffe!</option>
    
  1229.           </select>,
    
  1230.         );
    
  1231.       };
    
  1232.       expect(() =>
    
  1233.         expect(test).toThrowError(new TypeError('prod message')),
    
  1234.       ).toErrorDev(
    
  1235.         'The provided `value` attribute is an unsupported type TemporalLike.' +
    
  1236.           ' This value must be coerced to a string before using it here.',
    
  1237.       );
    
  1238.     });
    
  1239. 
    
  1240.     it('throws with updated Temporal.PlainDate-like defaultValue (select)', () => {
    
  1241.       ReactTestUtils.renderIntoDocument(
    
  1242.         <select onChange={noop} defaultValue="monkey">
    
  1243.           <option value="2020-01-01">like a Temporal.PlainDate</option>
    
  1244.           <option value="monkey">A monkey!</option>
    
  1245.           <option value="giraffe">A giraffe!</option>
    
  1246.         </select>,
    
  1247.       );
    
  1248.       const test = () => {
    
  1249.         ReactTestUtils.renderIntoDocument(
    
  1250.           <select onChange={noop} defaultValue={new TemporalLike()}>
    
  1251.             <option value="2020-01-01">like a Temporal.PlainDate</option>
    
  1252.             <option value="monkey">A monkey!</option>
    
  1253.             <option value="giraffe">A giraffe!</option>
    
  1254.           </select>,
    
  1255.         );
    
  1256.       };
    
  1257.       expect(() =>
    
  1258.         expect(test).toThrowError(new TypeError('prod message')),
    
  1259.       ).toErrorDev(
    
  1260.         'Form field values (value, checked, defaultValue, or defaultChecked props)' +
    
  1261.           ' must be strings, not TemporalLike. ' +
    
  1262.           'This value must be coerced to a string before using it here.',
    
  1263.       );
    
  1264.     });
    
  1265. 
    
  1266.     it('throws with updated Temporal.PlainDate-like defaultValue (both)', () => {
    
  1267.       ReactTestUtils.renderIntoDocument(
    
  1268.         <select onChange={noop} defaultValue="monkey">
    
  1269.           <option value="donkey">like a Temporal.PlainDate</option>
    
  1270.           <option value="monkey">A monkey!</option>
    
  1271.           <option value="giraffe">A giraffe!</option>
    
  1272.         </select>,
    
  1273.       );
    
  1274.       const test = () => {
    
  1275.         ReactTestUtils.renderIntoDocument(
    
  1276.           <select onChange={noop} value={new TemporalLike()}>
    
  1277.             <option value={new TemporalLike()}>
    
  1278.               like a Temporal.PlainDate
    
  1279.             </option>
    
  1280.             <option value="monkey">A monkey!</option>
    
  1281.             <option value="giraffe">A giraffe!</option>
    
  1282.           </select>,
    
  1283.         );
    
  1284.       };
    
  1285.       expect(() =>
    
  1286.         expect(test).toThrowError(new TypeError('prod message')),
    
  1287.       ).toErrorDev(
    
  1288.         'The provided `value` attribute is an unsupported type TemporalLike.' +
    
  1289.           ' This value must be coerced to a string before using it here.',
    
  1290.       );
    
  1291.     });
    
  1292.   });
    
  1293. });