Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: http3 OR http2
- Manifest: devtools/client/netmonitor/src/har/test/browser.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
/**
* Tests for importing HAR data.
*/
add_task(async () => {
const { tab, monitor } = await initNetMonitor(
HAR_EXAMPLE_URL + "html_har_import-test-page.html",
{ requestCount: 1 }
);
info("Starting test... ");
const { actions, store, windowRequire } = monitor.panelWin;
const Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
const { HarImporter } = windowRequire(
"devtools/client/netmonitor/src/har/har-importer"
);
store.dispatch(Actions.batchEnable(false));
// Execute one POST request on the page and wait till its done.
const wait = waitForNetworkEvents(monitor, 3);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await content.wrappedJSObject.executeTest();
});
await wait;
// Copy HAR into the clipboard
const json1 = await copyAllAsHARWithContextMenu(monitor, { asString: true });
// Import HAR string
const importer = new HarImporter(actions);
importer.import(json1);
// Copy HAR into the clipboard again
const json2 = await copyAllAsHARWithContextMenu(monitor, { asString: true });
// Compare exported HAR data
const har1 = JSON.parse(json1);
const har2 = JSON.parse(json2);
// Explicit tests
is(har2.log.entries.length, 3, "There must be expected number of requests");
is(
har2.log.pages[0].title,
HAR_EXAMPLE_URL + "html_har_import-test-page.html",
"There must be some page title"
);
ok(
!!har2.log.entries[0].request.headers.length,
"There must be some request headers"
);
ok(
!!har2.log.entries[0].response.headers.length,
"There must be some response headers"
);
is(
har2.log.entries[1].response.cookies.length,
3,
"There must be expected number of cookies"
);
is(
har2.log.entries[1]._securityState,
"secure",
"There must be expected security state"
);
is(har2.log.entries[2].response.status, 304, "There must be expected status");
// Complex test comparing exported & imported HARs.
ok(compare(har1.log, har2.log, ["log"]), "Exported HAR must be the same");
// Clean up
return teardown(monitor);
});
/**
* Check equality of HAR files.
*/
function compare(obj1, obj2, path) {
const keys1 = Object.getOwnPropertyNames(obj1).sort();
const keys2 = Object.getOwnPropertyNames(obj2).sort();
const name = path.join("/");
is(
keys1.length,
keys2.length,
"There must be the same number of keys for: " + name
);
if (keys1.length != keys2.length) {
return false;
}
is(keys1.join(), keys2.join(), "There must be the same keys for: " + name);
if (keys1.join() != keys2.join()) {
return false;
}
// Page IDs are generated and don't have to be the same after import.
const ignore = [
"log/entries/0/pageref",
"log/entries/1/pageref",
"log/entries/2/pageref",
"log/pages/0/id",
"log/pages/1/id",
"log/pages/2/id",
];
let result = true;
for (let i = 0; i < keys1.length; i++) {
const key = keys1[i];
const prop1 = obj1[key];
const prop2 = obj2[key];
if (prop1 instanceof Array) {
if (!(prop2 instanceof Array)) {
ok(false, "Arrays are not the same " + name);
result = false;
break;
}
if (!compare(prop1, prop2, path.concat(key))) {
result = false;
break;
}
} else if (prop1 instanceof Object) {
if (!(prop2 instanceof Object)) {
ok(false, "Objects are not the same in: " + name);
result = false;
break;
}
if (!compare(prop1, prop2, path.concat(key))) {
result = false;
break;
}
} else if (prop1 !== prop2) {
const propName = name + "/" + key;
if (!ignore.includes(propName)) {
is(prop1, prop2, "Values are not the same: " + propName);
result = false;
break;
}
}
}
return result;
}