<!DOCTYPE html>
<meta charset="UTF-8">
<title>Fragment navigations on iframe with src set to URL that doesn't load a document (HTTP 204)</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/helpers.js"></script>
<body></body>
<script>
/*
  When an iframe is created it will contain the initial empty document. If the
  src is set to a URL that doesn't load a new document (e.g. it results in a
  HTTP 204 response), it will stay on the initial empty document. After fragment
  navigations happen on it, it should still stay on the initial empty document.
  These tests verifies the behavior of navigations that happen on the initial
  empty document in that situation. They should all be converted to do a
  replacement.
*/
"use strict";
const url1 = "about:blank#1";
const url2 = "/common/blank.html?2";

promise_test(async t => {
  const startingHistoryLength = history.length;
  // Create an iframe with src set to URL that doesn't load a new document, so
  // it will stay in the initial empty document.
  const iframe = insertIframeWith204Src(t);
  assert_equals(history.length, startingHistoryLength,
    "Inserting iframe with src set to URL that doesn't load a new document must not change history.length");

  // Do a fragment navigation within the initial empty document through iframe.src.
  iframe.src = url1;
  await new Promise(resolve => t.step_timeout(resolve, 100));
  assert_equals(iframe.contentWindow.location.href, url1);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after fragment navigation on initial empty document");

  // Navigate away from the initial empty document through iframe.src.
  iframe.src = url2;
  await waitForLoad(t, iframe, url2);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after normal navigation from initial empty document");
}, "src");

promise_test(async t => {
  const startingHistoryLength = history.length;
  // Create an iframe with src set to URL that doesn't load a new document, so
  // it will stay in the initial empty document.
  const iframe = insertIframeWith204Src(t);
  assert_equals(history.length, startingHistoryLength,
    "Inserting iframe with src set to URL that doesn't load a new document must not change history.length");

  // Do a fragment navigation within the initial empty document through setting location.href.
  // This should do a replacement.
  iframe.contentWindow.location.href = url1;
  await new Promise(resolve => t.step_timeout(resolve, 100));
  assert_equals(iframe.contentWindow.location.href, url1);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after fragment navigation on initial empty document");

  // Navigate away from the initial empty document through setting location.href.
  // This should do a replacement.
  iframe.contentWindow.location.href = url2;
  await waitForLoad(t, iframe, url2);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after normal navigation from initial empty document");
}, "location.href");

promise_test(async t => {
  const startingHistoryLength = history.length;
  // Create an iframe with src set to URL that doesn't load a new document, so
  // it will stay in the initial empty document.
  const iframe = insertIframeWith204Src(t);
  await new Promise(resolve => t.step_timeout(resolve, 100));
  assert_equals(history.length, startingHistoryLength,
    "Inserting iframe with src set to URL that doesn't load a new document must not change history.length");

  // Do a fragment navigation within the initial empty document through location.assign().
  // This should do a replacement.
  iframe.contentWindow.location.assign(url1);
  assert_equals(iframe.contentWindow.location.href, url1);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after fragment navigation on initial empty document");

  // Navigate away from the initial empty document through location.assign().
  // This should do a replacement.
  iframe.contentWindow.location.assign(url2);
  await waitForLoad(t, iframe, url2);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after normal navigation from initial empty document");
}, "location.assign");

promise_test(async t => {
  const startingHistoryLength = history.length;
  // Create an iframe with src set to URL that doesn't load a new document, so
  // it will stay in the initial empty document.
  const iframe = insertIframeWith204Src(t);
  await new Promise(resolve => t.step_timeout(resolve, 100));
  assert_equals(history.length, startingHistoryLength,
    "Inserting iframe with src set to URL that doesn't load a new document must not change history.length");

  // Do a fragment navigation within the initial empty document through window.open().
  // This should do a replacement.
  iframe.contentWindow.open(url1, "_self");
  assert_equals(iframe.contentWindow.location.href, url1);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after fragment navigation on initial empty document");

  // Navigate away from the initial empty document through window.open().
  // This should do a replacement.
  iframe.contentWindow.open(url2, "_self");
  await waitForLoad(t, iframe, url2);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after normal navigation from initial empty document");
}, "window.open");

promise_test(async t => {
  const startingHistoryLength = history.length;
  // Create an iframe with src set to URL that doesn't load a new document, so it will stay in the initial empty document.
  const iframe = insertIframeWith204Src(t);
  assert_equals(history.length, startingHistoryLength,
    "Inserting iframe with src set to URL that doesn't load a new document must not change history.length");

  // Do a fragment navigation within the initial empty document through clicking an <a> element.
  // This should do a replacement.
  const a1 = iframe.contentDocument.createElement("a");
  a1.href = url1;
  iframe.contentDocument.body.appendChild(a1);
  a1.click();
  await new Promise(resolve => t.step_timeout(resolve, 100));
  assert_equals(iframe.contentWindow.location.href, url1);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after fragment navigation on initial empty document");

  // Navigate away from the initial empty document through clicking an <a> element.
  // This should do a replacement.
  const a2 = iframe.contentDocument.createElement("a");
  a2.href = url2;
  iframe.contentDocument.body.appendChild(a2);
  a2.click();
  await waitForLoad(t, iframe, url2);
  assert_equals(history.length, startingHistoryLength,
    "history.length must not change after normal navigation from initial empty document");
}, "link click");
</script>
