mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 970517 - Storage Inspector fron end - tests, r=jwalker
This commit is contained in:
parent
2e264a6e61
commit
d97f20d1cc
@ -4,6 +4,8 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
EXTRA_JS_MODULES.devtools.storage += [
|
||||
'panel.js',
|
||||
'ui.js'
|
||||
|
15
browser/devtools/storage/test/browser.ini
Normal file
15
browser/devtools/storage/test/browser.ini
Normal file
@ -0,0 +1,15 @@
|
||||
[DEFAULT]
|
||||
skip-if = e10s # Bug 1049888 - storage actors do not work in e10s for now
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
storage-complex-values.html
|
||||
storage-listings.html
|
||||
storage-secured-iframe.html
|
||||
storage-unsecured-iframe.html
|
||||
storage-updates.html
|
||||
head.js
|
||||
|
||||
[browser_storage_basic.js]
|
||||
[browser_storage_dynamic_updates.js]
|
||||
[browser_storage_sidebar.js]
|
||||
[browser_storage_values.js]
|
114
browser/devtools/storage/test/browser_storage_basic.js
Normal file
114
browser/devtools/storage/test/browser_storage_basic.js
Normal file
@ -0,0 +1,114 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Basic test to assert that the storage tree and table corresponding to each
|
||||
// item in the storage tree is correctly displayed
|
||||
|
||||
// Entries that should be present in the tree for this test
|
||||
// Format for each entry in the array :
|
||||
// [
|
||||
// ["path", "to", "tree", "item"], - The path to the tree item to click formed
|
||||
// by id of each item
|
||||
// ["key_value1", "key_value2", ...] - The value of the first (unique) column
|
||||
// for each row in the table corresponding
|
||||
// to the tree item selected.
|
||||
// ]
|
||||
// These entries are formed by the cookies, local storage, session storage and
|
||||
// indexedDB entries created in storage-listings.html,
|
||||
// storage-secured-iframe.html and storage-unsecured-iframe.html
|
||||
const storeItems = [
|
||||
[["cookies", "test1.example.org"],
|
||||
["c1", "cs2", "c3", "uc1"]],
|
||||
[["cookies", "sectest1.example.org"],
|
||||
["uc1", "cs2", "sc1"]],
|
||||
[["localStorage", "http://test1.example.org"],
|
||||
["ls1", "ls2"]],
|
||||
[["localStorage", "http://sectest1.example.org"],
|
||||
["iframe-u-ls1"]],
|
||||
[["localStorage", "https://sectest1.example.org"],
|
||||
["iframe-s-ls1"]],
|
||||
[["sessionStorage", "http://test1.example.org"],
|
||||
["ss1"]],
|
||||
[["sessionStorage", "http://sectest1.example.org"],
|
||||
["iframe-u-ss1", "iframe-u-ss2"]],
|
||||
[["sessionStorage", "https://sectest1.example.org"],
|
||||
["iframe-s-ss1"]],
|
||||
[["indexedDB", "http://test1.example.org"],
|
||||
["idb1", "idb2"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1"],
|
||||
["obj1", "obj2"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb2"],
|
||||
["obj3"]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"],
|
||||
[1, 2, 3]],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj2"],
|
||||
[1]],
|
||||
[["indexedDB", "http://test1.example.org", "idb2", "obj3"],
|
||||
[]],
|
||||
[["indexedDB", "http://sectest1.example.org"],
|
||||
[]],
|
||||
[["indexedDB", "https://sectest1.example.org"],
|
||||
["idb-s1", "idb-s2"]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s1"],
|
||||
["obj-s1"]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s2"],
|
||||
["obj-s2"]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s1", "obj-s1"],
|
||||
[6, 7]],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s2", "obj-s2"],
|
||||
[16]],
|
||||
];
|
||||
|
||||
/**
|
||||
* Test that the desired number of tree items are present
|
||||
*/
|
||||
function testTree() {
|
||||
let doc = gPanelWindow.document;
|
||||
for (let item of storeItems) {
|
||||
ok(doc.querySelector("[data-id='" + JSON.stringify(item[0]) + "']"),
|
||||
"Tree item " + item[0] + " should be present in the storage tree");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that correct table entries are shown for each of the tree item
|
||||
*/
|
||||
let testTables = Task.async(function*() {
|
||||
let doc = gPanelWindow.document;
|
||||
// Expand all nodes so that the synthesized click event actually works
|
||||
gUI.tree.expandAll();
|
||||
|
||||
// First tree item is already selected so no clicking and waiting for update
|
||||
for (let id of storeItems[0][1]) {
|
||||
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||
"Table item " + id + " should be present");
|
||||
}
|
||||
|
||||
// Click rest of the tree items and wait for the table to be updated
|
||||
for (let item of storeItems.slice(1)) {
|
||||
selectTreeItem(item[0]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
// Check whether correct number of items are present in the table
|
||||
is(doc.querySelectorAll(
|
||||
".table-widget-wrapper:first-of-type .table-widget-cell"
|
||||
).length, item[1].length, "Number of items in table is correct");
|
||||
|
||||
// Check if all the desired items are present in the table
|
||||
for (let id of item[1]) {
|
||||
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
|
||||
"Table item " + id + " should be present");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
testTree();
|
||||
yield testTables();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html").then(startTest);
|
||||
}
|
211
browser/devtools/storage/test/browser_storage_dynamic_updates.js
Normal file
211
browser/devtools/storage/test/browser_storage_dynamic_updates.js
Normal file
@ -0,0 +1,211 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
let testUpdates = Task.async(function*() {
|
||||
|
||||
let $ = id => gPanelWindow.document.querySelector(id);
|
||||
let $$ = sel => gPanelWindow.document.querySelectorAll(sel);
|
||||
|
||||
gUI.tree.expandAll();
|
||||
|
||||
ok(gUI.sidebar.hidden, "Sidebar is initially hidden");
|
||||
selectTableItem("c1");
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
// test that value is something initially
|
||||
let initialValue = [[
|
||||
{name: "c1", value: "1.2.3.4.5.6.7"},
|
||||
{name: "c1.path", value: "/browser"}
|
||||
],[
|
||||
{name: "c1", value: "Array"},
|
||||
{name: "c1.0", value: "1"},
|
||||
{name: "c1.6", value: "7"}
|
||||
]];
|
||||
|
||||
// test that value is something initially
|
||||
let finalValue = [[
|
||||
{name: "c1", value: '{"foo": 4,"bar":6}'},
|
||||
{name: "c1.path", value: "/browser"}
|
||||
],[
|
||||
{name: "c1", value: "Object"},
|
||||
{name: "c1.foo", value: "4"},
|
||||
{name: "c1.bar", value: "6"}
|
||||
]];
|
||||
// Check that sidebar shows correct initial value
|
||||
yield findVariableViewProperties(initialValue[0], false);
|
||||
yield findVariableViewProperties(initialValue[1], true);
|
||||
// Check if table shows correct initial value
|
||||
ok($("#value [data-id='c1'].table-widget-cell"), "cell is present");
|
||||
is($("#value [data-id='c1'].table-widget-cell").value, "1.2.3.4.5.6.7",
|
||||
"correct initial value in table");
|
||||
gWindow.addCookie("c1", '{"foo": 4,"bar":6}', "/browser");
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
yield findVariableViewProperties(finalValue[0], false);
|
||||
yield findVariableViewProperties(finalValue[1], true);
|
||||
ok($("#value [data-id='c1'].table-widget-cell"), "cell is present after update");
|
||||
is($("#value [data-id='c1'].table-widget-cell").value, '{"foo": 4,"bar":6}',
|
||||
"correct final value in table");
|
||||
|
||||
// Add a new entry
|
||||
is($$("#value .table-widget-cell").length, 2,
|
||||
"Correct number of rows before update 0");
|
||||
|
||||
gWindow.addCookie("c3", "booyeah");
|
||||
|
||||
// Wait once for update and another time for value fetching
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 3,
|
||||
"Correct number of rows after update 1");
|
||||
|
||||
// Add another
|
||||
gWindow.addCookie("c4", "booyeah");
|
||||
|
||||
// Wait once for update and another time for value fetching
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 4,
|
||||
"Correct number of rows after update 2");
|
||||
|
||||
// Removing cookies
|
||||
gWindow.removeCookie("c1", "/browser");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 3,
|
||||
"Correct number of rows after delete update 3");
|
||||
|
||||
ok(!$("#c1"), "Correct row got deleted");
|
||||
|
||||
ok(!gUI.sidebar.hidden, "Sidebar still visible for next row");
|
||||
|
||||
// Check if next element's value is visible in sidebar
|
||||
yield findVariableViewProperties([{name: "c2", value: "foobar"}]);
|
||||
|
||||
// Keep deleting till no rows
|
||||
|
||||
gWindow.removeCookie("c3");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 2,
|
||||
"Correct number of rows after delete update 4");
|
||||
|
||||
// Check if next element's value is visible in sidebar
|
||||
yield findVariableViewProperties([{name: "c2", value: "foobar"}]);
|
||||
|
||||
gWindow.removeCookie("c2", "/browser");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
yield findVariableViewProperties([{name: "c4", value: "booyeah"}]);
|
||||
|
||||
is($$("#value .table-widget-cell").length, 1,
|
||||
"Correct number of rows after delete update 5");
|
||||
|
||||
gWindow.removeCookie("c4");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 0,
|
||||
"Correct number of rows after delete update 6");
|
||||
ok(gUI.sidebar.hidden, "Sidebar is hidden when no rows");
|
||||
|
||||
// Testing in local storage
|
||||
selectTreeItem(["localStorage", "http://test1.example.org"]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 7,
|
||||
"Correct number of rows after delete update 7");
|
||||
|
||||
ok($(".table-widget-cell[data-id='ls4']"), "ls4 exists before deleting");
|
||||
|
||||
gWindow.localStorage.removeItem("ls4");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 6,
|
||||
"Correct number of rows after delete update 8");
|
||||
ok(!$(".table-widget-cell[data-id='ls4']"),
|
||||
"ls4 does not exists after deleting");
|
||||
|
||||
gWindow.localStorage.setItem("ls4", "again");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 7,
|
||||
"Correct number of rows after delete update 9");
|
||||
ok($(".table-widget-cell[data-id='ls4']"),
|
||||
"ls4 came back after adding it again");
|
||||
|
||||
// Updating a row
|
||||
gWindow.localStorage.setItem("ls2", "ls2-changed");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($("#value [data-id='ls2']").value, "ls2-changed",
|
||||
"Value got updated for local storage");
|
||||
|
||||
// Testing in session storage
|
||||
selectTreeItem(["sessionStorage", "http://test1.example.org"]);
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 3,
|
||||
"Correct number of rows for session storage");
|
||||
|
||||
gWindow.sessionStorage.setItem("ss4", "new-item");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 4,
|
||||
"Correct number of rows after session storage update");
|
||||
|
||||
// deleting item
|
||||
|
||||
gWindow.sessionStorage.removeItem("ss3");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
gWindow.sessionStorage.removeItem("ss1");
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
is($$("#value .table-widget-cell").length, 2,
|
||||
"Correct number of rows after removing items from session storage");
|
||||
|
||||
selectTableItem("ss2");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
ok(!gUI.sidebar.hidden, "sidebar is visible");
|
||||
|
||||
// Checking for correct value in sidebar before update
|
||||
yield findVariableViewProperties([{name: "ss2", value: "foobar"}]);
|
||||
|
||||
gWindow.sessionStorage.setItem("ss2", "changed=ss2");
|
||||
|
||||
yield gUI.once("sidebar-updated");
|
||||
|
||||
is($("#value [data-id='ss2']").value, "changed=ss2",
|
||||
"Value got updated for session storage in the table");
|
||||
|
||||
yield findVariableViewProperties([{name: "ss2", value: "changed=ss2"}]);
|
||||
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
yield testUpdates();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-updates.html").then(startTest);
|
||||
}
|
67
browser/devtools/storage/test/browser_storage_sidebar.js
Normal file
67
browser/devtools/storage/test/browser_storage_sidebar.js
Normal file
@ -0,0 +1,67 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Test to verify that the sidebar opens, closes and updates
|
||||
// This test is not testing the values in the sidebar, being tested in _values
|
||||
|
||||
// Format: [
|
||||
// <id of the table item to click> or <id array for tree item to select> or
|
||||
// null to press Escape,
|
||||
// <do we wait for the async "sidebar-updated" event>,
|
||||
// <is the sidebar open>
|
||||
// ]
|
||||
const testCases = [
|
||||
[["cookies", "sectest1.example.org"], 0, 0],
|
||||
["cs2", 1, 1],
|
||||
[null, 0, 0],
|
||||
["cs2", 1, 1],
|
||||
["uc1", 1, 1],
|
||||
["uc1", 0, 1],
|
||||
[["localStorage", "http://sectest1.example.org"], 0, 0],
|
||||
["iframe-u-ls1", 1, 1],
|
||||
["iframe-u-ls1", 0, 1],
|
||||
[null, 0, 0],
|
||||
[["sessionStorage", "http://test1.example.org"], 0, 0],
|
||||
["ss1", 1, 1],
|
||||
[null, 0, 0],
|
||||
[["indexedDB", "http://test1.example.org"], 0, 0],
|
||||
["idb2", 1, 1],
|
||||
[["indexedDB", "http://test1.example.org", "idb2", "obj3"], 0, 0],
|
||||
[["indexedDB", "https://sectest1.example.org", "idb-s2"], 0, 0],
|
||||
["obj-s2", 1, 1],
|
||||
[null, 0, 0],
|
||||
[null, 0, 0],
|
||||
["obj-s2", 1, 1],
|
||||
[null, 0, 0],
|
||||
];
|
||||
|
||||
let testSidebar = Task.async(function*() {
|
||||
let doc = gPanelWindow.document;
|
||||
for (let item of testCases) {
|
||||
info("clicking for item " + item);
|
||||
if (Array.isArray(item[0])) {
|
||||
selectTreeItem(item[0]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
}
|
||||
else if (item[0]) {
|
||||
selectTableItem(item[0]);
|
||||
}
|
||||
else {
|
||||
EventUtils.sendKey("ESCAPE", gPanelWindow);
|
||||
}
|
||||
if (item[1]) {
|
||||
yield gUI.once("sidebar-updated");
|
||||
}
|
||||
is(!item[2], gUI.sidebar.hidden, "Correct visibility state of sidebar");
|
||||
}
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
yield testSidebar();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html").then(startTest);
|
||||
}
|
143
browser/devtools/storage/test/browser_storage_values.js
Normal file
143
browser/devtools/storage/test/browser_storage_values.js
Normal file
@ -0,0 +1,143 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Test to verify that the values shown in sidebar are correct
|
||||
|
||||
// Format: [
|
||||
// <id of the table item to click> or <id array for tree item to select> or
|
||||
// null do click nothing,
|
||||
// null to skip checking value in variables view or a key value pair object
|
||||
// which will be asserted to exist in the storage sidebar,
|
||||
// true if the check is to be made in the parsed value section
|
||||
// ]
|
||||
const testCases = [
|
||||
["cs2", [
|
||||
{name: "cs2", value: "sessionCookie"},
|
||||
{name: "cs2.path", value: "/"},
|
||||
{name: "cs2.isDomain", value: "true"},
|
||||
{name: "cs2.isHttpOnly", value: "false"},
|
||||
{name: "cs2.host", value: ".example.org"},
|
||||
{name: "cs2.expires", value: "Session"},
|
||||
{name: "cs2.isSecure", value: "false"},
|
||||
]],
|
||||
["c1", [
|
||||
{name: "c1", value: JSON.stringify(["foo", "Bar", {foo: "Bar"}])},
|
||||
{name: "c1.path", value: "/browser"},
|
||||
{name: "c1.isDomain", value: "false"},
|
||||
{name: "c1.isHttpOnly", value: "false"},
|
||||
{name: "c1.host", value: "test1.example.org"},
|
||||
{name: "c1.expires", value: new Date(2000000000000).toLocaleString()},
|
||||
{name: "c1.isSecure", value: "false"},
|
||||
]],
|
||||
[/*"c1"*/, [
|
||||
{name: "c1", value: "Array"},
|
||||
{name: "c1.0", value: "foo"},
|
||||
{name: "c1.1", value: "Bar"},
|
||||
{name: "c1.2", value: "Object"},
|
||||
{name: "c1.2.foo", value: "Bar"},
|
||||
], true],
|
||||
[["localStorage", "http://test1.example.org"]],
|
||||
["ls2", [
|
||||
{name: "ls2", value: "foobar-2"}
|
||||
]],
|
||||
["ls1", [
|
||||
{name: "ls1", value: JSON.stringify({
|
||||
es6: "for", the: "win", baz: [0, 2, 3, {
|
||||
deep: "down",
|
||||
nobody: "cares"
|
||||
}]})}
|
||||
]],
|
||||
[/*ls1*/, [
|
||||
{name: "ls1", value: "Object"},
|
||||
{name: "ls1.es6", value: "for"},
|
||||
{name: "ls1.the", value: "win"},
|
||||
{name: "ls1.baz", value: "Array"},
|
||||
{name: "ls1.baz.0", value: "0"},
|
||||
{name: "ls1.baz.1", value: "2"},
|
||||
{name: "ls1.baz.2", value: "3"},
|
||||
{name: "ls1.baz.3", value: "Object"},
|
||||
{name: "ls1.baz.3.deep", value: "down"},
|
||||
{name: "ls1.baz.3.nobody", value: "cares"},
|
||||
], true],
|
||||
["ls3", [
|
||||
{name: "ls3", "value": "http://foobar.com/baz.php"}
|
||||
]],
|
||||
[/*ls3*/, [
|
||||
{name: "ls3", "value": "http://foobar.com/baz.php", dontMatch: true}
|
||||
], true],
|
||||
[["sessionStorage", "http://test1.example.org"]],
|
||||
["ss1", [
|
||||
{name: "ss1", value: "This#is#an#array"}
|
||||
]],
|
||||
[/*ss1*/, [
|
||||
{name: "ss1", value: "Array"},
|
||||
{name: "ss1.0", value: "This"},
|
||||
{name: "ss1.1", value: "is"},
|
||||
{name: "ss1.2", value: "an"},
|
||||
{name: "ss1.3", value: "array"},
|
||||
], true],
|
||||
["ss2", [
|
||||
{name: "ss2", value: "Array"},
|
||||
{name: "ss2.0", value: "This"},
|
||||
{name: "ss2.1", value: "is"},
|
||||
{name: "ss2.2", value: "another"},
|
||||
{name: "ss2.3", value: "array"},
|
||||
], true],
|
||||
["ss3", [
|
||||
{name: "ss3", value: "Object"},
|
||||
{name: "ss3.this", value: "is"},
|
||||
{name: "ss3.an", value: "object"},
|
||||
{name: "ss3.foo", value: "bar"},
|
||||
], true],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj1"]],
|
||||
[1, [
|
||||
{name: 1, value: JSON.stringify({id: 1, name: "foo", email: "foo@bar.com"})}
|
||||
]],
|
||||
[/*1*/, [
|
||||
{name: "1.id", value: "1"},
|
||||
{name: "1.name", value: "foo"},
|
||||
{name: "1.email", value: "foo@bar.com"},
|
||||
], true],
|
||||
[["indexedDB", "http://test1.example.org", "idb1", "obj2"]],
|
||||
[1, [
|
||||
{name: 1, value: JSON.stringify({
|
||||
id2: 1, name: "foo", email: "foo@bar.com", extra: "baz"
|
||||
})}
|
||||
]],
|
||||
[/*1*/, [
|
||||
{name: "1.id2", value: "1"},
|
||||
{name: "1.name", value: "foo"},
|
||||
{name: "1.email", value: "foo@bar.com"},
|
||||
{name: "1.extra", value: "baz"},
|
||||
], true]
|
||||
];
|
||||
|
||||
let testValues = Task.async(function*() {
|
||||
gUI.tree.expandAll();
|
||||
let doc = gPanelWindow.document;
|
||||
for (let item of testCases) {
|
||||
info("clicking for item " + item);
|
||||
if (Array.isArray(item[0])) {
|
||||
selectTreeItem(item[0]);
|
||||
yield gUI.once("store-objects-updated");
|
||||
continue;
|
||||
}
|
||||
else if (item[0]) {
|
||||
selectTableItem(item[0]);
|
||||
}
|
||||
if (item[0] && item[1]) {
|
||||
yield gUI.once("sidebar-updated");
|
||||
}
|
||||
yield findVariableViewProperties(item[1], item[2]);
|
||||
}
|
||||
});
|
||||
|
||||
let startTest = Task.async(function*() {
|
||||
yield testValues();
|
||||
finishTests();
|
||||
});
|
||||
|
||||
function test() {
|
||||
openTabAndSetupStorage(MAIN_DOMAIN + "storage-complex-values.html").then(startTest);
|
||||
}
|
499
browser/devtools/storage/test/head.js
Normal file
499
browser/devtools/storage/test/head.js
Normal file
@ -0,0 +1,499 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm", tempScope);
|
||||
const console = tempScope.console;
|
||||
const devtools = tempScope.devtools;
|
||||
tempScope = null;
|
||||
const require = devtools.require;
|
||||
const TargetFactory = devtools.TargetFactory;
|
||||
|
||||
const SPLIT_CONSOLE_PREF = "devtools.toolbox.splitconsoleEnabled";
|
||||
const STORAGE_PREF = "devtools.storage.enabled";
|
||||
const PATH = "browser/browser/devtools/storage/test/";
|
||||
const MAIN_DOMAIN = "http://test1.example.org/" + PATH;
|
||||
const ALT_DOMAIN = "http://sectest1.example.org/" + PATH;
|
||||
const ALT_DOMAIN_SECURED = "https://sectest1.example.org:443/" + PATH;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let gToolbox, gPanelWindow, gWindow, gUI;
|
||||
|
||||
Services.prefs.setBoolPref(STORAGE_PREF, true);
|
||||
gDevTools.testing = true;
|
||||
registerCleanupFunction(() => {
|
||||
gToolbox = gPanelWindow = gWindow = gUI = null;
|
||||
Services.prefs.clearUserPref(STORAGE_PREF);
|
||||
Services.prefs.clearUserPref(SPLIT_CONSOLE_PREF);
|
||||
gDevTools.testing = false;
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a new test tab in the browser and load the given url.
|
||||
*
|
||||
* @param {String} url The url to be loaded in the new tab
|
||||
*
|
||||
* @return a promise that resolves to the content window when the url is loaded
|
||||
*/
|
||||
function addTab(url) {
|
||||
info("Adding a new tab with URL: '" + url + "'");
|
||||
let def = promise.defer();
|
||||
|
||||
// Bug 921935 should bring waitForFocus() support to e10s, which would
|
||||
// probably cover the case of the test losing focus when the page is loading.
|
||||
// For now, we just make sure the window is focused.
|
||||
window.focus();
|
||||
|
||||
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
linkedBrowser.addEventListener("load", function onload(event) {
|
||||
if (event.originalTarget.location.href != url) {
|
||||
return;
|
||||
}
|
||||
linkedBrowser.removeEventListener("load", onload, true);
|
||||
info("URL '" + url + "' loading complete");
|
||||
def.resolve(tab.linkedBrowser.contentWindow);
|
||||
}, true);
|
||||
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the given url in a new tab, then sets up the page by waiting for
|
||||
* all cookies, indexedDB items etc. to be created; Then opens the storage
|
||||
* inspector and waits for the storage tree and table to be populated
|
||||
*
|
||||
* @param url {String} The url to be opened in the new tab
|
||||
*
|
||||
* @return {Promise} A promise that resolves after storage inspector is ready
|
||||
*/
|
||||
let openTabAndSetupStorage = Task.async(function*(url) {
|
||||
/**
|
||||
* This method iterates over iframes in a window and setups the indexed db
|
||||
* required for this test.
|
||||
*/
|
||||
let setupIDBInFrames = (w, i, c) => {
|
||||
if (w[i] && w[i].idbGenerator) {
|
||||
w[i].setupIDB = w[i].idbGenerator(() => setupIDBInFrames(w, i + 1, c));
|
||||
w[i].setupIDB.next();
|
||||
}
|
||||
else if (w[i] && w[i + 1]) {
|
||||
setupIDBInFrames(w, i + 1, c);
|
||||
}
|
||||
else {
|
||||
c();
|
||||
}
|
||||
};
|
||||
|
||||
let content = yield addTab(url);
|
||||
|
||||
let def = promise.defer();
|
||||
// Setup the indexed db in main window.
|
||||
gWindow = content.wrappedJSObject;
|
||||
if (gWindow.idbGenerator) {
|
||||
gWindow.setupIDB = gWindow.idbGenerator(() => {
|
||||
setupIDBInFrames(gWindow, 0, () => {
|
||||
def.resolve();
|
||||
});
|
||||
});
|
||||
gWindow.setupIDB.next();
|
||||
yield def.promise;
|
||||
}
|
||||
|
||||
// open storage inspector
|
||||
return yield openStoragePanel();
|
||||
});
|
||||
|
||||
/**
|
||||
* Open the toolbox, with the storage tool visible.
|
||||
*
|
||||
* @param cb {Function} Optional callback, if you don't want to use the returned
|
||||
* promise
|
||||
*
|
||||
* @return {Promise} a promise that resolves when the storage inspector is ready
|
||||
*/
|
||||
let openStoragePanel = Task.async(function*(cb) {
|
||||
info("Opening the storage inspector");
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
let storage, toolbox;
|
||||
|
||||
// Checking if the toolbox and the storage are already loaded
|
||||
// The storage-updated event should only be waited for if the storage
|
||||
// isn't loaded yet
|
||||
toolbox = gDevTools.getToolbox(target);
|
||||
if (toolbox) {
|
||||
storage = toolbox.getPanel("storage");
|
||||
if (storage) {
|
||||
gPanelWindow = storage.panelWindow;
|
||||
gUI = storage.UI;
|
||||
gToolbox = toolbox;
|
||||
info("Toolbox and storage already open");
|
||||
if (cb) {
|
||||
return cb(storage, toolbox);
|
||||
} else {
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
storage: storage
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info("Opening the toolbox");
|
||||
toolbox = yield gDevTools.showToolbox(target, "storage");
|
||||
storage = toolbox.getPanel("storage");
|
||||
gPanelWindow = storage.panelWindow;
|
||||
gUI = storage.UI;
|
||||
gToolbox = toolbox;
|
||||
|
||||
info("Waiting for the stores to update");
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
yield waitForToolboxFrameFocus(toolbox);
|
||||
|
||||
if (cb) {
|
||||
return cb(storage, toolbox);
|
||||
} else {
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
storage: storage
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Wait for the toolbox frame to receive focus after it loads
|
||||
*
|
||||
* @param toolbox {Toolbox}
|
||||
*
|
||||
* @return a promise that resolves when focus has been received
|
||||
*/
|
||||
function waitForToolboxFrameFocus(toolbox) {
|
||||
info("Making sure that the toolbox's frame is focused");
|
||||
let def = promise.defer();
|
||||
let win = toolbox.frame.contentWindow;
|
||||
waitForFocus(def.resolve, win);
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces GC, CC and Shrinking GC to get rid of disconnected docshells and
|
||||
* windows.
|
||||
*/
|
||||
function forceCollections() {
|
||||
Cu.forceGC();
|
||||
Cu.forceCC();
|
||||
Cu.forceShrinkingGC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up and finishes the test
|
||||
*/
|
||||
function finishTests() {
|
||||
// Cleanup so that indexed db created from this test do not interfere next ones
|
||||
|
||||
/**
|
||||
* This method iterates over iframes in a window and clears the indexed db
|
||||
* created by this test.
|
||||
*/
|
||||
let clearIDB = (w, i, c) => {
|
||||
if (w[i] && w[i].clear) {
|
||||
w[i].clearIterator = w[i].clear(() => clearIDB(w, i + 1, c));
|
||||
w[i].clearIterator.next();
|
||||
}
|
||||
else if (w[i] && w[i + 1]) {
|
||||
clearIDB(w, i + 1, c);
|
||||
}
|
||||
else {
|
||||
c();
|
||||
}
|
||||
};
|
||||
|
||||
gWindow.clearIterator = gWindow.clear(() => {
|
||||
clearIDB(gWindow, 0, () => {
|
||||
// Forcing GC/CC to get rid of docshells and windows created by this test.
|
||||
forceCollections();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
gWindow.clearIterator.next();
|
||||
}
|
||||
|
||||
// Sends a click event on the passed DOM node in an async manner
|
||||
function click(node) {
|
||||
node.scrollIntoView()
|
||||
executeSoon(() => EventUtils.synthesizeMouseAtCenter(node, {}, gPanelWindow));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Recursively expand the variables view up to a given property.
|
||||
*
|
||||
* @param aOptions
|
||||
* Options for view expansion:
|
||||
* - rootVariable: start from the given scope/variable/property.
|
||||
* - expandTo: string made up of property names you want to expand.
|
||||
* For example: "body.firstChild.nextSibling" given |rootVariable:
|
||||
* document|.
|
||||
* @return object
|
||||
* A promise that is resolved only when the last property in |expandTo|
|
||||
* is found, and rejected otherwise. Resolution reason is always the
|
||||
* last property - |nextSibling| in the example above. Rejection is
|
||||
* always the last property that was found.
|
||||
*/
|
||||
function variablesViewExpandTo(aOptions) {
|
||||
let root = aOptions.rootVariable;
|
||||
let expandTo = aOptions.expandTo.split(".");
|
||||
let lastDeferred = promise.defer();
|
||||
|
||||
function getNext(aProp) {
|
||||
let name = expandTo.shift();
|
||||
let newProp = aProp.get(name);
|
||||
|
||||
if (expandTo.length > 0) {
|
||||
ok(newProp, "found property " + name);
|
||||
if (newProp && newProp.expand) {
|
||||
newProp.expand();
|
||||
getNext(newProp);
|
||||
}
|
||||
else {
|
||||
lastDeferred.reject(aProp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (newProp) {
|
||||
lastDeferred.resolve(newProp);
|
||||
}
|
||||
else {
|
||||
lastDeferred.reject(aProp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetchError(aProp) {
|
||||
lastDeferred.reject(aProp);
|
||||
}
|
||||
|
||||
if (root && root.expand) {
|
||||
root.expand();
|
||||
getNext(root);
|
||||
}
|
||||
else {
|
||||
lastDeferred.resolve(root)
|
||||
}
|
||||
|
||||
return lastDeferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find variables or properties in a VariablesView instance.
|
||||
*
|
||||
* @param array aRules
|
||||
* The array of rules you want to match. Each rule is an object with:
|
||||
* - name (string|regexp): property name to match.
|
||||
* - value (string|regexp): property value to match.
|
||||
* - dontMatch (boolean): make sure the rule doesn't match any property.
|
||||
* @param boolean aParsed
|
||||
* true if we want to test the rules in the parse value section of the
|
||||
* storage sidebar
|
||||
* @return object
|
||||
* A promise object that is resolved when all the rules complete
|
||||
* matching. The resolved callback is given an array of all the rules
|
||||
* you wanted to check. Each rule has a new property: |matchedProp|
|
||||
* which holds a reference to the Property object instance from the
|
||||
* VariablesView. If the rule did not match, then |matchedProp| is
|
||||
* undefined.
|
||||
*/
|
||||
function findVariableViewProperties(aRules, aParsed) {
|
||||
// Initialize the search.
|
||||
function init() {
|
||||
// If aParsed is true, we are checking rules in the parsed value section of
|
||||
// the storage sidebar. That scope uses a blank variable as a placeholder
|
||||
// Thus, adding a blank parent to each name
|
||||
if (aParsed) {
|
||||
aRules = aRules.map(({name, value, dontMatch}) => {
|
||||
return {name: "." + name, value, dontMatch}
|
||||
});
|
||||
}
|
||||
// Separate out the rules that require expanding properties throughout the
|
||||
// view.
|
||||
let expandRules = [];
|
||||
let rules = aRules.filter((aRule) => {
|
||||
if (typeof aRule.name == "string" && aRule.name.indexOf(".") > -1) {
|
||||
expandRules.push(aRule);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Search through the view those rules that do not require any properties to
|
||||
// be expanded. Build the array of matchers, outstanding promises to be
|
||||
// resolved.
|
||||
let outstanding = [];
|
||||
|
||||
finder(rules, gUI.view, outstanding);
|
||||
|
||||
// Process the rules that need to expand properties.
|
||||
let lastStep = processExpandRules.bind(null, expandRules);
|
||||
|
||||
// Return the results - a promise resolved to hold the updated aRules array.
|
||||
let returnResults = onAllRulesMatched.bind(null, aRules);
|
||||
|
||||
return promise.all(outstanding).then(lastStep).then(returnResults);
|
||||
}
|
||||
|
||||
function onMatch(aProp, aRule, aMatched) {
|
||||
if (aMatched && !aRule.matchedProp) {
|
||||
aRule.matchedProp = aProp;
|
||||
}
|
||||
}
|
||||
|
||||
function finder(aRules, aView, aPromises) {
|
||||
for (let scope of aView) {
|
||||
for (let [id, prop] of scope) {
|
||||
for (let rule of aRules) {
|
||||
let matcher = matchVariablesViewProperty(prop, rule);
|
||||
aPromises.push(matcher.then(onMatch.bind(null, prop, rule)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processExpandRules(aRules) {
|
||||
let rule = aRules.shift();
|
||||
if (!rule) {
|
||||
return promise.resolve(null);
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
let expandOptions = {
|
||||
rootVariable: gUI.view.getScopeAtIndex(aParsed ? 1: 0),
|
||||
expandTo: rule.name
|
||||
};
|
||||
|
||||
variablesViewExpandTo(expandOptions).then(function onSuccess(aProp) {
|
||||
let name = rule.name;
|
||||
let lastName = name.split(".").pop();
|
||||
rule.name = lastName;
|
||||
|
||||
let matched = matchVariablesViewProperty(aProp, rule);
|
||||
return matched.then(onMatch.bind(null, aProp, rule)).then(function() {
|
||||
rule.name = name;
|
||||
});
|
||||
}, function onFailure() {
|
||||
return promise.resolve(null);
|
||||
}).then(processExpandRules.bind(null, aRules)).then(function() {
|
||||
deferred.resolve(null);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function onAllRulesMatched(aRules) {
|
||||
for (let rule of aRules) {
|
||||
let matched = rule.matchedProp;
|
||||
if (matched && !rule.dontMatch) {
|
||||
ok(true, "rule " + rule.name + " matched for property " + matched.name);
|
||||
}
|
||||
else if (matched && rule.dontMatch) {
|
||||
ok(false, "rule " + rule.name + " should not match property " +
|
||||
matched.name);
|
||||
}
|
||||
else {
|
||||
ok(rule.dontMatch, "rule " + rule.name + " did not match any property");
|
||||
}
|
||||
}
|
||||
return aRules;
|
||||
}
|
||||
|
||||
return init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given Property object from the variables view matches the given
|
||||
* rule.
|
||||
*
|
||||
* @param object aProp
|
||||
* The variable's view Property instance.
|
||||
* @param object aRule
|
||||
* Rules for matching the property. See findVariableViewProperties() for
|
||||
* details.
|
||||
* @return object
|
||||
* A promise that is resolved when all the checks complete. Resolution
|
||||
* result is a boolean that tells your promise callback the match
|
||||
* result: true or false.
|
||||
*/
|
||||
function matchVariablesViewProperty(aProp, aRule) {
|
||||
function resolve(aResult) {
|
||||
return promise.resolve(aResult);
|
||||
}
|
||||
|
||||
if (!aProp) {
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
if (aRule.name) {
|
||||
let match = aRule.name instanceof RegExp ?
|
||||
aRule.name.test(aProp.name) :
|
||||
aProp.name == aRule.name;
|
||||
if (!match) {
|
||||
return resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
if ("value" in aRule) {
|
||||
let displayValue = aProp.displayValue;
|
||||
if (aProp.displayValueClassName == "token-string") {
|
||||
displayValue = displayValue.substring(1, displayValue.length - 1);
|
||||
}
|
||||
|
||||
let match = aRule.value instanceof RegExp ?
|
||||
aRule.value.test(displayValue) :
|
||||
displayValue == aRule.value;
|
||||
if (!match) {
|
||||
info("rule " + aRule.name + " did not match value, expected '" +
|
||||
aRule.value + "', found '" + displayValue + "'");
|
||||
return resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click selects a row in the table.
|
||||
*
|
||||
* @param {[String]} ids
|
||||
* The array id of the item in the tree
|
||||
*/
|
||||
function selectTreeItem(ids) {
|
||||
// Expand tree as some/all items could be collapsed leading to click on an
|
||||
// incorrect tree item
|
||||
gUI.tree.expandAll();
|
||||
click(gPanelWindow.document.querySelector("[data-id='" + JSON.stringify(ids) +
|
||||
"'] > .tree-widget-item"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Click selects a row in the table.
|
||||
*
|
||||
* @param {String} id
|
||||
* The id of the row in the table widget
|
||||
*/
|
||||
function selectTableItem(id) {
|
||||
click(gPanelWindow.document.querySelector(".table-widget-cell[data-id='" +
|
||||
id + "']"));
|
||||
}
|
8
browser/devtools/storage/test/moz.build
Normal file
8
browser/devtools/storage/test/moz.build
Normal file
@ -0,0 +1,8 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['browser.ini']
|
||||
|
99
browser/devtools/storage/test/storage-complex-values.html
Normal file
99
browser/devtools/storage/test/storage-complex-values.html
Normal file
@ -0,0 +1,99 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 970517 - Storage inspector front end - tests
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Storage inspector test for correct values in the sidebar</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
let partialHostname = location.hostname.match(/^[^.]+(\..*)$/)[1];
|
||||
let cookieExpiresTime = 2000000000000;
|
||||
// Setting up some cookies to eat.
|
||||
document.cookie = "c1=" + JSON.stringify([
|
||||
"foo", "Bar", {
|
||||
foo: "Bar"
|
||||
}]) + "; expires=" + new Date(cookieExpiresTime).toGMTString() +
|
||||
"; path=/browser";
|
||||
document.cookie = "cs2=sessionCookie; path=/; domain=" + partialHostname;
|
||||
// ... and some local storage items ..
|
||||
var es6 = "for";
|
||||
localStorage.setItem("ls1", JSON.stringify({
|
||||
es6, the: "win", baz: [0, 2, 3, {
|
||||
deep: "down",
|
||||
nobody: "cares"
|
||||
}]}));
|
||||
localStorage.setItem("ls2", "foobar-2");
|
||||
localStorage.setItem("ls3", "http://foobar.com/baz.php");
|
||||
// ... and finally some session storage items too
|
||||
sessionStorage.setItem("ss1", "This#is#an#array");
|
||||
sessionStorage.setItem("ss2", "This~is~another~array");
|
||||
sessionStorage.setItem("ss3", "this#is~an#object~foo#bar");
|
||||
console.log("added cookies and stuff from main page");
|
||||
|
||||
function success(event) {
|
||||
setupIDB.next(event);
|
||||
}
|
||||
|
||||
window.idbGenerator = function*(callback) {
|
||||
let request = indexedDB.open("idb1", 1);
|
||||
request.onupgradeneeded = success;
|
||||
request.onerror = function(e) {
|
||||
throw new Error("error opening db connection");
|
||||
};
|
||||
let event = yield undefined;
|
||||
let db = event.target.result;
|
||||
let store1 = db.createObjectStore("obj1", { keyPath: "id" });
|
||||
store1.createIndex("name", "name", { unique: false });
|
||||
store1.createIndex("email", "email", { unique: true });
|
||||
let store2 = db.createObjectStore("obj2", { keyPath: "id2" });
|
||||
|
||||
store1.add({id: 1, name: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 2, name: "foo2", email: "foo2@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 3, name: "foo2", email: "foo3@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store2.add({id2: 1, name: "foo", email: "foo@bar.com", extra: "baz"}).onsuccess = success;
|
||||
yield undefined;
|
||||
|
||||
store1.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
request = indexedDB.open("idb2", 1);
|
||||
request.onupgradeneeded = success;
|
||||
event = yield undefined;
|
||||
|
||||
let db2 = event.target.result;
|
||||
let store3 = db2.createObjectStore("obj3", { keyPath: "id3" });
|
||||
store3.createIndex("name2", "name2", { unique: true });
|
||||
store3.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db2.close();
|
||||
console.log("added cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
|
||||
function successClear(event) {
|
||||
clearIterator.next(event);
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/browser";
|
||||
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
|
||||
yield undefined;
|
||||
indexedDB.deleteDatabase("idb2").onsuccess = successClear;
|
||||
yield undefined;
|
||||
console.log("removed cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
94
browser/devtools/storage/test/storage-listings.html
Normal file
94
browser/devtools/storage/test/storage-listings.html
Normal file
@ -0,0 +1,94 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 970517 - Storage inspector front end - tests
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Storage inspector test for listing hosts and storages</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://sectest1.example.org/browser/browser/devtools/storage/test/storage-unsecured-iframe.html"></iframe>
|
||||
<iframe src="https://sectest1.example.org:443/browser/browser/devtools/storage/test/storage-secured-iframe.html"></iframe>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
let partialHostname = location.hostname.match(/^[^.]+(\..*)$/)[1];
|
||||
let cookieExpiresTime1 = 2000000000000;
|
||||
let cookieExpiresTime2 = 2000000001000;
|
||||
// Setting up some cookies to eat.
|
||||
document.cookie = "c1=foobar; expires=" +
|
||||
new Date(cookieExpiresTime1).toGMTString() + "; path=/browser";
|
||||
document.cookie = "cs2=sessionCookie; path=/; domain=" + partialHostname;
|
||||
document.cookie = "c3=foobar-2; secure=true; expires=" +
|
||||
new Date(cookieExpiresTime2).toGMTString() + "; path=/";
|
||||
// ... and some local storage items ..
|
||||
localStorage.setItem("ls1", "foobar");
|
||||
localStorage.setItem("ls2", "foobar-2");
|
||||
// ... and finally some session storage items too
|
||||
sessionStorage.setItem("ss1", "foobar-3");
|
||||
console.log("added cookies and stuff from main page");
|
||||
|
||||
function success(event) {
|
||||
setupIDB.next(event);
|
||||
}
|
||||
|
||||
window.idbGenerator = function*(callback) {
|
||||
let request = indexedDB.open("idb1", 1);
|
||||
request.onupgradeneeded = success;
|
||||
request.onerror = function(e) {
|
||||
throw new Error("error opening db connection");
|
||||
};
|
||||
let event = yield undefined;
|
||||
let db = event.target.result;
|
||||
let store1 = db.createObjectStore("obj1", { keyPath: "id" });
|
||||
store1.createIndex("name", "name", { unique: false });
|
||||
store1.createIndex("email", "email", { unique: true });
|
||||
let store2 = db.createObjectStore("obj2", { keyPath: "id2" });
|
||||
|
||||
store1.add({id: 1, name: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 2, name: "foo2", email: "foo2@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 3, name: "foo2", email: "foo3@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store2.add({id2: 1, name: "foo", email: "foo@bar.com", extra: "baz"}).onsuccess = success;
|
||||
yield undefined;
|
||||
|
||||
store1.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
request = indexedDB.open("idb2", 1);
|
||||
request.onupgradeneeded = success;
|
||||
event = yield undefined;
|
||||
|
||||
let db2 = event.target.result;
|
||||
let store3 = db2.createObjectStore("obj3", { keyPath: "id3" });
|
||||
store3.createIndex("name2", "name2", { unique: true });
|
||||
store3.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db2.close();
|
||||
console.log("added cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
|
||||
function successClear(event) {
|
||||
clearIterator.next(event);
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/browser";
|
||||
document.cookie = "c3=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; secure=true";
|
||||
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=" + partialHostname;
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
|
||||
yield undefined;
|
||||
indexedDB.deleteDatabase("idb2").onsuccess = successClear;
|
||||
yield undefined;
|
||||
console.log("removed cookies and stuff from main page");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
71
browser/devtools/storage/test/storage-secured-iframe.html
Normal file
71
browser/devtools/storage/test/storage-secured-iframe.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Iframe for testing multiple host detetion in storage actor
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
document.cookie = "sc1=foobar;";
|
||||
localStorage.setItem("iframe-s-ls1", "foobar");
|
||||
sessionStorage.setItem("iframe-s-ss1", "foobar-2");
|
||||
|
||||
function success(event) {
|
||||
setupIDB.next(event);
|
||||
}
|
||||
|
||||
window.idbGenerator = function*(callback) {
|
||||
let request = indexedDB.open("idb-s1", 1);
|
||||
request.onupgradeneeded = success;
|
||||
request.onerror = function(e) {
|
||||
throw new Error("error opening db connection");
|
||||
};
|
||||
let event = yield undefined;
|
||||
let db = event.target.result;
|
||||
let store1 = db.createObjectStore("obj-s1", { keyPath: "id" });
|
||||
|
||||
store1.add({id: 6, name: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.add({id: 7, name: "foo2", email: "foo2@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store1.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db.close();
|
||||
|
||||
request = indexedDB.open("idb-s2", 1);
|
||||
request.onupgradeneeded = success;
|
||||
event = yield undefined;
|
||||
|
||||
let db2 = event.target.result;
|
||||
let store3 = db2.createObjectStore("obj-s2", { keyPath: "id3", autoIncrement: true });
|
||||
store3.createIndex("name2", "name2", { unique: true });
|
||||
store3.add({id3: 16, name2: "foo", email: "foo@bar.com"}).onsuccess = success;
|
||||
yield undefined;
|
||||
store3.transaction.oncomplete = success;
|
||||
yield undefined;
|
||||
db2.close();
|
||||
console.log("added cookies and stuff from secured iframe");
|
||||
callback();
|
||||
}
|
||||
|
||||
function successClear(event) {
|
||||
clearIterator.next(event);
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "sc1=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
indexedDB.deleteDatabase("idb-s1").onsuccess = successClear;
|
||||
yield undefined;
|
||||
indexedDB.deleteDatabase("idb-s2").onsuccess = successClear;
|
||||
yield undefined;
|
||||
console.log("removed cookies and stuff from secured iframe");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
27
browser/devtools/storage/test/storage-unsecured-iframe.html
Normal file
27
browser/devtools/storage/test/storage-unsecured-iframe.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Iframe for testing multiple host detetion in storage actor
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
document.cookie = "uc1=foobar; domain=.example.org; path=/; secure=true";
|
||||
localStorage.setItem("iframe-u-ls1", "foobar");
|
||||
sessionStorage.setItem("iframe-u-ss1", "foobar1");
|
||||
sessionStorage.setItem("iframe-u-ss2", "foobar2");
|
||||
console.log("added cookies and stuff from unsecured iframe");
|
||||
|
||||
window.clear = function*(callback) {
|
||||
document.cookie = "uc1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.example.org; secure=true";
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
console.log("removed cookies and stuff from unsecured iframe");
|
||||
callback();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
63
browser/devtools/storage/test/storage-updates.html
Normal file
63
browser/devtools/storage/test/storage-updates.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Bug 965872 - Storage inspector actor with cookies, local storage and session storage.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Storage inspector blank html for tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
window.addCookie = function(name, value, path, domain, expires, secure) {
|
||||
var cookieString = name + "=" + value + ";";
|
||||
if (path) {
|
||||
cookieString += "path=" + path + ";";
|
||||
}
|
||||
if (domain) {
|
||||
cookieString += "domain=" + domain + ";";
|
||||
}
|
||||
if (expires) {
|
||||
cookieString += "expires=" + expires + ";";
|
||||
}
|
||||
if (secure) {
|
||||
cookieString += "secure=true;";
|
||||
}
|
||||
document.cookie = cookieString;
|
||||
};
|
||||
|
||||
window.removeCookie = function(name, path) {
|
||||
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=" + path;
|
||||
}
|
||||
|
||||
window.clear = function*(callback) {
|
||||
var cookies = document.cookie;
|
||||
for (var cookie of cookies.split(";")) {
|
||||
removeCookie(cookie.split("=")[0]);
|
||||
removeCookie(cookie.split("=")[0], "/browser");
|
||||
}
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
callback();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
addCookie("c1", "1.2.3.4.5.6.7", "/browser");
|
||||
addCookie("c2", "foobar", "/browser");
|
||||
|
||||
localStorage.setItem("ls1", "testing");
|
||||
localStorage.setItem("ls2", "testing");
|
||||
localStorage.setItem("ls3", "testing");
|
||||
localStorage.setItem("ls4", "testing");
|
||||
localStorage.setItem("ls5", "testing");
|
||||
localStorage.setItem("ls6", "testing");
|
||||
localStorage.setItem("ls7", "testing");
|
||||
|
||||
sessionStorage.setItem("ss1", "foobar");
|
||||
sessionStorage.setItem("ss2", "foobar");
|
||||
sessionStorage.setItem("ss3", "foobar");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -516,7 +516,7 @@ StorageUI.prototype = {
|
||||
* Array of objects to be populated in the storage table
|
||||
* @param {number} reason
|
||||
* The reason of this populateTable call. 2 for update, 1 for new row
|
||||
* in an existing table and 1 when populating a table for the first
|
||||
* in an existing table and 0 when populating a table for the first
|
||||
* time for the given host/type
|
||||
*/
|
||||
populateTable: function(data, reason) {
|
||||
|
Loading…
Reference in New Issue
Block a user