tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_request.js (21816B)


      1 function testDefaultCtor() {
      2  var req = new Request("");
      3  is(req.method, "GET", "Default Request method is GET");
      4  ok(
      5    req.headers instanceof Headers,
      6    "Request should have non-null Headers object"
      7  );
      8  is(
      9    req.url,
     10    self.location.href,
     11    "URL should be resolved with entry settings object's API base URL"
     12  );
     13  is(req.destination, "", "Default destination is the empty string.");
     14  is(
     15    req.referrer,
     16    "about:client",
     17    "Default referrer is `client` which serializes to about:client."
     18  );
     19  is(req.mode, "cors", "Request mode for string input is cors");
     20  is(
     21    req.credentials,
     22    "same-origin",
     23    "Default Request credentials is same-origin"
     24  );
     25  is(req.cache, "default", "Default Request cache is default");
     26 
     27  var req = new Request(req);
     28  is(req.method, "GET", "Default Request method is GET");
     29  ok(
     30    req.headers instanceof Headers,
     31    "Request should have non-null Headers object"
     32  );
     33  is(
     34    req.url,
     35    self.location.href,
     36    "URL should be resolved with entry settings object's API base URL"
     37  );
     38  is(req.destination, "", "Default destination is the empty string.");
     39  is(
     40    req.referrer,
     41    "about:client",
     42    "Default referrer is `client` which serializes to about:client."
     43  );
     44  is(req.mode, "cors", "Request mode string input is cors");
     45  is(
     46    req.credentials,
     47    "same-origin",
     48    "Default Request credentials is same-origin"
     49  );
     50  is(req.cache, "default", "Default Request cache is default");
     51 }
     52 
     53 function testClone() {
     54  var orig = new Request("./cloned_request.txt", {
     55    method: "POST",
     56    headers: { "Sample-Header": "5" },
     57    body: "Sample body",
     58    mode: "same-origin",
     59    credentials: "same-origin",
     60    cache: "no-store",
     61  });
     62  var clone = orig.clone();
     63  ok(clone.method === "POST", "Request method is POST");
     64  ok(
     65    clone.headers instanceof Headers,
     66    "Request should have non-null Headers object"
     67  );
     68 
     69  is(
     70    clone.headers.get("sample-header"),
     71    "5",
     72    "Request sample-header should be 5."
     73  );
     74  orig.headers.set("sample-header", 6);
     75  is(
     76    clone.headers.get("sample-header"),
     77    "5",
     78    "Cloned Request sample-header should continue to be 5."
     79  );
     80 
     81  ok(
     82    clone.url === new URL("./cloned_request.txt", self.location.href).href,
     83    "URL should be resolved with entry settings object's API base URL"
     84  );
     85  ok(
     86    clone.referrer === "about:client",
     87    "Default referrer is `client` which serializes to about:client."
     88  );
     89  ok(clone.mode === "same-origin", "Request mode is same-origin");
     90  ok(clone.credentials === "same-origin", "Default credentials is same-origin");
     91  ok(clone.cache === "no-store", "Default cache is no-store");
     92 
     93  ok(!orig.bodyUsed, "Original body is not consumed.");
     94  ok(!clone.bodyUsed, "Clone body is not consumed.");
     95 
     96  var origBody = null;
     97  var clone2 = null;
     98  return orig
     99    .text()
    100    .then(function (body) {
    101      origBody = body;
    102      is(origBody, "Sample body", "Original body string matches");
    103      ok(orig.bodyUsed, "Original body is consumed.");
    104      ok(!clone.bodyUsed, "Clone body is not consumed.");
    105 
    106      try {
    107        orig.clone();
    108        ok(false, "Cannot clone Request whose body is already consumed");
    109      } catch (e) {
    110        is(
    111          e.name,
    112          "TypeError",
    113          "clone() of consumed body should throw TypeError"
    114        );
    115      }
    116 
    117      clone2 = clone.clone();
    118      return clone.text();
    119    })
    120    .then(function (body) {
    121      is(body, origBody, "Clone body matches original body.");
    122      ok(clone.bodyUsed, "Clone body is consumed.");
    123 
    124      try {
    125        clone.clone();
    126        ok(false, "Cannot clone Request whose body is already consumed");
    127      } catch (e) {
    128        is(
    129          e.name,
    130          "TypeError",
    131          "clone() of consumed body should throw TypeError"
    132        );
    133      }
    134 
    135      return clone2.text();
    136    })
    137    .then(function (body) {
    138      is(body, origBody, "Clone body matches original body.");
    139      ok(clone2.bodyUsed, "Clone body is consumed.");
    140 
    141      try {
    142        clone2.clone();
    143        ok(false, "Cannot clone Request whose body is already consumed");
    144      } catch (e) {
    145        is(
    146          e.name,
    147          "TypeError",
    148          "clone() of consumed body should throw TypeError"
    149        );
    150      }
    151    });
    152 }
    153 
    154 function testUsedRequest() {
    155  // Passing a used request should fail.
    156  var req = new Request("", { method: "post", body: "This is foo" });
    157  var p1 = req.text().then(function (v) {
    158    try {
    159      var req2 = new Request(req);
    160      ok(false, "Used Request cannot be passed to new Request");
    161    } catch (e) {
    162      ok(true, "Used Request cannot be passed to new Request");
    163    }
    164  });
    165 
    166  // Passing a request should set the request as used.
    167  var reqA = new Request("", { method: "post", body: "This is foo" });
    168  var reqB = new Request(reqA);
    169  is(
    170    reqA.bodyUsed,
    171    true,
    172    "Passing a Request to another Request should set the former as used"
    173  );
    174  return p1;
    175 }
    176 
    177 function testSimpleUrlParse() {
    178  // Just checks that the URL parser is actually being used.
    179  var req = new Request("/file.html");
    180  is(
    181    req.url,
    182    new URL("/file.html", self.location.href).href,
    183    "URL parser should be used to resolve Request URL"
    184  );
    185 }
    186 
    187 // Bug 1109574 - Passing a Request with null body should keep bodyUsed unset.
    188 function testBug1109574() {
    189  var r1 = new Request("");
    190  is(r1.bodyUsed, false, "Initial value of bodyUsed should be false");
    191  var r2 = new Request(r1);
    192  is(r1.bodyUsed, false, "Request with null body should not have bodyUsed set");
    193  // This should succeed.
    194  var r3 = new Request(r1);
    195 }
    196 
    197 // Bug 1184550 - Request constructor should always throw if used flag is set,
    198 // even if body is null
    199 function testBug1184550() {
    200  var req = new Request("", { method: "post", body: "Test" });
    201  fetch(req);
    202  ok(req.bodyUsed, "Request body should be used immediately after fetch()");
    203  return fetch(req)
    204    .then(function (resp) {
    205      ok(false, "Second fetch with same request should fail.");
    206    })
    207    .catch(function (err) {
    208      is(err.name, "TypeError", "Second fetch with same request should fail.");
    209    });
    210 }
    211 
    212 function testHeaderGuard() {
    213  var headers = {
    214    Cookie: "Custom cookie",
    215    "Non-Simple-Header": "value",
    216  };
    217  var r1 = new Request("", { headers });
    218  ok(
    219    !r1.headers.has("Cookie"),
    220    "Default Request header should have guard request and prevent setting forbidden header."
    221  );
    222  ok(
    223    r1.headers.has("Non-Simple-Header"),
    224    "Default Request header should have guard request and allow setting non-simple header."
    225  );
    226 
    227  var r2 = new Request("", { mode: "no-cors", headers });
    228  ok(
    229    !r2.headers.has("Cookie"),
    230    "no-cors Request header should have guard request-no-cors and prevent setting non-simple header."
    231  );
    232  ok(
    233    !r2.headers.has("Non-Simple-Header"),
    234    "no-cors Request header should have guard request-no-cors and prevent setting non-simple header."
    235  );
    236 }
    237 
    238 function testMode() {
    239  try {
    240    var req = new Request("http://example.com", { mode: "navigate" });
    241    ok(
    242      false,
    243      "Creating a Request with navigate RequestMode should throw a TypeError"
    244    );
    245  } catch (e) {
    246    is(
    247      e.name,
    248      "TypeError",
    249      "Creating a Request with navigate RequestMode should throw a TypeError"
    250    );
    251  }
    252 }
    253 
    254 function testMethod() {
    255  // These get normalized.
    256  var allowed = ["delete", "get", "head", "options", "post", "put"];
    257  for (var i = 0; i < allowed.length; ++i) {
    258    try {
    259      var r = new Request("", { method: allowed[i] });
    260      ok(true, "Method " + allowed[i] + " should be allowed");
    261      is(
    262        r.method,
    263        allowed[i].toUpperCase(),
    264        "Standard HTTP method " + allowed[i] + " should be normalized"
    265      );
    266    } catch (e) {
    267      ok(false, "Method " + allowed[i] + " should be allowed");
    268    }
    269  }
    270 
    271  var allowed = ["pAtCh", "foo"];
    272  for (var i = 0; i < allowed.length; ++i) {
    273    try {
    274      var r = new Request("", { method: allowed[i] });
    275      ok(true, "Method " + allowed[i] + " should be allowed");
    276      is(
    277        r.method,
    278        allowed[i],
    279        "Non-standard but valid HTTP method " +
    280          allowed[i] +
    281          " should not be normalized"
    282      );
    283    } catch (e) {
    284      ok(false, "Method " + allowed[i] + " should be allowed");
    285    }
    286  }
    287 
    288  var forbidden = ["connect", "trace", "track", "<invalid token??"];
    289  for (var i = 0; i < forbidden.length; ++i) {
    290    try {
    291      var r = new Request("", { method: forbidden[i] });
    292      ok(false, "Method " + forbidden[i] + " should be forbidden");
    293    } catch (e) {
    294      ok(true, "Method " + forbidden[i] + " should be forbidden");
    295    }
    296  }
    297 
    298  var allowedNoCors = ["get", "head", "post"];
    299  for (var i = 0; i < allowedNoCors.length; ++i) {
    300    try {
    301      var r = new Request("", { method: allowedNoCors[i], mode: "no-cors" });
    302      ok(
    303        true,
    304        "Method " + allowedNoCors[i] + " should be allowed in no-cors mode"
    305      );
    306    } catch (e) {
    307      ok(
    308        false,
    309        "Method " + allowedNoCors[i] + " should be allowed in no-cors mode"
    310      );
    311    }
    312  }
    313 
    314  var forbiddenNoCors = ["aardvark", "delete", "options", "put"];
    315  for (var i = 0; i < forbiddenNoCors.length; ++i) {
    316    try {
    317      var r = new Request("", { method: forbiddenNoCors[i], mode: "no-cors" });
    318      ok(
    319        false,
    320        "Method " + forbiddenNoCors[i] + " should be forbidden in no-cors mode"
    321      );
    322    } catch (e) {
    323      ok(
    324        true,
    325        "Method " + forbiddenNoCors[i] + " should be forbidden in no-cors mode"
    326      );
    327    }
    328  }
    329 
    330  // HEAD/GET requests cannot have a body.
    331  try {
    332    var r = new Request("", { method: "get", body: "hello" });
    333    ok(false, "HEAD/GET request cannot have a body");
    334  } catch (e) {
    335    is(e.name, "TypeError", "HEAD/GET request cannot have a body");
    336  }
    337 
    338  try {
    339    var r = new Request("", { method: "head", body: "hello" });
    340    ok(false, "HEAD/GET request cannot have a body");
    341  } catch (e) {
    342    is(e.name, "TypeError", "HEAD/GET request cannot have a body");
    343  }
    344  // Non HEAD/GET should not throw.
    345  var r = new Request("", { method: "patch", body: "hello" });
    346 }
    347 function testUrlFragment() {
    348  var req = new Request("./request#withfragment");
    349  is(
    350    req.url,
    351    new URL("./request#withfragment", self.location.href).href,
    352    "request.url should be serialized without exclude fragment flag set"
    353  );
    354 }
    355 function testUrlMalformed() {
    356  try {
    357    var req = new Request("http:// example.com");
    358    ok(
    359      false,
    360      "Creating a Request with a malformed URL should throw a TypeError"
    361    );
    362  } catch (e) {
    363    is(
    364      e.name,
    365      "TypeError",
    366      "Creating a Request with a malformed URL should throw a TypeError"
    367    );
    368  }
    369 }
    370 
    371 function testUrlCredentials() {
    372  try {
    373    var req = new Request("http://user@example.com");
    374    ok(false, "URLs with credentials should be rejected");
    375  } catch (e) {
    376    is(e.name, "TypeError", "URLs with credentials should be rejected");
    377  }
    378 
    379  try {
    380    var req = new Request("http://user:password@example.com");
    381    ok(false, "URLs with credentials should be rejected");
    382  } catch (e) {
    383    is(e.name, "TypeError", "URLs with credentials should be rejected");
    384  }
    385 }
    386 
    387 function testBodyUsed() {
    388  var req = new Request("./bodyused", { method: "post", body: "Sample body" });
    389  is(req.bodyUsed, false, "bodyUsed is initially false.");
    390  return req
    391    .text()
    392    .then(v => {
    393      is(v, "Sample body", "Body should match");
    394      is(req.bodyUsed, true, "After reading body, bodyUsed should be true.");
    395    })
    396    .then(v => {
    397      return req.blob().then(
    398        v => {
    399          ok(false, "Attempting to read body again should fail.");
    400        },
    401        e => {
    402          ok(true, "Attempting to read body again should fail.");
    403        }
    404      );
    405    });
    406 }
    407 
    408 var text = "κόσμε";
    409 function testBodyCreation() {
    410  var req1 = new Request("", { method: "post", body: text });
    411  var p1 = req1.text().then(function (v) {
    412    ok(typeof v === "string", "Should resolve to string");
    413    is(text, v, "Extracted string should match");
    414  });
    415 
    416  var req2 = new Request("", {
    417    method: "post",
    418    body: new Uint8Array([72, 101, 108, 108, 111]),
    419  });
    420  var p2 = req2.text().then(function (v) {
    421    is("Hello", v, "Extracted string should match");
    422  });
    423 
    424  var req2b = new Request("", {
    425    method: "post",
    426    body: new Uint8Array([72, 101, 108, 108, 111]).buffer,
    427  });
    428  var p2b = req2b.text().then(function (v) {
    429    is("Hello", v, "Extracted string should match");
    430  });
    431 
    432  var reqblob = new Request("", { method: "post", body: new Blob([text]) });
    433  var pblob = reqblob.text().then(function (v) {
    434    is(v, text, "Extracted string should match");
    435  });
    436 
    437  // FormData has its own function since it has blobs and files.
    438 
    439  var params = new URLSearchParams();
    440  params.append("item", "Geckos");
    441  params.append("feature", "stickyfeet");
    442  params.append("quantity", "700");
    443  var req3 = new Request("", { method: "post", body: params });
    444  var p3 = req3.text().then(function (v) {
    445    var extracted = new URLSearchParams(v);
    446    is(extracted.get("item"), "Geckos", "Param should match");
    447    is(extracted.get("feature"), "stickyfeet", "Param should match");
    448    is(extracted.get("quantity"), "700", "Param should match");
    449  });
    450 
    451  return Promise.all([p1, p2, p2b, pblob, p3]);
    452 }
    453 
    454 function testFormDataBodyCreation() {
    455  var f1 = new FormData();
    456  f1.append("key", "value");
    457  f1.append("foo", "bar");
    458 
    459  var r1 = new Request("", { method: "post", body: f1 });
    460  // Since f1 is serialized immediately, later additions should not show up.
    461  f1.append("more", "stuff");
    462  var p1 = r1.formData().then(function (fd) {
    463    ok(fd instanceof FormData, "Valid FormData extracted.");
    464    ok(fd.has("key"), "key should exist.");
    465    ok(fd.has("foo"), "foo should exist.");
    466    ok(!fd.has("more"), "more should not exist.");
    467  });
    468 
    469  f1.append("blob", new Blob([text]));
    470  var r2 = new Request("", { method: "post", body: f1 });
    471  f1.delete("key");
    472  var p2 = r2.formData().then(function (fd) {
    473    ok(fd instanceof FormData, "Valid FormData extracted.");
    474    ok(fd.has("more"), "more should exist.");
    475 
    476    var b = fd.get("blob");
    477    is(b.name, "blob", "blob entry should be a Blob.");
    478    ok(b instanceof Blob, "blob entry should be a Blob.");
    479 
    480    return readAsText(b).then(function (output) {
    481      is(output, text, "Blob contents should match.");
    482    });
    483  });
    484 
    485  return Promise.all([p1, p2]);
    486 }
    487 
    488 function testBodyExtraction() {
    489  var text = "κόσμε";
    490  var newReq = function () {
    491    return new Request("", { method: "post", body: text });
    492  };
    493  return newReq()
    494    .text()
    495    .then(function (v) {
    496      ok(typeof v === "string", "Should resolve to string");
    497      is(text, v, "Extracted string should match");
    498    })
    499    .then(function () {
    500      return newReq()
    501        .blob()
    502        .then(function (v) {
    503          ok(v instanceof Blob, "Should resolve to Blob");
    504          return readAsText(v).then(function (result) {
    505            is(result, text, "Decoded Blob should match original");
    506          });
    507        });
    508    })
    509    .then(function () {
    510      return newReq()
    511        .json()
    512        .then(
    513          function (v) {
    514            ok(false, "Invalid json should reject");
    515          },
    516          function (e) {
    517            ok(true, "Invalid json should reject");
    518          }
    519        );
    520    })
    521    .then(function () {
    522      return newReq()
    523        .arrayBuffer()
    524        .then(function (v) {
    525          ok(v instanceof ArrayBuffer, "Should resolve to ArrayBuffer");
    526          var dec = new TextDecoder();
    527          is(
    528            dec.decode(new Uint8Array(v)),
    529            text,
    530            "UTF-8 decoded ArrayBuffer should match original"
    531          );
    532        });
    533    })
    534    .then(function () {
    535      return newReq()
    536        .formData()
    537        .then(
    538          function (v) {
    539            ok(false, "invalid FormData read should fail.");
    540          },
    541          function (e) {
    542            ok(e.name == "TypeError", "invalid FormData read should fail.");
    543          }
    544        );
    545    });
    546 }
    547 
    548 function testFormDataBodyExtraction() {
    549  // URLSearchParams translates to application/x-www-form-urlencoded.
    550  var params = new URLSearchParams();
    551  params.append("item", "Geckos");
    552  params.append("feature", "stickyfeet");
    553  params.append("quantity", "700");
    554  params.append("quantity", "800");
    555 
    556  var req = new Request("", { method: "POST", body: params });
    557  var p1 = req.formData().then(function (fd) {
    558    ok(fd.has("item"), "Has entry 'item'.");
    559    ok(fd.has("feature"), "Has entry 'feature'.");
    560    var entries = fd.getAll("quantity");
    561    is(entries.length, 2, "Entries with same name are correctly handled.");
    562    is(entries[0], "700", "Entries with same name are correctly handled.");
    563    is(entries[1], "800", "Entries with same name are correctly handled.");
    564  });
    565 
    566  var f1 = new FormData();
    567  f1.append("key", "value");
    568  f1.append("foo", "bar");
    569  f1.append("blob", new Blob([text]));
    570  var r2 = new Request("", { method: "post", body: f1 });
    571  var p2 = r2.formData().then(function (fd) {
    572    ok(fd.has("key"), "Has entry 'key'.");
    573    ok(fd.has("foo"), "Has entry 'foo'.");
    574    ok(fd.has("blob"), "Has entry 'blob'.");
    575    var entries = fd.getAll("blob");
    576    is(entries.length, 1, "getAll returns all items.");
    577    is(entries[0].name, "blob", "Filename should be blob.");
    578    ok(entries[0] instanceof Blob, "getAll returns blobs.");
    579  });
    580 
    581  var ws = "\r\n\r\n\r\n\r\n";
    582  f1.set(
    583    "key",
    584    new File([ws], "file name has spaces.txt", { type: "new/lines" })
    585  );
    586  var r3 = new Request("", { method: "post", body: f1 });
    587  var p3 = r3.formData().then(function (fd) {
    588    ok(fd.has("foo"), "Has entry 'foo'.");
    589    ok(fd.has("blob"), "Has entry 'blob'.");
    590    var entries = fd.getAll("blob");
    591    is(entries.length, 1, "getAll returns all items.");
    592    is(entries[0].name, "blob", "Filename should be blob.");
    593    ok(entries[0] instanceof Blob, "getAll returns blobs.");
    594 
    595    ok(fd.has("key"), "Has entry 'key'.");
    596    var f = fd.get("key");
    597    ok(f instanceof File, "entry should be a File.");
    598    is(f.name, "file name has spaces.txt", "File name should match.");
    599    is(f.type, "new/lines", "File type should match.");
    600    is(f.size, ws.length, "File size should match.");
    601    return readAsText(f).then(function (text) {
    602      is(text, ws, "File contents should match.");
    603    });
    604  });
    605 
    606  // Override header and ensure parse fails.
    607  var boundary = "1234567891011121314151617";
    608  var body =
    609    boundary +
    610    '\r\nContent-Disposition: form-data; name="greeting"\r\n\r\n"hello"\r\n' +
    611    boundary +
    612    "-";
    613 
    614  var r4 = new Request("", {
    615    method: "post",
    616    body,
    617    headers: {
    618      "Content-Type": "multipart/form-datafoobar; boundary=" + boundary,
    619    },
    620  });
    621  var p4 = r4.formData().then(
    622    function () {
    623      ok(false, "Invalid mimetype should fail.");
    624    },
    625    function () {
    626      ok(true, "Invalid mimetype should fail.");
    627    }
    628  );
    629 
    630  var r5 = new Request("", {
    631    method: "POST",
    632    body: params,
    633    headers: {
    634      "Content-Type": "application/x-www-form-urlencodedfoobar",
    635    },
    636  });
    637  var p5 = r5.formData().then(
    638    function () {
    639      ok(false, "Invalid mimetype should fail.");
    640    },
    641    function () {
    642      ok(true, "Invalid mimetype should fail.");
    643    }
    644  );
    645  return Promise.all([p1, p2, p3, p4]);
    646 }
    647 
    648 // mode cannot be set to "CORS-with-forced-preflight" from javascript.
    649 function testModeCorsPreflightEnumValue() {
    650  try {
    651    var r = new Request(".", { mode: "cors-with-forced-preflight" });
    652    ok(
    653      false,
    654      "Creating Request with mode cors-with-forced-preflight should fail."
    655    );
    656  } catch (e) {
    657    ok(
    658      true,
    659      "Creating Request with mode cors-with-forced-preflight should fail."
    660    );
    661    // Also ensure that the error message matches error messages for truly
    662    // invalid strings.
    663    var invalidMode = "not-in-requestmode-enum";
    664    var invalidExc;
    665    try {
    666      var r = new Request(".", { mode: invalidMode });
    667    } catch (e) {
    668      invalidExc = e;
    669    }
    670    var expectedMessage = invalidExc.message.replace(
    671      invalidMode,
    672      "cors-with-forced-preflight"
    673    );
    674    is(
    675      e.message,
    676      expectedMessage,
    677      "mode cors-with-forced-preflight should throw same error as invalid RequestMode strings."
    678    );
    679  }
    680 }
    681 
    682 // HEAD/GET Requests are not allowed to have a body even when copying another
    683 // Request.
    684 function testBug1154268() {
    685  var r1 = new Request("/index.html", { method: "POST", body: "Hi there" });
    686  ["HEAD", "GET"].forEach(function (method) {
    687    try {
    688      var r2 = new Request(r1, { method });
    689      ok(
    690        false,
    691        method + " Request copied from POST Request with body should fail."
    692      );
    693    } catch (e) {
    694      is(
    695        e.name,
    696        "TypeError",
    697        method + " Request copied from POST Request with body should fail."
    698      );
    699    }
    700  });
    701 }
    702 
    703 function testRequestConsumedByFailedConstructor() {
    704  var r1 = new Request("http://example.com", {
    705    method: "POST",
    706    body: "hello world",
    707  });
    708  try {
    709    var r2 = new Request(r1, { method: "GET" });
    710    ok(false, "GET Request copied from POST Request with body should fail.");
    711  } catch (e) {
    712    ok(true, "GET Request copied from POST Request with body should fail.");
    713  }
    714  ok(
    715    !r1.bodyUsed,
    716    "Initial request should not be consumed by failed Request constructor"
    717  );
    718 }
    719 
    720 function runTest() {
    721  testDefaultCtor();
    722  testSimpleUrlParse();
    723  testUrlFragment();
    724  testUrlCredentials();
    725  testUrlMalformed();
    726  testMode();
    727  testMethod();
    728  testBug1109574();
    729  testBug1184550();
    730  testHeaderGuard();
    731  testModeCorsPreflightEnumValue();
    732  testBug1154268();
    733  testRequestConsumedByFailedConstructor();
    734 
    735  return Promise.resolve()
    736    .then(testBodyCreation)
    737    .then(testBodyUsed)
    738    .then(testBodyExtraction)
    739    .then(testFormDataBodyCreation)
    740    .then(testFormDataBodyExtraction)
    741    .then(testUsedRequest)
    742    .then(testClone());
    743  // Put more promise based tests here.
    744 }