<!DOCTYPE html>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<iframe id="iframe"></iframe>
<script>
const testList = [
  { tag_name: 'div', defined: true },
  { tag_name: 'a-a', defined: false },
  { tag_name: 'font-face', defined: true },
];

// Setup iframe to test the parser.
const neither = 'rgb(255, 0, 0)';
const defined = 'rgb(255, 165, 0)';
const not_defined = 'rgb(0, 0, 255)';
iframe.srcdoc = `<style>
  * { color:${neither}; }
  :defined { color:${defined}; }
  :not(:defined) { color:${not_defined}; }
</style>`
  + testList.map(d => `<${d.tag_name}></${d.tag_name}>`).join('');
setup({ explicit_done: true });
iframe.onload = () => {
  const doc = iframe.contentDocument;
  const doc_without_browsing_context = doc.implementation.createHTMLDocument();
  for (const data of testList) {
    // Test elements inserted by parser.
    test_defined(data.defined, doc.getElementsByTagName(data.tag_name)[0], `<${data.tag_name}>`);

    // Test DOM createElement() methods.
    test_defined_for_createElement(data.defined, doc, data.tag_name);

    // Documents without browsing context should be "uncustomized"; i.e., "defined".
    test_defined_for_createElement(true, doc_without_browsing_context, data.tag_name, 'Without browsing context: ');
  }

  done();
};

function test_defined_for_createElement(defined, doc, tag_name, description = '') {
  // Test document.createElement().
  let element = doc.createElement(tag_name);
  doc.body.appendChild(element);
  test_defined(defined, element, `${description}createElement("${tag_name}")`);

  // Test document.createElementNS().
  let html_element = doc.createElementNS('http://www.w3.org/1999/xhtml', tag_name);
  doc.body.appendChild(html_element);
  test_defined(defined, html_element, `${description}createElementNS("http://www.w3.org/1999/xhtml", "${tag_name}")`);

  // If the element namespace is not HTML, it should be "uncustomized"; i.e., "defined".
  let svg_element = doc.createElementNS('http://www.w3.org/2000/svg', tag_name);
  doc.body.appendChild(svg_element);
  test_defined(true, svg_element, `${description}createElementNS("http://www.w3.org/2000/svg", "${tag_name}")`);

  // Test ":defined" changes when the custom element was defined.
  if (!defined) {
    let w = doc.defaultView;
    w.customElements.define(tag_name, class extends w.HTMLElement {
      constructor() { super(); }
    });

    test_defined(true, element, `Upgraded ${description}createElement("${tag_name}")`);
    test_defined(true, html_element, `Upgraded ${description}createElementNS("http://www.w3.org/1999/xhtml", "${tag_name}")`);
  }
}

function test_defined(expected, element, description) {
  test(() => {
    assert_equals(element.matches(':defined'), expected, 'matches(":defined")');
    assert_equals(element.matches(':not(:defined)'), !expected, 'matches(":not(:defined")');
    const view = element.ownerDocument.defaultView;
    if (!view)
      return;
    const style = view.getComputedStyle(element);
    assert_equals(style.color, expected ? defined : not_defined, 'getComputedStyle');
  }, `${description} should ${expected ? 'be' : 'not be'} :defined`);
}
</script>
