summaryrefslogtreecommitdiff
path: root/toolkit/devtools/tilt/test
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/devtools/tilt/test')
-rw-r--r--toolkit/devtools/tilt/test/browser.ini53
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_01_lazy_getter.js14
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_02_notifications-seq.js99
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_02_notifications-tabs.js179
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_02_notifications.js131
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_03_tab_switch.js110
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_04_initialization.js59
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_05_destruction-esc.js51
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_05_destruction-url.js51
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_05_destruction.js51
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_arcball-reset-typeahead.js132
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_arcball-reset.js130
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_arcball.js496
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_controller.js138
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl01.js157
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl02.js46
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl03.js69
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl04.js126
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl05.js42
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl06.js59
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl07.js60
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_gl08.js51
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_math01.js59
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_math02.js104
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_math03.js33
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_math04.js49
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_math05.js101
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_math06.js42
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_math07.js49
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking.js56
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking_delete.js78
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking_highlight01-offs.js77
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking_highlight01.js77
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking_highlight02.js72
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking_highlight03.js72
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking_inspector.js63
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_picking_miv.js78
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils01.js69
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils02.js21
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils03.js18
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils04.js54
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils05.js101
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils06.js44
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils07.js159
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_utils08.js85
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_visualizer.js128
-rw-r--r--toolkit/devtools/tilt/test/browser_tilt_zoom.js93
-rw-r--r--toolkit/devtools/tilt/test/head.js215
48 files changed, 4301 insertions, 0 deletions
diff --git a/toolkit/devtools/tilt/test/browser.ini b/toolkit/devtools/tilt/test/browser.ini
new file mode 100644
index 000000000..af573cb51
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser.ini
@@ -0,0 +1,53 @@
+[DEFAULT]
+skip-if = e10s # Bug 1086492 - Disable tilt for e10s
+ # Bug 937166 - Make tilt work in E10S mode
+subsuite = devtools
+support-files = head.js
+
+[browser_tilt_01_lazy_getter.js]
+[browser_tilt_02_notifications-seq.js]
+[browser_tilt_02_notifications-tabs.js]
+[browser_tilt_02_notifications.js]
+[browser_tilt_03_tab_switch.js]
+skip-if = true # Bug 1093215 - Failed assertion
+[browser_tilt_04_initialization.js]
+[browser_tilt_05_destruction-esc.js]
+[browser_tilt_05_destruction-url.js]
+[browser_tilt_05_destruction.js]
+[browser_tilt_arcball-reset-typeahead.js]
+[browser_tilt_arcball-reset.js]
+[browser_tilt_arcball.js]
+[browser_tilt_controller.js]
+[browser_tilt_gl01.js]
+[browser_tilt_gl02.js]
+[browser_tilt_gl03.js]
+[browser_tilt_gl04.js]
+[browser_tilt_gl05.js]
+[browser_tilt_gl06.js]
+[browser_tilt_gl07.js]
+[browser_tilt_gl08.js]
+[browser_tilt_math01.js]
+[browser_tilt_math02.js]
+[browser_tilt_math03.js]
+[browser_tilt_math04.js]
+[browser_tilt_math05.js]
+[browser_tilt_math06.js]
+[browser_tilt_math07.js]
+[browser_tilt_picking.js]
+[browser_tilt_picking_delete.js]
+[browser_tilt_picking_highlight01-offs.js]
+[browser_tilt_picking_highlight01.js]
+[browser_tilt_picking_highlight02.js]
+[browser_tilt_picking_highlight03.js]
+[browser_tilt_picking_inspector.js]
+[browser_tilt_picking_miv.js]
+[browser_tilt_utils01.js]
+[browser_tilt_utils02.js]
+[browser_tilt_utils03.js]
+[browser_tilt_utils04.js]
+[browser_tilt_utils05.js]
+[browser_tilt_utils06.js]
+[browser_tilt_utils07.js]
+[browser_tilt_utils08.js]
+[browser_tilt_visualizer.js]
+[browser_tilt_zoom.js]
diff --git a/toolkit/devtools/tilt/test/browser_tilt_01_lazy_getter.js b/toolkit/devtools/tilt/test/browser_tilt_01_lazy_getter.js
new file mode 100644
index 000000000..de77ccb90
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_01_lazy_getter.js
@@ -0,0 +1,14 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ ok(Tilt,
+ "The Tilt object wasn't got correctly via defineLazyGetter.");
+ is(Tilt.chromeWindow, window,
+ "The top-level window wasn't saved correctly");
+ ok(Tilt.visualizers,
+ "The holder object for all the instances of the visualizer doesn't exist.")
+ ok(Tilt.NOTIFICATIONS,
+ "The notifications constants weren't referenced correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_02_notifications-seq.js b/toolkit/devtools/tilt/test/browser_tilt_02_notifications-seq.js
new file mode 100644
index 000000000..2295213dd
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_02_notifications-seq.js
@@ -0,0 +1,99 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tabEvents = "";
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping notifications test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping notifications test because WebGL isn't supported.");
+ return;
+ }
+
+ requestLongerTimeout(10);
+ waitForExplicitFinish();
+
+ createTab(function() {
+ Services.obs.addObserver(finalize, DESTROYED, false);
+ Services.obs.addObserver(obs_STARTUP, STARTUP, false);
+ Services.obs.addObserver(obs_INITIALIZING, INITIALIZING, false);
+ Services.obs.addObserver(obs_INITIALIZED, INITIALIZED, false);
+ Services.obs.addObserver(obs_DESTROYING, DESTROYING, false);
+ Services.obs.addObserver(obs_BEFORE_DESTROYED, BEFORE_DESTROYED, false);
+ Services.obs.addObserver(obs_DESTROYED, DESTROYED, false);
+
+ info("Starting up the Tilt notifications test.");
+ createTilt({}, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function obs_STARTUP(win) {
+ info("Handling the STARTUP notification.");
+ is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "STARTUP;";
+}
+
+function obs_INITIALIZING(win) {
+ info("Handling the INITIALIZING notification.");
+ is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "INITIALIZING;";
+}
+
+function obs_INITIALIZED(win) {
+ info("Handling the INITIALIZED notification.");
+ is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "INITIALIZED;";
+
+ Tilt.destroy(Tilt.currentWindowId, true);
+}
+
+function obs_DESTROYING(win) {
+ info("Handling the DESTROYING( notification.");
+ is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "DESTROYING;";
+}
+
+function obs_BEFORE_DESTROYED(win) {
+ info("Handling the BEFORE_DESTROYED notification.");
+ is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "BEFORE_DESTROYED;";
+}
+
+function obs_DESTROYED(win) {
+ info("Handling the DESTROYED notification.");
+ is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "DESTROYED;";
+}
+
+function finalize(win) {
+ is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
+ is(tabEvents, "STARTUP;INITIALIZING;INITIALIZED;DESTROYING;BEFORE_DESTROYED;DESTROYED;",
+ "The notifications weren't fired in the correct order.");
+
+ cleanup();
+}
+
+function cleanup() {
+ info("Cleaning up the notifications test.");
+
+ Services.obs.removeObserver(finalize, DESTROYED);
+ Services.obs.removeObserver(obs_INITIALIZING, INITIALIZING);
+ Services.obs.removeObserver(obs_INITIALIZED, INITIALIZED);
+ Services.obs.removeObserver(obs_DESTROYING, DESTROYING);
+ Services.obs.removeObserver(obs_BEFORE_DESTROYED, BEFORE_DESTROYED);
+ Services.obs.removeObserver(obs_DESTROYED, DESTROYED);
+ Services.obs.removeObserver(obs_STARTUP, STARTUP);
+
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_02_notifications-tabs.js b/toolkit/devtools/tilt/test/browser_tilt_02_notifications-tabs.js
new file mode 100644
index 000000000..6646b6a94
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_02_notifications-tabs.js
@@ -0,0 +1,179 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tab0, tab1, tab2;
+let testStep = -1;
+
+let expected = [];
+function expect(notification, win) {
+ expected.push({ notification: notification, window: win });
+}
+
+function notification(win, topic) {
+ if (expected.length == 0) {
+ is(topic, null, "Shouldn't see a notification");
+ return;
+ }
+
+ let { notification, window } = expected.shift();
+ if (Cu.isDeadWrapper(window)) {
+ // Sometimes we end up with a nuked window reference here :-(
+ return;
+ }
+ is(topic, notification, "Saw the expected notification");
+ is(win, window, "Saw the expected window");
+}
+
+function after(notification, callback) {
+ function observer() {
+ Services.obs.removeObserver(observer, notification);
+ executeSoon(callback);
+ }
+ Services.obs.addObserver(observer, notification, false);
+}
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping tab switch test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tab switch test because WebGL isn't supported.");
+ return;
+ }
+
+ Services.obs.addObserver(notification, STARTUP, false);
+ Services.obs.addObserver(notification, INITIALIZING, false);
+ Services.obs.addObserver(notification, INITIALIZED, false);
+ Services.obs.addObserver(notification, DESTROYING, false);
+ Services.obs.addObserver(notification, BEFORE_DESTROYED, false);
+ Services.obs.addObserver(notification, DESTROYED, false);
+ Services.obs.addObserver(notification, SHOWN, false);
+ Services.obs.addObserver(notification, HIDDEN, false);
+
+ waitForExplicitFinish();
+
+ tab0 = gBrowser.selectedTab;
+ nextStep();
+}
+
+function createTab2() {
+}
+
+let testSteps = [
+ function step0() {
+ tab1 = createTab(function() {
+ expect(STARTUP, tab1.linkedBrowser.contentWindow);
+ expect(INITIALIZING, tab1.linkedBrowser.contentWindow);
+ expect(INITIALIZED, tab1.linkedBrowser.contentWindow);
+ after(INITIALIZED, nextStep);
+
+ createTilt({}, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+ },
+ function step1() {
+ expect(HIDDEN, tab1.linkedBrowser.contentWindow);
+
+ tab2 = createTab(function() {
+ expect(STARTUP, tab2.linkedBrowser.contentWindow);
+ expect(INITIALIZING, tab2.linkedBrowser.contentWindow);
+ expect(INITIALIZED, tab2.linkedBrowser.contentWindow);
+ after(INITIALIZED, nextStep);
+
+ createTilt({}, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+ },
+ function step2() {
+ expect(HIDDEN, tab2.linkedBrowser.contentWindow);
+ after(HIDDEN, nextStep);
+
+ gBrowser.selectedTab = tab0;
+ },
+ function step3() {
+ expect(SHOWN, tab2.linkedBrowser.contentWindow);
+ after(SHOWN, nextStep);
+
+ gBrowser.selectedTab = tab2;
+ },
+ function step4() {
+ expect(HIDDEN, tab2.linkedBrowser.contentWindow);
+ expect(SHOWN, tab1.linkedBrowser.contentWindow);
+ after(SHOWN, nextStep);
+
+ gBrowser.selectedTab = tab1;
+ },
+ function step5() {
+ expect(HIDDEN, tab1.linkedBrowser.contentWindow);
+ expect(SHOWN, tab2.linkedBrowser.contentWindow);
+ after(SHOWN, nextStep);
+
+ gBrowser.selectedTab = tab2;
+ },
+ function step6() {
+ expect(DESTROYING, tab2.linkedBrowser.contentWindow);
+ expect(BEFORE_DESTROYED, tab2.linkedBrowser.contentWindow);
+ expect(DESTROYED, tab2.linkedBrowser.contentWindow);
+ after(DESTROYED, nextStep);
+
+ Tilt.destroy(Tilt.currentWindowId, true);
+ },
+ function step7() {
+ expect(SHOWN, tab1.linkedBrowser.contentWindow);
+
+ gBrowser.removeCurrentTab();
+ tab2 = null;
+
+ expect(DESTROYING, tab1.linkedBrowser.contentWindow);
+ expect(HIDDEN, tab1.linkedBrowser.contentWindow);
+ expect(BEFORE_DESTROYED, tab1.linkedBrowser.contentWindow);
+ expect(DESTROYED, tab1.linkedBrowser.contentWindow);
+ after(DESTROYED, nextStep);
+
+ gBrowser.removeCurrentTab();
+ tab1 = null;
+ },
+ function step8_cleanup() {
+ is(gBrowser.selectedTab, tab0, "Should be back to the first tab");
+
+ cleanup();
+ }
+];
+
+function cleanup() {
+ if (tab1) {
+ gBrowser.removeTab(tab1);
+ tab1 = null;
+ }
+ if (tab2) {
+ gBrowser.removeTab(tab2);
+ tab2 = null;
+ }
+
+ Services.obs.removeObserver(notification, STARTUP);
+ Services.obs.removeObserver(notification, INITIALIZING);
+ Services.obs.removeObserver(notification, INITIALIZED);
+ Services.obs.removeObserver(notification, DESTROYING);
+ Services.obs.removeObserver(notification, BEFORE_DESTROYED);
+ Services.obs.removeObserver(notification, DESTROYED);
+ Services.obs.removeObserver(notification, SHOWN);
+ Services.obs.removeObserver(notification, HIDDEN);
+
+ finish();
+}
+
+function nextStep() {
+ let step = testSteps.shift();
+ info("Executing " + step.name);
+ step();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_02_notifications.js b/toolkit/devtools/tilt/test/browser_tilt_02_notifications.js
new file mode 100644
index 000000000..6b67e1be1
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_02_notifications.js
@@ -0,0 +1,131 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tab0, tab1;
+let testStep = -1;
+let tabEvents = "";
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping notifications test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping notifications test because WebGL isn't supported.");
+ return;
+ }
+
+ requestLongerTimeout(10);
+ waitForExplicitFinish();
+
+ gBrowser.tabContainer.addEventListener("TabSelect", tabSelect, false);
+ createNewTab();
+}
+
+function createNewTab() {
+ tab0 = gBrowser.selectedTab;
+
+ tab1 = createTab(function() {
+ Services.obs.addObserver(finalize, DESTROYED, false);
+ Services.obs.addObserver(tab_STARTUP, STARTUP, false);
+ Services.obs.addObserver(tab_INITIALIZING, INITIALIZING, false);
+ Services.obs.addObserver(tab_DESTROYING, DESTROYING, false);
+ Services.obs.addObserver(tab_SHOWN, SHOWN, false);
+ Services.obs.addObserver(tab_HIDDEN, HIDDEN, false);
+
+ info("Starting up the Tilt notifications test.");
+ createTilt({
+ onTiltOpen: function()
+ {
+ testStep = 0;
+ tabSelect();
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function tab_STARTUP(win) {
+ info("Handling the STARTUP notification.");
+ is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "STARTUP;";
+}
+
+function tab_INITIALIZING(win) {
+ info("Handling the INITIALIZING notification.");
+ is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "INITIALIZING;";
+}
+
+function tab_DESTROYING(win) {
+ info("Handling the DESTROYING notification.");
+ is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "DESTROYING;";
+}
+
+function tab_SHOWN(win) {
+ info("Handling the SHOWN notification.");
+ is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "SHOWN;";
+}
+
+function tab_HIDDEN(win) {
+ info("Handling the HIDDEN notification.");
+ is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
+ tabEvents += "HIDDEN;";
+}
+
+let testSteps = [
+ function step0() {
+ info("Selecting tab0.");
+ gBrowser.selectedTab = tab0;
+ },
+ function step1() {
+ info("Selecting tab1.");
+ gBrowser.selectedTab = tab1;
+ },
+ function step2() {
+ info("Killing it.");
+ Tilt.destroy(Tilt.currentWindowId, true);
+ }
+];
+
+function finalize(win) {
+ is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
+
+ is(tabEvents, "STARTUP;INITIALIZING;HIDDEN;SHOWN;DESTROYING;",
+ "The notifications weren't fired in the correct order.");
+
+ cleanup();
+}
+
+function cleanup() {
+ info("Cleaning up the notifications test.");
+
+ tab0 = null;
+ tab1 = null;
+
+ Services.obs.removeObserver(finalize, DESTROYED);
+ Services.obs.removeObserver(tab_INITIALIZING, INITIALIZING);
+ Services.obs.removeObserver(tab_DESTROYING, DESTROYING);
+ Services.obs.removeObserver(tab_SHOWN, SHOWN);
+ Services.obs.removeObserver(tab_HIDDEN, HIDDEN);
+ Services.obs.removeObserver(tab_STARTUP, STARTUP);
+
+ gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect);
+ gBrowser.removeCurrentTab();
+ finish();
+}
+
+function tabSelect() {
+ if (testStep !== -1) {
+ executeSoon(testSteps[testStep]);
+ testStep++;
+ }
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_03_tab_switch.js b/toolkit/devtools/tilt/test/browser_tilt_03_tab_switch.js
new file mode 100644
index 000000000..0c54c57e4
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_03_tab_switch.js
@@ -0,0 +1,110 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tab0, tab1, tab2;
+let testStep = -1;
+
+function test() {
+ // This test relies on a timeout to indicate pass or fail. All tests need at
+ // least one pass, fail or todo so let's create a dummy pass.
+ ok(true, "Each test requires at least one pass, fail or todo so here is a pass.");
+
+ if (!isTiltEnabled()) {
+ info("Skipping tab switch test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ info("Skipping tab switch test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ gBrowser.tabContainer.addEventListener("TabSelect", tabSelect, false);
+ createTab1();
+}
+
+function createTab1() {
+ tab0 = gBrowser.selectedTab;
+
+ tab1 = createTab(function() {
+ createTilt({
+ onTiltOpen: function()
+ {
+ createTab2();
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function createTab2() {
+ tab2 = createTab(function() {
+
+ createTilt({
+ onTiltOpen: function()
+ {
+ testStep = 0;
+ tabSelect();
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+let testSteps = [
+ function step0() {
+ gBrowser.selectedTab = tab1;
+ },
+ function step1() {
+ gBrowser.selectedTab = tab0;
+ },
+ function step2() {
+ gBrowser.selectedTab = tab1;
+ },
+ function step3() {
+ gBrowser.selectedTab = tab2;
+ },
+ function step4() {
+ Tilt.destroy(Tilt.currentWindowId);
+ gBrowser.removeCurrentTab();
+ tab2 = null;
+ },
+ function step5() {
+ Tilt.destroy(Tilt.currentWindowId);
+ gBrowser.removeCurrentTab();
+ tab1 = null;
+ },
+ function step6_cleanup() {
+ cleanup();
+ }
+];
+
+function cleanup() {
+ gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, false);
+
+ if (tab1) {
+ gBrowser.removeTab(tab1);
+ tab1 = null;
+ }
+ if (tab2) {
+ gBrowser.removeTab(tab2);
+ tab2 = null;
+ }
+
+ finish();
+}
+
+function tabSelect() {
+ if (testStep !== -1) {
+ executeSoon(testSteps[testStep]);
+ testStep++;
+ }
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_04_initialization.js b/toolkit/devtools/tilt/test/browser_tilt_04_initialization.js
new file mode 100644
index 000000000..da0a936a2
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_04_initialization.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping initialization test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping initialization test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+
+ is(id, Tilt.currentWindowId,
+ "The unique window identifiers should match for the same window.");
+
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ is(document.activeElement, instance.presenter.canvas,
+ "The visualizer canvas should be focused on initialization.");
+
+ ok(Tilt.visualizers[id] instanceof TiltVisualizer,
+ "A new instance of the visualizer wasn't created properly.");
+ ok(Tilt.visualizers[id].isInitialized(),
+ "The new instance of the visualizer wasn't initialized properly.");
+ },
+ onTiltClose: function()
+ {
+ is(document.activeElement, gBrowser.selectedBrowser,
+ "The focus wasn't correctly given back to the selectedBrowser.");
+
+ is(Tilt.visualizers[id], null,
+ "The current instance of the visualizer wasn't destroyed properly.");
+ },
+ onEnd: function()
+ {
+ cleanup();
+ }
+ }, true, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function cleanup() {
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_05_destruction-esc.js b/toolkit/devtools/tilt/test/browser_tilt_05_destruction-esc.js
new file mode 100644
index 000000000..7e0fd5772
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_05_destruction-esc.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tiltOpened = false;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping destruction test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping destruction test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function()
+ {
+ tiltOpened = true;
+
+ Services.obs.addObserver(finalize, DESTROYED, false);
+ EventUtils.sendKey("ESCAPE");
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function finalize() {
+ let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+
+ is(Tilt.visualizers[id], null,
+ "The current instance of the visualizer wasn't destroyed properly.");
+
+ cleanup();
+}
+
+function cleanup() {
+ if (tiltOpened) { Services.obs.removeObserver(finalize, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_05_destruction-url.js b/toolkit/devtools/tilt/test/browser_tilt_05_destruction-url.js
new file mode 100644
index 000000000..734fcda2f
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_05_destruction-url.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tiltOpened = false;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping destruction test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping destruction test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function()
+ {
+ tiltOpened = true;
+
+ Services.obs.addObserver(finalize, DESTROYED, false);
+ window.content.location = "about:mozilla";
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function finalize() {
+ let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+
+ is(Tilt.visualizers[id], null,
+ "The current instance of the visualizer wasn't destroyed properly.");
+
+ cleanup();
+}
+
+function cleanup() {
+ if (tiltOpened) { Services.obs.removeObserver(finalize, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_05_destruction.js b/toolkit/devtools/tilt/test/browser_tilt_05_destruction.js
new file mode 100644
index 000000000..e3f3852b4
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_05_destruction.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tiltOpened = false;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping destruction test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping destruction test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function()
+ {
+ tiltOpened = true;
+
+ Services.obs.addObserver(finalize, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function finalize() {
+ let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+
+ is(Tilt.visualizers[id], null,
+ "The current instance of the visualizer wasn't destroyed properly.");
+
+ cleanup();
+}
+
+function cleanup() {
+ if (tiltOpened) { Services.obs.removeObserver(finalize, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_arcball-reset-typeahead.js b/toolkit/devtools/tilt/test/browser_tilt_arcball-reset-typeahead.js
new file mode 100644
index 000000000..a80879cd6
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_arcball-reset-typeahead.js
@@ -0,0 +1,132 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tiltOpened = false;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping part of the arcball test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping part of the arcball test because WebGL isn't supported.");
+ return;
+ }
+
+ requestLongerTimeout(10);
+ waitForExplicitFinish();
+ Services.prefs.setBoolPref("accessibility.typeaheadfind", true);
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ tiltOpened = true;
+
+ performTest(instance.presenter.canvas,
+ instance.controller.arcball, function() {
+
+ info("Killing arcball reset test.");
+
+ Services.prefs.setBoolPref("accessibility.typeaheadfind", false);
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function performTest(canvas, arcball, callback) {
+ is(document.activeElement, canvas,
+ "The visualizer canvas should be focused when performing this test.");
+
+ info("Starting arcball reset test.");
+
+ // start translating and rotating sometime at random
+
+ window.setTimeout(function() {
+ info("Synthesizing key down events.");
+
+ EventUtils.synthesizeKey("VK_S", { type: "keydown" }); // add a little
+ EventUtils.synthesizeKey("VK_RIGHT", { type: "keydown" }); // diversity
+
+ // wait for some arcball translations and rotations to happen
+
+ window.setTimeout(function() {
+ info("Synthesizing key up events.");
+
+ EventUtils.synthesizeKey("VK_S", { type: "keyup" });
+ EventUtils.synthesizeKey("VK_RIGHT", { type: "keyup" });
+
+ // ok, transformations finished, we can now try to reset the model view
+
+ window.setTimeout(function() {
+ info("Synthesizing arcball reset key press.");
+
+ arcball._onResetStart = function() {
+ info("Starting arcball reset animation.");
+ };
+
+ arcball._onResetStep = function() {
+ info("\nlastRot: " + quat4.str(arcball._lastRot) +
+ "\ndeltaRot: " + quat4.str(arcball._deltaRot) +
+ "\ncurrentRot: " + quat4.str(arcball._currentRot) +
+ "\nlastTrans: " + vec3.str(arcball._lastTrans) +
+ "\ndeltaTrans: " + vec3.str(arcball._deltaTrans) +
+ "\ncurrentTrans: " + vec3.str(arcball._currentTrans) +
+ "\nadditionalRot: " + vec3.str(arcball._additionalRot) +
+ "\nadditionalTrans: " + vec3.str(arcball._additionalTrans) +
+ "\nzoomAmount: " + arcball._zoomAmount);
+ };
+
+ arcball._onResetFinish = function() {
+ ok(isApproxVec(arcball._lastRot, [0, 0, 0, 1]),
+ "The arcball _lastRot field wasn't reset correctly.");
+ ok(isApproxVec(arcball._deltaRot, [0, 0, 0, 1]),
+ "The arcball _deltaRot field wasn't reset correctly.");
+ ok(isApproxVec(arcball._currentRot, [0, 0, 0, 1]),
+ "The arcball _currentRot field wasn't reset correctly.");
+
+ ok(isApproxVec(arcball._lastTrans, [0, 0, 0]),
+ "The arcball _lastTrans field wasn't reset correctly.");
+ ok(isApproxVec(arcball._deltaTrans, [0, 0, 0]),
+ "The arcball _deltaTrans field wasn't reset correctly.");
+ ok(isApproxVec(arcball._currentTrans, [0, 0, 0]),
+ "The arcball _currentTrans field wasn't reset correctly.");
+
+ ok(isApproxVec(arcball._additionalRot, [0, 0, 0]),
+ "The arcball _additionalRot field wasn't reset correctly.");
+ ok(isApproxVec(arcball._additionalTrans, [0, 0, 0]),
+ "The arcball _additionalTrans field wasn't reset correctly.");
+
+ ok(isApproxVec([arcball._zoomAmount], [0]),
+ "The arcball _zoomAmount field wasn't reset correctly.");
+
+ executeSoon(function() {
+ info("Finishing arcball reset test.");
+ callback();
+ });
+ };
+
+ EventUtils.synthesizeKey("VK_R", { type: "keydown" });
+
+ }, Math.random() * 1000); // leave enough time for transforms to happen
+ }, Math.random() * 1000);
+ }, Math.random() * 1000);
+}
+
+function cleanup() {
+ info("Cleaning up arcball reset test.");
+
+ if (tiltOpened) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_arcball-reset.js b/toolkit/devtools/tilt/test/browser_tilt_arcball-reset.js
new file mode 100644
index 000000000..11f130fdb
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_arcball-reset.js
@@ -0,0 +1,130 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tiltOpened = false;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping part of the arcball test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping part of the arcball test because WebGL isn't supported.");
+ return;
+ }
+
+ requestLongerTimeout(10);
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ tiltOpened = true;
+
+ performTest(instance.presenter.canvas,
+ instance.controller.arcball, function() {
+
+ info("Killing arcball reset test.");
+
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function performTest(canvas, arcball, callback) {
+ is(document.activeElement, canvas,
+ "The visualizer canvas should be focused when performing this test.");
+
+ info("Starting arcball reset test.");
+
+ // start translating and rotating sometime at random
+
+ window.setTimeout(function() {
+ info("Synthesizing key down events.");
+
+ EventUtils.synthesizeKey("VK_W", { type: "keydown" });
+ EventUtils.synthesizeKey("VK_LEFT", { type: "keydown" });
+
+ // wait for some arcball translations and rotations to happen
+
+ window.setTimeout(function() {
+ info("Synthesizing key up events.");
+
+ EventUtils.synthesizeKey("VK_W", { type: "keyup" });
+ EventUtils.synthesizeKey("VK_LEFT", { type: "keyup" });
+
+ // ok, transformations finished, we can now try to reset the model view
+
+ window.setTimeout(function() {
+ info("Synthesizing arcball reset key press.");
+
+ arcball._onResetStart = function() {
+ info("Starting arcball reset animation.");
+ };
+
+ arcball._onResetStep = function() {
+ info("\nlastRot: " + quat4.str(arcball._lastRot) +
+ "\ndeltaRot: " + quat4.str(arcball._deltaRot) +
+ "\ncurrentRot: " + quat4.str(arcball._currentRot) +
+ "\nlastTrans: " + vec3.str(arcball._lastTrans) +
+ "\ndeltaTrans: " + vec3.str(arcball._deltaTrans) +
+ "\ncurrentTrans: " + vec3.str(arcball._currentTrans) +
+ "\nadditionalRot: " + vec3.str(arcball._additionalRot) +
+ "\nadditionalTrans: " + vec3.str(arcball._additionalTrans) +
+ "\nzoomAmount: " + arcball._zoomAmount);
+ };
+
+ arcball._onResetFinish = function() {
+ ok(isApproxVec(arcball._lastRot, [0, 0, 0, 1]),
+ "The arcball _lastRot field wasn't reset correctly.");
+ ok(isApproxVec(arcball._deltaRot, [0, 0, 0, 1]),
+ "The arcball _deltaRot field wasn't reset correctly.");
+ ok(isApproxVec(arcball._currentRot, [0, 0, 0, 1]),
+ "The arcball _currentRot field wasn't reset correctly.");
+
+ ok(isApproxVec(arcball._lastTrans, [0, 0, 0]),
+ "The arcball _lastTrans field wasn't reset correctly.");
+ ok(isApproxVec(arcball._deltaTrans, [0, 0, 0]),
+ "The arcball _deltaTrans field wasn't reset correctly.");
+ ok(isApproxVec(arcball._currentTrans, [0, 0, 0]),
+ "The arcball _currentTrans field wasn't reset correctly.");
+
+ ok(isApproxVec(arcball._additionalRot, [0, 0, 0]),
+ "The arcball _additionalRot field wasn't reset correctly.");
+ ok(isApproxVec(arcball._additionalTrans, [0, 0, 0]),
+ "The arcball _additionalTrans field wasn't reset correctly.");
+
+ ok(isApproxVec([arcball._zoomAmount], [0]),
+ "The arcball _zoomAmount field wasn't reset correctly.");
+
+ executeSoon(function() {
+ info("Finishing arcball reset test.");
+ callback();
+ });
+ };
+
+ EventUtils.synthesizeKey("VK_R", { type: "keydown" });
+
+ }, Math.random() * 1000); // leave enough time for transforms to happen
+ }, Math.random() * 1000);
+ }, Math.random() * 1000);
+}
+
+function cleanup() {
+ info("Cleaning up arcball reset test.");
+
+ if (tiltOpened) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_arcball.js b/toolkit/devtools/tilt/test/browser_tilt_arcball.js
new file mode 100644
index 000000000..3d1078e1b
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_arcball.js
@@ -0,0 +1,496 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function cloneUpdate(update) {
+ return {
+ rotation: quat4.create(update.rotation),
+ translation: vec3.create(update.translation)
+ };
+}
+
+function isExpectedUpdate(update1, update2) {
+ if (update1.length !== update2.length) {
+ return false;
+ }
+ for (let i = 0, len = update1.length; i < len; i++) {
+ if (!isApproxVec(update1[i].rotation, update2[i].rotation) ||
+ !isApproxVec(update1[i].translation, update2[i].translation)) {
+ info("isExpectedUpdate expected " + JSON.stringify(update1), ", got " +
+ JSON.stringify(update2) + " instead.");
+ return false;
+ }
+ }
+ return true;
+}
+
+function test() {
+ let arcball1 = new TiltVisualizer.Arcball(window, 123, 456);
+
+ is(arcball1.width, 123,
+ "The first arcball width wasn't set correctly.");
+ is(arcball1.height, 456,
+ "The first arcball height wasn't set correctly.");
+ is(arcball1.radius, 123,
+ "The first arcball radius wasn't implicitly set correctly.");
+
+
+ let arcball2 = new TiltVisualizer.Arcball(window, 987, 654);
+
+ is(arcball2.width, 987,
+ "The second arcball width wasn't set correctly.");
+ is(arcball2.height, 654,
+ "The second arcball height wasn't set correctly.");
+ is(arcball2.radius, 654,
+ "The second arcball radius wasn't implicitly set correctly.");
+
+
+ let arcball3 = new TiltVisualizer.Arcball(window, 512, 512);
+
+ let sphereVec = vec3.create();
+ arcball3._pointToSphere(123, 456, 256, 512, 512, sphereVec);
+
+ ok(isApproxVec(sphereVec, [-0.009765625, 0.390625, 0.9204980731010437]),
+ "The _pointToSphere() function didn't map the coordinates correctly.");
+
+ let stack1 = [];
+ let expect1 = [
+ { rotation: [
+ -0.08877250552177429, 0.0242881178855896,
+ -0.04222869873046875, -0.9948599338531494],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.13086390495300293, 0.03413732722401619,
+ -0.06334304809570312, -0.9887855648994446],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.15138940513134003, 0.03854173421859741,
+ -0.07390022277832031, -0.9849540591239929],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.1615273654460907, 0.040619146078825,
+ -0.0791788101196289, -0.9828477501869202],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.16656573116779327, 0.04162723943591118,
+ -0.0818181037902832, -0.9817478656768799],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.16907735168933868, 0.042123712599277496,
+ -0.08313775062561035, -0.9811863303184509],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17033125460147858, 0.042370058596134186,
+ -0.08379757404327393, -0.9809026718139648],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17095772922039032, 0.04249274358153343,
+ -0.08412748575210571, -0.9807600975036621],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17127084732055664, 0.04255397245287895,
+ -0.0842924416065216, -0.9806886315345764],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.171427384018898, 0.042584557086229324,
+ -0.08437491953372955, -0.9806528687477112],
+ translation: [0, 0, 0] }];
+
+ arcball3.mouseDown(10, 10, 1);
+ arcball3.mouseMove(10, 100);
+ for (let i1 = 0; i1 < 10; i1++) {
+ stack1.push(cloneUpdate(arcball3.update()));
+ }
+
+ ok(isExpectedUpdate(stack1, expect1),
+ "Mouse down & move events didn't create the expected transform. results.");
+
+ let stack2 = [];
+ let expect2 = [
+ { rotation: [
+ -0.1684110015630722, 0.04199237748980522,
+ -0.0827873945236206, -0.9813361167907715],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.16936375200748444, 0.04218007251620293,
+ -0.08328840136528015, -0.9811217188835144],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17003019154071808, 0.04231100529432297,
+ -0.08363909274339676, -0.9809709787368774],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17049652338027954, 0.042402446269989014,
+ -0.0838845893740654, -0.9808651208877563],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17082282900810242, 0.042466338723897934,
+ -0.08405643701553345, -0.9807908535003662],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17105120420455933, 0.04251104220747948,
+ -0.08417671173810959, -0.9807388186454773],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17121103405952454, 0.04254228621721268,
+ -0.08426092565059662, -0.9807023406028748],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17132291197776794, 0.042564138770103455,
+ -0.08431987464427948, -0.9806767106056213],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.1714012324810028, 0.04257945716381073,
+ -0.08436112850904465, -0.9806588888168335],
+ translation: [0, 0, 0] },
+ { rotation: [
+ -0.17145603895187378, 0.042590171098709106,
+ -0.08439001441001892, -0.9806463718414307],
+ translation: [0, 0, 0] }];
+
+ arcball3.mouseUp(100, 100);
+ for (let i2 = 0; i2 < 10; i2++) {
+ stack2.push(cloneUpdate(arcball3.update()));
+ }
+
+ ok(isExpectedUpdate(stack2, expect2),
+ "Mouse up events didn't create the expected transformation results.");
+
+ let stack3 = [];
+ let expect3 = [
+ { rotation: [
+ -0.17149439454078674, 0.04259764403104782,
+ -0.08441022783517838, -0.9806375503540039],
+ translation: [0, 0, -1] },
+ { rotation: [
+ -0.17152123153209686, 0.04260288551449776,
+ -0.08442437648773193, -0.980631411075592],
+ translation: [0, 0, -1.899999976158142] },
+ { rotation: [
+ -0.1715400665998459, 0.04260658100247383,
+ -0.08443428575992584, -0.9806271195411682],
+ translation: [0, 0, -2.7100000381469727] },
+ { rotation: [
+ -0.17155319452285767, 0.04260912910103798,
+ -0.08444121479988098, -0.9806240797042847],
+ translation: [0, 0, -3.439000129699707] },
+ { rotation: [
+ -0.17156240344047546, 0.042610932141542435,
+ -0.08444607257843018, -0.9806219935417175],
+ translation: [0, 0, -4.095099925994873] },
+ { rotation: [
+ -0.1715688556432724, 0.042612191289663315,
+ -0.08444946259260178, -0.9806205034255981],
+ translation: [0, 0, -4.685589790344238] },
+ { rotation: [
+ -0.17157337069511414, 0.04261308163404465,
+ -0.0844518393278122, -0.980619490146637],
+ translation: [0, 0, -5.217031002044678] },
+ { rotation: [
+ -0.17157652974128723, 0.0426136814057827,
+ -0.0844535157084465, -0.9806187748908997],
+ translation: [0, 0, -5.6953277587890625] },
+ { rotation: [
+ -0.17157875001430511, 0.04261413961648941,
+ -0.08445467799901962, -0.9806182980537415],
+ translation: [0, 0, -6.125794887542725] },
+ { rotation: [
+ -0.17158031463623047, 0.04261442646384239,
+ -0.08445550501346588, -0.980617880821228],
+ translation: [0, 0, -6.5132155418396] }];
+
+ arcball3.zoom(10);
+ for (let i3 = 0; i3 < 10; i3++) {
+ stack3.push(cloneUpdate(arcball3.update()));
+ }
+
+ ok(isExpectedUpdate(stack3, expect3),
+ "Mouse zoom events didn't create the expected transformation results.");
+
+ let stack4 = [];
+ let expect4 = [
+ { rotation: [
+ -0.17158135771751404, 0.04261462762951851,
+ -0.08445606380701065, -0.9806176424026489],
+ translation: [0, 0, -6.861894130706787] },
+ { rotation: [
+ -0.1715821474790573, 0.04261479899287224,
+ -0.08445646613836288, -0.9806175231933594],
+ translation: [0, 0, -7.1757049560546875] },
+ { rotation: [
+ -0.1715826541185379, 0.0426148846745491,
+ -0.08445674180984497, -0.980617344379425],
+ translation: [0, 0, -7.458134651184082] },
+ { rotation: [
+ -0.17158304154872894, 0.04261497035622597,
+ -0.08445693552494049, -0.9806172847747803],
+ translation: [0, 0, -7.7123212814331055] },
+ { rotation: [
+ -0.17158329486846924, 0.042615000158548355,
+ -0.08445708453655243, -0.9806172251701355],
+ translation: [0, 0, -7.941089153289795] },
+ { rotation: [
+ -0.17158347368240356, 0.04261505603790283,
+ -0.084457166492939, -0.9806172251701355],
+ translation: [0, 0, -8.146980285644531] },
+ { rotation: [
+ -0.1715836226940155, 0.04261508584022522,
+ -0.08445724099874496, -0.9806171655654907],
+ translation: [0, 0, -8.332282066345215] },
+ { rotation: [
+ -0.17158368229866028, 0.04261508584022522,
+ -0.08445728570222855, -0.980617105960846],
+ translation: [0, 0, -8.499053955078125] },
+ { rotation: [
+ -0.17158377170562744, 0.04261511191725731,
+ -0.08445732295513153, -0.980617105960846],
+ translation: [0, 0, -8.649148941040039] },
+ { rotation: [
+ -0.17158380150794983, 0.04261511191725731,
+ -0.08445733785629272, -0.980617105960846],
+ translation: [0, 0, -8.784234046936035] }];
+
+ arcball3.keyDown(arcball3.rotateKeys.left);
+ arcball3.keyDown(arcball3.rotateKeys.right);
+ arcball3.keyDown(arcball3.rotateKeys.up);
+ arcball3.keyDown(arcball3.rotateKeys.down);
+ arcball3.keyDown(arcball3.panKeys.left);
+ arcball3.keyDown(arcball3.panKeys.right);
+ arcball3.keyDown(arcball3.panKeys.up);
+ arcball3.keyDown(arcball3.panKeys.down);
+ for (let i4 = 0; i4 < 10; i4++) {
+ stack4.push(cloneUpdate(arcball3.update()));
+ }
+
+ ok(isExpectedUpdate(stack4, expect4),
+ "Key down events didn't create the expected transformation results.");
+
+ let stack5 = [];
+ let expect5 = [
+ { rotation: [
+ -0.1715838462114334, 0.04261511191725731,
+ -0.08445736765861511, -0.980617105960846],
+ translation: [0, 0, -8.905810356140137] },
+ { rotation: [
+ -0.1715838462114334, 0.04261511191725731,
+ -0.08445736765861511, -0.980617105960846],
+ translation: [0, 0, -9.015229225158691] },
+ { rotation: [
+ -0.1715838462114334, 0.04261511191725731,
+ -0.08445736765861511, -0.980617105960846],
+ translation: [0, 0, -9.113706588745117] },
+ { rotation: [
+ -0.1715838611125946, 0.04261511191725731,
+ -0.0844573825597763, -0.9806170463562012],
+ translation: [0, 0, -9.202336311340332] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -9.282102584838867] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -9.35389232635498] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -9.418502807617188] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -9.476652145385742] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -9.528986930847168] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -9.576087951660156] }];
+
+ arcball3.keyUp(arcball3.rotateKeys.left);
+ arcball3.keyUp(arcball3.rotateKeys.right);
+ arcball3.keyUp(arcball3.rotateKeys.up);
+ arcball3.keyUp(arcball3.rotateKeys.down);
+ arcball3.keyUp(arcball3.panKeys.left);
+ arcball3.keyUp(arcball3.panKeys.right);
+ arcball3.keyUp(arcball3.panKeys.up);
+ arcball3.keyUp(arcball3.panKeys.down);
+ for (let i5 = 0; i5 < 10; i5++) {
+ stack5.push(cloneUpdate(arcball3.update()));
+ }
+
+ ok(isExpectedUpdate(stack5, expect5),
+ "Key up events didn't create the expected transformation results.");
+
+ let stack6 = [];
+ let expect6 = [
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -9.618478775024414] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, -6.156630992889404] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 0.4590320587158203] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 9.913128852844238] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 21.921815872192383] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 36.22963333129883] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 52.60667037963867] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 70.84600067138672] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 90.76139831542969] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 112.18525695800781] }];
+
+ arcball3.keyDown(arcball3.zoomKeys["in"][0]);
+ arcball3.keyDown(arcball3.zoomKeys["in"][1]);
+ arcball3.keyDown(arcball3.zoomKeys["in"][2]);
+ for (let i6 = 0; i6 < 10; i6++) {
+ stack6.push(cloneUpdate(arcball3.update()));
+ }
+ arcball3.keyUp(arcball3.zoomKeys["in"][0]);
+ arcball3.keyUp(arcball3.zoomKeys["in"][1]);
+ arcball3.keyUp(arcball3.zoomKeys["in"][2]);
+
+ ok(isExpectedUpdate(stack6, expect6),
+ "Key zoom in events didn't create the expected transformation results.");
+
+ let stack7 = [];
+ let expect7 = [
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 134.96673583984375] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 151.97006225585938] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 163.77305603027344] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 170.895751953125] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 173.80618286132812] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 172.92556762695312] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 168.6330108642578] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 161.26971435546875] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 151.1427459716797] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 138.52847290039062] }];
+
+ arcball3.keyDown(arcball3.zoomKeys["out"][0]);
+ arcball3.keyDown(arcball3.zoomKeys["out"][1]);
+ for (let i7 = 0; i7 < 10; i7++) {
+ stack7.push(cloneUpdate(arcball3.update()));
+ }
+ arcball3.keyUp(arcball3.zoomKeys["out"][0]);
+ arcball3.keyUp(arcball3.zoomKeys["out"][1]);
+
+ ok(isExpectedUpdate(stack7, expect7),
+ "Key zoom out events didn't create the expected transformation results.");
+
+ let stack8 = [];
+ let expect8 = [
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 123.67562866210938] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 111.30806732177734] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 100.17726135253906] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 90.15953826904297] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 81.14358520507812] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 73.02922821044922] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 65.72630310058594] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 59.15367126464844] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 53.238304138183594] },
+ { rotation: [
+ -0.17158392071723938, 0.0426151417195797,
+ -0.0844573974609375, -0.980617105960846],
+ translation: [0, 0, 47.91447448730469] }];
+
+ arcball3.keyDown(arcball3.zoomKeys["unzoom"]);
+ for (let i8 = 0; i8 < 10; i8++) {
+ stack8.push(cloneUpdate(arcball3.update()));
+ }
+ arcball3.keyUp(arcball3.zoomKeys["unzoom"]);
+
+ ok(isExpectedUpdate(stack8, expect8),
+ "Key zoom reset events didn't create the expected transformation results.");
+
+
+ arcball3.resize(123, 456);
+ is(arcball3.width, 123,
+ "The third arcball width wasn't updated correctly.");
+ is(arcball3.height, 456,
+ "The third arcball height wasn't updated correctly.");
+ is(arcball3.radius, 123,
+ "The third arcball radius wasn't implicitly updated correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_controller.js b/toolkit/devtools/tilt/test/browser_tilt_controller.js
new file mode 100644
index 000000000..282b42903
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_controller.js
@@ -0,0 +1,138 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping controller test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping controller test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ let canvas = instance.presenter.canvas;
+ let prev_tran = vec3.create([0, 0, 0]);
+ let prev_rot = quat4.create([0, 0, 0, 1]);
+
+ function tran() {
+ return instance.presenter.transforms.translation;
+ }
+
+ function rot() {
+ return instance.presenter.transforms.rotation;
+ }
+
+ function save() {
+ prev_tran = vec3.create(tran());
+ prev_rot = quat4.create(rot());
+ }
+
+ ok(isEqualVec(tran(), prev_tran),
+ "At init, the translation should be zero.");
+ ok(isEqualVec(rot(), prev_rot),
+ "At init, the rotation should be zero.");
+
+ function testEventCancel(cancellingEvent, cancellingDescription) {
+ let description = "testEventCancel, cancellingEvent is " + cancellingDescription + ": ";
+ is(document.activeElement, canvas,
+ description + "The visualizer canvas should be focused when performing this test.");
+
+ EventUtils.synthesizeKey("a", { type: "keydown", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A });
+ instance.controller._update();
+ ok(!isEqualVec(rot(), prev_rot),
+ description + "After a rotation key is pressed, the quaternion should change.");
+ EventUtils.synthesizeKey("a", { type: "keyup", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A });
+
+ EventUtils.synthesizeKey("ArrowLeft", { type: "keydown", code: "ArrowLeft", keyCode: KeyboardEvent.DOM_VK_LEFT });
+ instance.controller._update();
+ ok(!isEqualVec(tran(), prev_tran),
+ description + "After a translation key is pressed, the vector should change.");
+ EventUtils.synthesizeKey("ArrowLeft", { type: "keyup", code: "ArrowLeft", keyCode: KeyboardEvent.DOM_VK_LEFT });
+
+ save();
+
+
+ cancellingEvent();
+ instance.controller._update();
+
+ ok(!isEqualVec(tran(), prev_tran),
+ description + "Even if the canvas lost focus, the vector has some inertia.");
+ ok(!isEqualVec(rot(), prev_rot),
+ description + "Even if the canvas lost focus, the quaternion has some inertia.");
+
+ save();
+
+
+ while (!isEqualVec(tran(), prev_tran) ||
+ !isEqualVec(rot(), prev_rot)) {
+ instance.controller._update();
+ save();
+ }
+
+ ok(isEqualVec(tran(), prev_tran) && isEqualVec(rot(), prev_rot),
+ "After focus lost, the transforms inertia eventually stops.");
+ }
+
+ info("Setting typeaheadfind to true.");
+
+ let typeaheadfindEnabled = true;
+ Services.prefs.setBoolPref("accessibility.typeaheadfind", typeaheadfindEnabled);
+ for (var i = 0; i < 2; i++) {
+ testEventCancel(function() {
+ // XXX Don't use a character which is registered as a mnemonic in the menubar.
+ EventUtils.synthesizeKey("A", { altKey: true, code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A });
+ }, "Alt + A");
+ testEventCancel(function() {
+ // XXX Don't use a character which is registered as a shortcut key.
+ EventUtils.synthesizeKey(";", { ctrlKey: true, code: "Semicolon", keyCode: KeyboardEvent.DOM_VK_SEMICONLON });
+ }, "Ctrl + ;");
+ testEventCancel(function() {
+ // XXX Don't use a character which is registered as a shortcut key.
+ EventUtils.synthesizeKey("\\", { metaKey: true, code: "Backslash", keyCode: KeyboardEvent.DOM_VK_BACK_SLASH });
+ }, "Meta + \\");
+ // If typeahead is enabled, Shift + T causes moving focus to the findbar because it inputs "T".
+ if (!typeaheadfindEnabled) {
+ testEventCancel(function() {
+ EventUtils.synthesizeKey("T", { shiftKey: true, code: "KeyT", keyCode: KeyboardEvent.DOM_VK_T });
+ }, "Shift + T");
+ }
+
+ // Retry after disabling typeaheadfind.
+ info("Setting typeaheadfind to false.");
+
+ typeaheadfindEnabled = false;
+ Services.prefs.setBoolPref("accessibility.typeaheadfind", typeaheadfindEnabled);
+ }
+
+ info("Testing if loosing focus halts any stacked arcball animations.");
+
+ testEventCancel(function() {
+ gBrowser.selectedBrowser.contentWindow.focus();
+ }, "setting focus to the content window");
+ },
+ onEnd: function()
+ {
+ cleanup();
+ }
+ }, true, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function cleanup() {
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl01.js b/toolkit/devtools/tilt/test/browser_tilt_gl01.js
new file mode 100644
index 000000000..d42471726
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl01.js
@@ -0,0 +1,157 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl01 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ ok(renderer,
+ "The TiltGL.Renderer constructor should have initialized a new object.");
+
+ ok(gl instanceof WebGLRenderingContext,
+ "The renderer context wasn't created correctly from the passed canvas.");
+
+
+ let clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE),
+ clearDepth = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
+
+ is(clearColor[0], 0,
+ "The default red clear color wasn't set correctly at initialization.");
+ is(clearColor[1], 0,
+ "The default green clear color wasn't set correctly at initialization.");
+ is(clearColor[2], 0,
+ "The default blue clear color wasn't set correctly at initialization.");
+ is(clearColor[3], 0,
+ "The default alpha clear color wasn't set correctly at initialization.");
+ is(clearDepth, 1,
+ "The default clear depth wasn't set correctly at initialization.");
+
+ is(renderer.width, canvas.width,
+ "The renderer width wasn't set correctly from the passed canvas.");
+ is(renderer.height, canvas.height,
+ "The renderer height wasn't set correctly from the passed canvas.");
+
+ ok(renderer.mvMatrix,
+ "The model view matrix wasn't initialized properly.");
+ ok(renderer.projMatrix,
+ "The model view matrix wasn't initialized properly.");
+
+ ok(isApproxVec(renderer._fillColor, [1, 1, 1, 1]),
+ "The default fill color wasn't set correctly.");
+ ok(isApproxVec(renderer._strokeColor, [0, 0, 0, 1]),
+ "The default stroke color wasn't set correctly.");
+ is(renderer._strokeWeightValue, 1,
+ "The default stroke weight wasn't set correctly.");
+
+ ok(renderer._colorShader,
+ "A default color shader should have been created.");
+
+ ok(typeof renderer.Program, "function",
+ "At init, the renderer should have created a Program constructor.");
+ ok(typeof renderer.VertexBuffer, "function",
+ "At init, the renderer should have created a VertexBuffer constructor.");
+ ok(typeof renderer.IndexBuffer, "function",
+ "At init, the renderer should have created a IndexBuffer constructor.");
+ ok(typeof renderer.Texture, "function",
+ "At init, the renderer should have created a Texture constructor.");
+
+ renderer.depthTest(true);
+ is(gl.getParameter(gl.DEPTH_TEST), true,
+ "The depth test wasn't enabled when requested.");
+
+ renderer.depthTest(false);
+ is(gl.getParameter(gl.DEPTH_TEST), false,
+ "The depth test wasn't disabled when requested.");
+
+ renderer.stencilTest(true);
+ is(gl.getParameter(gl.STENCIL_TEST), true,
+ "The stencil test wasn't enabled when requested.");
+
+ renderer.stencilTest(false);
+ is(gl.getParameter(gl.STENCIL_TEST), false,
+ "The stencil test wasn't disabled when requested.");
+
+ renderer.cullFace("front");
+ is(gl.getParameter(gl.CULL_FACE), true,
+ "The cull face wasn't enabled when requested.");
+ is(gl.getParameter(gl.CULL_FACE_MODE), gl.FRONT,
+ "The cull face front mode wasn't set correctly.");
+
+ renderer.cullFace("back");
+ is(gl.getParameter(gl.CULL_FACE), true,
+ "The cull face wasn't enabled when requested.");
+ is(gl.getParameter(gl.CULL_FACE_MODE), gl.BACK,
+ "The cull face back mode wasn't set correctly.");
+
+ renderer.cullFace("both");
+ is(gl.getParameter(gl.CULL_FACE), true,
+ "The cull face wasn't enabled when requested.");
+ is(gl.getParameter(gl.CULL_FACE_MODE), gl.FRONT_AND_BACK,
+ "The cull face back mode wasn't set correctly.");
+
+ renderer.cullFace(false);
+ is(gl.getParameter(gl.CULL_FACE), false,
+ "The cull face wasn't disabled when requested.");
+
+ renderer.frontFace("cw");
+ is(gl.getParameter(gl.FRONT_FACE), gl.CW,
+ "The front face cw mode wasn't set correctly.");
+
+ renderer.frontFace("ccw");
+ is(gl.getParameter(gl.FRONT_FACE), gl.CCW,
+ "The front face ccw mode wasn't set correctly.");
+
+ renderer.blendMode("alpha");
+ is(gl.getParameter(gl.BLEND), true,
+ "The blend mode wasn't enabled when requested.");
+ is(gl.getParameter(gl.BLEND_SRC_ALPHA), gl.SRC_ALPHA,
+ "The soruce blend func wasn't set correctly.");
+ is(gl.getParameter(gl.BLEND_DST_ALPHA), gl.ONE_MINUS_SRC_ALPHA,
+ "The destination blend func wasn't set correctly.");
+
+ renderer.blendMode("add");
+ is(gl.getParameter(gl.BLEND), true,
+ "The blend mode wasn't enabled when requested.");
+ is(gl.getParameter(gl.BLEND_SRC_ALPHA), gl.SRC_ALPHA,
+ "The soruce blend func wasn't set correctly.");
+ is(gl.getParameter(gl.BLEND_DST_ALPHA), gl.ONE,
+ "The destination blend func wasn't set correctly.");
+
+ renderer.blendMode(false);
+ is(gl.getParameter(gl.CULL_FACE), false,
+ "The blend mode wasn't disabled when requested.");
+
+
+ is(gl.getParameter(gl.CURRENT_PROGRAM), null,
+ "No program should be initially set in the WebGL context.");
+
+ renderer.useColorShader(new renderer.VertexBuffer([1, 2, 3], 3));
+
+ ok(gl.getParameter(gl.CURRENT_PROGRAM) instanceof WebGLProgram,
+ "The correct program hasn't been set in the WebGL context.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl02.js b/toolkit/devtools/tilt/test/browser_tilt_gl02.js
new file mode 100644
index 000000000..b885e3f8e
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl02.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl02 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ renderer.fill([1, 0, 0, 1]);
+ ok(isApproxVec(renderer._fillColor, [1, 0, 0, 1]),
+ "The fill color wasn't set correctly.");
+
+ renderer.stroke([0, 1, 0, 1]);
+ ok(isApproxVec(renderer._strokeColor, [0, 1, 0, 1]),
+ "The stroke color wasn't set correctly.");
+
+ renderer.strokeWeight(2);
+ is(renderer._strokeWeightValue, 2,
+ "The stroke weight wasn't set correctly.");
+ is(gl.getParameter(gl.LINE_WIDTH), 2,
+ "The stroke weight wasn't applied correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl03.js b/toolkit/devtools/tilt/test/browser_tilt_gl03.js
new file mode 100644
index 000000000..509eb1182
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl03.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl03 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ renderer.defaults();
+ is(gl.getParameter(gl.DEPTH_TEST), true,
+ "The depth test wasn't set to the correct default value.");
+ is(gl.getParameter(gl.STENCIL_TEST), false,
+ "The stencil test wasn't set to the correct default value.");
+ is(gl.getParameter(gl.CULL_FACE), false,
+ "The cull face wasn't set to the correct default value.");
+ is(gl.getParameter(gl.FRONT_FACE), gl.CCW,
+ "The front face wasn't set to the correct default value.");
+ is(gl.getParameter(gl.BLEND), true,
+ "The blend mode wasn't set to the correct default value.");
+ is(gl.getParameter(gl.BLEND_SRC_ALPHA), gl.SRC_ALPHA,
+ "The soruce blend func wasn't set to the correct default value.");
+ is(gl.getParameter(gl.BLEND_DST_ALPHA), gl.ONE_MINUS_SRC_ALPHA,
+ "The destination blend func wasn't set to the correct default value.");
+
+
+ ok(isApproxVec(renderer._fillColor, [1, 1, 1, 1]),
+ "The fill color wasn't set to the correct default value.");
+ ok(isApproxVec(renderer._strokeColor, [0, 0, 0, 1]),
+ "The stroke color wasn't set to the correct default value.");
+ is(renderer._strokeWeightValue, 1,
+ "The stroke weight wasn't set to the correct default value.");
+ is(gl.getParameter(gl.LINE_WIDTH), 1,
+ "The stroke weight wasn't applied with the correct default value.");
+
+
+ ok(isApproxVec(renderer.projMatrix, [
+ 1.2071068286895752, 0, 0, 0, 0, -2.4142136573791504, 0, 0, 0, 0,
+ -1.0202020406723022, -1, -181.06602478027344, 181.06602478027344,
+ 148.14492797851562, 181.06602478027344
+ ]), "The default perspective projection matrix wasn't set correctly.");
+
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
+ ]), "The default model view matrix wasn't set correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl04.js b/toolkit/devtools/tilt/test/browser_tilt_gl04.js
new file mode 100644
index 000000000..8136c5c23
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl04.js
@@ -0,0 +1,126 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl04 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ renderer.perspective();
+ ok(isApproxVec(renderer.projMatrix, [
+ 1.2071068286895752, 0, 0, 0, 0, -2.4142136573791504, 0, 0, 0, 0,
+ -1.0202020406723022, -1, -181.06602478027344, 181.06602478027344,
+ 148.14492797851562, 181.06602478027344
+ ]), "The default perspective proj. matrix wasn't calculated correctly.");
+
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
+ ]), "Changing the perpective matrix should reset the modelview by default.");
+
+
+ renderer.ortho();
+ ok(isApproxVec(renderer.projMatrix, [
+ 0.006666666828095913, 0, 0, 0, 0, -0.013333333656191826, 0, 0, 0, 0, -1,
+ 0, -1, 1, 0, 1
+ ]), "The default ortho proj. matrix wasn't calculated correctly.");
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
+ ]), "Changing the ortho matrix should reset the modelview by default.");
+
+
+ renderer.projection(mat4.perspective(45, 1, 0.1, 100));
+ ok(isApproxVec(renderer.projMatrix, [
+ 2.4142136573791504, 0, 0, 0, 0, 2.4142136573791504, 0, 0, 0, 0,
+ -1.0020020008087158, -1, 0, 0, -0.20020020008087158, 0
+ ]), "A custom proj. matrix couldn't be set correctly.");
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
+ ]), "Setting a custom proj. matrix should reset the model view by default.");
+
+
+ renderer.translate(1, 1, 1);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1
+ ]), "The translation transformation wasn't applied correctly.");
+
+ renderer.rotate(0.5, 1, 1, 1);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 0.9183883666992188, 0.317602276802063, -0.23599065840244293, 0,
+ -0.23599065840244293, 0.9183883666992188, 0.317602276802063, 0,
+ 0.317602276802063, -0.23599065840244293, 0.9183883666992188, 0, 1, 1, 1, 1
+ ]), "The rotation transformation wasn't applied correctly.");
+
+ renderer.rotateX(0.5);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 0.9183883666992188, 0.317602276802063, -0.23599065840244293, 0,
+ -0.05483464524149895, 0.6928216814994812, 0.7190210819244385, 0,
+ 0.391862154006958, -0.6474001407623291, 0.6536949872970581, 0, 1, 1, 1, 1
+ ]), "The X rotation transformation wasn't applied correctly.");
+
+ renderer.rotateY(0.5);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 0.6180928945541382, 0.5891023874282837, -0.5204993486404419, 0,
+ -0.05483464524149895, 0.6928216814994812, 0.7190210819244385, 0,
+ 0.7841902375221252, -0.4158804416656494, 0.4605313837528229, 0, 1, 1, 1, 1
+ ]), "The Y rotation transformation wasn't applied correctly.");
+
+ renderer.rotateZ(0.5);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 0.5161384344100952, 0.8491423726081848, -0.11206408590078354, 0,
+ -0.3444514572620392, 0.3255774974822998, 0.8805410265922546, 0,
+ 0.7841902375221252, -0.4158804416656494, 0.4605313837528229, 0, 1, 1, 1, 1
+ ]), "The Z rotation transformation wasn't applied correctly.");
+
+ renderer.scale(2, 2, 2);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1.0322768688201904, 1.6982847452163696, -0.22412817180156708, 0,
+ -0.6889029145240784, 0.6511549949645996, 1.7610820531845093, 0,
+ 1.5683804750442505, -0.8317608833312988, 0.9210627675056458, 0, 1, 1, 1, 1
+ ]), "The Z rotation transformation wasn't applied correctly.");
+
+ renderer.transform(mat4.create());
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1.0322768688201904, 1.6982847452163696, -0.22412817180156708, 0,
+ -0.6889029145240784, 0.6511549949645996, 1.7610820531845093, 0,
+ 1.5683804750442505, -0.8317608833312988, 0.9210627675056458, 0, 1, 1, 1, 1
+ ]), "The identity matrix transformation wasn't applied correctly.");
+
+ renderer.origin(1, 1, 1);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
+ ]), "The origin wasn't reset to identity correctly.");
+
+ renderer.translate(1, 2);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 0, 1
+ ]), "The second translation transformation wasn't applied correctly.");
+
+ renderer.scale(3, 4);
+ ok(isApproxVec(renderer.mvMatrix, [
+ 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1, 0, 1, 2, 0, 1
+ ]), "The second scale transformation wasn't applied correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl05.js b/toolkit/devtools/tilt/test/browser_tilt_gl05.js
new file mode 100644
index 000000000..6432ec3e6
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl05.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl05 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ let mesh = {
+ vertices: new renderer.VertexBuffer([1, 2, 3], 3),
+ indices: new renderer.IndexBuffer([1]),
+ };
+
+ ok(mesh.vertices instanceof TiltGL.VertexBuffer,
+ "The mesh vertices weren't saved at initialization.");
+ ok(mesh.indices instanceof TiltGL.IndexBuffer,
+ "The mesh indices weren't saved at initialization.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl06.js b/toolkit/devtools/tilt/test/browser_tilt_gl06.js
new file mode 100644
index 000000000..7a0080eb1
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl06.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl06 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ let vb = new renderer.VertexBuffer([1, 2, 3, 4, 5, 6], 3);
+
+ ok(vb instanceof TiltGL.VertexBuffer,
+ "The vertex buffer object wasn't instantiated correctly.");
+ ok(vb._ref,
+ "The vertex buffer gl element wasn't created at initialization.");
+ ok(vb.components,
+ "The vertex buffer components weren't created at initialization.");
+ is(vb.itemSize, 3,
+ "The vertex buffer item size isn't set correctly.");
+ is(vb.numItems, 2,
+ "The vertex buffer number of items weren't calculated correctly.");
+
+
+ let ib = new renderer.IndexBuffer([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+
+ ok(ib instanceof TiltGL.IndexBuffer,
+ "The index buffer object wasn't instantiated correctly.");
+ ok(ib._ref,
+ "The index buffer gl element wasn't created at initialization.");
+ ok(ib.components,
+ "The index buffer components weren't created at initialization.");
+ is(ib.itemSize, 1,
+ "The index buffer item size isn't set correctly.");
+ is(ib.numItems, 10,
+ "The index buffer number of items weren't calculated correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl07.js b/toolkit/devtools/tilt/test/browser_tilt_gl07.js
new file mode 100644
index 000000000..17ff9b91e
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl07.js
@@ -0,0 +1,60 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl07 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ let p = new renderer.Program({
+ vs: TiltGL.ColorShader.vs,
+ fs: TiltGL.ColorShader.fs,
+ attributes: ["vertexPosition"],
+ uniforms: ["mvMatrix", "projMatrix", "fill"]
+ });
+
+ ok(p instanceof TiltGL.Program,
+ "The program object wasn't instantiated correctly.");
+
+ ok(p._ref,
+ "The program WebGL object wasn't created properly.");
+ isnot(p._id, -1,
+ "The program id wasn't set properly.");
+ ok(p._attributes,
+ "The program attributes cache wasn't created properly.");
+ ok(p._uniforms,
+ "The program uniforms cache wasn't created properly.");
+
+ is(typeof p._attributes.vertexPosition, "number",
+ "The vertexPosition attribute wasn't cached as it should.");
+ is(typeof p._uniforms.mvMatrix, "object",
+ "The mvMatrix uniform wasn't cached as it should.");
+ is(typeof p._uniforms.projMatrix, "object",
+ "The projMatrix uniform wasn't cached as it should.");
+ is(typeof p._uniforms.fill, "object",
+ "The fill uniform wasn't cached as it should.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_gl08.js b/toolkit/devtools/tilt/test/browser_tilt_gl08.js
new file mode 100644
index 000000000..936de6f24
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_gl08.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let isWebGLAvailable;
+
+function onWebGLFail() {
+ isWebGLAvailable = false;
+}
+
+function onWebGLSuccess() {
+ isWebGLAvailable = true;
+}
+
+function test() {
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping tilt_gl08 because WebGL isn't supported on this hardware.");
+ return;
+ }
+
+ let canvas = createCanvas();
+
+ let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
+ let gl = renderer.context;
+
+ if (!isWebGLAvailable) {
+ aborting();
+ return;
+ }
+
+
+ let t = new renderer.Texture({
+ source: canvas,
+ format: "RGB"
+ });
+
+ ok(t instanceof TiltGL.Texture,
+ "The texture object wasn't instantiated correctly.");
+
+ ok(t._ref,
+ "The texture WebGL object wasn't created properly.");
+ isnot(t._id, -1,
+ "The texture id wasn't set properly.");
+ isnot(t.width, -1,
+ "The texture width wasn't set properly.");
+ isnot(t.height, -1,
+ "The texture height wasn't set properly.");
+ ok(t.loaded,
+ "The texture loaded flag wasn't set to true as it should.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_math01.js b/toolkit/devtools/tilt/test/browser_tilt_math01.js
new file mode 100644
index 000000000..da9e23285
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_math01.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ ok(isApprox(TiltMath.radians(30), 0.523598775),
+ "The radians() function didn't calculate the value correctly.");
+
+ ok(isApprox(TiltMath.degrees(0.5), 28.64788975),
+ "The degrees() function didn't calculate the value correctly.");
+
+ ok(isApprox(TiltMath.map(0.5, 0, 1, 0, 100), 50),
+ "The map() function didn't calculate the value correctly.");
+
+ is(TiltMath.isPowerOfTwo(32), true,
+ "The isPowerOfTwo() function didn't return the expected value.");
+
+ is(TiltMath.isPowerOfTwo(33), false,
+ "The isPowerOfTwo() function didn't return the expected value.");
+
+ ok(isApprox(TiltMath.nextPowerOfTwo(31), 32),
+ "The nextPowerOfTwo() function didn't calculate the 1st value correctly.");
+
+ ok(isApprox(TiltMath.nextPowerOfTwo(32), 32),
+ "The nextPowerOfTwo() function didn't calculate the 2nd value correctly.");
+
+ ok(isApprox(TiltMath.nextPowerOfTwo(33), 64),
+ "The nextPowerOfTwo() function didn't calculate the 3rd value correctly.");
+
+ ok(isApprox(TiltMath.clamp(5, 1, 3), 3),
+ "The clamp() function didn't calculate the 1st value correctly.");
+
+ ok(isApprox(TiltMath.clamp(5, 3, 1), 3),
+ "The clamp() function didn't calculate the 2nd value correctly.");
+
+ ok(isApprox(TiltMath.saturate(5), 1),
+ "The saturate() function didn't calculate the 1st value correctly.");
+
+ ok(isApprox(TiltMath.saturate(-5), 0),
+ "The saturate() function didn't calculate the 2nd value correctly.");
+
+ ok(isApproxVec(TiltMath.hex2rgba("#f00"), [1, 0, 0, 1]),
+ "The hex2rgba() function didn't calculate the 1st rgba values correctly.");
+
+ ok(isApproxVec(TiltMath.hex2rgba("#f008"), [1, 0, 0, 0.53]),
+ "The hex2rgba() function didn't calculate the 2nd rgba values correctly.");
+
+ ok(isApproxVec(TiltMath.hex2rgba("#ff0000"), [1, 0, 0, 1]),
+ "The hex2rgba() function didn't calculate the 3rd rgba values correctly.");
+
+ ok(isApproxVec(TiltMath.hex2rgba("#ff0000aa"), [1, 0, 0, 0.66]),
+ "The hex2rgba() function didn't calculate the 4th rgba values correctly.");
+
+ ok(isApproxVec(TiltMath.hex2rgba("rgba(255, 0, 0, 0.5)"), [1, 0, 0, 0.5]),
+ "The hex2rgba() function didn't calculate the 5th rgba values correctly.");
+
+ ok(isApproxVec(TiltMath.hex2rgba("rgb(255, 0, 0)"), [1, 0, 0, 1]),
+ "The hex2rgba() function didn't calculate the 6th rgba values correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_math02.js b/toolkit/devtools/tilt/test/browser_tilt_math02.js
new file mode 100644
index 000000000..dae2708c4
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_math02.js
@@ -0,0 +1,104 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let v1 = vec3.create();
+
+ ok(v1, "Should have created a vector with vec3.create().");
+ is(v1.length, 3, "A vec3 should have 3 elements.");
+
+ ok(isApproxVec(v1, [0, 0, 0]),
+ "When created, a vec3 should have the values default to 0.");
+
+ vec3.set([1, 2, 3], v1);
+ ok(isApproxVec(v1, [1, 2, 3]),
+ "The vec3.set() function didn't set the values correctly.");
+
+ vec3.zero(v1);
+ ok(isApproxVec(v1, [0, 0, 0]),
+ "The vec3.zero() function didn't set the values correctly.");
+
+ let v2 = vec3.create([4, 5, 6]);
+ ok(isApproxVec(v2, [4, 5, 6]),
+ "When cloning arrays, a vec3 should have the values copied.");
+
+ let v3 = vec3.create(v2);
+ ok(isApproxVec(v3, [4, 5, 6]),
+ "When cloning vectors, a vec3 should have the values copied.");
+
+ vec3.add(v2, v3);
+ ok(isApproxVec(v2, [8, 10, 12]),
+ "The vec3.add() function didn't set the x value correctly.");
+
+ vec3.subtract(v2, v3);
+ ok(isApproxVec(v2, [4, 5, 6]),
+ "The vec3.subtract() function didn't set the values correctly.");
+
+ vec3.negate(v2);
+ ok(isApproxVec(v2, [-4, -5, -6]),
+ "The vec3.negate() function didn't set the values correctly.");
+
+ vec3.scale(v2, -2);
+ ok(isApproxVec(v2, [8, 10, 12]),
+ "The vec3.scale() function didn't set the values correctly.");
+
+ vec3.normalize(v1);
+ ok(isApproxVec(v1, [0, 0, 0]),
+ "Normalizing a vector with zero length should return [0, 0, 0].");
+
+ vec3.normalize(v2);
+ ok(isApproxVec(v2, [
+ 0.4558423161506653, 0.5698028802871704, 0.6837634444236755
+ ]), "The vec3.normalize() function didn't set the values correctly.");
+
+ vec3.cross(v2, v3);
+ ok(isApproxVec(v2, [
+ 5.960464477539063e-8, -1.1920928955078125e-7, 5.960464477539063e-8
+ ]), "The vec3.cross() function didn't set the values correctly.");
+
+ vec3.dot(v2, v3);
+ ok(isApproxVec(v2, [
+ 5.960464477539063e-8, -1.1920928955078125e-7, 5.960464477539063e-8
+ ]), "The vec3.dot() function didn't set the values correctly.");
+
+ ok(isApproxVec([vec3.length(v2)], [1.4600096599955427e-7]),
+ "The vec3.length() function didn't calculate the value correctly.");
+
+ vec3.direction(v2, v3);
+ ok(isApproxVec(v2, [
+ -0.4558422863483429, -0.5698028802871704, -0.6837634444236755
+ ]), "The vec3.direction() function didn't set the values correctly.");
+
+ vec3.lerp(v2, v3, 0.5);
+ ok(isApproxVec(v2, [
+ 1.7720788717269897, 2.2150986194610596, 2.65811824798584
+ ]), "The vec3.lerp() function didn't set the values correctly.");
+
+
+ vec3.project([100, 100, 10], [0, 0, 100, 100],
+ mat4.create(), mat4.perspective(45, 1, 0.1, 100), v1);
+ ok(isApproxVec(v1, [-1157.10693359375, 1257.10693359375, 0]),
+ "The vec3.project() function didn't set the values correctly.");
+
+ vec3.unproject([100, 100, 1], [0, 0, 100, 100],
+ mat4.create(), mat4.perspective(45, 1, 0.1, 100), v1);
+ ok(isApproxVec(v1, [
+ 41.420406341552734, -41.420406341552734, -99.99771118164062
+ ]), "The vec3.project() function didn't set the values correctly.");
+
+
+ let ray = vec3.createRay([10, 10, 0], [100, 100, 1], [0, 0, 100, 100],
+ mat4.create(), mat4.perspective(45, 1, 0.1, 100));
+
+ ok(isApproxVec(ray.origin, [
+ -0.03313708305358887, 0.03313708305358887, -0.1000000014901161
+ ]), "The vec3.createRay() function didn't create the position correctly.");
+ ok(isApproxVec(ray.direction, [
+ 0.35788586614428364, -0.35788586614428364, -0.862458934459091
+ ]), "The vec3.createRay() function didn't create the direction correctly.");
+
+
+ is(vec3.str([0, 0, 0]), "[0, 0, 0]",
+ "The vec3.str() function didn't work properly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_math03.js b/toolkit/devtools/tilt/test/browser_tilt_math03.js
new file mode 100644
index 000000000..9a039ae77
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_math03.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let m1 = mat3.create();
+
+ ok(m1, "Should have created a matrix with mat3.create().");
+ is(m1.length, 9, "A mat3 should have 9 elements.");
+
+ ok(isApproxVec(m1, [1, 0, 0, 0, 1, 0, 0, 0, 1]),
+ "When created, a mat3 should have the values default to identity.");
+
+ mat3.set([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
+ ok(isApproxVec(m1, [1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ "The mat3.set() function didn't set the values correctly.");
+
+ mat3.transpose(m1);
+ ok(isApproxVec(m1, [1, 4, 7, 2, 5, 8, 3, 6, 9]),
+ "The mat3.transpose() function didn't set the values correctly.");
+
+ mat3.identity(m1);
+ ok(isApproxVec(m1, [1, 0, 0, 0, 1, 0, 0, 0, 1]),
+ "The mat3.identity() function didn't set the values correctly.");
+
+ let m2 = mat3.toMat4(m1);
+ ok(isApproxVec(m2, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
+ "The mat3.toMat4() function didn't set the values correctly.");
+
+
+ is(mat3.str([1, 2, 3, 4, 5, 6, 7, 8, 9]), "[1, 2, 3, 4, 5, 6, 7, 8, 9]",
+ "The mat3.str() function didn't work properly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_math04.js b/toolkit/devtools/tilt/test/browser_tilt_math04.js
new file mode 100644
index 000000000..587dc45fd
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_math04.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let m1 = mat4.create();
+
+ ok(m1, "Should have created a matrix with mat4.create().");
+ is(m1.length, 16, "A mat4 should have 16 elements.");
+
+ ok(isApproxVec(m1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
+ "When created, a mat4 should have the values default to identity.");
+
+ mat4.set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
+ ok(isApproxVec(m1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
+ "The mat4.set() function didn't set the values correctly.");
+
+ mat4.transpose(m1);
+ ok(isApproxVec(m1, [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]),
+ "The mat4.transpose() function didn't set the values correctly.");
+
+ mat4.identity(m1);
+ ok(isApproxVec(m1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
+ "The mat4.identity() function didn't set the values correctly.");
+
+ ok(isApprox(mat4.determinant(m1), 1),
+ "The mat4.determinant() function didn't calculate the value correctly.");
+
+ let m2 = mat4.inverse([1, 3, 1, 1, 1, 1, 2, 1, 2, 3, 4, 1, 1, 1, 1, 1]);
+ ok(isApproxVec(m2, [
+ -1, -3, 1, 3, 0.5, 0, 0, -0.5, 0, 1, 0, -1, 0.5, 2, -1, -0.5
+ ]), "The mat4.inverse() function didn't calculate the values correctly.");
+
+ let m3 = mat4.toRotationMat([
+ 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]);
+ ok(isApproxVec(m3, [
+ 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 0, 0, 0, 1
+ ]), "The mat4.toRotationMat() func. didn't calculate the values correctly.");
+
+ let m4 = mat4.toMat3([
+ 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]);
+ ok(isApproxVec(m4, [1, 5, 9, 2, 6, 10, 3, 7, 11]),
+ "The mat4.toMat3() function didn't set the values correctly.");
+
+ let m5 = mat4.toInverseMat3([
+ 1, 3, 1, 1, 1, 1, 2, 1, 2, 3, 4, 1, 1, 1, 1, 1]);
+ ok(isApproxVec(m5, [2, 9, -5, 0, -2, 1, -1, -3, 2]),
+ "The mat4.toInverseMat3() function didn't set the values correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_math05.js b/toolkit/devtools/tilt/test/browser_tilt_math05.js
new file mode 100644
index 000000000..d39695f55
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_math05.js
@@ -0,0 +1,101 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let m1 = mat4.create([
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+
+ let m2 = mat4.create([
+ 0, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]);
+
+ mat4.multiply(m1, m2);
+ ok(isApproxVec(m1, [
+ 275, 302, 329, 356, 304, 336, 368, 400,
+ 332, 368, 404, 440, 360, 400, 440, 480
+ ]), "The mat4.multiply() function didn't set the values correctly.");
+
+ let v1 = mat4.multiplyVec3(m1, [1, 2, 3]);
+ ok(isApproxVec(v1, [2239, 2478, 2717]),
+ "The mat4.multiplyVec3() function didn't set the values correctly.");
+
+ let v2 = mat4.multiplyVec4(m1, [1, 2, 3, 0]);
+ ok(isApproxVec(v2, [1879, 2078, 2277, 2476]),
+ "The mat4.multiplyVec4() function didn't set the values correctly.");
+
+ mat4.translate(m1, [1, 2, 3]);
+ ok(isApproxVec(m1, [
+ 275, 302, 329, 356, 304, 336, 368, 400,
+ 332, 368, 404, 440, 2239, 2478, 2717, 2956
+ ]), "The mat4.translate() function didn't set the values correctly.");
+
+ mat4.scale(m1, [1, 2, 3]);
+ ok(isApproxVec(m1, [
+ 275, 302, 329, 356, 608, 672, 736, 800,
+ 996, 1104, 1212, 1320, 2239, 2478, 2717, 2956
+ ]), "The mat4.scale() function didn't set the values correctly.");
+
+ mat4.rotate(m1, 0.5, [1, 1, 1]);
+ ok(isApproxVec(m1, [
+ 210.6123046875, 230.2483367919922, 249.88438415527344, 269.5204162597656,
+ 809.8145751953125, 896.520751953125, 983.2268676757812,
+ 1069.9329833984375, 858.5731201171875, 951.23095703125,
+ 1043.8887939453125, 1136.5465087890625, 2239, 2478, 2717, 2956
+ ]), "The mat4.rotate() function didn't set the values correctly.");
+
+ mat4.rotateX(m1, 0.5);
+ ok(isApproxVec(m1, [
+ 210.6123046875, 230.2483367919922, 249.88438415527344, 269.5204162597656,
+ 1122.301025390625, 1242.8154296875, 1363.3297119140625,
+ 1483.843994140625, 365.2230224609375, 404.96875, 444.71453857421875,
+ 484.460205078125, 2239, 2478, 2717, 2956
+ ]), "The mat4.rotateX() function didn't set the values correctly.");
+
+ mat4.rotateY(m1, 0.5);
+ ok(isApproxVec(m1, [
+ 9.732441902160645, 7.909564018249512, 6.086670875549316,
+ 4.263822555541992, 1122.301025390625, 1242.8154296875, 1363.3297119140625,
+ 1483.843994140625, 421.48626708984375, 465.78045654296875,
+ 510.0746765136719, 554.3687744140625, 2239, 2478, 2717, 2956
+ ]), "The mat4.rotateY() function didn't set the values correctly.");
+
+ mat4.rotateZ(m1, 0.5);
+ ok(isApproxVec(m1, [
+ 546.6007690429688, 602.7787475585938, 658.9566650390625, 715.1345825195312,
+ 980.245849609375, 1086.881103515625, 1193.5162353515625,
+ 1300.1514892578125, 421.48626708984375, 465.78045654296875,
+ 510.0746765136719, 554.3687744140625, 2239, 2478, 2717, 2956
+ ]), "The mat4.rotateZ() function didn't set the values correctly.");
+
+
+ let m3 = mat4.frustum(0, 100, 200, 0, 0.1, 100);
+ ok(isApproxVec(m3, [
+ 0.0020000000949949026, 0, 0, 0, 0, -0.0010000000474974513, 0, 0, 1, -1,
+ -1.0020020008087158, -1, 0, 0, -0.20020020008087158, 0
+ ]), "The mat4.frustum() function didn't compute the values correctly.");
+
+ let m4 = mat4.perspective(45, 1.6, 0.1, 100);
+ ok(isApproxVec(m4, [1.5088834762573242, 0, 0, 0, 0, 2.4142136573791504, 0,
+ 0, 0, 0, -1.0020020008087158, -1, 0, 0, -0.20020020008087158, 0
+ ]), "The mat4.frustum() function didn't compute the values correctly.");
+
+ let m5 = mat4.ortho(0, 100, 200, 0, -1, 1);
+ ok(isApproxVec(m5, [
+ 0.019999999552965164, 0, 0, 0, 0, -0.009999999776482582, 0, 0,
+ 0, 0, -1, 0, -1, 1, 0, 1
+ ]), "The mat4.ortho() function didn't compute the values correctly.");
+
+ let m6 = mat4.lookAt([1, 2, 3], [4, 5, 6], [0, 1, 0]);
+ ok(isApproxVec(m6, [
+ -0.7071067690849304, -0.40824830532073975, -0.5773502588272095, 0, 0,
+ 0.8164966106414795, -0.5773502588272095, 0, 0.7071067690849304,
+ -0.40824830532073975, -0.5773502588272095, 0, -1.4142135381698608, 0,
+ 3.464101552963257, 1
+ ]), "The mat4.lookAt() function didn't compute the values correctly.");
+
+
+ is(mat4.str([
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
+ "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]",
+ "The mat4.str() function didn't work properly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_math06.js b/toolkit/devtools/tilt/test/browser_tilt_math06.js
new file mode 100644
index 000000000..2ed331eaa
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_math06.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let q1 = quat4.create();
+
+ ok(q1, "Should have created a quaternion with quat4.create().");
+ is(q1.length, 4, "A quat4 should have 4 elements.");
+
+ ok(isApproxVec(q1, [0, 0, 0, 1]),
+ "When created, a vec3 should have the values default to identity.");
+
+ quat4.set([1, 2, 3, 4], q1);
+ ok(isApproxVec(q1, [1, 2, 3, 4]),
+ "The quat4.set() function didn't set the values correctly.");
+
+ quat4.identity(q1);
+ ok(isApproxVec(q1, [0, 0, 0, 1]),
+ "The quat4.identity() function didn't set the values correctly.");
+
+ quat4.set([5, 6, 7, 8], q1);
+ ok(isApproxVec(q1, [5, 6, 7, 8]),
+ "The quat4.set() function didn't set the values correctly.");
+
+ quat4.calculateW(q1);
+ ok(isApproxVec(q1, [5, 6, 7, -10.440306663513184]),
+ "The quat4.calculateW() function didn't compute the values correctly.");
+
+ quat4.inverse(q1);
+ ok(isApproxVec(q1, [-5, -6, -7, -10.440306663513184]),
+ "The quat4.inverse() function didn't compute the values correctly.");
+
+ quat4.normalize(q1);
+ ok(isApproxVec(q1, [
+ -0.33786869049072266, -0.40544241666793823,
+ -0.4730161726474762, -0.7054905295372009
+ ]), "The quat4.normalize() function didn't compute the values correctly.");
+
+ ok(isApprox(quat4.length(q1), 1),
+ "The mat4.length() function didn't calculate the value correctly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_math07.js b/toolkit/devtools/tilt/test/browser_tilt_math07.js
new file mode 100644
index 000000000..309d3763d
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_math07.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let q1 = quat4.create([1, 2, 3, 4]);
+ let q2 = quat4.create([5, 6, 7, 8]);
+
+ quat4.multiply(q1, q2);
+ ok(isApproxVec(q1, [24, 48, 48, -6]),
+ "The quat4.multiply() function didn't set the values correctly.");
+
+ let v1 = quat4.multiplyVec3(q1, [9, 9, 9]);
+ ok(isApproxVec(v1, [5508, 54756, 59940]),
+ "The quat4.multiplyVec3() function didn't set the values correctly.");
+
+ let m1 = quat4.toMat3(q1);
+ ok(isApproxVec(m1, [
+ -9215, 2880, 1728, 1728, -5759, 4896, 2880, 4320, -5759
+ ]), "The quat4.toMat3() function didn't set the values correctly.");
+
+ let m2 = quat4.toMat4(q1);
+ ok(isApproxVec(m2, [
+ -9215, 2880, 1728, 0, 1728, -5759, 4896, 0,
+ 2880, 4320, -5759, 0, 0, 0, 0, 1
+ ]), "The quat4.toMat4() function didn't set the values correctly.");
+
+ quat4.calculateW(q1);
+ quat4.calculateW(q2);
+ quat4.slerp(q1, q2, 0.5);
+ ok(isApproxVec(q1, [24, 48, 48, -71.99305725097656]),
+ "The quat4.slerp() function didn't set the values correctly.");
+
+ let q3 = quat4.fromAxis([1, 1, 1], 0.5);
+ ok(isApproxVec(q3, [
+ 0.24740396440029144, 0.24740396440029144, 0.24740396440029144,
+ 0.9689124226570129
+ ]), "The quat4.fromAxis() function didn't compute the values correctly.");
+
+ let q4 = quat4.fromEuler(0.5, 0.75, 1.25);
+ ok(isApproxVec(q4, [
+ 0.15310347080230713, 0.39433568716049194,
+ 0.4540249705314636, 0.7841683626174927
+ ]), "The quat4.fromEuler() function didn't compute the values correctly.");
+
+
+ is(quat4.str([1, 2, 3, 4]), "[1, 2, 3, 4]",
+ "The quat4.str() function didn't work properly.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking.js b/toolkit/devtools/tilt/test/browser_tilt_picking.js
new file mode 100644
index 000000000..a40f26588
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking.js
@@ -0,0 +1,56 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let pickDone = false;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping picking test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping picking test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ let presenter = instance.presenter;
+ let canvas = presenter.canvas;
+
+ presenter._onSetupMesh = function() {
+ let p = getPickablePoint(presenter);
+
+ presenter.pickNode(p[0], p[1], {
+ onpick: function(data)
+ {
+ ok(data.index > 0,
+ "Simply picking a node didn't work properly.");
+
+ pickDone = true;
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ }
+ });
+ };
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function cleanup() {
+ if (pickDone) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking_delete.js b/toolkit/devtools/tilt/test/browser_tilt_picking_delete.js
new file mode 100644
index 000000000..bf16f31e6
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking_delete.js
@@ -0,0 +1,78 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let nodeDeleted = false;
+let presenter;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping picking delete test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping picking delete test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ presenter = instance.presenter;
+ Services.obs.addObserver(whenNodeRemoved, NODE_REMOVED, false);
+
+ presenter._onSetupMesh = function() {
+ let p = getPickablePoint(presenter);
+
+ presenter.highlightNodeAt(p[0], p[1], {
+ onpick: function()
+ {
+ ok(presenter._currentSelection > 0,
+ "Highlighting a node didn't work properly.");
+ ok(!presenter._highlight.disabled,
+ "After highlighting a node, it should be highlighted. D'oh.");
+
+ nodeDeleted = true;
+ presenter.deleteNode();
+ }
+ });
+ };
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function whenNodeRemoved() {
+ ok(presenter._currentSelection > 0,
+ "Deleting a node shouldn't change the current selection.");
+ ok(presenter._highlight.disabled,
+ "After deleting a node, it shouldn't be highlighted.");
+
+ let nodeIndex = presenter._currentSelection;
+ let vertices = presenter._meshStacks[0].vertices.components;
+
+ for (let i = 0, k = 36 * nodeIndex; i < 36; i++) {
+ is(vertices[i + k], 0,
+ "The stack vertices weren't degenerated properly.");
+ }
+
+ executeSoon(function() {
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+}
+
+function cleanup() {
+ if (nodeDeleted) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking_highlight01-offs.js b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight01-offs.js
new file mode 100644
index 000000000..4f5b6f06a
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight01-offs.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let nodeHighlighted = false;
+let presenter;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping highlight test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping highlight test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ presenter = instance.presenter;
+ Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
+
+ presenter._onInitializationFinished = function() {
+ let contentDocument = presenter.contentWindow.document;
+ let div = contentDocument.getElementById("far-far-away");
+
+ nodeHighlighted = true;
+ presenter.highlightNode(div, "moveIntoView");
+ };
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function whenHighlighting() {
+ ok(presenter._currentSelection > 0,
+ "Highlighting a node didn't work properly.");
+ ok(!presenter._highlight.disabled,
+ "After highlighting a node, it should be highlighted. D'oh.");
+ ok(presenter.controller.arcball._resetInProgress,
+ "Highlighting a node that's not already visible should trigger a reset!");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
+ Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
+ presenter.highlightNode(null);
+ });
+}
+
+function whenUnhighlighting() {
+ ok(presenter._currentSelection < 0,
+ "Unhighlighting a should remove the current selection.");
+ ok(presenter._highlight.disabled,
+ "After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+}
+
+function cleanup() {
+ if (nodeHighlighted) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking_highlight01.js b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight01.js
new file mode 100644
index 000000000..8ad2c2ae4
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight01.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let nodeHighlighted = false;
+let presenter;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping highlight test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping highlight test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ presenter = instance.presenter;
+ Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
+
+ presenter._onInitializationFinished = function() {
+ let contentDocument = presenter.contentWindow.document;
+ let div = contentDocument.getElementById("first-law");
+
+ nodeHighlighted = true;
+ presenter.highlightNode(div, "moveIntoView");
+ };
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function whenHighlighting() {
+ ok(presenter._currentSelection > 0,
+ "Highlighting a node didn't work properly.");
+ ok(!presenter._highlight.disabled,
+ "After highlighting a node, it should be highlighted. D'oh.");
+ ok(!presenter.controller.arcball._resetInProgress,
+ "Highlighting a node that's already visible shouldn't trigger a reset.");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
+ Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
+ presenter.highlightNode(null);
+ });
+}
+
+function whenUnhighlighting() {
+ ok(presenter._currentSelection < 0,
+ "Unhighlighting a should remove the current selection.");
+ ok(presenter._highlight.disabled,
+ "After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+}
+
+function cleanup() {
+ if (nodeHighlighted) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking_highlight02.js b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight02.js
new file mode 100644
index 000000000..b6f20121e
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight02.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let nodeHighlighted = false;
+let presenter;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping highlight test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping highlight test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ presenter = instance.presenter;
+ Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
+
+ presenter._onInitializationFinished = function() {
+ nodeHighlighted = true;
+ presenter.highlightNodeAt.apply(this, getPickablePoint(presenter));
+ };
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function whenHighlighting() {
+ ok(presenter._currentSelection > 0,
+ "Highlighting a node didn't work properly.");
+ ok(!presenter._highlight.disabled,
+ "After highlighting a node, it should be highlighted. D'oh.");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
+ Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
+ presenter.highlightNode(null);
+ });
+}
+
+function whenUnhighlighting() {
+ ok(presenter._currentSelection < 0,
+ "Unhighlighting a should remove the current selection.");
+ ok(presenter._highlight.disabled,
+ "After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+}
+
+function cleanup() {
+ if (nodeHighlighted) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking_highlight03.js b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight03.js
new file mode 100644
index 000000000..56e311b9a
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking_highlight03.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let nodeHighlighted = false;
+let presenter;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping highlight test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping highlight test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ presenter = instance.presenter;
+ Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
+
+ presenter._onInitializationFinished = function() {
+ nodeHighlighted = true;
+ presenter.highlightNodeFor(3); // 1 = html, 2 = body, 3 = first div
+ };
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function whenHighlighting() {
+ ok(presenter._currentSelection > 0,
+ "Highlighting a node didn't work properly.");
+ ok(!presenter._highlight.disabled,
+ "After highlighting a node, it should be highlighted. D'oh.");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
+ Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
+ presenter.highlightNodeFor(-1);
+ });
+}
+
+function whenUnhighlighting() {
+ ok(presenter._currentSelection < 0,
+ "Unhighlighting a should remove the current selection.");
+ ok(presenter._highlight.disabled,
+ "After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+}
+
+function cleanup() {
+ if (nodeHighlighted) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking_inspector.js b/toolkit/devtools/tilt/test/browser_tilt_picking_inspector.js
new file mode 100644
index 000000000..688f3d07f
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking_inspector.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let presenter;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping highlight test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping highlight test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
+ let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
+
+ gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+ let contentDocument = toolbox.target.tab.linkedBrowser.contentDocument;
+ let div = contentDocument.getElementById("first-law");
+ toolbox.getCurrentPanel().selection.setNode(div);
+
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ presenter = instance.presenter;
+ whenOpen();
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+ });
+}
+
+function whenOpen() {
+ ok(presenter._currentSelection > 0,
+ "Highlighting a node didn't work properly.");
+ ok(!presenter._highlight.disabled,
+ "After highlighting a node, it should be highlighted. D'oh.");
+ ok(!presenter.controller.arcball._resetInProgress,
+ "Highlighting a node that's already visible shouldn't trigger a reset.");
+
+ executeSoon(function() {
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+}
+
+function cleanup() {
+ Services.obs.removeObserver(cleanup, DESTROYED);
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_picking_miv.js b/toolkit/devtools/tilt/test/browser_tilt_picking_miv.js
new file mode 100644
index 000000000..28f01dab7
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_picking_miv.js
@@ -0,0 +1,78 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let nodeHighlighted = false;
+let presenter;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping highlight test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping highlight test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ presenter = instance.presenter;
+ Services.obs.addObserver(whenHighlighting, HIGHLIGHTING, false);
+
+ presenter._onInitializationFinished = function() {
+ let contentDocument = presenter.contentWindow.document;
+ let div = contentDocument.getElementById("far-far-away");
+
+ nodeHighlighted = true;
+ presenter.highlightNode(div);
+ };
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function whenHighlighting() {
+ ok(presenter._currentSelection > 0,
+ "Highlighting a node didn't work properly.");
+ ok(!presenter._highlight.disabled,
+ "After highlighting a node, it should be highlighted. D'oh.");
+ ok(!presenter.controller.arcball._resetInProgress,
+ "Highlighting a node that's not already visible shouldn't trigger a reset " +
+ "without this being explicitly requested!");
+
+ EventUtils.sendKey("F");
+ executeSoon(whenBringingIntoView);
+}
+
+function whenBringingIntoView() {
+ ok(presenter._currentSelection > 0,
+ "The node should still be selected.");
+ ok(!presenter._highlight.disabled,
+ "The node should still be highlighted");
+ ok(presenter.controller.arcball._resetInProgress,
+ "Highlighting a node that's not already visible should trigger a reset " +
+ "when this is being explicitly requested!");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+}
+
+function cleanup() {
+ if (nodeHighlighted) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils01.js b/toolkit/devtools/tilt/test/browser_tilt_utils01.js
new file mode 100644
index 000000000..7beb6a3a2
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils01.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let prefs = TiltUtils.Preferences;
+ ok(prefs, "The TiltUtils.Preferences wasn't found.");
+
+ prefs.create("test-pref-bool", "boolean", true);
+ prefs.create("test-pref-int", "integer", 42);
+ prefs.create("test-pref-string", "string", "hello world!");
+
+ is(prefs.get("test-pref-bool", "boolean"), true,
+ "The boolean test preference wasn't initially set correctly.");
+ is(prefs.get("test-pref-int", "integer"), 42,
+ "The integer test preference wasn't initially set correctly.");
+ is(prefs.get("test-pref-string", "string"), "hello world!",
+ "The string test preference wasn't initially set correctly.");
+
+
+ prefs.set("test-pref-bool", "boolean", false);
+ prefs.set("test-pref-int", "integer", 24);
+ prefs.set("test-pref-string", "string", "!dlrow olleh");
+
+ is(prefs.get("test-pref-bool", "boolean"), false,
+ "The boolean test preference wasn't changed correctly.");
+ is(prefs.get("test-pref-int", "integer"), 24,
+ "The integer test preference wasn't changed correctly.");
+ is(prefs.get("test-pref-string", "string"), "!dlrow olleh",
+ "The string test preference wasn't changed correctly.");
+
+
+ is(typeof prefs.get("unknown-pref", "boolean"), "undefined",
+ "Inexisted boolean prefs should be handled as undefined.");
+ is(typeof prefs.get("unknown-pref", "integer"), "undefined",
+ "Inexisted integer prefs should be handled as undefined.");
+ is(typeof prefs.get("unknown-pref", "string"), "undefined",
+ "Inexisted string prefs should be handled as undefined.");
+
+
+ is(prefs.get("test-pref-bool", "integer"), null,
+ "The get() boolean function didn't handle incorrect types as it should.");
+ is(prefs.get("test-pref-bool", "string"), null,
+ "The get() boolean function didn't handle incorrect types as it should.");
+ is(prefs.get("test-pref-int", "boolean"), null,
+ "The get() integer function didn't handle incorrect types as it should.");
+ is(prefs.get("test-pref-int", "string"), null,
+ "The get() integer function didn't handle incorrect types as it should.");
+ is(prefs.get("test-pref-string", "boolean"), null,
+ "The get() string function didn't handle incorrect types as it should.");
+ is(prefs.get("test-pref-string", "integer"), null,
+ "The get() string function didn't handle incorrect types as it should.");
+
+
+ is(typeof prefs.get(), "undefined",
+ "The get() function should not work if not enough params are passed.");
+ is(typeof prefs.set(), "undefined",
+ "The set() function should not work if not enough params are passed.");
+ is(typeof prefs.create(), "undefined",
+ "The create() function should not work if not enough params are passed.");
+
+
+ is(prefs.get("test-pref-wrong-type", "wrong-type", 1), null,
+ "The get() function should expect only correct pref types.");
+ is(prefs.set("test-pref-wrong-type", "wrong-type", 1), false,
+ "The set() function should expect only correct pref types.");
+ is(prefs.create("test-pref-wrong-type", "wrong-type", 1), false,
+ "The create() function should expect only correct pref types.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils02.js b/toolkit/devtools/tilt/test/browser_tilt_utils02.js
new file mode 100644
index 000000000..fcee265c6
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils02.js
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let l10 = TiltUtils.L10n;
+ ok(l10, "The TiltUtils.L10n wasn't found.");
+
+
+ ok(l10.stringBundle,
+ "The necessary string bundle wasn't found.");
+ is(l10.get(), null,
+ "The get() function shouldn't work if no params are passed.");
+ is(l10.format(), null,
+ "The format() function shouldn't work if no params are passed.");
+
+ is(typeof l10.get("initWebGL.error"), "string",
+ "No valid string was returned from a corect name in the bundle.");
+ is(typeof l10.format("linkProgram.error", ["error"]), "string",
+ "No valid formatted string was returned from a name in the bundle.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils03.js b/toolkit/devtools/tilt/test/browser_tilt_utils03.js
new file mode 100644
index 000000000..61d256fe1
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils03.js
@@ -0,0 +1,18 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let dom = TiltUtils.DOM;
+
+ is(dom.parentNode, null,
+ "The parent node should not be initially set.");
+
+ dom.parentNode = {};
+ ok(dom.parentNode,
+ "The parent node should now be set.");
+
+ TiltUtils.clearCache();
+ is(dom.parentNode, null,
+ "The parent node should not be set after clearing the cache.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils04.js b/toolkit/devtools/tilt/test/browser_tilt_utils04.js
new file mode 100644
index 000000000..8574c266e
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils04.js
@@ -0,0 +1,54 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ let dom = TiltUtils.DOM;
+ ok(dom, "The TiltUtils.DOM wasn't found.");
+
+
+ is(dom.initCanvas(), null,
+ "The initCanvas() function shouldn't work if no parent node is set.");
+
+
+ dom.parentNode = gBrowser.parentNode;
+ ok(dom.parentNode,
+ "The necessary parent node wasn't found.");
+
+
+ let canvas = dom.initCanvas(null, {
+ append: true,
+ focusable: true,
+ width: 123,
+ height: 456,
+ id: "tilt-test-canvas"
+ });
+
+ is(canvas.width, 123,
+ "The test canvas doesn't have the correct width set.");
+ is(canvas.height, 456,
+ "The test canvas doesn't have the correct height set.");
+ is(canvas.getAttribute("tabindex"), 1,
+ "The test canvas tab index wasn't set correctly.");
+ is(canvas.getAttribute("id"), "tilt-test-canvas",
+ "The test canvas doesn't have the correct id set.");
+ ok(dom.parentNode.ownerDocument.getElementById(canvas.id),
+ "A canvas should be appended to the parent node if specified.");
+ canvas.parentNode.removeChild(canvas);
+
+ let canvas2 = dom.initCanvas(null, { id: "tilt-test-canvas2" });
+
+ is(canvas2.width, dom.parentNode.clientWidth,
+ "The second test canvas doesn't have the implicit width set.");
+ is(canvas2.height, dom.parentNode.clientHeight,
+ "The second test canvas doesn't have the implicit height set.");
+ is(canvas2.id, "tilt-test-canvas2",
+ "The second test canvas doesn't have the correct id set.");
+ is(dom.parentNode.ownerDocument.getElementById(canvas2.id), null,
+ "A canvas shouldn't be appended to the parent node if not specified.");
+
+
+ dom.parentNode = null;
+ is(dom.parentNode, null,
+ "The necessary parent node shouldn't be found anymore.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils05.js b/toolkit/devtools/tilt/test/browser_tilt_utils05.js
new file mode 100644
index 000000000..139b4aa3c
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils05.js
@@ -0,0 +1,101 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const STACK_THICKNESS = 15;
+
+function init(callback) {
+ let iframe = gBrowser.ownerDocument.createElement("iframe");
+
+ iframe.addEventListener("load", function onLoad() {
+ iframe.removeEventListener("load", onLoad, true);
+ callback(iframe);
+
+ gBrowser.parentNode.removeChild(iframe);
+ finish();
+ }, true);
+
+ iframe.setAttribute("src", ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<head>",
+ "<style>",
+ "</style>",
+ "<script>",
+ "</script>",
+ "</head>",
+ "<body style='margin: 0;'>",
+ "<div style='margin-top: 98px;" +
+ "margin-left: 76px;" +
+ "width: 123px;" +
+ "height: 456px;' id='test-div'>",
+ "<span></span>",
+ "</div>",
+ "</body>",
+ "</html>"
+ ].join(""));
+
+ gBrowser.parentNode.appendChild(iframe);
+}
+
+function test() {
+ waitForExplicitFinish();
+ ok(TiltUtils, "The TiltUtils object doesn't exist.");
+
+ let dom = TiltUtils.DOM;
+ ok(dom, "The TiltUtils.DOM wasn't found.");
+
+ init(function(iframe) {
+ let cwDimensions = dom.getContentWindowDimensions(iframe.contentWindow);
+
+ is(cwDimensions.width - iframe.contentWindow.scrollMaxX,
+ iframe.contentWindow.innerWidth,
+ "The content window width wasn't calculated correctly.");
+ is(cwDimensions.height - iframe.contentWindow.scrollMaxY,
+ iframe.contentWindow.innerHeight,
+ "The content window height wasn't calculated correctly.");
+
+ let lh = new LayoutHelpers(gBrowser.contentWindow);
+ let nodeCoordinates = lh.getRect(
+ iframe.contentDocument.getElementById("test-div"), iframe.contentWindow);
+
+ let frameOffset = lh.getIframeContentOffset(iframe);
+ let frameRect = iframe.getBoundingClientRect();
+
+ is(nodeCoordinates.top, frameRect.top + frameOffset[0] + 98,
+ "The node coordinates top value wasn't calculated correctly.");
+ is(nodeCoordinates.left, frameRect.left + frameOffset[1] + 76,
+ "The node coordinates left value wasn't calculated correctly.");
+ is(nodeCoordinates.width, 123,
+ "The node coordinates width value wasn't calculated correctly.");
+ is(nodeCoordinates.height, 456,
+ "The node coordinates height value wasn't calculated correctly.");
+
+
+ let store = dom.traverse(iframe.contentWindow);
+
+ let expected = [
+ { name: "html", depth: 0 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "head", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "body", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "style", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "script", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "div", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "span", depth: 3 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ ];
+
+ is(store.nodes.length, expected.length,
+ "The traverse() function didn't walk the correct number of nodes.");
+ is(store.info.length, expected.length,
+ "The traverse() function didn't examine the correct number of nodes.");
+
+ for (let i = 0; i < expected.length; i++) {
+ is(store.info[i].name, expected[i].name,
+ "traversed node " + (i + 1) + " isn't the expected one.");
+ is(store.info[i].coord.depth, expected[i].depth,
+ "traversed node " + (i + 1) + " doesn't have the expected depth.");
+ is(store.info[i].coord.thickness, expected[i].thickness,
+ "traversed node " + (i + 1) + " doesn't have the expected thickness.");
+ }
+ });
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils06.js b/toolkit/devtools/tilt/test/browser_tilt_utils06.js
new file mode 100644
index 000000000..eee915261
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils06.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let someObject = {
+ a: 1,
+ func: function()
+ {
+ this.b = 2;
+ }
+};
+
+let anotherObject = {
+ _finalize: function()
+ {
+ someObject.c = 3;
+ }
+};
+
+function test() {
+ ok(TiltUtils, "The TiltUtils object doesn't exist.");
+
+ TiltUtils.bindObjectFunc(someObject, "", anotherObject);
+ someObject.func();
+
+ is(someObject.a, 1,
+ "The bindObjectFunc() messed the non-function members of the object.");
+ isnot(someObject.b, 2,
+ "The bindObjectFunc() didn't ignore the old scope correctly.");
+ is(anotherObject.b, 2,
+ "The bindObjectFunc() didn't set the new scope correctly.");
+
+
+ TiltUtils.destroyObject(anotherObject);
+ is(someObject.c, 3,
+ "The finalize function wasn't called when an object was destroyed.");
+
+
+ TiltUtils.destroyObject(someObject);
+ is(typeof someObject.a, "undefined",
+ "Not all members of the destroyed object were deleted.");
+ is(typeof someObject.func, "undefined",
+ "Not all function members of the destroyed object were deleted.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils07.js b/toolkit/devtools/tilt/test/browser_tilt_utils07.js
new file mode 100644
index 000000000..ab97cc698
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils07.js
@@ -0,0 +1,159 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const STACK_THICKNESS = 15;
+
+function init(callback) {
+ let iframe = gBrowser.ownerDocument.createElement("iframe");
+
+ iframe.addEventListener("load", function onLoad() {
+ iframe.removeEventListener("load", onLoad, true);
+ callback(iframe);
+
+ gBrowser.parentNode.removeChild(iframe);
+ finish();
+ }, true);
+
+ iframe.setAttribute("src", ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body style='margin: 0;'>",
+ "<frameset cols='50%,50%'>",
+ "<frame src='",
+ ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body style='margin: 0;'>",
+ "<div id='test-div' style='width: 123px; height: 456px;'></div>",
+ "</body>",
+ "</html>"
+ ].join(""),
+ "' />",
+ "<frame src='",
+ ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body style='margin: 0;'>",
+ "<span></span>",
+ "</body>",
+ "</html>"
+ ].join(""),
+ "' />",
+ "</frameset>",
+ "<iframe src='",
+ ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body>",
+ "<span></span>",
+ "</body>",
+ "</html>"
+ ].join(""),
+ "'></iframe>",
+ "<frame src='",
+ ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body style='margin: 0;'>",
+ "<span></span>",
+ "</body>",
+ "</html>"
+ ].join(""),
+ "' />",
+ "<frame src='",
+ ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body style='margin: 0;'>",
+ "<iframe src='",
+ ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body>",
+ "<div></div>",
+ "</body>",
+ "</html>"
+ ].join(""),
+ "'></iframe>",
+ "</body>",
+ "</html>"
+ ].join(""),
+ "' />",
+ "</body>",
+ "</html>"
+ ].join(""));
+
+ gBrowser.parentNode.appendChild(iframe);
+}
+
+function test() {
+ waitForExplicitFinish();
+ ok(TiltUtils, "The TiltUtils object doesn't exist.");
+
+ let dom = TiltUtils.DOM;
+ ok(dom, "The TiltUtils.DOM wasn't found.");
+
+ init(function(iframe) {
+ let cwDimensions = dom.getContentWindowDimensions(iframe.contentWindow);
+
+ is(cwDimensions.width - iframe.contentWindow.scrollMaxX,
+ iframe.contentWindow.innerWidth,
+ "The content window width wasn't calculated correctly.");
+ is(cwDimensions.height - iframe.contentWindow.scrollMaxY,
+ iframe.contentWindow.innerHeight,
+ "The content window height wasn't calculated correctly.");
+
+ let lh = new LayoutHelpers(gBrowser.contentWindow);
+ let nodeCoordinates = lh.getRect(
+ iframe.contentDocument.getElementById("test-div"), iframe.contentWindow);
+
+ let frameOffset = lh.getIframeContentOffset(iframe);
+ let frameRect = iframe.getBoundingClientRect();
+
+ is(nodeCoordinates.top, frameRect.top + frameOffset[0],
+ "The node coordinates top value wasn't calculated correctly.");
+ is(nodeCoordinates.left, frameRect.left + frameOffset[1],
+ "The node coordinates left value wasn't calculated correctly.");
+ is(nodeCoordinates.width, 123,
+ "The node coordinates width value wasn't calculated correctly.");
+ is(nodeCoordinates.height, 456,
+ "The node coordinates height value wasn't calculated correctly.");
+
+
+ let store = dom.traverse(iframe.contentWindow);
+
+ let expected = [
+ { name: "html", depth: 0 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "head", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "body", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "div", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "span", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "iframe", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "span", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "iframe", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "html", depth: 3 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "html", depth: 3 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "head", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "body", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "head", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "body", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "span", depth: 5 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "div", depth: 5 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ ];
+
+ is(store.nodes.length, expected.length,
+ "The traverse() function didn't walk the correct number of nodes.");
+ is(store.info.length, expected.length,
+ "The traverse() function didn't examine the correct number of nodes.");
+
+ for (let i = 0; i < expected.length; i++) {
+ is(store.info[i].name, expected[i].name,
+ "traversed node " + (i + 1) + " isn't the expected one.");
+ is(store.info[i].coord.depth, expected[i].depth,
+ "traversed node " + (i + 1) + " doesn't have the expected depth.");
+ is(store.info[i].coord.thickness, expected[i].thickness,
+ "traversed node " + (i + 1) + " doesn't have the expected thickness.");
+ }
+ });
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_utils08.js b/toolkit/devtools/tilt/test/browser_tilt_utils08.js
new file mode 100644
index 000000000..797c9e7a7
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_utils08.js
@@ -0,0 +1,85 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const STACK_THICKNESS = 15;
+
+function init(callback) {
+ let iframe = gBrowser.ownerDocument.createElement("iframe");
+
+ iframe.addEventListener("load", function onLoad() {
+ iframe.removeEventListener("load", onLoad, true);
+ callback(iframe);
+
+ gBrowser.parentNode.removeChild(iframe);
+ finish();
+ }, true);
+
+ iframe.setAttribute("src", ["data:text/html,",
+ "<!DOCTYPE html>",
+ "<html>",
+ "<body style='margin: 0;'>",
+ "<div>",
+ "<p>Foo</p>",
+ "<div>",
+ "<span>Bar</span>",
+ "</div>",
+ "<div></div>",
+ "</div>",
+ "</body>",
+ "</html>"
+ ].join(""));
+
+ gBrowser.parentNode.appendChild(iframe);
+}
+
+function nodeCallback(aContentWindow, aNode, aParentPosition) {
+ let coord = TiltUtils.DOM.getNodePosition(aContentWindow, aNode, aParentPosition);
+
+ if (aNode.localName != "div")
+ coord.thickness = 0;
+
+ if (aNode.localName == "span")
+ coord.depth += STACK_THICKNESS;
+
+ return coord;
+}
+
+function test() {
+ waitForExplicitFinish();
+ ok(TiltUtils, "The TiltUtils object doesn't exist.");
+
+ let dom = TiltUtils.DOM;
+ ok(dom, "The TiltUtils.DOM wasn't found.");
+
+ init(function(iframe) {
+ let store = dom.traverse(iframe.contentWindow, {
+ nodeCallback: nodeCallback
+ });
+
+ let expected = [
+ { name: "html", depth: 0 * STACK_THICKNESS, thickness: 0 },
+ { name: "head", depth: 0 * STACK_THICKNESS, thickness: 0 },
+ { name: "body", depth: 0 * STACK_THICKNESS, thickness: 0 },
+ { name: "div", depth: 0 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "p", depth: 1 * STACK_THICKNESS, thickness: 0 },
+ { name: "div", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "div", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
+ { name: "span", depth: 3 * STACK_THICKNESS, thickness: 0 },
+ ];
+
+ is(store.nodes.length, expected.length,
+ "The traverse() function didn't walk the correct number of nodes.");
+ is(store.info.length, expected.length,
+ "The traverse() function didn't examine the correct number of nodes.");
+
+ for (let i = 0; i < expected.length; i++) {
+ is(store.info[i].name, expected[i].name,
+ "traversed node " + (i + 1) + " isn't the expected one.");
+ is(store.info[i].coord.depth, expected[i].depth,
+ "traversed node " + (i + 1) + " doesn't have the expected depth.");
+ is(store.info[i].coord.thickness, expected[i].thickness,
+ "traversed node " + (i + 1) + " doesn't have the expected thickness.");
+ }
+ });
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_visualizer.js b/toolkit/devtools/tilt/test/browser_tilt_visualizer.js
new file mode 100644
index 000000000..74f906ff0
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_visualizer.js
@@ -0,0 +1,128 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping notifications test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping visualizer test because WebGL isn't supported.");
+ return;
+ }
+
+ let webGLError = false;
+ let webGLLoad = false;
+
+ let visualizer = new TiltVisualizer({
+ chromeWindow: window,
+ contentWindow: gBrowser.selectedBrowser.contentWindow,
+ parentNode: gBrowser.selectedBrowser.parentNode,
+ notifications: Tilt.NOTIFICATIONS,
+ tab: gBrowser.selectedTab,
+
+ onError: function onWebGLError()
+ {
+ webGLError = true;
+ },
+
+ onLoad: function onWebGLLoad()
+ {
+ webGLLoad = true;
+ }
+ });
+ visualizer.init();
+
+ ok(webGLError ^ webGLLoad,
+ "The WebGL context should either be created or not.");
+
+ if (webGLError) {
+ info("Skipping visualizer test because WebGL couldn't be initialized.");
+ return;
+ }
+
+ ok(visualizer.canvas,
+ "Visualizer constructor should have created a child canvas object.");
+ ok(visualizer.presenter,
+ "Visualizer constructor should have created a child presenter object.");
+ ok(visualizer.controller,
+ "Visualizer constructor should have created a child controller object.");
+ ok(visualizer.isInitialized(),
+ "The visualizer should have been initialized properly.");
+ ok(visualizer.presenter.isInitialized(),
+ "The visualizer presenter should have been initialized properly.");
+ ok(visualizer.controller.isInitialized(),
+ "The visualizer controller should have been initialized properly.");
+
+ testPresenter(visualizer.presenter);
+ testController(visualizer.controller);
+
+ visualizer.removeOverlay();
+ is(visualizer.canvas.parentNode, null,
+ "The visualizer canvas wasn't removed from the parent node.");
+
+ visualizer.cleanup();
+ is(visualizer.presenter, undefined,
+ "The visualizer presenter wasn't destroyed.");
+ is(visualizer.controller, undefined,
+ "The visualizer controller wasn't destroyed.");
+ is(visualizer.canvas, undefined,
+ "The visualizer canvas wasn't destroyed.");
+}
+
+function testPresenter(presenter) {
+ ok(presenter._renderer,
+ "The presenter renderer wasn't initialized properly.");
+ ok(presenter._visualizationProgram,
+ "The presenter visualizationProgram wasn't initialized properly.");
+ ok(presenter._texture,
+ "The presenter texture wasn't initialized properly.");
+ ok(!presenter._meshStacks,
+ "The presenter meshStacks shouldn't be initialized yet.");
+ ok(!presenter._meshWireframe,
+ "The presenter meshWireframe shouldn't be initialized yet.");
+ ok(presenter._traverseData,
+ "The presenter nodesInformation wasn't initialized properly.");
+ ok(presenter._highlight,
+ "The presenter highlight wasn't initialized properly.");
+ ok(presenter._highlight.disabled,
+ "The presenter highlight should be initially disabled.");
+ ok(isApproxVec(presenter._highlight.v0, [0, 0, 0]),
+ "The presenter highlight first vertex should be initially zeroed.");
+ ok(isApproxVec(presenter._highlight.v1, [0, 0, 0]),
+ "The presenter highlight second vertex should be initially zeroed.");
+ ok(isApproxVec(presenter._highlight.v2, [0, 0, 0]),
+ "The presenter highlight third vertex should be initially zeroed.");
+ ok(isApproxVec(presenter._highlight.v3, [0, 0, 0]),
+ "The presenter highlight fourth vertex should be initially zeroed.");
+ ok(presenter.transforms,
+ "The presenter transforms wasn't initialized properly.");
+ is(presenter.transforms.zoom, 1,
+ "The presenter transforms zoom should be initially 1.");
+ ok(isApproxVec(presenter.transforms.offset, [0, 0, 0]),
+ "The presenter transforms offset should be initially zeroed.");
+ ok(isApproxVec(presenter.transforms.translation, [0, 0, 0]),
+ "The presenter transforms translation should be initially zeroed.");
+ ok(isApproxVec(presenter.transforms.rotation, [0, 0, 0, 1]),
+ "The presenter transforms rotation should be initially set to identity.");
+
+ presenter.setTranslation([1, 2, 3]);
+ presenter.setRotation([5, 6, 7, 8]);
+
+ ok(isApproxVec(presenter.transforms.translation, [1, 2, 3]),
+ "The presenter transforms translation wasn't modified as it should");
+ ok(isApproxVec(presenter.transforms.rotation, [5, 6, 7, 8]),
+ "The presenter transforms rotation wasn't modified as it should");
+ ok(presenter._redraw,
+ "The new transforms should have issued a redraw request.");
+}
+
+function testController(controller) {
+ ok(controller.arcball,
+ "The controller arcball wasn't initialized properly.");
+ ok(!controller.coordinates,
+ "The presenter meshWireframe shouldn't be initialized yet.");
+}
diff --git a/toolkit/devtools/tilt/test/browser_tilt_zoom.js b/toolkit/devtools/tilt/test/browser_tilt_zoom.js
new file mode 100644
index 000000000..687eb40b1
--- /dev/null
+++ b/toolkit/devtools/tilt/test/browser_tilt_zoom.js
@@ -0,0 +1,93 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const ZOOM = 2;
+const RESIZE = 50;
+let tiltOpened = false;
+
+function test() {
+ if (!isTiltEnabled()) {
+ aborting();
+ info("Skipping controller test because Tilt isn't enabled.");
+ return;
+ }
+ if (!isWebGLSupported()) {
+ aborting();
+ info("Skipping controller test because WebGL isn't supported.");
+ return;
+ }
+
+ waitForExplicitFinish();
+
+ createTab(function() {
+ TiltUtils.setDocumentZoom(window, ZOOM);
+
+ createTilt({
+ onTiltOpen: function(instance)
+ {
+ tiltOpened = true;
+
+ ok(isApprox(instance.presenter._getPageZoom(), ZOOM),
+ "The Highlighter zoom doesn't have the expected results.");
+
+ ok(isApprox(instance.presenter.transforms.zoom, ZOOM),
+ "The presenter transforms zoom wasn't initially set correctly.");
+
+ let contentWindow = gBrowser.selectedBrowser.contentWindow;
+ let initialWidth = contentWindow.innerWidth;
+ let initialHeight = contentWindow.innerHeight;
+
+ let renderer = instance.presenter._renderer;
+ let arcball = instance.controller.arcball;
+
+ ok(isApprox(contentWindow.innerWidth * ZOOM, renderer.width, 1),
+ "The renderer width wasn't set correctly before the resize.");
+ ok(isApprox(contentWindow.innerHeight * ZOOM, renderer.height, 1),
+ "The renderer height wasn't set correctly before the resize.");
+
+ ok(isApprox(contentWindow.innerWidth * ZOOM, arcball.width, 1),
+ "The arcball width wasn't set correctly before the resize.");
+ ok(isApprox(contentWindow.innerHeight * ZOOM, arcball.height, 1),
+ "The arcball height wasn't set correctly before the resize.");
+
+
+ window.resizeBy(-RESIZE * ZOOM, -RESIZE * ZOOM);
+
+ executeSoon(function() {
+ ok(isApprox(contentWindow.innerWidth + RESIZE, initialWidth, 1),
+ "The content window width wasn't set correctly after the resize.");
+ ok(isApprox(contentWindow.innerHeight + RESIZE, initialHeight, 1),
+ "The content window height wasn't set correctly after the resize.");
+
+ ok(isApprox(contentWindow.innerWidth * ZOOM, renderer.width, 1),
+ "The renderer width wasn't set correctly after the resize.");
+ ok(isApprox(contentWindow.innerHeight * ZOOM, renderer.height, 1),
+ "The renderer height wasn't set correctly after the resize.");
+
+ ok(isApprox(contentWindow.innerWidth * ZOOM, arcball.width, 1),
+ "The arcball width wasn't set correctly after the resize.");
+ ok(isApprox(contentWindow.innerHeight * ZOOM, arcball.height, 1),
+ "The arcball height wasn't set correctly after the resize.");
+
+
+ window.resizeBy(RESIZE * ZOOM, RESIZE * ZOOM);
+
+
+ Services.obs.addObserver(cleanup, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+ }
+ }, false, function suddenDeath()
+ {
+ ok(false, "Tilt could not be initialized properly.");
+ cleanup();
+ });
+ });
+}
+
+function cleanup() {
+ if (tiltOpened) { Services.obs.removeObserver(cleanup, DESTROYED); }
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/toolkit/devtools/tilt/test/head.js b/toolkit/devtools/tilt/test/head.js
new file mode 100644
index 000000000..8d3dbf696
--- /dev/null
+++ b/toolkit/devtools/tilt/test/head.js
@@ -0,0 +1,215 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let {devtools} = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
+let TiltManager = devtools.require("devtools/tilt/tilt").TiltManager;
+let TiltGL = devtools.require("devtools/tilt/tilt-gl");
+let {EPSILON, TiltMath, vec3, mat3, mat4, quat4} = devtools.require("devtools/tilt/tilt-math");
+let TiltUtils = devtools.require("devtools/tilt/tilt-utils");
+let {TiltVisualizer} = devtools.require("devtools/tilt/tilt-visualizer");
+
+let tempScope = {};
+Components.utils.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope);
+let LayoutHelpers = tempScope.LayoutHelpers;
+
+const DEFAULT_HTML = "data:text/html," +
+ "<DOCTYPE html>" +
+ "<html>" +
+ "<head>" +
+ "<meta charset='utf-8'/>" +
+ "<title>Three Laws</title>" +
+ "</head>" +
+ "<body>" +
+ "<div id='first-law'>" +
+ "A robot may not injure a human being or, through inaction, allow a " +
+ "human being to come to harm." +
+ "</div>" +
+ "<div>" +
+ "A robot must obey the orders given to it by human beings, except " +
+ "where such orders would conflict with the First Law." +
+ "</div>" +
+ "<div>" +
+ "A robot must protect its own existence as long as such protection " +
+ "does not conflict with the First or Second Laws." +
+ "</div>" +
+ "<div id='far-far-away' style='position: absolute; top: 250%;'>" +
+ "I like bacon." +
+ "</div>" +
+ "<body>" +
+ "</html>";
+
+let Tilt = TiltManager.getTiltForBrowser(window);
+
+const STARTUP = Tilt.NOTIFICATIONS.STARTUP;
+const INITIALIZING = Tilt.NOTIFICATIONS.INITIALIZING;
+const INITIALIZED = Tilt.NOTIFICATIONS.INITIALIZED;
+const DESTROYING = Tilt.NOTIFICATIONS.DESTROYING;
+const BEFORE_DESTROYED = Tilt.NOTIFICATIONS.BEFORE_DESTROYED;
+const DESTROYED = Tilt.NOTIFICATIONS.DESTROYED;
+const SHOWN = Tilt.NOTIFICATIONS.SHOWN;
+const HIDDEN = Tilt.NOTIFICATIONS.HIDDEN;
+const HIGHLIGHTING = Tilt.NOTIFICATIONS.HIGHLIGHTING;
+const UNHIGHLIGHTING = Tilt.NOTIFICATIONS.UNHIGHLIGHTING;
+const NODE_REMOVED = Tilt.NOTIFICATIONS.NODE_REMOVED;
+
+const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled");
+
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+ gDevTools.testing = false;
+});
+
+function isTiltEnabled() {
+ info("Apparently, Tilt is" + (TILT_ENABLED ? "" : " not") + " enabled.");
+ return TILT_ENABLED;
+}
+
+function isWebGLSupported() {
+ let supported = !TiltGL.isWebGLForceEnabled() &&
+ TiltGL.isWebGLSupported() &&
+ TiltGL.create3DContext(createCanvas());
+
+ info("Apparently, WebGL is" + (supported ? "" : " not") + " supported.");
+ return supported;
+}
+
+function isApprox(num1, num2, delta) {
+ if (Math.abs(num1 - num2) > (delta || EPSILON)) {
+ info("isApprox expected " + num1 + ", got " + num2 + " instead.");
+ return false;
+ }
+ return true;
+}
+
+function isApproxVec(vec1, vec2, delta) {
+ vec1 = Array.prototype.slice.call(vec1);
+ vec2 = Array.prototype.slice.call(vec2);
+
+ if (vec1.length !== vec2.length) {
+ return false;
+ }
+ for (let i = 0, len = vec1.length; i < len; i++) {
+ if (!isApprox(vec1[i], vec2[i], delta)) {
+ info("isApproxVec expected [" + vec1 + "], got [" + vec2 + "] instead.");
+ return false;
+ }
+ }
+ return true;
+}
+
+function isEqualVec(vec1, vec2) {
+ vec1 = Array.prototype.slice.call(vec1);
+ vec2 = Array.prototype.slice.call(vec2);
+
+ if (vec1.length !== vec2.length) {
+ return false;
+ }
+ for (let i = 0, len = vec1.length; i < len; i++) {
+ if (vec1[i] !== vec2[i]) {
+ info("isEqualVec expected [" + vec1 + "], got [" + vec2 + "] instead.");
+ return false;
+ }
+ }
+ return true;
+}
+
+function createCanvas() {
+ return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+}
+
+
+function createTab(callback, location) {
+ info("Creating a tab, with callback " + typeof callback +
+ ", and location " + location + ".");
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab();
+
+ gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+ callback(tab);
+ }, true);
+
+ gBrowser.selectedBrowser.contentWindow.location = location || DEFAULT_HTML;
+ return tab;
+}
+
+
+function createTilt(callbacks, close, suddenDeath) {
+ info("Creating Tilt, with callbacks {" + Object.keys(callbacks) + "}" +
+ ", autoclose param " + close +
+ ", and sudden death handler " + typeof suddenDeath + ".");
+
+ handleFailure(suddenDeath);
+
+ Services.prefs.setBoolPref("webgl.verbose", true);
+ TiltUtils.Output.suppressAlerts = true;
+
+ info("Attempting to start Tilt.");
+ Services.obs.addObserver(onTiltOpen, INITIALIZING, false);
+ Tilt.toggle();
+
+ function onTiltOpen() {
+ info("Tilt was opened.");
+ Services.obs.removeObserver(onTiltOpen, INITIALIZING);
+
+ executeSoon(function() {
+ if ("function" === typeof callbacks.onTiltOpen) {
+ info("Calling 'onTiltOpen'.");
+ callbacks.onTiltOpen(Tilt.visualizers[Tilt.currentWindowId]);
+ }
+ if (close) {
+ executeSoon(function() {
+ info("Attempting to close Tilt.");
+ Services.obs.addObserver(onTiltClose, DESTROYED, false);
+ Tilt.destroy(Tilt.currentWindowId);
+ });
+ }
+ });
+ }
+
+ function onTiltClose() {
+ info("Tilt was closed.");
+ Services.obs.removeObserver(onTiltClose, DESTROYED);
+
+ executeSoon(function() {
+ if ("function" === typeof callbacks.onTiltClose) {
+ info("Calling 'onTiltClose'.");
+ callbacks.onTiltClose();
+ }
+ if ("function" === typeof callbacks.onEnd) {
+ info("Calling 'onEnd'.");
+ callbacks.onEnd();
+ }
+ });
+ }
+
+ function handleFailure(suddenDeath) {
+ Tilt.failureCallback = function() {
+ info("Tilt FAIL.");
+ Services.obs.removeObserver(onTiltOpen, INITIALIZING);
+
+ info("Now relying on sudden death handler " + typeof suddenDeath + ".");
+ suddenDeath && suddenDeath();
+ }
+ }
+}
+
+function getPickablePoint(presenter) {
+ let vertices = presenter._meshStacks[0].vertices.components;
+
+ let topLeft = vec3.create([vertices[0], vertices[1], vertices[2]]);
+ let bottomRight = vec3.create([vertices[6], vertices[7], vertices[8]]);
+ let center = vec3.lerp(topLeft, bottomRight, 0.5, []);
+
+ let renderer = presenter._renderer;
+ let viewport = [0, 0, renderer.width, renderer.height];
+
+ return vec3.project(center, viewport, renderer.mvMatrix, renderer.projMatrix);
+}
+
+function aborting() {
+ // Tilt aborting and we need at least one pass, fail or todo so let's add a
+ // dummy pass.
+ ok(true, "Test aborted early.");
+}