<!DOCTYPE html>
<title>HTMLSelectMenuElement Test: value and selectedOption</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<selectmenu id="selectMenu0"></selectmenu>

<selectmenu id="selectMenu1">
  <option>one</option>
  <option>two</option>
  <div>I'm a div with no part attr</div>
  <option id="selectMenu1-option3">three</option>
  <option>four</option>
</selectmenu>

<selectmenu id="selectMenu2">
  <div behavior="option">one</div>
  <div behavior="option">two</div>
  <div>I'm a div with no part attr</div>
  <div behavior="option">three</div>
  <div behavior="option">four</div>
</selectmenu>

<selectmenu id="selectMenu3">
  <div>I'm a div with no part attr</div>
  <option id="selectMenu3-child1">one</option>
  <option id="selectMenu3-child2">two</option>
  <option id="selectMenu3-child3">three</option>
</selectmenu>

<selectmenu id="selectMenu4">
  <div slot="button" behavior="button">
    <div behavior="selected-value" id="selectMenu4-custom-selected-value">Default custom selected-value text</div>
  </div>
  <option id="selectMenu4-option1">one</option>
  <option id="selectMenu4-option2">two</option>
</selectmenu>

<selectmenu id="selectMenu5">
  <div slot="button" behavior="button">
    <div behavior="selected-value" id="selectMenu5-custom-selected-value">Default custom selected-value text</div>
  </div>
  <div popover slot="listbox" behavior="listbox">
    <option id="selectMenu5-option1">one</option>
    <option id="selectMenu5-option2">two</option>
  </div>
</selectmenu>

<selectmenu id="selectMenu6">
  <option id="selectMenu6-option1">one</option>
  <option id="selectMenu6-option2" selected>two</option>
  <option id="selectMenu6-option3">three</option>
</selectmenu>

<selectmenu id="selectMenu7">
  <option id="selectMenu7-option1">one</option>
  <option id="selectMenu7-option2" selected value="test">two</option>
  <option>three</option>
</selectmenu>

<script>

test(() => {
  const selectMenu0 = document.getElementById("selectMenu0");
  assert_equals(selectMenu0.value, "");
  assert_equals(selectMenu0.selectedOption, null);
  selectMenu0.value = "something";
  assert_equals(selectMenu0.value, "", "If there is no matching option, selectmenu should be cleared");
  assert_equals(selectMenu0.selectedOption, null);
}, "Test that HTMLSelectMenu with no options has empty string for value and null for selectedOption");

test(() => {
  const selectMenu1 = document.getElementById("selectMenu1");
  assert_equals(selectMenu1.value, "one", "value should start with the text of the first option part");

  selectMenu1.value = "three";
  assert_equals(selectMenu1.value, "three", "value can be set to the text of an option part");
  assert_equals(selectMenu1.selectedOption, document.getElementById("selectMenu1-option3"));

  selectMenu1.value = "I'm a div with no part attr";
  assert_equals(selectMenu1.value, "", "If there is no matching option selectmenu should be cleared");
  assert_equals(selectMenu1.selectedOption, null);
}, "Test value and selectedOption with HTMLOptionElement element option parts");

test(() => {
  const selectMenu1 = document.getElementById("selectMenu1");
  selectMenu1.value = "one";
  assert_equals(selectMenu1.value, "one");

  selectMenu1.value = null;
  assert_equals(selectMenu1.value, "");
  assert_equals(selectMenu1.selectedOption, null);
}, "Test value and selectedOption when value is null");

test(() => {
  const selectMenu1 = document.getElementById("selectMenu1");
  selectMenu1.value = "one";
  assert_equals(selectMenu1.value, "one");

  selectMenu1.value = undefined;
  assert_equals(selectMenu1.value, "");
  assert_equals(selectMenu1.selectedOption, null);
}, "Test value and selectedOption when value is undefined");

test(() => {
  const selectMenu2 = document.getElementById("selectMenu2");
  assert_equals(selectMenu2.value, "", "Non-HTMLOptionElements shouldn't be treated as option parts");
  assert_equals(selectMenu2.selectedOption, null);

  selectMenu2.value = "three";
  assert_equals(selectMenu2.value, "", "value can't be set when there are no option parts'");
  assert_equals(selectMenu2.selectedOption, null);
}, "Test value with non-HTMLOptionElement elements labeled as parts");

test(() => {
  const selectMenu3 = document.getElementById("selectMenu3");
  assert_equals(selectMenu3.value, "one", "value should start with the text of the first option part");
  assert_equals(selectMenu3.selectedOption, document.getElementById("selectMenu3-child1"));

  document.getElementById("selectMenu3-child3").remove();
  assert_equals(selectMenu3.value, "one", "Removing a non-selected option should not change the value");
  assert_equals(selectMenu3.selectedOption, document.getElementById("selectMenu3-child1"));

  document.getElementById("selectMenu3-child1").remove();
  assert_equals(selectMenu3.value, "two", "When the selected option is removed, the new first option should become selected");
  assert_equals(selectMenu3.selectedOption, document.getElementById("selectMenu3-child2"));

  document.getElementById("selectMenu3-child2").remove();
  assert_equals(selectMenu3.value, "", "When all options are removed, value should be the empty string");
  assert_equals(selectMenu3.selectedOption, null);
}, "Test that value and selectedOption are updated when options are removed");

test(() => {
  const selectMenu4 = document.getElementById("selectMenu4");
  let customSelectedValuePart = document.getElementById("selectMenu4-custom-selected-value");
  assert_equals(selectMenu4.value, "one", "value should start with the text of the first option part");
  assert_equals(selectMenu4.selectedOption, document.getElementById("selectMenu4-option1"));
  assert_equals(customSelectedValuePart.innerText, "one", "Custom selected value part should be set to initial value of selectmenu");

  selectMenu4.value = "two";
  assert_equals(customSelectedValuePart.innerText, "two", "Custom selected value part should be updated when value of selectmenu changes");
  assert_equals(selectMenu4.selectedOption, document.getElementById("selectMenu4-option2"));
}, "Test that slotted-in selected-value part is updated to value of selectmenu");

test(() => {
  const selectMenu5 = document.getElementById("selectMenu5");
  let customSelectedValuePart = document.getElementById("selectMenu5-custom-selected-value");
  assert_equals(selectMenu5.value, "one", "value should start with the text of the first option part");
  assert_equals(selectMenu5.selectedOption, document.getElementById("selectMenu5-option1"));
  assert_equals(customSelectedValuePart.innerText, "one", "Custom selected value part should be set to initial value of selectmenu");

  selectMenu5.value = "two";
  assert_equals(customSelectedValuePart.innerText, "two", "Custom selected value part should be updated when value of selectmenu changes");
  assert_equals(selectMenu5.selectedOption, document.getElementById("selectMenu5-option2"));
}, "Test that option parts in a slotted-in listbox are reflected in the value property");

test(() => {
  let selectMenu = document.createElement('selectmenu');
  assert_equals(selectMenu.value, "");
  let option = document.createElement('option');
  option.innerText = "one";
  selectMenu.appendChild(option);
  assert_equals(selectMenu.value, "one");
  assert_equals(selectMenu.selectedOption, option);

  let newOption = document.createElement('option');
  newOption.innerText = 'two';
  selectMenu.appendChild(newOption);
  selectMenu.value = "two";
  assert_equals(selectMenu.value, "two");
  assert_equals(selectMenu.selectedOption, newOption);

  option.click();
  assert_equals(selectMenu.value, "one");
  assert_equals(selectMenu.selectedOption, option);
}, "Test that value and selectedOption are correctly updated");

test(() => {
  const selectMenu = document.getElementById("selectMenu6");
  let selectMenuOption1 = document.getElementById("selectMenu6-option1");

  assert_equals(selectMenu.value, "two");
  assert_equals(selectMenu.selectedOption, document.getElementById("selectMenu6-option2"));
  assert_false(selectMenuOption1.selected);
  selectMenuOption1.selected = true;
  assert_equals(selectMenu.value, "one");
  assert_equals(selectMenu.selectedOption, selectMenuOption1);

  let newOption = document.createElement("option");
  newOption.innerText = "four";
  newOption.selected = true;
  selectMenu.appendChild(newOption);
  assert_equals(selectMenu.value, "four");
  assert_equals(selectMenu.selectedOption, newOption);
  assert_false(selectMenuOption1.selected);

  selectMenu.value = "three";
  assert_equals(selectMenu.selectedOption, document.getElementById("selectMenu6-option3"));
  assert_false(newOption.selected);
}, "Test that HTMLOption.selected updates selectmenu.value and selectmenu.selectedOption");

test(() => {
  const selectMenu = document.getElementById("selectMenu7");
  let selectMenuOption1 = document.getElementById("selectMenu7-option1");

  assert_equals(selectMenu.value, "test");
  assert_equals(selectMenu.selectedOption, document.getElementById("selectMenu7-option2"));
  assert_false(selectMenuOption1.selected);
  selectMenuOption1.selected = true;
  assert_equals(selectMenu.value, "one");
  assert_equals(selectMenu.selectedOption, selectMenuOption1);

  selectMenuOption1.value = "new test";
  assert_equals(selectMenu.value, "new test");
  assert_equals(selectMenu.selectedOption, selectMenuOption1);
  selectMenuOption1.removeAttribute("value");
  assert_equals(selectMenu.value, "one");
  assert_equals(selectMenu.selectedOption, selectMenuOption1);
  selectMenuOption1.value = "";
  assert_equals(selectMenu.value, "");
  assert_equals(selectMenu.selectedOption, selectMenuOption1);
}, "Test that HTMLOption.value updates selectmenu.value");

</script>
