diff options
Diffstat (limited to 'dom/html/test')
731 files changed, 51889 insertions, 0 deletions
diff --git a/dom/html/test/347174transform.xsl b/dom/html/test/347174transform.xsl new file mode 100644 index 000000000..1b201de3f --- /dev/null +++ b/dom/html/test/347174transform.xsl @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> +<xsl:template match="/"> +<html> +<head> +<script> +window.parent.frameScriptTag(document.readyState); + +function attachCustomEventListener(element, eventName, command) { + if (window.addEventListener && !window.opera) + element.addEventListener(eventName, command, true); + else if (window.attachEvent) + element.attachEvent("on" + eventName, command); +} + +function load() { + window.parent.frameLoad(document.readyState); +} + +function readyStateChange() { + window.parent.frameReadyStateChange(document.readyState); +} + +function DOMContentLoaded() { + window.parent.frameDOMContentLoaded(document.readyState); +} + +window.onload=load; + +attachCustomEventListener(document, "readystatechange", readyStateChange); +attachCustomEventListener(document, "DOMContentLoaded", DOMContentLoaded); + +</script> +</head> +<body> +</body> +</html> +</xsl:template> + +</xsl:stylesheet>
\ No newline at end of file diff --git a/dom/html/test/347174transformable.xml b/dom/html/test/347174transformable.xml new file mode 100644 index 000000000..68f7bc6dc --- /dev/null +++ b/dom/html/test/347174transformable.xml @@ -0,0 +1,3 @@ +<?xml version='1.0'?> +<?xml-stylesheet type="text/xsl" href="347174transform.xsl"?> +<doc>This is a sample document.</doc> diff --git a/dom/html/test/allowMedia.sjs b/dom/html/test/allowMedia.sjs new file mode 100644 index 000000000..f29619cd8 --- /dev/null +++ b/dom/html/test/allowMedia.sjs @@ -0,0 +1,12 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(req, resp) { + resp.setHeader("Cache-Control", "no-cache", false); + resp.setHeader("Content-Type", "text/plain", false); + + let stateKey = "allowMediaState"; + let state = getState(stateKey); + setState(stateKey, req.queryString ? "FAIL" : ""); + resp.write(state || "PASS"); +} diff --git a/dom/html/test/browser.ini b/dom/html/test/browser.ini new file mode 100644 index 000000000..49caea726 --- /dev/null +++ b/dom/html/test/browser.ini @@ -0,0 +1,25 @@ +[DEFAULT] +support-files = + bug592641_img.jpg + dummy_page.html + file_bug649778.html + file_bug649778.html^headers^ + file_fullscreen-api-keys.html + file_content_contextmenu.html + head.js + +[browser_bug592641.js] +[browser_bug649778.js] +skip-if = e10s # Bug 1271025 +[browser_bug1081537.js] +[browser_bug1108547.js] +support-files = + file_bug1108547-1.html + file_bug1108547-2.html + file_bug1108547-3.html +[browser_content_contextmenu_userinput.js] +[browser_DOMDocElementInserted.js] +[browser_fullscreen-api-keys.js] +tags = fullscreen +[browser_fullscreen-contextmenu-esc.js] +tags = fullscreen diff --git a/dom/html/test/browser_DOMDocElementInserted.js b/dom/html/test/browser_DOMDocElementInserted.js new file mode 100644 index 000000000..9fa8335e6 --- /dev/null +++ b/dom/html/test/browser_DOMDocElementInserted.js @@ -0,0 +1,24 @@ +// Tests that the DOMDocElementInserted event is visible on the frame +add_task(function*() { + let tab = gBrowser.addTab(); + let uri = "data:text/html;charset=utf-8,<html/>" + + let eventPromise = ContentTask.spawn(tab.linkedBrowser, null, function() { + Cu.import("resource://gre/modules/PromiseUtils.jsm"); + let deferred = PromiseUtils.defer(); + + let listener = (event) => { + removeEventListener("DOMDocElementInserted", listener, true); + deferred.resolve(event.target.documentURIObject.spec); + }; + addEventListener("DOMDocElementInserted", listener, true); + + return deferred.promise; + }); + + tab.linkedBrowser.loadURI(uri); + let loadedURI = yield eventPromise; + is(loadedURI, uri, "Should have seen the event for the right URI"); + + gBrowser.removeTab(tab); +}); diff --git a/dom/html/test/browser_bug1081537.js b/dom/html/test/browser_bug1081537.js new file mode 100644 index 000000000..8ae53e4ff --- /dev/null +++ b/dom/html/test/browser_bug1081537.js @@ -0,0 +1,11 @@ +// This test is useful because mochitest-browser runs as an addon, so we test +// addon-scope paths here. +var ifr; +function test() { + ifr = document.createElement('iframe'); + document.getElementById('main-window').appendChild(ifr); + is(ifr.contentDocument.nodePrincipal.origin, "[System Principal]"); + ifr.contentDocument.open(); + ok(true, "Didn't throw"); +} +registerCleanupFunction(() => ifr.remove()); diff --git a/dom/html/test/browser_bug1108547.js b/dom/html/test/browser_bug1108547.js new file mode 100644 index 000000000..711dac0aa --- /dev/null +++ b/dom/html/test/browser_bug1108547.js @@ -0,0 +1,113 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +requestLongerTimeout(2); + +function test() { + waitForExplicitFinish(); + + runPass("file_bug1108547-2.html", function() { + runPass("file_bug1108547-3.html", function() { + finish(); + }); + }); +} + +function runPass(getterFile, finishedCallback) { + var rootDir = "http://mochi.test:8888/browser/dom/html/test/"; + var testBrowser; + var privateWin; + + function whenDelayedStartupFinished(win, callback) { + let topic = "browser-delayed-startup-finished"; + Services.obs.addObserver(function onStartup(aSubject) { + if (win != aSubject) + return; + + Services.obs.removeObserver(onStartup, topic); + executeSoon(callback); + }, topic, false); + } + + // First, set the cookie in a normal window. + gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug1108547-1.html"); + BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpenCookieSetter); + + function afterOpenCookieSetter() { + gBrowser.removeCurrentTab(); + + // Now, open a private window. + privateWin = OpenBrowserWindow({private: true}); + whenDelayedStartupFinished(privateWin, afterPrivateWindowOpened); + } + + function afterPrivateWindowOpened() { + // In the private window, open the getter file, and wait for a new tab to be opened. + privateWin.gBrowser.selectedTab = privateWin.gBrowser.addTab(rootDir + getterFile); + testBrowser = privateWin.gBrowser.selectedBrowser; + privateWin.gBrowser.tabContainer.addEventListener("TabOpen", onNewTabOpened, true); + } + + function fetchResult() { + return ContentTask.spawn(testBrowser, null, function() { + return content.document.getElementById("result").textContent; + }); + } + + function onNewTabOpened() { + // When the new tab is opened, wait for it to load. + privateWin.gBrowser.tabContainer.removeEventListener("TabOpen", onNewTabOpened, true); + BrowserTestUtils.browserLoaded(privateWin.gBrowser.tabs[privateWin.gBrowser.tabs.length - 1].linkedBrowser).then(fetchResult).then(onNewTabLoaded); + } + + function onNewTabLoaded(result) { + // Now, ensure that the private tab doesn't have access to the cookie set in normal mode. + is(result, "", "Shouldn't have access to the cookies"); + + // We're done with the private window, close it. + privateWin.close(); + + // Clear all cookies. + Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager).removeAll(); + + // Open a new private window, this time to set a cookie inside it. + privateWin = OpenBrowserWindow({private: true}); + whenDelayedStartupFinished(privateWin, afterPrivateWindowOpened2); + } + + function afterPrivateWindowOpened2() { + // In the private window, open the setter file, and wait for it to load. + privateWin.gBrowser.selectedTab = privateWin.gBrowser.addTab(rootDir + "file_bug1108547-1.html"); + BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser).then(afterOpenCookieSetter2); + } + + function afterOpenCookieSetter2() { + // We're done with the private window now, close it. + privateWin.close(); + + // Now try to read the cookie in a normal window, and wait for a new tab to be opened. + gBrowser.selectedTab = gBrowser.addTab(rootDir + getterFile); + testBrowser = gBrowser.selectedBrowser; + gBrowser.tabContainer.addEventListener("TabOpen", onNewTabOpened2, true); + } + + function onNewTabOpened2() { + // When the new tab is opened, wait for it to load. + gBrowser.tabContainer.removeEventListener("TabOpen", onNewTabOpened2, true); + BrowserTestUtils.browserLoaded(gBrowser.tabs[gBrowser.tabs.length - 1].linkedBrowser).then(fetchResult).then(onNewTabLoaded2); + } + + function onNewTabLoaded2(result) { + // Now, ensure that the normal tab doesn't have access to the cookie set in private mode. + is(result, "", "Shouldn't have access to the cookies"); + + // Remove both of the tabs opened here. + gBrowser.removeCurrentTab(); + gBrowser.removeCurrentTab(); + + privateWin = null; + testBrowser = null; + + finishedCallback(); + } +} diff --git a/dom/html/test/browser_bug592641.js b/dom/html/test/browser_bug592641.js new file mode 100644 index 000000000..94e2e92c2 --- /dev/null +++ b/dom/html/test/browser_bug592641.js @@ -0,0 +1,61 @@ +// Test for bug 592641 - Image document doesn't show dimensions of cached images + +// Globals +var testPath = "http://mochi.test:8888/browser/dom/html/test/"; +var ctx = {loadsDone : 0}; + +// Entry point from Mochikit +function test() { + + waitForExplicitFinish(); + + ctx.tab1 = gBrowser.addTab(testPath + "bug592641_img.jpg"); + ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1); + ctx.tab1Browser.addEventListener("load", load1Soon, true); +} + +function checkTitle(title) { + + ctx.loadsDone++; + ok(/^bug592641_img\.jpg \(JPEG Image, 1500\u00A0\u00D7\u00A01500 pixels\)/.test(title), + "Title should be correct on load #" + ctx.loadsDone); +} + +function load1Soon() { + ctx.tab1Browser.removeEventListener("load", load1Soon, true); + // onload is fired in OnStopDecode, so let's use executeSoon() to make sure + // that any other OnStopDecode event handlers get the chance to fire first. + executeSoon(load1Done); +} + +function load1Done() { + // Check the title + var title = ctx.tab1Browser.contentTitle; + checkTitle(title); + + // Try loading the same image in a new tab to make sure things work in + // the cached case. + ctx.tab2 = gBrowser.addTab(testPath + "bug592641_img.jpg"); + ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2); + ctx.tab2Browser.addEventListener("load", load2Soon, true); +} + +function load2Soon() { + ctx.tab2Browser.removeEventListener("load", load2Soon, true); + // onload is fired in OnStopDecode, so let's use executeSoon() to make sure + // that any other OnStopDecode event handlers get the chance to fire first. + executeSoon(load2Done); +} + +function load2Done() { + // Check the title + var title = ctx.tab2Browser.contentTitle; + checkTitle(title); + + // Clean up + gBrowser.removeTab(ctx.tab1); + gBrowser.removeTab(ctx.tab2); + + // Test done + finish(); +} diff --git a/dom/html/test/browser_bug649778.js b/dom/html/test/browser_bug649778.js new file mode 100644 index 000000000..6356d20fe --- /dev/null +++ b/dom/html/test/browser_bug649778.js @@ -0,0 +1,82 @@ +// Test for bug 649778 - document.write may cause a document to be written to disk cache even when the page has Cache-Control: no-store + +// Globals +var testPath = "http://mochi.test:8888/browser/dom/html/test/"; +var popup; + +var {LoadContextInfo} = Cu.import("resource://gre/modules/LoadContextInfo.jsm", null); +var {Services} = Cu.import("resource://gre/modules/Services.jsm", null); + +function checkCache(url, inMemory, shouldExist, cb) +{ + var cache = Services.cache2; + var storage = cache.diskCacheStorage(LoadContextInfo.default, false); + + function CheckCacheListener(inMemory, shouldExist) + { + this.inMemory = inMemory; + this.shouldExist = shouldExist; + this.onCacheEntryCheck = function() { + return Components.interfaces.nsICacheEntryOpenCallback.ENTRY_WANTED; + }; + + this.onCacheEntryAvailable = function oCEA(entry, isNew, appCache, status) { + if (shouldExist) { + ok(entry, "Entry not found"); + is(this.inMemory, !entry.persistent, "Entry is " + (inMemory ? "" : " not ") + " in memory as expected"); + is(status, Components.results.NS_OK, "Entry not found"); + } else { + ok(!entry, "Entry found"); + is(status, Components.results.NS_ERROR_CACHE_KEY_NOT_FOUND, + "Invalid error code"); + } + + setTimeout(cb, 0); + }; + }; + + storage.asyncOpenURI(Services.io.newURI(url, null, null), "", + Components.interfaces.nsICacheStorage.OPEN_READONLY, + new CheckCacheListener(inMemory, shouldExist)); +} +function getPopupURL() { + var sh = popup.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIWebNavigation) + .sessionHistory; + + return sh.getEntryAtIndex(sh.index, false).URI.spec; +} + +var wyciwygURL; +function testContinue() { + wyciwygURL = getPopupURL(); + is(wyciwygURL.substring(0, 10), "wyciwyg://", "Unexpected URL."); + popup.close() + + // We have to find the entry and it must not be persisted to disk + checkCache(wyciwygURL, true, true, finish); +} + +function waitForWyciwygDocument() { + try { + var url = getPopupURL(); + if (url.substring(0, 10) == "wyciwyg://") { + setTimeout(testContinue, 0); + return; + } + } + catch (e) { + } + setTimeout(waitForWyciwygDocument, 100); +} + +// Entry point from Mochikit +function test() { + waitForExplicitFinish(); + + popup = window.open(testPath + "file_bug649778.html", "popup 0", + "height=200,width=200,location=yes," + + "menubar=yes,status=yes,toolbar=yes,dependent=yes"); + + waitForWyciwygDocument(); +} diff --git a/dom/html/test/browser_content_contextmenu_userinput.js b/dom/html/test/browser_content_contextmenu_userinput.js new file mode 100644 index 000000000..7d0387715 --- /dev/null +++ b/dom/html/test/browser_content_contextmenu_userinput.js @@ -0,0 +1,50 @@ +"use strict"; + +const kPage = "http://example.org/browser/" + + "dom/html/test/file_content_contextmenu.html"; + +add_task(function* () { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: kPage + }, function*(aBrowser) { + let contextMenu = document.getElementById("contentAreaContextMenu"); + ok(contextMenu, "Got context menu"); + + info("Open context menu"); + is(contextMenu.state, "closed", "Should not have opened context menu"); + let popupShownPromise = promiseWaitForEvent(window, "popupshown"); + EventUtils.synthesizeMouse(aBrowser, window.innerWidth / 3, + window.innerHeight / 3, + {type: "contextmenu", button: 2}, window); + yield popupShownPromise; + is(contextMenu.state, "open", "Should have opened context menu"); + + let pageMenuSep = document.getElementById("page-menu-separator"); + ok(pageMenuSep && !pageMenuSep.hidden, + "Page menu separator should be shown"); + + let testMenuSep = pageMenuSep.previousSibling; + ok(testMenuSep && !testMenuSep.hidden, + "User-added menu separator should be shown"); + + let testMenuItem = testMenuSep.previousSibling; + is(testMenuItem.label, "Test Context Menu Click", "Got context menu item"); + + let promiseCtxMenuClick = ContentTask.spawn(aBrowser, null, function*() { + yield new Promise(resolve => { + let Ci = Components.interfaces; + let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + let menuitem = content.document.getElementById("menuitem"); + menuitem.addEventListener("click", function() { + Assert.ok(windowUtils.isHandlingUserInput, + "Content menu click should be a user input"); + resolve(); + }); + }); + }); + EventUtils.synthesizeMouseAtCenter(testMenuItem, {}, window); + yield promiseCtxMenuClick; + }); +}); diff --git a/dom/html/test/browser_fullscreen-api-keys.js b/dom/html/test/browser_fullscreen-api-keys.js new file mode 100644 index 000000000..92358efee --- /dev/null +++ b/dom/html/test/browser_fullscreen-api-keys.js @@ -0,0 +1,170 @@ +"use strict"; + +/** Test for Bug 545812 **/ + +// List of key codes which should exit full-screen mode. +const kKeyList = [ + { code: "VK_ESCAPE", suppressed: true}, + { code: "VK_F11", suppressed: false}, +]; + +function frameScript() { + let doc = content.document; + addMessageListener("Test:RequestFullscreen", () => { + doc.body.requestFullscreen(); + }); + addMessageListener("Test:DispatchUntrustedKeyEvents", msg => { + var evt = new content.CustomEvent("Test:DispatchKeyEvents", { + detail: { code: msg.data } + }); + content.dispatchEvent(evt); + }); + + doc.addEventListener("fullscreenchange", () => { + sendAsyncMessage("Test:FullscreenChanged", !!doc.fullscreenElement); + }); + + function keyHandler(evt) { + sendAsyncMessage("Test:KeyReceived", { + type: evt.type, + keyCode: evt.keyCode + }); + } + doc.addEventListener("keydown", keyHandler, true); + doc.addEventListener("keyup", keyHandler, true); + doc.addEventListener("keypress", keyHandler, true); + + function waitUntilActive() { + if (doc.docShell.isActive && doc.hasFocus()) { + sendAsyncMessage("Test:Activated"); + } else { + setTimeout(waitUntilActive, 10); + } + } + waitUntilActive(); +} + +var gMessageManager; + +function listenOneMessage(aMsg, aListener) { + function listener({ data }) { + gMessageManager.removeMessageListener(aMsg, listener); + aListener(data); + } + gMessageManager.addMessageListener(aMsg, listener); +} + +function promiseOneMessage(aMsg) { + return new Promise(resolve => listenOneMessage(aMsg, resolve)); +} + +function captureUnexpectedFullscreenChange() { + ok(false, "Caught an unexpected fullscreen change"); +} + +function* temporaryRemoveUnexpectedFullscreenChangeCapture(callback) { + gMessageManager.removeMessageListener( + "Test:FullscreenChanged", captureUnexpectedFullscreenChange); + yield* callback(); + gMessageManager.addMessageListener( + "Test:FullscreenChanged", captureUnexpectedFullscreenChange); +} + +function captureUnexpectedKeyEvent(type) { + ok(false, `Caught an unexpected ${type} event`); +} + +function* temporaryRemoveUnexpectedKeyEventCapture(callback) { + gMessageManager.removeMessageListener( + "Test:KeyReceived", captureUnexpectedKeyEvent); + yield* callback(); + gMessageManager.addMessageListener( + "Test:KeyReceived", captureUnexpectedKeyEvent); +} + +function receiveExpectedKeyEvents(keyCode) { + return new Promise(resolve => { + let events = ["keydown", "keypress", "keyup"]; + function listener({ data }) { + let expected = events.shift(); + is(data.type, expected, `Should receive a ${expected} event`); + is(data.keyCode, keyCode, + `Should receive the event with key code ${keyCode}`); + if (!events.length) { + gMessageManager.removeMessageListener("Test:KeyReceived", listener); + resolve(); + } + } + gMessageManager.addMessageListener("Test:KeyReceived", listener); + }); +} + +const kPage = "http://example.org/browser/" + + "dom/html/test/file_fullscreen-api-keys.html"; + +add_task(function* () { + yield pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"]); + + let tab = gBrowser.addTab(kPage); + let browser = tab.linkedBrowser; + gBrowser.selectedTab = tab; + registerCleanupFunction(() => gBrowser.removeTab(tab)); + yield waitForDocLoadComplete(); + + gMessageManager = browser.messageManager; + gMessageManager.loadFrameScript( + "data:,(" + frameScript.toString() + ")();", false); + + // Wait for the document being actived, so that + // fullscreen request won't be denied. + yield promiseOneMessage("Test:Activated"); + + // Register listener to capture unexpected events + gMessageManager.addMessageListener( + "Test:FullscreenChanged", captureUnexpectedFullscreenChange); + gMessageManager.addMessageListener( + "Test:KeyReceived", captureUnexpectedKeyEvent); + registerCleanupFunction(() => { + gMessageManager.removeMessageListener( + "Test:FullscreenChanged", captureUnexpectedFullscreenChange); + gMessageManager.removeMessageListener( + "Test:KeyReceived", captureUnexpectedKeyEvent); + }); + + for (let {code, suppressed} of kKeyList) { + var keyCode = KeyEvent["DOM_" + code]; + info(`Test keycode ${code} (${keyCode})`); + + info("Enter fullscreen"); + yield* temporaryRemoveUnexpectedFullscreenChangeCapture(function* () { + gMessageManager.sendAsyncMessage("Test:RequestFullscreen"); + let state = yield promiseOneMessage("Test:FullscreenChanged"); + ok(state, "The content should have entered fullscreen"); + ok(document.fullscreenElement, + "The chrome should also be in fullscreen"); + }); + + info("Dispatch untrusted key events from content"); + yield* temporaryRemoveUnexpectedKeyEventCapture(function* () { + let promiseExpectedKeyEvents = receiveExpectedKeyEvents(keyCode); + gMessageManager.sendAsyncMessage("Test:DispatchUntrustedKeyEvents", code); + yield promiseExpectedKeyEvents; + }); + + info("Send trusted key events"); + yield* temporaryRemoveUnexpectedFullscreenChangeCapture(function* () { + yield* temporaryRemoveUnexpectedKeyEventCapture(function* () { + let promiseExpectedKeyEvents = suppressed ? + Promise.resolve() : receiveExpectedKeyEvents(keyCode); + EventUtils.synthesizeKey(code, {}); + yield promiseExpectedKeyEvents; + let state = yield promiseOneMessage("Test:FullscreenChanged"); + ok(!state, "The content should have exited fullscreen"); + ok(!document.fullscreenElement, + "The chrome should also have exited fullscreen"); + }); + }); + } +}); diff --git a/dom/html/test/browser_fullscreen-contextmenu-esc.js b/dom/html/test/browser_fullscreen-contextmenu-esc.js new file mode 100644 index 000000000..bbc741e47 --- /dev/null +++ b/dom/html/test/browser_fullscreen-contextmenu-esc.js @@ -0,0 +1,107 @@ +"use strict"; + +function frameScript() { + addMessageListener("Test:RequestFullscreen", () => { + content.document.body.requestFullscreen(); + }); + content.document.addEventListener("fullscreenchange", () => { + sendAsyncMessage("Test:FullscreenChanged", + !!content.document.fullscreenElement); + }); + addMessageListener("Test:QueryFullscreenState", () => { + sendAsyncMessage("Test:FullscreenState", + !!content.document.fullscreenElement); + }); + function waitUntilActive() { + let doc = content.document; + if (doc.docShell.isActive && doc.hasFocus()) { + sendAsyncMessage("Test:Activated"); + } else { + setTimeout(waitUntilActive, 10); + } + } + waitUntilActive(); +} + +var gMessageManager; + +function listenOneMessage(aMsg, aListener) { + function listener({ data }) { + gMessageManager.removeMessageListener(aMsg, listener); + aListener(data); + } + gMessageManager.addMessageListener(aMsg, listener); +} + +function promiseOneMessage(aMsg) { + return new Promise(resolve => listenOneMessage(aMsg, resolve)); +} + +function captureUnexpectedFullscreenChange() { + ok(false, "Caught an unexpected fullscreen change"); +} + +const kPage = "http://example.org/browser/dom/html/test/dummy_page.html"; + +add_task(function* () { + yield pushPrefs( + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"]); + + let tab = gBrowser.addTab(kPage); + registerCleanupFunction(() => gBrowser.removeTab(tab)); + let browser = tab.linkedBrowser; + gBrowser.selectedTab = tab; + yield waitForDocLoadComplete(); + + gMessageManager = browser.messageManager; + gMessageManager.loadFrameScript( + "data:,(" + frameScript.toString() + ")();", false); + + // Wait for the document being activated, so that + // fullscreen request won't be denied. + yield promiseOneMessage("Test:Activated"); + + let contextMenu = document.getElementById("contentAreaContextMenu"); + ok(contextMenu, "Got context menu"); + + let state; + info("Enter DOM fullscreen"); + gMessageManager.sendAsyncMessage("Test:RequestFullscreen"); + state = yield promiseOneMessage("Test:FullscreenChanged"); + ok(state, "The content should have entered fullscreen"); + ok(document.fullscreenElement, "The chrome should also be in fullscreen"); + gMessageManager.addMessageListener( + "Test:FullscreenChanged", captureUnexpectedFullscreenChange); + + info("Open context menu"); + is(contextMenu.state, "closed", "Should not have opened context menu"); + let popupShownPromise = promiseWaitForEvent(window, "popupshown"); + EventUtils.synthesizeMouse(browser, screen.width / 2, screen.height / 2, + {type: "contextmenu", button: 2}, window); + yield popupShownPromise; + is(contextMenu.state, "open", "Should have opened context menu"); + + info("Send the first escape"); + let popupHidePromise = promiseWaitForEvent(window, "popuphidden"); + EventUtils.synthesizeKey("VK_ESCAPE", {}); + yield popupHidePromise; + is(contextMenu.state, "closed", "Should have closed context menu"); + + // Wait a small time to confirm that the first ESC key + // does not exit fullscreen. + yield new Promise(resolve => setTimeout(resolve, 1000)); + gMessageManager.sendAsyncMessage("Test:QueryFullscreenState"); + state = yield promiseOneMessage("Test:FullscreenState"); + ok(state, "The content should still be in fullscreen"); + ok(document.fullscreenElement, "The chrome should still be in fullscreen"); + + info("Send the second escape"); + gMessageManager.removeMessageListener( + "Test:FullscreenChanged", captureUnexpectedFullscreenChange); + let fullscreenExitPromise = promiseOneMessage("Test:FullscreenChanged"); + EventUtils.synthesizeKey("VK_ESCAPE", {}); + state = yield fullscreenExitPromise; + ok(!state, "The content should have exited fullscreen"); + ok(!document.fullscreenElement, "The chrome should have exited fullscreen"); +}); diff --git a/dom/html/test/bug100533_iframe.html b/dom/html/test/bug100533_iframe.html new file mode 100644 index 000000000..ddf58a15c --- /dev/null +++ b/dom/html/test/bug100533_iframe.html @@ -0,0 +1,8 @@ +<html> +<head> +<title></title> +</head> +<body> +<form method='get' action='bug100533_load.html' id='b'><input type="submit"/></form> +</body> +</html> diff --git a/dom/html/test/bug100533_load.html b/dom/html/test/bug100533_load.html new file mode 100644 index 000000000..99cf26640 --- /dev/null +++ b/dom/html/test/bug100533_load.html @@ -0,0 +1,14 @@ +<html> +<head> +<title></title> +</head> + + +<body onload="parent.submitted();"> + +<span id="foo"></span> + + + +</body> +</html> diff --git a/dom/html/test/bug1260704_iframe.html b/dom/html/test/bug1260704_iframe.html new file mode 100644 index 000000000..41d238958 --- /dev/null +++ b/dom/html/test/bug1260704_iframe.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript"> + var noDefault = (location.search.indexOf("noDefault=true") !== -1); + var isMap = (location.search.indexOf("isMap=true") !== -1); + + window.addEventListener("load", () => { + let image = document.getElementById("testImage"); + isMap ? image.setAttribute("ismap", "") : image.removeAttribute("ismap"); + image.addEventListener("click", event => { + if (noDefault) { + ok(true, "image element prevents default"); + event.preventDefault(); + } + }, false); + + window.addEventListener("click", event => { + ok(true, "expected prevent default = " + noDefault); + ok(true, "actual prevent default = " + event.defaultPrevented); + ok(event.defaultPrevented == noDefault, "PreventDefault should work fine"); + if (noDefault) { + window.parent.postMessage("finished", "http://mochi.test:8888"); + } + }, false); + window.parent.postMessage("started", "http://mochi.test:8888"); + }, false); + </script> +</head> +<body> +<a href="bug1260704_iframe_empty.html"> + <img id="testImage" src="file_bug1260704.png" width="100" height="100"/> +</a> +</body> +</html> diff --git a/dom/html/test/bug1260704_iframe_empty.html b/dom/html/test/bug1260704_iframe_empty.html new file mode 100644 index 000000000..3c90f9f13 --- /dev/null +++ b/dom/html/test/bug1260704_iframe_empty.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript"> + window.addEventListener("load", () => { + window.parent.postMessage("empty_frame_loaded", "http://mochi.test:8888"); + }, false); + </script> +</head> +<body> +</body> +</html> diff --git a/dom/html/test/bug1292522_iframe.html b/dom/html/test/bug1292522_iframe.html new file mode 100644 index 000000000..99a3369d0 --- /dev/null +++ b/dom/html/test/bug1292522_iframe.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html><head><title>iframe</title></head> + <body> + <p>var testvar = "testiframe"</p> + <script> + document.domain='example.org'; + var testvar = "testiframe"; + </script> + </body> +</html> diff --git a/dom/html/test/bug1292522_page.html b/dom/html/test/bug1292522_page.html new file mode 100644 index 000000000..9570f12d2 --- /dev/null +++ b/dom/html/test/bug1292522_page.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <title>Test for Bug 1292522</title> + <script> + var check_var = function() { + opener.postMessage(document.getElementsByTagName('iframe')[0].contentWindow.testvar, "http://mochi.test:8888"); + } + </script> + </head> + <body> + <iframe src="http://test2.example.org:80/tests/dom/html/test/bug1292522_iframe.html" onload="document.domain='example.org';check_var();"></iframe> + </body> +</html> diff --git a/dom/html/test/bug1315146-iframe.html b/dom/html/test/bug1315146-iframe.html new file mode 100644 index 000000000..280db5305 --- /dev/null +++ b/dom/html/test/bug1315146-iframe.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<script> +document.domain = "example.org"; +</script> diff --git a/dom/html/test/bug1315146-main.html b/dom/html/test/bug1315146-main.html new file mode 100644 index 000000000..e9f356dda --- /dev/null +++ b/dom/html/test/bug1315146-main.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<iframe src="http://example.org/tests/dom/html/test/bug1315146-iframe.html"></iframe> +<input value="test"> +<script> +document.domain = "example.org"; +onload = function() { + let iframe = document.querySelector("iframe"); + let input = document.querySelector("input"); + input.selectionStart = input.selectionEnd = 2; + document.body.style.overflow = "scroll"; + iframe.contentDocument.body.offsetWidth; + opener.postMessage({start: input.selectionStart, + end: input.selectionEnd}, "*"); +} +</script> diff --git a/dom/html/test/bug196523-subframe.html b/dom/html/test/bug196523-subframe.html new file mode 100644 index 000000000..ac53572a7 --- /dev/null +++ b/dom/html/test/bug196523-subframe.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<script> + function checkDomain(str, msg) { + window.parent.postMessage((str == document.domain) + ";" +msg, + "http://mochi.test:8888"); + } + + function reportException(msg) { + window.parent.postMessage(false + ";" + msg, "http://mochi.test:8888"); + } + + var win1; + try { + win1 = window.open("", "", "width=100,height=100"); + var otherDomain1 = win1.document.domain; + win1.close(); + checkDomain(otherDomain1, "Opened document should have our domain"); + } catch(e) { + reportException("Exception getting document.domain: " + e); + } finally { + win1.close(); + } + + document.domain = "example.org"; + + var win2; + try { + win2 = window.open("", "", "width=100,height=100"); + var otherDomain2 = win2.document.domain; + checkDomain(otherDomain2, "Opened document should have our domain"); + win2.close(); + } catch(e) { + reportException("Exception getting document.domain after domain set: " + e); + } finally { + win2.close(); + } +</script> diff --git a/dom/html/test/bug199692-nested-d2.html b/dom/html/test/bug199692-nested-d2.html new file mode 100644 index 000000000..70064efe7 --- /dev/null +++ b/dom/html/test/bug199692-nested-d2.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=199692 +--> +<head> + <title>Nested, nested iframe for bug 199692 tests</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +</head> +<body> + <div id="nest2div" style="border: 2px dotted blue;">nested, depth 2</div> +</body> +</html> + diff --git a/dom/html/test/bug199692-nested.html b/dom/html/test/bug199692-nested.html new file mode 100644 index 000000000..27201a953 --- /dev/null +++ b/dom/html/test/bug199692-nested.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=199692 +--> +<head> + <title>Nested iframe for bug 199692 tests</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +</head> +<body> + <div id="nest1div" style="border: 2px dotted green;">nested, depth 1</div> + <iframe src="bug199692-nested-d2.html"></iframe> +</body> +</html> + diff --git a/dom/html/test/bug199692-popup.html b/dom/html/test/bug199692-popup.html new file mode 100644 index 000000000..29512823e --- /dev/null +++ b/dom/html/test/bug199692-popup.html @@ -0,0 +1,188 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=199692 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>Popup in test for Bug 199692</title> + <style type="text/css"> +#content * { + border: 2px solid black; + margin: 2px; + clear: both; + height: 20px; + overflow: hidden; +} + +#txt, #static, #fixed, #absolute, #relative, #hidden, #float, #empty, #static, #relative { + width: 200px !important; +} + </style> + +</head> +<!-- +Elements are styled in such a way that they don't overlap visually +unless they also overlap structurally. + +This file is designed to be opened from test_bug199692.html in a popup +window, to guarantee that the window in which document.elementFromPoint runs +is large enough to display all the elements being tested. +--> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=199692">Mozilla Bug 199692</a> + +<div id="content" style="width: 500px; background-color: #ccc;"> + +<!-- element containing text --> +<div id="txt" style="height: 30px;">txt</div> + +<!-- element not containing text --> +<div id="empty" style="border: 2px solid blue;"></div> + +<!-- element with only whitespace --> +<p id="whitespace" style="border: 2px solid magenta;"> </p> + +<!-- position: static --> +<span id="static" style="position: static; border-color: green;">static</span> + +<!-- floated element --> +<div id="float" style="border-color: red; float: right;">float</div> + +<!-- position: fixed --> +<span id="fixed" style="position: fixed; top: 500px; left: 100px; border: 3px solid yellow;">fixed</span> + +<!-- position: absolute --> +<span id="absolute" style="position: absolute; top: 550px; left: 150px; border-color: orange;">abs</span> + +<!-- position: relative --> +<div id="relative" style="position: relative; top: 200px; border-color: teal;">rel</div> + +<!-- visibility: hidden --> +<div id="hidden-wrapper" style="border: 1px dashed teal;"> + <div id="hidden" style="opacity: 0.5; background-color: blue; visibility:hidden;">hidden</div> +</div> + +<!-- iframe (within iframe) --> +<iframe id="our-iframe" src="bug199692-nested.html" style="height: 100px; overflow: scroll;"></iframe> + +<input type="textbox" id="textbox" value="textbox"></input> +</div> + +<!-- interaction with scrolling --> +<iframe id="scrolled-iframe" + src="bug199692-scrolled.html#down" + style="position: absolute; top: 345px; left: 325px; height: 200px; width: 200px"></iframe> + +<script type="application/javascript"> + +var SimpleTest = window.opener.SimpleTest; +function ok() { window.opener.ok.apply(window.opener, arguments); } +function is() { window.opener.is.apply(window.opener, arguments); } +function todo() { window.opener.todo.apply(window.opener, arguments); } +function todo_is() { window.opener.todo_is.apply(window.opener, arguments); } +function $(id) { return document.getElementById(id); } + +/** + * Like is, but for tests which don't always succeed or always fail on all + * platforms. + */ +function random_fail(a, b, m) +{ + if (a != b) + todo_is(a, b, m); + else + is(a, b, m); +} + +/* Test for Bug 199692 */ + +function getCoords(elt) +{ + var x = 0, y = 0; + + do + { + x += elt.offsetLeft; + y += elt.offsetTop; + } while ((elt = elt.offsetParent)); + + return { x: x, y: y }; +} + +var elts = ["txt", "empty", "whitespace", "static", "fixed", "absolute", + "relative", "float", "textbox"]; + +function testPoints() +{ + ok('elementFromPoint' in document, "document.elementFromPoint must exist"); + ok(typeof document.elementFromPoint === "function", "must be a function"); + + var doc = document; + doc.pt = doc.elementFromPoint; // for shorter lines + is(doc.pt(-1, 0), null, "Negative coordinates (-1, 0) should return null"); + is(doc.pt(0, -1), null, "Negative coordinates (0, -1) should return null"); + is(doc.pt(-1, -1), null, "Negative coordinates (-1, -1) should return null"); + + var pos; + for (var i = 0; i < elts.length; i++) + { + var id = elts[i]; + var elt = $(id); + + // The upper left corner of an element (with a moderate offset) will + // usually contain text, and the lower right corner usually won't. + var pos = getCoords(elt); + var x = pos.x, y = pos.y; + var w = elt.offsetWidth, h = elt.offsetHeight; + + var d = 5; + is(doc.pt(x + d, y + d), elt, + "(" + (x + d) + "," + (y + d) + ") IDs should match (upper left " + + "corner of " + id + ")"); + is(doc.pt(x + w - d, y + h - d), elt, + "(" + (x + w - d) + "," + (y + h - d) + ") IDs should match (lower " + + "right corner of " + id + ")"); + } + + // content + var c = $("content"); + pos = getCoords(c); + x = pos.x + c.offsetWidth / 2; + y = pos.y; + + // This fails on some platforms but not others for unknown reasons + random_fail(doc.pt(x, y), c, "Point to right of #txt should be #content"); + is(doc.pt(x, y + 1), c, "Point to right of #txt should be #content"); + random_fail(doc.pt(x + 1, y), c, "Point to right of #txt should be #content"); + is(doc.pt(x + 1, y + 1), c, "Point to right of #txt should be #content"); + + // hidden + c = $("hidden"); + pos = getCoords(c); + x = pos.x, y = pos.y; + is(doc.pt(x, y), $("hidden-wrapper"), + "Hit testing should bypass hidden elements."); + + // iframe nested + var iframe = $("our-iframe"); + pos = getCoords(iframe); + x = pos.x, y = pos.y; + is(doc.pt(x + 20, y + 20), $("our-iframe"), + "Element from nested iframe returned is from calling document"); + // iframe, doubly nested + is(doc.pt(x + 60, y + 60), $("our-iframe"), + "Element from doubly nested iframe returned is from calling document"); + + // scrolled iframe tests + $("scrolled-iframe").contentWindow.runTests(); + + SimpleTest.finish(); + window.close(); +} + +window.onload = testPoints; +</script> +</body> +</html> + diff --git a/dom/html/test/bug199692-scrolled.html b/dom/html/test/bug199692-scrolled.html new file mode 100644 index 000000000..f13bf7ab1 --- /dev/null +++ b/dom/html/test/bug199692-scrolled.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=199692 +--> +<head> + <title>Scrolled page for bug 199692 tests</title> + <style type="text/css"> +/* Disable default margins/padding/borders so (0, 0) gets a div. */ +* { margin: 0; padding: 0; border: 0; } + </style> + <script type="application/javascript"> +function $(id) { return document.getElementById(id); } + +function runTests() +{ + var is = window.parent.is; + + is(document.elementFromPoint(0, 0), $("down"), + "document.elementFromPoint not respecting scrolling?"); + is(document.elementFromPoint(200, 200), null, + "should have returned null for a not-visible point"); + is(document.elementFromPoint(3, -5), null, + "should have returned null for a not-visible point"); +} + </script> +</head> +<!-- This page is loaded in a 200px-square iframe scrolled to #down. --> +<body> +<div style="height: 150px; background: lightblue;">first</div> +<div id="down" style="height: 250px; background: lightgreen;">second</div> +</body> +</html> + diff --git a/dom/html/test/bug242709_iframe.html b/dom/html/test/bug242709_iframe.html new file mode 100644 index 000000000..1ee3320ae --- /dev/null +++ b/dom/html/test/bug242709_iframe.html @@ -0,0 +1,20 @@ +<html> +<head> +<title></title> +<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +<script type="text/javascript"> +function submitIframeForm () { + document.getElementById('b').submit(); + document.getElementById('thebutton').disabled = true; +} +</script> + +</head> +<body onload="sendMouseEvent({type:'click'}, 'thebutton')"> + +<form method="get" action="bug242709_load.html" id="b"> +<input type="submit" onclick="submitIframeForm()" id="thebutton"> +</form> + +</body> +</html> diff --git a/dom/html/test/bug242709_load.html b/dom/html/test/bug242709_load.html new file mode 100644 index 000000000..c9be79b24 --- /dev/null +++ b/dom/html/test/bug242709_load.html @@ -0,0 +1,11 @@ +<html> +<head> +<title></title> +</head> + +<body onload="parent.submitted();"> + +<span id="foo"></span> + +</body> +</html> diff --git a/dom/html/test/bug277724_iframe1.html b/dom/html/test/bug277724_iframe1.html new file mode 100644 index 000000000..d0d881b76 --- /dev/null +++ b/dom/html/test/bug277724_iframe1.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<!-- Use an unload handler to prevent bfcache from messing with us --> +<body onunload="parent.childUnloaded = true;"> + <select id="select"> + <option>aaa</option> + <option>bbbb</option> + </select> + + <textarea id="textarea"> + </textarea> + + <input type="text" id="text"> + <input type="password" id="password"> + <input type="checkbox" id="checkbox"> + <input type="radio" id="radio"> + <input type="image" id="image"> + <input type="submit" id="submit"> + <input type="reset" id="reset"> + <input type="button" id="button input"> + <input type="hidden" id="hidden"> + <input type="file" id="file"> + + <button type="submit" id="submit button"></button> + <button type="reset" id="reset button"></button> + <button type="button" id="button"></button> +</body> +</html> diff --git a/dom/html/test/bug277724_iframe2.xhtml b/dom/html/test/bug277724_iframe2.xhtml new file mode 100644 index 000000000..14423aa06 --- /dev/null +++ b/dom/html/test/bug277724_iframe2.xhtml @@ -0,0 +1,27 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- Use an unload handler to prevent bfcache from messing with us --> +<body onunload="parent.childUnloaded = true;"> + <select id="select"> + <option>aaa</option> + <option>bbbb</option> + </select> + + <textarea id="textarea"> + </textarea> + + <input type="text" id="text" /> + <input type="password" id="password" /> + <input type="checkbox" id="checkbox" /> + <input type="radio" id="radio" /> + <input type="image" id="image" /> + <input type="submit" id="submit" /> + <input type="reset" id="reset" /> + <input type="button" id="button input" /> + <input type="hidden" id="hidden" /> + <input type="file" id="file" /> + + <button type="submit" id="submit button"></button> + <button type="reset" id="reset button"></button> + <button type="button" id="button"></button> +</body> +</html> diff --git a/dom/html/test/bug277890_iframe.html b/dom/html/test/bug277890_iframe.html new file mode 100644 index 000000000..890ff839e --- /dev/null +++ b/dom/html/test/bug277890_iframe.html @@ -0,0 +1,20 @@ +<html> +<head> +<title></title> +<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +<script type="text/javascript"> +function submitIframeForm () { + document.getElementById('b').submit(); + document.getElementById('thebutton').disabled = true; +} +</script> + +</head> +<body onload="sendMouseEvent({type:'click'}, 'thebutton')"> + +<form method="get" action="bug277890_load.html" id="b"> +<button onclick="submitIframeForm()" id="thebutton">Submit</button> +</form> + +</body> +</html> diff --git a/dom/html/test/bug277890_load.html b/dom/html/test/bug277890_load.html new file mode 100644 index 000000000..c9be79b24 --- /dev/null +++ b/dom/html/test/bug277890_load.html @@ -0,0 +1,11 @@ +<html> +<head> +<title></title> +</head> + +<body onload="parent.submitted();"> + +<span id="foo"></span> + +</body> +</html> diff --git a/dom/html/test/bug340800_iframe.txt b/dom/html/test/bug340800_iframe.txt new file mode 100644 index 000000000..369dfe744 --- /dev/null +++ b/dom/html/test/bug340800_iframe.txt @@ -0,0 +1,4 @@ +Line 1. +Line 2. +Line 3. +Line 4. diff --git a/dom/html/test/bug369370-popup.png b/dom/html/test/bug369370-popup.png Binary files differnew file mode 100644 index 000000000..9063d1264 --- /dev/null +++ b/dom/html/test/bug369370-popup.png diff --git a/dom/html/test/bug372098-link-target.html b/dom/html/test/bug372098-link-target.html new file mode 100644 index 000000000..b22b8e020 --- /dev/null +++ b/dom/html/test/bug372098-link-target.html @@ -0,0 +1,7 @@ +<html> +<script type="text/javascript"> + +parent.callback(location.search.substr(1)); + +</script> +</html> diff --git a/dom/html/test/bug392567.jar b/dom/html/test/bug392567.jar Binary files differnew file mode 100644 index 000000000..bca06515d --- /dev/null +++ b/dom/html/test/bug392567.jar diff --git a/dom/html/test/bug392567.jar^headers^ b/dom/html/test/bug392567.jar^headers^ new file mode 100644 index 000000000..28b8aa0a5 --- /dev/null +++ b/dom/html/test/bug392567.jar^headers^ @@ -0,0 +1 @@ +Content-Type: application/java-archive diff --git a/dom/html/test/bug441930_iframe.html b/dom/html/test/bug441930_iframe.html new file mode 100644 index 000000000..532cd5c36 --- /dev/null +++ b/dom/html/test/bug441930_iframe.html @@ -0,0 +1,27 @@ +<html> +<body> + The content of this <code>textarea</code> should not disappear on page reload:<br /> + <textarea>This text should not disappear on page reload!</textarea> + <script> + var ta = document.getElementsByTagName("textarea").item(0); + if (!parent.reloaded) { + parent.reloaded = true; + ta.disabled = true; + location.reload(); + } else { + // Primary regression test: + parent.isnot(ta.value, "", + "Content of dynamically disabled textarea disappeared on page reload."); + + // Bonus regression test: changing the textarea's defaultValue after + // reloading should also update the textarea's value. + var newDefaultValue = "new default value"; + ta.defaultValue = newDefaultValue; + parent.is(ta.value, newDefaultValue, + "Changing the defaultValue attribute of a textarea fails to update its value attribute."); + + parent.SimpleTest.finish(); + } + </script> +</body> +</html> diff --git a/dom/html/test/bug445004-inner.html b/dom/html/test/bug445004-inner.html new file mode 100644 index 000000000..b946520ea --- /dev/null +++ b/dom/html/test/bug445004-inner.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <base href="http://test1.example.org/tests/dom/html/test/bug445004-inner.html"> + <script src="bug445004-inner.js"></script> + </head> + <body> + <iframe name="w" id="w" width="100" height="100"></iframe> + <iframe name="x" id="x" width="100" height="100"></iframe> + <iframe name="y" id="y" width="100" height="100"></iframe> + <iframe name="z" id="z" width="100" height="100"></iframe> + <img src="test1.example.org.png"> + </body> +</html> diff --git a/dom/html/test/bug445004-inner.js b/dom/html/test/bug445004-inner.js new file mode 100644 index 000000000..3675f8e69 --- /dev/null +++ b/dom/html/test/bug445004-inner.js @@ -0,0 +1,23 @@ +document.domain = "example.org"; +function $(str) { return document.getElementById(str); } +function hookLoad(str) { + $(str).onload = function() { window.parent.parent.postMessage('end', '*'); }; + window.parent.parent.postMessage('start', '*'); +} +window.onload = function() { + hookLoad("w"); + $("w").contentWindow.location.href = "test1.example.org.png"; + hookLoad("x"); + var doc = $("x").contentDocument; + doc.write('<img src="test1.example.org.png">'); + doc.close(); +}; +function doIt() { + hookLoad("y"); + $("y").contentWindow.location.href = "example.org.png"; + hookLoad("z"); + var doc = $("z").contentDocument; + doc.write('<img src="example.org.png">'); + doc.close(); +} +window.addEventListener("message", doIt, false);
\ No newline at end of file diff --git a/dom/html/test/bug445004-outer-abs.html b/dom/html/test/bug445004-outer-abs.html new file mode 100644 index 000000000..8a93ef2b7 --- /dev/null +++ b/dom/html/test/bug445004-outer-abs.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <head> + <base href="http://example.org/tests/dom/html/test/bug445004-outer.html"> + <script>document.domain = "example.org"</script> + </head> + <body> + <iframe width="500" height="200" src="http://test1.example.org/tests/dom/html/test/bug445004-inner.html" + onload="window.frames[0].doIt()"></iframe> + </body> +</html> diff --git a/dom/html/test/bug445004-outer-rel.html b/dom/html/test/bug445004-outer-rel.html new file mode 100644 index 000000000..096733889 --- /dev/null +++ b/dom/html/test/bug445004-outer-rel.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <head> + <base href="http://example.org/tests/dom/html/test/bug445004-outer.html"> + <script>document.domain = "example.org"</script> + </head> + <body> + <iframe width="500" height="200" src="bug445004-inner.html" + onload="window.frames[0].doIt()"></iframe> + </body> +</html> diff --git a/dom/html/test/bug445004-outer-write.html b/dom/html/test/bug445004-outer-write.html new file mode 100644 index 000000000..be6e37b6d --- /dev/null +++ b/dom/html/test/bug445004-outer-write.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <head> + <base href="http://example.org/tests/dom/html/test/bug445004-outer.html"> + <script>document.domain = "example.org"</script> + </head> + <body> + <iframe width="500" height="200" src="javascript:"<!DOCTYPE html> <html> <script> function $(str) { return document.getElementById(str); } function hookLoad(str) { $(str).onload = function() { window.parent.parent.postMessage('end', '*'); }; window.parent.parent.postMessage('start', '*'); } window.onload = function() { hookLoad(\"w\"); $(\"w\").contentWindow.location.href = \"example.org.png\"; hookLoad(\"x\"); var doc = $(\"x\").contentDocument; doc.write('<img src=\"example.org.png\">'); doc.close(); }; function doIt() { hookLoad(\"y\"); $(\"y\").contentWindow.location.href = \"example.org.png\"; hookLoad(\"z\"); var doc = $(\"z\").contentDocument; doc.write('<img src=\"example.org.png\">'); doc.close(); } </script> <body> <iframe name=\"w\" id=\"w\" width=\"100\" height=\"100\"></iframe> <iframe name=\"x\" id=\"x\" width=\"100\" height=\"100\"></iframe> <iframe name=\"y\" id=\"y\" width=\"100\" height=\"100\"></iframe> <iframe name=\"z\" id=\"z\" width=\"100\" height=\"100\"></iframe><img src=\"example.org.png\"> </body> </html>" " + onload="window.frames[0].doIt();"></iframe> + </body> +</html> diff --git a/dom/html/test/bug446483-iframe.html b/dom/html/test/bug446483-iframe.html new file mode 100644 index 000000000..fe5a6cf9f --- /dev/null +++ b/dom/html/test/bug446483-iframe.html @@ -0,0 +1,10 @@ +<script>
+function doe(){
+window.focus();
+window.getSelection().collapse(document.body, 0);
+}
+setTimeout(doe,50);
+
+setTimeout(function() {window.location.reload()}, 200);
+</script>
+<span contenteditable="true"></span>
diff --git a/dom/html/test/bug448564-echo.sjs b/dom/html/test/bug448564-echo.sjs new file mode 100644 index 000000000..1eee116fd --- /dev/null +++ b/dom/html/test/bug448564-echo.sjs @@ -0,0 +1,6 @@ +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + response.setStatusLine(request.httpVersion, 200, "OK"); + + response.write(request.queryString); +} diff --git a/dom/html/test/bug448564-iframe-1.html b/dom/html/test/bug448564-iframe-1.html new file mode 100644 index 000000000..4f3e79e5d --- /dev/null +++ b/dom/html/test/bug448564-iframe-1.html @@ -0,0 +1,16 @@ +<html> +<body> + + <table> + <form action="bug448564-echo.sjs" method="GET"> + <tr><td><input name="a" value="aval"></td></tr> + <input type="hidden" name="b" value="bval"> + <input name="c" value="cval"> + <tr><td><input name="d" value="dval" type="submit"></td></tr> + </form> + </table> + + <script src="bug448564-submit.js"></script> + +</body> +</html> diff --git a/dom/html/test/bug448564-iframe-2.html b/dom/html/test/bug448564-iframe-2.html new file mode 100644 index 000000000..dba19b37e --- /dev/null +++ b/dom/html/test/bug448564-iframe-2.html @@ -0,0 +1,16 @@ +<html> +<body> + + <form action="bug448564-echo.sjs" method="GET"> + <table> + <tr><td><input name="a" value="aval"></td></tr> + <input type="hidden" name="b" value="bval"> + <input name="c" value="cval"> + <tr><td><input name="d" value="dval" type="submit"></td></tr> + </table> + </form> + + <script src="bug448564-submit.js"></script> + +</body> +</html> diff --git a/dom/html/test/bug448564-iframe-3.html b/dom/html/test/bug448564-iframe-3.html new file mode 100644 index 000000000..64288ebb1 --- /dev/null +++ b/dom/html/test/bug448564-iframe-3.html @@ -0,0 +1,16 @@ +<html> +<body> + + <table> + <span><form action="bug448564-echo.sjs" method="GET"> + <tr><td><input name="a" value="aval"></td></tr> + <input type="hidden" name="b" value="bval"> + <input name="c" value="cval"> + <tr><td><input name="d" value="dval" type="submit"></td></tr> + </form></span> + </table> + + <script src="bug448564-submit.js"></script> + +</body> +</html> diff --git a/dom/html/test/bug448564-submit.js b/dom/html/test/bug448564-submit.js new file mode 100644 index 000000000..34de44d4d --- /dev/null +++ b/dom/html/test/bug448564-submit.js @@ -0,0 +1,4 @@ +var inputs = document.getElementsByTagName("input"); +for (var input, i = 0; input = inputs[i]; ++i) + if ("submit" == input.type) + input.click(); diff --git a/dom/html/test/bug499092.html b/dom/html/test/bug499092.html new file mode 100644 index 000000000..0476fa4e7 --- /dev/null +++ b/dom/html/test/bug499092.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<script> +var title = document.createElementNS("http://www.w3.org/1999/xhtml", "aa:title"); +title.textContent = "HTML OK"; +document.documentElement.firstChild.appendChild(title); +</script> diff --git a/dom/html/test/bug499092.xml b/dom/html/test/bug499092.xml new file mode 100644 index 000000000..eedd2c77b --- /dev/null +++ b/dom/html/test/bug499092.xml @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<doc xmlns:aa="http://www.w3.org/1999/xhtml"> +<aa:title>XML OK</aa:title> +</doc> diff --git a/dom/html/test/bug514856_iframe.html b/dom/html/test/bug514856_iframe.html new file mode 100644 index 000000000..2abf9e91e --- /dev/null +++ b/dom/html/test/bug514856_iframe.html @@ -0,0 +1,21 @@ +<html> + <head> + <style> + html, body, a, img { + padding: 0px; + margin: 0px; + border: 0px; + } + img { + width: 100%; + height: 100%; + } + </style> + </head> + <body> + <a href="bug514856_iframe.html"> + <img ismap="ismap" + src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0vr4MkhoXe0rZigAAAABJRU5ErkJggg=="> + </a> + </body> +</html> diff --git a/dom/html/test/bug592641_img.jpg b/dom/html/test/bug592641_img.jpg Binary files differnew file mode 100644 index 000000000..c9103b8b0 --- /dev/null +++ b/dom/html/test/bug592641_img.jpg diff --git a/dom/html/test/bug649134/file_bug649134-1.sjs b/dom/html/test/bug649134/file_bug649134-1.sjs new file mode 100644 index 000000000..890f8aa5e --- /dev/null +++ b/dom/html/test/bug649134/file_bug649134-1.sjs @@ -0,0 +1,12 @@ +function handleRequest(request, response) +{ + response.seizePower(); + var r = 'HTTP/1.1 200 OK\r\n' + + 'Content-Type: text/html\r\n' + + 'Link: < \014>; rel="stylesheet"\r\n' + + '\r\n' + + '<!-- selector {} body {display:none;} --><body>PASS</body>\r\n'; + response.bodyOutputStream.write(r, r.length); + response.bodyOutputStream.flush(); + response.finish(); +} diff --git a/dom/html/test/bug649134/file_bug649134-2.sjs b/dom/html/test/bug649134/file_bug649134-2.sjs new file mode 100644 index 000000000..7f005eda6 --- /dev/null +++ b/dom/html/test/bug649134/file_bug649134-2.sjs @@ -0,0 +1,12 @@ +function handleRequest(request, response) +{ + response.seizePower(); + var r = 'HTTP/1.1 200 OK\r\n' + + 'Content-Type: text/html\r\n' + + 'Link: < \014>; rel="stylesheet",\r\n' + + '\r\n' + + '<!-- selector {} body {display:none;} --><body>PASS</body>\r\n'; + response.bodyOutputStream.write(r, r.length); + response.bodyOutputStream.flush(); + response.finish(); +} diff --git a/dom/html/test/bug649134/index.html b/dom/html/test/bug649134/index.html new file mode 100644 index 000000000..2f3973704 --- /dev/null +++ b/dom/html/test/bug649134/index.html @@ -0,0 +1,3 @@ +body { + display:none; +} diff --git a/dom/html/test/chrome.ini b/dom/html/test/chrome.ini new file mode 100644 index 000000000..fd8009690 --- /dev/null +++ b/dom/html/test/chrome.ini @@ -0,0 +1,10 @@ +[DEFAULT] +support-files = + file_anchor_ping.html + wakelock.ogg + wakelock.ogv + +[test_anchor_ping.html] +skip-if = os == 'android' +[test_audio_wakelock.html] +[test_video_wakelock.html] diff --git a/dom/html/test/dummy_page.html b/dom/html/test/dummy_page.html new file mode 100644 index 000000000..fd238954c --- /dev/null +++ b/dom/html/test/dummy_page.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<title>Dummy test page</title> +<meta charset="utf-8"/> +</head> +<body> +<p>Dummy test page</p> +</body> +</html> diff --git a/dom/html/test/file_anchor_ping.html b/dom/html/test/file_anchor_ping.html new file mode 100644 index 000000000..3b9717263 --- /dev/null +++ b/dom/html/test/file_anchor_ping.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>file_anchor_ping.html</title> + </head> + <body onload="document.body.firstElementChild.click()"> + <a href="/">click me</a> + <script> + document.body.firstElementChild.ping = window.location.search.slice(1); + </script> + </body> +</html> diff --git a/dom/html/test/file_bug1108547-1.html b/dom/html/test/file_bug1108547-1.html new file mode 100644 index 000000000..efc0eae49 --- /dev/null +++ b/dom/html/test/file_bug1108547-1.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<script> +document.cookie = "foo=bar"; +</script> diff --git a/dom/html/test/file_bug1108547-2.html b/dom/html/test/file_bug1108547-2.html new file mode 100644 index 000000000..af06c8c42 --- /dev/null +++ b/dom/html/test/file_bug1108547-2.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<body onload="document.querySelector('form').submit();"> +<form action="javascript:opener.document.getElementById('result').textContent = document.cookie;" target="_blank"> +</form> +<div id="result">not tested yet</div> +</body> diff --git a/dom/html/test/file_bug1108547-3.html b/dom/html/test/file_bug1108547-3.html new file mode 100644 index 000000000..d99a2d355 --- /dev/null +++ b/dom/html/test/file_bug1108547-3.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<body onload="document.querySelector('a').click();"> +<a href="javascript:opener.document.getElementById('result').textContent = document.cookie;" target="_blank">test</a> +<div id="result">not tested yet</div> +</body> diff --git a/dom/html/test/file_bug1166138_1x.png b/dom/html/test/file_bug1166138_1x.png Binary files differnew file mode 100644 index 000000000..df421453c --- /dev/null +++ b/dom/html/test/file_bug1166138_1x.png diff --git a/dom/html/test/file_bug1166138_2x.png b/dom/html/test/file_bug1166138_2x.png Binary files differnew file mode 100644 index 000000000..6f76d4438 --- /dev/null +++ b/dom/html/test/file_bug1166138_2x.png diff --git a/dom/html/test/file_bug1166138_def.png b/dom/html/test/file_bug1166138_def.png Binary files differnew file mode 100644 index 000000000..144a2f0b9 --- /dev/null +++ b/dom/html/test/file_bug1166138_def.png diff --git a/dom/html/test/file_bug1260704.png b/dom/html/test/file_bug1260704.png Binary files differnew file mode 100644 index 000000000..df421453c --- /dev/null +++ b/dom/html/test/file_bug1260704.png diff --git a/dom/html/test/file_bug209275_1.html b/dom/html/test/file_bug209275_1.html new file mode 100644 index 000000000..3f7233876 --- /dev/null +++ b/dom/html/test/file_bug209275_1.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<head> + <base href="http://example.org" /> +</head> +<body onload="load();"> +Initial state + +<script> +function load() { + // Nuke and rebuild the page. + document.removeChild(document.documentElement); + var html = document.createElement("html"); + var body = document.createElement("body"); + html.appendChild(body); + var link = document.createElement("a"); + link.href = "#"; + link.id = "link"; + body.appendChild(link); + document.appendChild(html); + + // Tell our parent to have a look at us. + parent.gGen.next(); +} +</script> + +</body> +</html> diff --git a/dom/html/test/file_bug209275_2.html b/dom/html/test/file_bug209275_2.html new file mode 100644 index 000000000..36e9ff467 --- /dev/null +++ b/dom/html/test/file_bug209275_2.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<html> +<head> + <base href="http://example.com" /> +</head> +<body onload="load();"> +Page 2 initial state + +<script> +function load() { + // Nuke and rebuild the page. + document.removeChild(document.documentElement); + html = document.createElement("html"); + html.innerHTML = "<body><a href='/' id='link'>B</a></body>" + document.appendChild(html); + + // Tell our parent to have a look at us + parent.gGen.next(); +} +</script> + +</body> +</html> diff --git a/dom/html/test/file_bug209275_3.html b/dom/html/test/file_bug209275_3.html new file mode 100644 index 000000000..254411590 --- /dev/null +++ b/dom/html/test/file_bug209275_3.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<html> +<head> + <base href="http://example.org" /> +</head> +<body onload="load();"> +Initial state + +<script> +function load() { + // Nuke and rebuild the page. If document.open() clears the <base> properly, + // our new <base> will take precedence and the test will pass. + document.open(); + document.write("<html><base href='http://mochi.test:8888' /><body>" + + "<a id='link' href='/'>A</a></body></html>"); + + // Tell our parent to have a look at us. + parent.gGen.next(); +} +</script> + +</body> +</html> diff --git a/dom/html/test/file_bug297761.html b/dom/html/test/file_bug297761.html new file mode 100644 index 000000000..5e861a00f --- /dev/null +++ b/dom/html/test/file_bug297761.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> + <head> + <base href="http://www.mozilla.org/"> + </head> + <body> + <form action=""> + <input type='submit' formaction=""> + <button type='submit' formaction=""></button> + <input id='i' type='image' formaction=""> + </form> + </body> +</html> diff --git a/dom/html/test/file_bug417760.png b/dom/html/test/file_bug417760.png Binary files differnew file mode 100644 index 000000000..743292dc6 --- /dev/null +++ b/dom/html/test/file_bug417760.png diff --git a/dom/html/test/file_bug649778.html b/dom/html/test/file_bug649778.html new file mode 100644 index 000000000..48a9870e7 --- /dev/null +++ b/dom/html/test/file_bug649778.html @@ -0,0 +1,11 @@ +<html> +<script> +function test() { + document.open(); + document.write('<html><body>WYCIWYG DOCUMENT</body></html>'); + document.close(); +} +</script> +<body onload="setTimeout(test, 0);"> +</body> +</html> diff --git a/dom/html/test/file_bug649778.html^headers^ b/dom/html/test/file_bug649778.html^headers^ new file mode 100644 index 000000000..4030ea1d3 --- /dev/null +++ b/dom/html/test/file_bug649778.html^headers^ @@ -0,0 +1 @@ +Cache-Control: no-store diff --git a/dom/html/test/file_bug871161-1.html b/dom/html/test/file_bug871161-1.html new file mode 100644 index 000000000..16015f0c4 --- /dev/null +++ b/dom/html/test/file_bug871161-1.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset=windows-1251> +<title>Page with non-default charset</title> +<script> +function run() { + document.forms[0].submit(); +} +</script> +</head> +<body onload="run();"> +<form method=post action="http://example.org/tests/dom/html/test/file_bug871161-2.html"></form> +</body> +</html> + diff --git a/dom/html/test/file_bug871161-2.html b/dom/html/test/file_bug871161-2.html new file mode 100644 index 000000000..18cf825b2 --- /dev/null +++ b/dom/html/test/file_bug871161-2.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> +<title>Page without declared charset</title> +<script> +function done() { + window.opener.postMessage(document.characterSet, "*"); +} +</script> +</head> +<body onload="done();"> +</body> +</html> + diff --git a/dom/html/test/file_bug893537.html b/dom/html/test/file_bug893537.html new file mode 100644 index 000000000..1dcb454ff --- /dev/null +++ b/dom/html/test/file_bug893537.html @@ -0,0 +1,9 @@ +<!doctype html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=893537 +--> +<body> +<iframe id="iframe" src="data:text/html;charset=US-ASCII,Goodbye World" srcdoc="Hello World"></iframe> +</body> +</html> diff --git a/dom/html/test/file_content_contextmenu.html b/dom/html/test/file_content_contextmenu.html new file mode 100644 index 000000000..4d6874d2f --- /dev/null +++ b/dom/html/test/file_content_contextmenu.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title></title> + <style> + body { + margin: 0; + width: 100vw; + height: 100vh; + } + </style> +</head> +<body contextmenu="testmenu"> + <menu type="context" id="testmenu"> + <menuitem label="Test Context Menu Click" id="menuitem"></menuitem> + <hr> + </menu> +</body> +</html> diff --git a/dom/html/test/file_cookiemanager.js b/dom/html/test/file_cookiemanager.js new file mode 100644 index 000000000..98f356534 --- /dev/null +++ b/dom/html/test/file_cookiemanager.js @@ -0,0 +1,20 @@ +let { classes: Cc, interfaces: Ci } = Components; +addMessageListener("getCookieFromManager", ({ host, path }) => { + let cm = Cc["@mozilla.org/cookiemanager;1"] + .getService(Ci.nsICookieManager); + let values = []; + path = path.substring(0, path.lastIndexOf("/") + 1); + let e = cm.enumerator; + while (e.hasMoreElements()) { + let cookie = e.getNext().QueryInterface(Ci.nsICookie); + if (!cookie) { + break; + } + if (host != cookie.host || path != cookie.path) { + continue; + } + values.push(cookie.name + "=" + cookie.value); + } + + sendAsyncMessage("getCookieFromManager:return", { cookie: values.join("; ") }); +}); diff --git a/dom/html/test/file_formSubmission_img.jpg b/dom/html/test/file_formSubmission_img.jpg Binary files differnew file mode 100644 index 000000000..dcd99b967 --- /dev/null +++ b/dom/html/test/file_formSubmission_img.jpg diff --git a/dom/html/test/file_formSubmission_text.txt b/dom/html/test/file_formSubmission_text.txt new file mode 100644 index 000000000..a496efee8 --- /dev/null +++ b/dom/html/test/file_formSubmission_text.txt @@ -0,0 +1 @@ +This is a text file diff --git a/dom/html/test/file_fullscreen-api-keys.html b/dom/html/test/file_fullscreen-api-keys.html new file mode 100644 index 000000000..33a68d03e --- /dev/null +++ b/dom/html/test/file_fullscreen-api-keys.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> +</head> +<body> +<script> +window.addEventListener("Test:DispatchKeyEvents", aEvent => { + var keyCode = KeyEvent["DOM_" + aEvent.detail.code]; + + document.body.focus(); + var evt = document.createEvent("KeyboardEvent"); + evt.initKeyEvent("keydown", true, true, window, + false, false, false, false, + keyCode, 0); + document.body.dispatchEvent(evt); + + evt = document.createEvent("KeyboardEvent"); + evt.initKeyEvent("keypress", true, true, window, + false, false, false, false, + keyCode, 0); + document.body.dispatchEvent(evt); + + evt = document.createEvent("KeyboardEvent"); + evt.initKeyEvent("keyup", true, true, window, + false, false, false, false, + keyCode, 0); + document.body.dispatchEvent(evt); +}); +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-api.html b/dom/html/test/file_fullscreen-api.html new file mode 100644 index 000000000..89162058e --- /dev/null +++ b/dom/html/test/file_fullscreen-api.html @@ -0,0 +1,317 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=545812 + +Test DOM full-screen API. + +--> +<head> + <title>Test for Bug 545812</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> + <style> + body { + background-color: black; + } + </style> +</head> +<body> +<script type="application/javascript"> + +/** Test for Bug 545812 **/ + +function ok(condition, msg) { + opener.ok(condition, "[fullscreen] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[fullscreen] " + msg); +} + +/* +<html> + <body onload='document.body.requestFullscreen();'> + <iframe id='inner-frame'></iframe> + </body> +</html> +*/ +var iframeContents = "data:text/html;charset=utf-8,<html><body onload%3D'parent.SimpleTest.waitForFocus(function(){document.body.requestFullscreen();});'><iframe id%3D'inner-frame'><%2Fiframe><%2Fbody><%2Fhtml>"; + +var iframe = null; +var outOfDocElement = null; +var inDocElement = null; +var container = null; +var button = null; + + +function sendMouseClick(element) { + synthesizeMouseAtCenter(element, {}); +} + +function fullScreenElement() { + return document.getElementById('full-screen-element'); +} + +function enter1(event) { + is(event.target, document, "Event target should be full-screen document #1"); + ok(document.fullscreen, "Document should be in fullscreen"); + is(document.fullscreenElement, fullScreenElement(), + "Full-screen element should be div element."); + ok(document.fullscreenElement.matches(":fullscreen"), + "FSE should match :fullscreen"); + var fse = fullScreenElement(); + addFullscreenChangeContinuation("exit", exit1); + fse.parentNode.removeChild(fse); + is(document.fullscreenElement, null, + "Full-screen element should be null after removing."); + document.body.appendChild(fse); + is(document.fullscreenElement, null, + "Full-screen element should still be null after re-adding former FSE."); +} + +function exit1(event) { + is(event.target, document, "Event target should be full-screen document #2"); + ok(!document.fullscreen, "Document should not be in fullscreen"); + is(document.fullscreenElement, null, "Full-screen element should be null."); + iframe = document.createElement("iframe"); + iframe.allowFullscreen = true; + addFullscreenChangeContinuation("enter", enter2); + document.body.appendChild(iframe); + iframe.src = iframeContents; +} + +function enter2(event) { + is(event.target, document, "Event target should be full-screen document #3"); + is(document.fullscreenElement, iframe, + "Full-screen element should be iframe element."); + is(iframe.contentDocument.fullscreenElement, iframe.contentDocument.body, + "Full-screen element in subframe should be body"); + + // The iframe's body is full-screen. Cancel full-screen in the subdocument to return + // the full-screen element to the previous full-screen element. This causes + // a fullscreenchange event. + addFullscreenChangeContinuation("exit", exit2); + document.exitFullscreen(); +} + +function exit2(event) { + is(document.fullscreenElement, null, + "Full-screen element should have rolled back."); + is(iframe.contentDocument.fullscreenElement, null, + "Full-screen element in subframe should be null"); + + addFullscreenChangeContinuation("enter", enter3); + fullScreenElement().requestFullscreen(); +} + +function enter3(event) { + is(event.target, document, "Event target should be full-screen document #3"); + is(document.fullscreenElement, fullScreenElement(), + "Full-screen element should be div."); + + // Transplant the FSE into subdoc. Should exit full-screen. + addFullscreenChangeContinuation("exit", exit3); + var _innerFrame = iframe.contentDocument.getElementById("inner-frame"); + var fse = fullScreenElement(); + _innerFrame.contentDocument.body.appendChild(fse); + is(document.fullscreenElement, null, + "Full-screen element transplanted, should be null."); + is(iframe.contentDocument.fullscreenElement, null, + "Full-screen element in outer frame should be null."); + is(_innerFrame.contentDocument.fullscreenElement, null, + "Full-screen element in inner frame should be null."); + + document.body.appendChild(fse); +} + +function exit3(event) { + is(event.target, document, "Event target should be full-screen document #4"); + is(document.fullscreenElement, null, "Full-screen element should be null."); + document.body.removeChild(iframe); + iframe = null; + + // Do a request out of document. It should be denied. + // Continue test in the following fullscreenerror handler. + outOfDocElement = document.createElement("div"); + addFullscreenErrorContinuation(error1); + outOfDocElement.requestFullscreen(); +} + +function error1(event) { + ok(!document.fullscreenElement, + "Requests for full-screen from not-in-doc elements should fail."); + container = document.createElement("div"); + inDocElement = document.createElement("div"); + container.appendChild(inDocElement); + fullScreenElement().appendChild(container); + + addFullscreenChangeContinuation("enter", enter4); + inDocElement.requestFullscreen(); +} + +function enter4(event) { + is(event.target, document, "Event target should be full-screen document #5"); + is(document.fullscreenElement, inDocElement, "FSE should be inDocElement."); + + // Remove full-screen ancestor element from document, verify it stops being reported as current FSE. + addFullscreenChangeContinuation("exit", exit_to_arg_test_1); + container.parentNode.removeChild(container); + is(document.fullscreenElement, null, + "Should not have a full-screen element again."); +} + +function exit_to_arg_test_1(event) { + ok(!document.fullscreenElement, + "Should have left full-screen mode (third time)."); + addFullscreenChangeContinuation("enter", enter_from_arg_test_1); + var threw = false; + try { + fullScreenElement().requestFullscreen(123); + } catch (e) { + threw = true; + // trigger normal fullscreen so that we continue + fullScreenElement().requestFullscreen(); + } + ok(!threw, "requestFullscreen with bogus arg (123) shouldn't throw exception"); +} + +function enter_from_arg_test_1(event) { + ok(document.fullscreenElement, + "Should have entered full-screen after calling with bogus (ignored) argument (fourth time)"); + addFullscreenChangeContinuation("exit", exit_to_arg_test_2); + document.exitFullscreen(); +} + +function exit_to_arg_test_2(event) { + ok(!document.fullscreenElement, + "Should have left full-screen mode (fourth time)."); + addFullscreenChangeContinuation("enter", enter_from_arg_test_2); + var threw = false; + try { + fullScreenElement().requestFullscreen({ vrDisplay: null }); + } catch (e) { + threw = true; + // trigger normal fullscreen so that we continue + fullScreenElement().requestFullscreen(); + } + ok(!threw, "requestFullscreen with { vrDisplay: null } shouldn't throw exception"); +} + +function enter_from_arg_test_2(event) { + ok(document.fullscreenElement, + "Should have entered full-screen after calling with vrDisplay null argument (fifth time)"); + addFullscreenChangeContinuation("exit", exit4); + document.exitFullscreen(); +} + +function exit4(event) { + ok(!document.fullscreenElement, + "Should be back in non-full-screen mode (fifth time)"); + SpecialPowers.pushPrefEnv({"set":[["full-screen-api.allow-trusted-requests-only", true]]}, function() { + addFullscreenErrorContinuation(error2); + fullScreenElement().requestFullscreen(); + }); +} + +function error2(event) { + ok(!document.fullscreenElement, + "Should still be in normal mode, because calling context isn't trusted."); + button = document.createElement("button"); + button.onclick = function(){fullScreenElement().requestFullscreen();} + fullScreenElement().appendChild(button); + addFullscreenChangeContinuation("enter", enter5); + sendMouseClick(button); +} + +function enter5(event) { + ok(document.fullscreenElement, "Moved to full-screen after mouse click"); + addFullscreenChangeContinuation("exit", exit5); + document.exitFullscreen(); +} + +function exit5(event) { + ok(!document.fullscreenElement, + "Should have left full-screen mode (last time)."); + SpecialPowers.pushPrefEnv({ + "set":[["full-screen-api.allow-trusted-requests-only", false], + ["full-screen-api.enabled", false]]}, function() { + is(document.fullscreenEnabled, false, "document.fullscreenEnabled should be false if full-screen-api.enabled is false"); + addFullscreenErrorContinuation(error3); + fullScreenElement().requestFullscreen(); + }); +} + +function error3(event) { + ok(!document.fullscreenElement, + "Should still be in normal mode, because pref is not enabled."); + + SpecialPowers.pushPrefEnv({"set":[["full-screen-api.enabled", true]]}, function() { + is(document.fullscreenEnabled, true, "document.fullscreenEnabled should be true if full-screen-api.enabled is true"); + opener.nextTest(); + }); +} + +function begin() { + testNamespaces(() => { + addFullscreenChangeContinuation("enter", enter1); + fullScreenElement().requestFullscreen(); + }); +} + +function testNamespaces(followupTestFn) { + let tests = [ + {allowed: false, name: "element", ns: "http://www.w3.org/XML/1998/namespace"}, + {allowed: false, name: "element", ns: "http://www.w3.org/1999/xlink"}, + {allowed: false, name: "element", ns: "http://www.w3.org/2000/svg"}, + {allowed: false, name: "element", ns: "http://www.w3.org/1998/Math/MathML"}, + {allowed: false, name: "mathml", ns: "unknown"}, + {allowed: false, name: "svg", ns: "unknown"}, + {allowed: true, name: "element", ns: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"}, + {allowed: true, name: "element", ns: "http://www.w3.org/1999/xhtml"}, + {allowed: true, name: "svg", ns: "http://www.w3.org/1999/xhtml"}, + {allowed: true, name: "math", ns: "http://www.w3.org/1999/xhtml"}, + {allowed: true, name: "svg", ns: "http://www.w3.org/2000/svg"}, + {allowed: true, name: "math", ns: "http://www.w3.org/1998/Math/MathML"}, + {allowed: true, name: "element"}, + ]; + + function runNextNamespaceTest() { + let test = tests.shift(); + if (!test) { + followupTestFn(); + return; + } + + let elem = test.ns ? document.createElementNS(test.ns, test.name) : + document.createElement(test.name); + document.body.appendChild(elem); + + if (test.allowed) { + addFullscreenChangeContinuation("enter", () => { + ok(document.fullscreen, "Document should be in fullscreen"); + is(document.fullscreenElement, elem, + `Element named '${test.name}' in this namespace should be allowed: ${test.ns}`); + addFullscreenChangeContinuation("exit", runNextNamespaceTest); + document.body.removeChild(elem); + }); + } else { + addFullscreenErrorContinuation(() => { + ok(!document.fullscreenElement, + `Element named '${test.name}' in this namespace should not be allowed: ${test.ns}`); + document.body.removeChild(elem); + runNextNamespaceTest(); + }); + } + + elem.requestFullscreen(); + } + + runNextNamespaceTest(); +} +</script> +</pre> +<div id="full-screen-element"></div> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-backdrop.html b/dom/html/test/file_fullscreen-backdrop.html new file mode 100644 index 000000000..d3d4cc446 --- /dev/null +++ b/dom/html/test/file_fullscreen-backdrop.html @@ -0,0 +1,107 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Test for Bug 1064843</title> + <style id="style"></style> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script> + <script type="text/javascript" src="file_fullscreen-utils.js"></script> + <style> + html { + overflow: hidden; + } + #placeholder { + height: 1000vh; + } + </style> +</head> +<body> +<div id="fullscreen"></div> +<div id="placeholder"></div> +<script> + +const gStyle = document.getElementById("style"); +const gFullscreen = document.getElementById("fullscreen"); + +function is(a, b, msg) { + opener.is(a, b, "[backdrop] " + msg); +} + +function isnot(a, b, msg) { + opener.isnot(a, b, "[backdrop] " + msg); +} + +function ok(cond, msg) { + opener.ok(cond, "[backdrop] " + msg); +} + +function info(msg) { + opener.info("[backdrop] " + msg); +} + +function synthesizeMouseAtWindowCenter() { + synthesizeMouseAtPoint(innerWidth / 2, innerHeight / 2, {}); +} + +const gFullscreenElementBackground = getComputedStyle(gFullscreen).background; + +function begin() { + info("The default background of window should be white"); + assertWindowPureColor(window, "white"); + addFullscreenChangeContinuation("enter", enterFullscreen); + gFullscreen.requestFullscreen(); +} + +function setBackdropStyle(style) { + gStyle.textContent = `#fullscreen::backdrop { ${style} }`; +} + +function enterFullscreen() { + is(getComputedStyle(gFullscreen).background, gFullscreenElementBackground, + "Computed background of #fullscreen shouldn't be changed"); + + info("The default background of backdrop for fullscreen is black"); + assertWindowPureColor(window, "black"); + + setBackdropStyle("background: green"); + info("The background color of backdrop should be changed to green"); + assertWindowPureColor(window, "green"); + + gFullscreen.style.background = "blue"; + info("The blue fullscreen element should cover the backdrop"); + assertWindowPureColor(window, "blue"); + + gFullscreen.style.background = ""; + setBackdropStyle("display: none"); + info("The white body should be shown when the backdrop is hidden"); + assertWindowPureColor(window, "white"); + + setBackdropStyle(""); + info("Content should return to black because we restore the backdrop"); + assertWindowPureColor(window, "black"); + + gFullscreen.style.display = "none"; + info("The backdrop should disappear with the fullscreen element"); + assertWindowPureColor(window, "white"); + + gFullscreen.style.display = ""; + setBackdropStyle("position: absolute"); + info("Changing position shouldn't immediately affect the view"); + assertWindowPureColor(window, "black"); + + window.scroll(0, screen.height); + info("Scrolled up the absolutely-positioned element"); + assertWindowPureColor(window, "white"); + + addFullscreenChangeContinuation("exit", exitFullscreen); + document.exitFullscreen(); +} + +function exitFullscreen() { + opener.nextTest(); +} +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-denied-inner.html b/dom/html/test/file_fullscreen-denied-inner.html new file mode 100644 index 000000000..6b5916b2e --- /dev/null +++ b/dom/html/test/file_fullscreen-denied-inner.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8"> +</head> +<body onload="doRequestFullscreen()"> +<script> +function doRequestFullscreen() { + function handler(evt) { + document.removeEventListener("fullscreenchange", handler); + document.removeEventListener("fullscreenerror", handler); + parent.is(evt.type, "fullscreenerror", "Request from " + + `document inside ${parent.testTargetName} should be denied`); + parent.continueTest(); + } + parent.ok(!document.fullscreenEnabled, "Fullscreen " + + `should not be enabled in ${parent.testTargetName}`); + document.addEventListener("fullscreenchange", handler); + document.addEventListener("fullscreenerror", handler); + document.documentElement.requestFullscreen(); +} +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-denied.html b/dom/html/test/file_fullscreen-denied.html new file mode 100644 index 000000000..322723083 --- /dev/null +++ b/dom/html/test/file_fullscreen-denied.html @@ -0,0 +1,129 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=545812 + +Test DOM fullscreen API. + +--> +<head> + <title>Test for Bug 545812</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> + <style> + body { + background-color: black; + } + </style> +</head> +<body> + +<script type="application/javascript"> + +/** Test for Bug 545812 **/ + +function ok(condition, msg) { + opener.ok(condition, "[denied] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[denied] " + msg); +} + +const INNER_FILE = "file_fullscreen-denied-inner.html"; +function setupForInnerTest(targetName, callback) { + window.testTargetName = targetName; + window.continueTest = () => { + delete window.testTargetName; + delete window.continueTest; + callback(); + }; +} + +function begin() { + document.addEventListener("fullscreenchange", () => { + ok(false, "Should never receive " + + "a fullscreenchange event in the main window."); + }); + SimpleTest.executeSoon(testIFrameWithoutAllowFullscreen); +} + +function testIFrameWithoutAllowFullscreen() { + // Create an iframe without an allowfullscreen attribute, whose + // contents request fullscreen. The request should be denied, and + // we should not receive a fullscreenchange event in this document. + var iframe = document.createElement("iframe"); + iframe.src = INNER_FILE; + setupForInnerTest("an iframe without allowfullscreen", () => { + document.body.removeChild(iframe); + SimpleTest.executeSoon(testFrameElement); + }); + document.body.appendChild(iframe); +} + +function testFrameElement() { + var frameset = document.createElement("frameset"); + var frame = document.createElement("frame"); + frame.src = INNER_FILE; + frameset.appendChild(frame); + setupForInnerTest("a frame element", () => { + document.documentElement.removeChild(frameset); + SimpleTest.executeSoon(testObjectElement); + }); + document.documentElement.appendChild(frameset); +} + +function testObjectElement() { + var objectElem = document.createElement("object"); + objectElem.data = INNER_FILE; + setupForInnerTest("an object element", () => { + document.body.removeChild(objectElem); + // In the following tests we want to test trust context requirement + // of fullscreen request, so temporary re-enable this pref. + SpecialPowers.pushPrefEnv({ + "set":[["full-screen-api.allow-trusted-requests-only", true]] + }, testNonTrustContext); + }); + document.body.appendChild(objectElem); +} + +function testNonTrustContext() { + addFullscreenErrorContinuation(() => { + ok(!document.fullscreenElement, + "Should not grant request in non-trust context."); + SimpleTest.executeSoon(testLongRunningEventHandler); + }); + document.documentElement.requestFullscreen(); +} + +function testLongRunningEventHandler() { + function longRunningHandler() { + window.removeEventListener("keypress", longRunningHandler); + // Busy loop until 2s has passed. We should then be past the one + // second threshold, and so our request for fullscreen should be + // rejected. + var end = (new Date()).getTime() + 2000; + while ((new Date()).getTime() < end) { + ; // Wait... + } + document.documentElement.requestFullscreen(); + } + addFullscreenErrorContinuation(() => { + ok(!document.fullscreenElement, + "Should not grant request in long-running event handler."); + // Restore the pref environment we changed before + // entering testNonTrustContext. + SpecialPowers.popPrefEnv(finish); + }); + window.addEventListener("keypress", longRunningHandler); + synthesizeKey("VK_A", {}); +} + +function finish() { + opener.nextTest(); +} + +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-esc-exit-inner.html b/dom/html/test/file_fullscreen-esc-exit-inner.html new file mode 100644 index 000000000..08744d644 --- /dev/null +++ b/dom/html/test/file_fullscreen-esc-exit-inner.html @@ -0,0 +1,58 @@ + <!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=700764 + +Verify that an ESC key press in a subdoc of a full-screen doc causes us to +exit DOM full-screen mode. + +--> +<head> + <title>Test for Bug 700764</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <style> + body:not(:fullscreen) { + background-color: blue; + } + </style> +</head> +<body> + +<script type="application/javascript"> + +/** Test for Bug 700764 **/ + +function ok(condition, msg) { + parent.ok(condition, msg); +} + +function is(a, b, msg) { + parent.is(a, b, msg); +} + +var escKeyReceived = false; +var escKeySent = false; + +function keyHandler(event) { + if (escKeyReceived == SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_ESC) { + escKeyReceived = true; + } +} + +window.addEventListener("keydown", keyHandler, true); +window.addEventListener("keyup", keyHandler, true); +window.addEventListener("keypress", keyHandler, true); + +function startTest() { + ok(!document.fullscreenElement, "Subdoc should not be in full-screen mode"); + ok(parent.document.fullscreenElement, "Parent should be in full-screen mode"); + escKeySent = true; + window.focus(); + synthesizeKey("VK_ESCAPE", {}); +} + +</script> +</pre> +<p>Inner frame</p> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-esc-exit.html b/dom/html/test/file_fullscreen-esc-exit.html new file mode 100644 index 000000000..beb52f926 --- /dev/null +++ b/dom/html/test/file_fullscreen-esc-exit.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=700764 + +Verify that an ESC key press in a subdoc of a full-screen doc causes us to +exit DOM full-screen mode. + +--> +<head> + <title>Test for Bug 700764</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> + <style> + body:fullscreen, div:fullscreen { + background-color: red; + } + </style> +</head> +<body> + +<script type="application/javascript"> + +function ok(condition, msg) { + opener.ok(condition, "[esc-exit] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[esc-exit] " + msg); +} + +function finish() { + opener.nextTest(); +} + +function fullscreenchange1(event) { + is(document.fullscreenElement, document.body, "FSE should be doc"); + addFullscreenChangeContinuation("exit", fullscreenchange2); + ok(!document.getElementById("subdoc").contentWindow.escKeySent, "Should not yet have sent ESC key press."); + document.getElementById("subdoc").contentWindow.startTest(); +} + +function fullscreenchange2(event) { + ok(document.getElementById("subdoc").contentWindow.escKeySent, "Should have sent ESC key press."); + ok(!document.getElementById("subdoc").contentWindow.escKeyReceived, "ESC key press to exit should not be delivered."); + ok(!document.fullscreenElement, "Should have left full-screen mode on ESC key press"); + finish(); +} + +function begin() { + addFullscreenChangeContinuation("enter", fullscreenchange1); + document.body.requestFullscreen(); +} + +</script> + +<!-- This subframe conducts the test. --> +<iframe id="subdoc" src="file_fullscreen-esc-exit-inner.html"></iframe> + +</pre> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-hidden.html b/dom/html/test/file_fullscreen-hidden.html new file mode 100644 index 000000000..b458a1714 --- /dev/null +++ b/dom/html/test/file_fullscreen-hidden.html @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=697636 +--> +<head> + <title>Test for Bug 697636</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<iframe id="f" src="data:text/html,<body text=green>1" allowfullscreen></iframe> + +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=697636">Mozilla Bug 697636</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 697636 **/ + +var frameWin; +var e1; + +function begin() +{ + frameWin = document.getElementById("f").contentWindow; + e1 = frameWin.document.documentElement; + frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2"; +} + +function b2() +{ + try { + e1.requestFullscreen(); + } catch(e) { + opener.ok(false, "[hidden] Should not enter full-screen"); + } + setTimeout(done, 0); +} + +function done() { + opener.ok(!document.fullscreenElement, "[hidden] Should not have entered full-screen mode in hidden document."); + opener.ok(!e1.ownerDocument.fullscreenElement, "[hidden] Requesting owner should not have entered full-screen mode."); + opener.nextTest(); +} + +</script> +</pre> +</body> + +</html> diff --git a/dom/html/test/file_fullscreen-lenient-setters.html b/dom/html/test/file_fullscreen-lenient-setters.html new file mode 100644 index 000000000..e8df91502 --- /dev/null +++ b/dom/html/test/file_fullscreen-lenient-setters.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Test for Bug 1268798</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<script> +"use strict"; + +function ok(condition, msg) { + opener.ok(condition, "[lenient-setters] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[lenient-setters] " + msg); +} + +function info(msg) { + opener.info("[lenient-setters] " + msg); +} + +let unattachedDiv = document.createElement("div"); + +function begin() { + var originalValue = document.fullscreen; + try { + document.fullscreen = !document.fullscreen; + is(document.fullscreen, originalValue, + "fullscreen should not be changed"); + } catch (e) { + ok(false, "Setting fullscreen should not throw"); + } + + var originalElem = document.fullscreenElement; + try { + document.fullscreenElement = unattachedDiv; + document.fullscreenElement = []; + is(document.fullscreenElement, originalElem, + "fullscreenElement should not be changed"); + } catch (e) { + ok(false, "Setting fullscreenElement should not throw"); + } + + var originalEnabled = document.fullscreenEnabled; + try { + document.fullscreenEnabled = !originalEnabled; + is(document.fullscreenEnabled, originalEnabled, + "fullscreenEnabled should not be changed"); + } catch (e) { + ok(false, "Setting fullscreenEnabled should not throw"); + } + + opener.nextTest(); +} + +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-multiple-inner.html b/dom/html/test/file_fullscreen-multiple-inner.html new file mode 100644 index 000000000..8390cffec --- /dev/null +++ b/dom/html/test/file_fullscreen-multiple-inner.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 724554</title> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> +</head> +<body> + +<script type="application/javascript"> + + +/** Test for Bug 545812 **/ +function begin(id) { + addFullscreenErrorContinuation(function() { + opener.ok(false, "Fullscreen denied " + id); + }); + addFullscreenChangeContinuation("enter", + function() { + opener.enteredFullscreen(id); + }); + document.body.requestFullscreen(); +} + + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-multiple.html b/dom/html/test/file_fullscreen-multiple.html new file mode 100644 index 000000000..1a457b361 --- /dev/null +++ b/dom/html/test/file_fullscreen-multiple.html @@ -0,0 +1,64 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=724554 + +Test that multiple windows can be fullscreen at the same time. + +Open one window, focus it and enter fullscreen, then open another, focus +it and enter fullscreen, and check that both are still fullscreen. + +--> +<head> + <title>Test for Bug 724554</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> +</head> +<body> + +<script type="application/javascript"> + +/** Test for Bug 545812 **/ + +function ok(condition, msg) { + opener.ok(condition, "[multiple] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[multiple] " + msg); +} + +var window1, window2; + +function openWindow(id) { + var w = window.open("file_fullscreen-multiple-inner.html", "", "width=500,height=500"); + w.addEventListener("load", function onload() { + w.focus(); + SimpleTest.waitForFocus(function(){w.begin(id)}, w); + }); + return w; +} + +function begin() { + window1 = openWindow("one"); +} + +function enteredFullscreen(id) { + if (id == "one") { + window2 = openWindow("two"); + } else if (id == "two") { + ok(window1.document.fullscreenElement && + window2.document.fullscreenElement, + "Both windows should be fullscreen concurrently"); + window1.close(); + window2.close(); + opener.nextTest(); + } +} + +</script> +</pre> +<div id="full-screen-element"></div> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-navigation.html b/dom/html/test/file_fullscreen-navigation.html new file mode 100644 index 000000000..00a4ed4e1 --- /dev/null +++ b/dom/html/test/file_fullscreen-navigation.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=685402 +--> +<head> + <title>Test for Bug 685402</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body style="background-color: gray;"> + +<iframe id="f" src="data:text/html,<body text=green>1" allowfullscreen></iframe> + +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685402">Mozilla Bug 685402</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 685402 **/ + +var frameWin; +var e1; +var prevEnabled; +var prevTrusted; + +function begin() +{ + frameWin = document.getElementById("f").contentWindow; + e1 = frameWin.document.body; + document.addEventListener("fullscreenchange", function onfullscreen() { + document.removeEventListener("fullscreenchange", onfullscreen, false); + opener.ok(document.fullscreenElement, "[navigation] Request should be granted"); + frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2"; + }, false); + + e1.requestFullscreen(); +} + +function b2() +{ + opener.ok(!document.fullscreenElement, "[navigation] Should have left full-screen due to navigation."); + opener.nextTest(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-nested.html b/dom/html/test/file_fullscreen-nested.html new file mode 100644 index 000000000..60989cd1c --- /dev/null +++ b/dom/html/test/file_fullscreen-nested.html @@ -0,0 +1,120 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 1187801</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> +</head> +<body> +<iframe src="about:blank" allowfullscreen></iframe> +<script type="text/javascript"> + +/** Test for Bug 1187801 **/ + +function info(msg) { + opener.info("[nested] " + msg); +} + +function ok(condition, msg) { + opener.ok(condition, "[nested] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[nested] " + msg); +} + +var gInnerDoc; +var gTestSteps; +var gTestIndex = 0; + +function begin() { + var root = document.documentElement; + var iframe = document.querySelector("iframe"); + var innerDoc = gInnerDoc = iframe.contentDocument; + var innerRoot = innerDoc.documentElement; + + // The format of each test step is: + // [[action, target], [fsOuter, fsInner]] where: + // * "action" is either "enter" or "exit", means whether we want to + // enter or exit fullscreen in this step. + // * "target" is where we apply this action. For "enter" action, it + // is the element we want to call requestFullscreen() on, and for + // "exit", it is the document we want to call exitFullscreen() on. + // * "fsOuter" and "fsInner" are the expected fullscreen elements of + // the outer and inner document respectively after executing the + // action in this step. + gTestSteps = [ + // innerRoot + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", innerDoc], [ null, null]], + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", document], [ null, null]], + // root, innerRoot + [["enter", root], [ root, null]], + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", innerDoc], [ root, null]], + [[ "exit", document], [ null, null]], + [["enter", root], [ root, null]], + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", document], [ root, null]], + [[ "exit", document], [ null, null]], + // iframe, innerRoot + [["enter", iframe], [iframe, null]], + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", innerDoc], [iframe, null]], + [[ "exit", document], [ null, null]], + [["enter", iframe], [iframe, null]], + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", document], [ null, null]], + // root, iframe, innerRoot + [["enter", root], [ root, null]], + [["enter", iframe], [iframe, null]], + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", innerDoc], [iframe, null]], + [[ "exit", document], [ root, null]], + [[ "exit", document], [ null, null]], + [["enter", root], [ root, null]], + [["enter", iframe], [iframe, null]], + [["enter", innerRoot], [iframe, innerRoot]], + [[ "exit", document], [ root, null]], + [[ "exit", document], [ null, null]], + ]; + + nextStep(); +} + +function nextStep() { + if (gTestIndex == gTestSteps.length) { + opener.nextTest(); + return; + } + + var index = gTestIndex; + var [[action, target], [fsOuter, fsInner]] = gTestSteps[gTestIndex++]; + + function checkAndNext() { + is(document.fullscreenElement, fsOuter, + `Fullscreen element of outer doc should match after step ${index}`); + is(gInnerDoc.fullscreenElement, fsInner, + `Fullscreen element of inner doc should match after step ${index}`); + nextStep(); + } + + info(`Executing step ${index}: ${action} on ${target}...`); + if (action == "enter") { + // For "enter" action, the target is the element + var doc = target.ownerDocument; + addFullscreenChangeContinuation("enter", checkAndNext, doc); + target.requestFullscreen(); + } else if (action == "exit") { + // For "exit" action, the target is the document + addFullscreenChangeContinuation("exit", checkAndNext, target); + target.exitFullscreen(); + } else { + ok(false, `Unknown action ${action}`); + } +} +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-plugins.html b/dom/html/test/file_fullscreen-plugins.html new file mode 100644 index 000000000..f28fbede9 --- /dev/null +++ b/dom/html/test/file_fullscreen-plugins.html @@ -0,0 +1,160 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=545812 + +Test plugins with DOM full-screen API: +* Presence of plugins has no effect on request for full-screen on MacOS. +* Request for full-screen is denied when windowed plugin in current doc is present. +* Request for full-screen is denied when windowed plugin in subdocument is present. +* Request for full-screen is not denied when the only plugin present is windowless. +* Adding an existing (out-of-doc) windowed plugin to a full-screen document causes document to exit full-screen. +* Create windowed plugin and adding it to full-screen document caused exit from full-screen. + +--> +<head> + <title>Test for Bug 545812</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="plugin-utils.js"></script> + <script type="application/javascript"> + setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); + </script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> + <style> + body:fullscreen, div:fullscreen { + background-color: red; + } + </style> +</head> +<body> + + +<!-- Windowed plugin, focusing should revoke full-screen. --> +<embed id="windowed-plugin" type="application/x-test" style="width:200px;height:100px;" wmode="window"></embed> + +<!-- Windowless plugin, focusing should not revoke full-screen. --> +<embed id="windowless-plugin" type="application/x-test" style="width:200px;height:100px;"></embed> + + +<!-- iframe contents: + +<html><body><embed id='windowed-plugin' type='application/x-test' style='width:200px;height:100px;' wmode='window'></embed></body></html> + +--> + +<iframe id="subdoc-plugin" src="data:text/html;charset=utf-8,<html><body><embed id%3D'windowed-plugin' type%3D'application%2Fx-test' style%3D'width%3A200px%3Bheight%3A100px%3B' wmode%3D'window'><%2Fembed><%2Fbody><%2Fhtml>%0D%0A"></iframe> + +<script type="application/javascript"> + +/** Test for Bug 545812 **/ + +function ok(condition, msg) { + opener.ok(condition, "[plugins] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[plugins] " + msg); +} + +function e(id) { + return document.getElementById(id); +} + +function removeElement(e) { + e.parentNode.removeChild(e); +} + +const isMacOs = navigator.appVersion.indexOf("Macintosh") != -1; + +var windowedPlugin = null; + +function begin() { + // Delay test startup long enough for the windowed plugin in the subframe to + // start up and create its window. + opener.SimpleTest.executeSoon(function() { + opener.SimpleTest.executeSoon(function() { + startTest(); + }) + }); +} + +function startTest() { + ok(!document.fullscreenElement, "Should not be in full-screen mode initially"); + document.body.requestFullscreen(); + + // Focus the windowed plugin. On MacOS we should still enter full-screen mode, + // on windows the pending request for full-screen should be denied. + e("windowed-plugin").focus(); + + if (isMacOs) { + // Running on MacOS, all plugins are effectively windowless, request for full-screen should be granted. + // Continue test in the (mac-specific) "fullscreenchange" handler. + addFullscreenChangeContinuation("enter", macFullScreenChange1); + } else { + // Non-MacOS, request should be denied, carry on the test after receiving error event. + addFullscreenErrorContinuation(nonMacTest); + } +} + +function nonMacTest() { + ok(!document.fullscreenElement, "Request for full-screen with focused windowed plugin should be denied."); + + // Focus a regular html element, and re-request full-screen, request should be granted. + e("windowless-plugin").focus(); + addFullscreenChangeContinuation("enter", nonMacTest2); + document.body.requestFullscreen(); +} + +function nonMacTest2() { + ok(document.fullscreenElement, "Request for full-screen with non-plugin focused should be granted."); + // Focus a windowed plugin, full-screen should be revoked. + addFullscreenChangeContinuation("exit", nonMacTest3); + e("windowed-plugin").focus(); +} + +function nonMacTest3() { + ok(!document.fullscreenElement, "Full-screen should have been revoked when windowed-plugin was focused."); + // Remove windowed plugins before closing the window + // to work around bug 1237853. + removeElement(e("windowed-plugin")); + removeElement(e("subdoc-plugin").contentDocument.getElementById("windowed-plugin")); + opener.nextTest(); +} + +var fullScreenChangeCount = 0; + +function createWindowedPlugin() { + var p = document.createElement("embed"); + p.setAttribute("type", "application/x-test"); + p.setAttribute("wmode", "window"); + return p; +} + +function macFullScreenChange1(event) { + ok(document.fullscreenElement, "Requests for full-screen with focused windowed plugins should be granted on MacOS"); + + // Create a new windowed plugin, and add that to the document. Should *not* exit full-screen mode on MacOS. + windowedPlugin = createWindowedPlugin(); + document.body.appendChild(windowedPlugin); + + // Focus windowed plugin. Should not exit full-screen mode on MacOS. + windowedPlugin.focus(); + + setTimeout( + function() { + ok(document.fullscreenElement, "Adding & focusing a windowed plugin to document should not cause full-screen to exit on MacOS."); + addFullscreenChangeContinuation("exit", macFullScreenChange2); + document.exitFullscreen(); + }, 0); +} + +function macFullScreenChange2(event) { + ok(!document.fullscreenElement, "Should have left full-screen mode after calling document.exitFullscreen()."); + opener.nextTest(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-prefixed.html b/dom/html/test/file_fullscreen-prefixed.html new file mode 100644 index 000000000..5f3d60196 --- /dev/null +++ b/dom/html/test/file_fullscreen-prefixed.html @@ -0,0 +1,153 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Test for Bug 743198</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> + <div id="fullscreen"></div> +<script> + +function ok(condition, msg) { + opener.ok(condition, "[prefixed] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[prefixed] " + msg); +} + +function info(msg) { + opener.info("[prefixed] " + msg); +} + +SimpleTest.requestFlakyTimeout( + "need to wait for a while to confirm no unexpected event is dispatched"); + +let div = document.getElementById("fullscreen"); +let unattachedDiv = document.createElement('div'); + +const NO_EVENT_HANDLER = 0; +const PREFIXED_EVENT_ONLY = 1; +const PREFIXED_AND_UNPREFIXED_EVENT = 2; + +class TestCase { + constructor(num, handlersOnWindow, handlersOnDocument) { + this.number = num; + this.handlersType = new Map([[window, handlersOnWindow], + [document, handlersOnDocument]]); + } + + static checkState(inFullscreen, msg) { + var emptyOrNot = inFullscreen ? "" : "not "; + info(`Check fullscreen state ${msg}`); + is(document.mozFullScreen, inFullscreen, + `Should ${emptyOrNot}be in fullscreen`); + is(document.fullscreenElement, inFullscreen ? div : null, + `Fullscreen element should be ${inFullscreen ? "div" : "null"}`); + is(document.mozFullScreenElement, document.fullscreenElement, + "document.mozFullScreenElement should be identical to fullscreenElement"); + is(div.matches(":fullscreen"), inFullscreen, + `Fullscreen element should ${emptyOrNot}match :fullscreen pseudo class`); + is(div.matches(":-moz-full-screen"), inFullscreen, + `Fullscreen element should ${emptyOrNot}match :-moz-full-screen pseudo class`); + } + + changeListeners(action, eventType, handler) { + let method = `${action}EventListener`; + for (let [target, type] of this.handlersType.entries()) { + if (type == PREFIXED_EVENT_ONLY) { + target[method](`moz${eventType}`, handler); + } else if (type == PREFIXED_AND_UNPREFIXED_EVENT) { + target[method](eventType, handler); + target[method](`moz${eventType}`, handler); + } else if (type != NO_EVENT_HANDLER) { + ok(false, `Unknown handlers type ${type}`); + } + } + } + + doTest(actionCallback, eventType, inFullscreen, msg) { + return new Promise(resolve => { + let timeout = 0; + let expectEvent = new Map(); + for (let [target, type] of this.handlersType) { + expectEvent.set(target, this.handlersType != NO_EVENT_HANDLER); + } + let handleEvent = evt => { + let target = evt.currentTarget; + let type = this.handlersType.get(target); + if (type == PREFIXED_EVENT_ONLY) { + is(evt.type, `moz${eventType}`, + `Should get prefixed event on ${target}`); + } else if (type == PREFIXED_AND_UNPREFIXED_EVENT) { + is(evt.type, eventType, + `Should only get unprefixed event on ${target}`); + } else { + ok(false, `No event should be triggered on ${target}`); + } + // Ensure we receive each event exactly once. + if (expectEvent.get(target)) { + expectEvent.set(target, false); + } else { + ok(false, `Got an unexpected ${evt.type} event on ${target}`); + } + if (!timeout) { + timeout = setTimeout(() => { + this.changeListeners("remove", eventType, handleEvent); + TestCase.checkState(inFullscreen, + `${msg} in test case ${this.number}`); + resolve(); + }); + } + }; + this.changeListeners("add", eventType, handleEvent); + actionCallback(); + }); + } + + test() { + return new Promise(resolve => { + Promise.resolve().then(() => { + return this.doTest(() => div.mozRequestFullScreen(), + "fullscreenchange", true, "after request"); + }).then(() => { + return this.doTest(() => document.mozCancelFullScreen(), + "fullscreenchange", false, "after exit"); + }).then(() => { + return this.doTest(() => unattachedDiv.mozRequestFullScreen(), + "fullscreenerror", false, "after failed request"); + }).then(resolve); + }); + } +} + +let gTestcases = [ + new TestCase(1, PREFIXED_EVENT_ONLY, NO_EVENT_HANDLER), + new TestCase(2, PREFIXED_AND_UNPREFIXED_EVENT, NO_EVENT_HANDLER), + new TestCase(3, NO_EVENT_HANDLER, PREFIXED_EVENT_ONLY), + new TestCase(4, PREFIXED_EVENT_ONLY, PREFIXED_EVENT_ONLY), + new TestCase(5, PREFIXED_AND_UNPREFIXED_EVENT, PREFIXED_EVENT_ONLY), + new TestCase(6, NO_EVENT_HANDLER, PREFIXED_AND_UNPREFIXED_EVENT), + new TestCase(7, PREFIXED_EVENT_ONLY, PREFIXED_AND_UNPREFIXED_EVENT), + new TestCase(8, PREFIXED_AND_UNPREFIXED_EVENT, PREFIXED_AND_UNPREFIXED_EVENT), + ]; + +function begin() { + TestCase.checkState(false, "at the beginning"); + runNextTestCase(); +} + +function runNextTestCase() { + let testcase = gTestcases.shift(); + if (!testcase) { + opener.nextTest(); + return; + } + testcase.test().then(runNextTestCase); +} + +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-rollback.html b/dom/html/test/file_fullscreen-rollback.html new file mode 100644 index 000000000..605a917aa --- /dev/null +++ b/dom/html/test/file_fullscreen-rollback.html @@ -0,0 +1,128 @@ + <!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=700764 + +Verifies that cancelFullScreen() rolls back to have the previous full-screen +element full-screen. + +Tests: +* Request full-screen in doc. +* Request full-screen in doc on element not descended from full-screen element. Request should be denied. +* Request full-screen in subdoc. +* Cancel full-screen in subdoc, doc should be full-screen. +* Request full-screen in subdoc. +* Removing FSE should fully-exit full-screen. + + +--> +<head> + <title>Test for Bug 700764</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> +</head> +<body> + +<div id="fse"> + <div id="fse-inner"> + <iframe id="subdoc" allowfullscreen src="data:text/html,<html><body bgcolor='black'></body></html>"></iframe> + </div> +</div> + +<div id="non-fse"></div> + +<script type="application/javascript"> + +/** Test for Bug 700764 **/ + +function ok(condition, msg) { + opener.ok(condition, "[rollback] " + msg); + if (!condition) { + opener.finish(); + } +} + +function is(a, b, msg) { + opener.is(a, b, "[rollback] " + msg); + if (a != b) { + opener.finish(); + } +} + +function enterFullscreen(element, callback) { + addFullscreenChangeContinuation("enter", callback); + element.focus(); + element.requestFullscreen(); +} + +function revertFullscreen(doc, callback) { + ok(doc.fullscreenElement != null, "Should only exit fullscreen on a fullscreen doc"); + addFullscreenChangeContinuation("exit", callback, doc); + doc.exitFullscreen(); +} + +function e(id) { + return document.getElementById(id); +} + +function requestFullscreen(element) { + element.focus(); + element.requestFullscreen(); +} + +function begin() { + enterFullscreen(e("fse"), change1); +} + +function change1() { + is(document.fullscreenElement, e("fse"), "Body should be FSE"); + // Request full-screen from element not descendent from current FSE. + addFullscreenErrorContinuation(error1); + requestFullscreen(e("non-fse")); +} + +function error1() { + is(document.fullscreenElement, e("fse"), "FSE should not change"); + var iframe = e("subdoc"); + enterFullscreen(iframe.contentDocument.body, change2); +} + +function change2() { + var iframe = e("subdoc"); + is(document.fullscreenElement, iframe, "Subdoc container should be FSE."); + is(iframe.contentDocument.fullscreenElement, iframe.contentDocument.body, "Subdoc body should be FSE in subdoc"); + revertFullscreen(document, change3); +} + +function change3() { + is(document.fullscreenElement, e("fse"), "FSE should rollback to FSE."); + revertFullscreen(document, change4); +} + +function change4() { + is(document.fullscreenElement, null, "Should have left full-screen entirely"); + enterFullscreen(e("fse"), change5); +} + +function change5() { + is(document.fullscreenElement, e("fse"), "FSE should be e('fse')"); + enterFullscreen(e("fse-inner"), change6); +} + +function change6() { + addFullscreenChangeContinuation("exit", change7); + var element = e('fse-inner'); + is(document.fullscreenElement, element, "FSE should be e('fse-inner')"); + element.parentNode.removeChild(element); +} + +function change7() { + is(document.fullscreenElement, null, "Should have fully exited full-screen mode when removed FSE from doc"); + opener.nextTest(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-scrollbar.html b/dom/html/test/file_fullscreen-scrollbar.html new file mode 100644 index 000000000..76a090681 --- /dev/null +++ b/dom/html/test/file_fullscreen-scrollbar.html @@ -0,0 +1,126 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Test for Bug 1201798</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="file_fullscreen-utils.js"></script> + <style> + html, body, #measure { + width: 100%; height: 100%; + } + #ref-outer { width: 100px; height: 100px; overflow: scroll; } + #ref-inner { width: 100%; height: 100%; } + </style> +</head> +<body> +<div id="measure"></div> +<div style="height: 1000vh; width: 1000vw"></div> +<div id="ref-outer"> + <div id="ref-inner"></div> +</div> +<div id="fullscreen"></div> +<script type="text/javascript"> + +/** Test for Bug 1201798 */ + +var info = msg => opener.info("[scrollbar] " + msg); +var ok = (cond, msg) => opener.ok(cond, "[scrollbar] " + msg); +var is = (a, b, msg) => opener.is(a, b, "[scrollbar] " + msg); + +var gVerticalScrollbarWidth, gHorizontalScrollbarWidth; +var gMeasureDiv = document.getElementById("measure"); +var gFullscreenDiv = document.getElementById("fullscreen"); + +function getMeasureRect() { + return gMeasureDiv.getBoundingClientRect(); +} + +function triggerFrameReconstruction() { + info("Triggering a force frame reconstruction"); + var docElem = document.documentElement; + var wm = window.getComputedStyle(docElem).writingMode; + if (wm == "horizontal-tb") { + docElem.style.writingMode = "vertical-rl"; + } else { + docElem.style.writingMode = "horizontal-tb"; + } + docElem.getBoundingClientRect(); +} + +function assertHasScrollbars(elem) { + var rect = getMeasureRect(); + is(rect.width, screen.width - gVerticalScrollbarWidth, + `Should have vertical scrollbar when ${elem} is in fullscreen`); + is(rect.height, screen.height - gHorizontalScrollbarWidth, + `Should have horizontal scrollbar when ${elem} is in fullscreen`); +} + +function assertHasNoScrollbars(elem) { + var rect = getMeasureRect(); + is(rect.width, screen.width, + `Should not have vertical scrollbar when ${elem} is in fullscreen`); + is(rect.height, screen.height, + `Should not have horizontal scrollbar when ${elem} is in fullscreen`); +} + +function checkScrollbars(elem, shouldHaveScrollbars) { + is(elem, document.fullscreenElement, + "Should only check the current fullscreen element"); + var assertFunc = shouldHaveScrollbars ? + assertHasScrollbars : assertHasNoScrollbars; + assertFunc(elem); + triggerFrameReconstruction(); + assertFunc(elem); +} + +function begin() { + if (window.matchMedia("(-moz-overlay-scrollbar").matches) { + // If overlay scrollbar is enabled, the scrollbar is not measurable, + // so we skip this test in that case. + info("Skip this test because of overlay scrollbar"); + opener.nextTest(); + return; + } + + var rectOuter = document.getElementById("ref-outer").getBoundingClientRect(); + var rectInner = document.getElementById("ref-inner").getBoundingClientRect(); + gVerticalScrollbarWidth = rectOuter.width - rectInner.width; + gHorizontalScrollbarWidth = rectOuter.height - rectInner.height; + ok(gVerticalScrollbarWidth != 0, "Should have vertical scrollbar"); + ok(gHorizontalScrollbarWidth != 0, "Should have horizontal scrollbar"); + + info("Entering fullscreen on root"); + addFullscreenChangeContinuation("enter", enteredFullscreenOnRoot); + document.documentElement.requestFullscreen(); +} + +function enteredFullscreenOnRoot() { + checkScrollbars(document.documentElement, true); + info("Entering fullscreen on div"); + addFullscreenChangeContinuation("enter", enteredFullscreenOnDiv); + gFullscreenDiv.requestFullscreen(); +} + +function enteredFullscreenOnDiv() { + checkScrollbars(gFullscreenDiv, false); + info("Exiting fullscreen on div"); + addFullscreenChangeContinuation("exit", exitedFullscreenOnDiv); + document.exitFullscreen(); +} + +function exitedFullscreenOnDiv() { + checkScrollbars(document.documentElement, true); + info("Exiting fullscreen on root"); + addFullscreenChangeContinuation("exit", exitedFullscreenOnRoot); + document.exitFullscreen(); +} + +function exitedFullscreenOnRoot() { + opener.nextTest(); +} + +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-selector.html b/dom/html/test/file_fullscreen-selector.html new file mode 100644 index 000000000..9aceb659e --- /dev/null +++ b/dom/html/test/file_fullscreen-selector.html @@ -0,0 +1,178 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 1199522</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="file_fullscreen-utils.js"></script> + <style> + div { + position: fixed; + top: 20px; height: 50px; + opacity: 0.3; + border: 5px solid black; + box-sizing: border-box; + } + #fullscreen0 { + left: 50px; width: 50px; + background: #ff0000; + border-color: #800000; + } + #fullscreen1 { + left: 100px; width: 50px; + background: #00ff00; + border-color: #008000; + } + #fullscreen2 { + left: 150px; width: 50px; + background: #0000ff; + border-color: #000080; + } + </style> +</head> +<body> +<script type="application/javascript"> + +/** Test for Bug 1199522 **/ + +function info(msg) { + opener.info("[selector] " + msg); +} + +function ok(condition, msg) { + opener.ok(condition, "[selector] " + msg); +} + +function is(a, b, msg) { + opener.is(a, b, "[selector] " + msg); +} + +function rectEquals(rect1, rect2) { + return rect1.x == rect2.x && rect1.y == rect2.y && + rect1.width == rect2.width && rect1.height == rect2.height; +} + +function getViewportRect() { + return new DOMRect(0, 0, window.innerWidth, window.innerHeight); +} + +var fullscreenElems = []; + +function checkFullscreenState(elem, hasState, viewportRect) { + var id = elem.id; + var rect = elem.getBoundingClientRect(); + if (hasState) { + ok(elem.matches(":fullscreen"), + `${id} should match selector ":fullscreen"`); + ok(rectEquals(rect, viewportRect), + `The bounding rect of ${id} should match the viewport`); + } else { + ok(!elem.matches(":fullscreen"), + `${id} should not match selector ":fullscreen"`); + ok(rectEquals(rect, elem.initialRect), + `The bounding rect of ${id} should match its initial state`); + } +} + +function checkFullscreenStates(states) { + var viewportRect = getViewportRect(); + fullscreenElems.forEach((elem, index) => { + checkFullscreenState(elem, states[index], viewportRect); + }); +} + +function begin() { + fullscreenElems.push(document.getElementById('fullscreen0')); + fullscreenElems.push(document.getElementById('fullscreen1')); + fullscreenElems.push(document.getElementById('fullscreen2')); + + var viewportRect = getViewportRect(); + for (var elem of fullscreenElems) { + var rect = elem.getBoundingClientRect(); + var id = elem.id; + elem.initialRect = rect; + ok(!elem.matches(":fullscreen"), + `${id} should not match selector ":fullscreen"`); + ok(!rectEquals(elem.initialRect, viewportRect), + `The initial bounding rect of ${id} should not match the viewport`); + } + + info("Entering fullscreen on fullscreen0"); + addFullscreenChangeContinuation("enter", enter0); + fullscreenElems[0].requestFullscreen(); +} + +function enter0() { + checkFullscreenStates([true, false, false]); + info("Entering fullscreen on fullscreen1"); + addFullscreenChangeContinuation("enter", enter1); + fullscreenElems[1].requestFullscreen(); +} + +function enter1() { + checkFullscreenStates([true, true, false]); + info("Entering fullscreen on fullscreen2"); + addFullscreenChangeContinuation("enter", enter2); + fullscreenElems[2].requestFullscreen(); +} + +function enter2() { + checkFullscreenStates([true, true, true]); + info("Leaving fullscreen on fullscreen2"); + addFullscreenChangeContinuation("exit", exit2); + document.exitFullscreen(); +} + +function exit2() { + checkFullscreenStates([true, true, false]); + info("Leaving fullscreen on fullscreen1"); + addFullscreenChangeContinuation("exit", exit1); + document.exitFullscreen(); +} + +function exit1() { + checkFullscreenStates([true, false, false]); + info("Leaving fullscreen on fullscreen0"); + addFullscreenChangeContinuation("exit", exit0); + document.exitFullscreen(); +} + +function exit0() { + checkFullscreenStates([false, false, false]); + + info("Entering fullscreen on all elements"); + var count = 0; + function listener() { + if (++count == 3) { + document.removeEventListener("fullscreenchange", listener); + enterAll(); + } + } + document.addEventListener("fullscreenchange", listener); + fullscreenElems[0].requestFullscreen(); + fullscreenElems[1].requestFullscreen(); + fullscreenElems[2].requestFullscreen(); +} + +function enterAll() { + checkFullscreenStates([true, true, true]); + info("Fully-exiting fullscreen"); + addFullscreenChangeContinuation("exit", exitAll); + synthesizeKey("VK_ESCAPE", {}); +} + +function exitAll() { + checkFullscreenStates([false, false, false]); + opener.nextTest(); +} + +</script> +</pre> +<div id="fullscreen0"> + <div id="fullscreen1"> + <div id="fullscreen2"> + </div> + </div> +</div> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-svg-element.html b/dom/html/test/file_fullscreen-svg-element.html new file mode 100644 index 000000000..dd0f3b593 --- /dev/null +++ b/dom/html/test/file_fullscreen-svg-element.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> + <!-- + https://bugzilla.mozilla.org/show_bug.cgi?id=735031 + Bug 735031 - Fullscreen API implementation assumes an HTML Element + --> + <head> + <title>Bug 735031</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"> + </script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=73503"> + Mozilla Bug 735031</a> + + <svg id="svg-elem" width="100" height="100" viewbox="0 0 100 100"> + <rect x="10" y="10" width="50" height="50" + fill="black" stroke="blue" stroke-width="2"/> + </svg> + + <pre id="test"> + <script type="application/javascript"> + /* + * Test for Bug 735031 + * Test locking non-html element. + */ + function begin() { + var elem = document.getElementById("svg-elem") + , elemWasLocked = false; + + document.addEventListener("fullscreenchange", function (e) { + if (document.fullscreenElement === elem) { + elemWasLocked = true; + document.exitFullscreen(); + } else { + opener.ok(elemWasLocked, "Expected SVG elem to become locked."); + opener.nextTest(); + } + }, false); + elem.requestFullscreen(); + } + </script> + </pre> + </body> +</html> diff --git a/dom/html/test/file_fullscreen-top-layer.html b/dom/html/test/file_fullscreen-top-layer.html new file mode 100644 index 000000000..fe3d2cf9e --- /dev/null +++ b/dom/html/test/file_fullscreen-top-layer.html @@ -0,0 +1,160 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Test for Bug 1126230</title> + <style> + #back { + position: fixed !important; + z-index: 2147483647 !important; + top: 0 !important; left: 0 !important; + right: 0 !important; bottom: 0 !important; + width: 100% !important; height: 100% !important; + } + #parent { + position: fixed; + z-index: -2147483748; + width: 0; height: 0; + overflow: hidden; + opacity: 0; + mask: url(#mask); + clip: rect(0, 0, 0, 0); + clip-path: url(#clipPath); + filter: opacity(0%); + will-change: transform; + perspective: 10px; + transform: scale(0); + } + /* The following styles are copied from ua.css to ensure that + * no other style change may trigger frame reconstruction */ + :root { + overflow: hidden !important; + } + .two #fullscreen { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + z-index: 2147483647 !important; + width: 100% !important; + height: 100% !important; + margin: 0 !important; + min-width: 0 !important; + max-width: none !important; + min-height: 0 !important; + max-height: none !important; + box-sizing: border-box !important; + } + </style> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script> + <script type="text/javascript" src="file_fullscreen-utils.js"></script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1126230">Mozilla Bug 1126230</a> +<div id="parent"> + <div id="fullscreen" style="background-color: green"></div> +</div> +<div id="back" style="background-color: red"></div> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <clipPath id="clipPath"></clipPath> + <mask id="mask"></mask> + </defs> +</svg> +<script> +const gParentProperties = [ + "position", "zIndex", "overflow", + "opacity", "mask", "clip", "clipPath", + "filter", "willChange", "transform" +]; + +var gInitialVals = {}; + +const gParent = document.getElementById("parent"); +const gFullscreen = document.getElementById("fullscreen"); +const gBack = document.getElementById("back"); + +function is(a, b, msg) { + opener.is(a, b, "[top-layer] " + msg); +} + +function isnot(a, b, msg) { + opener.isnot(a, b, "[top-layer] " + msg); +} + +function ok(cond, msg) { + opener.ok(cond, "[top-layer] " + msg); +} + +function synthesizeMouseAtWindowCenter() { + synthesizeMouseAtPoint(innerWidth / 2, innerHeight / 2, {}); +} + + +var tests = ["one", "two"]; + +function begin() { + // record initial computed style of #parent + const style = getComputedStyle(gParent); + for (var prop of gParentProperties) { + gInitialVals[prop] = style[prop]; + } + + nextTest(); +} + +function nextTest() { + document.body.className = tests.shift(); + // trigger a reflow to ensure the state of frames before fullscreen + gFullscreen.getBoundingClientRect(); + + ok(!document.fullscreenElement, "Shouldn't be in fullscreen"); + // check window snapshot + assertWindowPureColor(window, "red"); + // simulate click + window.addEventListener("click", firstClick); + synthesizeMouseAtWindowCenter(); +} + +function firstClick(evt) { + window.removeEventListener("click", firstClick); + is(evt.target, gBack, "Click target should be #back before fullscreen"); + addFullscreenChangeContinuation("enter", enterFullscreen); + gFullscreen.requestFullscreen(); +} + +function enterFullscreen() { + ok(document.fullscreenElement, "Should now be in fullscreen"); + // check window snapshot + assertWindowPureColor(window, "green"); + // check computed style of #parent + const style = getComputedStyle(gParent); + for (var prop of gParentProperties) { + is(style[prop], gInitialVals[prop], + `Computed style ${prop} of #parent should not be changed`); + } + // simulate click + window.addEventListener("click", secondClick); + synthesizeMouseAtWindowCenter(); +} + +function secondClick(evt) { + window.removeEventListener("click", secondClick); + is(evt.target, gFullscreen, "Click target should be #fullscreen now"); + addFullscreenChangeContinuation("exit", exitFullscreen); + document.exitFullscreen(); +} + +function exitFullscreen() { + if (tests.length > 0) { + nextTest(); + } else { + opener.nextTest(); + } +} +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-unprefix-disabled-inner.html b/dom/html/test/file_fullscreen-unprefix-disabled-inner.html new file mode 100644 index 000000000..632a6c0ce --- /dev/null +++ b/dom/html/test/file_fullscreen-unprefix-disabled-inner.html @@ -0,0 +1,96 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Test for Bug 1268749</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> + <div id="fullscreen"></div> +<script> + +function ok(condition, msg) { + opener.opener.ok(condition, "[unprefix-disabled] " + msg); +} + +function is(a, b, msg) { + opener.opener.is(a, b, "[unprefix-disabled] " + msg); +} + +function info(msg) { + opener.opener.info("[unprefix-disabled] " + msg); +} + +SimpleTest.requestFlakyTimeout( + "need to wait for a while to confirm no unexpected event is dispatched"); + +let div = document.getElementById("fullscreen"); +let unattachedDiv = document.createElement('div'); + +function begin() { + ok(!("requestFullscreen" in div), "No element.requestFullscreen"); + ok(!("exitFullscreen" in document), "No document.exitFullscreen"); + ok(!("fullscreen" in document), "No document.fullscreen"); + ok(!("fullscreenElement" in document), "No document.fullscreenElement"); + ok(!("fullscreenEnabled" in document), "No document.fullscreenEnabled"); + ok(!("onfullscreenchange" in document), "No document.onfullscreenchange"); + ok(!("onfullscreenerror" in document), "No document.onfullscreenerror"); + + for (var event of ["fullscreenchange", "fullscreenerror"]) { + let customEvent = new Event(event, {bubbles: true}); + let gotCustomEventFromWindow = false; + let gotCustomEventFromDocument = false; + let listenerForWindow = evt => { + ok(!gotCustomEventFromWindow, + "Should get custom event from window only once"); + ok(evt == customEvent, "Should get the desired custom event"); + gotCustomEventFromWindow = true; + }; + let listenerForDocument = evt => { + ok(!gotCustomEventFromDocument, + "Should get custom event from document only once"); + ok(evt == customEvent, "Should get the desired custom event"); + gotCustomEventFromDocument = true; + }; + window.addEventListener(event, listenerForWindow); + document.addEventListener(event, listenerForDocument); + document.dispatchEvent(customEvent); + ok(gotCustomEventFromWindow, "Should get the custom event from window"); + ok(gotCustomEventFromDocument, "Should get the custom event from document"); + window.removeEventListener(event, listenerForWindow); + document.removeEventListener(event, listenerForDocument); + + for (var target of [window, document]) { + target.addEventListener(event, () => { + ok(false, `No ${event} should be triggered on ${target}`); + }); + } + } + + document.addEventListener("mozfullscreenchange", enteredFullscreen); + SimpleTest.executeSoon(() => div.mozRequestFullScreen()); +} + +function enteredFullscreen() { + document.removeEventListener("mozfullscreenchange", enteredFullscreen); + document.addEventListener("mozfullscreenchange", exitedFullscreen); + SimpleTest.executeSoon(() => document.mozCancelFullScreen()); +} + +function exitedFullscreen() { + document.removeEventListener("mozfullscreenchange", exitedFullscreen); + document.addEventListener("mozfullscreenerror", errorFullscreen); + SimpleTest.executeSoon(() => unattachedDiv.mozRequestFullScreen()); +} + +function errorFullscreen() { + document.removeEventListener("mozfullscreenerror", errorFullscreen); + // Wait a short time before exiting this test to confirm that there is + // really no unwanted event gets dispatched. + setTimeout(() => opener.finish(), 200); +} + +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-unprefix-disabled.html b/dom/html/test/file_fullscreen-unprefix-disabled.html new file mode 100644 index 000000000..59737ec1d --- /dev/null +++ b/dom/html/test/file_fullscreen-unprefix-disabled.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Test for Bug 1268749</title> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<script> + +var gWindow = null; + +function begin() { + SpecialPowers.pushPrefEnv({ + "set": [["full-screen-api.unprefix.enabled", false]] + }, () => { + gWindow = window.open("file_fullscreen-unprefix-disabled-inner.html", + "", "width=500,height=500"); + gWindow.addEventListener("load", () => { + gWindow.focus(); + SimpleTest.waitForFocus(() => gWindow.begin(), gWindow); + }); + }); +} + +function finish() { + gWindow.close(); + SpecialPowers.popPrefEnv(opener.nextTest); +} + +</script> +</body> +</html> diff --git a/dom/html/test/file_fullscreen-utils.js b/dom/html/test/file_fullscreen-utils.js new file mode 100644 index 000000000..d1af72f8c --- /dev/null +++ b/dom/html/test/file_fullscreen-utils.js @@ -0,0 +1,82 @@ + +// Returns true if the window occupies the entire screen. +// Note this only returns true once the transition from normal to +// fullscreen mode is complete. +function inFullscreenMode(win) { + return win.innerWidth == win.screen.width && + win.innerHeight == win.screen.height; +} + +// Returns true if the window is in normal mode, i.e. non fullscreen mode. +// Note this only returns true once the transition from fullscreen back to +// normal mode is complete. +function inNormalMode(win) { + return win.innerWidth == win.normalSize.w && + win.innerHeight == win.normalSize.h; +} + +// Adds a listener that will be called once a fullscreen transition +// is complete. When type==='enter', callback is called when we've +// received a fullscreenchange event, and the fullscreen transition is +// complete. When type==='exit', callback is called when we've +// received a fullscreenchange event and the window dimensions match +// the window dimensions when the window opened (so don't resize the +// window while running your test!). inDoc is the document which +// the listeners are added on, if absent, the listeners are added to +// the current document. +function addFullscreenChangeContinuation(type, callback, inDoc) { + var doc = inDoc || document; + var topWin = doc.defaultView.top; + // Remember the window size in non-fullscreen mode. + if (!topWin.normalSize) { + topWin.normalSize = { + w: window.innerWidth, + h: window.innerHeight + }; + } + function checkCondition() { + if (type == "enter") { + return inFullscreenMode(topWin); + } else if (type == "exit") { + // If we just revert the state to a previous fullscreen state, + // the window won't back to the normal mode. Hence we check + // fullscreenElement first here. Note that we need to check + // the fullscreen element of the outmost document here instead + // of the current one. + return topWin.document.fullscreenElement || inNormalMode(topWin); + } else { + throw "'type' must be either 'enter', or 'exit'."; + } + } + function invokeCallback(event) { + // Use async call after a paint to workaround unfinished fullscreen + // change even when the window size has changed on Linux. + requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0); + } + function onFullscreenChange(event) { + doc.removeEventListener("fullscreenchange", onFullscreenChange, false); + if (checkCondition()) { + invokeCallback(event); + return; + } + function onResize() { + if (checkCondition()) { + topWin.removeEventListener("resize", onResize, false); + invokeCallback(event); + } + } + topWin.addEventListener("resize", onResize, false); + } + doc.addEventListener("fullscreenchange", onFullscreenChange, false); +} + +// Calls |callback| when the next fullscreenerror is dispatched to inDoc||document. +function addFullscreenErrorContinuation(callback, inDoc) { + var doc = inDoc || document; + var listener = function(event) { + doc.removeEventListener("fullscreenerror", listener, false); + setTimeout(function(){callback(event);}, 0); + }; + doc.addEventListener("fullscreenerror", listener, false); +} + diff --git a/dom/html/test/file_iframe_sandbox_a_if1.html b/dom/html/test/file_iframe_sandbox_a_if1.html new file mode 100644 index 000000000..b60d52ca0 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if1.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + I am sandboxed without any permissions + <iframe id="if_2a" src="file_iframe_sandbox_a_if2.html" height="10" width="10"></iframe> + <iframe id="if_2b" sandbox="allow-scripts" src="file_iframe_sandbox_a_if2.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_a_if10.html b/dom/html/test/file_iframe_sandbox_a_if10.html new file mode 100644 index 000000000..14306eb61 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if10.html @@ -0,0 +1,12 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<frameset> + <frame src="file_iframe_sandbox_a_if11.html"> + <frame src="file_iframe_sandbox_a_if16.html"> +</frameset> +</html> diff --git a/dom/html/test/file_iframe_sandbox_a_if11.html b/dom/html/test/file_iframe_sandbox_a_if11.html new file mode 100644 index 000000000..8eee71df1 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if11.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script> + function doStuff() { + try { + window.parent.parent.ok_wrapper(false, "a frame inside a sandboxed iframe should NOT be same origin with the iframe's parent"); + } + catch (e) { + window.parent.parent.postMessage({ok: true, desc: "a frame inside a sandboxed iframe is not same origin with the iframe's parent"}, "*"); + } + } + </script> +</head> +<frameset> + <frame onload='doStuff()' src="file_iframe_sandbox_a_if12.html"> +</frameset> +I'm a <frame> inside an iframe which is sandboxed with 'allow-scripts allow-forms' +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if12.html b/dom/html/test/file_iframe_sandbox_a_if12.html new file mode 100644 index 000000000..d49d4e562 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if12.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> +function doStuff() { + try { + window.parent.parent.parent.ok_wrapper(false, "a frame inside a frame inside a sandboxed iframe should NOT be same origin with the iframe's parent"); + } + catch (e) { + dump("caught some e if12\n"); + window.parent.parent.parent.postMessage({ok: true, desc: "a frame inside a frame inside a sandboxed iframe is not same origin with the iframe's parent"}, "*"); + } +} +</script> +<body onload='doStuff()'> + I'm a <frame> inside a <frame> inside an iframe which is sandboxed with 'allow-scripts allow-forms' +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if13.html b/dom/html/test/file_iframe_sandbox_a_if13.html new file mode 100644 index 000000000..8737a7682 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if13.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 886262</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body> + <object data="file_iframe_sandbox_a_if14.html"></object> +</body> + +</html> diff --git a/dom/html/test/file_iframe_sandbox_a_if14.html b/dom/html/test/file_iframe_sandbox_a_if14.html new file mode 100644 index 000000000..77210fca0 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if14.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 886262</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + window.addEventListener("message", receiveMessage, false); + + function receiveMessage(event) + { + window.parent.parent.postMessage({ok: event.data.ok, desc: "objects containing " + event.data.desc}, "*"); + } + + function doStuff() { + try { + window.parent.parent.ok_wrapper(false, "an object inside a sandboxed iframe should NOT be same origin with the iframe's parent"); + } + catch (e) { + window.parent.parent.postMessage({ok: true, desc: "an object inside a sandboxed iframe is not same origin with the iframe's parent"}, "*"); + } + } +</script> + +<body onload='doStuff()'> +I'm a <object> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + + <object data="file_iframe_sandbox_a_if15.html"></object> +</body> + +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if15.html b/dom/html/test/file_iframe_sandbox_a_if15.html new file mode 100644 index 000000000..9c5a003d7 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if15.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 886262</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> +function doStuff() { + try { + window.parent.parent.parent.ok_wrapper(false, "an object inside a frame or object inside a sandboxed iframe should NOT be same origin with the iframe's parent"); + } + catch (e) { + window.parent.parent.parent.postMessage({ok: true, desc: "an object inside a frame or object inside a sandboxed iframe is not same origin with the iframe's parent"}, "*"); + } + + // Check that sandboxed forms browsing context flag NOT set by attempting to submit a form. + document.getElementById('a_form').submit(); +} +</script> + +<body onload='doStuff()'> + I'm a <object> inside a <frame> or <object> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + + <form method="get" action="file_iframe_sandbox_form_pass.html" id="a_form"> + First name: <input type="text" name="firstname"> + Last name: <input type="text" name="lastname"> + <input type="submit" id="a_button"> + </form> +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if16.html b/dom/html/test/file_iframe_sandbox_a_if16.html new file mode 100644 index 000000000..f92531465 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if16.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 886262</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + window.addEventListener("message", receiveMessage, false); + + function receiveMessage(event) + { + window.parent.parent.postMessage({ok: event.data.ok, desc: "objects containing " + event.data.desc}, "*"); + } +</script> + +<body> +I'm a <frame> inside an iframe which is sandboxed with 'allow-scripts allow-forms' + + <object data="file_iframe_sandbox_a_if15.html"></object> +</body> + +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if17.html b/dom/html/test/file_iframe_sandbox_a_if17.html new file mode 100644 index 000000000..a736924bf --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if17.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 886262</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doTest() { + var if_18_19 = document.getElementById('if_18_19'); + if_18_19.sandbox = "allow-scripts allow-same-origin"; + if_18_19.contentWindow.postMessage("go", "*"); + } +</script> + +<body onload="doTest()"> + I am sandboxed but with "allow-scripts". I change the sandbox flags on if_18_19 to + "allow-scripts allow-same-origin" then get it to re-navigate itself to + file_iframe_sandbox_a_if18.html, which attemps to call a function in my parent. + This should fail since my sandbox flags should be copied to it when the sandbox + flags are changed. + + <iframe sandbox="allow-scripts" id="if_18_19" src="file_iframe_sandbox_a_if19.html" height="10" width="10"></iframe> +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if18.html b/dom/html/test/file_iframe_sandbox_a_if18.html new file mode 100644 index 000000000..bbe90970d --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if18.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 886262</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doTest() { + try { + window.parent.parent.ok_wrapper(false, "an iframe in an iframe SHOULD copy its parent's sandbox flags when its sandbox flags are changed"); + } + catch (e) { + window.parent.parent.postMessage({ok: true, desc: "an iframe in an iframe copies its parent's sandbox flags when its sandbox flags are changed"}, "*"); + } + } +</script> + +<body onload="doTest()"> + I'm an iframe whose sandbox flags have been changed to include allow-same-origin. + I should not be able to call a function in my parent's parent because my parent's + iframe does not have allow-same-origin set. +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if19.html b/dom/html/test/file_iframe_sandbox_a_if19.html new file mode 100644 index 000000000..a065a9450 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if19.html @@ -0,0 +1,21 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 886262</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script> + window.addEventListener("message", function(e){ + window.open("file_iframe_sandbox_a_if18.html", "_self"); + }, false); +</script> + +<body> + I'm just here to navigate to file_iframe_sandbox_a_if18.html after my owning + iframe has had allow-same-origin added. +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if2.html b/dom/html/test/file_iframe_sandbox_a_if2.html new file mode 100644 index 000000000..72bde69e4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if2.html @@ -0,0 +1,21 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> +function doStuff() { + // should NOT be able to execute scripts + window.parent.parent.postMessage({ok: false, desc: "a document within an iframe sandboxed with sandbox='' should NOT be able to execute scripts"}, "*"); +} +</script> + +<body onLoad="doStuff()"> + I am NOT sandboxed or am sandboxed with "allow-scripts" but am contained within an iframe sandboxed with sandbox = "" + or am sandboxed with sandbox='' inside an iframe sandboxed with "allow-scripts" +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if3.html b/dom/html/test/file_iframe_sandbox_a_if3.html new file mode 100644 index 000000000..c103c19f2 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if3.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script type="text/javascript"> + function ok_wrapper(condition, msg) { + window.parent.ok_wrapper(condition, msg); + } +</script> + +<body> + I am sandboxed but with "allow-scripts" + + <iframe id='if_4' src='file_iframe_sandbox_a_if4.html' height="10" width="10"></iframe> + <iframe id='if_7' src='file_iframe_sandbox_a_if7.html' height="10" width="10"></iframe> + <iframe id='if_2' sandbox='' src='file_iframe_sandbox_a_if2.html' height="10" width="10"></iframe> +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if4.html b/dom/html/test/file_iframe_sandbox_a_if4.html new file mode 100644 index 000000000..2bd727e96 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if4.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script type="text/javascript"> +function doStuff() { + try { + window.parent.ok_wrapper(false, "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with its parent"); + } catch(e) { + window.parent.parent.postMessage({type: "ok", ok: true, desc: "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with its parent"}, "*"); + } + + try { + window.parent.parent.ok_wrapper(false, "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with the top level"); + } catch(e) { + window.parent.parent.postMessage({type: "ok", ok: true, desc: "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with the top level"}, "*"); + } +} +</script> + +<body onLoad="doStuff()"> + I am not sandboxed but contained within a sandboxed document with 'allow-scripts' +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if5.html b/dom/html/test/file_iframe_sandbox_a_if5.html new file mode 100644 index 000000000..dfa0fed01 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if5.html @@ -0,0 +1,22 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script type="text/javascript"> + function ok_wrapper(result, desc) { + window.parent.ok_wrapper(result, desc); + } +</script> + +<body> + I am sandboxed but with "allow-scripts allow-same-origin" + + <iframe sandbox='allow-scripts allow-same-origin' id='if_6' src='file_iframe_sandbox_a_if6.html' height="10" width="10"></iframe> +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if6.html b/dom/html/test/file_iframe_sandbox_a_if6.html new file mode 100644 index 000000000..79f15e6ec --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if6.html @@ -0,0 +1,21 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script type="text/javascript"> +function doStuff() { + window.parent.ok_wrapper(true, "a document sandboxed with 'allow-same-origin' and contained within a sandboxed document with 'allow-same-origin' should be same domain with its parent"); + window.parent.parent.ok_wrapper(true, "a document sandboxed with 'allow-same-origin' contained within a sandboxed document with 'allow-same-origin' should be same domain with the top level"); +} +</script> + +<body onLoad="doStuff()"> + I am sandboxed with 'allow-scripts allow-same-origin' and contained within a sandboxed document with 'allow-scripts allow-same-origin' +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if7.html b/dom/html/test/file_iframe_sandbox_a_if7.html new file mode 100644 index 000000000..6480eebdb --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if7.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> +function doStuff() { + // should be able to execute scripts + window.parent.parent.postMessage({ok: true, desc: "a document contained within an iframe contained within an iframe sandboxed with 'allow-scripts' should be able to execute scripts"}, "*"); +} +</script> + +<body onLoad="doStuff()"> + I am NOT sandboxed but am contained within an iframe contained within an iframe sandboxed with sandbox = "allow-scripts" +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if8.html b/dom/html/test/file_iframe_sandbox_a_if8.html new file mode 100644 index 000000000..002df5df5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if8.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script> +function doSubload() { + var if_9 = document.getElementById('if_9'); + if_9.src = 'file_iframe_sandbox_a_if9.html'; +} + +window.doSubload = doSubload; + +</script> +<body> + I am sandboxed but with "allow-scripts allow-same-origin". After my initial load, "allow-same-origin" is removed + and then I load file_iframe_sandbox_a_if9.html, which attemps to call a function in window.top. This should + succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded. + + <iframe id='if_9' src='about:blank' height="10" width="10"></iframe> +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_a_if9.html b/dom/html/test/file_iframe_sandbox_a_if9.html new file mode 100644 index 000000000..da2bcf1fa --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_a_if9.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> +function doStuff() { + window.parent.parent.ok_wrapper(true, "a subloaded document should inherit the flags of the document, not of the docshell/sandbox attribute"); +} +</script> +<body onload='doStuff()'> + I'm a subloaded document of file_iframe_sandbox_a_if8.html. I should be able to call a function in window.top + because I should be same-origin with it. +</body> +</html> + diff --git a/dom/html/test/file_iframe_sandbox_b_if1.html b/dom/html/test/file_iframe_sandbox_b_if1.html new file mode 100644 index 000000000..a65cbec6b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_b_if1.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + I am sandboxed without any permissions +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_b_if2.html b/dom/html/test/file_iframe_sandbox_b_if2.html new file mode 100644 index 000000000..08e745357 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_b_if2.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> + function ok(condition, msg) { + window.parent.ok_wrapper(condition, msg); + } + + function testXHR() { + var xhr = new XMLHttpRequest(); + + xhr.open("GET", "file_iframe_sandbox_b_if1.html"); + + xhr.onreadystatechange = function (oEvent) { + var result = false; + if (xhr.readyState == 4) { + if (xhr.status == 200) { + result = true; + } + ok(result, "XHR should work normally in an iframe sandboxed with 'allow-same-origin'"); + } + } + + xhr.send(null); + } + + function doStuff() { + ok(true, "documents sandboxed with 'allow-same-origin' should be able to access their parent"); + + // should be able to access document.cookie since we have 'allow-same-origin' + ok(document.cookie == "", "a document sandboxed with allow-same-origin should be able to access document.cookie"); + + // should be able to access localStorage since we have 'allow-same-origin' + ok(window.localStorage, "a document sandboxed with allow-same-origin should be able to access localStorage"); + + // should be able to access sessionStorage since we have 'allow-same-origin' + ok(window.sessionStorage, "a document sandboxed with allow-same-origin should be able to access sessionStorage"); + + testXHR(); + } +</script> +<body onLoad="doStuff()"> + I am sandboxed but with "allow-same-origin" and "allow-scripts" +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_b_if3.html b/dom/html/test/file_iframe_sandbox_b_if3.html new file mode 100644 index 000000000..350e2ac47 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_b_if3.html @@ -0,0 +1,92 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> + function ok(result, message) { + window.parent.postMessage({ok: result, desc: message}, "*"); + } + + function testXHR() { + // Standard URL should be blocked as we have a unique origin. + var xhr = new XMLHttpRequest(); + xhr.open("GET", "file_iframe_sandbox_b_if1.html"); + xhr.onreadystatechange = function (oEvent) { + var result = false; + if (xhr.readyState == 4) { + if (xhr.status == 0) { + result = true; + } + ok(result, "XHR should be blocked in an iframe sandboxed WITHOUT 'allow-same-origin'"); + } + } + xhr.send(null); + + // Blob URL should work as it will have our unique origin. + var blobXhr = new XMLHttpRequest(); + var blobUrl = URL.createObjectURL(new Blob(["wibble"], {type: "text/plain"})); + blobXhr.open("GET", blobUrl); + blobXhr.onreadystatechange = function () { + if (this.readyState == 4) { + ok(this.status == 200 && this.response == "wibble", "XHR for a blob URL created in this document should NOT be blocked in an iframe sandboxed WITHOUT 'allow-same-origin'"); + } + } + try { + blobXhr.send(); + } catch(e) { + ok(false, "failed to send XHR for blob URL: error: " + e); + } + + // Data URL should work as it inherits the loader's origin. + var dataXhr = new XMLHttpRequest(); + dataXhr.open("GET", "data:text/html,wibble"); + dataXhr.onreadystatechange = function () { + if (this.readyState == 4) { + ok(this.status == 200 && this.response == "wibble", "XHR for a data URL should NOT be blocked in an iframe sandboxed WITHOUT 'allow-same-origin'"); + } + } + try { + dataXhr.send(); + } catch(e) { + ok(false, "failed to send XHR for data URL: error: " + e); + } + } + + function doStuff() { + try { + window.parent.ok(false, "documents sandboxed without 'allow-same-origin' should NOT be able to access their parent"); + } catch (error) { + ok(true, "documents sandboxed without 'allow-same-origin' should NOT be able to access their parent"); + } + + // should NOT be able to access document.cookie + try { + var foo = document.cookie; + } catch(error) { + ok(true, "a document sandboxed without allow-same-origin should NOT be able to access document.cookie"); + } + + // should NOT be able to access localStorage + try { + var foo = window.localStorage; + } catch(error) { + ok(true, "a document sandboxed without allow-same-origin should NOT be able to access localStorage"); + } + + // should NOT be able to access sessionStorage + try { + var foo = window.sessionStorage; + } catch(error) { + ok(true, "a document sandboxed without allow-same-origin should NOT be able to access sessionStorage"); + } + + testXHR(); + } +</script> +<body onLoad="doStuff()"> + I am sandboxed but with "allow-scripts" +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_c_if1.html b/dom/html/test/file_iframe_sandbox_c_if1.html new file mode 100644 index 000000000..fff2f6d40 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if1.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="text/javascript"> + function ok(result, desc) { + window.parent.postMessage({ok: result, desc: desc}, "*"); + } + + function doStuff() { + ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts"); + + document.getElementById('a_form').submit(); + + // trigger the javascript: url test + sendMouseEvent({type:'click'}, 'a_link'); + } +</script> +<script src='file_iframe_sandbox_pass.js'></script> +<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'> + I am sandboxed but with "allow-scripts" + + <form method="get" action="file_iframe_sandbox_form_fail.html" id="a_form"> + First name: <input type="text" name="firstname"> + Last name: <input type="text" name="lastname"> + <input type="submit" onclick="doSubmit()" id="a_button"> + </form> + + <a href = 'javascript:ok(true, "documents sandboxed with allow-scripts should be able to run script from javascript: URLs");' id='a_link'>click me</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_c_if2.html b/dom/html/test/file_iframe_sandbox_c_if2.html new file mode 100644 index 000000000..b39231919 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if2.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +</head> +<script type="text/javascript"> + function ok(result, desc) { + window.parent.postMessage({ok: result, desc: desc}, "*"); + } + + function doStuff() { + ok(false, "documents sandboxed without allow-scripts should NOT be able to run inline scripts"); + } +</script> +<script src='file_iframe_sandbox_fail.js'></script> +<body onLoad='window.parent.postmessage({ok: false, desc: "documents sandboxed without allow-scripts should NOT be able to run script from event handlers"}, "*");doStuff();'> + I am sandboxed with no permissions + <img src="about:blank" onerror='ok(false, "documents sandboxed without allow-scripts should NOT be able to run script from event handlers");')> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_c_if3.html b/dom/html/test/file_iframe_sandbox_c_if3.html new file mode 100644 index 000000000..aca5d3356 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if3.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +</head> +<script type="text/javascript"> + function doStuff() { + dump("*** c_if3 has loaded\n"); + // try and submit the form - this should succeed + document.getElementById('a_form').submit(); + } +</script> +<body onLoad="doStuff()"> + I am sandboxed but with "allow-scripts allow-forms" + + <form method="get" action="file_iframe_sandbox_form_pass.html" id="a_form"> + First name: <input type="text" name="firstname"> + Last name: <input type="text" name="lastname"> + <input type="submit" onclick="doSubmit()" id="a_button"> + </form> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_c_if4.html b/dom/html/test/file_iframe_sandbox_c_if4.html new file mode 100644 index 000000000..53bf49559 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if4.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="text/javascript"> + function ok(result, desc) { + window.parent.ok_wrapper(result, desc); + } + + function doStuff() { + // try to open a new window via target="_blank", target="BC341604", window.open(), and showModalDialog() + // the window we try to open closes itself once it opens + sendMouseEvent({type:'click'}, 'target_blank'); + sendMouseEvent({type:'click'}, 'target_BC341604'); + + var threw = false; + try { + window.open("about:blank"); + } catch (error) { + threw = true; + } + + ok(threw, "window.open threw a JS exception and was not allowed"); + + threw = false; + try { + window.showModalDialog("about:blank"); + } catch(error) { + threw = true; + } + + ok(threw, "window.showModalDialog threw a JS exception and was not allowed"); + } +</script> +<body onLoad="doStuff()"> + I am sandboxed but with "allow-scripts allow-same-origin" + + <a href="file_iframe_sandbox_open_window_fail.html" target="_blank" id="target_blank">open window</a> + <a href="file_iframe_sandbox_open_window_fail.html" target="BC341604" id="target_BC341604">open window</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_c_if5.html b/dom/html/test/file_iframe_sandbox_c_if5.html new file mode 100644 index 000000000..267864bd8 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if5.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +</head> +<script type="text/javascript"> + function ok(result, desc) { + window.parent.ok_wrapper(result, desc); + } +</script> +<body onLoad="doStuff()"> + I am sandboxed but with "allow-same-origin" + + <a href = 'javascript:ok(false, "documents sandboxed without allow-scripts should not be able to run script with javascript: URLs");' id='a_link'>click me</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_c_if6.html b/dom/html/test/file_iframe_sandbox_c_if6.html new file mode 100644 index 000000000..3dab59771 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if6.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.ok_wrapper(result, desc);
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ ok(true, "a document sandboxed with allow-same-origin and allow-scripts should be same origin with its parent and able to run scripts " +
+ "regardless of what kind of whitespace was used in its sandbox attribute");
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-same-origin" and "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if7.html b/dom/html/test/file_iframe_sandbox_c_if7.html new file mode 100644 index 000000000..fbd55dbd4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if7.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ try {
+ var thing = indexedDB.open("sandbox");
+ ok(false, "documents sandboxed without allow-same-origin should NOT be able to access indexedDB");
+ }
+
+ catch(e) {
+ ok(true, "documents sandboxed without allow-same-origin should NOT be able to access indexedDB");
+ }
+ }
+</script>
+<body onLoad='doStuff();'>
+ I am sandboxed but with "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if8.html b/dom/html/test/file_iframe_sandbox_c_if8.html new file mode 100644 index 000000000..a03cc77de --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if8.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ var thing = indexedDB.open("sandbox");
+
+ thing.onerror = function(event) {
+ ok(false, "documents sandboxed with allow-same-origin SHOULD be able to access indexedDB");
+ };
+ thing.onsuccess = function(event) {
+ ok(true, "documents sandboxed with allow-same-origin SHOULD be able to access indexedDB");
+ };
+ }
+</script>
+<body onLoad='doStuff();'>
+ I am sandboxed but with "allow-scripts allow-same-origin"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if9.html b/dom/html/test/file_iframe_sandbox_c_if9.html new file mode 100644 index 000000000..0c88a677c --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_c_if9.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 671389</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + I am + <ul> + <li>sandboxed but with "allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", and "allow-top-navigation", </li> + <li>sandboxed but with "allow-same-origin", "allow-scripts", </li> + <li>sandboxed, or </li> + <li>not sandboxed.</li> + </ul> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_close.html b/dom/html/test/file_iframe_sandbox_close.html new file mode 100644 index 000000000..3b8753497 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_close.html @@ -0,0 +1,3 @@ +<script> + self.close(); +</script> diff --git a/dom/html/test/file_iframe_sandbox_d_if1.html b/dom/html/test/file_iframe_sandbox_d_if1.html new file mode 100644 index 000000000..054edbfe1 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if1.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +function doTest() { + sendMouseEvent({type:'click'}, 'anchor'); +} +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' + + <a href="file_iframe_sandbox_navigation_pass.html?Test 1:%20" target="_self" id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if10.html b/dom/html/test/file_iframe_sandbox_d_if10.html new file mode 100644 index 000000000..8811c8897 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if10.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +function doTest() { + window.parent.postMessage({type: "if_10"}, "*"); +} +</script> +<body onload='doTest()'> + I am sandboxed with 'allow-scripts' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if11.html b/dom/html/test/file_iframe_sandbox_d_if11.html new file mode 100644 index 000000000..b6d431c89 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if11.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +function doTest() { + // this should fail the first time, but work the second + try { + window.parent.ok_wrapper(true, "a document that was loaded, navigated to another document, had 'allow-same-origin' added and then was" + + " navigated back should be same-origin with its parent"); + } + catch (e) { + sendMouseEvent({type:'click'}, 'anchor'); + } +} + +</script> +<body onload='doTest()'> + I am sandboxed with 'allow-scripts' + <a href='file_iframe_sandbox_d_if12.html' id='anchor'>CLICK ME</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if12.html b/dom/html/test/file_iframe_sandbox_d_if12.html new file mode 100644 index 000000000..0d7936512 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if12.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> +function doTest() { + window.parent.postMessage({test:'if_11'}, "*"); +} +</script> +<body onload='doTest()'> + I am sandboxed with 'allow-scripts' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if13.html b/dom/html/test/file_iframe_sandbox_d_if13.html new file mode 100644 index 000000000..275490f87 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if13.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) { + // this message is part of if_11's test + if (event.data.test == 'if_11') { + doIf11TestPart2(); + return; + } +} + +function ok_wrapper(result, msg) { + window.opener.postMessage({ok: result, desc: msg}, "*"); + window.close(); +} + +function doIf11TestPart2() { + var if_11 = document.getElementById('if_11'); + if_11.sandbox = 'allow-scripts allow-same-origin'; + // window.history is no longer cross-origin accessible in gecko. + SpecialPowers.wrap(if_11).contentWindow.history.back(); +} +</script> +<body> + <iframe sandbox='allow-scripts' id="if_11" src="file_iframe_sandbox_d_if11.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if14.html b/dom/html/test/file_iframe_sandbox_d_if14.html new file mode 100644 index 000000000..c670b5ff6 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if14.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 838692</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + var test20Context = "Test 20: Navigate another window (not opened by us): "; + + function doTest() { + // Try to navigate auxiliary browsing context (window) not opened by us. + // We should not be able to do this as we are sandboxed. + sendMouseEvent({type:'click'}, 'navigate_window'); + window.parent.postMessage({type: "attempted"}, "*"); + + // Try to navigate auxiliary browsing context (window) not opened by us, using window.open(). + // We should not be able to do this as we are sandboxed. + try { + window.open("file_iframe_sandbox_window_navigation_fail.html?" + escape(test20Context), "window_to_navigate2"); + window.parent.postMessage({type: "attempted"}, "*"); + } catch(error) { + window.parent.postMessage({ok: true, desc: test20Context + "as expected, error thrown during window.open(..., \"window_to_navigate2\")"}, "*"); + } + } +</script> + +<body onload="doTest()"> + I am sandboxed but with "allow-scripts allow-same-origin allow-top-navigation". + + <a href="file_iframe_sandbox_window_navigation_fail.html?Test 14: Navigate another window (not opened by us):%20" target="window_to_navigate" id="navigate_window">navigate window</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if15.html b/dom/html/test/file_iframe_sandbox_d_if15.html new file mode 100644 index 000000000..6c969c8fe --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if15.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body> + I am an unsandboxed iframe. + + <iframe sandbox="allow-same-origin allow-scripts" id="if_16" src="file_iframe_sandbox_d_if16.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if16.html b/dom/html/test/file_iframe_sandbox_d_if16.html new file mode 100644 index 000000000..aba5d4b96 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if16.html @@ -0,0 +1,22 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script type="application/javascript"> +function doTest() { + window.parent.parent.postMessage({type: "attempted"}, "*"); + sendMouseEvent({type:'click'}, 'anchor'); +} +</script> + +<body onload="doTest()"> + I am sandboxed with 'allow-same-origin allow-scripts' + + <a href="file_iframe_sandbox_navigation_fail.html?Test 16: Navigate parent/ancestor by name:%20" target='if_parent' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if17.html b/dom/html/test/file_iframe_sandbox_d_if17.html new file mode 100644 index 000000000..047a08137 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if17.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="application/javascript"> + var testContext = "Test 17: navigate _self with window.open(): "; + + function doTest() { + try { + window.open("file_iframe_sandbox_navigation_pass.html?" + escape(testContext), "_self"); + } catch(error) { + window.parent.postMessage({ok: false, desc: testContext + "error thrown during window.open(..., \"_self\")"}, "*"); + } + } +</script> + +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if18.html b/dom/html/test/file_iframe_sandbox_d_if18.html new file mode 100644 index 000000000..03aa0aa9b --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if18.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script type="application/javascript"> + window.addEventListener("message", receiveMessage, false); + + function receiveMessage(event) { + window.parent.postMessage(event.data, "*"); + } + + var testContext = "Test 18: navigate child with window.open(): "; + + function doTest() { + try { + window.open("file_iframe_sandbox_navigation_pass.html?" + escape(testContext), "foo"); + } catch(error) { + window.parent.postMessage({ok: false, desc: testContext + " error thrown during window.open(..., \"foo\")"}, "*"); + } + } +</script> + +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' + + <iframe name="foo" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if19.html b/dom/html/test/file_iframe_sandbox_d_if19.html new file mode 100644 index 000000000..d766d2649 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if19.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + I am sandboxed with 'allow-scripts' + + <iframe sandbox="allow-scripts" id="if_20" src="file_iframe_sandbox_d_if20.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if2.html b/dom/html/test/file_iframe_sandbox_d_if2.html new file mode 100644 index 000000000..763585c62 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if2.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +// needed to forward the message to the main test page +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) { + window.parent.postMessage(event.data, "*"); +} + +function doTest() { + sendMouseEvent({type:'click'}, 'anchor'); +} +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' + + <iframe name="foo" src="file_iframe_sandbox_navigation_start.html" height="10" width="10"></iframe> + + <a href="file_iframe_sandbox_navigation_pass.html?Test 2:%20" target='foo' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if20.html b/dom/html/test/file_iframe_sandbox_d_if20.html new file mode 100644 index 000000000..005c4bc82 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if20.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="application/javascript"> + var testContext = "Test 19: navigate _parent with window.open(): "; + + function doTest() { + try { + window.open("file_iframe_sandbox_navigation_fail.html?" + escape(testContext), "_parent"); + window.parent.parent.postMessage({type: "attempted"}, "*"); + } catch(error) { + window.parent.parent.postMessage({ok: true, desc: testContext + "as expected, error thrown during window.open(..., \"_parent\")"}, "*"); + } + } +</script> + +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if21.html b/dom/html/test/file_iframe_sandbox_d_if21.html new file mode 100644 index 000000000..6d0ab232e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if21.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body> + I am an unsandboxed iframe. + + <iframe sandbox="allow-same-origin allow-scripts" id="if_22" src="file_iframe_sandbox_d_if22.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if22.html b/dom/html/test/file_iframe_sandbox_d_if22.html new file mode 100644 index 000000000..bd2715792 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if22.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="application/javascript"> + var testContext = "Test 21: navigate parent by name with window.open(): "; + + function doTest() { + try { + window.open("file_iframe_sandbox_navigation_fail.html?" + escape(testContext), "if_parent2"); + window.parent.parent.postMessage({type: "attempted"}, "*"); + } catch(error) { + window.parent.parent.postMessage({ok: true, desc: testContext + "as expected, error thrown during window.open(..., \"if_parent2\")"}, "*"); + } + } +</script> + +<body onload="doTest()"> + I am sandboxed with 'allow-same-origin allow-scripts' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if23.html b/dom/html/test/file_iframe_sandbox_d_if23.html new file mode 100644 index 000000000..04688b3d9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if23.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="application/javascript"> + var test27Context = "Test 27: navigate opened window by name with anchor: "; + var test28Context = "Test 28: navigate opened window by name with window.open(): "; + + var windowsToClose = new Array(); + + function closeWindows() { + for (var i = 0; i < windowsToClose.length; i++) { + windowsToClose[i].close(); + } + } + + // Add message listener to forward messages on to parent + window.addEventListener("message", receiveMessage, false); + + function receiveMessage(event) { + switch (event.data.type) { + case "closeWindows": + closeWindows(); + break; + default: + window.parent.postMessage(event.data, "*"); + } + } + + function doTest() { + try { + windowsToClose.push(window.open("about:blank", "test27window")); + var test27Anchor = document.getElementById("test27Anchor"); + test27Anchor.href = "file_iframe_sandbox_window_navigation_pass.html?" + escape(test27Context); + sendMouseEvent({type:"click"}, "test27Anchor"); + window.parent.postMessage({type: "attempted"}, "*"); + } catch(error) { + window.parent.postMessage({ok: false, desc: test27Context + "error thrown during window.open(): " + error}, "*"); + } + + try { + windowsToClose.push(window.open("about:blank", "test28window")); + window.open("file_iframe_sandbox_window_navigation_pass.html?" + escape(test28Context), "test28window"); + window.parent.postMessage({type: "attempted"}, "*"); + } catch(error) { + window.parent.postMessage({ok: false, desc: test28Context + "error thrown during window.open(): " + error}, "*"); + } + } +</script> + +<body onload="doTest()"> + I am sandboxed with 'allow-scripts allow-popups' + + <a id="test27Anchor" target="test27window">Test 27 anchor</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if3.html b/dom/html/test/file_iframe_sandbox_d_if3.html new file mode 100644 index 000000000..cd2d53bce --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if3.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + I am sandboxed with 'allow-scripts' + + <iframe sandbox="allow-scripts" id="if_4" src="file_iframe_sandbox_d_if4.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if4.html b/dom/html/test/file_iframe_sandbox_d_if4.html new file mode 100644 index 000000000..64e173a64 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if4.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +function doTest() { + window.parent.parent.postMessage({type: "attempted"}, "*"); + sendMouseEvent({type:'click'}, 'anchor'); +} +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' + + <a href="file_iframe_sandbox_navigation_fail.html" target='_parent' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if5.html b/dom/html/test/file_iframe_sandbox_d_if5.html new file mode 100644 index 000000000..ba31053ad --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if5.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +function doTest() { + window.parent.postMessage({type: "attempted"}, "*"); + sendMouseEvent({type:'click'}, 'anchor'); +} +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts allow-same-origin' + + <a href="file_iframe_sandbox_navigation_fail.html?Test 4: Navigate sibling iframe by name:%20" target='if_sibling' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if6.html b/dom/html/test/file_iframe_sandbox_d_if6.html new file mode 100644 index 000000000..e7e19fc2e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if6.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +function doTest() { + sendMouseEvent({type:'click'}, 'anchor'); +} +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' + + <a href="file_iframe_sandbox_d_if7.html" target='_self' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if7.html b/dom/html/test/file_iframe_sandbox_d_if7.html new file mode 100644 index 000000000..5023ee029 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if7.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> +function doTest() { + try { + window.parent.ok_wrapper(false, "a sandboxed document when navigated should still NOT be same-origin with its parent"); + } catch(error) { + window.parent.postMessage({ok: true, desc: "sandboxed document's attempt to access parent after navigation blocked, as not same-origin."}, "*"); + } +} +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if8.html b/dom/html/test/file_iframe_sandbox_d_if8.html new file mode 100644 index 000000000..2b4398ef0 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if8.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="application/javascript"> + function doTest() { + window.parent.modify_if_8(); + } +</script> + +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' and 'allow-same-origin' the first time I am loaded, and with 'allow-scripts' the second time +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_d_if9.html b/dom/html/test/file_iframe_sandbox_d_if9.html new file mode 100644 index 000000000..ee641904f --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_d_if9.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+function doTest() {
+ window.parent.modify_if_9();
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts' and 'allow-same-origin' the first time I am loaded, and with 'allow-same-origin' the second time
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_e_if1.html b/dom/html/test/file_iframe_sandbox_e_if1.html new file mode 100644 index 000000000..69f827ce4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if1.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> + +<script> + function doTest() { + var testContext = location.search == "" ? "?Test 10: Navigate _top:%20" : location.search; + document.getElementById("if_6").src = "file_iframe_sandbox_e_if6.html" + testContext; + } +</script> + +<body onload="doTest()"> + <iframe sandbox='allow-scripts' id='if_6' height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if10.html b/dom/html/test/file_iframe_sandbox_e_if10.html new file mode 100644 index 000000000..2484b8f34 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if10.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doTest() { + var testContext = "?Test 23: Nested navigate _top with window.open():%20"; + document.getElementById("if_9").src = "file_iframe_sandbox_e_if9.html" + testContext; + } +</script> + +<body onload="doTest()"> + <iframe sandbox='allow-scripts allow-top-navigation' id='if_9' height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if11.html b/dom/html/test/file_iframe_sandbox_e_if11.html new file mode 100644 index 000000000..42c28021a --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if11.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> + function doTest() { + var testContext = location.search.substring(1); + try { + var topsOpener = window.top.opener; + window.open("file_iframe_sandbox_top_navigation_pass.html?" + testContext, "_top"); + topsOpener.postMessage({ok: true, desc: unescape(testContext) + "top navigation should be allowed by a document sandboxed with 'allow-top-navigation.'"}, "*"); + } catch(error) { + window.top.opener.postMessage({ok: false, desc: unescape(testContext) + "error thrown during window.open(..., \"_top\")"}, "*"); + window.top.close(); + } + } +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts and allow-top-navigation' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if12.html b/dom/html/test/file_iframe_sandbox_e_if12.html new file mode 100644 index 000000000..0b1b87e09 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if12.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doTest() { + var testContext = location.search == "" ? "?Test 24: Navigate _top with window.open():%20" : location.search; + document.getElementById("if_14").src = "file_iframe_sandbox_e_if14.html" + testContext; + } +</script> + +<body onload="doTest()"> + <iframe sandbox='allow-scripts' id='if_14' height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if13.html b/dom/html/test/file_iframe_sandbox_e_if13.html new file mode 100644 index 000000000..f5cf912f6 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if13.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doTest() { + var testContext = "?Test 25: Nested navigate _top with window.open():%20"; + document.getElementById("if_12").src = "file_iframe_sandbox_e_if12.html" + testContext; + } +</script> + +<body onload="doTest()"> + <iframe sandbox='allow-scripts allow-top-navigation' id='if_12' height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if14.html b/dom/html/test/file_iframe_sandbox_e_if14.html new file mode 100644 index 000000000..76d978702 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if14.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> + function doTest() { + var testContext = location.search.substring(1); + try { + var topsOpener = window.top.opener; + window.open("file_iframe_sandbox_top_navigation_fail.html?" + testContext, "_top"); + topsOpener.postMessage({ok: false, desc: unescape(testContext) + "top navigation should NOT be allowed by a document sandboxed without 'allow-top-navigation.'"}, "*"); + } catch(error) { + window.top.opener.postMessage({ok: true, desc: unescape(testContext) + "as expected error thrown during window.open(..., \"_top\")"}, "*"); + window.top.close(); + } + } +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if15.html b/dom/html/test/file_iframe_sandbox_e_if15.html new file mode 100644 index 000000000..bf4138e1d --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if15.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + // Set our name, to allow an attempt to navigate us by name. + window.name = "e_if15"; +</script> + +<body> + <iframe sandbox='allow-scripts' id='if_16' src="file_iframe_sandbox_e_if16.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if16.html b/dom/html/test/file_iframe_sandbox_e_if16.html new file mode 100644 index 000000000..06c8bf871 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if16.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + var testContext = "Test 26: navigate top by name with window.open(): "; + + function doTest() { + try { + var topsOpener = window.top.opener; + window.open("file_iframe_sandbox_top_navigation_fail.html?" + escape(testContext), "e_if15"); + topsOpener.postMessage({ok: false, desc: unescape(testContext) + "top navigation should NOT be allowed by a document sandboxed without 'allow-top-navigation.'"}, "*"); + } catch(error) { + window.top.opener.postMessage({ok: true, desc: testContext + "as expected, error thrown during window.open(..., \"e_if15\")"}, "*"); + window.top.close(); + } + } +</script> + +<body onload="doTest()"> + I am sandboxed but with "allow-scripts" +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if2.html b/dom/html/test/file_iframe_sandbox_e_if2.html new file mode 100644 index 000000000..47251d6dc --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if2.html @@ -0,0 +1,12 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> + <iframe sandbox='allow-scripts allow-top-navigation allow-same-origin' id='if_1' src="file_iframe_sandbox_e_if1.html?Test 11: Nested navigate _top:%20" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if3.html b/dom/html/test/file_iframe_sandbox_e_if3.html new file mode 100644 index 000000000..ce010e689 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if3.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <iframe sandbox='allow-scripts allow-top-navigation' id='if_5' src="file_iframe_sandbox_e_if5.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if4.html b/dom/html/test/file_iframe_sandbox_e_if4.html new file mode 100644 index 000000000..740a33a94 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if4.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <iframe sandbox='allow-scripts allow-top-navigation' id='if_3' src="file_iframe_sandbox_e_if3.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if5.html b/dom/html/test/file_iframe_sandbox_e_if5.html new file mode 100644 index 000000000..46bfff357 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if5.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts and allow-top-navigation'
+
+ <a href="file_iframe_sandbox_top_navigation_pass.html" target='_top' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if6.html b/dom/html/test/file_iframe_sandbox_e_if6.html new file mode 100644 index 000000000..b1266416c --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if6.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> +function doTest() { + document.getElementById('anchor').href = "file_iframe_sandbox_top_navigation_fail.html" + location.search; + window.top.opener.postMessage({type: "attempted"}, "*"); + sendMouseEvent({type:'click'}, 'anchor'); +} +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts' + + <a target='_top' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if7.html b/dom/html/test/file_iframe_sandbox_e_if7.html new file mode 100644 index 000000000..9d60ed2db --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if7.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + // Set our name, to allow an attempt to navigate us by name. + window.name = "e_if7"; +</script> + +<body> + <iframe sandbox='allow-scripts' id='if_8' src="file_iframe_sandbox_e_if8.html" height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if8.html b/dom/html/test/file_iframe_sandbox_e_if8.html new file mode 100644 index 000000000..324ccf90c --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if8.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script> + function doTest() { + // Try to navigate top using its name (e_if7). We should not be able to do this as allow-top-navigation is not specified. + window.top.opener.postMessage({type: "attempted"}, "*"); + sendMouseEvent({type:'click'}, 'navigate_top'); + } +</script> + +<body onload="doTest()"> + I am sandboxed but with "allow-scripts" + + <a href="file_iframe_sandbox_top_navigation_fail.html?Test 15: Navigate top by name:%20" target="e_if7" id="navigate_top">navigate top</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_e_if9.html b/dom/html/test/file_iframe_sandbox_e_if9.html new file mode 100644 index 000000000..f18a16dba --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_e_if9.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doTest() { + var testContext = location.search == "" ? "?Test 22: Navigate _top with window.open():%20" : location.search; + document.getElementById("if_11").src = "file_iframe_sandbox_e_if11.html" + testContext; + } +</script> + +<body onload="doTest()"> + <iframe sandbox='allow-scripts allow-top-navigation' id='if_11' height="10" width="10"></iframe> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_f_if1.html b/dom/html/test/file_iframe_sandbox_f_if1.html new file mode 100644 index 000000000..294bf0797 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_f_if1.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+I have 2 plugin instances embedded in me.
+<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+<object type="application/x-test" width="200" height="200"></object>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_f_if2.html b/dom/html/test/file_iframe_sandbox_f_if2.html new file mode 100644 index 000000000..7b3010d53 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_f_if2.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ I am a document that should be handled by a plugin load.
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_f_if2.html^headers^ b/dom/html/test/file_iframe_sandbox_f_if2.html^headers^ new file mode 100644 index 000000000..9af65b111 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_f_if2.html^headers^ @@ -0,0 +1 @@ +Content-Type: application/x-test
diff --git a/dom/html/test/file_iframe_sandbox_fail.js b/dom/html/test/file_iframe_sandbox_fail.js new file mode 100644 index 000000000..63397c7de --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_fail.js @@ -0,0 +1 @@ +ok(false, "documents sandboxed with allow-scripts should NOT be able to run <script src=...>");
\ No newline at end of file diff --git a/dom/html/test/file_iframe_sandbox_form_fail.html b/dom/html/test/file_iframe_sandbox_form_fail.html new file mode 100644 index 000000000..6254f87c7 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_form_fail.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body onLoad="doStuff()"> + I should NOT be loaded by a form submit from a sandbox without 'allow-forms' +</body> +</html> + +<script> + function doStuff() { + window.parent.postMessage({ok: false, desc: "documents sandboxed without allow-forms should NOT be able to submit forms"}, "*"); + } +</script>
\ No newline at end of file diff --git a/dom/html/test/file_iframe_sandbox_form_pass.html b/dom/html/test/file_iframe_sandbox_form_pass.html new file mode 100644 index 000000000..1ba8853fa --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_form_pass.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> +</head> + +<body onLoad="doStuff()"> + I should be loaded by a form submit from a sandbox with 'allow-forms' +</body> +</html> + +<script> + function doStuff() { + window.parent.postMessage({ok: true, desc: "documents sandboxed with allow-forms should be able to submit forms"}, "*"); + } +</script>
\ No newline at end of file diff --git a/dom/html/test/file_iframe_sandbox_g_if1.html b/dom/html/test/file_iframe_sandbox_g_if1.html new file mode 100644 index 000000000..9a985faf9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_g_if1.html @@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="text/javascript"> + function ok(result, desc) { + window.parent.postMessage({ok: result, desc: desc}, "*"); + } + + function doStuff() { + // test data URI + + // self.onmessage = function(event) { + // self.postMessage('make it so'); + // }; + var data_url = "data:text/plain;charset=utf-8;base64,c2VsZi5vbm1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkgeyAgDQogICAgc2VsZi5wb3N0TWVzc2FnZSgnbWFrZSBpdCBzbycpOyAgDQp9Ow=="; + var worker_data = new Worker(data_url); + worker_data.addEventListener('message', function(event) { + ok(true, "a worker in a sandboxed document should be able to be loaded from a data: URI"); + }, false); + + worker_data.postMessage("engage!"); + + // test a blob URI we created (will have the same null principal + // as us + var b = new Blob(["onmessage = function(event) { self.postMessage('make it so');};"]); + + var blobURL = URL.createObjectURL(b); + + var worker_blob = new Worker(blobURL); + + worker_blob.addEventListener('message', function(event) { + ok(true, "a worker in a sandboxed document should be able to be loaded from a blob URI " + + "created by that sandboxed document"); + }, false); + + worker_blob.postMessage("engage!"); + + // test loading with relative url - this should fail since we are + // sandboxed and have a null principal + var worker_js = new Worker('file_iframe_sandbox_worker.js'); + worker_js.onerror = function(error) { + ok(true, "a worker in a sandboxed document should tell the load error via error event"); + } + + worker_js.addEventListener('message', function(event) { + ok(false, "a worker in a sandboxed document should not be able to load from a relative URI"); + }, false); + + worker_js.postMessage('engage'); + } +</script> +<body onload='doStuff();'> + I am sandboxed but with "allow-scripts" +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_h_if1.html b/dom/html/test/file_iframe_sandbox_h_if1.html new file mode 100644 index 000000000..3cb6781f1 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_h_if1.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 766282</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +</head> +<script type="text/javascript"> + function ok(result, desc) { + window.parent.ok_wrapper(result, desc); + } + + function doStuff() { + // Try to open a new window via target="_blank", target="BC766282" and window.open(). + // The window we try to open closes itself once it opens. + sendMouseEvent({type:'click'}, 'target_blank'); + sendMouseEvent({type:'click'}, 'target_BC766282'); + + try { + window.open("file_iframe_sandbox_open_window_pass.html"); + } catch(e) { + ok(false, "Test 3: iframes sandboxed with allow-popups, should be able to open windows"); + } + } +</script> +<body onLoad="doStuff()"> + I am sandboxed but with "allow-popups allow-scripts allow-same-origin" + + <a href="file_iframe_sandbox_open_window_pass.html" target="_blank" id="target_blank">open window</a> + <a href="file_iframe_sandbox_open_window_pass.html?BC766282" target="BC766282" id="target_BC766282">open window</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_j_if1.html b/dom/html/test/file_iframe_sandbox_j_if1.html new file mode 100644 index 000000000..6d4347dfc --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_j_if1.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + function doStuff() { + // Open a new window via showModalDialog(). + try { + window.showModalDialog("file_iframe_sandbox_k_if5.html"); + } catch(e) { + window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog"); + } + + // Open a new window via showModalDialog(). + try { + window.showModalDialog("file_iframe_sandbox_k_if7.html"); + } catch(e) { + window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog"); + } + } +</script> + +<body onLoad="doStuff()"> + I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation". +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_j_if2.html b/dom/html/test/file_iframe_sandbox_j_if2.html new file mode 100644 index 000000000..9552307ee --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_j_if2.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + function doSubOpens() { + // Open a new window showModalDialog(). + try { + window.showModalDialog("file_iframe_sandbox_k_if9.html"); + } catch(e) { + window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog"); + } + } + + window.doSubOpens = doSubOpens; +</script> + +<body> + I am sandboxed but with "allow-scripts allow-popups allow-same-origin". + After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html, + which attemps to call a function in my parent. + This should succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded. +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_j_if3.html b/dom/html/test/file_iframe_sandbox_j_if3.html new file mode 100644 index 000000000..07c5b66c1 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_j_if3.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +</head> +<script type="text/javascript"> + function ok(result, desc) { + window.parent.ok_wrapper(result, desc); + } + + function doStuff() { + // Try to open a new window via showModalDialog(). + // The window we try to open closes itself once it opens. + try { + window.showModalDialog("file_iframe_sandbox_open_window_pass.html"); + } catch(e) { + ok(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog"); + } + } +</script> +<body onLoad="doStuff()"> + I am sandboxed but with "allow-popups allow-scripts allow-same-origin" +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if1.html b/dom/html/test/file_iframe_sandbox_k_if1.html new file mode 100644 index 000000000..cb0719556 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if1.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="text/javascript"> + var windowsToClose = new Array(); + + function closeWindows() { + for (var i = 0; i < windowsToClose.length; i++) { + windowsToClose[i].close(); + } + window.open("file_iframe_sandbox_close.html", "blank_if2"); + window.open("file_iframe_sandbox_close.html", "BC766282_if2"); + } + + // Add message listener to forward messages on to parent + window.addEventListener("message", receiveMessage, false); + + function receiveMessage(event) { + switch (event.data.type) { + case "closeWindows": + closeWindows(); + break; + } + } + + function doStuff() { + // Open a new window via target="_blank", target="BC766282_if2" and window.open(). + sendMouseEvent({type:'click'}, 'target_blank_if2'); + sendMouseEvent({type:'click'}, 'target_BC766282_if2'); + + windowsToClose.push(window.open("file_iframe_sandbox_k_if2.html")); + } +</script> +<body onLoad="doStuff()"> + I am navigated to from file_iframe_sandbox_k_if8.html. + This was opened in an iframe with "allow-scripts allow-popups allow-same-origin". + However allow-same-origin was removed from the iframe before navigating to me, + so I should only have "allow-scripts allow-popups" in force. + <a href="file_iframe_sandbox_k_if2.html" target="_blank" id="target_blank_if2">open window</a> + <a href="file_iframe_sandbox_k_if2.html" target="BC766282_if2" id="target_BC766282_if2">open window</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if2.html b/dom/html/test/file_iframe_sandbox_k_if2.html new file mode 100644 index 000000000..dce42aef5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if2.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + if (window.name == "") { + window.name = "blank_if2"; + } + + function ok(result, message) { + window.opener.parent.postMessage({type: "ok", ok: result, desc: message}, "*"); + } + + function doStuff() { + // Check that sandboxed forms browsing context flag copied by attempting to submit a form. + document.getElementById('a_form').submit(); + window.opener.parent.postMessage({type: "attempted"}, "*"); + + // Check that sandboxed origin browsing context flag copied by attempting to access cookies. + try { + var foo = document.cookie; + ok(false, "Sandboxed origin browsing context flag NOT copied to new auxiliary browsing context."); + } catch(error) { + ok(true, "Sandboxed origin browsing context flag copied to new auxiliary browsing context."); + } + + // Check that sandboxed top-level navigation browsing context flag copied. + // if_3 tries to navigate this document. + var if_3 = document.getElementById('if_3'); + if_3.src = "file_iframe_sandbox_k_if3.html"; + } +</script> + +<body onLoad="doStuff()"> + I am not sandboxed directly, but opened from a sandboxed document with 'allow-scripts allow-popups' + + <form method="get" action="file_iframe_sandbox_window_form_fail.html" id="a_form"> + First name: <input type="text" name="firstname"> + Last name: <input type="text" name="lastname"> + <input type="submit" id="a_button"> + </form> + + <iframe id="if_3" src="about:blank" height="10" width="10"></iframe> + +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if3.html b/dom/html/test/file_iframe_sandbox_k_if3.html new file mode 100644 index 000000000..b6a005aa5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if3.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> +<script type="application/javascript"> + function doTest() { + sendMouseEvent({type:'click'}, 'anchor'); + window.parent.opener.parent.postMessage({type: "attempted"}, "*"); + } +</script> +<body onload="doTest()"> + I am sandboxed with 'allow-scripts allow-popups' + + <a href="file_iframe_sandbox_window_top_navigation_fail.html" target='_top' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if4.html b/dom/html/test/file_iframe_sandbox_k_if4.html new file mode 100644 index 000000000..b9b4427ed --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if4.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + function doStuff() { + // Open a new window via target="_blank", target="BC766282_if5" and window.open(). + sendMouseEvent({type:'click'}, 'target_blank_if5'); + sendMouseEvent({type:'click'}, 'target_BC766282_if5'); + + window.open("file_iframe_sandbox_k_if5.html"); + + // Open a new window via target="_blank", target="BC766282_if7" and window.open(). + sendMouseEvent({type:'click'}, 'target_blank_if7'); + sendMouseEvent({type:'click'}, 'target_BC766282_if7'); + + window.open("file_iframe_sandbox_k_if7.html"); + } +</script> + +<body onLoad="doStuff()"> + I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation". + <a href="file_iframe_sandbox_k_if5.html" target="_blank" id="target_blank_if5">open window</a> + <a href="file_iframe_sandbox_k_if5.html" target="BC766282_if5" id="target_BC766282_if5">open window</a> + + <a href="file_iframe_sandbox_k_if7.html" target="_blank" id="target_blank_if7">open window</a> + <a href="file_iframe_sandbox_k_if7.html" target="BC766282_if7" id="target_BC766282_if7">open window</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if5.html b/dom/html/test/file_iframe_sandbox_k_if5.html new file mode 100644 index 000000000..8deb65852 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if5.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + function doStuff() { + // Check that sandboxed origin browsing context flag NOT set by attempting to access cookies. + try { + var foo = document.cookie; + window.opener.parent.ok_wrapper(true, "Sandboxed origin browsing context flag NOT set on new auxiliary browsing context."); + } catch(error) { + window.opener.parent.ok_wrapper(false, "Sandboxed origin browsing context flag set on new auxiliary browsing context."); + } + + // Check that sandboxed top-level navigation browsing context flag NOT set. + // if_6 tries to navigate this document. + var if_6 = document.getElementById('if_6'); + if_6.src = "file_iframe_sandbox_k_if6.html"; + } +</script> + +<body onLoad="doStuff()"> + I am not sandboxed directly, but opened from a sandboxed document with at least + 'allow-scripts allow-popups allow-same-origin allow-top-navigation' + + <iframe id="if_6" src="about:blank" height="10" width="10"></iframe> + +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if6.html b/dom/html/test/file_iframe_sandbox_k_if6.html new file mode 100644 index 000000000..22dec5c1c --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if6.html @@ -0,0 +1,21 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +</head> + +<script type="application/javascript"> + function doTest() { + sendMouseEvent({type:'click'}, 'anchor'); + } +</script> + +<body onload="doTest()"> + I am sandboxed with at least 'allow-scripts allow-popups allow-top-navigation' + + <a href="file_iframe_sandbox_window_top_navigation_pass.html" target='_top' id='anchor'> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if7.html b/dom/html/test/file_iframe_sandbox_k_if7.html new file mode 100644 index 000000000..269e31eb5 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if7.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + function doStuff() { + // Check that sandboxed forms browsing context flag NOT set by attempting to submit a form. + document.getElementById('a_form').submit(); + } +</script> + +<body onLoad="doStuff()"> + I am not sandboxed directly, but opened from a sandboxed document with at least + 'allow-scripts allow-popups allow-forms allow-same-origin' + + <form method="get" action="file_iframe_sandbox_window_form_pass.html" id="a_form"> + First name: <input type="text" name="firstname"> + Last name: <input type="text" name="lastname"> + <input type="submit" id="a_button"> + </form> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if8.html b/dom/html/test/file_iframe_sandbox_k_if8.html new file mode 100644 index 000000000..6f425c428 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if8.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="text/javascript"> + function doSubOpens() { + // Open a new window via target="_blank", target="BC766282_if9" and window.open(). + sendMouseEvent({type:'click'}, 'target_blank_if9'); + sendMouseEvent({type:'click'}, 'target_BC766282_if9'); + + window.open("file_iframe_sandbox_k_if9.html"); + + sendMouseEvent({type:'click'}, 'target_if1'); + } + + window.doSubOpens = doSubOpens; +</script> + +<body> + I am sandboxed but with "allow-scripts allow-popups allow-same-origin". + After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html + in 3 different ways, which attemps to call a function in my parent. + This should succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded. + <a href="file_iframe_sandbox_k_if9.html" target="_blank" id="target_blank_if9">open window</a> + <a href="file_iframe_sandbox_k_if9.html" target="BC766282_if9" id="target_BC766282_if9">open window</a> + + Now navigate to file_iframe_sandbox_k_if1.html to do tests for a sandbox opening a window + when only "allow-scripts allow-popups" are specified. + <a href="file_iframe_sandbox_k_if1.html" id="target_if1">navigate to if1</a> +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_k_if9.html b/dom/html/test/file_iframe_sandbox_k_if9.html new file mode 100644 index 000000000..56e8db3f9 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_k_if9.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doStuff() { + window.opener.parent.ok_wrapper(true, "A window opened from within a sandboxed document should inherit the flags of the document, not of the docshell/sandbox attribute."); + self.close(); + } +</script> + +<body onload='doStuff()'> + I'm a window opened from the sandboxed document of file_iframe_sandbox_k_if8.html. + I should be able to call ok_wrapper in main test page directly because I should be same-origin with it. +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_navigation_fail.html b/dom/html/test/file_iframe_sandbox_navigation_fail.html new file mode 100644 index 000000000..bae5276bd --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_navigation_fail.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body onLoad="doStuff()"> +FAIL +</body> +<script> + function doStuff() { + var testContext = unescape(location.search.substring(1)); + window.parent.postMessage({ok: false, desc: testContext + "this navigation should NOT be allowed by a sandboxed document", addToAttempted: false}, "*"); + } +</script> +</html> diff --git a/dom/html/test/file_iframe_sandbox_navigation_pass.html b/dom/html/test/file_iframe_sandbox_navigation_pass.html new file mode 100644 index 000000000..e07248247 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_navigation_pass.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> +function doStuff() { + var testContext = unescape(location.search.substring(1)); + window.parent.postMessage({ok: true, desc: testContext + "this navigation should be allowed by a sandboxed document"}, "*"); +} +</script> +<body onLoad="doStuff()"> +PASS +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_navigation_start.html b/dom/html/test/file_iframe_sandbox_navigation_start.html new file mode 100644 index 000000000..fa5642517 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_navigation_start.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+I am just a normal HTML document, probably contained in a sandboxed iframe
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_open_window_fail.html b/dom/html/test/file_iframe_sandbox_open_window_fail.html new file mode 100644 index 000000000..64e0d3618 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_open_window_fail.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body onLoad="doStuff()"> + I should NOT be opened by a sandboxed iframe via any method +</body> +</html> + +<script> + function doStuff() { + window.opener.ok(false, "sandboxed documents should NOT be able to open windows"); + self.close(); + } +</script> diff --git a/dom/html/test/file_iframe_sandbox_open_window_pass.html b/dom/html/test/file_iframe_sandbox_open_window_pass.html new file mode 100644 index 000000000..ac45c7fd3 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_open_window_pass.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body onLoad="doStuff()"> + I should be opened by a sandboxed iframe via any method when "allow-popups" is specified. +</body> +</html> + +<script> + function doStuff() { + // Check that the browsing context's (window's) name is as expected. + var expectedName = location.search.substring(1); + if (expectedName == window.name) { + window.opener.ok(true, "sandboxed documents should be able to open windows when \"allow-popups\" is specified"); + } else { + window.opener.ok(false, "window opened with \"allow-popups\", but expected name was " + expectedName + " and actual was " + window.name); + } + self.close(); + } +</script> diff --git a/dom/html/test/file_iframe_sandbox_pass.js b/dom/html/test/file_iframe_sandbox_pass.js new file mode 100644 index 000000000..bd633056f --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_pass.js @@ -0,0 +1 @@ +ok(true, "documents sandboxed with allow-scripts should be able to run <script src=...>");
\ No newline at end of file diff --git a/dom/html/test/file_iframe_sandbox_redirect.html b/dom/html/test/file_iframe_sandbox_redirect.html new file mode 100644 index 000000000..62419d7f4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_redirect.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<body>redirect</body> diff --git a/dom/html/test/file_iframe_sandbox_redirect.html^headers^ b/dom/html/test/file_iframe_sandbox_redirect.html^headers^ new file mode 100644 index 000000000..71b739c42 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_redirect.html^headers^ @@ -0,0 +1,2 @@ +HTTP 301 Moved Permanently +Location: file_iframe_sandbox_redirect_target.html diff --git a/dom/html/test/file_iframe_sandbox_redirect_target.html b/dom/html/test/file_iframe_sandbox_redirect_target.html new file mode 100644 index 000000000..c134ac0ff --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_redirect_target.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<head> + <script> + onmessage = function(event) { + parent.postMessage(event.data + " redirect target", "*"); + } + </script> +</head> +<body>I have been redirected</body> diff --git a/dom/html/test/file_iframe_sandbox_refresh.html b/dom/html/test/file_iframe_sandbox_refresh.html new file mode 100644 index 000000000..1fad80c42 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_refresh.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<body>refresh</body> diff --git a/dom/html/test/file_iframe_sandbox_refresh.html^headers^ b/dom/html/test/file_iframe_sandbox_refresh.html^headers^ new file mode 100644 index 000000000..a7cc383b4 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_refresh.html^headers^ @@ -0,0 +1 @@ +Refresh: 0 url=data:text/html,Refreshed diff --git a/dom/html/test/file_iframe_sandbox_top_navigation_fail.html b/dom/html/test/file_iframe_sandbox_top_navigation_fail.html new file mode 100644 index 000000000..dad6b2c00 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_top_navigation_fail.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> +function doStuff() { + var testContext = unescape(location.search.substring(1)); + window.opener.postMessage({ok: false, desc: testContext + "top navigation should NOT be allowed by a document sandboxed without 'allow-top-navigation'", addToAttempted: false}, "*"); + window.close(); +} +</script> +<body onLoad="doStuff()"> +FAIL\ +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_top_navigation_pass.html b/dom/html/test/file_iframe_sandbox_top_navigation_pass.html new file mode 100644 index 000000000..fe016ab23 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_top_navigation_pass.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> +function doStuff() { + var testContext = unescape(location.search.substring(1)); + window.opener.postMessage({ok: true, desc: testContext + "top navigation should be allowed by a document sandboxed with 'allow-top-navigation'"}, "*"); + window.close(); +} +</script> +<body onLoad="doStuff()"> +PASS +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_window_form_fail.html b/dom/html/test/file_iframe_sandbox_window_form_fail.html new file mode 100644 index 000000000..2d678b3ac --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_form_fail.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body onLoad="doStuff()"> + I should NOT be loaded by a form submit from a window opened from a sandbox without 'allow-forms'. +</body> +</html> + +<script> + function doStuff() { + window.opener.parent.postMessage({ok: false, desc: "documents sandboxed without allow-forms should NOT be able to submit forms"}, "*"); + + self.close(); + } +</script> diff --git a/dom/html/test/file_iframe_sandbox_window_form_pass.html b/dom/html/test/file_iframe_sandbox_window_form_pass.html new file mode 100644 index 000000000..dd2656c1e --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_form_pass.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doStuff() { + window.opener.parent.ok_wrapper(true, "Sandboxed forms browsing context flag NOT set on new auxiliary browsing context."); + + self.close(); + } +</script> + +<body onLoad="doStuff()"> + I should be loaded by a form submit from a window opened from a sandbox with 'allow-forms allow-same-origin'. +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_window_navigation_fail.html b/dom/html/test/file_iframe_sandbox_window_navigation_fail.html new file mode 100644 index 000000000..f8e3c83ce --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_navigation_fail.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 838692</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> +function doStuff() { + var testContext = unescape(location.search.substring(1)); + window.opener.postMessage({ok: false, desc: testContext + "a sandboxed document should not be able to navigate a window it hasn't opened.", addToAttempted: false}, "*"); + window.close(); +} +</script> + +<body onLoad="doStuff()"> +FAIL +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_window_navigation_pass.html b/dom/html/test/file_iframe_sandbox_window_navigation_pass.html new file mode 100644 index 000000000..a1bff9eb8 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_navigation_pass.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> +function doStuff() { + var testContext = unescape(location.search.substring(1)); + window.opener.postMessage({type: "ok", ok: true, desc: testContext + "a permitted sandboxed document should be able to navigate a window it has opened.", addToAttempted: false}, "*"); + window.close(); +} +</script> + +<body onLoad="doStuff()"> +PASS +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html b/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html new file mode 100644 index 000000000..af5047604 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script> + function doStuff() { + window.opener.parent.postMessage({ok: false, desc: "Sandboxed top-level navigation browsing context flag NOT copied to new auxiliary browsing context."}, "*"); + + // Check that when no browsing context returned by "target='_top'", a new browsing context isn't opened by mistake. + try { + window.opener.parent.opener.parent.postMessage({ok: false, desc: "An attempt at top navigation without 'allow-top-navigation' should not have opened a new browsing context."}, "*"); + } catch (error) { + } + + self.close(); + } +</script> +<body onLoad="doStuff()"> +FAIL +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html b/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html new file mode 100644 index 000000000..d3637fb04 --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test for Bug 766282</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + function doStuff() { + window.opener.parent.ok_wrapper(true, "Sandboxed top-level navigation browsing context flag NOT copied to new auxiliary browsing context."); + + self.close(); + } +</script> + +<body onLoad="doStuff()"> + I am navigated to from a window opened from a sandbox with allow-top-navigation. +</body> +</html> diff --git a/dom/html/test/file_iframe_sandbox_worker.js b/dom/html/test/file_iframe_sandbox_worker.js new file mode 100644 index 000000000..edb63eb6c --- /dev/null +++ b/dom/html/test/file_iframe_sandbox_worker.js @@ -0,0 +1,3 @@ +self.onmessage = function(event) {
+ self.postMessage('make it so');
+};
\ No newline at end of file diff --git a/dom/html/test/file_ignoreuserfocus.html b/dom/html/test/file_ignoreuserfocus.html new file mode 100644 index 000000000..b9e330212 --- /dev/null +++ b/dom/html/test/file_ignoreuserfocus.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML> +<html> + <body> + <map name=a> + <area shape=rect coords=0,0,100,100 href=#fail> + </map> + <img usemap=#a src=image.png> + <input><iframe></iframe> + </body> +</html> diff --git a/dom/html/test/file_imports_basics.html b/dom/html/test/file_imports_basics.html new file mode 100644 index 000000000..0abf4e848 --- /dev/null +++ b/dom/html/test/file_imports_basics.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + </head> + <body> + <div id="foo">bar</div> + <script> + counter++; + var importDone = true; + is(document.currentScript.ownerDocument.getElementById("foo").textContent, "bar", + "currentScript.ownerDocument works in imported document,"); + try{ + document.currentScript.ownerDocument.open(); + document.currentScript.ownerDocument.write("<h1>This should not show up!</h1>"); + document.currentScript.ownerDocument.close(); + ok(false, "document.write should have thrown (import)") + } catch (e) { + ok(true, "document.write has thrown (import)") + } + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/file_imports_redirect.html b/dom/html/test/file_imports_redirect.html new file mode 100644 index 000000000..eaca3f49f --- /dev/null +++ b/dom/html/test/file_imports_redirect.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<html> +<body> +</body> +</html> diff --git a/dom/html/test/file_imports_redirect.html^headers^ b/dom/html/test/file_imports_redirect.html^headers^ new file mode 100644 index 000000000..39585a340 --- /dev/null +++ b/dom/html/test/file_imports_redirect.html^headers^ @@ -0,0 +1,2 @@ +HTTP 301 Moved Permanently +Location: http://mochi.test:8888/tests/dom/html/test/file_imports_redirected.html diff --git a/dom/html/test/file_imports_redirected.html b/dom/html/test/file_imports_redirected.html new file mode 100644 index 000000000..031ca313d --- /dev/null +++ b/dom/html/test/file_imports_redirected.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> +<body> +<script> var redirected = true; </script> +</body> +</html> diff --git a/dom/html/test/file_mozaudiochannel.html b/dom/html/test/file_mozaudiochannel.html new file mode 100644 index 000000000..588ae338b --- /dev/null +++ b/dom/html/test/file_mozaudiochannel.html @@ -0,0 +1,91 @@ +<!DOCTYPE HTML> +<html> +<body> +<div id="content" style="display: none"> + <audio id="audio1" /> + <audio id="audio2" mozaudiochannel="foo" /> +</div> + +<script type="application/javascript"> + +function is(a, b, msg) { + parent.postMessage({ status: a === b, msg: msg }, '*'); +} + +function ok(a, msg) { + parent.postMessage({ status: !!a, msg: msg }, '*'); +} + +function finish() { + parent.postMessage({ finish: true }, '*'); +} + +function test_basic() { + var audio1 = document.getElementById("audio1"); + ok(audio1, "Audio Element exists"); + is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'"); + try { + audio1.mozAudioChannelType = "foo"; + } catch(e) {} + is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'"); + + var audio2 = document.getElementById("audio2"); + ok(audio2, "Audio Element exists"); + is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'"); + try { + audio2.mozAudioChannelType = "foo"; + } catch(e) {} + is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'"); + + runTest(); +} + +function test_preferences(aChannel) { + SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", aChannel ]]}, + function() { + var audio = document.createElement('audio'); + ok(audio, "Audio Element created"); + is(audio.mozAudioChannelType, aChannel, "Default audio channel == '" + aChannel + "'"); + runTest(); + } + ); +} + +function test_wrong_preferences() { + SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", 'foobar' ]]}, + function() { + var audio = document.createElement('audio'); + ok(audio, "Audio Element created"); + is(audio.mozAudioChannelType, 'normal', "Default audio channel == 'normal'"); + runTest(); + } + ); +} +var tests = [ + test_basic, + + function() { test_preferences("content"); }, + function() { test_preferences("notification"); }, + function() { test_preferences("alarm"); }, + function() { test_preferences("telephony"); }, + function() { test_preferences("ringer"); }, + function() { test_preferences("publicnotification"); }, + + test_wrong_preferences, +]; + +function runTest() { + if (!tests.length) { + finish(); + return; + } + + var test = tests.shift(); + test(); +} + +runTest(); + +</script> +</body> +</html> diff --git a/dom/html/test/file_srcdoc-2.html b/dom/html/test/file_srcdoc-2.html new file mode 100644 index 000000000..bd75f5e05 --- /dev/null +++ b/dom/html/test/file_srcdoc-2.html @@ -0,0 +1,10 @@ +<!doctype html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=802895 +--> +<body> +<iframe id="iframe" srcdoc="Hello World"></iframe> +</body> + +</html> diff --git a/dom/html/test/file_srcdoc.html b/dom/html/test/file_srcdoc.html new file mode 100644 index 000000000..70fbff42f --- /dev/null +++ b/dom/html/test/file_srcdoc.html @@ -0,0 +1,16 @@ +<!doctype html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=802895 +--> +<body> +<iframe id="iframe" srcdoc="Hello World"></iframe> + +<iframe id="iframe1" src="about:mozilla" + srcdoc="Goodbye World"></iframe> +<iframe id="iframe2" srcdoc="Peeking test" sandbox=""></iframe> +<iframe id="iframe3" src="data:text/html;charset=US-ASCII,Gone" + srcdoc="Going"></iframe> +</body> + +</html> diff --git a/dom/html/test/file_window_open_close_inner.html b/dom/html/test/file_window_open_close_inner.html new file mode 100644 index 000000000..dbc7e3aba --- /dev/null +++ b/dom/html/test/file_window_open_close_inner.html @@ -0,0 +1,7 @@ +<html> +<body> +<script> +window.close(); +</script> +</html> +</body> diff --git a/dom/html/test/file_window_open_close_outer.html b/dom/html/test/file_window_open_close_outer.html new file mode 100644 index 000000000..b1450cee4 --- /dev/null +++ b/dom/html/test/file_window_open_close_outer.html @@ -0,0 +1,5 @@ +<html> +<body> +<a id="link" href="file_window_open_close_inner.html" target="_blank" onclick="setTimeout(function () { window.close() }, 0)">link</a> +</html> +</body> diff --git a/dom/html/test/formData_test.js b/dom/html/test/formData_test.js new file mode 100644 index 000000000..50341276f --- /dev/null +++ b/dom/html/test/formData_test.js @@ -0,0 +1,212 @@ +function testHas() { + var f = new FormData(); + f.append("foo", "bar"); + f.append("another", "value"); + ok(f.has("foo"), "has() on existing name should be true."); + ok(f.has("another"), "has() on existing name should be true."); + ok(!f.has("nonexistent"), "has() on non-existent name should be false."); +} + +function testGet() { + var f = new FormData(); + f.append("foo", "bar"); + f.append("foo", "bar2"); + f.append("blob", new Blob(["hey"], { type: 'text/plain' })); + f.append("file", new File(["hey"], 'testname', {type: 'text/plain'})); + + is(f.get("foo"), "bar", "get() on existing name should return first value"); + ok(f.get("blob") instanceof Blob, "get() on existing name should return first value"); + is(f.get("blob").type, 'text/plain', "get() on existing name should return first value"); + ok(f.get("file") instanceof File, "get() on existing name should return first value"); + is(f.get("file").name, 'testname', "get() on existing name should return first value"); + + is(f.get("nonexistent"), null, "get() on non-existent name should return null."); +} + +function testGetAll() { + var f = new FormData(); + f.append("other", "value"); + f.append("foo", "bar"); + f.append("foo", "bar2"); + f.append("foo", new Blob(["hey"], { type: 'text/plain' })); + + var arr = f.getAll("foo"); + is(arr.length, 3, "getAll() should retrieve all matching entries."); + is(arr[0], "bar", "values should match and be in order"); + is(arr[1], "bar2", "values should match and be in order"); + ok(arr[2] instanceof Blob, "values should match and be in order"); + + is(f.get("nonexistent"), null, "get() on non-existent name should return null."); +} + +function testDelete() { + var f = new FormData(); + f.append("other", "value"); + f.append("foo", "bar"); + f.append("foo", "bar2"); + f.append("foo", new Blob(["hey"], { type: 'text/plain' })); + + ok(f.has("foo"), "has() on existing name should be true."); + f.delete("foo"); + ok(!f.has("foo"), "has() on deleted name should be false."); + is(f.getAll("foo").length, 0, "all entries should be deleted."); + + is(f.getAll("other").length, 1, "other names should still be there."); + f.delete("other"); + is(f.getAll("other").length, 0, "all entries should be deleted."); +} + +function testSet() { + var f = new FormData(); + + f.set("other", "value"); + ok(f.has("other"), "set() on new name should be similar to append()"); + is(f.getAll("other").length, 1, "set() on new name should be similar to append()"); + + f.append("other", "value2"); + is(f.getAll("other").length, 2, "append() should not replace existing entries."); + + f.append("foo", "bar"); + f.append("other", "value3"); + f.append("other", "value3"); + f.append("other", "value3"); + is(f.getAll("other").length, 5, "append() should not replace existing entries."); + + f.set("other", "value4"); + is(f.getAll("other").length, 1, "set() should replace existing entries."); + is(f.getAll("other")[0], "value4", "set() should replace existing entries."); +} + +function testFilename() { + var f = new FormData(); + f.append("blob", new Blob(["hi"])); + ok(f.get("blob") instanceof Blob, "We should have a blob back."); + + // If a filename is passed, that should replace the original. + f.append("blob2", new Blob(["hi"]), "blob2.txt"); + is(f.get("blob2").name, "blob2.txt", "Explicit filename should override \"blob\"."); + + var file = new File(["hi"], "file1.txt"); + f.append("file1", file); + // If a file is passed, the "create entry" algorithm should not create a new File, but reuse the existing one. + is(f.get("file1"), file, "Retrieved File object should be original File object and not a copy."); + is(f.get("file1").name, "file1.txt", "File's filename should be original's name if no filename is explicitly passed."); + + file = new File(["hi"], "file2.txt"); + f.append("file2", file, "fakename.txt"); + ok(f.get("file2") !== file, "Retrieved File object should be new File object if explicit filename is passed."); + is(f.get("file2").name, "fakename.txt", "File's filename should be explicitly passed name."); + f.append("file3", new File(["hi"], "")); + is(f.get("file3").name, "", "File's filename is returned even if empty."); +} + +function testIterable() { + var fd = new FormData(); + fd.set('1','2'); + fd.set('2','4'); + fd.set('3','6'); + fd.set('4','8'); + fd.set('5','10'); + + var key_iter = fd.keys(); + var value_iter = fd.values(); + var entries_iter = fd.entries(); + for (var i = 0; i < 5; ++i) { + var v = i + 1; + var key = key_iter.next(); + var value = value_iter.next(); + var entry = entries_iter.next(); + is(key.value, v.toString(), "Correct Key iterator: " + v.toString()); + ok(!key.done, "key.done is false"); + is(value.value, (v * 2).toString(), "Correct Value iterator: " + (v * 2).toString()); + ok(!value.done, "value.done is false"); + is(entry.value[0], v.toString(), "Correct Entry 0 iterator: " + v.toString()); + is(entry.value[1], (v * 2).toString(), "Correct Entry 1 iterator: " + (v * 2).toString()); + ok(!entry.done, "entry.done is false"); + } + + var last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); + + last = value_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last value"); + + last = entries_iter.next(); + ok(last.done, "Nothing more to read."); + + key_iter = fd.keys(); + key_iter.next(); + key_iter.next(); + fd.delete('1'); + fd.delete('2'); + fd.delete('3'); + fd.delete('4'); + fd.delete('5'); + + last = key_iter.next(); + ok(last.done, "Nothing more to read."); + is(last.value, undefined, "Undefined is the last key"); +} + +function testSend(doneCb) { + var xhr = new XMLHttpRequest(); + xhr.open("POST", "form_submit_server.sjs"); + xhr.onload = function () { + var response = xhr.response; + + for (var entry of response) { + is(entry.body, 'hey'); + is(entry.headers['Content-Type'], 'text/plain'); + } + + is(response[0].headers['Content-Disposition'], + 'form-data; name="empty"; filename="blob"'); + + is(response[1].headers['Content-Disposition'], + 'form-data; name="explicit"; filename="explicit-file-name"'); + + is(response[2].headers['Content-Disposition'], + 'form-data; name="explicit-empty"; filename=""'); + + is(response[3].headers['Content-Disposition'], + 'form-data; name="file-name"; filename="testname"'); + + is(response[4].headers['Content-Disposition'], + 'form-data; name="empty-file-name"; filename=""'); + + is(response[5].headers['Content-Disposition'], + 'form-data; name="file-name-overwrite"; filename="overwrite"'); + + doneCb(); + } + + var file, blob = new Blob(['hey'], {type: 'text/plain'}); + + var fd = new FormData(); + fd.append("empty", blob); + fd.append("explicit", blob, "explicit-file-name"); + fd.append("explicit-empty", blob, ""); + file = new File([blob], 'testname', {type: 'text/plain'}); + fd.append("file-name", file); + file = new File([blob], '', {type: 'text/plain'}); + fd.append("empty-file-name", file); + file = new File([blob], 'testname', {type: 'text/plain'}); + fd.append("file-name-overwrite", file, "overwrite"); + xhr.responseType = 'json'; + xhr.send(fd); +} + +function runTest(doneCb) { + testHas(); + testGet(); + testGetAll(); + testDelete(); + testSet(); + testFilename(); + testIterable(); + // Finally, send an XHR and verify the response matches. + testSend(doneCb); +} + diff --git a/dom/html/test/formData_worker.js b/dom/html/test/formData_worker.js new file mode 100644 index 000000000..d83823554 --- /dev/null +++ b/dom/html/test/formData_worker.js @@ -0,0 +1,19 @@ +function ok(a, msg) { + postMessage({type: 'status', status: !!a, msg: a + ": " + msg }); +} + +function is(a, b, msg) { + postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg }); +} + +function todo(a, msg) { + postMessage({type: 'todo', status: !!a, msg: a + ": " + msg }); +} + +importScripts("formData_test.js"); + +onmessage = function() { + runTest(function() { + postMessage({type: 'finish'}); + }); +} diff --git a/dom/html/test/formSubmission_chrome.js b/dom/html/test/formSubmission_chrome.js new file mode 100644 index 000000000..540a11755 --- /dev/null +++ b/dom/html/test/formSubmission_chrome.js @@ -0,0 +1,6 @@ +var { classes: Cc, interfaces: Ci, utils: Cu } = Components; +Cu.importGlobalProperties(["File"]); + +addMessageListener("files.open", function (message) { + sendAsyncMessage("files.opened", message.map(path => File.createFromFileName(path))); +}); diff --git a/dom/html/test/form_submit_server.sjs b/dom/html/test/form_submit_server.sjs new file mode 100644 index 000000000..95c019d16 --- /dev/null +++ b/dom/html/test/form_submit_server.sjs @@ -0,0 +1,71 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream"); + +function utf8decode(s) { + return decodeURIComponent(escape(s)); +} + +function utf8encode(s) { + return unescape(encodeURIComponent(s)); +} + +function handleRequest(request, response) +{ + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var result = []; + var requestBody = ""; + while ((bodyAvail = bodyStream.available()) > 0) + requestBody += bodyStream.readBytes(bodyAvail); + + if (request.method == "POST") { + + var contentTypeParams = {}; + request.getHeader("Content-Type").split(/\s*\;\s*/).forEach(function(s) { + if (s.indexOf('=') >= 0) { + let [name, value] = s.split('='); + contentTypeParams[name] = value; + } + else { + contentTypeParams[''] = s; + } + }); + + if (contentTypeParams[''] == "multipart/form-data" && + request.queryString == "") { + requestBody.split("--" + contentTypeParams.boundary).slice(1, -1).forEach(function (s) { + + let headers = {}; + let headerEnd = s.indexOf("\r\n\r\n"); + s.substr(2, headerEnd-2).split("\r\n").forEach(function(s) { + // We're assuming UTF8 for now + let [name, value] = s.split(': '); + headers[name] = utf8decode(value); + }); + + let body = s.substring(headerEnd + 4, s.length - 2); + if (!headers["Content-Type"] || headers["Content-Type"] == "text/plain") { + // We're assuming UTF8 for now + body = utf8decode(body); + } + result.push({ headers: headers, body: body}); + }); + } + if (contentTypeParams[''] == "text/plain" && + request.queryString == "plain") { + result = utf8decode(requestBody); + } + if (contentTypeParams[''] == "application/x-www-form-urlencoded" && + request.queryString == "url") { + result = requestBody; + } + } + else if (request.method == "GET") { + result = request.queryString; + } + + // Send response body + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + response.write(utf8encode(JSON.stringify(result))); +} diff --git a/dom/html/test/forms/chrome.ini b/dom/html/test/forms/chrome.ini new file mode 100644 index 000000000..0c8fa8231 --- /dev/null +++ b/dom/html/test/forms/chrome.ini @@ -0,0 +1,5 @@ +[DEFAULT] +support-files = + submit_invalid_file.sjs +[test_autocompleteinfo.html] +[test_submit_invalid_file.html] diff --git a/dom/html/test/forms/mochitest.ini b/dom/html/test/forms/mochitest.ini new file mode 100644 index 000000000..35955b189 --- /dev/null +++ b/dom/html/test/forms/mochitest.ini @@ -0,0 +1,107 @@ +[DEFAULT] +support-files = + save_restore_radio_groups.sjs + test_input_number_data.js + !/dom/html/test/reflect.js + +[test_bug1039548.html] +[test_bug1283915.html] +[test_bug1286509.html] +skip-if = os == "android" # up/down arrow keys not supported on android +[test_button_attributes_reflection.html] +[test_input_radio_indeterminate.html] +[test_input_radio_radiogroup.html] +[test_input_radio_required.html] +[test_change_event.html] +[test_datalist_element.html] +[test_form_attribute-1.html] +[test_form_attribute-2.html] +[test_form_attribute-3.html] +[test_form_attribute-4.html] +[test_form_attributes_reflection.html] +[test_form_named_getter_dynamic.html] +[test_formaction_attribute.html] +[test_formnovalidate_attribute.html] +[test_input_attributes_reflection.html] +[test_input_autocomplete.html] +[test_input_color_input_change_events.html] +[test_input_color_picker_initial.html] +[test_input_color_picker_popup.html] +skip-if = android_version == '18' # Android, bug 1147974 +[test_input_color_picker_update.html] +skip-if = android_version == '18' # Android, bug 1147974 +[test_input_datetime_focus_blur.html] +skip-if = os == "android" +[test_input_datetime_tabindex.html] +skip-if = os == "android" +[test_input_defaultValue.html] +[test_input_email.html] +[test_input_event.html] +skip-if = android_version == '18' # bug 1147974 +[test_input_file_picker.html] +[test_input_list_attribute.html] +[test_input_number_l10n.html] +# We don't build ICU for Firefox for Android: +skip-if = os == "android" +[test_input_number_key_events.html] +[test_input_number_mouse_events.html] +# Not run on Firefox for Android where the spin buttons are hidden: +skip-if = os == "android" +[test_input_number_rounding.html] +skip-if = os == "android" +[test_input_number_validation.html] +# We don't build ICU for Firefox for Android: +skip-if = os == "android" +[test_input_number_focus.html] +[test_input_range_attr_order.html] +[test_input_range_key_events.html] +[test_input_range_mouse_and_touch_events.html] +[test_input_range_rounding.html] +[test_input_sanitization.html] +[test_input_textarea_set_value_no_scroll.html] +[test_input_time_key_events.html] +skip-if = os == "android" +[test_input_time_focus_blur_events.html] +skip-if = os == "android" +[test_input_types_pref.html] +[test_input_typing_sanitization.html] +[test_input_untrusted_key_events.html] +[test_input_url.html] +[test_interactive_content_in_label.html] +[test_label_control_attribute.html] +[test_label_input_controls.html] +[test_max_attribute.html] +[test_maxlength_attribute.html] +[test_minlength_attribute.html] +[test_meter_element.html] +[test_meter_pseudo-classes.html] +[test_min_attribute.html] +[test_mozistextfield.html] +[test_novalidate_attribute.html] +[test_option_disabled.html] +[test_option_index_attribute.html] +[test_option_text.html] +[test_output_element.html] +[test_pattern_attribute.html] +[test_progress_element.html] +[test_radio_in_label.html] +[test_radio_radionodelist.html] +[test_required_attribute.html] +[test_restore_form_elements.html] +[test_save_restore_radio_groups.html] +[test_select_change_event.html] +skip-if = android_version == '18' || os == 'mac' +[test_select_input_change_event.html] +skip-if = android_version == '18' || os == 'mac' +[test_select_selectedOptions.html] +[test_select_validation.html] +[test_set_range_text.html] +[test_step_attribute.html] +[test_stepup_stepdown.html] +[test_textarea_attributes_reflection.html] +[test_validation.html] +[test_valueAsDate_pref.html] +[test_valueasdate_attribute.html] +[test_valueasnumber_attribute.html] +[test_validation_not_in_doc.html] +[test_reportValidation_preventDefault.html] diff --git a/dom/html/test/forms/save_restore_radio_groups.sjs b/dom/html/test/forms/save_restore_radio_groups.sjs new file mode 100644 index 000000000..f0e36cb52 --- /dev/null +++ b/dom/html/test/forms/save_restore_radio_groups.sjs @@ -0,0 +1,50 @@ +var pages = [ + "<!DOCTYPE html>" + + "<html><body>" + + "<form>" + + "<input name='a' type='radio' checked><input name='a' type='radio'><input name='a' type='radio'>" + + "</form>" + + "</body></html>", + "<!DOCTYPE html>" + + "<html><body>" + + "<form>" + + "<input name='a' type='radio'><input name='a' type='radio' checked><input name='a' type='radio'>" + + "</form>" + + "</body></html>", + ]; + +/** + * This SJS is going to send the same page the two first times it will be called + * and another page the two following times. After that, the response will have + * no content. + * The use case is to have two iframes using this SJS and both being reloaded + * once. + */ + +function handleRequest(request, response) +{ + var counter = +getState("counter"); // convert to number; +"" === 0 + + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/html"); + response.setHeader("Cache-Control", "no-cache"); + + switch (counter) { + case 0: + case 1: + response.write(pages[0]); + break; + case 2: + case 3: + response.write(pages[1]); + break; + } + + // When we finish the test case we need to reset the counter + if (counter == 3) { + setState("counter", "0"); + } else { + setState("counter", "" + ++counter); + } +} + diff --git a/dom/html/test/forms/submit_invalid_file.sjs b/dom/html/test/forms/submit_invalid_file.sjs new file mode 100644 index 000000000..8f8b46957 --- /dev/null +++ b/dom/html/test/forms/submit_invalid_file.sjs @@ -0,0 +1,14 @@ +function handleRequest(request, response) +{ + response.setStatusLine(request.httpVersion, 200, "Ok"); + response.setHeader("Content-Type", "text/html"); + response.setHeader("Cache-Control", "no-cache"); + + var result = {}; + request.bodyInputStream.search("testfile", true, result, {}); + if (result.value) { + response.write("SUCCESS"); + } else { + response.write("FAIL"); + } +} diff --git a/dom/html/test/forms/test_autocompleteinfo.html b/dom/html/test/forms/test_autocompleteinfo.html new file mode 100644 index 000000000..310b7c9f3 --- /dev/null +++ b/dom/html/test/forms/test_autocompleteinfo.html @@ -0,0 +1,121 @@ +<!DOCTYPE html> +<html> +<!-- +Test getAutocompleteInfo() on <input> +--> +<head> + <title>Test for getAutocompleteInfo()</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> + +<body> +<p id="display"></p> +<div id="content" style="display: none"> + <form> + <input id="input"/> + </form> +</div> +<pre id="test"> +<script> +"use strict"; + +var values = [ + // Missing or empty attribute + [undefined, {}], + ["", {}], + + // One token + ["on", {fieldName: "on" }], + ["On", {fieldName: "on" }], + ["off", {fieldName: "off" } ], + ["username", {fieldName: "username" }], + [" username ", {fieldName: "username" }], + ["foobar", {}], + + // Two tokens + ["on off", {}], + ["off on", {}], + ["username tel", {}], + ["tel username ", {}], + [" username tel ", {}], + ["tel mobile", {}], + ["tel shipping", {}], + ["shipping tel", {addressType: "shipping", fieldName: "tel"}], + ["shipPING tel", {addressType: "shipping", fieldName: "tel"}], + ["mobile tel", {contactType: "mobile", fieldName: "tel"}], + [" MoBiLe TeL ", {contactType: "mobile", fieldName: "tel"}], + ["XXX tel", {}], + ["XXX username", {}], + + // Three tokens + ["billing invalid tel", {}], + ["___ mobile tel", {}], + ["mobile foo tel", {}], + ["mobile tel foo", {}], + ["tel mobile billing", {}], + ["billing mobile tel", {addressType: "billing", contactType: "mobile", fieldName: "tel"}], + [" BILLing MoBiLE tEl ", {addressType: "billing", contactType: "mobile", fieldName: "tel"}], + ["billing home tel", {addressType: "billing", contactType: "home", fieldName: "tel"}], + + // Four tokens (invalid) + ["billing billing mobile tel", {}], + + // Five tokens (invalid) + ["billing billing billing mobile tel", {}], +]; + +var autocompleteEnabledTypes = ["hidden", "text", "search", "url", "tel", + "email", "password", "date", "time", "number", + "range", "color"]; +var autocompleteDisabledTypes = ["reset", "submit", "image", "button", "radio", + "checkbox", "file"]; + +function start() { + const fieldid = "input"; + var field = document.getElementById(fieldid); + for (var test of values) { + if (typeof(test[0]) === "undefined") + field.removeAttribute("autocomplete"); + else + field.setAttribute("autocomplete", test[0]); + + var info = field.getAutocompleteInfo(); + + is(info.section, "section" in test[1] ? test[1].section : "", + "Checking autocompleteInfo.section for " + fieldid + ": " + test[0]); + is(info.addressType, "addressType" in test[1] ? test[1].addressType : "", + "Checking autocompleteInfo.addressType for " + fieldid + ": " + test[0]); + is(info.contactType, "contactType" in test[1] ? test[1].contactType : "", + "Checking autocompleteInfo.contactType for " + fieldid + ": " + test[0]); + is(info.fieldName, "fieldName" in test[1] ? test[1].fieldName : "", + "Checking autocompleteInfo.fieldName for " + fieldid + ": " + test[0]); + + } + + for (var type of autocompleteEnabledTypes) { + testAutocomplete(field, type, true); + } + + for (var type of autocompleteDisabledTypes) { + testAutocomplete(field, type, false); + } + SimpleTest.finish(); +} + +function testAutocomplete(aField, aType, aEnabled) { + aField.type = aType; + if (aEnabled) { + ok(aField.getAutocompleteInfo() !== null, "getAutocompleteInfo shouldn't return null"); + } else { + is(aField.getAutocompleteInfo(), null, "getAutocompleteInfo should return null"); + } +} + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.experimental", true]]}, start); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_bug1039548.html b/dom/html/test/forms/test_bug1039548.html new file mode 100644 index 000000000..0405d5482 --- /dev/null +++ b/dom/html/test/forms/test_bug1039548.html @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1039548 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1039548</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1039548 **/ + + SimpleTest.waitForExplicitFinish(); + + SimpleTest.waitForFocus(test); + + var didTryToSubmit; + function test() { + var r = document.getElementById("radio"); + r.focus(); + didTryToSubmit = false; + sendKey("return"); + ok(!didTryToSubmit, "Shouldn't have tried to submit!"); + + var t = document.getElementById("text"); + t.focus(); + didTryToSubmit = false; + sendKey("return"); + ok(didTryToSubmit, "Should have tried to submit!"); + SimpleTest.finish(); + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1039548">Mozilla Bug 1039548</a> +<p id="display"></p> +<div id="content"> + + <form onsubmit="didTryToSubmit = true; event.preventDefault();"> + <input type="radio" id="radio"> + </form> + + <form onsubmit="didTryToSubmit = true; event.preventDefault();"> + <input type="text" id="text"> + </form> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_bug1283915.html b/dom/html/test/forms/test_bug1283915.html new file mode 100644 index 000000000..0b0ac5f13 --- /dev/null +++ b/dom/html/test/forms/test_bug1283915.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1283915 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1283915</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1283915 **/ + + SimpleTest.waitForExplicitFinish(); + + function isCursorAtEnd(field){ + is(field.selectionStart, field.value.length); + is(field.selectionEnd, field.value.length); + } + + function test() { + var tField = document.getElementById("textField"); + tField.focus(); + + synthesizeKey("a", {}); + is(tField.value, "a"); + isCursorAtEnd(tField); + document.body.offsetWidth; // frame must be created after type change + + synthesizeKey("b", {}); + is(tField.value, "ab"); + isCursorAtEnd(tField); + + synthesizeKey("c", {}); + is(tField.value, "abc"); + isCursorAtEnd(tField); + + var nField = document.getElementById("numField"); + nField.focus(); + + synthesizeKey("1", {}); + is(nField.value, "1"); + document.body.offsetWidth; + + synthesizeKey("2", {}); + is(nField.value, "12"); + + synthesizeKey("3", {}); + is(nField.value, "123"); + + SimpleTest.finish(); + } + + SimpleTest.waitForFocus(test); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1283915">Mozilla Bug 1283915</a> +<p id="display"></p> +<input id="textField" type="text" oninput="if (this.type !='password') this.type = 'password';"> +<input id="numField" type="text" oninput="if (this.type !='number') this.type = 'number';"> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_bug1286509.html b/dom/html/test/forms/test_bug1286509.html new file mode 100644 index 000000000..05fbbac31 --- /dev/null +++ b/dom/html/test/forms/test_bug1286509.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1286509 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1286509</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1286509">Mozilla Bug 1286509</a> +<p id="display"></p> +<div id="content"> + <input type="range" id="test_input" min="0" max="10" value="5"> +</div> +<pre id="test"> + <script type="application/javascript"> + /** Test for Bug 1286509 **/ + SimpleTest.waitForExplicitFinish(); + var expectedEventSequence = ['keydown', 'change', 'keyup']; + var eventCounts = {}; + var expectedEventIdx = 0; + + function test() { + var range = document.getElementById("test_input"); + range.focus(); + expectedEventSequence.forEach((eventName) => { + eventCounts[eventName] = 0; + range.addEventListener(eventName, (e) => { + ++eventCounts[eventName]; + is(expectedEventSequence[expectedEventIdx], e.type, "Events sequence should be keydown, change, keyup"); + expectedEventIdx = (expectedEventIdx + 1) % 3; + }, false); + }); + synthesizeKey("VK_UP", {}); + synthesizeKey("VK_DOWN", {}); + synthesizeKey("VK_LEFT", {}); + synthesizeKey("VK_RIGHT", {}); + is(eventCounts['change'], 4, "Expect key up/down/left/right should trigger range input to fire change events"); + SimpleTest.finish(); + } + addLoadEvent(test); + </script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_button_attributes_reflection.html b/dom/html/test/forms/test_button_attributes_reflection.html new file mode 100644 index 000000000..26858e939 --- /dev/null +++ b/dom/html/test/forms/test_button_attributes_reflection.html @@ -0,0 +1,137 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLButtonElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLButtonElement attributes reflection **/ + +// .autofocus +reflectBoolean({ + element: document.createElement("button"), + attribute: "autofocus", +}); + +// .disabled +reflectBoolean({ + element: document.createElement("button"), + attribute: "disabled", +}); + +// TODO: formAction (URL). But note that we currently reflect it weirdly; see +// dom/html/test/test_bug607145.html + +// .formEnctype +reflectLimitedEnumerated({ + element: document.createElement("button"), + attribute: "formEnctype", + validValues: [ + "application/x-www-form-urlencoded", + "multipart/form-data", + "text/plain", + ], + invalidValues: [ "text/html", "", "tulip" ], + defaultValue: { + invalid: "application/x-www-form-urlencoded", + missing: "", + } +}); + +// .formMethod +reflectLimitedEnumerated({ + element: document.createElement("button"), + attribute: "formMethod", + validValues: [ "get", "post" ], + invalidValues: [ "put", "", "tulip" ], + unsupportedValues: [ "dialog" ], + defaultValue: { + invalid: "get", + missing: "", + } +}); + +// .formNoValidate +reflectBoolean({ + element: document.createElement("button"), + attribute: "formNoValidate", +}); + +// .formTarget +reflectString({ + element: document.createElement("button"), + attribute: "formTarget", + otherValues: [ "_blank", "_self", "_parent", "_top" ], +}); + +// .name +reflectString({ + element: document.createElement("button"), + attribute: "name", + otherValues: [ "isindex", "_charset_" ] +}); + +// .type +reflectLimitedEnumerated({ + element: document.createElement("button"), + attribute: "type", + validValues: [ "submit", "reset", "button" ], + invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ], + unsupportedValues: [ "menu" ], + defaultValue: "submit", +}); + +// .value +reflectString({ + element: document.createElement("button"), + attribute: "value", +}); + +// .willValidate +ok("willValidate" in document.createElement("button"), + "willValidate should be an IDL attribute of the button element"); +is(typeof(document.createElement("button").willValidate), "boolean", + "button.willValidate should be a boolean"); + +// .validity +ok("validity" in document.createElement("button"), + "validity should be an IDL attribute of the button element"); +is(typeof(document.createElement("button").validity), "object", + "button.validity should be an object"); +ok(document.createElement("button").validity instanceof ValidityState, + "button.validity sohuld be an instance of ValidityState"); + +// .validationMessage +ok("validationMessage" in document.createElement("button"), + "validationMessage should be an IDL attribute of the button element"); +is(typeof(document.createElement("button").validationMessage), "string", + "button.validationMessage should be a string"); + +// .checkValidity() +ok("checkValidity" in document.createElement("button"), + "checkValidity() should be a method of the button element"); +is(typeof(document.createElement("button").checkValidity), "function", + "button.checkValidity should be a function"); + +// .setCustomValidity() +ok("setCustomValidity" in document.createElement("button"), + "setCustomValidity() should be a method of the button element"); +is(typeof(document.createElement("button").setCustomValidity), "function", + "button.setCustomValidity should be a function"); + +// .labels +todo("labels" in document.createElement("button"), + "button.labels isn't implemented yet"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_change_event.html b/dom/html/test/forms/test_change_event.html new file mode 100644 index 000000000..d1f0f827e --- /dev/null +++ b/dom/html/test/forms/test_change_event.html @@ -0,0 +1,287 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=722599 +--> +<head> +<title>Test for Bug 722599</title> +<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=722599">Mozilla Bug 722599</a> +<p id="display"></p> +<div id="content"> +<input type="file" id="fileInput"></input> +<textarea id="textarea" onchange="++textareaChange;"></textarea> +<input type="text" id="input_text" onchange="++textInputChange[0];"></input> +<input type="email" id="input_email" onchange="++textInputChange[1];"></input> +<input type="search" id="input_search" onchange="++textInputChange[2];"></input> +<input type="tel" id="input_tel" onchange="++textInputChange[3];"></input> +<input type="url" id="input_url" onchange="++textInputChange[4];"></input> +<input type="password" id="input_password" onchange="++textInputChange[5];"></input> + +<!-- "Non-text" inputs--> +<input type="button" id="input_button" onchange="++NonTextInputChange[0];"></input> +<input type="submit" id="input_submit" onchange="++NonTextInputChange[1];"></input> +<input type="image" id="input_image" onchange="++NonTextInputChange[2];"></input> +<input type="reset" id="input_reset" onchange="++NonTextInputChange[3];"></input> +<input type="radio" id="input_radio" onchange="++NonTextInputChange[4];"></input> +<input type="checkbox" id="input_checkbox" onchange="++NonTextInputChange[5];"></input> +<input type="number" id="input_number" onchange="++numberChange;"></input> +<input type="range" id="input_range" onchange="++rangeChange;"></input> + +<!-- Input text with default value and blurs on focus--> +<input type="text" id="input_text_value" onchange="++textInputValueChange" + onfocus="this.blur();" value="foo"></input> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + + /** Test for Bug 722599 **/ + + const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent); + + var textareaChange = 0; + var fileInputChange = 0; + var textInputValueChange = 0; + + var textInputTypes = ["text", "email", "search", "tel", "url", "password"]; + var textInputChange = [0, 0, 0, 0, 0, 0]; + + var NonTextInputTypes = ["button", "submit", "image", "reset", "radio", "checkbox"]; + var NonTextInputChange = [0, 0, 0, 0, 0, 0]; + + var numberChange = 0; + var rangeChange = 0; + + var blurTestCalled = false; //Sentinel to prevent infinite loop. + + SimpleTest.waitForExplicitFinish(); + var MockFilePicker = SpecialPowers.MockFilePicker; + MockFilePicker.init(window); + + function fileInputBlurTest() { + var btn = document.getElementById('fileInput'); + btn.focus() + btn.blur(); + is(fileInputChange, 1, "change event shouldn't be dispatched on blur for file input element(1)"); + } + + function testUserInput() { + //Simulating an OK click and with a file name return. + MockFilePicker.useBlobFile(); + MockFilePicker.returnValue = MockFilePicker.returnOK; + var input = document.getElementById('fileInput'); + input.focus(); + + input.addEventListener("change", function (aEvent) { + ++fileInputChange; + if (!blurTestCalled) { + is(fileInputChange, 1, "change event should have been dispatched on file input."); + blurTestCalled = true; + fileInputBlurTest(); + } + else { + is(fileInputChange, 1, "change event shouldn't be dispatched on blur for file input element (2)"); + } + }, false); + input.click(); + // blur the file input, we can't use blur() because of bug 760283 + document.getElementById('input_text').focus(); + setTimeout(testUserInput2, 0); + } + + function testUserInput2() { + var input = document.getElementById('fileInput'); + // remove it, otherwise cleanup() opens a native file picker! + input.parentNode.removeChild(input); + MockFilePicker.cleanup(); + + //text, email, search, telephone, url & password input tests + for (var i = 0; i < textInputTypes.length; ++i) { + input = document.getElementById("input_" + textInputTypes[i]); + input.focus(); + synthesizeKey("VK_RETURN", {}); + is(textInputChange[i], 0, "Change event shouldn't be dispatched on " + textInputTypes[i] + " input element"); + + synthesizeKey("m", {}); + synthesizeKey("VK_RETURN", {}); + is(textInputChange[i], 1, textInputTypes[i] + " input element should have dispatched change event."); + } + + //focus and blur text input + input = document.getElementById("input_text"); + input.focus(); + synthesizeKey("f", {}); + input.blur(); + is(textInputChange[0], 2, "text input element should have dispatched change event (2)."); + + // value being set while focused + input.focus(); + input.value = 'foo'; + input.blur(); + is(textInputChange[0], 2, "text input element should not have dispatched change event (2)."); + + // value being set while focused after being modified manually + input.focus(); + synthesizeKey("f", {}); + input.value = 'bar'; + input.blur(); + is(textInputChange[0], 3, "text input element should have dispatched change event (3)."); + + //focus and blur textarea + var textarea = document.getElementById("textarea"); + textarea.focus(); + synthesizeKey("f", {}); + textarea.blur(); + is(textareaChange, 1, "Textarea element should have dispatched change event."); + + // value being set while focused + textarea.focus(); + textarea.value = 'foo'; + textarea.blur(); + is(textareaChange, 1, "textarea should not have dispatched change event (1)."); + + // value being set while focused after being modified manually + textarea.focus(); + synthesizeKey("f", {}); + textarea.value = 'bar'; + textarea.blur(); + is(textareaChange, 2, "textearea should have dispatched change event (2)."); + + //Non-text input tests: + for (var i = 0; i < NonTextInputTypes.length; ++i) { + //button, submit, image and reset input type tests. + if (i < 4) { + input = document.getElementById("input_" + NonTextInputTypes[i]); + input.focus(); + input.click(); + is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element"); + input.blur(); + is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element(2)"); + } + //for radio and and checkboxes, we require that change event should ONLY be dispatched on setting the value. + else { + input = document.getElementById("input_" + NonTextInputTypes[i]); + input.focus(); + input.click(); + is(NonTextInputChange[i], 1, NonTextInputTypes[i] + " input element should have dispatched change event."); + input.blur(); + is(NonTextInputChange[i], 1, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element"); + + // Test that change event is not dispatched if click event is cancelled. + function preventDefault(e) { + e.preventDefault(); + } + input.addEventListener("click", preventDefault, false); + input.click(); + is(NonTextInputChange[i], 1, "Change event shouldn't be dispatched if click event is cancelled"); + input.removeEventListener("click", preventDefault, false); + } + } + + // Special case type=number + var number = document.getElementById("input_number"); + number.focus(); + synthesizeKey("a", {}); + number.blur(); + is(numberChange, 0, "Change event shouldn't be dispatched on number input element for key changes that don't change its value"); + number.value = ""; + number.focus(); + synthesizeKey("1", {}); + synthesizeKey("2", {}); + is(numberChange, 0, "Change event shouldn't be dispatched on number input element for keyboard input until it loses focus"); + number.blur(); + is(numberChange, 1, "Change event should be dispatched on number input element on blur"); + is(number.value, "12", "Sanity check that number keys were actually handled"); + if (isDesktop) { // up/down arrow keys not supported on android/b2g + number.value = ""; + number.focus(); + synthesizeKey("VK_UP", {}); + synthesizeKey("VK_UP", {}); + synthesizeKey("VK_DOWN", {}); + is(numberChange, 4, "Change event should be dispatched on number input element for up/down arrow keys (a special case)"); + is(number.value, "1", "Sanity check that number and arrow keys were actually handled"); + } + + // Special case type=range + var range = document.getElementById("input_range"); + range.focus(); + synthesizeKey("a", {}); + range.blur(); + is(rangeChange, 0, "Change event shouldn't be dispatched on range input element for key changes that don't change its value"); + range.focus(); + synthesizeKey("VK_HOME", {}); + is(rangeChange, 1, "Change event should be dispatched on range input element for key changes"); + range.blur(); + is(rangeChange, 1, "Change event shouldn't be dispatched on range input element on blur"); + range.focus(); + var bcr = range.getBoundingClientRect(); + var centerOfRangeX = bcr.width / 2; + var centerOfRangeY = bcr.height / 2; + synthesizeMouse(range, centerOfRangeX - 10, centerOfRangeY, { type: "mousedown" }); + is(rangeChange, 1, "Change event shouldn't be dispatched on range input element for mousedown"); + synthesizeMouse(range, centerOfRangeX - 5, centerOfRangeY, { type: "mousemove" }); + is(rangeChange, 1, "Change event shouldn't be dispatched on range input element during drag of thumb"); + synthesizeMouse(range, centerOfRangeX, centerOfRangeY, { type: "mouseup" }); + is(rangeChange, 2, "Change event should be dispatched on range input element at end of drag"); + range.blur(); + is(rangeChange, 2, "Change event shouldn't be dispatched on range input element when range loses focus after a drag"); + synthesizeMouse(range, centerOfRangeX - 10, centerOfRangeY, {}); + is(rangeChange, 3, "Change event should be dispatched on range input element for a click that gives the range focus"); + + if (isDesktop) { // up/down arrow keys not supported on android/b2g + synthesizeKey("VK_UP", {}); + is(rangeChange, 4, "Change event should be dispatched on range input element for key changes that change its value (VK_UP)"); + synthesizeKey("VK_DOWN", {}); + is(rangeChange, 5, "Change event should be dispatched on range input element for key changes that change its value (VK_DOWN)"); + synthesizeKey("VK_RIGHT", {}); + is(rangeChange, 6, "Change event should be dispatched on range input element for key changes that change its value (VK_RIGHT)"); + synthesizeKey("VK_LEFT", {}); + is(rangeChange, 7, "Change event should be dispatched on range input element for key changes that change its value (VK_LEFT)"); + synthesizeKey("VK_UP", {shiftKey: true}); + is(rangeChange, 8, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_UP)"); + synthesizeKey("VK_DOWN", {shiftKey: true}); + is(rangeChange, 9, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_DOWN)"); + synthesizeKey("VK_RIGHT", {shiftKey: true}); + is(rangeChange, 10, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_RIGHT)"); + synthesizeKey("VK_LEFT", {shiftKey: true}); + is(rangeChange, 11, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_LEFT)"); + synthesizeKey("VK_PAGE_UP", {}); + is(rangeChange, 12, "Change event should be dispatched on range input element for key changes that change its value (VK_PAGE_UP)"); + synthesizeKey("VK_PAGE_DOWN", {}); + is(rangeChange, 13, "Change event should be dispatched on range input element for key changes that change its value (VK_PAGE_DOWN"); + synthesizeKey("VK_RIGHT", {shiftKey: true}); + is(rangeChange, 14, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_PAGE_UP)"); + synthesizeKey("VK_LEFT", {shiftKey: true}); + is(rangeChange, 15, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_PAGE_DOWN)"); + } + //Input type change test. + input = document.getElementById("input_checkbox"); + input.type = "text"; + input.focus(); + input.click(); + input.blur(); + is(NonTextInputChange[5], 1, "Change event shouldn't be dispatched for checkbox ---> text input type change"); + + setTimeout(testInputWithDefaultValue, 0); + } + + function testInputWithDefaultValue() { + // focus and blur an input text should not trigger change event if content hasn't changed. + var input = document.getElementById('input_text_value'); + input.focus(); + is(textInputValueChange, 0, "change event shouldn't be dispatched on input text with default value"); + + SimpleTest.finish(); + } + + addLoadEvent(testUserInput); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_datalist_element.html b/dom/html/test/forms/test_datalist_element.html new file mode 100644 index 000000000..67c8e854a --- /dev/null +++ b/dom/html/test/forms/test_datalist_element.html @@ -0,0 +1,118 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for the datalist element</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + <datalist> + </datalist> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 555840 **/ + +function checkClassesAndAttributes() +{ + var d = document.getElementsByTagName('datalist'); + is(d.length, 1, "One datalist has been found"); + + d = d[0]; + ok(d instanceof HTMLDataListElement, + "The datalist should be instance of HTMLDataListElement"); + + ok('options' in d, "datalist has an options IDL attribute"); + + ok(d.options, "options IDL attribute is not null"); + ok(!d.getAttribute('options'), "datalist has no options content attribute"); + + ok(d.options instanceof HTMLCollection, + "options IDL attribute should be instance of HTMLCollection"); +} + +function checkOptions() +{ + var testData = [ + /* [ Child list, Function modifying children, Recognized options ] */ + [['option'], null, 1], + [['option', 'option', 'option', 'option'], null, 4], + /* Disabled options are not valid. */ + [['option'], function(d) { d.childNodes[0].disabled = true; }, 0], + [['option', 'option'], function(d) { d.childNodes[0].disabled = true; }, 1], + /* Non-option elements are not recognized. */ + [['input'], null, 0], + [['input', 'option'], null, 1], + [['input', 'textarea'], null, 0], + /* .value and .label are not needed to be valid options. */ + [['option', 'option'], function(d) { d.childNodes[0].value = 'value'; }, 2], + [['option', 'option'], function(d) { d.childNodes[0].label = 'label'; }, 2], + [['option', 'option'], function(d) { d.childNodes[0].value = 'value'; d.childNodes[0].label = 'label'; }, 2], + [['select'], + function(d) { + var s = d.childNodes[0]; + s.appendChild(new Option("foo")); + s.appendChild(new Option("bar")); + }, + 2], + [['select'], + function(d) { + var s = d.childNodes[0]; + s.appendChild(new Option("foo")); + s.appendChild(new Option("bar")); + var label = document.createElement("label"); + d.appendChild(label); + label.appendChild(new Option("foobar")); + }, + 3], + [['select'], + function(d) { + var s = d.childNodes[0]; + s.appendChild(new Option("foo")); + s.appendChild(new Option("bar")); + var label = document.createElement("label"); + d.appendChild(label); + label.appendChild(new Option("foobar")); + s.appendChild(new Option()) + }, + 4], + [[], function(d) { d.appendChild(document.createElementNS("foo", "option")); }, 0] + ]; + + var d = document.getElementsByTagName('datalist')[0]; + var cachedOptions = d.options; + + testData.forEach(function(data) { + data[0].forEach(function(e) { + d.appendChild(document.createElement(e)); + }) + + /* Modify children. */ + if (data[1]) { + data[1](d); + } + + is(d.options, cachedOptions, "Should get the same object") + is(d.options.length, data[2], + "The number of recognized options should be " + data[2]) + + for (var i = 0; i < d.options.length; ++i) { + is(d.options[i].localName, "option", + "Should get an option for d.options[" + i + "]") + } + + /* Cleaning-up. */ + d.textContent = ""; + }) +} + +checkClassesAndAttributes(); +checkOptions(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_form_attribute-1.html b/dom/html/test/forms/test_form_attribute-1.html new file mode 100644 index 000000000..bb82cb0da --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-1.html @@ -0,0 +1,473 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=588683 +--> +<head> + <title>Test for form attributes 1</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for form attributes 1 **/ + +/** + * All functions take an array of forms in first argument and an array of + * elements in second argument. + * Then, it returns an array containing an array of form and an array of array + * of elements. The array represent the form association with elements like this: + * [ [ form1, form2 ], [ [ elmt1ofForm1, elmt2ofForm2 ], [ elmtofForm2 ] ] ] + */ + +/** + * test0a and test0b are testing the regular behavior of form ownership. + */ +function test0a(aForms, aElements) +{ + // <form><element></form> + // <form><element></form> + aForms[0].appendChild(aElements[0]); + aForms[1].appendChild(aElements[1]); + + return [[aForms[0],aForms[1]],[[aElements[0]],[aElements[1]]]]; +} + +function test0b(aForms, aElements) +{ + // <form><element><form><element></form></form> + aForms[0].appendChild(aElements[0]); + aForms[0].appendChild(aForms[1]); + aForms[1].appendChild(aElements[1]); + + return [[aForms[0],aForms[1]],[[aElements[0]],[aElements[1]]]]; +} + +/** + * This function test that, when an element is not a descendant of a form + * element and has @form set to a valid form id, it's form owner is the form + * which has the id. + */ +function test1(aForms, aElements) +{ + // <form id='f'></form><element id='f'> + aForms[0].id = 'f'; + aElements[0].setAttribute('form', 'f'); + + return [[aForms[0]], [[aElements[0]]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id (not it's descendant), it's form + * owner is the form which has the id. + */ +function test2(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + + return [[aForms[0], aForms[1]], [[aElements[0]],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id (not it's descendant), then the + * form attribute is removed, it does not have a form owner. + */ +function test3(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aElements[0].removeAttribute('form'); + + return [[aForms[0], aForms[1]], [[],[aElements[0]]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id (not it's descendant), then the + * form's id attribute is removed, it does not have a form owner. + */ +function test4(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aForms[0].removeAttribute('id'); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to an invalid form id, then it does not have a form + * owner. + */ +function test5(aForms, aElements) +{ + // <form id='f'></form><form><element form='foo'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'foo'); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id (not it's descendant), then the + * form id attribute is changed to an invalid id, it does not have a form owner. + */ +function test6(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aElements[0].setAttribute('form', 'foo'); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to an invalid form id, then the form id attribute + * is changed to a valid form id, it's form owner is the form which has this id. + */ +function test7(aForms, aElements) +{ + // <form id='f'></form><form><element form='foo'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'foo'); + aElements[0].setAttribute('form', 'f'); + + return [[aForms[0], aForms[1]], [[aElements[0]],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a list of ids containing one valid form, then + * it does not have a form owner. + */ +function test8(aForms, aElements) +{ + // <form id='f'></form><form><element form='f foo'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f foo'); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a form id which is valid in a case insensitive + * way, then it does not have a form owner. + */ +function test9(aForms, aElements) +{ + // <form id='f'></form><form><element form='F'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'F'); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a form id which is not a valid id, then it's + * form owner is it does not have a form owner. + */ +function test10(aForms, aElements) +{ + // <form id='F'></form><form><element form='f'></form> + aForms[0].id = 'F'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a form id which is not a valid id, then it's + * form owner is it does not have a form owner. + */ +function test11(aForms, aElements) +{ + // <form id='foo bar'></form><form><element form='foo bar'></form> + aForms[0].id = 'foo bar'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'foo bar'); + + return [[aForms[0], aForms[1]], [[aElements[0]],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id and the form id change, then + * it does not have a form owner. + */ +function test12(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aForms[0].id = 'foo'; + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to an invalid form id and the form id change to a + * valid one, then it's form owner is the form which has the id. + */ +function test13(aForms, aElements) +{ + // <form id='foo'></form><form><element form='f'></form> + aForms[0].id = 'foo'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aForms[0].id = 'f'; + + return [[aForms[0], aForms[1]], [[aElements[0]],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id and a form with the same id is + * inserted before in the tree, then it's form owner is the form which has the + * id. + */ +function test14(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aForms[2].id = 'f'; + + document.getElementById('content').insertBefore(aForms[2], aForms[0]); + + return [[aForms[0], aForms[1], aForms[2]], [[],[],[aElements[0]]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id and an element with the same id is + * inserted before in the tree, then it does not have a form owner. + */ +function test15(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aElements[1].id = 'f'; + + document.getElementById('content').insertBefore(aElements[1], aForms[0]); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form + * element and has @form set to a valid form id and the form is removed from + * the tree, then it does not have a form owner. + */ +function test16(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + aElements[1].id = 'f'; + + document.getElementById('content').removeChild(aForms[0]); + + return [[aForms[0], aForms[1]], [[],[]]]; +} + +/** + * This function test that, when an element is a descendant of a form element + * and has @form set to the empty string, it does not have a form owner. + */ +function test17(aForms, aElements) +{ + // <form><element form=''></form> + aForms[0].appendChild(aElements[0]); + aElements[0].setAttribute('form', ''); + + return [[aForms[0]], [[]]]; +} + +/** + * This function test that, when an element is a descendant of a form element + * and has @form set to the empty string, it does not have a form owner even if + * it's parent has its id equals to the empty string. + */ +function test18(aForms, aElements) +{ + // <form id=''><element form=''></form> + aForms[0].id = ''; + aForms[0].appendChild(aElements[0]); + aElements[0].setAttribute('form', ''); + + return [[aForms[0]], [[]]]; +} + +/** + * This function test that, when an element is a descendant of a form element + * and has @form set to a valid form id and the element is being moving inside + * it's parent, it's form owner will remain the form with the id. + */ +function test19(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'><element></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aForms[1].appendChild(aElements[1]); + aElements[0].setAttribute('form', 'f'); + aForms[1].appendChild(aElements[0]); + + return [[aForms[0],aForms[1]],[[aElements[0]],[aElements[1]]]]; +} + +/** + * This function test that, when an element is a descendant of a form element + * and has @form set to a valid form id and the element is being moving inside + * another form, it's form owner will remain the form with the id. + */ +function test20(aForms, aElements) +{ + // <form id='f'></form><form><element form='f'><element></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aForms[1].appendChild(aElements[1]); + aElements[0].setAttribute('form', 'f'); + aForms[2].appendChild(aElements[0]); + + return [[aForms[0],aForms[1],aForms[2]],[[aElements[0]],[aElements[1]],[]]]; +} + +/** + * This function test that when removing a form, the elements with a @form set + * will be correctly removed from there form owner. + */ +function test21(aForms, aElements) +{ + // <form id='f'><form><form><element form='f'></form> + aForms[0].id = 'f'; + aForms[1].appendChild(aElements[0]); + aElements[0].setAttribute('form', 'f'); + document.getElementById('content').removeChild(aForms[1]); + + return [[aForms[0]],[[]]]; +} + +var functions = [ + test0a, test0b, + test1, test2, test3, test4, test5, test6, test7, test8, test9, + test10, test11, test12, test13, test14, test15, test16, test17, test18, test19, + test20, test21, +]; + +// Global variable to have an easy access to <div id='content'>. +var content = document.getElementById('content'); + +// Initializing the needed elements. +var forms = [ + document.createElement('form'), + document.createElement('form'), + document.createElement('form'), +]; + +var elementNames = [ + 'button', 'fieldset', 'input', 'label', 'object', 'output', 'select', + 'textarea' +]; + +var todoElements = [ + ['keygen', 'Keygen'], +]; + +for (var e of todoElements) { + var node = document.createElement(e[0]); + var nodeString = HTMLElement.prototype.toString.apply(node); + nodeString = nodeString.replace(/Element[\] ].*/, "Element"); + todo_is(nodeString, "[object HTML" + e[1] + "Element", + e[0] + " should not be implemented"); +} + +for (var name of elementNames) { + var elements = [ + document.createElement(name), + document.createElement(name), + ]; + + for (var func of functions) { + // Clean-up. + while (content.firstChild) { + content.removeChild(content.firstChild); + } + for (form of forms) { + content.appendChild(form); + form.removeAttribute('id'); + } + for (e of elements) { + content.appendChild(e); + e.removeAttribute('form'); + is(e.form, null, "The element should not have a form owner"); + } + + // Calling the test. + var results = func(forms, elements); + + // Checking the results. + var formsList = results[0]; + for (var i=0; i<formsList.length; ++i) { + var elementsList = results[1][i]; + if (name != 'label' && name != 'meter' && name != 'progress') { + is(formsList[i].elements.length, elementsList.length, + "The form should contain " + elementsList.length + " elements"); + } + for (var j=0; j<elementsList.length; ++j) { + if (name != 'label' && name != 'meter' && name != 'progress') { + is(formsList[i].elements[j], elementsList[j], + "The form should contain " + elementsList[j]); + } + if (name != 'label') { + is(elementsList[j].form, formsList[i], + "The form owner should be the form associated to the list"); + } + } + } + } + + // Cleaning-up. + for (e of elements) { + e.parentNode.removeChild(e); + e = null; + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_form_attribute-2.html b/dom/html/test/forms/test_form_attribute-2.html new file mode 100644 index 000000000..96c706b3a --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-2.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=588683 +--> +<head> + <title>Test for form attributes 2</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a> +<p id="display"></p> +<div id="content" style="display: none"> + <form id='a'> + <form id='b'> + <input id='i' form='b'> + <script> + is(document.getElementById('i').form, document.getElementById('b'), + "While parsing, the form property should work."); + </script> + </form> + </form> + <form id='c'> + <form id='d'> + <input id='i2' form='c'> + <script> + is(document.getElementById('i2').form, document.getElementById('c'), + "While parsing, the form property should work."); + </script> + </form> + </form> + <!-- Let's tests without @form --> + <form id='e'> + <form id='f'> + <input id='i3'> + <script> + // bug 589073 + todo_is(document.getElementById('i3').form, document.getElementById('f'), + "While parsing, the form property should work."); + </script> + </form> + </form> + <form id='g'> + <input id='i4'> + <script> + is(document.getElementById('i4').form, document.getElementById('g'), + "While parsing, the form property should work."); + </script> + </form> +</div> +</body> +</html> diff --git a/dom/html/test/forms/test_form_attribute-3.html b/dom/html/test/forms/test_form_attribute-3.html new file mode 100644 index 000000000..a8d4fabef --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-3.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=588683 +--> +<head> + <title>Test for form attributes 3</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a> +<p id="display"></p> +<div id="content"> + <form id='f'> + <input name='e1'> + </form> + <form id='f2'> + <input name='e2'> + <input id='i3' form='f' + onfocus="var catched=false; + try { e1; } catch(e) { catched=true; } + ok(!catched, 'e1 should be in the scope of i3'); + catched = false; + try { e2; } catch(e) { catched=true; } + ok(catched, 'e2 should not be in the scope of i3'); + document.getElementById('i4').focus();" + > + <input id='i4' form='f2' + onfocus="var catched=false; + try { e2; } catch(e) { catched=true; } + ok(!catched, 'e2 should be in the scope of i4'); + document.getElementById('i5').focus();" + > + <input id='i5' + onfocus="var catched=false; + try { e2; } catch(e) { catched=true; } + ok(!catched, 'e2 should be in the scope of i5'); + document.getElementById('i6').focus();" + > + </form> + <input id='i6' form='f' + onfocus="var catched=false; + try { e1; } catch(e) { catched=true; } + ok(!catched, 'e1 should be in the scope of i6'); + document.getElementById('i7').focus();" + > + <input id='i7' form='f2' + onfocus="var catched=false; + try { e2; } catch(e) { catched=true; } + ok(!catched, 'e2 should be in the scope of i7'); + this.blur(); + SimpleTest.finish();" + > +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for form attributes 3 **/ + +SimpleTest.waitForExplicitFinish(); + +document.getElementById('i3').focus(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_form_attribute-4.html b/dom/html/test/forms/test_form_attribute-4.html new file mode 100644 index 000000000..67484f72e --- /dev/null +++ b/dom/html/test/forms/test_form_attribute-4.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=588683 +--> +<head> + <title>Test for form attributes 4</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a> +<p id="display"></p> +<div id="content" style='display:none;'> + <form id='f'> + </form> + <table id='t'> + <form id='f2'> + <tr><td><input id='i1'></td></tr> + <tr><td><input id='i2' form='f'></td></tr> + </form> + </table> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for form attributes 4 **/ + +var table = document.getElementById('t'); +var i1 = document.getElementById('i1'); +var i2 = document.getElementById('i2'); + +is(i1.form, document.getElementById('f2'), + "i1 form should be it's parent"); +is(i2.form, document.getElementById('f'), + "i1 form should be the form with the id in @form"); + +table.removeChild(document.getElementById('f2')); +is(i1, document.getElementById('i1'), + "i1 should still be in the document"); +is(i1.form, null, "i1 should not have any form owner"); +is(i2.form, document.getElementById('f'), + "i1 form should be the form with the id in @form"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_form_attributes_reflection.html b/dom/html/test/forms/test_form_attributes_reflection.html new file mode 100644 index 000000000..0c64ac4ea --- /dev/null +++ b/dom/html/test/forms/test_form_attributes_reflection.html @@ -0,0 +1,88 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLFormElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLFormElement attributes reflection **/ + +// .acceptCharset +reflectString({ + element: document.createElement("form"), + attribute: { idl: "acceptCharset", content: "accept-charset" }, + otherValues: [ "ISO-8859-1", "UTF-8" ], +}); + +// TODO: action (URL). But note that we currently reflect it weirdly; see +// dom/html/test/test_bug607145.html + +// .autocomplete +reflectLimitedEnumerated({ + element: document.createElement("form"), + attribute: "autocomplete", + validValues: [ "on", "off" ], + invalidValues: [ "", "foo", "tulip", "default" ], + defaultValue: "on", +}); + +// .enctype +reflectLimitedEnumerated({ + element: document.createElement("form"), + attribute: "enctype", + validValues: [ "application/x-www-form-urlencoded", "multipart/form-data", + "text/plain" ], + invalidValues: [ "", "foo", "tulip", "multipart/foo" ], + defaultValue: "application/x-www-form-urlencoded" +}); + +// .encoding +reflectLimitedEnumerated({ + element: document.createElement("form"), + attribute: { idl: "encoding", content: "enctype" }, + validValues: [ "application/x-www-form-urlencoded", "multipart/form-data", + "text/plain" ], + invalidValues: [ "", "foo", "tulip", "multipart/foo" ], + defaultValue: "application/x-www-form-urlencoded" +}); + +// .method +reflectLimitedEnumerated({ + element: document.createElement("form"), + attribute: "method", + validValues: [ "get", "post" ], + invalidValues: [ "", "foo", "tulip" ], + defaultValue: "get" +}); + +// .name +reflectString({ + element: document.createElement("form"), + attribute: "name", +}); + +// .noValidate +reflectBoolean({ + element: document.createElement("form"), + attribute: "noValidate", +}); + +// .target +reflectString({ + element: document.createElement("form"), + attribute: "target", + otherValues: [ "_blank", "_self", "_parent", "_top" ], +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_form_named_getter_dynamic.html b/dom/html/test/forms/test_form_named_getter_dynamic.html new file mode 100644 index 000000000..4a1976845 --- /dev/null +++ b/dom/html/test/forms/test_form_named_getter_dynamic.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=377413
+-->
+<head>
+ <title>Test for Bug 377413</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <link rel='stylesheet' href='/resources/testharness.css'>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377413">Mozilla Bug 377413</a>
+<p id="log"></p>
+<div id="content">
+ <form>
+ <table>
+ <tbody>
+ </tbody>
+ </table>
+ </form>
+</div>
+
+<script type="text/javascript">
+
+/** Tests for Bug 377413 **/
+var tb = document.getElementsByTagName('tbody')[0];
+
+test(function(){
+ tb.innerHTML = '<tr><td><input name="fooboo"></td></tr>';
+ document.forms[0].fooboo.value = 'testme';
+ document.getElementsByTagName('table')[0].deleteRow(0);
+ assert_equals(document.forms[0].fooboo, undefined);
+}, "no element reference after deleting it with deleteRow()");
+
+test(function(){
+ var b = tb.appendChild(document.createElement('tr')).appendChild(document.createElement('td')).appendChild(document.createElement('button'));
+ b.name = b.value = 'boofoo';
+ assert_equals(document.forms[0].elements[0].value, 'boofoo');
+}, 'element value set correctly');
+
+test(function(){
+ assert_true('boofoo' in document.forms[0]);
+}, 'element name has created property on form');
+
+test(function(){
+ tb.innerHTML = '';
+ assert_false('boofoo' in document.forms[0]);
+}, "no element reference after deleting it by setting innerHTML");
+
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_formaction_attribute.html b/dom/html/test/forms/test_formaction_attribute.html new file mode 100644 index 000000000..24af8b2db --- /dev/null +++ b/dom/html/test/forms/test_formaction_attribute.html @@ -0,0 +1,176 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=566160 +--> +<head> + <title>Test for Bug 566160</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a> +<p id="display"></p> +<style> + iframe { width: 130px; height: 100px;} +</style> +<iframe name='frame1' id='frame1'></iframe> +<iframe name='frame2' id='frame2'></iframe> +<iframe name='frame3' id='frame3'></iframe> +<iframe name='frame3bis' id='frame3bis'></iframe> +<iframe name='frame4' id='frame4'></iframe> +<iframe name='frame5' id='frame5'></iframe> +<iframe name='frame6' id='frame6'></iframe> +<iframe name='frame7' id='frame7'></iframe> +<div id="content"> + <!-- submit controls with formaction that are validated with a CLICK --> + <form target="frame1" action="data:text/html,FAIL" method="GET"> + <input name='foo' value='foo'> + <input type='submit' id='is' formaction="data:text/html,"> + </form> + <form target="frame2" action="data:text/html,FAIL" method="GET"> + <input name='bar' value='bar'> + <input type='image' id='ii' formaction="data:text/html,"> + </form> + <form target="frame3" action="data:text/html,FAIL" method="GET"> + <input name='tulip' value='tulip'> + <button type='submit' id='bs' formaction="data:text/html,">submit</button> + </form> + <form target="frame3bis" action="data:text/html,FAIL" method="GET"> + <input name='tulipbis' value='tulipbis'> + <button type='submit' id='bsbis' formaction="data:text/html,">submit</button> + </form> + + <!-- submit controls with formaction that are validated with ENTER --> + <form target="frame4" action="data:text/html,FAIL" method="GET"> + <input name='footulip' value='footulip'> + <input type='submit' id='is2' formaction="data:text/html,"> + </form> + <form target="frame5" action="data:text/html,FAIL" method="GET"> + <input name='foobar' value='foobar'> + <input type='image' id='ii2' formaction="data:text/html,"> + </form> + <form target="frame6" action="data:text/html,FAIL" method="GET"> + <input name='tulip2' value='tulip2'> + <button type='submit' id='bs2' formaction="data:text/html,">submit</button> + </form> + + <!-- check that when submitting a from from an element + which is not a submit control, @formaction isn't used --> + <form target='frame7' action="data:text/html," method="GET"> + <input id='enter' name='input' value='enter' formaction="data:text/html,FAIL"> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 566160 **/ + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + +var gTestResults = { + frame1: "data:text/html,?foo=foo", + frame2: "data:text/html,?bar=bar&x=0&y=0", + frame3: "data:text/html,?tulip=tulip", + frame3bis: "data:text/html,?tulipbis=tulipbis", + frame4: "data:text/html,?footulip=footulip", + frame5: "data:text/html,?foobar=foobar&x=0&y=0", + frame6: "data:text/html,?tulip2=tulip2", + frame7: "data:text/html,?input=enter", +}; + +var gPendingLoad = 0; // Has to be set after depending on the frames number. + +function runTests() +{ + // We add a load event for the frames which will be called when the forms + // will be submitted. + var frames = [ document.getElementById('frame1'), + document.getElementById('frame2'), + document.getElementById('frame3'), + document.getElementById('frame3bis'), + document.getElementById('frame4'), + document.getElementById('frame5'), + document.getElementById('frame6'), + document.getElementById('frame7'), + ]; + gPendingLoad = frames.length; + + for (var i=0; i<frames.length; i++) { + frames[i].setAttribute('onload', "frameLoaded(this);"); + } + + /** + * We are going to focus each element before interacting with either for + * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or + * using .click(). This because it may be needed (ENTER) and because we want + * to have the element visible in the iframe. + * + * Focusing the first element (id='is') is launching the tests. + */ + document.getElementById('is').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('is'), 5, 5, {}); + document.getElementById('ii').focus(); + }, false); + + document.getElementById('ii').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('ii'), 5, 5, {}); + document.getElementById('bs').focus(); + }, false); + + document.getElementById('bs').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('bs'), 5, 5, {}); + document.getElementById('bsbis').focus(); + }, false); + + document.getElementById('bsbis').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + document.getElementById('bsbis').click(); + document.getElementById('is2').focus(); + }, false); + + document.getElementById('is2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('ii2').focus(); + }, false); + + document.getElementById('ii2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('bs2').focus(); + }, false); + + document.getElementById('bs2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('enter').focus(); + }, false); + + document.getElementById('enter').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + }, false); + + document.getElementById('is').focus(); +} + +function frameLoaded(aFrame) { + // Check if formaction/action has the correct behavior. + is(aFrame.contentWindow.location.href, gTestResults[aFrame.name], + "the action attribute doesn't have the correct behavior"); + + if (--gPendingLoad == 0) { + SimpleTest.finish(); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_formnovalidate_attribute.html b/dom/html/test/forms/test_formnovalidate_attribute.html new file mode 100644 index 000000000..067060a5c --- /dev/null +++ b/dom/html/test/forms/test_formnovalidate_attribute.html @@ -0,0 +1,142 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=589696 +--> +<head> + <title>Test for Bug 589696</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=589696">Mozilla Bug 589696</a> +<p id="display"></p> +<iframe style='width:50px; height: 50px;' name='t'></iframe> +<div id="content"> + <!-- Next forms should not submit because formnovalidate isn't set on the + element used for the submission. --> + <form target='t' action='data:text/html,'> + <input id='av' required> + <input type='submit' formnovalidate> + <input id='a' type='submit'> + </form> + <form target='t' action='data:text/html,'> + <input id='bv' type='checkbox' required> + <button type='submit' formnovalidate></button> + <button id='b' type='submit'></button> + </form> + <!-- Next form should not submit because formnovalidate only applies for + submit controls. --> + <form target='t' action='data:text/html,'> + <input id='c' required formnovalidate> + </form> + <!--- Next forms should submit without any validation check. --> + <form target='t' action='data:text/html,'> + <input id='dv' required> + <input id='d' type='submit' formnovalidate> + </form> + <form target='t' action='data:text/html,'> + <input id='ev' type='checkbox' required> + <button id='e' type='submit' formnovalidate></button> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 589696 **/ + +var os = SpecialPowers.Cc['@mozilla.org/observer-service;1'] + .getService(SpecialPowers.Ci.nsIObserverService); +var observers = os.enumerateObservers("invalidformsubmit"); + +/** + * formnovalidate should prevent form validation if set on the submit control + * used to submit the form. + * + * The following test should not be done if there is no observer for + * "invalidformsubmit" because the form submission will not be canceled in that + * case. + */ + +if (observers.hasMoreElements()) { + document.getElementById('av').addEventListener("invalid", function(aEvent) { + aEvent.target.removeAttribute("invalid", arguments.callee, false); + ok(true, "formnovalidate should not apply on if not set on the submit " + + "control used for the submission"); + document.getElementById('b').click(); + }, false); + + document.getElementById('bv').addEventListener("invalid", function(aEvent) { + aEvent.target.removeAttribute("invalid", arguments.callee, false); + ok(true, "formnovalidate should not apply on if not set on the submit " + + "control used for the submission"); + var c = document.getElementById('c'); + c.focus(); + synthesizeKey("KEY_Enter", { code: "Enter" }); + }, false); + + document.getElementById('c').addEventListener("invalid", function(aEvent) { + aEvent.target.removeAttribute("invalid", arguments.callee, false); + ok(true, "formnovalidate should only apply on submit controls"); + document.getElementById('d').click(); + }, false); + + document.forms[3].addEventListener("submit", function(aEvent) { + aEvent.target.removeAttribute("submit", arguments.callee, false); + ok(true, "formnovalidate applies if set on the submit control used for the submission"); + document.getElementById('e').click(); + }, false); + + document.forms[4].addEventListener("submit", function(aEvent) { + aEvent.target.removeAttribute("submit", arguments.callee, false); + ok(true, "formnovalidate applies if set on the submit control used for the submission"); + SimpleTest.executeSoon(SimpleTest.finish); + }, false); + + /** + * We have to be sure invalid events behave as expected. + * They should be sent before the submit event so we can just create a test + * failure if we got one when unexpected. All of them should be caught if + * sent. + * At worst, we got random green which isn't harmful. + * If expected, they will be part of the chain reaction. + */ + function unexpectedInvalid(aEvent) + { + aEvent.target.removeAttribute("invalid", unexpectedInvalid, false); + ok(false, "invalid event should not be sent"); + } + + document.getElementById('dv').addEventListener("invalid", unexpectedInvalid, false); + document.getElementById('ev').addEventListener("invalid", unexpectedInvalid, false); + + /** + * Some submission have to be canceled. In that case, the submit events should + * not be sent. + * Same behavior as unexpected invalid events. + */ + function unexpectedSubmit(aEvent) + { + aEvent.target.removeAttribute("submit", unexpectedSubmit, false); + ok(false, "submit event should not be sent"); + } + + document.forms[0].addEventListener("submit", unexpectedSubmit, false); + document.forms[1].addEventListener("submit", unexpectedSubmit, false); + document.forms[2].addEventListener("submit", unexpectedSubmit, false); + + SimpleTest.waitForExplicitFinish(); + + // This is going to call all the tests (with a chain reaction). + SimpleTest.waitForFocus(function() { + document.getElementById('a').click(); + }); +} else { + todo(false, "No 'invalidformsubmit' observers. Skip test."); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_attributes_reflection.html b/dom/html/test/forms/test_input_attributes_reflection.html new file mode 100644 index 000000000..6a0eaf225 --- /dev/null +++ b/dom/html/test/forms/test_input_attributes_reflection.html @@ -0,0 +1,275 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLInputElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLInputElement attributes reflection **/ + +// TODO: maybe make those reflections be tested against all input types. + +function testWidthHeight(attr) { + var element = document.createElement('input'); + is(element[attr], 0, attr + ' always returns 0 if not type=image'); + element.setAttribute(attr, '42'); + is(element[attr], 0, attr + ' always returns 0 if not type=image'); + is(element.getAttribute(attr), '42'); + element[attr] = 0; + is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute'); + element[attr] = 12; + is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute'); + + element.removeAttribute(attr); + is(element.getAttribute(attr), null); + + element = document.createElement('input'); + element.type = 'image'; + document.getElementById('content').appendChild(element); + isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image'); + + element.setAttribute(attr, '42'); + isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image'); + isnot(element[attr], 42, attr + ' represents the dimension of the element if type=image'); + is(element.getAttribute(attr), '42'); + element[attr] = 0; + is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute'); + element[attr] = 12; + is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute'); + + element.removeAttribute(attr); + is(element.getAttribute(attr), null); +} + +// .accept +reflectString({ + element: document.createElement("input"), + attribute: "accept", + otherValues: [ "audio/*", "video/*", "image/*", "image/png", + "application/msword", "appplication/pdf" ], +}); + +// .alt +reflectString({ + element: document.createElement("input"), + attribute: "alt", +}); + +// .autocomplete +reflectLimitedEnumerated({ + element: document.createElement("input"), + attribute: "autocomplete", + validValues: [ "on", "off" ], + invalidValues: [ "", "default", "foo", "tulip" ], +}); + +// .autofocus +reflectBoolean({ + element: document.createElement("input"), + attribute: "autofocus", +}); + +// .defaultChecked +reflectBoolean({ + element: document.createElement("input"), + attribute: { idl: "defaultChecked", content: "checked" }, +}); + +// .checked doesn't reflect a content attribute. + +// .dirName +todo("dirName" in document.createElement("input"), + "dirName isn't implemented yet"); + +// .disabled +reflectBoolean({ + element: document.createElement("input"), + attribute: "disabled", +}); + +// TODO: form (HTMLFormElement) +// TODO: files (FileList) +// TODO: formAction (URL). But note that we currently reflect it weirdly; see +// dom/html/test/test_bug607145.html + +// .formEnctype +reflectLimitedEnumerated({ + element: document.createElement("input"), + attribute: "formEnctype", + validValues: [ "application/x-www-form-urlencoded", "multipart/form-data", + "text/plain" ], + invalidValues: [ "", "foo", "tulip", "multipart/foo" ], + defaultValue: { invalid: "application/x-www-form-urlencoded", missing: "" } +}); + +// .formMethod +reflectLimitedEnumerated({ + element: document.createElement("input"), + attribute: "formMethod", + validValues: [ "get", "post" ], + invalidValues: [ "", "foo", "tulip" ], + defaultValue: { invalid: "get", missing: "" } +}); + +// .formNoValidate +reflectBoolean({ + element: document.createElement("input"), + attribute: "formNoValidate", +}); + +// .formTarget +reflectString({ + element: document.createElement("input"), + attribute: "formTarget", + otherValues: [ "_blank", "_self", "_parent", "_top" ], +}); + +// .height +testWidthHeight('height'); + +// .indeterminate doesn't reflect a content attribute. + +// .inputmode +if (SpecialPowers.getBoolPref("dom.forms.inputmode")) { +reflectLimitedEnumerated({ + element: document.createElement("input"), + attribute: "inputMode", + validValues: [ "numeric", "digit", "uppercase", "lowercase", "titlecase", "autocapitalized", "auto" ], + invalidValues: [ "", "foo", "tulip" ], + defaultValue: "auto" +}); +} + +// TODO: list (HTMLElement) + +// .max +reflectString({ + element: document.createElement('input'), + attribute: 'max', +}); + +// .maxLength +reflectInt({ + element: document.createElement("input"), + attribute: "maxLength", + nonNegative: true, +}); + +// .min +reflectString({ + element: document.createElement('input'), + attribute: 'min', +}); + +// .multiple +reflectBoolean({ + element: document.createElement("input"), + attribute: "multiple", +}); + +// .name +reflectString({ + element: document.createElement("input"), + attribute: "name", + otherValues: [ "isindex", "_charset_" ], +}); + +// .pattern +reflectString({ + element: document.createElement("input"), + attribute: "pattern", + otherValues: [ "[0-9][A-Z]{3}" ], +}); + +// .placeholder +reflectString({ + element: document.createElement("input"), + attribute: "placeholder", + otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ], +}); + +// .readOnly +reflectBoolean({ + element: document.createElement("input"), + attribute: "readOnly", +}); + +// .required +reflectBoolean({ + element: document.createElement("input"), + attribute: "required", +}); + +// .size +reflectUnsignedInt({ + element: document.createElement("input"), + attribute: "size", + nonZero: true, + defaultValue: 20, +}); + +// .src (URL) +reflectURL({ + element: document.createElement('input'), + attribute: 'src', +}); + +// .step +reflectString({ + element: document.createElement('input'), + attribute: 'step', +}); + +// .type +reflectLimitedEnumerated({ + element: document.createElement("input"), + attribute: "type", + validValues: [ "hidden", "text", "search", "tel", "url", "email", "password", + "checkbox", "radio", "file", "submit", "image", "reset", + "button", "date", "time", "number", "range", "color", "month", + "week", "datetime-local" ], + invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ], + defaultValue: "text" +}); + +// .defaultValue +reflectString({ + element: document.createElement("input"), + attribute: { idl: "defaultValue", content: "value" }, + otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ], +}); + +// .value doesn't reflect a content attribute. + +// .valueAsDate +is("valueAsDate" in document.createElement("input"), true, + "valueAsDate should be available"); + +// Deeper check will be done with bug 763305. +is('valueAsNumber' in document.createElement("input"), true, + "valueAsNumber should be available"); + +// .selectedOption +todo("selectedOption" in document.createElement("input"), + "selectedOption isn't implemented yet"); + +// .width +testWidthHeight('width'); + +// .willValidate doesn't reflect a content attribute. +// .validity doesn't reflect a content attribute. +// .validationMessage doesn't reflect a content attribute. +// .labels doesn't reflect a content attribute. + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_autocomplete.html b/dom/html/test/forms/test_input_autocomplete.html new file mode 100644 index 000000000..2aaeac020 --- /dev/null +++ b/dom/html/test/forms/test_input_autocomplete.html @@ -0,0 +1,106 @@ +<!DOCTYPE html> +<html> +<!-- +Test @autocomplete on <input> +--> +<head> + <title>Test for <input autocomplete='…'></title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +<script> +"use strict"; + +var values = [ + // @autocomplete content attribute, expected IDL attribute value + + // Missing or empty attribute + [undefined, ""], + ["", ""], + + // One token + ["on", "on"], + ["On", "on"], + ["off", "off"], + ["OFF", "off"], + ["username", "username"], + [" username ", "username"], + ["foobar", ""], + + // Two tokens + ["on off", ""], + ["off on", ""], + ["username tel", ""], + ["tel username ", ""], + [" username tel ", ""], + ["tel mobile", ""], + ["tel shipping", ""], + ["shipping tel", "shipping tel"], + ["shipPING tel", "shipping tel"], + ["mobile tel", "mobile tel"], + [" MoBiLe TeL ", "mobile tel"], + ["XXX tel", ""], + ["XXX username", ""], + + // Three tokens + ["billing invalid tel", ""], + ["___ mobile tel", ""], + ["mobile foo tel", ""], + ["mobile tel foo", ""], + ["tel mobile billing", ""], + ["billing mobile tel", "billing mobile tel"], + [" BILLing MoBiLE tEl ", "billing mobile tel"], + ["billing home tel", "billing home tel"], + + // Four tokens (invalid) + ["billing billing mobile tel", ""], + + // Five tokens (invalid) + ["billing billing billing mobile tel", ""], +]; + +var types = [undefined, "hidden", "text", "search"]; // Valid types for all non-multiline hints. + +function checkAutocompleteValues(field, type) { + for (var test of values) { + if (typeof(test[0]) === "undefined") + field.removeAttribute("autocomplete"); + else + field.setAttribute("autocomplete", test[0]); + is(field.autocomplete, test[1], "Checking @autocomplete for @type=" + type + " of: " + test[0]); + is(field.autocomplete, test[1], "Checking cached @autocomplete for @type=" + type + " of: " + test[0]); + } +} + +function start() { + var inputField = document.getElementById("input-field"); + for (var type of types) { + // Switch the input type + if (typeof(type) === "undefined") + inputField.removeAttribute("type"); + else + inputField.type = type; + checkAutocompleteValues(inputField, type || ""); + } + + var selectField = document.getElementById("select-field"); + checkAutocompleteValues(selectField, "select"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.experimental", true]]}, start); +</script> +</head> + +<body> +<p id="display"></p> +<div id="content" style="display: none"> + <form> + <input id="input-field" /> + <select id="select-field" /> + </form> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_color_input_change_events.html b/dom/html/test/forms/test_input_color_input_change_events.html new file mode 100644 index 000000000..d9e7558f8 --- /dev/null +++ b/dom/html/test/forms/test_input_color_input_change_events.html @@ -0,0 +1,120 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=885996 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1234567</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript;version=1.8"> + + /** Test that update() modifies the element value such as done() when it is + * not called as a concellation. + */ + + SimpleTest.waitForExplicitFinish(); + + var MockColorPicker = SpecialPowers.MockColorPicker; + + var test = runTest(); + + SimpleTest.waitForFocus(function() { + test.next(); + }); + + function runTest() { + MockColorPicker.init(window); + var element = null; + + MockColorPicker.showCallback = function(picker, update) { + is(picker.initialColor, element.value); + + var inputEvent = false; + var changeEvent = false; + element.oninput = function() { + inputEvent = true; + }; + element.onchange = function() { + changeEvent = true; + }; + + if (element.dataset.type == 'update') { + update('#f00ba4'); + + is(inputEvent, true, 'input event should have been received'); + is(changeEvent, false, 'change event should not have been received'); + + inputEvent = changeEvent = false; + + is(element.value, '#f00ba4'); + + MockColorPicker.returnColor = '#f00ba7'; + isnot(element.value, MockColorPicker.returnColor); + } else if (element.dataset.type == 'cancel') { + MockColorPicker.returnColor = '#bababa'; + isnot(element.value, MockColorPicker.returnColor); + } else if (element.dataset.type == 'done') { + MockColorPicker.returnColor = '#098766'; + isnot(element.value, MockColorPicker.returnColor); + } else if (element.dataset.type == 'noop-done') { + MockColorPicker.returnColor = element.value; + is(element.value, MockColorPicker.returnColor); + } + + SimpleTest.executeSoon(function() { + if (element.dataset.type == 'cancel') { + isnot(element.value, MockColorPicker.returnColor); + is(inputEvent, false, 'no input event should have been sent'); + is(changeEvent, false, 'no change event should have been sent'); + } else if (element.dataset.type == 'noop-done') { + is(element.value, MockColorPicker.returnColor); + is(inputEvent, false, 'no input event should have been sent'); + is(changeEvent, false, 'no change event should have been sent'); + } else { + is(element.value, MockColorPicker.returnColor); + is(inputEvent, true, 'input event should have been sent'); + is(changeEvent, true, 'change event should have been sent'); + } + + changeEvent = false; + element.blur(); + + setTimeout(function() { + is(changeEvent, false, "change event should not be fired on blur"); + test.next(); + }); + }); + + return element.dataset.type == 'cancel' ? "" : MockColorPicker.returnColor; + }; + + for (var i = 0; i < document.getElementsByTagName('input').length; ++i) { + element = document.getElementsByTagName('input')[i]; + element.focus(); + synthesizeMouseAtCenter(element, {}); + yield undefined; + }; + + MockColorPicker.cleanup(); + SimpleTest.finish(); + yield undefined; + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a> +<p id="display"></p> +<div id="content"> + <input type='color' data-type='update'> + <input type='color' data-type='cancel'> + <input type='color' data-type='done'> + <input type='color' data-type='noop-done'> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_color_picker_initial.html b/dom/html/test/forms/test_input_color_picker_initial.html new file mode 100644 index 000000000..4b6a45cbb --- /dev/null +++ b/dom/html/test/forms/test_input_color_picker_initial.html @@ -0,0 +1,79 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=885996 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1234567</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript;version=1.8"> + + /** Test that the initial value of the nsIColorPicker is the current value of + the <input type='color'> element. **/ + + SimpleTest.waitForExplicitFinish(); + + var MockColorPicker = SpecialPowers.MockColorPicker; + + var test = runTest(); + + SimpleTest.waitForFocus(function() { + test.next(); + }); + + function runTest() { + MockColorPicker.init(window); + var element = null; + + MockColorPicker.showCallback = function(picker) { + is(picker.initialColor, element.value); + SimpleTest.executeSoon(function() { + test.next(); + }); + return ""; + }; + + for (var i = 0; i < document.getElementsByTagName('input').length; ++i) { + element = document.getElementsByTagName('input')[i]; + if (element.parentElement.id === 'dynamic-values') { + element.value = '#deadbe'; + } + synthesizeMouseAtCenter(element, {}); + yield undefined; + }; + + MockColorPicker.cleanup(); + SimpleTest.finish(); + yield undefined; + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a> +<p id="display"></p> +<div id="content"> + <div id='valid-values'> + <input type='color' value='#ff00ff'> + <input type='color' value='#ab3275'> + <input type='color' value='#abcdef'> + <input type='color' value='#ABCDEF'> + </div> + <div id='invalid-values'> + <input type='color' value='ffffff'> + <input type='color' value='#abcdez'> + <input type='color' value='#0123456'> + </div> + <div id='dynamic-values'> + <input type='color' value='#ab4594'> + <input type='color' value='#984534'> + <input type='color' value='#f8b9a0'> + </div> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_color_picker_popup.html b/dom/html/test/forms/test_input_color_picker_popup.html new file mode 100644 index 000000000..239f14014 --- /dev/null +++ b/dom/html/test/forms/test_input_color_picker_popup.html @@ -0,0 +1,140 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=885996 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1234567</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> body { font-family: serif } </style> + <script type="application/javascript;version=1.8"> + + /** Test the behaviour of the <input type='color'> when clicking on it from + different ways. **/ + + SimpleTest.waitForExplicitFinish(); + + var MockColorPicker = SpecialPowers.MockColorPicker; + + var test = runTest(); + var testData = [ + { id: 'normal', result: true }, + { id: 'hidden', result: false }, + { id: 'normal', type: 'untrusted', result: true }, + { id: 'normal', type: 'prevent-default-1', result: false }, + { id: 'normal', type: 'prevent-default-2', result: false }, + { id: 'normal', type: 'click-method', result: true }, + { id: 'normal', type: 'right-click', result: false }, + { id: 'normal', type: 'middle-click', result: false }, + { id: 'label-1', result: true }, + { id: 'label-2', result: true }, + { id: 'label-3', result: true }, + { id: 'label-4', result: true }, + { id: 'button-click', result: true }, + { id: 'button-down', result: true }, + { id: 'button-up', result: true }, + { id: 'div-click', result: true }, + { id: 'div-click-on-demand', result: true }, + ]; + var currentTest = null; + + SimpleTest.waitForFocus(function() { + test.next(); + }); + + function runTest() { + MockColorPicker.init(window); + var element = null; + + MockColorPicker.showCallback = function(picker) { + ok(currentTest.result); + SimpleTest.executeSoon(function() { + test.next(); + }); + return ""; + }; + + while (testData.length != 0) { + var currentTest = testData.shift(); + element = document.getElementById(currentTest.id); + + // To make sure we can actually click on the element. + element.focus(); + + switch (currentTest.type) { + case 'untrusted': + var e = document.createEvent('MouseEvents'); + e.initEvent('click', true, false); + document.getElementById(element.dispatchEvent(e)); + break; + case 'prevent-default-1': + element.onclick = function() { + return false; + }; + element.click(); + element.onclick = function() {}; + break; + case 'prevent-default-2': + element.onclick = function(e) { + e.preventDefault(); + }; + element.click(); + element.onclick = function() {}; + break; + case 'click-method': + element.click(); + break; + case 'right-click': + synthesizeMouseAtCenter(element, { button: 2 }); + break; + case 'middle-click': + synthesizeMouseAtCenter(element, { button: 1 }); + break; + default: + synthesizeMouseAtCenter(element, {}); + } + + if (!currentTest.result) { + setTimeout(function() { + setTimeout(function() { + ok(true); + SimpleTest.executeSoon(function() { + test.next(); + }); + }); + }); + } + yield undefined; + }; + + MockColorPicker.cleanup(); + SimpleTest.finish(); + yield undefined; + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a> +<p id="display"></p> +<div id="content"> + <input type='color' id='normal'> + <input type='color' id='hidden' hidden> + <label id='label-1'>foo<input type='color'></label> + <label id='label-2' for='labeled-2'>foo</label><input id='labeled-2' type='color'></label> + <label id='label-3'>foo<input type='color'></label> + <label id='label-4' for='labeled-4'>foo</label><input id='labeled-4' type='color'></label> + <input id='by-button' type='color'> + <button id='button-click' onclick="document.getElementById('by-button').click();">click</button> + <button id='button-down' onclick="document.getElementById('by-button').click();">click</button> + <button id='button-up' onclick="document.getElementById('by-button').click();">click</button> + <div id='div-click' onclick="document.getElementById('by-button').click();">click</div> + <div id='div-click-on-demand' onclick="var i=document.createElement('input'); i.type='color'; i.click();">click</div> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_color_picker_update.html b/dom/html/test/forms/test_input_color_picker_update.html new file mode 100644 index 000000000..c40791323 --- /dev/null +++ b/dom/html/test/forms/test_input_color_picker_update.html @@ -0,0 +1,87 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=885996 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1234567</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> body { font-family: serif } </style> + <script type="application/javascript;version=1.8"> + + /** Test that update() modifies the element value such as done() when it is + * not called as a concellation. + */ + + SimpleTest.waitForExplicitFinish(); + + var MockColorPicker = SpecialPowers.MockColorPicker; + + var test = runTest(); + + SimpleTest.waitForFocus(function() { + test.next(); + }); + + function runTest() { + MockColorPicker.init(window); + var element = null; + + MockColorPicker.showCallback = function(picker, update) { + is(picker.initialColor, element.value); + + if (element.dataset.type == 'update') { + update('#f00ba4'); + is(element.value, '#f00ba4'); + + MockColorPicker.returnColor = '#f00ba7'; + isnot(element.value, MockColorPicker.returnColor); + } else if (element.dataset.type == 'cancel') { + MockColorPicker.returnColor = '#bababa'; + isnot(element.value, MockColorPicker.returnColor); + } else if (element.dataset.type == 'done') { + MockColorPicker.returnColor = '#098766'; + isnot(element.value, MockColorPicker.returnColor); + } + + SimpleTest.executeSoon(function() { + if (element.dataset.type == 'cancel') { + isnot(element.value, MockColorPicker.returnColor); + } else { + is(element.value, MockColorPicker.returnColor); + } + + test.next(); + }); + + return element.dataset.type == 'cancel' ? "" : MockColorPicker.returnColor; + }; + + for (var i = 0; i < document.getElementsByTagName('input').length; ++i) { + element = document.getElementsByTagName('input')[i]; + synthesizeMouseAtCenter(element, {}); + yield undefined; + }; + + MockColorPicker.cleanup(); + SimpleTest.finish(); + yield undefined; + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a> +<p id="display"></p> +<div id="content"> + <input type='color' data-type='update'> + <input type='color' data-type='cancel'> + <input type='color' data-type='done'> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_datetime_focus_blur.html b/dom/html/test/forms/test_input_datetime_focus_blur.html new file mode 100644 index 000000000..5b8d95b25 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_focus_blur.html @@ -0,0 +1,58 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1288591 +--> +<head> + <title>Test focus/blur behaviour for <input type='time'></title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a> +<p id="display"></p> +<div id="content"> + <input id="input" type="time"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 1288591. + * This test checks whether date/time input types' .focus()/.blur() works + * correctly. This test also checks when focusing on an date/time input element, + * the focus is redirected to the anonymous text control, but the + * document.activeElement still returns date/time input element. + **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(); + SimpleTest.finish(); +}); + +function test() { + let time = document.getElementById("input"); + time.focus(); + + // The active element returns the input type=time. + let activeElement = document.activeElement; + is(activeElement, time, "activeElement should be the time element"); + is(activeElement.localName, "input", "activeElement should be an input element"); + is(activeElement.type, "time", "activeElement should be of type time"); + + // Use FocusManager to check that the actual focus is on the anonymous + // text control. + let fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"] + .getService(SpecialPowers.Ci.nsIFocusManager); + let focusedElement = fm.focusedElement; + is(focusedElement.localName, "input", "focusedElement should be an input element"); + is(focusedElement.type, "text", "focusedElement should be of type text"); + + time.blur(); + isnot(document.activeElement, time, "activeElement should no longer be the time element"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_datetime_tabindex.html b/dom/html/test/forms/test_input_datetime_tabindex.html new file mode 100644 index 000000000..fb7c9b2f1 --- /dev/null +++ b/dom/html/test/forms/test_input_datetime_tabindex.html @@ -0,0 +1,72 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1288591 +--> +<head> + <title>Test tabindex attribute for <input type='time'></title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a> +<p id="display"></p> +<div id="content"> + <input id="time1" type="time" tabindex="0"> + <input id="time2" type="time" tabindex="-1"> + <input id="time3" type="time" tabindex="0"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 1288591. + * This test checks whether date/time input types' tabindex attribute works + * correctly. + **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(); + SimpleTest.finish(); +}); + +function test() { + let time1 = document.getElementById("time1"); + let time2 = document.getElementById("time2"); + let time3 = document.getElementById("time3"); + + time1.focus(); + is(document.activeElement, time1, + "input element with tabindex=0 is focusable"); + + // Advance to time1 minute field + synthesizeKey("VK_TAB", {}); + is(document.activeElement, time1, + "input element with tabindex=0 is tabbable"); + + // Advance to time1 AM/PM field + synthesizeKey("VK_TAB", {}); + is(document.activeElement, time1, + "input element with tabindex=0 is tabbable"); + + // Advance to next element + synthesizeKey("VK_TAB", {}); + is(document.activeElement, time3, + "input element with tabindex=-1 is not tabbable"); + + time2.focus(); + is(document.activeElement, time2, + "input element with tabindex=-1 is still focusable"); + + // Changing the tabindex attribute dynamically. + time3.setAttribute("tabindex", "-1"); + synthesizeKey("VK_TAB", {}); // need only one TAB since time2 is not tabbable + isnot(document.activeElement, time3, + "element with tabindex changed to -1 should not be tabbable"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_defaultValue.html b/dom/html/test/forms/test_input_defaultValue.html new file mode 100644 index 000000000..53d2dd43a --- /dev/null +++ b/dom/html/test/forms/test_input_defaultValue.html @@ -0,0 +1,81 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=977029 +--> +<head> + <title>Test for Bug 977029</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<div id="content"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=977029">Bug 977029</a> + <p> + Goal of this test is to check that modifying defaultValue and value attribute + of input types is working as expected. + </p> + <form> + <input id='a' type="color" value="#00ff00"> + <input id='b' type="text" value="foo"> + <input id='c' type="email" value="foo"> + <input id='d' type="date" value="2010-09-20"> + <input id='e' type="search" value="foo"> + <input id='f' type="tel" value="foo"> + <input id='g' type="url" value="foo"> + <input id='h' type="number" value="42"> + <input id='i' type="range" value="42" min="0" max="100"> + <input id='j' type="time" value="17:00:25.54"> + </form> +</div> +<script type="application/javascript"> + +// [ element id | original defaultValue | another value | another default value] +// Preferably use only valid values: the goal of this test isn't to test the +// value sanitization algorithm (for input types which have one) as this is +// already part of another test) +var testData = [["a", "#00ff00", "#00aaaa", "#00ccaa"], + ["b", "foo", "bar", "tulip"], + ["c", "foo", "foo@bar.org", "tulip"], + ["d", "2010-09-20", "2012-09-21", ""], + ["e", "foo", "bar", "tulip"], + ["f", "foo", "bar", "tulip"], + ["g", "foo", "bar", "tulip"], + ["h", "42", "1337", "3"], + ["i", "42", "17", "3"], + ["j", "17:00:25.54", "07:00:25", "03:00:03"], + ]; + +for (var data of testData) { + id = data[0]; + input = document.getElementById(id); + originalDefaultValue = data[1]; + is(originalDefaultValue, input.defaultValue, + "Default value isn't the expected one"); + is(originalDefaultValue, input.value, + "input.value original value is different from defaultValue"); + input.defaultValue = data[2] + is(input.defaultValue, input.value, + "Changing default value before value was changed should change value too"); + input.value = data[3]; + input.defaultValue = originalDefaultValue; + is(input.value, data[3], + "Changing default value after value was changed should not change value"); + input.value = data[2]; + is(originalDefaultValue, input.defaultValue, + "defaultValue shouldn't change when changing value"); + input.defaultValue = data[3]; + is(input.defaultValue, data[3], + "defaultValue should have changed"); + // Change the value... + input.value = data[2]; + is(input.value, data[2], + "value should have changed"); + // ...then reset the form + input.form.reset(); + is(input.defaultValue, input.value, + "reset form should bring back the default value"); +} +</script> +</body> +</html> + diff --git a/dom/html/test/forms/test_input_email.html b/dom/html/test/forms/test_input_email.html new file mode 100644 index 000000000..9f35cbe22 --- /dev/null +++ b/dom/html/test/forms/test_input_email.html @@ -0,0 +1,237 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=555559 +https://bugzilla.mozilla.org/show_bug.cgi?id=668817 +https://bugzilla.mozilla.org/show_bug.cgi?id=854812 +--> +<head> + <title>Test for <input type='email'> validity</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555559">Mozilla Bug 555559</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=668817">Mozilla Bug 668817</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=854812">Mozilla Bug 854812</a> +<p id="display"></p> +<div id="content" style="display: none"> + <form> + <input type='email' name='email' id='i' oninvalid="invalidEventHandler(event);"> + <form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for <input type='email'> validity **/ + +var gInvalid = false; + +function invalidEventHandler(e) +{ + is(e.type, "invalid", "Invalid event type should be invalid"); + gInvalid = true; +} + +function checkValidEmailAddress(element) +{ + gInvalid = false; + ok(!element.validity.typeMismatch && !element.validity.badInput, + "Element should not suffer from type mismatch or bad input (with value='"+element.value+"')"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "Element should be valid"); + ok(!gInvalid, "The invalid event should not have been thrown"); + is(element.validationMessage, '', + "Validation message should be the empty string"); + ok(element.matches(":valid"), ":valid pseudo-class should apply"); +} + +const VALID = 0; +const TYPE_MISMATCH = 1 << 0; +const BAD_INPUT = 1 << 1; + +function checkInvalidEmailAddress(element, failedValidityStates) +{ + info("Checking " + element.value); + gInvalid = false; + var expectTypeMismatch = !!(failedValidityStates & TYPE_MISMATCH); + var expectBadInput = !!(failedValidityStates & BAD_INPUT); + ok(element.validity.typeMismatch == expectTypeMismatch, + "Element should " + (expectTypeMismatch ? "" : "not ") + "suffer from type mismatch (with value='"+element.value+"')"); + ok(element.validity.badInput == expectBadInput, + "Element should " + (expectBadInput ? "" : "not ") + "suffer from bad input (with value='"+element.value+"')"); + ok(!element.validity.valid, "Element should not be valid"); + ok(!element.checkValidity(), "Element should not be valid"); + ok(gInvalid, "The invalid event should have been thrown"); + is(element.validationMessage, "Please enter an email address.", + "Validation message is not valid"); + ok(element.matches(":invalid"), ":invalid pseudo-class should apply"); +} + +function testEmailAddress(aElement, aValue, aMultiple, aValidityFailures) +{ + aElement.multiple = aMultiple; + aElement.value = aValue; + + if (!aValidityFailures) { + checkValidEmailAddress(aElement); + } else { + checkInvalidEmailAddress(aElement, aValidityFailures); + } +} + +var email = document.forms[0].elements[0]; + +// Simple values, checking the e-mail syntax validity. +var values = [ + [ '' ], // The empty string shouldn't be considered as invalid. + [ 'foo@bar.com', VALID ], + [ ' foo@bar.com', VALID ], + [ 'foo@bar.com ', VALID ], + [ '\r\n foo@bar.com', VALID ], + [ 'foo@bar.com \n\r', VALID ], + [ '\n\n \r\rfoo@bar.com\n\n \r\r', VALID ], + [ '\n\r \n\rfoo@bar.com\n\r \n\r', VALID ], + [ 'tulip', TYPE_MISMATCH ], + // Some checks on the user part of the address. + [ '@bar.com', TYPE_MISMATCH ], + [ 'f\noo@bar.com', VALID ], + [ 'f\roo@bar.com', VALID ], + [ 'f\r\noo@bar.com', VALID ], + [ 'fü@foo.com', TYPE_MISMATCH ], + // Some checks for the domain part. + [ 'foo@bar', VALID ], + [ 'foo@b', VALID ], + [ 'foo@', TYPE_MISMATCH ], + [ 'foo@bar.', TYPE_MISMATCH ], + [ 'foo@foo.bar', VALID ], + [ 'foo@foo..bar', TYPE_MISMATCH ], + [ 'foo@.bar', TYPE_MISMATCH ], + [ 'foo@tulip.foo.bar', VALID ], + [ 'foo@tulip.foo-bar', VALID ], + [ 'foo@1.2', VALID ], + [ 'foo@127.0.0.1', VALID ], + [ 'foo@1.2.3', VALID ], + [ 'foo@b\nar.com', VALID ], + [ 'foo@b\rar.com', VALID ], + [ 'foo@b\r\nar.com', VALID ], + [ 'foo@.', TYPE_MISMATCH ], + [ 'foo@fü.com', VALID ], + [ 'foo@fu.cüm', VALID ], + [ 'thisUsernameIsLongerThanSixtyThreeCharactersInLengthRightAboutNow@mozilla.tld', VALID ], + // Long strings with UTF-8 in username. + [ 'this.is.email.should.be.longer.than.sixty.four.characters.föö@mözillä.tld', TYPE_MISMATCH ], + [ 'this-is-email-should-be-longer-than-sixty-four-characters-föö@mözillä.tld', TYPE_MISMATCH, true ], + // Long labels (labels greater than 63 chars long are not allowed). + [ 'foo@thislabelisexactly63characterssssssssssssssssssssssssssssssssss', VALID ], + [ 'foo@thislabelisexactly63characterssssssssssssssssssssssssssssssssss.com', VALID ], + [ 'foo@foo.thislabelisexactly63characterssssssssssssssssssssssssssssssssss.com', VALID ], + [ 'foo@foo.thislabelisexactly63characterssssssssssssssssssssssssssssssssss', VALID ], + [ 'foo@thislabelisexactly64charactersssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ], + [ 'foo@thislabelisexactly64charactersssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ], + [ 'foo@foo.thislabelisexactly64charactersssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ], + [ 'foo@foo.thislabelisexactly64charactersssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ], + // Long labels with UTF-8 (punycode encoding will increase the label to more than 63 chars). + [ 'foo@thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ], + [ 'foo@thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ], + [ 'foo@foo.thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ], + [ 'foo@foo.thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ], + // The domains labels (sub-domains or tld) can't start or finish with a '-' + [ 'foo@foo-bar', VALID ], + [ 'foo@-foo', TYPE_MISMATCH ], + [ 'foo@foo-.bar', TYPE_MISMATCH ], + [ 'foo@-.-', TYPE_MISMATCH ], + [ 'foo@fo-o.bar', VALID ], + [ 'foo@fo-o.-bar', TYPE_MISMATCH ], + [ 'foo@fo-o.bar-', TYPE_MISMATCH ], + [ 'foo@fo-o.-', TYPE_MISMATCH ], + [ 'foo@fo--o', VALID ], +]; + +// Multiple values, we don't check e-mail validity, only multiple stuff. +var multipleValues = [ + [ 'foo@bar.com, foo@bar.com', VALID ], + [ 'foo@bar.com,foo@bar.com', VALID ], + [ 'foo@bar.com,foo@bar.com,foo@bar.com', VALID ], + [ ' foo@bar.com , foo@bar.com ', VALID ], + [ '\tfoo@bar.com\t,\tfoo@bar.com\t', VALID ], + [ '\rfoo@bar.com\r,\rfoo@bar.com\r', VALID ], + [ '\nfoo@bar.com\n,\nfoo@bar.com\n', VALID ], + [ '\ffoo@bar.com\f,\ffoo@bar.com\f', VALID ], + [ '\t foo@bar.com\r,\nfoo@bar.com\f', VALID ], + [ 'foo@b,ar.com,foo@bar.com', TYPE_MISMATCH ], + [ 'foo@bar.com,foo@bar.com,', TYPE_MISMATCH ], + [ ' foo@bar.com , foo@bar.com , ', TYPE_MISMATCH ], + [ ',foo@bar.com,foo@bar.com', TYPE_MISMATCH ], + [ ',foo@bar.com,foo@bar.com', TYPE_MISMATCH ], + [ 'foo@bar.com,,,foo@bar.com', TYPE_MISMATCH ], + [ 'foo@bar.com;foo@bar.com', TYPE_MISMATCH ], + [ '<foo@bar.com>, <foo@bar.com>', TYPE_MISMATCH ], + [ 'foo@bar, foo@bar.com', VALID ], + [ 'foo@bar.com, foo', TYPE_MISMATCH ], + [ 'foo, foo@bar.com', TYPE_MISMATCH ], +]; + +/* Additional username checks. */ + +var legalCharacters = "abcdefghijklmnopqrstuvwxyz"; +legalCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +legalCharacters += "0123456789"; +legalCharacters += "!#$%&'*+-/=?^_`{|}~."; + +// Add all username legal characters individually to the list. +for (c of legalCharacters) { + values.push([c + "@bar.com", VALID]); +} +// Add the concatenation of all legal characters too. +values.push([legalCharacters + "@bar.com", VALID]); + +// Add username illegal characters, the same way. +var illegalCharacters = "()<>[]:;@\\, \t"; +for (c of illegalCharacters) { + values.push([illegalCharacters + "@bar.com", TYPE_MISMATCH]); +} + +/* Additional domain checks. */ + +legalCharacters = "abcdefghijklmnopqrstuvwxyz"; +legalCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +legalCharacters += "0123456789"; + +// Add domain legal characters (except '.' and '-' because they are special). +for (c of legalCharacters) { + values.push(["foo@foo.bar" + c, VALID]); +} +// Add the concatenation of all legal characters too. +values.push(["foo@bar." + legalCharacters, VALID]); + +// Add domain illegal characters. +illegalCharacters = "()<>[]:;@\\,!#$%&'*+/=?^_`{|}~ \t"; +for (c of illegalCharacters) { + values.push(['foo@foo.ba' + c + 'r', TYPE_MISMATCH]); +} + +values.forEach(function([value, valid, todo]) { + if (todo === true) { + email.value = value; + todo_is(email.validity.valid, true, "value should be valid"); + } else { + testEmailAddress(email, value, false, valid); + } +}); + +multipleValues.forEach(function([value, valid]) { + testEmailAddress(email, value, true, valid); +}); + +// Make sure setting multiple changes the value. +email.multiple = false; +email.value = "foo@bar.com, foo@bar.com"; +checkInvalidEmailAddress(email, TYPE_MISMATCH); +email.multiple = true; +checkValidEmailAddress(email); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_event.html b/dom/html/test/forms/test_input_event.html new file mode 100644 index 000000000..f458b1b48 --- /dev/null +++ b/dom/html/test/forms/test_input_event.html @@ -0,0 +1,234 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=851780 +--> +<head> +<title>Test for input event</title> +<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=851780">Mozilla Bug 851780</a> +<p id="display"></p> +<div id="content"> +<input type="file" id="fileInput"></input> +<textarea id="textarea" oninput="++textareaInput;"></textarea> +<input type="text" id="input_text" oninput="++textInput[0];"></input> +<input type="email" id="input_email" oninput="++textInput[1];"></input> +<input type="search" id="input_search" oninput="++textInput[2];"></input> +<input type="tel" id="input_tel" oninput="++textInput[3];"></input> +<input type="url" id="input_url" oninput="++textInput[4];"></input> +<input type="password" id="input_password" oninput="++textInput[5];"></input> + +<!-- "Non-text" inputs--> +<input type="button" id="input_button" oninput="++NonTextInput[0];"></input> +<input type="submit" id="input_submit" oninput="++NonTextInput[1];"></input> +<input type="image" id="input_image" oninput="++NonTextInput[2];"></input> +<input type="reset" id="input_reset" oninput="++NonTextInput[3];"></input> +<input type="radio" id="input_radio" oninput="++NonTextInput[4];"></input> +<input type="checkbox" id="input_checkbox" oninput="++NonTextInput[5];"></input> +<input type="range" id="input_range" oninput="++rangeInput;"></input> +<input type="number" id="input_number" oninput="++numberInput;"></input> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + + /** Test for input event. This is highly based on test_change_event.html **/ + + const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent); + + var textareaInput = 0; + + // Those are types were the input event apply. + var textTypes = ["text", "email", "search", "tel", "url", "password"]; + var textInput = [0, 0, 0, 0, 0, 0]; + + // Those are events were the input event does not apply. + var NonTextTypes = ["button", "submit", "image", "reset", "radio", "checkbox"]; + var NonTextInput = [0, 0, 0, 0, 0, 0]; + + var rangeInput = 0; + var numberInput = 0; + + SimpleTest.waitForExplicitFinish(); + var MockFilePicker = SpecialPowers.MockFilePicker; + MockFilePicker.init(window); + + function testUserInput() { + // Simulating an OK click and with a file name return. + MockFilePicker.useBlobFile(); + MockFilePicker.returnValue = MockFilePicker.returnOK; + var input = document.getElementById('fileInput'); + input.focus(); + + input.addEventListener("input", function (aEvent) { + ok(true, "input event should have been dispatched on file input."); + }, false); + + input.click(); + setTimeout(testUserInput2, 0); + } + + function testUserInput2() { + // Some generic checks for types that support the input event. + for (var i = 0; i < textTypes.length; ++i) { + input = document.getElementById("input_" + textTypes[i]); + input.focus(); + synthesizeKey("VK_RETURN", {}); + is(textInput[i], 0, "input event shouldn't be dispatched on " + textTypes[i] + " input element"); + + synthesizeKey("m", {}); + is(textInput[i], 1, textTypes[i] + " input element should have dispatched input event."); + synthesizeKey("VK_RETURN", {}); + is(textInput[i], 1, "input event shouldn't be dispatched on " + textTypes[i] + " input element"); + + synthesizeKey("VK_BACK_SPACE", {}); + is(textInput[i], 2, textTypes[i] + " input element should have dispatched input event."); + } + + // Some scenarios of value changing from script and from user input. + input = document.getElementById("input_text"); + input.focus(); + synthesizeKey("f", {}); + is(textInput[0], 3, "input event should have been dispatched"); + input.blur(); + is(textInput[0], 3, "input event should not have been dispatched"); + + input.focus(); + input.value = 'foo'; + is(textInput[0], 3, "input event should not have been dispatched"); + input.blur(); + is(textInput[0], 3, "input event should not have been dispatched"); + + input.focus(); + synthesizeKey("f", {}); + is(textInput[0], 4, "input event should have been dispatched"); + input.value = 'bar'; + is(textInput[0], 4, "input event should not have been dispatched"); + input.blur(); + is(textInput[0], 4, "input event should not have been dispatched"); + + // Same for textarea. + var textarea = document.getElementById("textarea"); + textarea.focus(); + synthesizeKey("f", {}); + is(textareaInput, 1, "input event should have been dispatched"); + textarea.blur(); + is(textareaInput, 1, "input event should not have been dispatched"); + + textarea.focus(); + textarea.value = 'foo'; + is(textareaInput, 1, "input event should not have been dispatched"); + textarea.blur(); + is(textareaInput, 1, "input event should not have been dispatched"); + + textarea.focus(); + synthesizeKey("f", {}); + is(textareaInput, 2, "input event should have been dispatched"); + textarea.value = 'bar'; + is(textareaInput, 2, "input event should not have been dispatched"); + synthesizeKey("VK_BACK_SPACE", {}); + is(textareaInput, 3, "input event should have been dispatched"); + textarea.blur(); + is(textareaInput, 3, "input event should not have been dispatched"); + + // Non-text input tests: + for (var i = 0; i < NonTextTypes.length; ++i) { + // Button, submit, image and reset input type tests. + if (i < 4) { + input = document.getElementById("input_" + NonTextTypes[i]); + input.focus(); + input.click(); + is(NonTextInput[i], 0, "input event doesn't apply"); + input.blur(); + is(NonTextInput[i], 0, "input event doesn't apply"); + } + // For radio and checkboxes, input event should be dispatched. + else { + input = document.getElementById("input_" + NonTextTypes[i]); + input.focus(); + input.click(); + is(NonTextInput[i], 1, "input event should have been dispatched"); + input.blur(); + is(NonTextInput[i], 1, "input event should not have been dispatched"); + + // Test that input event is not dispatched if click event is cancelled. + function preventDefault(e) { + e.preventDefault(); + } + input.addEventListener("click", preventDefault, false); + input.click(); + is(NonTextInput[i], 1, "input event shouldn't be dispatched if click event is cancelled"); + input.removeEventListener("click", preventDefault, false); + } + } + + // Type changes. + var input = document.createElement('input'); + input.type = 'text'; + input.value = 'foo'; + input.oninput = function() { + ok(false, "we shouldn't get an input event when the type changes"); + }; + input.type = 'range'; + isnot(input.value, 'foo'); + + // Tests for type='range'. + var range = document.getElementById("input_range"); + + range.focus(); + synthesizeKey("a", {}); + range.blur(); + is(rangeInput, 0, "input event shouldn't be dispatched on range input " + + "element for key changes that don't change its value"); + + range.focus(); + synthesizeKey("VK_HOME", {}); + is(rangeInput, 1, "input event should be dispatched for key changes"); + range.blur(); + is(rangeInput, 1, "input event shouldn't be dispatched on blur"); + + range.focus(); + var bcr = range.getBoundingClientRect(); + var centerOfRangeX = bcr.width / 2; + var centerOfRangeY = bcr.height / 2; + synthesizeMouse(range, centerOfRangeX - 10, centerOfRangeY, { type: "mousedown" }); + is(rangeInput, 2, "Input event should be dispatched on mousedown if the value changes"); + synthesizeMouse(range, centerOfRangeX - 5, centerOfRangeY, { type: "mousemove" }); + is(rangeInput, 3, "Input event should be dispatched during a drag"); + synthesizeMouse(range, centerOfRangeX, centerOfRangeY, { type: "mouseup" }); + is(rangeInput, 4, "Input event should be dispatched at the end of a drag"); + + // Tests for type='number'. + // We only test key events here since input events for mouse event changes + // are tested in test_input_number_mouse_events.html + var number = document.getElementById("input_number"); + + if (isDesktop) { // up/down arrow keys not supported on android/b2g + number.value = ""; + number.focus(); + synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" }); + is(numberInput, 1, "input event should be dispatched for up/down arrow key keypress"); + is(number.value, "1", "sanity check value of number control after keypress"); + + synthesizeKey("KEY_ArrowDown", { code: "ArrowDown", repeat: 3 }); + is(numberInput, 4, "input event should be dispatched for each up/down arrow key keypress event, even when rapidly repeated"); + is(number.value, "-2", "sanity check value of number control after multiple keydown events"); + + number.blur(); + is(numberInput, 4, "input event shouldn't be dispatched on blur"); + } + + MockFilePicker.cleanup(); + SimpleTest.finish(); + } + + addLoadEvent(testUserInput); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_file_picker.html b/dom/html/test/forms/test_input_file_picker.html new file mode 100644 index 000000000..6d3a98631 --- /dev/null +++ b/dom/html/test/forms/test_input_file_picker.html @@ -0,0 +1,267 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for <input type='file'> file picker</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 36619</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 377624</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=565274">Mozilla Bug 565274</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=701353">Mozilla Bug 701353</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=826176">Mozilla Bug 826176</a> +<p id="display"></p> +<div id="content"> + <input id='a' type='file' accept="image/*"> + <input id='b' type='file' accept="audio/*"> + <input id='c' type='file' accept="video/*"> + <input id='d' type='file' accept="image/*, audio/* "> + <input id='e' type='file' accept=" image/*,video/*"> + <input id='f' type='file' accept="audio/*,video/*"> + <input id='g' type='file' accept="image/*, audio/* ,video/*"> + <input id='h' type='file' accept="foo/baz,image/*,bogus/duh"> + <input id='i' type='file' accept="mime/type;parameter,video/*"> + <input id='j' type='file' accept="audio/*, audio/*, audio/*"> + <input id='k' type="file" accept="image/gif,image/png"> + <input id='l' type="file" accept="image/*,image/gif,image/png"> + <input id='m' type="file" accept="image/gif,image/gif"> + <input id='n' type="file" accept=""> + <input id='o' type="file" accept=".test"> + <input id='p' type="file" accept="image/gif,.csv"> + <input id='q' type="file" accept="image/gif,.gif"> + <input id='r' type="file" accept=".prefix,.prefixPlusSomething"> + <input id='s' type="file" accept=".xls,.xlsx"> + <input id='t' type="file" accept=".mp3,.wav,.flac"> + <input id='u' type="file" accept=".xls, .xlsx"> + <input id='v' type="file" accept=".xlsx, .xls"> + <input id='w' type="file" accept=".xlsx; .xls"> + <input id='x' type="file" accept=".xls, .xlsx"> + <input id='y' type="file" accept=".xlsx, .xls"> + <input id='z' type='file' accept="i/am,a,pathological,;,,,,test/case"> + <input id='A' type="file" accept=".xlsx, .xls*"> + <input id='mix-ref' type="file" accept="image/jpeg"> + <input id='mix' type="file" accept="image/jpeg,.jpg"> + <input id='hidden' hidden type='file'> + <input id='untrusted-click' type='file'> + <input id='prevent-default' type='file'> + <input id='prevent-default-false' type='file'> + <input id='right-click' type='file'> + <input id='middle-click' type='file'> + <input id='left-click' type='file'> + <label id='label-1'>foo<input type='file'></label> + <label id='label-2' for='labeled-2'>foo</label><input id='labeled-2' type='file'></label> + <label id='label-3'>foo<input type='file'></label> + <label id='label-4' for='labeled-4'>foo</label><input id='labeled-4' type='file'></label> + <input id='by-button' type='file'> + <button id='button-click' onclick="document.getElementById('by-button').click();">foo</button> + <button id='button-down' onclick="document.getElementById('by-button').click();">foo</button> + <button id='button-up' onclick="document.getElementById('by-button').click();">foo</button> + <div id='div-click' onclick="document.getElementById('by-button').click();" tabindex='1'>foo</div> + <div id='div-click-on-demand' onclick="var i=document.createElement('input'); i.type='file'; i.click();" tabindex='1'>foo</div> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * This test checks various scenarios and make sure that a file picker is being + * shown in all of them (minus a few exceptions). + * |testData| defines the tests to do and |launchNextTest| can be used to have + * specific behaviour for some tests. Everything else should just work. + */ + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +// The following lists are from toolkit/content/filepicker.properties which is used by filePicker +var imageExtensionList = "*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw" +var audioExtensionList = "*.aac; *.aif; *.flac; *.iff; *.m4a; *.m4b; *.mid; *.midi; *.mp3; *.mpa; *.mpc; *.oga; *.ogg; *.ra; *.ram; *.snd; *.wav; *.wma" +var videoExtensionList = "*.avi; *.divx; *.flv; *.m4v; *.mkv; *.mov; *.mp4; *.mpeg; *.mpg; *.ogm; *.ogv; *.ogx; *.rm; *.rmvb; *.smil; *.webm; *.wmv; *.xvid" + +// [ element name | number of filters | extension list or filter mask | filter index ] +var testData = [["a", 1, MockFilePicker.filterImages, 1], + ["b", 1, MockFilePicker.filterAudio, 1], + ["c", 1, MockFilePicker.filterVideo, 1], + ["d", 3, imageExtensionList + "; " + audioExtensionList, 1], + ["e", 3, imageExtensionList + "; " + videoExtensionList, 1], + ["f", 3, audioExtensionList + "; " + videoExtensionList, 1], + ["g", 4, imageExtensionList + "; " + audioExtensionList + "; " + videoExtensionList, 1], + ["h", 1, MockFilePicker.filterImages, 0], + ["i", 1, MockFilePicker.filterVideo, 0], + ["j", 1, MockFilePicker.filterAudio, 1], + ["k", 3, "*.gif; *.png", 1], + ["l", 4, imageExtensionList + "; " + "*.gif; *.png", 1], + ["m", 1, "*.gif", 1], + ["n", 0, undefined, 0], + ["o", 1, "*.test", 1], + ["p", 3, "*.gif; *.csv", 1], + ["q", 1, "*.gif", 1], + ["r", 3, "*.prefix; *.prefixPlusSomething", 1], + ["s", 3, "*.xls; *.xlsx", 1], + ["t", 4, "*.mp3; *.wav; *.flac", 1], + ["u", 3, "*.xls; *.xlsx", 1], + ["v", 3, "*.xlsx; *.xls", 1], + ["w", 0, undefined, 0], + ["x", 3, "*.xls; *.xlsx", 1], + ["y", 3, "*.xlsx; *.xls", 1], + ["z", 0, undefined, 0], + ["A", 1, "*.xlsx", 1], + // Note: mix and mix-ref tests extension lists are checked differently: see SimpleTest.executeSoon below + ["mix-ref", undefined, undefined, undefined], + ["mix", 1, undefined, 1], + ["hidden", 0, undefined, 0], + ["untrusted-click", 0, undefined, 0], + ["prevent-default", 0, undefined, 0, true], + ["prevent-default-false", 0, undefined, 0, true], + ["right-click", 0, undefined, 0, true], + ["middle-click", 0, undefined, 0, true], + ["left-click", 0, undefined, 0], + ["label-1", 0, undefined, 0], + ["label-2", 0, undefined, 0], + ["label-3", 0, undefined, 0], + ["label-4", 0, undefined, 0], + ["button-click", 0, undefined, 0], + ["button-down", 0, undefined, 0], + ["button-up", 0, undefined, 0], + ["div-click", 0, undefined, 0], + ["div-click-on-demand", 0, undefined, 0], + ]; + +var currentTest = 0; +var filterAllAdded; +var filters; +var filterIndex; +var mixRefExtensionList; + +// disable popups to make sure that the popup blocker does not interfere +// with manually opened file pickers. +SpecialPowers.pushPrefEnv({'set': [["dom.disable_open_during_load", false]]}, runTests); + +function launchNextTest() { + MockFilePicker.shown = false; + filterAllAdded = false; + filters = []; + filterIndex = 0; + + // Focusing the element will scroll them into view so making sure the clicks + // will work. + document.getElementById(testData[currentTest][0]).focus(); + + if (testData[currentTest][0] == "untrusted-click") { + var e = document.createEvent('MouseEvents'); + e.initEvent('click', true, false); + document.getElementById(testData[currentTest][0]).dispatchEvent(e); + // All tests that should *NOT* show a file picker. + } else if (testData[currentTest][0] == "prevent-default" || + testData[currentTest][0] == "prevent-default-false" || + testData[currentTest][0] == "right-click" || + testData[currentTest][0] == "middle-click") { + if (testData[currentTest][0] == "right-click" || + testData[currentTest][0] == "middle-click") { + var b = testData[currentTest][0] == "middle-click" ? 1 : 2; + synthesizeMouseAtCenter(document.getElementById(testData[currentTest][0]), + { button: b }); + } else { + if (testData[currentTest][0] == "prevent-default-false") { + document.getElementById(testData[currentTest][0]).onclick = function() { + return false; + }; + } else { + document.getElementById(testData[currentTest][0]).onclick = function(e) { + e.preventDefault(); + }; + } + document.getElementById(testData[currentTest][0]).click(); + } + + // Wait a bit and assume we can continue. If the file picker shows later, + // behaviour is uncertain but that would be a random green, no big deal... + setTimeout(function() { + ok(true, "we should be there without a file picker being opened"); + ++currentTest; + launchNextTest(); + }, 500); + } else if (testData[currentTest][0] == 'label-3' || + testData[currentTest][0] == 'label-4') { + synthesizeMouse(document.getElementById(testData[currentTest][0]), 5, 5, {}); + } else if (testData[currentTest][0] == 'button-click' || + testData[currentTest][0] == 'button-down' || + testData[currentTest][0] == 'button-up' || + testData[currentTest][0] == 'div-click' || + testData[currentTest][0] == 'div-click-on-demand') { + synthesizeMouseAtCenter(document.getElementById(testData[currentTest][0]), {}); + } else { + document.getElementById(testData[currentTest][0]).click(); + } +} + +function runTests() { + MockFilePicker.appendFilterCallback = function(filepicker, title, val) { + filters.push(val); + }; + MockFilePicker.appendFiltersCallback = function(filepicker, val) { + if (val === MockFilePicker.filterAll) { + filterAllAdded = true; + } else { + filters.push(val); + } + }; + MockFilePicker.showCallback = function(filepicker) { + if (testData[currentTest][4]) { + ok(false, "we shouldn't have a file picker showing!"); + return; + } + + filterIndex = filepicker.filterIndex; + testName = testData[currentTest][0]; + SimpleTest.executeSoon(function () { + ok(MockFilePicker.shown, + "File picker show method should have been called (" + testName + ")"); + ok(filterAllAdded, + "filterAll is missing (" + testName + ")"); + if (testName == "mix-ref") { + // Used only for reference for next test: nothing to be tested here + mixRefExtensionList = filters[0]; + if (mixRefExtensionList == undefined) { + mixRefExtensionList = ""; + } + } else { + if (testName == "mix") { + // Mixing mime type and file extension filters ("image/jpeg" and + // ".jpg" here) shouldn't restrict the list but only extend it, if file + // extension filter isn't a duplicate + ok(filters[0].includes(mixRefExtensionList), + "Mixing mime types and file extension filters shouldn't restrict extension list: " + + mixRefExtensionList + " | " + filters[0]); + ok(filters[0].includes("*.jpg"), + "Filter should contain '.jpg' extension", filters[0]); + } else { + is(filters[0], testData[currentTest][2], + "Correct filters should have been added (" + testName + ")"); + is(filters.length, testData[currentTest][1], + "appendFilters not called as often as expected (" + testName + ")"); + } + is(filterIndex, testData[currentTest][3], + "File picker should show the correct filter index (" + testName + ")"); + } + + if (++currentTest == testData.length) { + MockFilePicker.cleanup(); + SimpleTest.finish(); + } else { + launchNextTest(); + } + }); + }; + + launchNextTest(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_list_attribute.html b/dom/html/test/forms/test_input_list_attribute.html new file mode 100644 index 000000000..ff2be85d0 --- /dev/null +++ b/dom/html/test/forms/test_input_list_attribute.html @@ -0,0 +1,253 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=556007 +--> +<head> + <title>Test for Bug 556007</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=556007">Mozilla Bug 556007</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 556007 **/ + +function test0() { + var input = document.createElement("input"); + ok("list" in input, "list should be an input element IDL attribute"); +} + +// Default .list returns null. +function test1(aContent, aInput) { + return null; +} + +// Regular test case. +function test2(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aContent.appendChild(aInput); + aContent.appendChild(datalist); + aInput.setAttribute('list', 'd'); + + return datalist; +} + +// If none of the element is in doc. +function test3(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aInput.setAttribute('list', 'd'); + + return null; +} + +// If one of the element isn't in doc. +function test4(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aContent.appendChild(aInput); + aInput.setAttribute('list', 'd'); + + return null; +} + +// If one of the element isn't in doc. +function test5(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aContent.appendChild(datalist); + aInput.setAttribute('list', 'd'); + + return null; +} + +// If datalist is added before input. +function test6(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aContent.appendChild(datalist); + aContent.appendChild(aInput); + aInput.setAttribute('list', 'd'); + + return datalist; +} + +// If setAttribute is set before datalist and input are in doc. +function test7(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aInput.setAttribute('list', 'd'); + + aContent.appendChild(datalist); + aContent.appendChild(aInput); + + return datalist; +} + +// If setAttribute is set before datalist is in doc. +function test8(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aContent.appendChild(aInput); + aInput.setAttribute('list', 'd'); + + aContent.appendChild(datalist); + + return datalist; +} + +// If setAttribute is set before datalist is created. +function test9(aContent, aInput) { + aContent.appendChild(aInput); + aInput.setAttribute('list', 'd'); + + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + aContent.appendChild(datalist); + + return datalist; +} + +// If another datalist is added _after_ the first one, with the same id. +function test10(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + var datalist2 = document.createElement("datalist"); + datalist2.id = 'd'; + + aInput.setAttribute('list', 'd'); + aContent.appendChild(aInput); + aContent.appendChild(datalist); + aContent.appendChild(datalist2); + + return datalist; +} + +// If another datalist is added _before_ the first one with the same id. +function test11(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + var datalist2 = document.createElement("datalist"); + datalist2.id = 'd'; + + aInput.setAttribute('list', 'd'); + aContent.appendChild(aInput); + aContent.appendChild(datalist); + aContent.insertBefore(datalist2, datalist); + + return datalist2; +} + +// If datalist changes it's id. +function test12(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aInput.setAttribute('list', 'd'); + aContent.appendChild(aInput); + aContent.appendChild(datalist); + + datalist.id = 'foo'; + + return null; +} + +// If datalist is removed. +function test13(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aInput.setAttribute('list', 'd'); + aContent.appendChild(aInput); + aContent.appendChild(datalist); + aContent.removeChild(datalist); + + return null; +} + +// If id contain spaces. +function test14(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = 'a b c d'; + + aInput.setAttribute('list', 'a b c d'); + aContent.appendChild(aInput); + aContent.appendChild(datalist); + + return datalist; +} + +// If id is the empty string. +function test15(aContent, aInput) { + var datalist = document.createElement("datalist"); + datalist.id = ''; + + aInput.setAttribute('list', ''); + aContent.appendChild(aInput); + aContent.appendChild(datalist); + + return null; +} + +// If the id doesn't point to a datalist. +function test16(aContent, aInput) { + var input = document.createElement("input"); + input.id = 'd'; + + aInput.setAttribute('list', 'd'); + aContent.appendChild(aInput); + aContent.appendChild(input); + + return null; +} + +// If the first element with the id isn't a datalist. +function test17(aContent, aInput) { + var input = document.createElement("input"); + input.id = 'd'; + var datalist = document.createElement("datalist"); + datalist.id = 'd'; + + aInput.setAttribute('list', 'd'); + aContent.appendChild(aInput); + aContent.appendChild(input); + aContent.appendChild(datalist); + + return null; +} + +var tests = [ test1, test2, test3, test4, test5, test6, test7, test8, test9, + test10, test11, test12, test13, test14, test15, test16, test17 ]; + +test0(); + +for (var test of tests) { + var content = document.getElementById('content'); + + // Clean-up. + content.textContent = ''; + + var input = document.createElement("input"); + var res = test(content, input); + + is(input.list, res, "input.list should be " + res); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_number_data.js b/dom/html/test/forms/test_input_number_data.js new file mode 100644 index 000000000..0a995010f --- /dev/null +++ b/dom/html/test/forms/test_input_number_data.js @@ -0,0 +1,38 @@ + +var tests = [ + { desc: "British English", + langTag: "en-GB", inputWithGrouping: "123,456.78", + inputWithoutGrouping: "123456.78", value: 123456.78 + }, + { desc: "Farsi", + langTag: "fa", inputWithGrouping: "Û±Û²Û³Ù¬Û´ÛµÛ¶Ù«Û·Û¸", + inputWithoutGrouping: "Û±Û²Û³Û´ÛµÛ¶Ù«Û·Û¸", value: 123456.78 + }, + { desc: "French", + langTag: "fr-FR", inputWithGrouping: "123 456,78", + inputWithoutGrouping: "123456,78", value: 123456.78 + }, + { desc: "German", + langTag: "de", inputWithGrouping: "123.456,78", + inputWithoutGrouping: "123456,78", value: 123456.78 + }, + // Extra german test to check that a locale that uses '.' as its grouping + // separator doesn't result in it being invalid (due to step mismatch) due + // to the de-localization code mishandling numbers that look like other + // numbers formatted for English speakers (i.e. treating this as 123.456 + // instead of 123456): + { desc: "German (test 2)", + langTag: "de", inputWithGrouping: "123.456", + inputWithoutGrouping: "123456", value: 123456 + }, + { desc: "Hebrew", + langTag: "he", inputWithGrouping: "123,456.78", + inputWithoutGrouping: "123456.78", value: 123456.78 + }, +]; + +var invalidTests = [ + // Right now this will pass in a 'de' build, but not in the 'en' build that + // are used for testing. See bug . + // { desc: "Invalid German", langTag: "de", input: "12.34" } +]; diff --git a/dom/html/test/forms/test_input_number_focus.html b/dom/html/test/forms/test_input_number_focus.html new file mode 100644 index 000000000..121485463 --- /dev/null +++ b/dom/html/test/forms/test_input_number_focus.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1268556 +--> +<head> + <title>Test focus behaviour for <input type='number'></title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1268556">Mozilla Bug 1268556</a> +<p id="display"></p> +<div id="content"> + <input id="input" type="number"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 1268556. + * This test checks that when focusing on an input type=number, the focus is + * redirected to the anonymous text control, but the document.activeElement + * still returns the <input type=number>. + **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(); + SimpleTest.finish(); +}); + +function test() { + var number = document.getElementById("input"); + number.focus(); + + // The active element returns the input type=number. + var activeElement = document.activeElement; + is (activeElement, number, "activeElement should be the number element"); + is (activeElement.localName, "input", "activeElement should be an input element"); + is (activeElement.getAttribute("type"), "number", "activeElement should of type number"); + + // Use FocusManager to check that the actual focus is on the anonymous + // text control. + var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"] + .getService(SpecialPowers.Ci.nsIFocusManager); + var focusedElement = fm.focusedElement; + is (focusedElement.localName, "input", "focusedElement should be an input element"); + is (focusedElement.getAttribute("type"), "text", "focusedElement should of type text"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_number_key_events.html b/dom/html/test/forms/test_input_number_key_events.html new file mode 100644 index 000000000..89578541d --- /dev/null +++ b/dom/html/test/forms/test_input_number_key_events.html @@ -0,0 +1,244 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=935506 +--> +<head> + <title>Test key events for number control</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=935506">Mozilla Bug 935506</a> +<p id="display"></p> +<div id="content"> + <input id="input" type="number"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 935506 + * This test checks how the value of <input type=number> changes in response to + * key events while it is in various states. + **/ +SimpleTest.waitForExplicitFinish(); +// Turn off Spatial Navigation because it hijacks arrow keydown events: +SimpleTest.waitForFocus(function() { + SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() { + test(); + SimpleTest.finish(); + }); +}); +const defaultMinimum = "NaN"; +const defaultMaximum = "NaN"; +const defaultStep = 1; + +// Helpers: +// For the sake of simplicity, we do not currently support fractional value, +// step, etc. + +function getMinimum(element) { + return Number(element.min || defaultMinimum); +} + +function getMaximum(element) { + return Number(element.max || defaultMaximum); +} + +function getDefaultValue(element) { + return 0; +} + +function getValue(element) { + return Number(element.value || getDefaultValue(element)); +} + +function getStep(element) { + if (element.step == "any") { + return "any"; + } + var step = Number(element.step || defaultStep); + return step <= 0 ? defaultStep : step; +} + +function getStepBase(element) { + return Number(element.getAttribute("min") || "NaN") || + Number(element.getAttribute("value") || "NaN") || 0; +} + +function hasStepMismatch(element) { + var value = element.value; + if (value == "") { + value = 0; + } + var step = getStep(element); + if (step == "any") { + return false; + } + return ((value - getStepBase(element)) % step) != 0; +} + +function floorModulo(x, y) { + return (x - y * Math.floor(x / y)); +} + +function expectedValueAfterStepUpOrDown(stepFactor, element) { + var value = getValue(element); + if (isNaN(value)) { + value = 0; + } + var step = getStep(element); + if (step == "any") { + step = 1; + } + + var minimum = getMinimum(element); + var maximum = getMaximum(element); + if (!isNaN(maximum)) { + // "max - (max - stepBase) % step" is the nearest valid value to max. + maximum = maximum - floorModulo(maximum - getStepBase(element), step); + } + + // Cases where we are clearly going in the wrong way. + // We don't use ValidityState because we can be higher than the maximal + // allowed value and still not suffer from range overflow in the case of + // of the value specified in @max isn't in the step. + if ((value <= minimum && stepFactor < 0) || + (value >= maximum && stepFactor > 0)) { + return value; + } + + if (hasStepMismatch(element) && + value != minimum && value != maximum) { + if (stepFactor > 0) { + value -= floorModulo(value - getStepBase(element), step); + } else if (stepFactor < 0) { + value -= floorModulo(value - getStepBase(element), step); + value += step; + } + } + + value += step * stepFactor; + + // When stepUp() is called and the value is below minimum, we should clamp on + // minimum unless stepUp() moves us higher than minimum. + if (element.validity.rangeUnderflow && stepFactor > 0 && + value <= minimum) { + value = minimum; + } else if (element.validity.rangeOverflow && stepFactor < 0 && + value >= maximum) { + value = maximum; + } else if (stepFactor < 0 && !isNaN(minimum)) { + value = Math.max(value, minimum); + } else if (stepFactor > 0 && !isNaN(maximum)) { + value = Math.min(value, maximum); + } + + return value; +} + +function expectedValAfterKeyEvent(key, element) { + return expectedValueAfterStepUpOrDown(key == "VK_UP" ? 1 : -1, element); +} + +function test() { + var elem = document.getElementById("input"); + elem.focus(); + + elem.min = -5; + elem.max = 5; + elem.step = 2; + var defaultValue = 0; + var oldVal, expectedVal; + + for (key of ["VK_UP", "VK_DOWN"]) { + // Start at middle: + oldVal = elem.value = -1; + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for number control with value set between min/max (" + oldVal + ")"); + + // Same again: + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control"); + + // Start at maximum: + oldVal = elem.value = elem.max; + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the maximum (" + oldVal + ")"); + + // Same again: + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control"); + + // Start at minimum: + oldVal = elem.value = elem.min; + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the minimum (" + oldVal + ")"); + + // Same again: + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control"); + + // Test preventDefault(): + elem.addEventListener("keypress", function(evt) { + evt.preventDefault(); + elem.removeEventListener("keypress", arguments.callee, false); + }, false); + oldVal = elem.value = 0; + expectedVal = 0; + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for number control where scripted preventDefault() should prevent the value changing"); + + // Test step="any" behavior: + var oldStep = elem.step; + elem.step = "any"; + oldVal = elem.value = 0; + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the midpoint and step='any' (" + oldVal + ")"); + elem.step = oldStep; // restore + + // Test that invalid input blocks UI initiated stepping: + oldVal = elem.value = ""; + elem.select(); + sendString("abc"); + synthesizeKey(key, {}); + is(elem.value, "", "Test " + key + " does nothing when the input is invalid"); + + // Test that no value does not block UI initiated stepping: + oldVal = elem.value = ""; + elem.setAttribute("required", "required"); + elem.select(); + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the empty string and with the 'required' attribute set"); + + // Same again: + expectedVal = expectedValAfterKeyEvent(key, elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control"); + + // Reset 'required' attribute: + elem.removeAttribute("required"); + } + + // Test that key events are correctly dispatched + elem.max = ""; + elem.value = ""; + sendString("7837281"); + is(elem.value, "7837281", "Test keypress event dispatch for number control"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_number_l10n.html b/dom/html/test/forms/test_input_number_l10n.html new file mode 100644 index 000000000..4d46f7a80 --- /dev/null +++ b/dom/html/test/forms/test_input_number_l10n.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=844744 +--> +<head> + <title>Test localization of number control input</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="test_input_number_data.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=844744">Mozilla Bug 844744</a> +<p id="display"></p> +<div id="content"> + <input id="input" type="number" step="any"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 844744 + * This test checks that localized input that is typed into <input type=number> + * is correctly handled. + **/ +SimpleTest.waitForExplicitFinish(); + +SimpleTest.waitForFocus(function() { + startTests(); + SimpleTest.finish(); +}); + +var elem; + +function runTest(test) { + elem.lang = test.langTag; + elem.value = 0; + elem.focus(); + elem.select(); + sendString(test.inputWithGrouping); + is(elem.value, String(test.value), "Test " + test.desc + " ('" + test.langTag + + "') localization with grouping separator"); + elem.value = 0; + elem.select(); + sendString(test.inputWithoutGrouping); + is(elem.value, String(test.value), "Test " + test.desc + " ('" + test.langTag + + "') localization without grouping separator"); +} + +function runInvalidInputTest(test) { + elem.lang = test.langTag; + elem.value = 0; + elem.focus(); + elem.select(); + sendString(test.input); + is(elem.value, "", "Test " + test.desc + " ('" + test.langTag + + "') with invalid input: " + test.input); +} + +function startTests() { + elem = document.getElementById("input"); + for (var test of tests) { + runTest(test, elem); + } + for (var test of invalidTests) { + runInvalidInputTest(test, elem); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_number_mouse_events.html b/dom/html/test/forms/test_input_number_mouse_events.html new file mode 100644 index 000000000..45f310761 --- /dev/null +++ b/dom/html/test/forms/test_input_number_mouse_events.html @@ -0,0 +1,196 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=935501 +--> +<head> + <title>Test mouse events for number</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <style> + input { + margin: 0 ! important; + border: 0 ! important; + padding: 0 ! important; + } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=935501">Mozilla Bug 935501</a> +<p id="display"></p> +<div id="content"> + <input id="input" type="number"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 935501 + * This test checks how the value of <input type=number> changes in response to + * various mouse events. + **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +SimpleTest.waitForFocus(function() { + test(); +}); + +var input = document.getElementById("input"); +var inputRect = input.getBoundingClientRect(); + +// Points over the input's spin-up and spin-down buttons (as offsets from the +// top-left of the input's bounding client rect): +const SPIN_UP_X = inputRect.width - 3; +const SPIN_UP_Y = 3; +const SPIN_DOWN_X = inputRect.width - 3; +const SPIN_DOWN_Y = inputRect.height - 3; + +function test() { + input.value = 0; + + // Test click on spin-up button: + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); + is(input.value, "1", "Test step-up on mousedown on spin-up button"); + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); + is(input.value, "1", "Test mouseup on spin-up button"); + + // Test click on spin-down button: + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); + is(input.value, "0", "Test step-down on mousedown on spin-down button"); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); + is(input.value, "0", "Test mouseup on spin-down button"); + + // Test step="any" behavior: + input.value = 0; + var oldStep = input.step; + input.step = "any"; + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); + is(input.value, "1", "Test step-up on mousedown on spin-up button with step='any'"); + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); + is(input.value, "1", "Test mouseup on spin-up button with step='any'"); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); + is(input.value, "0", "Test step-down on mousedown on spin-down button with step='any'"); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); + is(input.value, "0", "Test mouseup on spin-down button with step='any'"); + input.step = oldStep; // restore + + // Test that preventDefault() works: + function preventDefault(e) { + e.preventDefault(); + } + input.value = 1; + input.addEventListener("mousedown", preventDefault, false); + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, {}); + is(input.value, "1", "Test that preventDefault() works for click on spin-up button"); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, {}); + is(input.value, "1", "Test that preventDefault() works for click on spin-down button"); + input.removeEventListener("mousedown", preventDefault, false); + + // Run the spin tests: + runNextSpinTest(); +} + +function runNextSpinTest() { + var test = spinTests.shift(); + if (!test) { + SimpleTest.finish(); + return; + } + test(); +} + +const SETTIMEOUT_DELAY = 500; + +var spinTests = [ + // Test spining when the mouse button is kept depressed on the spin-up + // button, then moved over the spin-down button: + function() { + var inputEventCount = 0; + input.value = 0; + input.addEventListener("input", function(evt) { + ++inputEventCount; + if (inputEventCount == 3) { + is(input.value, "3", "Testing spin-up button"); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousemove" }); + } else if (inputEventCount == 6) { + is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-up button to spin-down button"); + input.removeEventListener("input", arguments.callee, false); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); + runNextSpinTest(); + } + }, false); + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); + }, + + // Test spining when the mouse button is kept depressed on the spin-down + // button, then moved over the spin-up button: + function() { + var inputEventCount = 0; + input.value = 0; + input.addEventListener("input", function(evt) { + ++inputEventCount; + if (inputEventCount == 3) { + is(input.value, "-3", "Testing spin-down button"); + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousemove" }); + } else if (inputEventCount == 6) { + is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-down button to spin-up button"); + input.removeEventListener("input", arguments.callee, false); + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); + runNextSpinTest(); + } + }, false); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); + }, + + // Test that the spin is stopped when the mouse button is depressod on the + // spin-up button, then moved outside both buttons once the spin starts: + function() { + var inputEventCount = 0; + input.value = 0; + input.addEventListener("input", function(evt) { + ++inputEventCount; + if (inputEventCount == 3) { + synthesizeMouse(input, -1, -1, { type: "mousemove" }); + var eventHandler = arguments.callee; + setTimeout(function() { + is(input.value, "3", "Testing moving the mouse outside the spin buttons stops the spin"); + is(inputEventCount, 3, "Testing moving the mouse outside the spin buttons stops the spin input events"); + input.removeEventListener("input", eventHandler, false); + synthesizeMouse(input, -1, -1, { type: "mouseup" }); + runNextSpinTest(); + }, SETTIMEOUT_DELAY); + } + }, false); + synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); + }, + + // Test that changing the input type in the middle of a spin cancels the spin: + function() { + var inputEventCount = 0; + input.value = 0; + input.addEventListener("input", function(evt) { + ++inputEventCount; + if (inputEventCount == 3) { + input.type = "text" + var eventHandler = arguments.callee; + setTimeout(function() { + is(input.value, "-3", "Testing changing input type during a spin stops the spin"); + is(inputEventCount, 3, "Testing changing input type during a spin stops the spin input events"); + input.removeEventListener("input", eventHandler, false); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); + input.type = "number"; // restore + runNextSpinTest(); + }, SETTIMEOUT_DELAY); + } + }, false); + synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); + } +]; + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_number_rounding.html b/dom/html/test/forms/test_input_number_rounding.html new file mode 100644 index 000000000..16bc8ec52 --- /dev/null +++ b/dom/html/test/forms/test_input_number_rounding.html @@ -0,0 +1,120 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=783607 +--> +<head> + <title>Test rounding behaviour for <input type='number'></title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783607">Mozilla Bug 783607</a> +<p id="display"></p> +<div id="content"> + <input id=number type=number value=0 step=0.01 max=1> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 783607. + * This test checks that when <input type=number> has fractional step values, + * the values that a content author will see in their script will not have + * ugly rounding errors. + **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(); + SimpleTest.finish(); +}); + +/** + * We can _NOT_ generate these values by looping and simply incrementing a + * variable by 0.01 and stringifying it, since we'll end up with strings like + * "0.060000000000000005" due to the inability of binary floating point numbers + * to accurately represent decimal values. + */ +var stepVals = [ + "0", "0.01", "0.02", "0.03", "0.04", "0.05", "0.06", "0.07", "0.08", "0.09", + "0.1", "0.11", "0.12", "0.13", "0.14", "0.15", "0.16", "0.17", "0.18", "0.19", + "0.2", "0.21", "0.22", "0.23", "0.24", "0.25", "0.26", "0.27", "0.28", "0.29", + "0.3", "0.31", "0.32", "0.33", "0.34", "0.35", "0.36", "0.37", "0.38", "0.39", + "0.4", "0.41", "0.42", "0.43", "0.44", "0.45", "0.46", "0.47", "0.48", "0.49", + "0.5", "0.51", "0.52", "0.53", "0.54", "0.55", "0.56", "0.57", "0.58", "0.59", + "0.6", "0.61", "0.62", "0.63", "0.64", "0.65", "0.66", "0.67", "0.68", "0.69", + "0.7", "0.71", "0.72", "0.73", "0.74", "0.75", "0.76", "0.77", "0.78", "0.79", + "0.8", "0.81", "0.82", "0.83", "0.84", "0.85", "0.86", "0.87", "0.88", "0.89", + "0.9", "0.91", "0.92", "0.93", "0.94", "0.95", "0.96", "0.97", "0.98", "0.99", + "1" +]; + +var pgUpDnVals = [ + "0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1" +]; + +function test() { + var elem = document.getElementById("number"); + + elem.focus(); + + /** + * TODO: + * When <input type='number'> widget will have a widge we should test PAGE_UP, + * PAGE_DOWN, UP and DOWN keys. For the moment, there is no widget so those + * keys do not have any effect. + * The tests using those keys as marked as todo_is() hoping that at least part + * of them will fail when the widget will be implemented. + */ + +/* No other implementations implement this, so we don't either, for now. + Seems like it might be nice though. + + for (var i = 1; i < pgUpDnVals.length; ++i) { + synthesizeKey("VK_PAGE_UP", {}); + todo_is(elem.value, pgUpDnVals[i], "Test VK_PAGE_UP"); + is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]); + } + + for (var i = pgUpDnVals.length - 2; i >= 0; --i) { + synthesizeKey("VK_PAGE_DOWN", {}); + // TODO: this condition is there because the todo_is() below would pass otherwise. + if (stepVals[i] == 0) { continue; } + todo_is(elem.value, pgUpDnVals[i], "Test VK_PAGE_DOWN"); + is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]); + } +*/ + + for (var i = 1; i < stepVals.length; ++i) { + synthesizeKey("VK_UP", {}); + is(elem.value, stepVals[i], "Test VK_UP"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } + + for (var i = stepVals.length - 2; i >= 0; --i) { + synthesizeKey("VK_DOWN", {}); + // TODO: this condition is there because the todo_is() below would pass otherwise. + if (stepVals[i] == 0) { continue; } + is(elem.value, stepVals[i], "Test VK_DOWN"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } + + for (var i = 1; i < stepVals.length; ++i) { + elem.stepUp(); + is(elem.value, stepVals[i], "Test stepUp()"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } + + for (var i = stepVals.length - 2; i >= 0; --i) { + elem.stepDown(); + is(elem.value, stepVals[i], "Test stepDown()"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_number_validation.html b/dom/html/test/forms/test_input_number_validation.html new file mode 100644 index 000000000..5f551337b --- /dev/null +++ b/dom/html/test/forms/test_input_number_validation.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=827161 +--> +<head> + <title>Test validation of number control input</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="test_input_number_data.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=827161">Mozilla Bug 827161</a> +<p id="display"></p> +<div id="content"> + <input id="input" type="number" step="0.01" oninvalid="invalidEventHandler(event);"> + <input id="requiredinput" type="number" step="0.01" required + oninvalid="invalidEventHandler(event);"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 827161. + * This test checks that validation works correctly for <input type=number>. + **/ +SimpleTest.waitForExplicitFinish(); + +SimpleTest.waitForFocus(function() { + startTests(); + SimpleTest.finish(); +}); + +var elem; + +function runTest(test) { + elem.lang = test.langTag; + + gInvalid = false; // reset + var desc = `${test.desc} (lang='${test.langTag}', id='${elem.id}')`; + elem.value = 0; + elem.focus(); + elem.select(); + sendString(test.inputWithGrouping); + checkIsValid(elem, `${desc} with grouping separator`); + sendChar("a"); + checkIsInvalid(elem, `${desc} with grouping separator`); + + gInvalid = false; // reset + elem.value = 0; + elem.select(); + sendString(test.inputWithoutGrouping); + checkIsValid(elem, `${desc} without grouping separator`); + sendChar("a"); + checkIsInvalid(elem, `${desc} without grouping separator`); +} + +function runInvalidInputTest(test) { + elem.lang = test.langTag; + + gInvalid = false; // reset + var desc = `${test.desc} (lang='${test.langTag}', id='${elem.id}')`; + elem.value = 0; + elem.focus(); + elem.select(); + sendString(test.input); + checkIsInvalid(elem, `${desc} with invalid input ${test.input}`); +} + +function startTests() { + elem = document.getElementById("input"); + for (var test of tests) { + runTest(test); + } + for (var test of invalidTests) { + runInvalidInputTest(test); + } + elem = document.getElementById("requiredinput"); + for (var test of tests) { + runTest(test); + } + + gInvalid = false; // reset + elem.value = ""; + checkIsInvalidEmptyValue(elem, "empty value"); +} + +var gInvalid = false; + +function invalidEventHandler(e) +{ + is(e.type, "invalid", "Invalid event type should be 'invalid'"); + gInvalid = true; +} + +function checkIsValid(element, infoStr) +{ + ok(!element.validity.badInput, + "Element should not suffer from bad input for " + infoStr); + ok(element.validity.valid, "Element should be valid for " + infoStr); + ok(element.checkValidity(), "checkValidity() should return true for " + infoStr); + ok(!gInvalid, "The invalid event should not have been thrown for " + infoStr); + is(element.validationMessage, '', + "Validation message should be the empty string for " + infoStr); + ok(element.matches(":valid"), ":valid pseudo-class should apply for " + infoStr); +} + +function checkIsInvalid(element, infoStr) +{ + ok(element.validity.badInput, + "Element should suffer from bad input for " + infoStr); + if (element.id == "requiredinput") { + ok(element.validity.valueMissing, + "Element should suffer from value missing for " + infoStr); + } + ok(!element.validity.valid, "Element should not be valid for " + infoStr); + ok(!element.checkValidity(), "checkValidity() should return false for " + infoStr); + ok(gInvalid, "The invalid event should have been thrown for " + infoStr); + is(element.validationMessage, "Please enter a number.", + "Validation message is not the expected message for " + infoStr); + ok(element.matches(":invalid"), ":invalid pseudo-class should apply for " + infoStr); +} + +function checkIsInvalidEmptyValue(element, infoStr) +{ + ok(!element.validity.badInput, + "Element should not suffer from bad input for " + infoStr); + ok(element.validity.valueMissing, + "Element should suffer from value missing for " + infoStr); + ok(!element.validity.valid, "Element should not be valid for " + infoStr); + ok(!element.checkValidity(), "checkValidity() should return false for " + infoStr); + ok(gInvalid, "The invalid event should have been thrown for " + infoStr); + is(element.validationMessage, "Please enter a number.", + "Validation message is not the expected message for " + infoStr); + ok(element.matches(":invalid"), ":invalid pseudo-class should apply for " + infoStr); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_radio_indeterminate.html b/dom/html/test/forms/test_input_radio_indeterminate.html new file mode 100644 index 000000000..aa7ca21bf --- /dev/null +++ b/dom/html/test/forms/test_input_radio_indeterminate.html @@ -0,0 +1,109 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=885359 +--> +<head> + <title>Test for Bug 885359</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885359">Mozilla Bug 343444</a> +<p id="display"></p> +<form> + <input type="radio" id='radio1'/><br/> + + <input type="radio" id="g1radio1" name="group1"/> + <input type="radio" id="g1radio2" name="group1"/></br> + <input type="radio" id="g1radio3" name="group1"/></br> + + <input type="radio" id="g2radio1" name="group2"/> + <input type="radio" id="g2radio2" name="group2" checked/></br> +</form> +<script class="testbody" type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); + +var radio1 = document.getElementById("radio1"); +var g1radio1 = document.getElementById("g1radio1"); +var g1radio2 = document.getElementById("g1radio2"); +var g1radio3 = document.getElementById("g1radio3"); +var g2radio1 = document.getElementById("g2radio1"); +var g2radio2 = document.getElementById("g2radio2"); + +SimpleTest.waitForFocus(function() { + test(); + SimpleTest.finish(); +}); + +function verifyIndeterminateState(aElement, aIsIndeterminate, aMessage) { + is(aElement.mozMatchesSelector(':indeterminate'), aIsIndeterminate, aMessage); +} + +function test() { + // Initial State. + verifyIndeterminateState(radio1, true, + "Unchecked radio in its own group (no name attribute)"); + verifyIndeterminateState(g1radio1, true, "No selected radio in its group"); + verifyIndeterminateState(g1radio2, true, "No selected radio in its group"); + verifyIndeterminateState(g1radio3, true, "No selected radio in its group"); + verifyIndeterminateState(g2radio1, false, "Selected radio in its group"); + verifyIndeterminateState(g2radio2, false, "Selected radio in its group"); + + // Selecting radio buttion. + g1radio1.checked = true; + verifyIndeterminateState(g1radio1, false, + "Selecting a radio should affect all radios in the group"); + verifyIndeterminateState(g1radio2, false, + "Selecting a radio should affect all radios in the group"); + verifyIndeterminateState(g1radio3, false, + "Selecting a radio should affect all radios in the group"); + + // Changing the selected radio button. + g1radio3.checked = true; + verifyIndeterminateState(g1radio1, false, + "Selecting a radio should affect all radios in the group"); + verifyIndeterminateState(g1radio2, false, + "Selecting a radio should affect all radios in the group"); + verifyIndeterminateState(g1radio3, false, + "Selecting a radio should affect all radios in the group"); + + // Deselecting radio button. + g2radio2.checked = false; + verifyIndeterminateState(g2radio1, true, + "Deselecting a radio should affect all radios in the group"); + verifyIndeterminateState(g2radio2, true, + "Deselecting a radio should affect all radios in the group"); + + // Move a selected radio button to another group. + g1radio3.name = "group2"; + + // The radios' state in the original group becomes indeterminated. + verifyIndeterminateState(g1radio1, true, + "Removing a radio from a group should affect all radios in the group"); + verifyIndeterminateState(g1radio2, true, + "Removing a radio from a group should affect all radios in the group"); + + // The radios' state in the new group becomes determinated. + verifyIndeterminateState(g1radio3, false, + "Adding a radio from a group should affect all radios in the group"); + verifyIndeterminateState(g2radio1, false, + "Adding a radio from a group should affect all radios in the group"); + verifyIndeterminateState(g2radio2, false, + "Adding a radio from a group should affect all radios in the group"); + + // Change input type to 'text'. + g1radio3.type = "text"; + verifyIndeterminateState(g1radio3, false, + "Input type text does not have an indeterminate state"); + verifyIndeterminateState(g2radio1, true, + "Changing input type should affect all radios in the group"); + verifyIndeterminateState(g2radio2, true, + "Changing input type should affect all radios in the group"); +} +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/forms/test_input_radio_radiogroup.html b/dom/html/test/forms/test_input_radio_radiogroup.html new file mode 100644 index 000000000..86dd212b8 --- /dev/null +++ b/dom/html/test/forms/test_input_radio_radiogroup.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=343444 +--> +<head> + <title>Test for Bug 343444</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=343444">Mozilla Bug 343444</a> +<p id="display"></p> +<form> + <fieldset id="testradio"> + <input type="radio" name="testradio" id="start"></input> + <input type="text" name="testradio"></input> + <input type="text" name="testradio"></input> + <input type="radio" name="testradio"></input> + <input type="text" name="testradio"></input> + <input type="radio" name="testradio"></input> + <input type="text" name="testradio"></input> + <input type="radio" name="testradio"></input> + <input type="radio" name="testradio"></input> + <input type="text" name="testradio"></input> + </fieldset> + + <fieldset> + <input type="radio" name="testtwo" id="start2"></input> + <input type="radio" name="testtwo"></input> + <input type="radio" name="error" id="testtwo"></input> + <input type="radio" name="testtwo" id="end"></input> + </fieldset> + + <fieldset> + <input type="radio" name="testthree" id="start3"></input> + <input type="radio" name="errorthree" id="testthree"></input> + </fieldset> +</form> +<script class="testbody" type="text/javascript"> +/** Test for Bug 343444 **/ +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, startTest); +function startTest() { + document.getElementById("start").focus(); + var count=0; + while (count < 2) { + sendKey("DOWN"); + is(document.activeElement.type, "radio", "radioGroup should ignore non-radio input fields"); + if (document.activeElement.id == "start") { + count++; + } + } + + document.getElementById("start2").focus(); + count = 0; + while (count < 3) { + is(document.activeElement.name, "testtwo", + "radioGroup should only contain elements with the same @name") + sendKey("DOWN"); + count++; + } + + document.getElementById("start3").focus(); + sendKey("DOWN"); + is(document.activeElement.name, "testthree", "we don't have an infinite-loop"); + SimpleTest.finish(); +} +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/forms/test_input_radio_required.html b/dom/html/test/forms/test_input_radio_required.html new file mode 100644 index 000000000..e1ba42914 --- /dev/null +++ b/dom/html/test/forms/test_input_radio_required.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER} +--> +<head> + <title>Test for Bug 1100535</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1100535">Mozilla Bug 1100535</a> +<p id="display"></p> +<div id="content" style="display: none"> +<form> + <input type="radio" name="a"> +</form> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + var input = document.querySelector("input"); + input.setAttribute("required", "x"); + input.setAttribute("required", "y"); + is(document.forms[0].checkValidity(), false); + input.required = false; + is(document.forms[0].checkValidity(), true); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_range_attr_order.html b/dom/html/test/forms/test_input_range_attr_order.html new file mode 100644 index 000000000..3d3d6d6f7 --- /dev/null +++ b/dom/html/test/forms/test_input_range_attr_order.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=841941 +--> +<head> + <title>Test @min/@max/@step order for range</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841941">Mozilla Bug 841941</a> +<p id="display"></p> +<div id="content"> + <input type=range value=2 max=1.5 step=0.5> + <input type=range value=2 step=0.5 max=1.5> + <input type=range value=2 max=1.5 step=0.5> + <input type=range value=2 step=0.5 max=1.5> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 841941 + * This test checks that the order in which @min/@max/@step are specified in + * markup makes no difference to the value that <input type=range> will be + * given. Basically this checks that sanitization of the value does not occur + * until after the parser has finished with the element. + */ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(); + SimpleTest.finish(); +}); + +function test() { + var ranges = document.querySelectorAll("input[type=range]"); + for (var i = 0; i < ranges.length; i++) { + is(ranges.item(i).value, "1.5", "Check sanitization order for range " + i); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_range_key_events.html b/dom/html/test/forms/test_input_range_key_events.html new file mode 100644 index 000000000..efb1f7e4b --- /dev/null +++ b/dom/html/test/forms/test_input_range_key_events.html @@ -0,0 +1,210 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=843725 +--> +<head> + <title>Test key events for range</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=843725">Mozilla Bug 843725</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 843725 + * This test checks how the value of <input type=range> changes in response to + * various key events while it is in various states. + **/ +SimpleTest.waitForExplicitFinish(); + +// Turn off Spatial Navigation because it hijacks arrow keydown events: +SimpleTest.waitForFocus(function() { + SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() { + test(); + SimpleTest.finish(); + }); +}); + +const defaultMinimum = 0; +const defaultMaximum = 100; +const defaultStep = 1; + +// Helpers: +// For the sake of simplicity, we do not currently support fractional value, +// step, etc. + +function minimum(element) { + return Number(element.min || defaultMinimum); +} + +function maximum(element) { + return Number(element.max || defaultMaximum); +} + +function range(element) { + var max = maximum(element); + var min = minimum(element); + if (max < min) { + return 0; + } + return max - min; +} + +function defaultValue(element) { + return minimum(element) + range(element)/2; +} + +function value(element) { + return Number(element.value || defaultValue(element)); +} + +function step(element) { + var step = Number(element.step || defaultStep); + return step <= 0 ? defaultStep : step; +} + +function clampToRange(value, element) { + var min = minimum(element); + var max = maximum(element); + if (max < min) { + return min; + } + if (value < min) { + return min; + } + if (value > max) { + return max; + } + return value; +} + +// Functions used to specify expected test results: + +function valuePlusStep(element) { + return clampToRange(value(element) + step(element), element); +} + +function valueMinusStep(element) { + return clampToRange(value(element) - step(element), element); +} + +/** + * Returns the current value of the range plus whichever is greater of either + * 10% of the range or its current step value, clamped to the range's minimum/ + * maximum. The reason for using the step if it is greater than 10% of the + * range is because otherwise the PgUp/PgDn keys would do nothing in that case. + */ +function valuePlusTenPctOrStep(element) { + var tenPct = range(element)/10; + var stp = step(element); + return clampToRange(value(element) + Math.max(tenPct, stp), element); +} + +function valueMinusTenPctOrStep(element) { + var tenPct = range(element)/10; + var stp = step(element); + return clampToRange(value(element) - Math.max(tenPct, stp), element); +} + +// Test table: + +const LTR = "ltr"; +const RTL = "rtl"; + +var testTable = [ + ["VK_LEFT", LTR, valueMinusStep], + ["VK_LEFT", RTL, valuePlusStep], + ["VK_RIGHT", LTR, valuePlusStep], + ["VK_RIGHT", RTL, valueMinusStep], + ["VK_UP", LTR, valuePlusStep], + ["VK_UP", RTL, valuePlusStep], + ["VK_DOWN", LTR, valueMinusStep], + ["VK_DOWN", RTL, valueMinusStep], + ["VK_PAGE_UP", LTR, valuePlusTenPctOrStep], + ["VK_PAGE_UP", RTL, valuePlusTenPctOrStep], + ["VK_PAGE_DOWN", LTR, valueMinusTenPctOrStep], + ["VK_PAGE_DOWN", RTL, valueMinusTenPctOrStep], + ["VK_HOME", LTR, minimum], + ["VK_HOME", RTL, minimum], + ["VK_END", LTR, maximum], + ["VK_END", RTL, maximum], +] + +function test() { + var elem = document.createElement("input"); + elem.type = "range"; + + var content = document.getElementById("content"); + content.appendChild(elem); + elem.focus(); + + for (test of testTable) { + var [key, dir, expectedFunc] = test; + var oldVal, expectedVal; + + elem.step = "2"; + elem.style.direction = dir; + var flush = document.body.clientWidth; + + // Start at middle: + elem.value = oldVal = defaultValue(elem); + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the midpoint (" + oldVal + ")"); + + // Same again: + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range"); + + // Start at maximum: + elem.value = oldVal = maximum(elem); + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the maximum (" + oldVal + ")"); + + // Same again: + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range"); + + // Start at minimum: + elem.value = oldVal = minimum(elem); + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the minimum (" + oldVal + ")"); + + // Same again: + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range"); + + // Test for a step value that is greater than 10% of the range: + elem.step = 20; + elem.value = 60; + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with a step that is greater than 10% of the range (step=" + elem.step + ")"); + + // Same again: + expectedVal = expectedFunc(elem); + synthesizeKey(key, {}); + is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range"); + + // reset step: + elem.step = 2; + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_range_mouse_and_touch_events.html b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html new file mode 100644 index 000000000..4073fe139 --- /dev/null +++ b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html @@ -0,0 +1,199 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=846380 +--> +<head> + <title>Test mouse and touch events for range</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <style> + /* synthesizeMouse and synthesizeFunc uses getBoundingClientRect. We set + * the following properties to avoid fractional values in the rect returned + * by getBoundingClientRect in order to avoid rounding that would occur + * when event coordinates are internally converted to be relative to the + * top-left of the element. (Such rounding would make it difficult to + * predict exactly what value the input should take on for events at + * certain coordinates.) + */ + input { margin: 0 ! important; width: 200px ! important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=846380">Mozilla Bug 846380</a> +<p id="display"></p> +<div id="content"> + <input id="range" type="range"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 846380 + * This test checks how the value of <input type=range> changes in response to + * various mouse and touch events. + **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(synthesizeMouse, "click", "mousedown", "mousemove", "mouseup"); + test(synthesizeTouch, "tap", "touchstart", "touchmove", "touchend"); + SimpleTest.finish(); +}); + +const MIDDLE_OF_RANGE = "50"; +const MINIMUM_OF_RANGE = "0"; +const MAXIMUM_OF_RANGE = "100"; +const QUARTER_OF_RANGE = "25"; +const THREE_QUARTERS_OF_RANGE = "75"; + +function flush() { + // Flush style, specifically to flush the 'direction' property so that the + // browser uses the new value for thumb positioning. + var flush = document.body.clientWidth; +} + +function test(synthesizeFunc, clickOrTap, startName, moveName, endName) { + var elem = document.getElementById("range"); + elem.focus(); + flush(); + + var width = parseFloat(window.getComputedStyle(elem).width); + var height = parseFloat(window.getComputedStyle(elem).height); + var borderLeft = parseFloat(window.getComputedStyle(elem).borderLeftWidth); + var borderTop = parseFloat(window.getComputedStyle(elem).borderTopWidth); + var paddingLeft = parseFloat(window.getComputedStyle(elem).paddingLeft); + var paddingTop = parseFloat(window.getComputedStyle(elem).paddingTop); + + // Extrema for mouse/touch events: + var midY = height / 2 + borderTop + paddingTop; + var minX = borderLeft + paddingLeft; + var midX = minX + width / 2; + var maxX = minX + width; + + // Test click/tap in the middle of the range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, {}); + is(elem.value, MIDDLE_OF_RANGE, "Test " + clickOrTap + " in middle of range"); + + // Test mouse/touch dragging of ltr range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + synthesizeFunc(elem, minX, midY, { type: moveName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to left of ltr range"); + + synthesizeFunc(elem, maxX, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to right of ltr range (" + moveName + ")"); + + synthesizeFunc(elem, maxX, midY, { type: endName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to right of ltr range (" + endName + ")"); + + // Test mouse/touch dragging of rtl range: + elem.value = QUARTER_OF_RANGE; + elem.style.direction = "rtl"; + flush(); + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of rtl range"); + synthesizeFunc(elem, minX, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to left of rtl range"); + + synthesizeFunc(elem, maxX, midY, { type: moveName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to right of rtl range (" + moveName + ")"); + + synthesizeFunc(elem, maxX, midY, { type: endName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to right of rtl range (" + endName + ")"); + + elem.style.direction = "ltr"; // reset direction + flush(); + + // Test mouse/touch capturing by moving pointer to a position outside the range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + synthesizeFunc(elem, maxX+100, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to position outside range (" + moveName + ")"); + + synthesizeFunc(elem, maxX+100, midY, { type: endName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to position outside range (" + endName + ")"); + + // Test mouse/touch capturing by moving pointer to a position outside a rtl range: + elem.value = QUARTER_OF_RANGE; + elem.style.direction = "rtl"; + flush(); + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of rtl range"); + synthesizeFunc(elem, maxX+100, midY, { type: moveName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to position outside range (" + moveName + ")"); + + synthesizeFunc(elem, maxX+100, midY, { type: endName }); + is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to position outside range (" + endName + ")"); + + elem.style.direction = "ltr"; // reset direction + flush(); + + // Test mouse/touch events with modifiers are ignored: + var modifiers = ["shiftKey", "ctrlKey", "altKey", "metaKey", "accelKey", "altGrKey", "fnKey", "osKey"]; + for (var modifier of modifiers) { + elem.value = QUARTER_OF_RANGE; + var eventParams = {}; + eventParams[modifier] = true; + synthesizeFunc(elem, midX, midY, eventParams); + is(elem.value, QUARTER_OF_RANGE, "Test " + clickOrTap + " in the middle of range with " + modifier + " modifier key is ignored"); + } + + // Test that preventDefault() works: + function preventDefault(e) { + e.preventDefault(); + } + elem.value = QUARTER_OF_RANGE; + elem.addEventListener(startName, preventDefault, false); + synthesizeFunc(elem, midX, midY, {}); + is(elem.value, QUARTER_OF_RANGE, "Test that preventDefault() works"); + elem.removeEventListener(startName, preventDefault, false); + + // Test that changing the input type in the middle of a drag cancels the drag: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + elem.type = "text"; + is(elem.value, QUARTER_OF_RANGE, "Test that changing the input type cancels a drag"); + synthesizeFunc(elem, midX, midY, { type: endName }); + is(elem.value, QUARTER_OF_RANGE, "Test that changing the input type cancels a drag (after " + endName + ")"); + elem.type = "range"; + + // Check that we do not drag when the mousedown/touchstart occurs outside the range: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, maxX+100, midY, { type: startName }); + is(elem.value, QUARTER_OF_RANGE, "Test " + startName + " outside range doesn't change its value"); + synthesizeFunc(elem, midX, midY, { type: moveName }); + is(elem.value, QUARTER_OF_RANGE, "Test dragging is not occurring when " + startName + " was outside range"); + + synthesizeFunc(elem, midX, midY, { type: endName }); + is(elem.value, QUARTER_OF_RANGE, "Test dragging is not occurring when " + startName + " was outside range"); + + elem.focus(); // RESTORE FOCUS SO WE GET THE FOCUSED STYLE FOR TESTING OR ELSE minX/midX/maxX may be wrong! + + // Check what happens when a value changing key is pressed during a drag: + elem.value = QUARTER_OF_RANGE; + synthesizeFunc(elem, midX, midY, { type: startName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range"); + synthesizeKey("VK_HOME", {}); + // The VK_HOME tests are disabled until I can figure out why they fail on Android -jwatt + //is(elem.value, MINIMUM_OF_RANGE, "Test VK_HOME during a drag sets the value to the minimum of the range"); + synthesizeFunc(elem, midX+100, midY, { type: moveName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test " + moveName + " outside range after key press that occurred during a drag changes the value"); + synthesizeFunc(elem, midX, midY, { type: moveName }); + is(elem.value, MIDDLE_OF_RANGE, "Test " + moveName + " in middle of range"); + synthesizeKey("VK_HOME", {}); + //is(elem.value, MINIMUM_OF_RANGE, "Test VK_HOME during a drag sets the value to the minimum of the range (second time)"); + synthesizeFunc(elem, maxX+100, midY, { type: endName }); + is(elem.value, MAXIMUM_OF_RANGE, "Test " + endName + " outside range after key press that occurred during a drag changes the value"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_range_rounding.html b/dom/html/test/forms/test_input_range_rounding.html new file mode 100644 index 000000000..dfbca36ce --- /dev/null +++ b/dom/html/test/forms/test_input_range_rounding.html @@ -0,0 +1,106 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=853525 +--> +<head> + <title>Test key events for range</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=853525">Mozilla Bug 853525</a> +<p id="display"></p> +<div id="content"> + <input id=range type=range value=0 step=0.01 max=1> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** + * Test for Bug 853525 + * This test checks that when <input type=range> has fractional step values, + * the values that a content author will see in their script will not have + * ugly rounding errors. + **/ +SimpleTest.waitForExplicitFinish(); +// Turn off Spatial Navigation because it hijacks arrow keydown events: +SimpleTest.waitForFocus(function() { + SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() { + test(); + SimpleTest.finish(); + }); +}); + +/** + * We can _NOT_ generate these values by looping and simply incrementing a + * variable by 0.01 and stringifying it, since we'll end up with strings like + * "0.060000000000000005" due to the inability of binary floating point numbers + * to accurately represent decimal values. + */ +var stepVals = [ + "0", "0.01", "0.02", "0.03", "0.04", "0.05", "0.06", "0.07", "0.08", "0.09", + "0.1", "0.11", "0.12", "0.13", "0.14", "0.15", "0.16", "0.17", "0.18", "0.19", + "0.2", "0.21", "0.22", "0.23", "0.24", "0.25", "0.26", "0.27", "0.28", "0.29", + "0.3", "0.31", "0.32", "0.33", "0.34", "0.35", "0.36", "0.37", "0.38", "0.39", + "0.4", "0.41", "0.42", "0.43", "0.44", "0.45", "0.46", "0.47", "0.48", "0.49", + "0.5", "0.51", "0.52", "0.53", "0.54", "0.55", "0.56", "0.57", "0.58", "0.59", + "0.6", "0.61", "0.62", "0.63", "0.64", "0.65", "0.66", "0.67", "0.68", "0.69", + "0.7", "0.71", "0.72", "0.73", "0.74", "0.75", "0.76", "0.77", "0.78", "0.79", + "0.8", "0.81", "0.82", "0.83", "0.84", "0.85", "0.86", "0.87", "0.88", "0.89", + "0.9", "0.91", "0.92", "0.93", "0.94", "0.95", "0.96", "0.97", "0.98", "0.99", + "1" +]; + +var pgUpDnVals = [ + "0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1" +]; + +function test() { + var elem = document.getElementById("range"); + + elem.focus(); + + for (var i = 1; i < pgUpDnVals.length; ++i) { + synthesizeKey("VK_PAGE_UP", {}); + is(elem.value, pgUpDnVals[i], "Test VK_PAGE_UP"); + is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]); + } + + for (var i = pgUpDnVals.length - 2; i >= 0; --i) { + synthesizeKey("VK_PAGE_DOWN", {}); + is(elem.value, pgUpDnVals[i], "Test VK_PAGE_DOWN"); + is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]); + } + + for (var i = 1; i < stepVals.length; ++i) { + synthesizeKey("VK_UP", {}); + is(elem.value, stepVals[i], "Test VK_UP"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } + + for (var i = stepVals.length - 2; i >= 0; --i) { + synthesizeKey("VK_DOWN", {}); + is(elem.value, stepVals[i], "Test VK_DOWN"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } + + for (var i = 1; i < stepVals.length; ++i) { + elem.stepUp(); + is(elem.value, stepVals[i], "Test stepUp()"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } + + for (var i = stepVals.length - 2; i >= 0; --i) { + elem.stepDown(); + is(elem.value, stepVals[i], "Test stepDown()"); + is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_sanitization.html b/dom/html/test/forms/test_input_sanitization.html new file mode 100644 index 000000000..cd9877fdf --- /dev/null +++ b/dom/html/test/forms/test_input_sanitization.html @@ -0,0 +1,565 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=549475 +--> +<head> + <title>Test for Bug 549475</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=549475">Mozilla Bug 549475</a> +<p id="display"></p> +<pre id="test"> +<div id='content'> + <form> + </form> +</div> +<script type="application/javascript"> + +SimpleTest.requestLongerTimeout(2); + +/** + * This files tests the 'value sanitization algorithm' for the various input + * types. Note that an input's value is affected by more than just its type's + * value sanitization algorithm; e.g. some type=range has actions that the user + * agent must perform to change the element's value to avoid underflow/overflow + * and step mismatch (when possible). We specifically avoid triggering these + * other actions here so that this test only tests the value sanitization + * algorithm for the various input types. + * + * XXXjwatt splitting out testing of the value sanitization algorithm and + * "other things" that affect .value makes it harder to know what we're testing + * and what we've missed, because what's included in the value sanitization + * algorithm and what's not is different from input type to input type. It + * seems to me it would be better to have a test (maybe one per type) focused + * on testing .value for permutations of all other inputs that can affect it. + * The value sanitization algorithm is just an internal spec concept after all. + */ + +// We buffer up the results of sets of sub-tests, and avoid outputting log +// entries for them all if they all pass. Otherwise, we have an enormous amount +// of test output. + +var delayedTests = []; +var anyFailedDelayedTests = false; + +function delayed_is(actual, expected, description) +{ + var result = actual == expected; + delayedTests.push({ actual: actual, expected: expected, description: description }); + if (!result) { + anyFailedDelayedTests = true; + } +} + +function flushDelayedTests(description) +{ + if (anyFailedDelayedTests) { + info("Outputting individual results for \"" + description + "\" due to failures in subtests"); + for (var test of delayedTests) { + is(test.actual, test.expected, test.description); + } + } else { + ok(true, description + " (" + delayedTests.length + " subtests)"); + } + delayedTests = []; + anyFailedDelayedTests = false; +} + +// We are excluding "file" because it's too different from the other types. +// And it has no sanitizing algorithm. +var inputTypes = +[ + "text", "password", "search", "tel", "hidden", "checkbox", "radio", + "submit", "image", "reset", "button", "email", "url", "number", "date", + "time", "range", "color", "month", "week", "datetime-local" +]; + +var valueModeValue = +[ + "text", "search", "url", "tel", "email", "password", "date", "datetime", + "month", "week", "time", "datetime-local", "number", "range", "color", +]; + +function sanitizeDate(aValue) +{ + // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-date-string + function getNumbersOfDaysInMonth(aMonth, aYear) { + if (aMonth === 2) { + return (aYear % 400 === 0 || (aYear % 100 != 0 && aYear % 4 === 0)) ? 29 : 28; + } + return (aMonth === 1 || aMonth === 3 || aMonth === 5 || aMonth === 7 || + aMonth === 8 || aMonth === 10 || aMonth === 12) ? 31 : 30; + } + + var match = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})$/.exec(aValue); + if (!match) { + return ""; + } + var year = Number(match[1]); + if (year === 0) { + return ""; + } + var month = Number(match[2]); + if (month > 12 || month < 1) { + return ""; + } + var day = Number(match[3]); + return 1 <= day && day <= getNumbersOfDaysInMonth(month, year) ? aValue : ""; +} + +function sanitizeTime(aValue) +{ + // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string + var match = /^([0-9]{2}):([0-9]{2})(.*)$/.exec(aValue); + if (!match) { + return ""; + } + var hours = match[1]; + if (hours < 0 || hours > 23) { + return ""; + } + var minutes = match[2]; + if (minutes < 0 || minutes > 59) { + return ""; + } + var other = match[3]; + if (other == "") { + return aValue; + } + match = /^:([0-9]{2})(.*)$/.exec(other); + if (!match) { + return ""; + } + var seconds = match[1]; + if (seconds < 0 || seconds > 59) { + return ""; + } + var other = match[2]; + if (other == "") { + return aValue; + } + match = /^.([0-9]{1,3})$/.exec(other); + if (!match) { + return ""; + } + return aValue; +} + +function sanitizeDateTimeLocal(aValue) +{ + // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-local-date-and-time-string + if (aValue.length < 16) { + return ""; + } + + var separator = aValue[10]; + if (separator != "T" && separator != " ") { + return ""; + } + + var [date, time] = aValue.split(separator); + if (!sanitizeDate(date)) { + return ""; + } + + if (!sanitizeTime(time)) { + return ""; + } + + // Normalize datetime-local string. + // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-normalised-local-date-and-time-string + if (separator == " ") { + aValue = date + "T" + time; + } + + if (aValue.length == 16) { + return aValue; + } + + if (aValue.length > 19) { + var milliseconds = aValue.substring(20); + if (Number(milliseconds) != 0) { + return aValue; + } + aValue = aValue.slice(0, 19); + } + + var seconds = aValue.substring(17); + if (Number(seconds) != 0) { + return aValue; + } + aValue = aValue.slice(0, 16); + + return aValue; +} + +function sanitizeValue(aType, aValue) +{ + // http://www.whatwg.org/html/#value-sanitization-algorithm + switch (aType) { + case "text": + case "password": + case "search": + case "tel": + return aValue.replace(/[\n\r]/g, ""); + case "url": + case "email": + return aValue.replace(/[\n\r]/g, "").replace(/^[\u0020\u0009\t\u000a\u000c\u000d]+|[\u0020\u0009\t\u000a\u000c\u000d]+$/g, ""); + case "number": + return isNaN(Number(aValue)) ? "" : aValue; + case "range": + var defaultMinimum = 0; + var defaultMaximum = 100; + var value = Number(aValue); + if (isNaN(value)) { + return ((defaultMaximum - defaultMinimum)/2).toString(); // "50" + } + if (value < defaultMinimum) { + return defaultMinimum.toString(); + } + if (value > defaultMaximum) { + return defaultMaximum.toString(); + } + return aValue; + case "date": + return sanitizeDate(aValue); + case "time": + return sanitizeTime(aValue); + case "month": + // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-month-string + var match = /^([0-9]{4,})-([0-9]{2})$/.exec(aValue); + if (!match) { + return ""; + } + var year = Number(match[1]); + if (year === 0) { + return ""; + } + var month = Number(match[2]); + if (month > 12 || month < 1) { + return ""; + } + return aValue; + case "week": + // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-week-string + function isLeapYear(aYear) { + return ((aYear % 4 == 0) && (aYear % 100 != 0)) || (aYear % 400 == 0); + } + function getDayofWeek(aYear, aMonth, aDay) { /* 0 = Sunday */ + // Tomohiko Sakamoto algorithm. + var monthTable = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]; + aYear -= Number(aMonth < 3); + + return (aYear + parseInt(aYear / 4) - parseInt(aYear / 100) + + parseInt(aYear / 400) + monthTable[aMonth - 1] + aDay) % 7; + } + function getMaximumWeekInYear(aYear) { + var day = getDayofWeek(aYear, 1, 1); + return day == 4 || (day == 3 && isLeapYear(aYear)) ? 53 : 52; + } + + var match = /^([0-9]{4,})-W([0-9]{2})$/.exec(aValue); + if (!match) { + return ""; + } + var year = Number(match[1]); + if (year === 0) { + return ""; + } + var week = Number(match[2]); + if (week > 53 || month < 1) { + return ""; + } + return 1 <= week && week <= getMaximumWeekInYear(year) ? aValue : ""; + case "datetime-local": + return sanitizeDateTimeLocal(aValue); + case "color": + return /^#[0-9A-Fa-f]{6}$/.exec(aValue) ? aValue.toLowerCase() : "#000000"; + default: + return aValue; + } +} + +function checkSanitizing(element, inputTypeDescription) +{ + var testData = + [ + // For text, password, search, tel, email: + "\n\rfoo\n\r", + "foo\n\rbar", + " foo ", + " foo\n\r bar ", + // For url: + "\r\n foobar \n\r", + "\u000B foo \u000B", + "\u000A foo \u000A", + "\u000C foo \u000C", + "\u000d foo \u000d", + "\u0020 foo \u0020", + " \u0009 foo \u0009 ", + // For number and range: + "42", + "13.37", + "1.234567898765432", + "12foo", + "1e2", + "3E42", + // For date: + "1970-01-01", + "1234-12-12", + "1234567890-01-02", + "2012-12-31", + "2012-02-29", + "2000-02-29", + "1234", + "1234-", + "12345", + "1234-01", + "1234-012", + "1234-01-", + "12-12", + "999-01-01", + "1234-56-78-91", + "1234-567-78", + "1234--7-78", + "abcd-12-12", + "thisinotadate", + "2012-13-01", + "1234-12-42", + " 2012-13-01", + " 123-01-01", + "2012- 3-01", + "12- 10- 01", + " 12-0-1", + "2012-3-001", + "2012-12-00", + "2012-12-1r", + "2012-11-31", + "2011-02-29", + "2100-02-29", + "a2000-01-01", + "2000a-01-0'", + "20aa00-01-01", + "2000a2000-01-01", + "2000-1-1", + "2000-1-01", + "2000-01-1", + "2000-01-01 ", + "2000- 01-01", + "-1970-01-01", + "0000-00-00", + "0001-00-00", + "0000-01-01", + "1234-12 12", + "1234 12-12", + "1234 12 12", + // For time: + "1", + "10", + "10:", + "10:1", + "21:21", + ":21:21", + "-21:21", + " 21:21", + "21-21", + "21:21:", + "21:211", + "121:211", + "21:21 ", + "00:00", + "-1:00", + "24:00", + "00:60", + "01:01", + "23:59", + "99:99", + "8:30", + "19:2", + "19:a2", + "4c:19", + "10:.1", + "1.:10", + "13:37:42", + "13:37.42", + "13:37:42 ", + "13:37:42.", + "13:37:61.", + "13:37:00", + "13:37:99", + "13:37:b5", + "13:37:-1", + "13:37:.1", + "13:37:1.", + "13:37:42.001", + "13:37:42.001", + "13:37:42.abc", + "13:37:42.00c", + "13:37:42.a23", + "13:37:42.12e", + "13:37:42.1e1", + "13:37:42.e11", + "13:37:42.1", + "13:37:42.99", + "13:37:42.0", + "13:37:42.00", + "13:37:42.000", + "13:37:42.-1", + "13:37:42.1.1", + "13:37:42.1,1", + "13:37:42.", + "foo12:12", + "13:37:42.100000000000", + // For color + "#00ff00", + "#000000", + "red", + "#0f0", + "#FFFFAA", + "FFAABB", + "fFAaBb", + "FFAAZZ", + "ABCDEF", + "#7654321", + // For month + "1970-01", + "1234-12", + "123456789-01", + "2013-13", + "0000-00", + "2015-00", + "0001-01", + "1-1", + "888-05", + "2013-3", + "2013-may", + "2000-1a", + "2013-03-13", + "december", + "abcdef", + "12", + " 2013-03", + "2013 - 03", + "2013 03", + "2013/03", + // For week + "1970-W01", + "1970-W53", + "1964-W53", + "1900-W10", + "2004-W53", + "2065-W53", + "2099-W53", + "2010-W53", + "2016-W30", + "1900-W3", + "2016-w30", + "2016-30", + "16-W30", + "2016-Week30", + "2000-100", + "0000-W01", + "00-W01", + "123456-W05", + "1985-W100", + "week", + // For datetime-local + "1970-01-01T00:00", + "1970-01-01Z12:00", + "1970-01-01 00:00:00", + "1970-01-01T00:00:00.0", + "1970-01-01T00:00:00.00", + "1970-01-01T00:00:00.000", + "1970-01-01 00:00:00.20", + "1234567-01-01T12:00", + "2016-13-01T12:00", + "2016-12-32T12:00", + "2016-11-08 15:40:30.0", + "2016-11-08T15:40:30.00", + "2016-11-07T17:30:10", + "2016-12-1T12:45", + "2016-12-01T12:45:30.123456", + "2016-12-01T24:00", + "2016-12-01T12:88:30", + "2016-12-01T12:30:99", + "2016-12-01T12:30:100", + "2016-12-01", + "2016-12-01T", + "2016-Dec-01T00:00", + "12-05-2016T00:00", + "datetime-local" + ]; + + for (value of testData) { + element.setAttribute('value', value); + delayed_is(element.value, sanitizeValue(type, value), + "The value has not been correctly sanitized for type=" + type); + delayed_is(element.getAttribute('value'), value, + "The content value should not have been sanitized"); + + if (type in valueModeValue) { + element.setAttribute('value', 'tulip'); + element.value = value; + delayed_is(element.value, sanitizeValue(type, value), + "The value has not been correctly sanitized for type=" + type); + delayed_is(element.getAttribute('value'), 'tulip', + "The content value should not have been sanitized"); + } + + element.setAttribute('value', ''); + form.reset(); + element.type = 'checkbox'; // We know this type has no sanitizing algorithm. + element.setAttribute('value', value); + delayed_is(element.value, value, "The value should not have been sanitized"); + element.type = type; + delayed_is(element.value, sanitizeValue(type, value), + "The value has not been correctly sanitized for type=" + type); + delayed_is(element.getAttribute('value'), value, + "The content value should not have been sanitized"); + + element.setAttribute('value', ''); + form.reset(); + element.setAttribute('value', value); + form.reset(); + delayed_is(element.value, sanitizeValue(type, value), + "The value has not been correctly sanitized for type=" + type); + delayed_is(element.getAttribute('value'), value, + "The content value should not have been sanitized"); + + // Cleaning-up. + element.setAttribute('value', ''); + form.reset(); + } + + flushDelayedTests(inputTypeDescription); +} + +for (type of inputTypes) { + var form = document.forms[0]; + var element = document.createElement("input"); + element.style.display = "none"; + element.type = type; + form.appendChild(element); + + checkSanitizing(element, "type=" + type + ", no frame, no editor"); + + element.style.display = ""; + checkSanitizing(element, "type=" + type + ", frame, no editor"); + + element.focus(); + element.blur(); + checkSanitizing(element, "type=" + type + ", frame, editor"); + + element.style.display = "none"; + checkSanitizing(element, "type=" + type + ", no frame, editor"); + + form.removeChild(element); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html b/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html new file mode 100644 index 000000000..829daa8c9 --- /dev/null +++ b/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=829606 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 829606</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript;version=1.7"> + + /** Test for Bug 829606 **/ + /* + * This test checks that setting .value on an text field (input or textarea) + * doesn't scroll the field to its beginning. + */ + + SimpleTest.waitForExplicitFinish(); + + var gTestRunner = null; + + function test(aElementName) + { + var element = document.getElementsByTagName(aElementName)[0]; + element.focus(); + + var baseSnapshot = snapshotWindow(window); + + // This is a sanity check. + var s2 = snapshotWindow(window); + var results = compareSnapshots(baseSnapshot, snapshotWindow(window), true); + ok(results[0], "sanity check: screenshots should be the same"); + + element.selectionStart = element.selectionEnd = element.value.length; + + setTimeout(function() { + synthesizeKey('f', {}); + + var selectionAtTheEndSnapshot = snapshotWindow(window); + results = compareSnapshots(baseSnapshot, selectionAtTheEndSnapshot, false); + ok(results[0], "after appending a character, string should have changed"); + + element.value = element.value; + var tmpSnapshot = snapshotWindow(window); + + results = compareSnapshots(baseSnapshot, tmpSnapshot, false); + ok(results[0], "re-settig the value should change nothing"); + + results = compareSnapshots(selectionAtTheEndSnapshot, tmpSnapshot, true); + ok(results[0], "re-settig the value should change nothing"); + + element.selectionStart = element.selectionEnd = 0; + element.blur(); + + gTestRunner.next(); + }, 0); + } + + // This test checks that when a textarea has a long list of values and the + // textarea's value is then changed, the values are shown correctly. + function testCorrectUpdateOnScroll() + { + var textarea = document.createElement('textarea'); + textarea.rows = 5; + textarea.cols = 10; + textarea.value = 'a\nb\nc\nd'; + document.getElementById('content').appendChild(textarea); + + var baseSnapshot = snapshotWindow(window); + + textarea.value = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n'; + textarea.selectionStart = textarea.selectionEnd = textarea.value.length; + + var fullSnapshot = snapshotWindow(window); + var results = compareSnapshots(baseSnapshot, fullSnapshot, false); + ok(results[0], "sanity check: screenshots should not be the same"); + + textarea.value = 'a\nb\nc\nd'; + + var tmpSnapshot = snapshotWindow(window); + results = compareSnapshots(baseSnapshot, tmpSnapshot, true); + ok(results[0], "textarea view should look like the beginning"); + + setTimeout(function() { + gTestRunner.next(); + }, 0); + } + + function runTest() + { + test('input'); + yield undefined; + test('textarea'); + yield undefined; + testCorrectUpdateOnScroll(); + yield undefined; + SimpleTest.finish(); + yield undefined; + } + + gTestRunner = runTest(); + + SimpleTest.waitForFocus(function() { + gTestRunner.next(); + });; + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=829606">Mozilla Bug 829606</a> +<p id="display"></p> +<div id="content"> + <textarea rows='1' cols='5' style='-moz-appearance:none;'>this is a \n long text</textarea> + <input size='5' value="this is a very long text" style='-moz-appearance:none;'> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_time_focus_blur_events.html b/dom/html/test/forms/test_input_time_focus_blur_events.html new file mode 100644 index 000000000..483741477 --- /dev/null +++ b/dom/html/test/forms/test_input_time_focus_blur_events.html @@ -0,0 +1,82 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1301306 +--> +<head> +<title>Test for Bug 1301306</title> +<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a> +<p id="display"></p> +<div id="content"> +<input type="time" id="input_time" onfocus="++focusEvent" onblur="++blurEvent" + onfocusin="++focusInEvent" onfocusout="++focusOutEvent"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** + * Test for Bug 1301306. + * This test checks that when moving inside the time input element, e.g. jumping + * through the inner text boxes, does not fire extra focus/blur events. + **/ + +var focusEvent = 0; +var focusInEvent = 0; +var focusOutEvent = 0; +var blurEvent = 0; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + test(); + SimpleTest.finish(); +}); + +function test() { + var time = document.getElementById("input_time"); + time.focus(); + is(focusEvent, 1, "time input element should have dispatched focus event."); + is(focusInEvent, 1, "time input element should have dispatched focusin event."); + is(focusOutEvent, 0, "time input element should not have dispatched focusout event."); + is(blurEvent, 0, "time input element should not have dispatched blur event."); + + // Move around inside the input element's input box. + synthesizeKey("VK_TAB", {}); + is(focusEvent, 1, "time input element should not have dispatched focus event."); + is(focusInEvent, 1, "time input element should have dispatched focusin event."); + is(focusOutEvent, 0, "time input element should not have dispatched focusout event."); + is(blurEvent, 0, "time input element should not have dispatched blur event."); + + synthesizeKey("VK_RIGHT", {}); + is(focusEvent, 1, "time input element should not have dispatched focus event."); + is(focusInEvent, 1, "time input element should have dispatched focusin event."); + is(focusOutEvent, 0, "time input element should not have dispatched focusout event."); + is(blurEvent, 0, "time input element should not have dispatched blur event."); + + synthesizeKey("VK_LEFT", {}); + is(focusEvent, 1, "time input element should not have dispatched focus event."); + is(focusInEvent, 1, "time input element should have dispatched focusin event."); + is(focusOutEvent, 0, "time input element should not have dispatched focusout event."); + is(blurEvent, 0, "time input element should not have dispatched blur event."); + + synthesizeKey("VK_RIGHT", {}); + is(focusEvent, 1, "time input element should not have dispatched focus event."); + is(focusInEvent, 1, "time input element should have dispatched focusin event."); + is(focusOutEvent, 0, "time input element should not have dispatched focusout event."); + is(blurEvent, 0, "time input element should not have dispatched blur event."); + + time.blur(); + is(focusEvent, 1, "time input element should not have dispatched focus event."); + is(focusInEvent, 1, "time input element should have dispatched focusin event."); + is(focusOutEvent, 1, "time input element should not have dispatched focusout event."); + is(blurEvent, 1, "time input element should have dispatched blur event."); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_time_key_events.html b/dom/html/test/forms/test_input_time_key_events.html new file mode 100644 index 000000000..755db38ff --- /dev/null +++ b/dom/html/test/forms/test_input_time_key_events.html @@ -0,0 +1,197 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1288591 +--> +<head> + <title>Test key events for time control</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a> +<p id="display"></p> +<div id="content"> + <input id="input" type="time"> +</div> +<pre id="test"> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); +// Turn off Spatial Navigation because it hijacks arrow keydown events: +SimpleTest.waitForFocus(function() { + SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() { + test(); + SimpleTest.finish(); + }); +}); + +var testData = [ + /** + * keys: keys to send to the input element. + * initialVal: initial value set to the input element. + * expectedVal: expected value of the input element after sending the keys. + */ + { + // Type 1030 and select AM. + keys: ["1030", "VK_DOWN"], + initialVal: "", + expectedVal: "10:30" + }, + { + // Type 3 in the hour field will automatically advance to the minute field. + keys: ["330", "VK_DOWN"], + initialVal: "", + expectedVal: "03:30" + }, + { + // Type 5 in the hour field will automatically advance to the minute field. + // Type 7 in the minute field will automatically advance to the AM/PM field. + keys: ["57", "VK_DOWN"], + initialVal: "", + expectedVal: "05:07" + }, + { + // Advance to AM/PM field and change to PM. + keys: ["VK_TAB", "VK_TAB", "VK_DOWN"], + initialVal: "10:30", + expectedVal: "22:30" + }, + { + // Right key should do the same thing as TAB key. + keys: ["VK_RIGHT", "VK_RIGHT", "VK_DOWN"], + initialVal: "10:30", + expectedVal: "22:30" + }, + { + // Advance to minute field then back to hour field and decrement. + keys: ["VK_RIGHT", "VK_LEFT", "VK_DOWN"], + initialVal: "10:30", + expectedVal: "09:30" + }, + { + // Focus starts on the first field, hour in this case, and increment. + keys: ["VK_UP"], + initialVal: "16:00", + expectedVal: "17:00" + }, + { + // Advance to minute field and decrement. + keys: ["VK_TAB", "VK_DOWN"], + initialVal: "16:00", + expectedVal: "16:59" + }, + { + // Advance to minute field and increment. + keys: ["VK_TAB", "VK_UP"], + initialVal: "16:59", + expectedVal: "16:00" + }, + { + // PageUp on hour field increments hour by 3. + keys: ["VK_PAGE_UP"], + initialVal: "05:00", + expectedVal: "08:00" + }, + { + // PageDown on hour field decrements hour by 3. + keys: ["VK_PAGE_DOWN"], + initialVal: "05:00", + expectedVal: "02:00" + }, + { + // PageUp on minute field increments minute by 10. + keys: ["VK_TAB", "VK_PAGE_UP"], + initialVal: "14:00", + expectedVal: "14:10" + }, + { + // PageDown on minute field decrements minute by 10. + keys: ["VK_TAB", "VK_PAGE_DOWN"], + initialVal: "14:00", + expectedVal: "14:50" + }, + { + // Home key on hour field sets it to the minimum hour, which is 1 in 12-hour + // clock. + keys: ["VK_HOME"], + initialVal: "03:10", + expectedVal: "01:10" + }, + { + // End key on hour field sets it to the maximum hour, which is 12 in 12-hour + // clock. + keys: ["VK_END"], + initialVal: "03:10", + expectedVal: "00:10" + }, + { + // Home key on minute field sets it to the minimum minute, which is 0. + keys: ["VK_TAB", "VK_HOME"], + initialVal: "19:30", + expectedVal: "19:00" + }, + { + // End key on minute field sets it to the minimum minute, which is 59. + keys: ["VK_TAB", "VK_END"], + initialVal: "19:30", + expectedVal: "19:59" + }, + // Second field will show up when needed. + { + // PageUp on second field increments second by 10. + keys: ["VK_TAB", "VK_TAB", "VK_PAGE_UP"], + initialVal: "08:10:10", + expectedVal: "08:10:20" + }, + { + // PageDown on second field increments second by 10. + keys: ["VK_TAB", "VK_TAB", "VK_PAGE_DOWN"], + initialVal: "08:10:10", + expectedVal: "08:10:00" + }, + { + // Home key on second field sets it to the minimum second, which is 0. + keys: ["VK_TAB", "VK_TAB", "VK_HOME"], + initialVal: "16:00:30", + expectedVal: "16:00:00" + }, + { + // End key on second field sets it to the minimum second, which is 59. + keys: ["VK_TAB", "VK_TAB", "VK_END"], + initialVal: "16:00:30", + expectedVal: "16:00:59" + }, +]; + +function sendKeys(aKeys) { + for (let i = 0; i < aKeys.length; i++) { + let key = aKeys[i]; + if (key.startsWith("VK")) { + synthesizeKey(key, {}); + } else { + sendString(key); + } + } +} + +function test() { + var elem = document.getElementById("input"); + + for (let { keys, initialVal, expectedVal } of testData) { + elem.focus(); + elem.value = initialVal; + sendKeys(keys); + elem.blur(); + is(elem.value, expectedVal, + "Test with " + keys + ", result should be " + expectedVal); + elem.value = ""; + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_types_pref.html b/dom/html/test/forms/test_input_types_pref.html new file mode 100644 index 000000000..243836f34 --- /dev/null +++ b/dom/html/test/forms/test_input_types_pref.html @@ -0,0 +1,114 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=764481 +--> +<head> + <title>Test for Bug 764481</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764481">Mozilla Bug 764481</a> +<p id="display"></p> +<div id="content" style="display: none" > +</div> +<pre id="test"> +<script type="application/javascript"> + + var input = document.createElement("input"); + + var testData = [ + { + prefs: [["dom.forms.number", false]], + inputType: "number", + expectedType: "text" + }, { + prefs: [["dom.forms.number", true]], + inputType: "number", + expectedType: "number" + }, { + prefs: [["dom.forms.color", false]], + inputType: "color", + expectedType: "text" + }, { + prefs: [["dom.forms.color", true]], + inputType: "color", + expectedType: "color" + }, { + prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", false], + ["dom.forms.datetime", false]], + inputType: "date", + expectedType: "text" + }, { + prefs: [["dom.experimental_forms", true], ["dom.forms.datepicker", false], + ["dom.forms.datetime", false]], + inputType: "date", + expectedType: "date" + }, { + prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", true], + ["dom.forms.datetime", false]], + inputType: "date", + expectedType: "date" + }, { + prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", false], + ["dom.forms.datetime", true]], + inputType: "date", + expectedType: "date" + }, { + prefs: [["dom.forms.datetime", false]], + inputType: "month", + expectedType: "text" + }, { + prefs: [["dom.forms.datetime", true]], + inputType: "month", + expectedType: "month" + }, { + prefs: [["dom.forms.datetime", false]], + inputType: "week", + expectedType: "text" + }, { + prefs: [["dom.forms.datetime", true]], + inputType: "week", + expectedType: "week" + }, { + prefs: [["dom.forms.datetime", false]], + inputType: "datetime-local", + expectedType: "text" + }, { + prefs: [["dom.forms.datetime", true]], + inputType: "datetime-local", + expectedType: "datetime-local" + } + ]; + + function testInputTypePreference(aData) { + return SpecialPowers.pushPrefEnv({'set': aData.prefs}) + .then(() => { + // Change the type of input to text and then back to the tested input type, + // so that HTMLInputElement::ParseAttribute gets called with the pref enabled. + input.type = "text"; + input.type = aData.inputType; + is(input.type, aData.expectedType, "input type should be '" + + aData.expectedType + "'' when pref " + aData.prefs + " is set"); + is(input.getAttribute('type'), aData.inputType, + "input 'type' attribute should not change"); + }); + } + + SimpleTest.waitForExplicitFinish(); + + let promise = Promise.resolve(); + for (let i = 0; i < testData.length; i++) { + let data = testData[i]; + promise = promise.then(() => testInputTypePreference(data)); + } + + promise.catch(error => ok(false, "Promise reject: " + error)) + .then(() => SimpleTest.finish()); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_typing_sanitization.html b/dom/html/test/forms/test_input_typing_sanitization.html new file mode 100644 index 000000000..0896f19df --- /dev/null +++ b/dom/html/test/forms/test_input_typing_sanitization.html @@ -0,0 +1,260 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=765772 +--> +<head> + <title>Test for Bug 765772</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 765772</a> +<p id="display"></p> +<iframe name="submit_frame" style="visibility: hidden;"></iframe> +<div id="content"> + <form id='f' target="submit_frame" action="foo"> + <input name=i id="i" step='any' > + </form> +</div> +<pre id="test"> +<script type="application/javascript;version=1.7"> + +/* + * This test checks that when a user types in some input types, it will not be + * in a state where the value will be un-sanitized and usable (by a script). + */ + +var input = document.getElementById('i'); +var form = document.getElementById('f'); +var submitFrame = document.getElementsByTagName('iframe')[0]; +var testData = []; +var gCurrentTest = null; +var gValidData = []; +var gInvalidData = []; + +function submitForm() { + form.submit(); +} + +function sendKeyEventToSubmitForm() { + sendKey("return"); +} + +function urlify(aStr) { + return aStr.replace(/:/g, '%3A'); +} + +function runTestsForNextInputType() +{ + try { + testRunner.next(); + } catch (e) { + if (e.toString() == '[object StopIteration]') { + SimpleTest.finish(); + } else { + throw StopIteration; + } + } +} + +function checkValueSubmittedIsValid() +{ + is(frames['submit_frame'].location.href, + 'http://mochi.test:8888/tests/dom/html/test/forms/foo?i=' + + urlify(gValidData[valueIndex++]), + "The submitted value should not have been sanitized"); + + input.value = ""; + + if (valueIndex >= gValidData.length) { + if (gCurrentTest.canHaveBadInputValidityState) { + // Don't run the submission tests on the invalid input if submission + // will be blocked by invalid input. + runTestsForNextInputType(); + return; + } + valueIndex = 0; + submitFrame.onload = checkValueSubmittedIsInvalid; + testData = gInvalidData; + } + testSubmissions(); +} + +function checkValueSubmittedIsInvalid() +{ + is(frames['submit_frame'].location.href, + 'http://mochi.test:8888/tests/dom/html/test/forms/foo?i=', + "The submitted value should have been sanitized"); + + valueIndex++; + input.value = ""; + + if (valueIndex >= gInvalidData.length) { + if (submitMethod == sendKeyEventToSubmitForm) { + runTestsForNextInputType(); + return; + } + valueIndex = 0; + submitMethod = sendKeyEventToSubmitForm; + submitFrame.onload = checkValueSubmittedIsValid; + testData = gValidData; + } + testSubmissions(); +} + +function testSubmissions() { + input.focus(); + sendString(testData[valueIndex]); + submitMethod(); +} + +var valueIndex = 0; +var submitMethod = submitForm; + +SimpleTest.waitForExplicitFinish(); + +function runTest() +{ + SimpleTest.requestLongerTimeout(4); + + var data = [ + { + type: 'number', + canHaveBadInputValidityState: true, + validData: [ + "42", + "-42", // should work for negative values + "42.1234", + "123.123456789123", // double precision + "1e2", // e should be usable + "2e1", + "1e-1", // value after e can be negative + "1E2", // E can be used instead of e + ], + invalidData: [ + "e", + "e2", + "1e0.1", + "foo", + "42,13", // comma can't be used as a decimal separator + ] + }, + { + type: 'date', + validData: [ + '0001-01-01', + '2012-12-21', + '2013-01-28', + '100000-01-01', + ], + invalidData: [ + '1-01-01', + 'a', + '-', + '2012-01', + '2013-01-1', + '1011-23-21', + '1000-12-99', + ] + }, + { + type: 'month', + validData: [ + '0001-01', + '2012-12', + '100000-01', + ], + invalidData: [ + '1-01', + '-', + 'december', + '2012-dec', + '2012/12', + '2012-99', + '2012-1', + ] + }, + { + type: 'week', + validData: [ + '0001-W01', + '1970-W53', + '100000-W52', + '2016-W30', + ], + invalidData: [ + '1-W01', + 'week', + '2016-30', + '2010-W80', + '2000/W30', + '1985-W00', + '1000-W' + ] + }, + { + type: 'datetime-local', + validData: [ + '0001-01-01T00:00', + '2016-11-07T16:45', + '2016-11-07T16:45:30', + '2016-11-07T16:45:30.10', + '2016-11-07T16:45:00.111', + ], + invalidData: [ + '1-01-01T00:00', + '1970-01-01T9:30', + '2016/11/07T16:45', + '2016-11-07T16.45', + 'T', + 'datetime-local' + ] + }, + ]; + + for (test of data) { + gCurrentTest = test; + + input.type = test.type; + gValidData = test.validData; + gInvalidData = test.invalidData; + + for (data of gValidData) { + input.value = ""; + input.focus(); + sendString(data); + input.blur(); + is(input.value, data, "valid user input should not be sanitized"); + } + + for (data of gInvalidData) { + input.value = ""; + input.focus(); + sendString(data); + input.blur(); + is(input.value, "", "invalid user input should be sanitized"); + } + + input.value = ''; + + testData = gValidData; + valueIndex = 0; + submitFrame.onload = checkValueSubmittedIsValid; + testSubmissions(); + yield undefined; + } +} + +var testRunner = runTest(); + +addLoadEvent(function () { + testRunner.next(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_untrusted_key_events.html b/dom/html/test/forms/test_input_untrusted_key_events.html new file mode 100644 index 000000000..b356316ce --- /dev/null +++ b/dom/html/test/forms/test_input_untrusted_key_events.html @@ -0,0 +1,96 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for untrusted DOM KeyboardEvent on input element</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content"> + <input id="input"> +</div> +<pre id="test"> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runNextTest, window); + +const kTests = [ + { type: "text", value: "foo", key: "b", expectedNewValue: "foo" }, + { type: "number", value: "123", key: "4", expectedNewValue: "123" }, + { type: "number", value: "123", key: KeyEvent.DOM_VK_UP, expectedNewValue: "123" }, + { type: "number", value: "123", key: KeyEvent.DOM_VK_DOWN, expectedNewValue: "123" }, +]; + +function sendUntrustedKeyEvent(eventType, keyCode, target) { + var evt = document.createEvent("KeyboardEvent"); + var canBubbleArg = true; + var cancelableArg = true; + var viewArg = document.defaultView; + var ctrlKeyArg = false; + var altKeyArg = false; + var shiftKeyArg = false; + var metaKeyArg = false; + var keyCodeArg = keyCode; + var charCodeArg = 0; + evt.initKeyEvent(eventType, canBubbleArg, cancelableArg, viewArg, + ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, + keyCodeArg, charCodeArg); + target.dispatchEvent(evt); +} + +var input = document.getElementById("input"); + +var gotEvents = {}; + +function handleEvent(event) { + gotEvents[event.type] = true; +} + +input.addEventListener("keydown", handleEvent, false); +input.addEventListener("keyup", handleEvent, false); +input.addEventListener("keypress", handleEvent, false); + +var previousTest = null; + +function runNextTest() { + if (previousTest) { + var msg = "For <input " + "type=" + previousTest.type + ">, "; + is(gotEvents.keydown, true, msg + "checking got keydown"); + is(gotEvents.keyup, true, msg + "checking got keyup"); + is(gotEvents.keypress, true, msg + "checking got keypress"); + is(input.value, previousTest.expectedNewValue, msg + "checking element " + + " after being sent '" + previousTest.key + "' key events"); + } + + // reset flags + gotEvents.keydown = false; + gotEvents.keyup = false; + gotEvents.keypress = false; + + + var test = kTests.shift(); + if (!test) { + SimpleTest.finish(); + return; // We're all done + } + + input.type = test.type; + input.focus(); // make sure we still have focus after type change + input.value = test.value; + + sendUntrustedKeyEvent("keydown", test.key, input); + sendUntrustedKeyEvent("keyup", test.key, input); + sendUntrustedKeyEvent("keypress", test.key, input); + + previousTest = test; + + SimpleTest.executeSoon(runNextTest); +}; + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_input_url.html b/dom/html/test/forms/test_input_url.html new file mode 100644 index 000000000..b335f5983 --- /dev/null +++ b/dom/html/test/forms/test_input_url.html @@ -0,0 +1,89 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Tests for <input type='url'> validity</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + <input type='url' id='i' oninvalid='invalidEventHandler(event);'> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Tests for <input type='url'> validity **/ + +// More checks are done in test_bug551670.html. + +var gInvalid = false; + +function invalidEventHandler(e) +{ + is(e.type, "invalid", "Invalid event type should be invalid"); + gInvalid = true; +} + +function checkValidURL(element) +{ + gInvalid = false; + ok(!element.validity.typeMismatch, + "Element should not suffer from type mismatch"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "Element should be valid"); + ok(!gInvalid, "The invalid event should not have been thrown"); + is(element.validationMessage, '', + "Validation message should be the empty string"); + ok(element.matches(":valid"), ":valid pseudo-class should apply"); +} + +function checkInvalidURL(element) +{ + gInvalid = false; + ok(element.validity.typeMismatch, + "Element should suffer from type mismatch"); + ok(!element.validity.valid, "Element should not be valid"); + ok(!element.checkValidity(), "Element should not be valid"); + ok(gInvalid, "The invalid event should have been thrown"); + is(element.validationMessage, "Please enter a URL.", + "Validation message should be related to invalid URL"); + ok(element.matches(":invalid"), + ":invalid pseudo-class should apply"); +} + +var url = document.getElementById('i'); + +var values = [ + // [ value, validity ] + // The empty string should be considered as valid. + [ "", true ], + [ "foo", false ], + [ "http://mozilla.com/", true ], + [ "http://mozilla.com", true ], + [ "http://mozil\nla\r.com/", true ], + [ " http://mozilla.com/ ", true ], + [ "\r http://mozilla.com/ \n", true ], + [ "file:///usr/bin/tulip", true ], + [ "../../bar.html", false ], + [ "http://mozillá.org", true ], + [ "https://mózillä.org", true ], + [ "http://mózillä.órg", true ], + [ "ht://mózillä.órg", true ], + [ "httÅ://mózillä.órg", false ], +]; + +values.forEach(function([value, valid]) { + url.value = value; + + if (valid) { + checkValidURL(url); + } else { + checkInvalidURL(url); + } +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_interactive_content_in_label.html b/dom/html/test/forms/test_interactive_content_in_label.html new file mode 100644 index 000000000..3df64eae2 --- /dev/null +++ b/dom/html/test/forms/test_interactive_content_in_label.html @@ -0,0 +1,83 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=229925 +--> +<head> + <title>Test for Bug 229925</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=229925">Mozilla Bug 229925</a> +<p id="display"></p> +<form action="#"> + <label> + <span id="text">label</span> + <input type="button" id="target" value="target"> + + <a class="yes" href="#">a</a> + <audio class="yes" controls></audio> + <button class="yes">button</button> + <details class="yes">details</details> + <embed class="yes">embed</embed> + <iframe class="yes" src="data:text/plain," style="width: 16px; height: 16px;"></iframe> + <img class="yes" src="data:image/png," usemap="#map"> + <input class="yes" type="text" size="4"> + <keygen class="yes"> + <label class="yes">label</label> + <object class="yes" usemap="#map">object</object> + <select class="yes"><option>select</option></select> + <textarea class="yes" cols="1" rows="1"></textarea> + <video class="yes" controls></video> + + <a class="no">a</a> + <audio class="no"></audio> + <img class="no" src="data:image/png,"> + <input class="no" type="hidden"> + <object class="no">object</object> + <video class="no"></video> + + <span class="no" tabindex="1">tabindex</span> + <audio class="no" tabindex="1"></audio> + <img class="no" src="data:image/png," tabindex="1"> + <input class="no" type="hidden" tabindex="1"> + <object class="no" tabindex="1">object</object> + <video class="no" tabindex="1"></video> + </label> +</form> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 229925 **/ + +var target = document.getElementById("target"); + +var yes_nodes = Array.from(document.getElementsByClassName("yes")); + +var no_nodes = Array.from(document.getElementsByClassName("no")); + +var target_clicked = false; +target.addEventListener("click", function() { + target_clicked = true; +}); + +var node; +for (node of yes_nodes) { + target_clicked = false; + node.click(); + is(target_clicked, false, "mouse click on interactive content " + node.nodeName + " shouldn't dispatch event to label target"); +} + +for (node of no_nodes) { + target_clicked = false; + node.click(); + is(target_clicked, true, "mouse click on non interactive content " + node.nodeName + " should dispatch event to label target"); +} + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/forms/test_label_control_attribute.html b/dom/html/test/forms/test_label_control_attribute.html new file mode 100644 index 000000000..66b761c93 --- /dev/null +++ b/dom/html/test/forms/test_label_control_attribute.html @@ -0,0 +1,100 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=562932 +--> +<head> + <title>Test for Bug 562932</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562932">Mozilla Bug 562932</a> +<p id="display"></p> +<div id="content" style="display: none"> + <!-- No @for, we have to check the content --> + <label id='l1'><input id='i1'></label> + <label id='l2'><input id='i2'><input></label> + <label id='l3'></label> + <label id='l4a'><fieldset id='f'>foo</fieldset></label> + <label id='l4b'><label id='l4c'><input id='i3'></label></label> + <label id='l4d'><label id='l4e'><input id='i3b'></label><input></label> + + <!-- With @for, we do no check the content --> + <label id='l5' for='i1'></label> + <label id='l6' for='i4'></label> + <label id='l7' for='i4'><input></label> + <label id='l8' for='i1 i2'></label> + <label id='l9' for='i1 i2'><input></label> + <label id='l10' for='f'></label> + <label id='l11' for='i4'></label> + <label id='l12' for='i5'></label> + <label id='l13' for=''><input></label> + <!-- <label id='l14'> is created in script --> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 562932 **/ + +function checkControl(aLabelId, aElementId, aMsg) +{ + var element = null; + + if (aElementId != null) { + element = document.getElementById(aElementId); + } + + is(document.getElementById(aLabelId).control, element, aMsg); +} + +ok('control' in document.createElement('label'), + "label element should have a control IDL attribute"); + +checkControl('l1', 'i1', "label control should be the first form element"); +checkControl('l2', 'i2', "label control should be the first form element"); +checkControl('l3', null, "label control should be null when there is no child"); +checkControl('l4a', null, "label control should be null when there is no \ + labelable form element child"); +checkControl('l4b', 'i3', "label control should be the first labelable element \ + in tree order"); +checkControl('l4c', 'i3', "label control should be the first labelable element \ + in tree order"); +checkControl('l4d', 'i3b', "label control should be the first labelable element \ + in tree order"); +checkControl('l4e', 'i3b', "label control should be the first labelable element \ + in tree order"); +checkControl('l5', 'i1', "label control should be the id in @for"); +checkControl('l6', null, + "label control should be null if the id in @for is not valid"); +checkControl('l7', null, + "label control should be null if the id in @for is not valid"); +checkControl('l8', null, + "label control should be null if there are more than one id in @for"); +checkControl('l9', null, + "label control should be null if there are more than one id in @for"); +checkControl('l10', null, "label control should be null if the id in @for \ + is not an id from a labelable form element"); + +var inputOutOfDocument = document.createElement('input'); +inputOutOfDocument.id = 'i4'; +checkControl('l11', null, "label control should be null if the id in @for \ + is not an id from an element in the document"); + +var inputInDocument = document.createElement('input'); +inputInDocument.id = 'i5'; +document.getElementById('content').appendChild(inputInDocument); +checkControl('l12', 'i5', "label control should be the id in @for"); + +checkControl('l13', null, "label control should be null if the id in @for \ + is empty"); + +var labelOutOfDocument = document.createElement('label'); +labelOutOfDocument.htmlFor = 'i1'; +is(labelOutOfDocument.control, null, "out of document label shouldn't \ + labelize a form control"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_label_input_controls.html b/dom/html/test/forms/test_label_input_controls.html new file mode 100644 index 000000000..6dee2a5bb --- /dev/null +++ b/dom/html/test/forms/test_label_input_controls.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=597650 +--> +<head> + <title>Test for Bug 597650</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=597650">Mozilla Bug 597650</a> + <p id="display"></p> + <div id="content"> + <label id="l"> + <input id="h"></input> + <input type="text" id="i"></input> + </label> + <label id="lh" for="h"></label> + </div> + <pre id="test"> + <script class="testbody" type="text/javascript"> + /** Test for Bug 597650 **/ + label = document.getElementById("l"); + labelForH = document.getElementById("lh"); + inputI = document.getElementById("i"); + inputH = document.getElementById("h"); + + var labelableTypes = ["text", "search", "tel", "url", "email", "password", + "datetime", "date", "month", "week", "time", + "number", "range", "color", "checkbox", "radio", + "file", "submit", "image", "reset", "button"]; + var nonLabelableTypes = ["hidden"]; + + for (var i in labelableTypes) { + test(labelableTypes[i], true); + } + + for (var i in nonLabelableTypes) { + test(nonLabelableTypes[i], false); + } + + function test(type, isLabelable) { + inputH.type = type; + if (isLabelable) { + testControl(label, inputH, type, true); + testControl(labelForH, inputH, type, true); + } else { + testControl(label, inputI, type, false); + testControl(labelForH, null, type, false); + + inputH.type = "text"; + testControl(label, inputH, "text", true); + testControl(labelForH, inputH, "text", true); + + inputH.type = type; + testControl(label, inputI, type, false); + testControl(labelForH, null, type, false); + + label.removeChild(inputH); + testControl(label, inputI, "text", true); + + var element = document.createElement('input'); + element.type = type; + label.insertBefore(element, inputI); + testControl(label, inputI, "text", true); + } + } + + function testControl(label, control, type, labelable) { + if (labelable) { + is(label.control, control, "Input controls of type " + type + + " should be labeled"); + } else { + is(label.control, control, "Input controls of type " + type + + " should be ignored by <label>"); + } + } + </script> + </pre> + </body> +</html> + diff --git a/dom/html/test/forms/test_max_attribute.html b/dom/html/test/forms/test_max_attribute.html new file mode 100644 index 000000000..4007cfad6 --- /dev/null +++ b/dom/html/test/forms/test_max_attribute.html @@ -0,0 +1,437 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=635499 +--> +<head> + <title>Test for Bug 635499</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 635499 **/ + +var data = [ + { type: 'hidden', apply: false }, + { type: 'text', apply: false }, + { type: 'search', apply: false }, + { type: 'tel', apply: false }, + { type: 'url', apply: false }, + { type: 'email', apply: false }, + { type: 'password', apply: false }, + { type: 'date', apply: true }, + { type: 'month', apply: true }, + { type: 'week', apply: true }, + { type: 'time', apply: true }, + // TODO: temporary set to false until bug 888331 is fixed. + { type: 'datetime-local', apply: false }, + { type: 'number', apply: true }, + { type: 'range', apply: true }, + { type: 'color', apply: false }, + { type: 'checkbox', apply: false }, + { type: 'radio', apply: false }, + { type: 'file', apply: false }, + { type: 'submit', apply: false }, + { type: 'image', apply: false }, + { type: 'reset', apply: false }, + { type: 'button', apply: false }, +]; + +var input = document.createElement("input"); +document.getElementById('content').appendChild(input); + +/** + * @aValidity - boolean indicating whether the element is expected to be valid + * (aElement.validity.valid is true) or not. The value passed is ignored and + * overridden with true if aApply is false. + * @aApply - boolean indicating whether the min/max attributes apply to this + * element type. + * @aRangeApply - A boolean that's set to true if the current input type is a + * "[candidate] for constraint validation" and it "[has] range limitations" + * per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range + * (in other words, one of the pseudo classes :in-range and :out-of-range + * should apply (which, depends on aValidity)). + * Else (neither :in-range or :out-of-range should match) set to false. + */ +function checkValidity(aElement, aValidity, aApply, aRangeApply) +{ + aValidity = aApply ? aValidity : true; + + is(aElement.validity.valid, aValidity, + "element validity should be " + aValidity); + is(aElement.validity.rangeOverflow, !aValidity, + "element overflow status should be " + !aValidity); + var overflowMsg = + (aElement.type == "date" || aElement.type == "time" || + aElement.type == "month" || aElement.type == "week") ? + ("Please select a value that is no later than " + aElement.max + ".") : + ("Please select a value that is no more than " + aElement.max + "."); + is(aElement.validationMessage, + aValidity ? "" : overflowMsg, "Checking range overflow validation message"); + + is(aElement.matches(":valid"), aElement.willValidate && aValidity, + (aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply"); + is(aElement.matches(":invalid"), aElement.willValidate && !aValidity, + (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply"); + + if (!aRangeApply) { + ok(!aElement.matches(":in-range"), ":in-range should not match"); + ok(!aElement.matches(":out-of-range"), + ":out-of-range should not match"); + } else { + is(aElement.matches(":in-range"), aValidity, + ":in-range matches status should be " + aValidity); + is(aElement.matches(":out-of-range"), !aValidity, + ":out-of-range matches status should be " + !aValidity); + } +} + +for (var test of data) { + input.type = test.type; + var apply = test.apply; + + // The element should be valid. Range should not apply when @min and @max are + // undefined, except if the input type is 'range' (since that type has a + // default minimum and maximum). + if (input.type == 'range') { + checkValidity(input, true, apply, true); + } else { + checkValidity(input, true, apply, false); + } + checkValidity(input, true, apply, test.type == 'range'); + + switch (input.type) { + case 'hidden': + case 'text': + case 'search': + case 'password': + case 'url': + case 'tel': + case 'email': + case 'number': + case 'checkbox': + case 'radio': + case 'file': + case 'submit': + case 'reset': + case 'button': + case 'image': + case 'color': + input.max = '-1'; + break; + case 'date': + input.max = '2012-06-27'; + break; + case 'time': + input.max = '02:20'; + break; + case 'range': + // range is special, since setting max to -1 will make it invalid since + // it's default would then be 0, meaning it suffers from overflow. + input.max = '-1'; + checkValidity(input, false, apply, apply); + // Now make it something that won't cause an error below: + input.max = '10'; + break; + case 'month': + input.max = '2016-12'; + break; + case 'week': + input.max = '2016-W39'; + break; + case 'datetime-local': + // TODO: this is temporary until bug 888331 is fixed. + break; + default: + ok(false, 'please, add a case for this new type (' + input.type + ')'); + } + + checkValidity(input, true, apply, apply); + + switch (input.type) { + case 'text': + case 'hidden': + case 'search': + case 'password': + case 'tel': + case 'radio': + case 'checkbox': + case 'reset': + case 'button': + case 'submit': + case 'image': + input.value = '0'; + checkValidity(input, true, apply, apply); + break; + case 'url': + input.value = 'http://mozilla.org'; + checkValidity(input, true, apply, apply); + break; + case 'email': + input.value = 'foo@bar.com'; + checkValidity(input, true, apply, apply); + break; + case 'file': + var file = new File([''], '635499_file'); + + SpecialPowers.wrap(input).mozSetFileArray([file]); + checkValidity(input, true, apply, apply); + + break; + case 'date': + input.max = '2012-06-27'; + input.value = '2012-06-26'; + checkValidity(input, true, apply, apply); + + input.value = '2012-06-27'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '2012-06-28'; + checkValidity(input, false, apply, apply); + + input.max = '2012-06-30'; + checkValidity(input, true, apply, apply); + + input.value = '2012-07-05'; + checkValidity(input, false, apply, apply); + + input.value = '1000-01-01'; + checkValidity(input, true, apply, apply); + + input.value = '20120-01-01'; + checkValidity(input, false, apply, apply); + + input.max = '0050-01-01'; + checkValidity(input, false, apply, apply); + + input.value = '0049-01-01'; + checkValidity(input, true, apply, apply); + + input.max = ''; + checkValidity(input, true, apply, false); + + input.max = 'foo'; + checkValidity(input, true, apply, false); + + break; + case 'number': + input.max = '2'; + input.value = '1'; + checkValidity(input, true, apply, apply); + + input.value = '2'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '3'; + checkValidity(input, false, apply, apply); + + input.max = '5'; + checkValidity(input, true, apply, apply); + + input.value = '42'; + checkValidity(input, false, apply, apply); + + input.max = ''; + checkValidity(input, true, apply, false); + + input.max = 'foo'; + checkValidity(input, true, apply, false); + + // Check that we correctly convert input.max to a double in validationMessage. + if (input.type == 'number') { + input.max = "4.333333333333333333333333333333333331"; + input.value = "5"; + is(input.validationMessage, + "Please select a value that is no more than 4.33333333333333.", + "validation message"); + } + + break; + case 'range': + input.max = '2'; + input.value = '1'; + checkValidity(input, true, apply, apply); + + input.value = '2'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '3'; + checkValidity(input, true, apply, apply); + + is(input.value, input.max, "the value should have been set to max"); + + input.max = '5'; + checkValidity(input, true, apply, apply); + + input.value = '42'; + checkValidity(input, true, apply, apply); + + is(input.value, input.max, "the value should have been set to max"); + + input.max = ''; + checkValidity(input, true, apply, apply); + + input.max = 'foo'; + checkValidity(input, true, apply, apply); + + // Check that we correctly convert input.max to a double in validationMessage. + input.step = 'any'; + input.min = 5; + input.max = 0.66666666666666666666666666666666666 + input.value = 1; + is(input.validationMessage, + "Please select a value that is no more than 0.666666666666667.", + "validation message") + + break; + case 'time': + // Don't worry about that. + input.step = 'any'; + + input.max = '10:10'; + input.value = '10:09'; + checkValidity(input, true, apply, apply); + + input.value = '10:10'; + checkValidity(input, true, apply, apply); + + input.value = '10:10:00'; + checkValidity(input, true, apply, apply); + + input.value = '10:10:00.000'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '10:11'; + checkValidity(input, false, apply, apply); + + input.value = '10:10:00.001'; + checkValidity(input, false, apply, apply); + + input.max = '01:00:00.01'; + input.value = '01:00:00.001'; + checkValidity(input, true, apply, apply); + + input.value = '01:00:00'; + checkValidity(input, true, apply, apply); + + input.value = '01:00:00.1'; + checkValidity(input, false, apply, apply); + + input.max = ''; + checkValidity(input, true, apply, false); + + input.max = 'foo'; + checkValidity(input, true, apply, false); + + break; + case 'month': + input.value = '2016-06'; + checkValidity(input, true, apply, apply); + + input.value = '2016-12'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '2017-01'; + checkValidity(input, false, apply, apply); + + input.max = '2017-07'; + checkValidity(input, true, apply, apply); + + input.value = '2017-12'; + checkValidity(input, false, apply, apply); + + input.value = '1000-01'; + checkValidity(input, true, apply, apply); + + input.value = '20160-01'; + checkValidity(input, false, apply, apply); + + input.max = '0050-01'; + checkValidity(input, false, apply, apply); + + input.value = '0049-12'; + checkValidity(input, true, apply, apply); + + input.max = ''; + checkValidity(input, true, apply, false); + + input.max = 'foo'; + checkValidity(input, true, apply, false); + + break; + case 'week': + input.value = '2016-W01'; + checkValidity(input, true, apply, apply); + + input.value = '2016-W39'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '2017-W01'; + checkValidity(input, false, apply, apply); + + input.max = '2017-W01'; + checkValidity(input, true, apply, apply); + + input.value = '2017-W52'; + checkValidity(input, false, apply, apply); + + input.value = '1000-W01'; + checkValidity(input, true, apply, apply); + + input.value = '2100-W01'; + checkValidity(input, false, apply, apply); + + input.max = '0050-W01'; + checkValidity(input, false, apply, apply); + + input.value = '0049-W52'; + checkValidity(input, true, apply, apply); + + input.max = ''; + checkValidity(input, true, apply, false); + + input.max = 'foo'; + checkValidity(input, true, apply, false); + + break; + case 'datetime-local': + // TODO: this is temporary until bug 888331 is fixed. + + break; + } + + // Cleaning up, + input.removeAttribute('max'); + input.value = ''; +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_maxlength_attribute.html b/dom/html/test/forms/test_maxlength_attribute.html new file mode 100644 index 000000000..cfc50b67c --- /dev/null +++ b/dom/html/test/forms/test_maxlength_attribute.html @@ -0,0 +1,129 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=345624 +--> +<head> + <title>Test for Bug 345624</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input, textarea { background-color: rgb(0,0,0) !important; } + :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; } + :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a> +<p id="display"></p> +<div id="content"> + <input id='i'> + <textarea id='t'></textarea> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 345624 **/ + +/** + * This test is checking only tooLong related features + * related to constraint validation. + */ + +function checkTooLongValidity(element) +{ + element.value = "foo"; + ok(!element.validity.tooLong, + "Element should not be too long when maxlength is not set"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.maxLength = 1; + ok(!element.validity.tooLong, + "Element should not be too long unless the user edits it"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.focus(); + + synthesizeKey("VK_BACK_SPACE", {}); + is(element.value, "fo", "value should have changed"); + ok(element.validity.tooLong, + "Element should be too long after a user edit that does not make it short enough"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + ok(!element.validity.valid, "Element should be invalid"); + ok(!element.checkValidity(), "The element should not be valid"); + is(element.validationMessage, + "Please shorten this text to 1 characters or less (you are currently using 2 characters).", + "The validation message text is not correct"); + + synthesizeKey("VK_BACK_SPACE", {}); + is(element.value, "f", "value should have changed"); + ok(!element.validity.tooLong, + "Element should not be too long after a user edit makes it short enough"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + + element.maxLength = 2; + ok(!element.validity.tooLong, + "Element should remain valid if maxlength changes but maxlength > length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + + element.maxLength = 1; + ok(!element.validity.tooLong, + "Element should remain valid if maxlength changes but maxlength = length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.maxLength = 0; + ok(element.validity.tooLong, + "Element should become invalid if maxlength changes and maxlength < length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + ok(!element.validity.valid, "Element should be invalid"); + ok(!element.checkValidity(), "The element should not be valid"); + is(element.validationMessage, + "Please shorten this text to 0 characters or less (you are currently using 1 characters).", + "The validation message text is not correct"); + + element.maxLength = 1; + ok(!element.validity.tooLong, + "Element should become valid if maxlength changes and maxlength = length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.value = "test"; + ok(!element.validity.tooLong, + "Element should stay valid after programmatic edit (even if value is too long)"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.setCustomValidity("custom message"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + is(element.validationMessage, "custom message", + "Custom message should be shown instead of too long one"); +} + +checkTooLongValidity(document.getElementById('i')); +checkTooLongValidity(document.getElementById('t')); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_meter_element.html b/dom/html/test/forms/test_meter_element.html new file mode 100644 index 000000000..7b9c597ce --- /dev/null +++ b/dom/html/test/forms/test_meter_element.html @@ -0,0 +1,384 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=657938 +--> +<head> + <title>Test for <meter></title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=657938">Mozilla Bug 657938</a> +<p id="display"></p> +<iframe name="submit_frame" style="visibility: hidden;"></iframe> +<div id="content" style="visibility: hidden;"> + <form id='f' method='get' target='submit_frame' action='foo'> + <meter id='m' value=0.5></meter> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for <meter> **/ + +function checkFormIDLAttribute(aElement) +{ + is('form' in aElement, false, "<meter> shouldn't have a form attribute"); +} + +function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL) +{ + var expectedValueForIDL = aNewValue; + var expectedValueForContent = String(aNewValue); + + if (aExpectedValueForIDL !== undefined) { + expectedValueForIDL = aExpectedValueForIDL; + } + + if (aNewValue != null) { + aElement.setAttribute(aAttribute, aNewValue); + is(aElement.getAttribute(aAttribute), expectedValueForContent, + aAttribute + " content attribute should be " + expectedValueForContent); + is(aElement[aAttribute], expectedValueForIDL, + aAttribute + " IDL attribute should be " + expectedValueForIDL); + + if (parseFloat(aNewValue) == aNewValue) { + aElement[aAttribute] = aNewValue; + is(aElement.getAttribute(aAttribute), expectedValueForContent, + aAttribute + " content attribute should be " + expectedValueForContent); + is(aElement[aAttribute], parseFloat(expectedValueForIDL), + aAttribute + " IDL attribute should be " + parseFloat(expectedValueForIDL)); + } + } else { + aElement.removeAttribute(aAttribute); + is(aElement.getAttribute(aAttribute), null, + aAttribute + " content attribute should be null"); + is(aElement[aAttribute], expectedValueForIDL, + aAttribute + " IDL attribute should be " + expectedValueForIDL); + } +} + +function checkValueAttribute() +{ + var tests = [ + // value has to be a valid float, its default value is 0.0 otherwise. + [ null, 0.0 ], + [ 'foo', 0.0 ], + // If value < 0.0, 0.0 is used instead. + [ -1.0, 0.0 ], + // If value >= max, max is used instead (max default value is 1.0). + [ 2.0, 1.0 ], + [ 1.0, 0.5, 0.5 ], + [ 10.0, 5.0, 5.0 ], + [ 13.37, 13.37, 42.0 ], + // If value <= min, min is used instead (min default value is 0.0). + [ 0.5, 1.0, 10.0 ,1.0 ], + [ 10.0, 13.37, 42.0 , 13.37], + // Regular reflection. + [ 0.0 ], + [ 0.5 ], + [ 1.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('meter'); + + for (var test of tests) { + if (test[2]) { + element.setAttribute('max', test[2]); + } + + if (test[3]) { + element.setAttribute('min', test[3]); + } + + checkAttribute(element, 'value', test[0], test[1]); + + element.removeAttribute('max'); + element.removeAttribute('min'); + } +} + +function checkMinAttribute() +{ + var tests = [ + // min default value is 0.0. + [ null, 0.0 ], + [ 'foo', 0.0 ], + // Regular reflection. + [ 0.5 ], + [ 1.0 ], + [ 2.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('meter'); + + for (var test of tests) { + checkAttribute(element, 'min', test[0], test[1]); + } +} + +function checkMaxAttribute() +{ + var tests = [ + // max default value is 1.0. + [ null, 1.0 ], + [ 'foo', 1.0 ], + // If value <= min, min is used instead. + [ -1.0, 0.0 ], + [ 0.0, 0.5, 0.5 ], + [ 10.0, 15.0, 15.0 ], + [ 42, 42, 13.37 ], + // Regular reflection. + [ 0.5 ], + [ 1.0 ], + [ 2.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('meter'); + + for (var test of tests) { + if (test[2]) { + element.setAttribute('min', test[2]); + } + + checkAttribute(element, 'max', test[0], test[1]); + + element.removeAttribute('min'); + } +} + +function checkLowAttribute() +{ + var tests = [ + // low default value is min (min default value is 0.0). + [ null, 0.0 ], + [ 'foo', 0.0 ], + [ 'foo', 1.0, 1.0], + // If low <= min, min is used instead. + [ -1.0, 0.0 ], + [ 0.0, 0.5, 0.5 ], + [ 10.0, 15.0, 15.0, 42.0 ], + [ 42.0, 42.0, 13.37, 100.0 ], + // If low >= max, max is used instead. + [ 2.0, 1.0 ], + [ 10.0, 5.0 , 0.5, 5.0 ], + [ 13.37, 13.37, 0.0, 42.0 ], + // Regular reflection. + [ 0.0 ], + [ 0.5 ], + [ 1.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('meter'); + + for (var test of tests) { + if (test[2]) { + element.setAttribute('min', test[2]); + } + if (test[3]) { + element.setAttribute('max', test[3]); + } + + checkAttribute(element, 'low', test[0], test[1]); + + element.removeAttribute('min'); + element.removeAttribute('max'); + } +} + +function checkHighAttribute() +{ + var tests = [ + // high default value is max (max default value is 1.0). + [ null, 1.0 ], + [ 'foo', 1.0 ], + [ 'foo', 42.0, 0.0, 42.0], + // If high <= min, min is used instead. + [ -1.0, 0.0 ], + [ 0.0, 0.5, 0.5 ], + [ 10.0, 15.0, 15.0, 42.0 ], + [ 42.0, 42.0, 13.37, 100.0 ], + // If high >= max, max is used instead. + [ 2.0, 1.0 ], + [ 10.0, 5.0 , 0.5, 5.0 ], + [ 13.37, 13.37, 0.0, 42.0 ], + // Regular reflection. + [ 0.0 ], + [ 0.5 ], + [ 1.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('meter'); + + for (var test of tests) { + if (test[2]) { + element.setAttribute('min', test[2]); + } + if (test[3]) { + element.setAttribute('max', test[3]); + } + + checkAttribute(element, 'high', test[0], test[1]); + + element.removeAttribute('min'); + element.removeAttribute('max'); + } +} + +function checkOptimumAttribute() +{ + var tests = [ + // opt default value is (max-min)/2 (thus default value is 0.5). + [ null, 0.5 ], + [ 'foo', 0.5 ], + [ 'foo', 2.0, 1.0, 3.0], + // If opt <= min, min is used instead. + [ -1.0, 0.0 ], + [ 0.0, 0.5, 0.5 ], + [ 10.0, 15.0, 15.0, 42.0 ], + [ 42.0, 42.0, 13.37, 100.0 ], + // If opt >= max, max is used instead. + [ 2.0, 1.0 ], + [ 10.0, 5.0 , 0.5, 5.0 ], + [ 13.37, 13.37, 0.0, 42.0 ], + // Regular reflection. + [ 0.0 ], + [ 0.5 ], + [ 1.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('meter'); + + for (var test of tests) { + if (test[2]) { + element.setAttribute('min', test[2]); + } + if (test[3]) { + element.setAttribute('max', test[3]); + } + + checkAttribute(element, 'optimum', test[0], test[1]); + + element.removeAttribute('min'); + element.removeAttribute('max'); + } +} + +function checkFormListedElement(aElement) +{ + is(document.forms[0].elements.length, 0, "the form should have no element"); +} + +function checkLabelable(aElement) +{ + var content = document.getElementById('content'); + var label = document.createElement('label'); + + content.appendChild(label); + label.appendChild(aElement); + is(label.control, aElement, "meter should be labelable"); + + // Cleaning-up. + content.removeChild(label); + content.appendChild(aElement); +} + +function checkNotResetableAndFormSubmission(aElement) +{ + // Creating an input element to check the submission worked. + var form = document.forms[0]; + var input = document.createElement('input'); + + input.name = 'a'; + input.value = 'tulip'; + form.appendChild(input); + + // Setting values. + aElement.value = 42.0; + aElement.max = 100.0; + + document.getElementsByName('submit_frame')[0].addEventListener("load", function() { + document.getElementsByName('submit_frame')[0].removeEventListener("load", arguments.callee, false); + + /** + * All elements values have been set just before the submission. + * The input element value should be in the submit url but the meter + * element value should not appear. + */ + is(frames['submit_frame'].location.href, + 'http://mochi.test:8888/tests/dom/html/test/forms/foo?a=tulip', + "The meter element value should not be submitted"); + + checkNotResetable(); + }, false); + + form.submit(); +} + +function checkNotResetable() +{ + // Try to reset the form. + var form = document.forms[0]; + var element = document.getElementById('m'); + + element.value = 3.0; + element.max = 42.0; + + form.reset(); + + SimpleTest.executeSoon(function() { + is(element.value, 3.0, "meter.value should not have changed"); + is(element.max, 42.0, "meter.max should not have changed"); + + SimpleTest.finish(); + }); +} + +SimpleTest.waitForExplicitFinish(); + +var m = document.getElementById('m'); + +ok(m instanceof HTMLMeterElement, + "The meter element should be instance of HTMLMeterElement"); +is(m.constructor, HTMLMeterElement, + "The meter element constructor should be HTMLMeterElement"); + +// There is no such attribute. +checkFormIDLAttribute(m); + +checkValueAttribute(); + +checkMinAttribute(); + +checkMaxAttribute(); + +checkLowAttribute(); + +checkHighAttribute(); + +checkOptimumAttribute(); + +checkFormListedElement(m); + +checkLabelable(m); + +checkNotResetableAndFormSubmission(m); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_meter_pseudo-classes.html b/dom/html/test/forms/test_meter_pseudo-classes.html new file mode 100644 index 000000000..e11f48a53 --- /dev/null +++ b/dom/html/test/forms/test_meter_pseudo-classes.html @@ -0,0 +1,170 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=660238 +--> +<head> + <title>Test for Bug 660238</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=770238">Mozilla Bug 660238</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 660238 **/ + +function checkOptimum(aElement, aValue, aOptimum, expectedResult) +{ + var errorString = expectedResult + ? "value attribute should be in the optimum region" + : "value attribute should not be in the optimum region"; + + aElement.setAttribute('value', aValue); + aElement.setAttribute('optimum', aOptimum); + is(aElement.matches(":-moz-meter-optimum"), + expectedResult, errorString); +} + +function checkSubOptimum(aElement, aValue, aOptimum, expectedResult) +{ + var errorString = "value attribute should be in the suboptimal region"; + if (!expectedResult) { + errorString = "value attribute should not be in the suboptimal region"; + } + aElement.setAttribute('value', aValue); + aElement.setAttribute('optimum', aOptimum); + is(aElement.matches(":-moz-meter-sub-optimum"), + expectedResult, errorString); +} + +function checkSubSubOptimum(aElement, aValue, aOptimum, expectedResult) +{ + var errorString = "value attribute should be in the sub-suboptimal region"; + if (!expectedResult) { + errorString = "value attribute should not be in the sub-suboptimal region"; + } + aElement.setAttribute('value', aValue); + aElement.setAttribute('optimum', aOptimum); + is(aElement.matches(":-moz-meter-sub-sub-optimum"), + expectedResult, errorString); +} + +function checkMozMatchesSelector() +{ + var element = document.createElement('meter'); + // all tests realised with default values for min and max (0 and 1) + // low = 0.3 and high = 0.7 + element.setAttribute('low', 0.3); + element.setAttribute('high', 0.7); + + var tests = [ + /* + * optimum = 0.0 => + * optimum region = [ 0.0, 0.3 [ + * suboptimal region = [ 0.3, 0.7 ] + * sub-suboptimal region = ] 0.7, 1.0 ] + */ + [ 0.0, 0.0, true, false, false ], + [ 0.1, 0.0, true, false, false ], + [ 0.3, 0.0, false, true, false ], + [ 0.5, 0.0, false, true, false ], + [ 0.7, 0.0, false, true, false ], + [ 0.8, 0.0, false, false, true ], + [ 1.0, 0.0, false, false, true ], + /* + * optimum = 0.1 => + * optimum region = [ 0.0, 0.3 [ + * suboptimal region = [ 0.3, 0.7 ] + * sub-suboptimal region = ] 0.7, 1.0 ] + */ + [ 0.0, 0.1, true, false, false ], + [ 0.1, 0.1, true, false, false ], + [ 0.3, 0.1, false, true, false ], + [ 0.5, 0.1, false, true, false ], + [ 0.7, 0.1, false, true, false ], + [ 0.8, 0.1, false, false, true ], + [ 1.0, 0.1, false, false, true ], + /* + * optimum = 0.3 => + * suboptimal region = [ 0.0, 0.3 [ + * optimum region = [ 0.3, 0.7 ] + * suboptimal region = ] 0.7, 1.0 ] + */ + [ 0.0, 0.3, false, true, false ], + [ 0.1, 0.3, false, true, false ], + [ 0.3, 0.3, true, false, false ], + [ 0.5, 0.3, true, false, false ], + [ 0.7, 0.3, true, false, false ], + [ 0.8, 0.3, false, true, false ], + [ 1.0, 0.3, false, true, false ], + /* + * optimum = 0.5 => + * suboptimal region = [ 0.0, 0.3 [ + * optimum region = [ 0.3, 0.7 ] + * suboptimal region = ] 0.7, 1.0 ] + */ + [ 0.0, 0.5, false, true, false ], + [ 0.1, 0.5, false, true, false ], + [ 0.3, 0.5, true, false, false ], + [ 0.5, 0.5, true, false, false ], + [ 0.7, 0.5, true, false, false ], + [ 0.8, 0.5, false, true, false ], + [ 1.0, 0.5, false, true, false ], + /* + * optimum = 0.7 => + * suboptimal region = [ 0.0, 0.3 [ + * optimum region = [ 0.3, 0.7 ] + * suboptimal region = ] 0.7, 1.0 ] + */ + [ 0.0, 0.7, false, true, false ], + [ 0.1, 0.7, false, true, false ], + [ 0.3, 0.7, true, false, false ], + [ 0.5, 0.7, true, false, false ], + [ 0.7, 0.7, true, false, false ], + [ 0.8, 0.7, false, true, false ], + [ 1.0, 0.7, false, true, false ], + /* + * optimum = 0.8 => + * sub-suboptimal region = [ 0.0, 0.3 [ + * suboptimal region = [ 0.3, 0.7 ] + * optimum region = ] 0.7, 1.0 ] + */ + [ 0.0, 0.8, false, false, true ], + [ 0.1, 0.8, false, false, true ], + [ 0.3, 0.8, false, true, false ], + [ 0.5, 0.8, false, true, false ], + [ 0.7, 0.8, false, true, false ], + [ 0.8, 0.8, true, false, false ], + [ 1.0, 0.8, true, false, false ], + /* + * optimum = 1.0 => + * sub-suboptimal region = [ 0.0, 0.3 [ + * suboptimal region = [ 0.3, 0.7 ] + * optimum region = ] 0.7, 1.0 ] + */ + [ 0.0, 1.0, false, false, true ], + [ 0.1, 1.0, false, false, true ], + [ 0.3, 1.0, false, true, false ], + [ 0.5, 1.0, false, true, false ], + [ 0.7, 1.0, false, true, false ], + [ 0.8, 1.0, true, false, false ], + [ 1.0, 1.0, true, false, false ], + ]; + + for (var test of tests) { + checkOptimum(element, test[0], test[1], test[2]); + checkSubOptimum(element, test[0], test[1], test[3]); + checkSubSubOptimum(element, test[0], test[1], test[4]); + } +} + +checkMozMatchesSelector(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_min_attribute.html b/dom/html/test/forms/test_min_attribute.html new file mode 100644 index 000000000..1258babec --- /dev/null +++ b/dom/html/test/forms/test_min_attribute.html @@ -0,0 +1,437 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=635553 +--> +<head> + <title>Test for Bug 635553</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 635553 **/ + +var data = [ + { type: 'hidden', apply: false }, + { type: 'text', apply: false }, + { type: 'search', apply: false }, + { type: 'tel', apply: false }, + { type: 'url', apply: false }, + { type: 'email', apply: false }, + { type: 'password', apply: false }, + { type: 'date', apply: true }, + { type: 'month', apply: true }, + { type: 'week', apply: true }, + { type: 'time', apply: true }, + // TODO: temporary set to false until bug 888331 is fixed. + { type: 'datetime-local', apply: false }, + { type: 'number', apply: true }, + { type: 'range', apply: true }, + { type: 'color', apply: false }, + { type: 'checkbox', apply: false }, + { type: 'radio', apply: false }, + { type: 'file', apply: false }, + { type: 'submit', apply: false }, + { type: 'image', apply: false }, + { type: 'reset', apply: false }, + { type: 'button', apply: false }, +]; + +var input = document.createElement("input"); +document.getElementById('content').appendChild(input); + +/** + * @aValidity - boolean indicating whether the element is expected to be valid + * (aElement.validity.valid is true) or not. The value passed is ignored and + * overridden with true if aApply is false. + * @aApply - boolean indicating whether the min/max attributes apply to this + * element type. + * @aRangeApply - A boolean that's set to true if the current input type is a + * "[candidate] for constraint validation" and it "[has] range limitations" + * per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range + * (in other words, one of the pseudo classes :in-range and :out-of-range + * should apply (which, depends on aValidity)). + * Else (neither :in-range or :out-of-range should match) set to false. + */ +function checkValidity(aElement, aValidity, aApply, aRangeApply) +{ + aValidity = aApply ? aValidity : true; + + is(aElement.validity.valid, aValidity, + "element validity should be " + aValidity); + is(aElement.validity.rangeUnderflow, !aValidity, + "element underflow status should be " + !aValidity); + var underflowMsg = + (aElement.type == "date" || aElement.type == "time" || + aElement.type == "month" || aElement.type == "week") ? + ("Please select a value that is no earlier than " + aElement.min + ".") : + ("Please select a value that is no less than " + aElement.min + "."); + is(aElement.validationMessage, + aValidity ? "" : underflowMsg, "Checking range underflow validation message"); + + is(aElement.matches(":valid"), aElement.willValidate && aValidity, + (aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply"); + is(aElement.matches(":invalid"), aElement.willValidate && !aValidity, + (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply"); + + if (!aRangeApply) { + ok(!aElement.matches(":in-range"), ":in-range should not match"); + ok(!aElement.matches(":out-of-range"), + ":out-of-range should not match"); + } else { + is(aElement.matches(":in-range"), aValidity, + ":in-range matches status should be " + aValidity); + is(aElement.matches(":out-of-range"), !aValidity, + ":out-of-range matches status should be " + !aValidity); + } +} + +for (var test of data) { + input.type = test.type; + var apply = test.apply; + + if (test.todo) { + todo_is(input.type, test.type, test.type + " isn't implemented yet"); + continue; + } + + // The element should be valid. Range should not apply when @min and @max are + // undefined, except if the input type is 'range' (since that type has a + // default minimum and maximum). + if (input.type == 'range') { + checkValidity(input, true, apply, true); + } else { + checkValidity(input, true, apply, false); + } + + switch (input.type) { + case 'hidden': + case 'text': + case 'search': + case 'password': + case 'url': + case 'tel': + case 'email': + case 'number': + case 'checkbox': + case 'radio': + case 'file': + case 'submit': + case 'reset': + case 'button': + case 'image': + case 'color': + input.min = '999'; + break; + case 'date': + input.min = '2012-06-27'; + break; + case 'time': + input.min = '20:20'; + break; + case 'range': + // range is special, since setting min to 999 will make it invalid since + // it's default maximum is 100, its value would be 999, and it would + // suffer from overflow. + break; + case 'month': + input.min = '2016-06'; + break; + case 'week': + input.min = "2016-W39"; + break; + case 'datetime-local': + // TODO: this is temporary until bug 888331 is fixed. + break; + default: + ok(false, 'please, add a case for this new type (' + input.type + ')'); + } + + // The element should still be valid and range should apply if it can. + checkValidity(input, true, apply, apply); + + switch (input.type) { + case 'text': + case 'hidden': + case 'search': + case 'password': + case 'tel': + case 'radio': + case 'checkbox': + case 'reset': + case 'button': + case 'submit': + case 'image': + case 'color': + input.value = '0'; + checkValidity(input, true, apply, apply); + break; + case 'url': + input.value = 'http://mozilla.org'; + checkValidity(input, true, apply, apply); + break; + case 'email': + input.value = 'foo@bar.com'; + checkValidity(input, true, apply, apply); + break; + case 'file': + var file = new File([''], '635499_file'); + + SpecialPowers.wrap(input).mozSetFileArray([file]); + checkValidity(input, true, apply, apply); + + break; + case 'date': + input.value = '2012-06-28'; + checkValidity(input, true, apply, apply); + + input.value = '2012-06-27'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '2012-06-26'; + checkValidity(input, false, apply, apply); + + input.min = '2012-02-29'; + checkValidity(input, true, apply, apply); + + input.value = '2012-02-28'; + checkValidity(input, false, apply, apply); + + input.value = '1000-01-01'; + checkValidity(input, false, apply, apply); + + input.value = '20120-01-01'; + checkValidity(input, true, apply, apply); + + input.min = '0050-01-01'; + checkValidity(input, true, apply, apply); + + input.value = '0049-01-01'; + checkValidity(input, false, apply, apply); + + input.min = ''; + checkValidity(input, true, apply, false); + + input.min = 'foo'; + checkValidity(input, true, apply, false); + break; + case 'number': + input.min = '0'; + input.value = '1'; + checkValidity(input, true, apply, apply); + + input.value = '0'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '-1'; + checkValidity(input, false, apply, apply); + + input.min = '-1'; + checkValidity(input, true, apply, apply); + + input.value = '-42'; + checkValidity(input, false, apply, apply); + + input.min = ''; + checkValidity(input, true, apply, false); + + input.min = 'foo'; + checkValidity(input, true, apply, false); + + // Check that we correctly convert input.min to a double in + // validationMessage. + input.min = "4.333333333333333333333333333333333331"; + input.value = "2"; + is(input.validationMessage, + "Please select a value that is no less than 4.33333333333333.", + "validation message"); + break; + case 'range': + input.min = '0'; + input.value = '1'; + checkValidity(input, true, apply, apply); + + input.value = '0'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '-1'; + checkValidity(input, true, apply, apply); + + is(input.value, input.min, "the value should have been set to min"); + + input.min = '-1'; + checkValidity(input, true, apply, apply); + + input.value = '-42'; + checkValidity(input, true, apply, apply); + + is(input.value, input.min, "the value should have been set to min"); + + input.min = ''; + checkValidity(input, true, apply, true); + + input.min = 'foo'; + checkValidity(input, true, apply, true); + + // We don't check the conversion of input.min to a double in + // validationMessage for 'range' since range will always clamp the value + // up to at least the minimum (so we will never see the min in a + // validationMessage). + + break; + case 'time': + // Don't worry about that. + input.step = 'any'; + + input.min = '20:20'; + input.value = '20:20:01'; + checkValidity(input, true, apply, apply); + + input.value = '20:20:00'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '10:00'; + checkValidity(input, false, apply, apply); + + input.min = '20:20:00.001'; + input.value = '20:20'; + checkValidity(input, false, apply, apply); + + input.value = '00:00'; + checkValidity(input, false, apply, apply); + + input.value = '23:59'; + checkValidity(input, true, apply, apply); + + input.value = '20:20:01'; + checkValidity(input, true, apply, apply); + + input.value = '20:20:00.01'; + checkValidity(input, true, apply, apply); + + input.value = '20:20:00.1'; + checkValidity(input, true, apply, apply); + + input.min = '00:00:00'; + input.value = '01:00'; + checkValidity(input, true, apply, apply); + + input.value = '00:00:00.000'; + checkValidity(input, true, apply, apply); + + input.min = ''; + checkValidity(input, true, apply, false); + + input.min = 'foo'; + checkValidity(input, true, apply, false); + break; + case 'month': + input.value = '2016-07'; + checkValidity(input, true, apply, apply); + + input.value = '2016-06'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '2016-05'; + checkValidity(input, false, apply, apply); + + input.min = '2016-01'; + checkValidity(input, true, apply, apply); + + input.value = '2015-12'; + checkValidity(input, false, apply, apply); + + input.value = '1000-01'; + checkValidity(input, false, apply, apply); + + input.value = '10000-01'; + checkValidity(input, true, apply, apply); + + input.min = '0010-01'; + checkValidity(input, true, apply, apply); + + input.value = '0001-01'; + checkValidity(input, false, apply, apply); + + input.min = ''; + checkValidity(input, true, apply, false); + + input.min = 'foo'; + checkValidity(input, true, apply, false); + break; + case 'week': + input.value = '2016-W40'; + checkValidity(input, true, apply, apply); + + input.value = '2016-W39'; + checkValidity(input, true, apply, apply); + + input.value = 'foo'; + checkValidity(input, true, apply, apply); + + input.value = '2016-W38'; + checkValidity(input, false, apply, apply); + + input.min = '2016-W01'; + checkValidity(input, true, apply, apply); + + input.value = '2015-W53'; + checkValidity(input, false, apply, apply); + + input.value = '1000-W01'; + checkValidity(input, false, apply, apply); + + input.value = '10000-01'; + checkValidity(input, true, apply, apply); + + input.min = '0010-W01'; + checkValidity(input, true, apply, apply); + + input.value = '0001-W01'; + checkValidity(input, false, apply, apply); + + input.min = ''; + checkValidity(input, true, apply, false); + + input.min = 'foo'; + checkValidity(input, true, apply, false); + break; + case 'datetime-local': + // TODO: this is temporary until bug 888331 is fixed. + break; + default: + ok(false, 'write tests for ' + input.type); + } + + // Cleaning up, + input.removeAttribute('min'); + input.value = ''; +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_minlength_attribute.html b/dom/html/test/forms/test_minlength_attribute.html new file mode 100644 index 000000000..ca3743bd9 --- /dev/null +++ b/dom/html/test/forms/test_minlength_attribute.html @@ -0,0 +1,130 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=345624 +--> +<head> + <title>Test for Bug 345624</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input, textarea { background-color: rgb(0,0,0) !important; } + :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; } + :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a> +<p id="display"></p> +<div id="content"> + <input id='i'> + <textarea id='t'></textarea> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 345624 **/ + +/** + * This test is checking only tooShort related features + * related to constraint validation. + */ + +function checkTooShortValidity(element) +{ + element.value = "foo"; + ok(!element.validity.tooShort, + "Element should not be too short when minlength is not set"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.minLength = 5; + ok(!element.validity.tooShort, + "Element should not be too short unless the user edits it"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.focus(); + + synthesizeKey("o", {}); + is(element.value, "fooo", "value should have changed"); + ok(element.validity.tooShort, + "Element should be too short after a user edit that does not make it short enough"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + ok(!element.validity.valid, "Element should be invalid"); + ok(!element.checkValidity(), "The element should not be valid"); + is(element.validationMessage, + "Please use at least 5 characters (you are currently using 4 characters).", + "The validation message text is not correct"); + + synthesizeKey("o", {}); + is(element.value, "foooo", "value should have changed"); + ok(!element.validity.tooShort, + "Element should not be too short after a user edit makes it long enough"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + + element.minLength = 2; + ok(!element.validity.tooShort, + "Element should remain valid if minlength changes but minlength < length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + + element.minLength = 1; + ok(!element.validity.tooShort, + "Element should remain valid if minlength changes but minlength = length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.minLength = 6; + ok(element.validity.tooShort, + "Element should become invalid if minlength changes and minlength > length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + ok(!element.validity.valid, "Element should be invalid"); + ok(!element.checkValidity(), "The element should not be valid"); + is(element.validationMessage, + "Please use at least 6 characters (you are currently using 5 characters).", + "The validation message text is not correct"); + + element.minLength = 5; + ok(!element.validity.tooShort, + "Element should become valid if minlength changes and minlength = length"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.value = "test"; + ok(!element.validity.tooShort, + "Element should stay valid after programmatic edit (even if value is too short)"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "The element should be valid"); + + element.setCustomValidity("custom message"); + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + is(element.validationMessage, "custom message", + "Custom message should be shown instead of too short one"); +} + +checkTooShortValidity(document.getElementById('i')); +checkTooShortValidity(document.getElementById('t')); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/forms/test_mozistextfield.html b/dom/html/test/forms/test_mozistextfield.html new file mode 100644 index 000000000..7c5a6bc5a --- /dev/null +++ b/dom/html/test/forms/test_mozistextfield.html @@ -0,0 +1,111 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=565538 +--> +<head> + <title>Test for Bug 565538</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=565538">Mozilla Bug 565538</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 565538 **/ + +var gElementTestData = [ +/* element result */ + ['input', true], + ['button', false], + ['fieldset', false], + ['label', false], + ['option', false], + ['optgroup', false], + ['output', false], + ['legend', false], + ['select', false], + ['textarea', false], + ['object', false], +]; + +var gInputTestData = [ +/* type result */ + ['password', true], + ['tel', true], + ['text', true], + ['button', false], + ['checkbox', false], + ['file', false], + ['hidden', false], + ['reset', false], + ['image', false], + ['radio', false], + ['submit', false], + ['search', true], + ['email', true], + ['url', true], + ['number', false], + ['range', false], + ['date', false], + ['time', false], + ['color', false], + ['month', false], + ['week', false], + ['datetime-local', false], +]; + +function checkMozIsTextFieldDefined(aElement, aResult) +{ + var element = document.createElement(aElement); + + var msg = "mozIsTextField should be " + if (aResult) { + msg += "defined"; + } else { + msg += "undefined"; + } + + is('mozIsTextField' in element, aResult, msg); +} + +function checkMozIsTextFieldValue(aInput, aResult) +{ + is(aInput.mozIsTextField(false), aResult, + "mozIsTextField(false) should return " + aResult); + + if (aInput.type == 'password') { + ok(!aInput.mozIsTextField(true), + "mozIsTextField(true) should return false for password"); + } else { + is(aInput.mozIsTextField(true), aResult, + "mozIsTextField(true) should return " + aResult); + } +} + +function checkMozIsTextFieldValueTodo(aInput, aResult) +{ + todo_is(aInput.mozIsTextField(false), aResult, + "mozIsTextField(false) should return " + aResult); + todo_is(aInput.mozIsTextField(true), aResult, + "mozIsTextField(true) should return " + aResult); +} + +// Check if the method is defined for the correct elements. +for (data of gElementTestData) { + checkMozIsTextFieldDefined(data[0], data[1]); +} + +// Check if the method returns the correct value. +var input = document.createElement('input'); +for (data of gInputTestData) { + input.type = data[0]; + checkMozIsTextFieldValue(input, data[1]); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_novalidate_attribute.html b/dom/html/test/forms/test_novalidate_attribute.html new file mode 100644 index 000000000..38b789f5f --- /dev/null +++ b/dom/html/test/forms/test_novalidate_attribute.html @@ -0,0 +1,87 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=556013 +--> +<head> + <title>Test for Bug 556013</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=556013">Mozilla Bug 556013</a> +<p id="display"></p> +<iframe style='width:50px; height: 50px;' name='t'></iframe> +<div id="content"> + <form target='t' action='data:text/html,' novalidate> + <input id='av' required> + <input id='a' type='submit'> + </form> + <form target='t' action='data:text/html,' novalidate> + <input id='bv' type='checkbox' required> + <button id='b' type='submit'></button> + </form> + <form target='t' action='data:text/html,' novalidate> + <input id='c' required> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 556013 **/ + +/** + * novalidate should prevent form validation, thus not blocking form submission. + * + * NOTE: if there is no invalidformsubmit observer, the form submission will + * never be blocked and this test might be a false-positive but that should not + * be a problem. + */ +document.forms[0].addEventListener("submit", function(aEvent) { + aEvent.target.removeEventListener("submit", arguments.callee, false); + ok(true, "novalidate has been correctly used for first form"); + document.getElementById('b').click(); +}, false); + +document.forms[1].addEventListener("submit", function(aEvent) { + aEvent.target.removeEventListener("submit", arguments.callee, false); + ok(true, "novalidate has been correctly used for second form"); + var c = document.getElementById('c'); + c.focus(); + synthesizeKey("KEY_Enter", { code: "Enter" }); +}, false); + +document.forms[2].addEventListener("submit", function(aEvent) { + aEvent.target.removeEventListener("submit", arguments.callee, false); + ok(true, "novalidate has been correctly used for third form"); + SimpleTest.executeSoon(SimpleTest.finish); +}, false); + +/** + * We have to be sure invalid events are not send too. + * They should be sent before the submit event so we can just create a test + * failure if we got one. All of them should be catched if sent. + * At worst, we got random green which isn't harmful. + */ +function invalidHandling(aEvent) +{ + aEvent.target.removeEventListener("invalid", invalidHandling, false); + ok(false, "invalid event should not be sent"); +} + +document.getElementById('av').addEventListener("invalid", invalidHandling, false); +document.getElementById('bv').addEventListener("invalid", invalidHandling, false); +document.getElementById('c').addEventListener("invalid", invalidHandling, false); + +SimpleTest.waitForExplicitFinish(); + +// This is going to call all the tests (with a chain reaction). +SimpleTest.waitForFocus(function() { + document.getElementById('a').click(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_option_disabled.html b/dom/html/test/forms/test_option_disabled.html new file mode 100644 index 000000000..1383b0846 --- /dev/null +++ b/dom/html/test/forms/test_option_disabled.html @@ -0,0 +1,123 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=759666 +--> +<head> + <meta charset="utf-8"> + <title>Test for HTMLOptionElement disabled attribute and pseudo-class</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=759666">Mozilla Bug 759666</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLOptionElement disabled attribute and pseudo-class **/ + +var testCases = [ + // Static checks. + { html: "<option></option>", + result: { attr: null, idl: false, pseudo: false } }, + { html: "<option disabled></option>", + result: { attr: "", idl: true, pseudo: true } }, + { html: "<optgroup><option></option></otpgroup>", + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup><option disabled></option></optgroup>", + result: { attr: "", idl: true, pseudo: true } }, + { html: "<optgroup disabled><option disabled></option></optgroup>", + result: { attr: "", idl: true, pseudo: true } }, + { html: "<optgroup disabled><option></option></optgroup>", + result: { attr: null, idl: false, pseudo: true } }, + { html: "<optgroup><optgroup disabled><option></option></optgroup></optgroup>", + result: { attr: null, idl: false, pseudo: true } }, + { html: "<optgroup disabled><optgroup><option></option></optgroup></optgroup>", + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>", + result: { attr: "", idl: true, pseudo: true } }, + + // Dynamic checks: changing disable value. + { html: "<option></option>", + modifier: function(c) { c.querySelector('option').disabled = true; }, + result: { attr: "", idl: true, pseudo: true } }, + { html: "<option disabled></option>", + modifier: function(c) { c.querySelector('option').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup><option></option></otpgroup>", + modifier: function(c) { c.querySelector('optgroup').disabled = true; }, + result: { attr: null, idl: false, pseudo: true } }, + { html: "<optgroup><option disabled></option></optgroup>", + modifier: function(c) { c.querySelector('option').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup disabled><option disabled></option></optgroup>", + modifier: function(c) { c.querySelector('optgroup').disabled = false; }, + result: { attr: "", idl: true, pseudo: true } }, + { html: "<optgroup disabled><option disabled></option></optgroup>", + modifier: function(c) { c.querySelector('option').disabled = false; }, + result: { attr: null, idl: false, pseudo: true } }, + { html: "<optgroup disabled><option disabled></option></optgroup>", + modifier: function(c) { c.querySelector('optgroup').disabled = c.querySelector('option').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup disabled><option></option></optgroup>", + modifier: function(c) { c.querySelector('optgroup').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup><optgroup disabled><option></option></optgroup></optgroup>", + modifier: function(c) { c.querySelector('optgroup[disabled]').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup disabled><optgroup><option></option></optgroup></optgroup>", + modifier: function(c) { c.querySelector('optgroup[disabled]').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>", + modifier: function(c) { c.querySelector('optgroup').disabled = false; }, + result: { attr: "", idl: true, pseudo: true } }, + { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>", + modifier: function(c) { c.querySelector('option').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>", + modifier: function(c) { c.querySelector('option').disabled = c.querySelector('option').disabled = false; }, + result: { attr: null, idl: false, pseudo: false } }, + + // Dynamic checks: moving option element. + { html: "<optgroup id='a'><option></option></optgroup><optgroup id='b'></optgroup>", + modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); }, + result: { attr: null, idl: false, pseudo: false } }, + { html: "<optgroup id='a'><option disabled></option></optgroup><optgroup id='b'></optgroup>", + modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); }, + result: { attr: "", idl: true, pseudo: true } }, + { html: "<optgroup id='a'><option></option></optgroup><optgroup disabled id='b'></optgroup>", + modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); }, + result: { attr: null, idl: false, pseudo: true } }, + { html: "<optgroup disabled id='a'><option></option></optgroup><optgroup id='b'></optgroup>", + modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); }, + result: { attr: null, idl: false, pseudo: false } }, +]; + +var content = document.getElementById('content'); + +testCases.forEach(function(testCase) { + var result = testCase.result; + + content.innerHTML = testCase.html; + + if (testCase.modifier !== undefined) { + testCase.modifier(content); + } + + var option = content.querySelector('option'); + is(option.getAttribute('disabled'), result.attr, "disabled content attribute value should be " + result.attr); + is(option.disabled, result.idl, "disabled idl attribute value should be " + result.idl); + is(option.matches(":disabled"), result.pseudo, ":disabled state should be " + result.pseudo); + is(option.matches(":enabled"), !result.pseudo, ":enabled state should be " + !result.pseudo); + + content.innerHTML = ""; +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_option_index_attribute.html b/dom/html/test/forms/test_option_index_attribute.html new file mode 100644 index 000000000..5d51d2991 --- /dev/null +++ b/dom/html/test/forms/test_option_index_attribute.html @@ -0,0 +1,76 @@ +<!DOCTYPE HTML> +<html> +<!-- +See those bugs: +https://bugzilla.mozilla.org/show_bug.cgi?id=720385 +--> +<head> + <meta charset="utf-8"> + <title>Test for option.index</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720385">Mozilla Bug 720385</a> +<p id="display"></p> +<div id="content" style="display: none"> + <datalist> + <option></option> + <option></option> + </datalist> + <select> + <option></option> + <foo> + <option></option> + <optgroup> + <option></option> + </optgroup> + <option></option> + </foo> + <option></option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 720385 **/ + +var initialIndexes = [ 0, 0, 0, 1, 2, 3, 4 ]; +var options = document.getElementsByTagName('option'); + +is(options.length, initialIndexes.length, + "Must have " + initialIndexes.length +" options"); + +for (var i=0; i<options.length; ++i) { + is(options[i].index, initialIndexes[i], "test"); +} + +var o = document.createElement('option'); +is(o.index, 0, "option outside of a document have index=0"); + +document.body.appendChild(o); +is(o.index, 0, "option outside of a select have index=0"); + +var datalist = document.getElementsByTagName('datalist')[0]; + +datalist.appendChild(o); +is(o.index, 0, "option outside of a select have index=0"); + +datalist.removeChild(o); +is(o.index, 0, "option outside of a select have index=0"); + +var select = document.getElementsByTagName('select')[0]; + +select.appendChild(o); +is(o.index, 5, "option inside a select have an index"); + +select.removeChild(select.options[0]); +is(o.index, 4, "option inside a select have an index"); + +select.insertBefore(o, select.options[0]); +is(o.index, 0, "option inside a select have an index"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_option_text.html b/dom/html/test/forms/test_option_text.html new file mode 100644 index 000000000..3afe3e786 --- /dev/null +++ b/dom/html/test/forms/test_option_text.html @@ -0,0 +1,57 @@ +<!doctype html> +<meta charset=utf-8> +<title>HTMLOptionElement.text</title> +<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com"> +<link rel=help href="http://www.whatwg.org/html/#dom-option-text"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +test(function() { + var option = document.createElement("option"); + option.appendChild(document.createElement("font")) + .appendChild(document.createTextNode(" font ")); + assert_equals(option.text, "font"); +}, "option.text should recurse"); +test(function() { + var option = document.createElement("option"); + option.appendChild(document.createTextNode(" before ")); + option.appendChild(document.createElement("script")) + .appendChild(document.createTextNode(" script ")); + option.appendChild(document.createTextNode(" after ")); + assert_equals(option.text, "before after"); +}, "option.text should not recurse into HTML script elements"); +test(function() { + var option = document.createElement("option"); + option.appendChild(document.createTextNode(" before ")); + option.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "script")) + .appendChild(document.createTextNode(" script ")); + option.appendChild(document.createTextNode(" after ")); + assert_equals(option.text, "before after"); +}, "option.text should not recurse into SVG script elements"); +test(function() { + var option = document.createElement("option"); + option.appendChild(document.createTextNode(" before ")); + option.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "script")) + .appendChild(document.createTextNode(" script ")); + option.appendChild(document.createTextNode(" after ")); + assert_equals(option.text, "before script after"); +}, "option.text should recurse into MathML script elements"); +test(function() { + var option = document.createElement("option"); + option.appendChild(document.createTextNode(" before ")); + option.appendChild(document.createElementNS(null, "script")) + .appendChild(document.createTextNode(" script ")); + option.appendChild(document.createTextNode(" after ")); + assert_equals(option.text, "before script after"); +}, "option.text should recurse into null script elements"); +test(function() { + var option = document.createElement("option"); + var span = option.appendChild(document.createElement("span")); + span.appendChild(document.createTextNode(" Some ")); + span.appendChild(document.createElement("script")) + .appendChild(document.createTextNode(" script ")); + option.appendChild(document.createTextNode(" Text ")); + assert_equals(option.text, "Some Text"); +}, "option.text should work if a child of the option ends with a script"); +</script> diff --git a/dom/html/test/forms/test_output_element.html b/dom/html/test/forms/test_output_element.html new file mode 100644 index 000000000..5b4097047 --- /dev/null +++ b/dom/html/test/forms/test_output_element.html @@ -0,0 +1,182 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=346485 +--> +<head> + <title>Test for Bug 346485</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + frameLoaded = function() { + is(frames['submit_frame'].location.href, "about:blank", + "Blank frame loaded"); + } + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=346485">Mozilla Bug 346485</a> +<p id="display"></p> +<iframe name="submit_frame" onload="frameLoaded()" style="visibility: hidden;"></iframe> +<div id="content" style="display: none"> + <form id='f' method='get' target='submit_frame' action='foo'> + <input name='a' id='a'> + <input name='b' id='b'> + <output id='o' for='a b' name='output-name'>tulip</output> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 346485 **/ + +function checkNameAttribute(element) +{ + is(element.name, "output-name", "Output name IDL attribute is not correct"); + is(element.getAttribute('name'), "output-name", + "Output name content attribute is not correct"); +} + +function checkValueAndDefaultValueIDLAttribute(element) +{ + is(element.value, element.textContent, + "The value IDL attribute should act like the textContent IDL attribute"); + + element.value = "foo"; + is(element.value, "foo", "Value should be 'foo'"); + + is(element.defaultValue, "", "Default defaultValue is ''"); + + element.defaultValue = "bar"; + is(element.defaultValue, "bar", "defaultValue should be 'bar'"); + + // More complex situation. + element.textContent = 'foo'; + var b = document.createElement('b'); + b.textContent = 'bar' + element.appendChild(b); + is(element.value, element.textContent, + "The value IDL attribute should act like the textContent IDL attribute"); +} + +function checkValueModeFlag(element) +{ + /** + * The value mode flag is the flag used to know if value should represent the + * textContent or the default value. + */ + // value mode flag should be 'value' + isnot(element.defaultValue, element.value, + "When value is set, defaultValue keeps its value"); + + var f = document.getElementById('f'); + f.reset(); + // value mode flag should be 'default' + is(element.defaultValue, element.value, "When reset, defaultValue=value"); + is(element.textContent, element.defaultValue, + "textContent should contain the defaultValue"); +} + +function checkDescendantChanged(element) +{ + /** + * Whenever a descendant is changed if the value mode flag is value, + * the default value should be the textContent value. + */ + element.defaultValue = 'tulip'; + element.value = 'foo'; + + // set value mode flag to 'default' + var f = document.getElementById('f'); + f.reset(); + + is(element.textContent, element.defaultValue, + "textContent should contain the defaultValue"); + element.textContent = "bar"; + is(element.textContent, element.defaultValue, + "textContent should contain the defaultValue"); +} + +function checkFormIDLAttribute(element) +{ + is(element.form, document.getElementById('f'), + "form IDL attribute is invalid"); +} + +function checkHtmlForIDLAttribute(element) +{ + is(String(element.htmlFor), 'a b', + "htmlFor IDL attribute should reflect the for content attribute"); + + // DOMTokenList is tested in another bug so we just test assignation + element.htmlFor.value = 'a b c'; + is(String(element.htmlFor), 'a b c', "htmlFor should have changed"); +} + +function submitForm() +{ + // Setting the values for the submit. + document.getElementById('o').value = 'foo'; + document.getElementById('a').value = 'afield'; + document.getElementById('b').value = 'bfield'; + + frameLoaded = checkFormSubmission; + + // This will call checkFormSubmission() which is going to call ST.finish(). + document.getElementById('f').submit(); +} + +function checkFormSubmission() +{ + /** + * All elements values have been set just before the submission. + * The input elements values should be in the submit url but the ouput + * element value should not appear. + */ + + is(frames['submit_frame'].location.href, + 'http://mochi.test:8888/tests/dom/html/test/forms/foo?a=afield&b=bfield', + "The output element value should not be submitted"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + reflectString({ + element: document.createElement("output"), + attribute: "name", + }); + + var o = document.getElementsByTagName('output'); + is(o.length, 1, "There should be one output element"); + + o = o[0]; + ok(o instanceof HTMLOutputElement, + "The output should be instance of HTMLOutputElement"); + + o = document.getElementById('o'); + ok(o instanceof HTMLOutputElement, + "The output should be instance of HTMLOutputElement"); + + is(o.type, "output", "Output type IDL attribute should be 'output'"); + + checkNameAttribute(o); + + checkValueAndDefaultValueIDLAttribute(o); + + checkValueModeFlag(o); + + checkDescendantChanged(o); + + checkFormIDLAttribute(o); + + checkHtmlForIDLAttribute(o); + + submitForm(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_pattern_attribute.html b/dom/html/test/forms/test_pattern_attribute.html new file mode 100644 index 000000000..efa1a1543 --- /dev/null +++ b/dom/html/test/forms/test_pattern_attribute.html @@ -0,0 +1,324 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=345512 +--> +<head> + <title>Test for Bug 345512</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input { background-color: rgb(0,0,0) !important; } + input:valid { background-color: rgb(0,255,0) !important; } + input:invalid { background-color: rgb(255,0,0) !important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345512">Mozilla Bug 345512</a> +<p id="display"></p> +<div id="content" style="display: none"> + <input id='i' pattern="tulip" oninvalid="invalidEventHandler(event);"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 345512 **/ + +var gInvalid = false; + +function invalidEventHandler(e) +{ + is(e.type, "invalid", "Invalid event type should be invalid"); + gInvalid = true; +} + +function completeValidityCheck(element, alwaysValid, isBarred) +{ + // Check when pattern matches. + if (element.type == 'email') { + element.pattern = ".*@bar.com"; + element.value = "foo@bar.com"; + } else if (element.type == 'url') { + element.pattern = "http://.*\\.com$"; + element.value = "http://mozilla.com"; + } else if (element.type == 'file') { + element.pattern = "foo"; + SpecialPowers.wrap(element).mozSetFileArray([new File(["foo"], "foo")]); + } else { + element.pattern = "foo"; + element.value = "foo"; + } + + checkValidPattern(element, true, isBarred); + + // Check when pattern does not match. + + if (element.type == 'email') { + element.pattern = ".*@bar.com"; + element.value = "foo@foo.com"; + } else if (element.type == 'url') { + element.pattern = "http://.*\\.com$"; + element.value = "http://mozilla.org"; + } else if (element.type == 'file') { + element.pattern = "foo"; + SpecialPowers.wrap(element).mozSetFileArray([new File(["bar"], "bar")]); + } else { + element.pattern = "foo"; + element.value = "bar"; + } + + if (!alwaysValid) { + checkInvalidPattern(element, true); + } else { + checkValidPattern(element, true, isBarred); + } +} + +function checkValidPattern(element, completeCheck, isBarred) +{ + if (completeCheck) { + gInvalid = false; + + ok(!element.validity.patternMismatch, + "Element should not suffer from pattern mismatch"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "Element should be valid"); + ok(!gInvalid, "Invalid event shouldn't have been thrown"); + is(element.validationMessage, '', + "Validation message should be the empty string"); + if (element.type != 'radio' && element.type != 'checkbox') { + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + isBarred ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)", + "The pseudo-class is not correctly applied"); + } + } else { + ok(!element.validity.patternMismatch, + "Element should not suffer from pattern mismatch"); + } +} + +function checkInvalidPattern(element, completeCheck) +{ + if (completeCheck) { + gInvalid = false; + + ok(element.validity.patternMismatch, + "Element should suffer from pattern mismatch"); + ok(!element.validity.valid, "Element should not be valid"); + ok(!element.checkValidity(), "Element should not be valid"); + ok(gInvalid, "Invalid event should have been thrown"); + is(element.validationMessage, + "Please match the requested format.", + "Validation message is not valid"); + } else { + ok(element.validity.patternMismatch, + "Element should suffer from pattern mismatch"); + } + + if (element.type != 'radio' && element.type != 'checkbox') { + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + } +} + +function checkSyntaxError(element) +{ + ok(!element.validity.patternMismatch, + "On SyntaxError, element should not suffer"); +} + +function checkPatternValidity(element) +{ + element.pattern = "foo"; + + element.value = ''; + checkValidPattern(element); + + element.value = "foo"; + checkValidPattern(element); + + element.value = "bar"; + checkInvalidPattern(element); + + element.value = "foobar"; + checkInvalidPattern(element); + + element.value = "foofoo"; + checkInvalidPattern(element); + + element.pattern = "foo\"bar"; + element.value = "foo\"bar"; + checkValidPattern(element); + + element.value = 'foo"bar'; + checkValidPattern(element); + + element.pattern = "foo'bar"; + element.value = "foo\'bar"; + checkValidPattern(element); + + element.pattern = "foo\\(bar"; + element.value = "foo(bar"; + checkValidPattern(element); + + element.value = "foo"; + checkInvalidPattern(element); + + element.pattern = "foo\\)bar"; + element.value = "foo)bar"; + checkValidPattern(element); + + element.value = "foo"; + checkInvalidPattern(element); + + // Check for 'i' flag disabled. Should be case sensitive. + element.value = "Foo"; + checkInvalidPattern(element); + + // We can't check for the 'g' flag because we only test, we don't execute. + // We can't check for the 'm' flag because .value shouldn't contain line breaks. + + // We need '\\\\' because '\\' will produce '\\' and we want to escape the '\' + // for the regexp. + element.pattern = "foo\\\\bar"; + element.value = "foo\\bar"; + checkValidPattern(element); + + // We may want to escape the ' in the pattern, but this is a SyntaxError + // when unicode flag is set. + element.pattern = "foo\\'bar"; + element.value = "foo'bar"; + checkSyntaxError(element); + element.value = "baz"; + checkSyntaxError(element); + + // We should check the pattern attribute do not pollute |RegExp.lastParen|. + is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string"); + + element.pattern = "(foo)"; + element.value = "foo"; + checkValidPattern(element); + is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string"); + + // That may sound weird but the empty string is a valid pattern value. + element.pattern = ""; + element.value = ""; + checkValidPattern(element); + + element.value = "foo"; + checkInvalidPattern(element); + + // Checking some complex patterns. As we are using js regexp mechanism, these + // tests doesn't aim to test the regexp mechanism. + element.pattern = "\\d{2}\\s\\d{2}\\s\\d{4}" + element.value = "01 01 2010" + checkValidPattern(element); + + element.value = "01/01/2010" + checkInvalidPattern(element); + + element.pattern = "[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z_+])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9}"; + element.value = "foo@bar.com"; + checkValidPattern(element); + + element.value = "...@bar.com"; + checkInvalidPattern(element); + + element.pattern = "^(?:\\w{3,})$"; + element.value = "foo"; + checkValidPattern(element); + + element.value = "f"; + checkInvalidPattern(element); + + // If @title is specified, it should be added in the validation message. + if (element.type == 'email') { + element.pattern = "foo@bar.com" + element.value = "bar@foo.com"; + } else if (element.type == 'url') { + element.pattern = "http://mozilla.com"; + element.value = "http://mozilla.org"; + } else { + element.pattern = "foo"; + element.value = "bar"; + } + element.title = "this is an explanation of the regexp"; + is(element.validationMessage, + "Please match the requested format: " + element.title + ".", + "Validation message is not valid"); + element.title = ""; + is(element.validationMessage, + "Please match the requested format.", + "Validation message is not valid"); + + element.pattern = "foo"; + if (element.type == 'email') { + element.value = "bar@foo.com"; + } else if (element.type == 'url') { + element.value = "http://mozilla.org"; + } else { + element.value = "bar"; + } + checkInvalidPattern(element); + + element.removeAttribute('pattern'); + checkValidPattern(element, true); + + // Unicode pattern + for (var pattern of ["\\u{1F438}{2}", "\u{1F438}{2}", + "\\uD83D\\uDC38{2}", "\uD83D\uDC38{2}", + "\u{D83D}\u{DC38}{2}"]) { + element.pattern = pattern; + + element.value = "\u{1F438}\u{1F438}"; + checkValidPattern(element); + + element.value = "\uD83D\uDC38\uD83D\uDC38"; + checkValidPattern(element); + + element.value = "\uD83D\uDC38\uDC38"; + checkInvalidPattern(element); + } + + element.pattern = "\\u{D83D}\\u{DC38}{2}"; + + element.value = "\u{1F438}\u{1F438}"; + checkInvalidPattern(element); + + element.value = "\uD83D\uDC38\uD83D\uDC38"; + checkInvalidPattern(element); + + element.value = "\uD83D\uDC38\uDC38"; + checkInvalidPattern(element); +} + +var input = document.getElementById('i'); + +// |validTypes| are the types which accept @pattern +// and |invalidTypes| are the ones which do not accept it. +var validTypes = Array('text', 'password', 'search', 'tel', 'email', 'url'); +var barredTypes = Array('hidden', 'reset', 'button'); +var invalidTypes = Array('checkbox', 'radio', 'file', 'number', 'range', 'date', + 'time', 'color', 'submit', 'image', 'month', 'week', + 'datetime-local'); + +for (type of validTypes) { + input.type = type; + completeValidityCheck(input, false); + checkPatternValidity(input); +} + +for (type of barredTypes) { + input.type = type; + completeValidityCheck(input, true, true); +} + +for (type of invalidTypes) { + input.type = type; + completeValidityCheck(input, true); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_progress_element.html b/dom/html/test/forms/test_progress_element.html new file mode 100644 index 000000000..bb1f801b2 --- /dev/null +++ b/dom/html/test/forms/test_progress_element.html @@ -0,0 +1,314 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=514437 +https://bugzilla.mozilla.org/show_bug.cgi?id=633913 +--> +<head> + <title>Test for progress element content and layout</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=514437">Mozilla Bug 514437</a> +and +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633913">Mozilla Bug 633913</a> +<p id="display"></p> +<iframe name="submit_frame" style="visibility: hidden;"></iframe> +<div id="content" style="visibility: hidden;"> + <form id='f' method='get' target='submit_frame' action='foo'> + <progress id='p'></progress> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +SimpleTest.expectAssertions(0, 1); + +/** Test for progress element content and layout **/ + +function checkFormIDLAttribute(aElement) +{ + is("form" in aElement, false, "<progress> shouldn't have a form attribute"); +} + +function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL) +{ + var expectedValueForIDL = aNewValue; + var expectedValueForContent = String(aNewValue); + + if (aExpectedValueForIDL !== undefined) { + expectedValueForIDL = aExpectedValueForIDL; + } + + if (aNewValue != null) { + aElement.setAttribute(aAttribute, aNewValue); + is(aElement.getAttribute(aAttribute), expectedValueForContent, + aAttribute + " content attribute should be " + expectedValueForContent); + is(aElement[aAttribute], expectedValueForIDL, + aAttribute + " IDL attribute should be " + expectedValueForIDL); + + if (parseFloat(aNewValue) == aNewValue) { + aElement[aAttribute] = aNewValue; + is(aElement.getAttribute(aAttribute), expectedValueForContent, + aAttribute + " content attribute should be " + expectedValueForContent); + is(aElement[aAttribute], parseFloat(expectedValueForIDL), + aAttribute + " IDL attribute should be " + parseFloat(expectedValueForIDL)); + } + } else { + aElement.removeAttribute(aAttribute); + is(aElement.getAttribute(aAttribute), null, + aAttribute + " content attribute should be null"); + is(aElement[aAttribute], expectedValueForIDL, + aAttribute + " IDL attribute should be " + expectedValueForIDL); + } +} + +function checkValueAttribute() +{ + var tests = [ + // value has to be a valid float, its default value is 0.0 otherwise. + [ null, 0.0 ], + [ 'fo', 0.0 ], + // If value < 0.0, 0.0 is used instead. + [ -1.0, 0.0 ], + // If value >= max, max is used instead (max default value is 1.0). + [ 2.0, 1.0 ], + [ 1.0, 0.5, 0.5 ], + [ 10.0, 5.0, 5.0 ], + [ 13.37, 13.37, 42.0 ], + // Regular reflection. + [ 0.0 ], + [ 0.5 ], + [ 1.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('progress'); + + for (var test of tests) { + if (test[2]) { + element.setAttribute('max', test[2]); + } + + checkAttribute(element, 'value', test[0], test[1]); + + element.removeAttribute('max'); + } +} + +function checkMaxAttribute() +{ + var tests = [ + // max default value is 1.0. + [ null, 1.0 ], + // If value <= 0.0, 1.0 is used instead. + [ 0.0, 1.0 ], + [ -1.0, 1.0 ], + // Regular reflection. + [ 0.5 ], + [ 1.0 ], + [ 2.0 ], + // Check double-precision value. + [ 0.234567898765432 ], + ]; + + var element = document.createElement('progress'); + + for (var test of tests) { + checkAttribute(element, 'max', test[0], test[1]); + } +} + +function checkPositionAttribute() +{ + function checkPositionValue(aElement, aValue, aMax, aExpected) { + if (aValue != null) { + aElement.setAttribute('value', aValue); + } else { + aElement.removeAttribute('value'); + } + + if (aMax != null) { + aElement.setAttribute('max', aMax); + } else { + aElement.removeAttribute('max'); + } + + is(aElement.position, aExpected, "position IDL attribute should be " + aExpected); + } + + var tests = [ + // value has to be defined (indeterminate state). + [ null, null, -1.0 ], + [ null, 1.0, -1.0 ], + // value has to be defined to a valid float (indeterminate state). + [ 'foo', 1.0, -1.0 ], + // If value < 0.0, 0.0 is used instead. + [ -1.0, 1.0, 0.0 ], + // If value >= max, max is used instead. + [ 2.0, 1.0, 1.0 ], + // If max isn't present, max is set to 1.0. + [ 1.0, null, 1.0 ], + // If max isn't a valid float, max is set to 1.0. + [ 1.0, 'foo', 1.0 ], + // If max isn't > 0, max is set to 1.0. + [ 1.0, -1.0, 1.0 ], + // A few simple and valid values. + [ 0.0, 1.0, 0.0 ], + [ 0.1, 1.0, 0.1/1.0 ], + [ 0.1, 2.0, 0.1/2.0 ], + [ 10, 50, 10/50 ], + // Values implying .position is a double. + [ 1.0, 3.0, 1.0/3.0 ], + [ 0.1, 0.7, 0.1/0.7 ], + ]; + + var element = document.createElement('progress'); + + for (var test of tests) { + checkPositionValue(element, test[0], test[1], test[2], test[3]); + } +} + +function checkIndeterminatePseudoClass() +{ + function checkIndeterminate(aElement, aValue, aMax, aIndeterminate) { + if (aValue != null) { + aElement.setAttribute('value', aValue); + } else { + aElement.removeAttribute('value'); + } + + if (aMax != null) { + aElement.setAttribute('max', aMax); + } else { + aElement.removeAttribute('max'); + } + + is(aElement.matches("progress:indeterminate"), aIndeterminate, + "<progress> indeterminate state should be " + aIndeterminate); + } + + var tests = [ + // Indeterminate state: (value is undefined, or not a float) + // value has to be defined (indeterminate state). + [ null, null, true ], + [ null, 1.0, true ], + [ 'foo', 1.0, true ], + // Determined state: + [ -1.0, 1.0, false ], + [ 2.0, 1.0, false ], + [ 1.0, null, false ], + [ 1.0, 'foo', false ], + [ 1.0, -1.0, false ], + [ 0.0, 1.0, false ], + ]; + + var element = document.createElement('progress'); + + for (var test of tests) { + checkIndeterminate(element, test[0], test[1], test[2]); + } +} + +function checkFormListedElement(aElement) +{ + is(document.forms[0].elements.length, 0, "the form should have no element"); +} + +function checkLabelable(aElement) +{ + var content = document.getElementById('content'); + var label = document.createElement('label'); + + content.appendChild(label); + label.appendChild(aElement); + is(label.control, aElement, "progress should be labelable"); + + // Cleaning-up. + content.removeChild(label); + content.appendChild(aElement); +} + +function checkNotResetableAndFormSubmission(aElement) +{ + // Creating an input element to check the submission worked. + var form = document.forms[0]; + var input = document.createElement('input'); + + input.name = 'a'; + input.value = 'tulip'; + form.appendChild(input); + + // Setting values. + aElement.value = 42.0; + aElement.max = 100.0; + + document.getElementsByName('submit_frame')[0].addEventListener("load", function() { + document.getElementsByName('submit_frame')[0].removeEventListener("load", arguments.callee, false); + + /** + * All elements values have been set just before the submission. + * The input element value should be in the submit url but the progress + * element value should not appear. + */ + is(frames['submit_frame'].location.href, + 'http://mochi.test:8888/tests/dom/html/test/forms/foo?a=tulip', + "The progress element value should not be submitted"); + + checkNotResetable(); + }, false); + + form.submit(); +} + +function checkNotResetable() +{ + // Try to reset the form. + var form = document.forms[0]; + var element = document.getElementById('p'); + + element.value = 3.0; + element.max = 42.0; + + form.reset(); + + SimpleTest.executeSoon(function() { + is(element.value, 3.0, "progress.value should not have changed"); + is(element.max, 42.0, "progress.max should not have changed"); + + SimpleTest.finish(); + }); +} + +SimpleTest.waitForExplicitFinish(); + +var p = document.getElementById('p'); + +ok(p instanceof HTMLProgressElement, + "The progress element should be instance of HTMLProgressElement"); +is(p.constructor, HTMLProgressElement, + "The progress element constructor should be HTMLProgressElement"); + +checkFormIDLAttribute(p); + +checkValueAttribute(); + +checkMaxAttribute(); + +checkPositionAttribute(); + +checkIndeterminatePseudoClass(); + +checkFormListedElement(p); + +checkLabelable(p); + +checkNotResetableAndFormSubmission(p); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_radio_in_label.html b/dom/html/test/forms/test_radio_in_label.html new file mode 100644 index 000000000..1676c9819 --- /dev/null +++ b/dom/html/test/forms/test_radio_in_label.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=229925 +--> +<head> + <title>Test for Bug 229925</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=229925">Mozilla Bug 229925</a> +<p id="display"></p> +<form> + <label> + <span id="s1">LABEL</span> + <input type="radio" name="rdo" value="1" id="r1" onmousedown="document.body.appendChild(document.createTextNode('down'));"> + <input type="radio" name="rdo" value="2" id="r2" checked="checked"> + </label> +</form> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 229925 **/ +SimpleTest.waitForExplicitFinish(); +var r1 = document.getElementById("r1"); +var r2 = document.getElementById("r2"); +var s1 = document.getElementById("s1"); +SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, startTest); +function startTest() { + r1.click(); + ok(r1.checked, + "The first radio input element should be checked by clicking the element"); + r2.click(); + ok(r2.checked, + "The second radio input element should be checked by clicking the element"); + s1.click(); + ok(r1.checked, + "The first radio input element should be checked by clicking other element"); + + r1.focus(); + synthesizeKey("VK_LEFT", {}); + ok(r2.checked, + "The second radio input element should be checked by key"); + synthesizeKey("VK_LEFT", {}); + ok(r1.checked, + "The first radio input element should be checked by key"); + SimpleTest.finish(); +} +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_radio_radionodelist.html b/dom/html/test/forms/test_radio_radionodelist.html new file mode 100644 index 000000000..7f915bba9 --- /dev/null +++ b/dom/html/test/forms/test_radio_radionodelist.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=779723 +--> +<head> + <title>Test for Bug 779723</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=779723">Mozilla Bug 779723</a> +<p id="display"></p> +<form> + <input type="checkbox" name="rdo" value="0" id="r0" checked="checked"> + <input type="radio" name="rdo" id="r1"> + <input type="radio" name="rdo" id="r2" value="2"> +</form> +<script class="testbody" type="text/javascript"> +/** Test for Bug 779723 **/ + +var rdoList = document.forms[0].elements.namedItem('rdo'); +is(rdoList.value, "", "The value attribute should be empty"); + +document.getElementById('r2').checked = true; +ok(rdoList.value, "2", "The value attribute should be 2"); + +document.getElementById('r1').checked = true; +ok(rdoList.value, "on", "The value attribute should be on"); + +document.getElementById('r1').value = 1; +ok(rdoList.value, "1", "The value attribute should be 1"); + +is(rdoList.value, document.getElementById('r1').value, + "The value attribute should be equal to the first checked radio input element's value"); +ok(!document.getElementById('r2').checked, + "The second radio input element should not be checked"); + +rdoList.value = '2'; +is(rdoList.value, document.getElementById('r2').value, + "The value attribute should be equal to the second radio input element's value"); +ok(document.getElementById('r2').checked, + "The second radio input element should be checked"); + +rdoList.value = '3'; +is(rdoList.value, document.getElementById('r2').value, + "The value attribute should be the second radio input element's value"); +ok(document.getElementById('r2').checked, + "The second radio input element should be checked"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/forms/test_reportValidation_preventDefault.html b/dom/html/test/forms/test_reportValidation_preventDefault.html new file mode 100644 index 000000000..034bb2ed2 --- /dev/null +++ b/dom/html/test/forms/test_reportValidation_preventDefault.html @@ -0,0 +1,93 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1088761 +--> +<head> + <title>Test for Bug 1088761</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input, textarea, fieldset, button, select, keygen, output, object { background-color: rgb(0,0,0) !important; } + :valid { background-color: rgb(0,255,0) !important; } + :invalid { background-color: rgb(255,0,0) !important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1088761">Mozilla Bug 1088761</a> +<p id="display"></p> +<div id="content" style="display: none"> + <fieldset id='f' oninvalid="invalidEventHandler(event, true);"></fieldset> + <input id='i' required oninvalid="invalidEventHandler(event, true);"> + <button id='b' oninvalid="invalidEventHandler(event, true);"></button> + <select id='s' required oninvalid="invalidEventHandler(event, true);"></select> + <textarea id='t' required oninvalid="invalidEventHandler(event, true);"></textarea> + <output id='o' oninvalid="invalidEventHandler(event, true);"></output> + <keygen id='k' oninvalid="invalidEventHandler(event, true);"></keygen> + <object id='obj' oninvalid="invalidEventHandler(event, true);"></object> +</div> +<div id="content2" style="display: none"> + <fieldset id='f2' oninvalid="invalidEventHandler(event, false);"></fieldset> + <input id='i2' required oninvalid="invalidEventHandler(event, false);"> + <button id='b2' oninvalid="invalidEventHandler(event, false);"></button> + <select id='s2' required oninvalid="invalidEventHandler(event, false);"></select> + <textarea id='t2' required oninvalid="invalidEventHandler(event, false);"></textarea> + <output id='o2' oninvalid="invalidEventHandler(event, false);"></output> + <keygen id='k2' oninvalid="invalidEventHandler(event, false);"></keygen> + <object id='obj2' oninvalid="invalidEventHandler(event, false);"></object> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1088761 **/ + +var gInvalid = false; + +function invalidEventHandler(aEvent, isPreventDefault) +{ + if (isPreventDefault) { + aEvent.preventDefault(); + } + + is(aEvent.type, "invalid", "Invalid event type should be invalid"); + ok(!aEvent.bubbles, "Invalid event should not bubble"); + ok(aEvent.cancelable, "Invalid event should be cancelable"); + gInvalid = true; +} + +function checkReportValidityForInvalid(element) +{ + gInvalid = false; + ok(!element.reportValidity(), "reportValidity() should return false when the element is not valid"); + ok(gInvalid, "Invalid event should have been handled"); +} + +function checkReportValidityForValid(element) +{ + gInvalid = false; + ok(element.reportValidity(), "reportValidity() should return true when the element is valid"); + ok(!gInvalid, "Invalid event shouldn't have been handled"); +} + +checkReportValidityForInvalid(document.getElementById('i')); +checkReportValidityForInvalid(document.getElementById('s')); +checkReportValidityForInvalid(document.getElementById('t')); + +checkReportValidityForInvalid(document.getElementById('i2')); +checkReportValidityForInvalid(document.getElementById('s2')); +checkReportValidityForInvalid(document.getElementById('t2')); + +checkReportValidityForValid(document.getElementById('o')); +checkReportValidityForValid(document.getElementById('k')); +checkReportValidityForValid(document.getElementById('obj')); +checkReportValidityForValid(document.getElementById('f')); + +checkReportValidityForValid(document.getElementById('o2')); +checkReportValidityForValid(document.getElementById('k2')); +checkReportValidityForValid(document.getElementById('obj2')); +checkReportValidityForValid(document.getElementById('f2')); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_required_attribute.html b/dom/html/test/forms/test_required_attribute.html new file mode 100644 index 000000000..1f9d76cf1 --- /dev/null +++ b/dom/html/test/forms/test_required_attribute.html @@ -0,0 +1,382 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=345822 +--> +<head> + <title>Test for Bug 345822</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345822">Mozilla Bug 345822</a> +<p id="display"></p> +<div id="content"> + <form> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 345822 **/ + +function checkNotSufferingFromBeingMissing(element, doNotApply) +{ + ok(!element.validity.valueMissing, + "Element should not suffer from value missing"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "Element should be valid"); + is(element.validationMessage, "", + "Validation message should be the empty string"); + + if (doNotApply) { + ok(!element.matches(':valid'), ":valid should not apply"); + ok(!element.matches(':invalid'), ":invalid should not apply"); + ok(!element.matches(':-moz-ui-valid'), ":-moz-ui-valid should not apply"); + ok(!element.matches(':-moz-ui-invalid'), ":-moz-ui-invalid should not apply"); + } else { + ok(element.matches(':valid'), ":valid should apply"); + ok(!element.matches(':invalid'), ":invalid should not apply"); + ok(element.matches(':-moz-ui-valid'), ":-moz-ui-valid should apply"); + ok(!element.matches(':-moz-ui-invalid'), ":-moz-ui-invalid should not apply"); + } +} + +function checkSufferingFromBeingMissing(element, hasMozUIInvalid) +{ + ok(element.validity.valueMissing, "Element should suffer from value missing"); + ok(!element.validity.valid, "Element should not be valid"); + ok(!element.checkValidity(), "Element should not be valid"); + + if (element.type == 'checkbox') + { + is(element.validationMessage, + "Please check this box if you want to proceed.", + "Validation message is wrong"); + } + else if (element.type == 'radio') + { + is(element.validationMessage, + "Please select one of these options.", + "Validation message is wrong"); + } + else if (element.type == 'file') + { + is(element.validationMessage, + "Please select a file.", + "Validation message is wrong"); + } + else if (element.type == 'number') + { + is(element.validationMessage, + "Please enter a number.", + "Validation message is wrong"); + } + else // text fields + { + is(element.validationMessage, + "Please fill out this field.", + "Validation message is wrong"); + } + + ok(!element.matches(':valid'), ":valid should apply"); + ok(element.matches(':invalid'), ":invalid should not apply"); + ok(!element.matches(':-moz-ui-valid'), ":-moz-ui-valid should not apply"); + is(element.matches(':-moz-ui-invalid'), hasMozUIInvalid, ":-moz-ui-invalid expected state is " + hasMozUIInvalid); +} + +function checkTextareaRequiredValidity() +{ + var element = document.createElement('textarea'); + document.forms[0].appendChild(element); + + SpecialPowers.wrap(element).value = ''; + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.required = true; + checkSufferingFromBeingMissing(element, true); + + element.readOnly = true; + checkNotSufferingFromBeingMissing(element, true); + + element.readOnly = false; + checkSufferingFromBeingMissing(element, true); + + SpecialPowers.wrap(element).value = 'foo'; + checkNotSufferingFromBeingMissing(element); + + SpecialPowers.wrap(element).value = ''; + checkSufferingFromBeingMissing(element, true); + + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.focus(); + element.required = true; + SpecialPowers.wrap(element).value = 'foobar'; + element.blur(); + element.form.reset(); + checkSufferingFromBeingMissing(element, false); + + // TODO: for the moment, a textarea outside of a document is mutable. + SpecialPowers.wrap(element).value = ''; // To make -moz-ui-valid apply. + element.required = false; + document.forms[0].removeChild(element); + checkNotSufferingFromBeingMissing(element); +} + +function checkInputRequiredNotApply(type, isBarred) +{ + var element = document.createElement('input'); + element.type = type; + document.forms[0].appendChild(element); + + SpecialPowers.wrap(element).value = ''; + element.required = false; + checkNotSufferingFromBeingMissing(element, isBarred); + + element.required = true; + checkNotSufferingFromBeingMissing(element, isBarred); + + element.required = false; + + document.forms[0].removeChild(element); + checkNotSufferingFromBeingMissing(element, isBarred); +} + +function checkInputRequiredValidity(type) +{ + var element = document.createElement('input'); + element.type = type; + document.forms[0].appendChild(element); + + SpecialPowers.wrap(element).value = ''; + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.required = true; + checkSufferingFromBeingMissing(element, true); + + element.readOnly = true; + checkNotSufferingFromBeingMissing(element, true); + + element.readOnly = false; + checkSufferingFromBeingMissing(element, true); + + if (element.type == 'email') { + SpecialPowers.wrap(element).value = 'foo@bar.com'; + } else if (element.type == 'url') { + SpecialPowers.wrap(element).value = 'http://mozilla.org/'; + } else if (element.type == 'number') { + SpecialPowers.wrap(element).value = '42'; + } else if (element.type == 'date') { + SpecialPowers.wrap(element).value = '2010-10-10'; + } else if (element.type == 'time') { + SpecialPowers.wrap(element).value = '21:21'; + } else if (element.type = 'month') { + SpecialPowers.wrap(element).value = '2010-10'; + } else { + SpecialPowers.wrap(element).value = 'foo'; + } + checkNotSufferingFromBeingMissing(element); + + SpecialPowers.wrap(element).value = ''; + checkSufferingFromBeingMissing(element, true); + + element.focus(); + element.required = true; + SpecialPowers.wrap(element).value = 'foobar'; + element.blur(); + element.form.reset(); + checkSufferingFromBeingMissing(element, false); + + element.required = true; + SpecialPowers.wrap(element).value = ''; // To make :-moz-ui-valid apply. + checkSufferingFromBeingMissing(element, true); + document.forms[0].removeChild(element); + // Removing the child changes nothing about whether it's valid + checkSufferingFromBeingMissing(element, true); +} + +function checkInputRequiredValidityForCheckbox() +{ + var element = document.createElement('input'); + element.type = 'checkbox'; + document.forms[0].appendChild(element); + + element.checked = false; + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.required = true; + checkSufferingFromBeingMissing(element, true); + + element.checked = true; + checkNotSufferingFromBeingMissing(element); + + element.checked = false; + checkSufferingFromBeingMissing(element, true); + + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.focus(); + element.required = true; + element.checked = true; + element.blur(); + element.form.reset(); + checkSufferingFromBeingMissing(element, false); + + element.required = true; + element.checked = false; + document.forms[0].removeChild(element); + checkSufferingFromBeingMissing(element, true); +} + +function checkInputRequiredValidityForRadio() +{ + var element = document.createElement('input'); + element.type = 'radio'; + element.name = 'test' + document.forms[0].appendChild(element); + + element.checked = false; + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.required = true; + checkSufferingFromBeingMissing(element, true); + + element.checked = true; + checkNotSufferingFromBeingMissing(element); + + element.checked = false; + checkSufferingFromBeingMissing(element, true); + + // A required radio button should not suffer from value missing if another + // radio button from the same group is checked. + var element2 = document.createElement('input'); + element2.type = 'radio'; + element2.name = 'test'; + + element2.checked = true; + element2.required = false; + document.forms[0].appendChild(element2); + + // Adding a checked radio should make required radio in the group not + // suffering from being missing. + checkNotSufferingFromBeingMissing(element); + + element.checked = false; + element2.checked = false; + checkSufferingFromBeingMissing(element, true); + + // The other radio button should not be disabled. + // A disabled checked radio button in the radio group + // is enough to not suffer from value missing. + element2.checked = true; + element2.disabled = true; + checkNotSufferingFromBeingMissing(element); + + // If a radio button is not required but another radio button is required in + // the same group, the not required radio button should suffer from value + // missing. + element2.disabled = false; + element2.checked = false; + element.required = false; + element2.required = true; + checkSufferingFromBeingMissing(element, true); + checkSufferingFromBeingMissing(element2, true); + + element.checked = true; + checkNotSufferingFromBeingMissing(element2); + + // The checked radio is not in the group anymore, element2 should be invalid. + element.form.removeChild(element); + checkNotSufferingFromBeingMissing(element); + checkSufferingFromBeingMissing(element2, true); + + element2.focus(); + element2.required = true; + element2.checked = true; + element2.blur(); + element2.form.reset(); + checkSufferingFromBeingMissing(element2, false); + + element2.required = true; + element2.checked = false; + document.forms[0].removeChild(element2); + checkSufferingFromBeingMissing(element2, true); +} + +function checkInputRequiredValidityForFile() +{ + var element = document.createElement('input'); + element.type = 'file' + document.forms[0].appendChild(element); + + var file = new File([""], "345822_file"); + + SpecialPowers.wrap(element).value = ""; + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.required = true; + checkSufferingFromBeingMissing(element, true); + + SpecialPowers.wrap(element).mozSetFileArray([file]); + checkNotSufferingFromBeingMissing(element); + + SpecialPowers.wrap(element).value = ""; + checkSufferingFromBeingMissing(element, true); + + element.required = false; + checkNotSufferingFromBeingMissing(element); + + element.focus(); + SpecialPowers.wrap(element).mozSetFileArray([file]); + element.required = true; + element.blur(); + element.form.reset(); + checkSufferingFromBeingMissing(element, false); + + element.required = true; + SpecialPowers.wrap(element).value = ''; + document.forms[0].removeChild(element); + checkSufferingFromBeingMissing(element, true); +} + +checkTextareaRequiredValidity(); + +// The require attribute behavior depend of the input type. +// First of all, checks for types that make the element barred from +// constraint validation. +var typeBarredFromConstraintValidation = ["hidden", "button", "reset"]; +for (type of typeBarredFromConstraintValidation) { + checkInputRequiredNotApply(type, true); +} + +// Then, checks for the types which do not use the required attribute. +var typeRequireNotApply = ['range', 'color', 'submit', 'image']; +for (type of typeRequireNotApply) { + checkInputRequiredNotApply(type, false); +} + +// Now, checking for all types which accept the required attribute. +var typeRequireApply = ["text", "password", "search", "tel", "email", "url", + "number", "date", "time", "month", "week", + "datetime-local"]; + +for (type of typeRequireApply) { + checkInputRequiredValidity(type); +} + +checkInputRequiredValidityForCheckbox(); +checkInputRequiredValidityForRadio(); +checkInputRequiredValidityForFile(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_restore_form_elements.html b/dom/html/test/forms/test_restore_form_elements.html new file mode 100644 index 000000000..d92c5c7e9 --- /dev/null +++ b/dom/html/test/forms/test_restore_form_elements.html @@ -0,0 +1,174 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=737851 +--> +<head> + <meta charset="utf-8"> + + <title>Test for Bug 737851</title> + + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<body> + +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=737851">Mozilla Bug 737851</a> + +<p id="display"></p> + + +<div id="content"> + + <iframe id="frame" width="800px" height="600px" src='data:text/html, + <html> + <body style="display:none;"> + + <h3>Checking persistence of inputs through js inserts and moves</h3> + <div id="test"> + <input id="a"/> + <input id="b"/> + <form id="form1"> + <input id="c"/> + <input id="d"/> + </form> + <form id="form2"> + <input id="radio1" type="radio" name="radio"/> + <input type="radio" name="radio"/> + <input type="radio" name="radio"/> + <input type="radio" name="radio"/> + </form> + <input id="e"/> + </div> + + <h3>Bug 728798: checking persistence of inputs when forward-using @form</h3> + <div> + <input id="728798-a" form="728798-form" name="a"/> + <form id="728798-form"> + <input id="728798-b" form="728798-form" name="b"/> + <input id="728798-c" name="c"/> + </form> + <input id="728798-d" form="728798-form" name="d"/> + </div> + + </body> + </html> + '></iframe> + +</div> + + +<pre id="test"> +<script type="text/javascript"> + +var frameElem = document.getElementById("frame"); +var frame = frameElem.contentWindow; + + +/* -- Main test run -- */ + +SimpleTest.waitForExplicitFinish(); + +addLoadEvent(function() { + shuffle(); + fill(); + frameElem.addEventListener("load", function() { + shuffle(); + checkAllFields(); + SimpleTest.finish(); + }); + frame.location.reload(); +}) + + +/* -- Input fields js changes and moves -- */ + +function shuffle() { + var framedoc = frame.document; + + // Insert a button (toplevel) + var btn = framedoc.createElement("button"); + var testdiv = framedoc.getElementById("test"); + testdiv.insertBefore(btn, framedoc.getElementById("b")); + + // Insert a dynamically generated input (in a form) + var newInput = framedoc.createElement("input"); + newInput.setAttribute("id","c0"); + var form1 = framedoc.getElementById("form1"); + form1.insertBefore(newInput, form1.firstChild); + + // Move an input around + var inputD = framedoc.getElementById("d"); + var form2 = framedoc.getElementById("form2"); + form2.insertBefore(inputD, form2.firstChild) + + // Clone an existing input + var inputE2 = framedoc.getElementById("e").cloneNode(true); + inputE2.setAttribute("id","e2"); + testdiv.appendChild(inputE2); +} + + +/* -- Input fields fill & check -- */ + +/* Values entered in the input fields (by id) */ + +var fieldValues = { + 'a':'simple input', + 'b':'moved by inserting a button before (no form)', + 'c0':'dynamically generated input', + 'c':'moved by inserting an input before (in a form)', + 'd':'moved from a form to another', + 'e':'the original', + 'e2':'the clone', + '728798-a':'before the form', + '728798-b':'from within the form', + '728798-c':'no form attribute in the form', + '728798-d':'after the form' +} + +/* Fields for which the input is changed, and corresponding value + (clone and creation, same behaviour as webkit) */ + +var changedFields = { + // dynamically generated input field not preserved + 'c0':'', + // cloned input field is restored with the value of the original + 'e2':fieldValues.e +} + +/* Simulate user input by entering the values */ + +function fill() { + for (id in fieldValues) { + frame.document.getElementById(id).value = fieldValues[id]; + } + // an input is inserted before the radios (that may move the selected one by 1) + frame.document.getElementById('radio1').checked = true; +} + +/* Check that all the fields are as they have been entered */ + +function checkAllFields() { + + for (id in fieldValues) { + var fieldValue = frame.document.getElementById(id).value; + if (changedFields[id] === undefined) { + is(fieldValue, fieldValues[id], + "Field "+id+" should be restored after reload"); + } else { + is(fieldValue, changedFields[id], + "Field "+id+" normally gets a different value after reload"); + } + } + + ok(frame.document.getElementById('radio1').checked, + "Radio button radio1 should be restored after reload") + +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_save_restore_radio_groups.html b/dom/html/test/forms/test_save_restore_radio_groups.html new file mode 100644 index 000000000..837d5d681 --- /dev/null +++ b/dom/html/test/forms/test_save_restore_radio_groups.html @@ -0,0 +1,73 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=350022 +--> +<head> + <title>Test for Bug 350022</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=350022">Mozilla Bug 350022</a> +<p id="display"></p> +<div id="content"><!-- style="display: none">--> + <iframe src="save_restore_radio_groups.sjs"></iframe> + <iframe src="save_restore_radio_groups.sjs"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 350022 **/ + +function checkRadioGroup(aFrame, aResults) +{ + var radios = frames[aFrame].document.getElementsByTagName('input'); + + is(radios.length, aResults.length, + "Radio group should have " + aResults.length + "elements"); + + for (var i=0; i<aResults.length; ++i) { + is(radios[i].checked, aResults[i], + "Radio checked state should be " + aResults[i]); + } +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + /** + * We have two iframes each containing one radio button group. + * We are going to change the selected radio button in one group. + * Then, both iframes will be reloaded and the new groups will have another + * radio checked by default. + * For the first group (which had a selection change), nothing should change. + * For the second, the selected radio button should change. + */ + checkRadioGroup(0, [true, false, false]); + checkRadioGroup(1, [true, false, false]); + + frames[0].document.getElementsByTagName('input')[2].checked = true; + checkRadioGroup(0, [false, false, true]); + + framesElts = document.getElementsByTagName('iframe'); + framesElts[0].addEventListener("load", function() { + framesElts[0].removeEventListener("load", arguments.callee, false); + checkRadioGroup(0, [false, false, true]); + + framesElts[1].addEventListener("load", function() { + framesElts[1].removeEventListener("load", arguments.callee, false); + + checkRadioGroup(1, [false, true, false]); + SimpleTest.finish(); + }, false); + + frames[1].location.reload(); + }, false); + + frames[0].location.reload(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_select_change_event.html b/dom/html/test/forms/test_select_change_event.html new file mode 100644 index 000000000..80d3cd09d --- /dev/null +++ b/dom/html/test/forms/test_select_change_event.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1265968 +--> +<head> + <title>Test for Bug 1265968</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265968">Mozilla Bug 1265968</a> +<p id="display"></p> +<div id="content"> + <select id="select" onchange="++selectChange;"> + <option>one</option> + <option>two</option> + <option>three</option> + <option>four</option> + <option>five</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + var select = document.getElementById("select"); + var selectChange = 0; + var expectedChange = 0; + + select.focus(); + for (var i = 1; i < select.length; i++) { + synthesizeKey("VK_DOWN", {}); + is(select.options[i].selected, true, "Option should be selected"); + is(selectChange, ++expectedChange, "Down key should fire change event."); + } + + // We are at the end of the list, going down should not fire change event. + synthesizeKey("VK_DOWN", {}); + is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list."); + + for (var i = select.length - 2; i >= 0; i--) { + synthesizeKey("VK_UP", {}); + is(select.options[i].selected, true, "Option should be selected"); + is(selectChange, ++expectedChange, "Up key should fire change event."); + } + + // We are at the top of the list, going up should not fire change event. + synthesizeKey("VK_UP", {}); + is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list."); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_select_input_change_event.html b/dom/html/test/forms/test_select_input_change_event.html new file mode 100644 index 000000000..fa1b24b41 --- /dev/null +++ b/dom/html/test/forms/test_select_input_change_event.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1265968 +--> +<head> + <title>Test for Bug 1024350</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1024350">Mozilla Bug 1024350</a> +<p id="display"></p> +<div id="content"> + <select oninput='++selectInput;' onchange="++selectChange;"> + <option>one</option> + </select> + <select oninput='++selectInput;' onchange="++selectChange;"> + <option>one</option> + <option>two</option> + </select> + <select multiple size='1' oninput='++selectInput;' onchange="++selectChange;"> + <option>one</option> + </select> + <select multiple oninput='++selectInput;' onchange="++selectChange;"> + <option>one</option> + <option>two</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + var selectSingleOneItem = document.getElementsByTagName('select')[0]; + var selectSingle = document.getElementsByTagName('select')[1]; + var selectMultipleOneItem = document.getElementsByTagName('select')[2]; + var selectMultiple = document.getElementsByTagName('select')[3]; + + var selectChange = 0; + var selectInput = 0; + var expectedChange = 0; + var expectedInput = 0; + + selectSingleOneItem.focus(); + synthesizeKey("VK_DOWN", {}); + is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list."); + is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list."); + + synthesizeKey("VK_UP", {}); + is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list."); + is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list."); + + selectSingle.focus(); + for (var i = 1; i < selectSingle.length; i++) { + synthesizeKey("VK_DOWN", {}); + + is(selectSingle.options[i].selected, true, "Option should be selected"); + is(selectInput, ++expectedInput, "Down key should fire input event."); + is(selectChange, ++expectedChange, "Down key should fire change event."); + } + + // We are at the end of the list, going down should not fire change event. + synthesizeKey("VK_DOWN", {}); + is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list."); + is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list."); + + for (var i = selectSingle.length - 2; i >= 0; i--) { + synthesizeKey("VK_UP", {}); + + is(selectSingle.options[i].selected, true, "Option should be selected"); + is(selectInput, ++expectedInput, "Up key should fire input event."); + is(selectChange, ++expectedChange, "Up key should fire change event."); + } + + // We are at the top of the list, going up should not fire change event. + synthesizeKey("VK_UP", {}); + is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list."); + is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list."); + + selectMultipleOneItem.focus(); + synthesizeKey("VK_DOWN", {}); + is(selectInput, ++expectedInput, "Down key should fire input event when reaching end of the list."); + is(selectChange, ++expectedChange, "Down key should fire change event when reaching end of the list."); + + synthesizeKey("VK_DOWN", {}); + is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list."); + is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list."); + + synthesizeKey("VK_UP", {}); + is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list."); + is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list."); + + selectMultiple.focus(); + for (var i = 0; i < selectMultiple.length; i++) { + synthesizeKey("VK_DOWN", {}); + + is(selectMultiple.options[i].selected, true, "Option should be selected"); + is(selectInput, ++expectedInput, "Down key should fire input event."); + is(selectChange, ++expectedChange, "Down key should fire change event."); + } + + // We are at the end of the list, going down should not fire change event. + synthesizeKey("VK_DOWN", {}); + is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list."); + is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list."); + + for (var i = selectMultiple.length - 2; i >= 0; i--) { + synthesizeKey("VK_UP", {}); + + is(selectMultiple.options[i].selected, true, "Option should be selected"); + is(selectInput, ++expectedInput, "Up key should fire input event."); + is(selectChange, ++expectedChange, "Up key should fire change event."); + } + + // We are at the top of the list, going up should not fire change event. + synthesizeKey("VK_UP", {}); + is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list."); + is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list."); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_select_selectedOptions.html b/dom/html/test/forms/test_select_selectedOptions.html new file mode 100644 index 000000000..e93222459 --- /dev/null +++ b/dom/html/test/forms/test_select_selectedOptions.html @@ -0,0 +1,120 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=596681 +--> +<head> + <title>Test for HTMLSelectElement.selectedOptions</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596681">Mozilla Bug 596681</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript;version=1.7"> + +/** Test for HTMLSelectElement's selectedOptions attribute. + * + * selectedOptions is a live list of the options that have selectedness of true + * (not the selected content attribute). + * + * See http://www.whatwg.org/html/#dom-select-selectedoptions + **/ + +function checkSelectedOptions(size, elements) +{ + is(selectedOptions.length, size, + "select should have " + size + " selected options"); + for (let i = 0; i < size; ++i) { + ok(selectedOptions[i], "selected option is valid"); + if (selectedOptions[i]) { + is(selectedOptions[i].value, elements[i].value, "selected options are correct"); + } + } +} + +let select = document.createElement("select"); +document.body.appendChild(select); +let selectedOptions = select.selectedOptions; + +ok("selectedOptions" in select, + "select element should have a selectedOptions IDL attribute"); + +ok(select.selectedOptions instanceof HTMLCollection, + "selectedOptions should be an HTMLCollection instance"); + +let option1 = document.createElement("option"); +let option2 = document.createElement("option"); +let option3 = document.createElement("option"); +option1.id = "option1"; +option1.value = "option1"; +option2.value = "option2"; +option3.value = "option3"; + +checkSelectedOptions(0, null); + +select.add(option1, null); +is(selectedOptions.namedItem("option1").value, "option1", "named getter works"); +checkSelectedOptions(1, [option1]); + +select.add(option2, null); +checkSelectedOptions(1, [option1]); + +select.options[1].selected = true; +checkSelectedOptions(1, [option2]); + +select.multiple = true; +checkSelectedOptions(1, [option2]); + +select.options[0].selected = true; +checkSelectedOptions(2, [option1, option2]); + +option1.selected = false; +// Usinig selected directly on the option should work. +checkSelectedOptions(1, [option2]); + +select.remove(1); +select.add(option2, 0); +select.options[0].selected = true; +select.options[1].selected = true; +// Should be in tree order. +checkSelectedOptions(2, [option2, option1]); + +select.add(option3, null); +checkSelectedOptions(2, [option2, option1]); + +select.options[2].selected = true; +checkSelectedOptions(3, [option2, option1, option3]); + +select.length = 0; +option1.selected = false; +option2.selected = false; +option3.selected = false; +var optgroup1 = document.createElement("optgroup"); +optgroup1.appendChild(option1); +optgroup1.appendChild(option2); +select.add(optgroup1) +var optgroup2 = document.createElement("optgroup"); +optgroup2.appendChild(option3); +select.add(optgroup2); + +checkSelectedOptions(0, null); + +option2.selected = true; +checkSelectedOptions(1, [option2]); + +option3.selected = true; +checkSelectedOptions(2, [option2, option3]); + +optgroup1.removeChild(option2); +checkSelectedOptions(1, [option3]); + +document.body.removeChild(select); +option1.selected = true; +checkSelectedOptions(2, [option1, option3]); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_select_validation.html b/dom/html/test/forms/test_select_validation.html new file mode 100644 index 000000000..1ae134801 --- /dev/null +++ b/dom/html/test/forms/test_select_validation.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=942321 +--> +<head> + <title>Test for Bug 942321</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=942321">Mozilla Bug 942321</a> +<p id="display"></p> +<form id="form" href=""> + <select required id="testselect"> + <option id="placeholder" value="" selected>placeholder</option> + <option value="test" id="actualvalue">test</option> + <select> + <input type="submit" /> +</form> +<script class="testbody" type="text/javascript"> +/** Test for Bug 942321 **/ +var option = document.getElementById("actualvalue"); +option.selected = true; +is(form.checkValidity(), true, "Select is required and should be valid"); + +var placeholder = document.getElementById("placeholder"); +placeholder.selected = true; +is(form.checkValidity(), false, "Select is required and should be invalid"); + +placeholder.value = "not-invalid-anymore"; +is(form.checkValidity(), true, "Select is required and should be valid when option's value is changed by javascript"); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/forms/test_set_range_text.html b/dom/html/test/forms/test_set_range_text.html new file mode 100644 index 000000000..160c8e58e --- /dev/null +++ b/dom/html/test/forms/test_set_range_text.html @@ -0,0 +1,244 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=850364 +--> +<head> +<title>Tests for Bug 850364 && Bug 918940</title> +<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=850364">Mozilla Bug 850364</a> +<p id="display"></p> +<div id="content"> + +<!-- "SetRangeText() supported types"--> +<input type="text" id="input_text"></input> +<input type="search" id="input_search"></input> +<input type="url" id="input_url"></input> +<input type="tel" id="input_tel"></input> +<input type="password" id="input_password"></input> +<textarea id="input_textarea"></textarea> + +<!-- "SetRangeText() non-supported types" --> +<input type="button" id="input_button"></input> +<input type="submit" id="input_submit"></input> +<input type="image" id="input_image"></input> +<input type="reset" id="input_reset"></input> +<input type="radio" id="input_radio"></input> +<input type="checkbox" id="input_checkbox"></input> +<input type="range" id="input_range"></input> +<input type="file" id="input_file"></input> +<input type="email" id="input_email"></input> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + + /** Tests for Bug 850364 && Bug 918940**/ + + var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea"]; + var NonSupportedTypes = ["button", "submit", "image", "reset", "radio", + "checkbox", "range", "file", "email"]; + + SimpleTest.waitForExplicitFinish(); + + function TestInputs() { + + var opThrows, elem, i, msg; + + //Non-supported types should throw + for (i = 0; i < NonSupportedTypes.length; ++i) { + opThrows = false; + msg = "input_" + NonSupportedTypes[i]; + elem = document.getElementById(msg); + elem.focus(); + try { + elem.setRangeText("abc"); + } catch (ex) { + opThrows = true; + } + ok(opThrows, msg + " should throw InvalidStateError"); + } + + var numOfSelectCalls = 0, expectedNumOfSelectCalls = 0; + //Supported types should not throw + for (i = 0; i < SupportedTypes.length; ++i) { + opThrows = false; + msg = "input_" + SupportedTypes[i]; + elem = document.getElementById(msg); + elem.focus(); + try { + elem.setRangeText("abc"); + expectedNumOfSelectCalls += 1; + } catch (ex) { + opThrows = true; + } + is(opThrows, false, msg + " should not throw InvalidStateError"); + + elem.addEventListener("select", function (aEvent) { + ok(true, "select event should be fired for " + aEvent.target.id); + if (++numOfSelectCalls == expectedNumOfSelectCalls) { + SimpleTest.finish(); + } else if (numOfSelectCalls > expectedNumOfSelectCalls) { + ok(false, "Too many select events were fired"); + } + }, false); + + elem.addEventListener("input", function (aEvent) { + ok(false, "input event should NOT be fired for " + + aEvent.target.id); + }, false); + + var test = " setRange(replacement), shrink"; + elem.value = "0123456789ABCDEF"; + elem.setSelectionRange(1, 6); + elem.setRangeText("xyz"); + is(elem.value, "0xyz6789ABCDEF", msg + test); + is(elem.selectionStart, 1, msg + test); + is(elem.selectionEnd, 4, msg + test); + elem.setRangeText("mnk"); + is(elem.value, "0mnk6789ABCDEF", msg + test); + expectedNumOfSelectCalls += 3; + + test = " setRange(replacement), expand"; + elem.value = "0123456789ABCDEF"; + elem.setSelectionRange(1, 2); + elem.setRangeText("xyz"); + is(elem.value, "0xyz23456789ABCDEF", msg + test); + is(elem.selectionStart, 1, msg + test); + is(elem.selectionEnd, 4, msg + test); + elem.setRangeText("mnk"); + is(elem.value, "0mnk23456789ABCDEF", msg + test); + expectedNumOfSelectCalls += 3; + + test = " setRange(replacement) pure insertion at start"; + elem.value = "0123456789ABCDEF"; + elem.setSelectionRange(0, 0); + elem.setRangeText("xyz"); + is(elem.value, "xyz0123456789ABCDEF", msg + test); + is(elem.selectionStart, 0, msg + test); + is(elem.selectionEnd, 0, msg + test); + elem.setRangeText("mnk"); + is(elem.value, "mnkxyz0123456789ABCDEF", msg + test); + expectedNumOfSelectCalls += 3; + + test = " setRange(replacement) pure insertion in the middle"; + elem.value = "0123456789ABCDEF"; + elem.setSelectionRange(4, 4); + elem.setRangeText("xyz"); + is(elem.value, "0123xyz456789ABCDEF", msg + test); + is(elem.selectionStart, 4, msg + test); + is(elem.selectionEnd, 4, msg + test); + elem.setRangeText("mnk"); + is(elem.value, "0123mnkxyz456789ABCDEF", msg + test); + expectedNumOfSelectCalls += 3; + + test = " setRange(replacement) pure insertion at the end"; + elem.value = "0123456789ABCDEF"; + elem.setSelectionRange(16, 16); + elem.setRangeText("xyz"); + is(elem.value, "0123456789ABCDEFxyz", msg + test); + is(elem.selectionStart, 16, msg + test); + is(elem.selectionEnd, 16, msg + test); + elem.setRangeText("mnk"); + is(elem.value, "0123456789ABCDEFmnkxyz", msg + test); + expectedNumOfSelectCalls += 3; + + //test SetRange(replacement, start, end, mode) with start > end + try { + elem.setRangeText("abc", 20, 4); + } catch (ex) { + opThrows = (ex.name == "IndexSizeError" && ex.code == DOMException.INDEX_SIZE_ERR); + } + is(opThrows, true, msg + " should throw IndexSizeError"); + + //test SelectionMode 'select' + elem.value = "0123456789ABCDEF"; + elem.setRangeText("xyz", 4, 9, "select"); + is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"select\""); + is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"select\""); + expectedNumOfSelectCalls += 1; + + elem.setRangeText("pqm", 6, 25, "select"); + is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"select\""); + is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"select\""); + expectedNumOfSelectCalls += 1; + + //test SelectionMode 'start' + elem.value = "0123456789ABCDEF"; + elem.setRangeText("xyz", 4, 9, "start"); + is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"start\""); + is(elem.selectionEnd, 4, msg + ".selectionEnd == 4, with \"start\""); + expectedNumOfSelectCalls += 1; + + elem.setRangeText("pqm", 6, 25, "start"); + is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"start\""); + is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"start\""); + expectedNumOfSelectCalls += 1; + + //test SelectionMode 'end' + elem.value = "0123456789ABCDEF"; + elem.setRangeText("xyz", 4, 9, "end"); + is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + is(elem.selectionStart, 7, msg + ".selectionStart == 7, with \"end\""); + is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"end\""); + expectedNumOfSelectCalls += 1; + + elem.setRangeText("pqm", 6, 25, "end"); + is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + is(elem.selectionStart, 9, msg + ".selectionStart == 9, with \"end\""); + is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"end\""); + expectedNumOfSelectCalls += 1; + + //test SelectionMode 'preserve' (default) + + //subcase: selection{Start|End} > end + elem.value = "0123456789"; + elem.setSelectionRange(6, 9); + elem.setRangeText("Z", 1, 2, "preserve"); + is(elem.value, "0Z23456789", msg + ".value == \"0Z23456789\""); + is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"preserve\""); + is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"preserve\""); + expectedNumOfSelectCalls += 2; + + //subcase: selection{Start|End} < end + elem.value = "0123456789"; + elem.setSelectionRange(4, 5); + elem.setRangeText("QRST", 2, 9, "preserve"); + is(elem.value, "01QRST9", msg + ".value == \"01QRST9\""); + is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"preserve\""); + is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"preserve\""); + expectedNumOfSelectCalls += 2; + + //subcase: selectionStart > end, selectionEnd < end + elem.value = "0123456789"; + elem.setSelectionRange(8, 4); + elem.setRangeText("QRST", 1, 5); + is(elem.value, "0QRST56789", msg + ".value == \"0QRST56789\""); + is(elem.selectionStart, 1, msg + ".selectionStart == 1, with \"default\""); + is(elem.selectionEnd, 5, msg + ".selectionEnd == 5, with \"default\""); + expectedNumOfSelectCalls += 2; + + //subcase: selectionStart < end, selectionEnd > end + elem.value = "0123456789"; + elem.setSelectionRange(4, 9); + elem.setRangeText("QRST", 2, 6); + is(elem.value, "01QRST6789", msg + ".value == \"01QRST6789\""); + is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"default\""); + is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"default\""); + expectedNumOfSelectCalls += 2; + } + } + + addLoadEvent(TestInputs); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_step_attribute.html b/dom/html/test/forms/test_step_attribute.html new file mode 100644 index 000000000..31277860c --- /dev/null +++ b/dom/html/test/forms/test_step_attribute.html @@ -0,0 +1,965 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=635553 +--> +<head> + <title>Test for Bug 635553</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 635553 **/ + +var data = [ + { type: 'hidden', apply: false }, + { type: 'text', apply: false }, + { type: 'search', apply: false }, + { type: 'tel', apply: false }, + { type: 'url', apply: false }, + { type: 'email', apply: false }, + { type: 'password', apply: false }, + { type: 'date', apply: true }, + { type: 'month', apply: true }, + { type: 'week', apply: true }, + { type: 'time', apply: true }, + // TODO: temporary set to false until bug 888331 is fixed. + { type: 'datetime-local', apply: false }, + { type: 'number', apply: true }, + { type: 'range', apply: true }, + { type: 'color', apply: false }, + { type: 'checkbox', apply: false }, + { type: 'radio', apply: false }, + { type: 'file', apply: false }, + { type: 'submit', apply: false }, + { type: 'image', apply: false }, + { type: 'reset', apply: false }, + { type: 'button', apply: false }, +]; + +function getFreshElement(type) { + var elmt = document.createElement('input'); + elmt.type = type; + return elmt; +} + +function checkValidity(aElement, aValidity, aApply, aData) +{ + aValidity = aApply ? aValidity : true; + + is(aElement.validity.valid, aValidity, + "element validity should be " + aValidity); + is(aElement.validity.stepMismatch, !aValidity, + "element step mismatch status should be " + !aValidity); + + if (aValidity) { + is(aElement.validationMessage, "", "There should be no validation message."); + } else { + if (aElement.validity.rangeUnderflow) { + var underflowMsg = + (aElement.type == "date" || aElement.type == "time") ? + ("Please select a value that is no earlier than " + aElement.min + ".") : + ("Please select a value that is no less than " + aElement.min + "."); + is(aElement.validationMessage, underflowMsg, + "Checking range underflow validation message."); + } else if (aData.low == aData.high) { + is(aElement.validationMessage, "Please select a valid value. " + + "The nearest valid value is " + aData.low + ".", + "There should be a validation message."); + } else { + is(aElement.validationMessage, "Please select a valid value. " + + "The two nearest valid values are " + aData.low + " and " + aData.high + ".", + "There should be a validation message."); + } + } + + is(aElement.matches(":valid"), aElement.willValidate && aValidity, + (aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply"); + is(aElement.matches(":invalid"), aElement.willValidate && !aValidity, + (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply"); +} + +for (var test of data) { + var input = getFreshElement(test.type); + var apply = test.apply; + + if (test.todo) { + todo_is(input.type, test.type, test.type + " isn't implemented yet"); + continue; + } + + // The element should be valid, there should be no step mismatch. + checkValidity(input, true, apply); + + // Checks to do for all types that support step: + // - check for @step=0, + // - check for @step behind removed, + // - check for @step being 'any' with different case variations. + switch (input.type) { + case 'text': + case 'hidden': + case 'search': + case 'password': + case 'tel': + case 'radio': + case 'checkbox': + case 'reset': + case 'button': + case 'submit': + case 'image': + case 'color': + input.value = '0'; + checkValidity(input, true, apply); + break; + case 'url': + input.value = 'http://mozilla.org'; + checkValidity(input, true, apply); + break; + case 'email': + input.value = 'foo@bar.com'; + checkValidity(input, true, apply); + break; + case 'file': + var file = new File([''], '635499_file'); + + SpecialPowers.wrap(input).mozSetFileArray([file]); + checkValidity(input, true, apply); + + break; + case 'date': + // For date, the step is calulated on the timestamp since 1970-01-01 + // which mean that for all dates prior to the epoch, this timestamp is < 0 + // and the behavior might differ, therefore we have to test for these cases. + + // When step is invalid, every date is valid + input.step = 0; + input.value = '2012-07-05'; + checkValidity(input, true, apply); + + input.step = 'foo'; + input.value = '1970-01-01'; + checkValidity(input, true, apply); + + input.step = '-1'; + input.value = '1969-12-12'; + checkValidity(input, true, apply); + + input.removeAttribute('step'); + input.value = '1500-01-01'; + checkValidity(input, true, apply); + + input.step = 'any'; + input.value = '1966-12-12'; + checkValidity(input, true, apply); + + input.step = 'ANY'; + input.value = '2013-02-03'; + checkValidity(input, true, apply); + + // When min is set to a valid date, there is a step base. + input.min = '2008-02-28'; + input.step = '2'; + input.value = '2008-03-01'; + checkValidity(input, true, apply); + + input.value = '2008-02-29'; + checkValidity(input, false, apply, { low: "2008-02-28", high: "2008-03-01" }); + + input.min = '2008-02-27'; + input.value = '2008-02-28'; + checkValidity(input, false, apply, { low: "2008-02-27", high: "2008-02-29" }); + + input.min = '2009-02-27'; + input.value = '2009-02-28'; + checkValidity(input, false, apply, { low: "2009-02-27", high: "2009-03-01" }); + + input.min = '2009-02-01'; + input.step = '1.1'; + input.value = '2009-02-02'; + checkValidity(input, true, apply); + + // Without any step attribute the date is valid + input.removeAttribute('step'); + checkValidity(input, true, apply); + + input.min = '1950-01-01'; + input.step = '366'; + input.value = '1951-01-01'; + checkValidity(input, false, apply, { low: "1950-01-01", high: "1951-01-02" }); + + input.min = '1951-01-01'; + input.step = '365'; + input.value = '1952-01-01'; + checkValidity(input, true, apply); + + input.step = '0.9'; + input.value = '1951-01-02'; + is(input.step, '0.9', "check that step value is unchanged"); + checkValidity(input, true, apply); + + input.step = '0.4'; + input.value = '1951-01-02'; + is(input.step, '0.4', "check that step value is unchanged"); + checkValidity(input, true, apply); + + input.step = '1.5'; + input.value = '1951-01-02'; + is(input.step, '1.5', "check that step value is unchanged"); + checkValidity(input, false, apply, { low: "1951-01-01", high: "1951-01-03" }); + + input.value = '1951-01-08'; + checkValidity(input, false, apply, { low: "1951-01-07", high: "1951-01-09" }); + + input.step = '3000'; + input.min= '1968-01-01'; + input.value = '1968-05-12'; + checkValidity(input, false, apply, { low: "1968-01-01", high: "1976-03-19" }); + + input.value = '1971-01-01'; + checkValidity(input, false, apply, { low: "1968-01-01", high: "1976-03-19" }); + + input.value = '1991-01-01'; + checkValidity(input, false, apply, { low: "1984-06-05", high: "1992-08-22" }); + + input.value = '1984-06-05'; + checkValidity(input, true, apply); + + input.value = '1992-08-22'; + checkValidity(input, true, apply); + + input.step = '2.1'; + input.min = '1991-01-01'; + input.value = '1991-01-01'; + checkValidity(input, true, apply); + + input.value = '1991-01-02'; + checkValidity(input, false, apply, { low: "1991-01-01", high: "1991-01-03" }); + + input.value = '1991-01-03'; + checkValidity(input, true, apply); + + input.step = '2.1'; + input.min = '1969-12-20'; + input.value = '1969-12-20'; + checkValidity(input, true, apply); + + input.value = '1969-12-21'; + checkValidity(input, false, apply, { low: "1969-12-20", high: "1969-12-22" }); + + input.value = '1969-12-22'; + checkValidity(input, true, apply); + + break; + case 'number': + // When step=0, the allowed step is 1. + input.step = '0'; + input.value = '1.2'; + checkValidity(input, false, apply, { low: 1, high: 2 }); + + input.value = '1'; + checkValidity(input, true, apply); + + input.value = '0'; + checkValidity(input, true, apply); + + // When step is NaN, the allowed step value is 1. + input.step = 'foo'; + input.value = '1'; + checkValidity(input, true, apply); + + input.value = '1.5'; + checkValidity(input, false, apply, { low: 1, high: 2 }); + + // When step is negative, the allowed step value is 1. + input.step = '-0.1'; + checkValidity(input, false, apply, { low: 1, high: 2 }); + + input.value = '1'; + checkValidity(input, true, apply); + + // When step is missing, the allowed step value is 1. + input.removeAttribute('step'); + input.value = '1.5'; + checkValidity(input, false, apply, { low: 1, high: 2 }); + + input.value = '1'; + checkValidity(input, true, apply); + + // When step is 'any', all values are fine wrt to step. + input.step = 'any'; + checkValidity(input, true, apply); + + input.step = 'aNy'; + input.value = '1337'; + checkValidity(input, true, apply); + + input.step = 'AnY'; + input.value = '0.1'; + checkValidity(input, true, apply); + + input.step = 'ANY'; + input.value = '-13.37'; + checkValidity(input, true, apply); + + // When min is set to a valid float, there is a step base. + input.min = '1'; + input.step = '2'; + input.value = '3'; + checkValidity(input, true, apply); + + input.value = '2'; + checkValidity(input, false, apply, { low: 1, high: 3 }); + + input.removeAttribute('step'); // step = 1 + input.min = '0.5'; + input.value = '5.5'; + checkValidity(input, true, apply); + + input.value = '1'; + checkValidity(input, false, apply, { low: 0.5, high: 1.5 }); + + input.min = '-0.1'; + input.step = '1'; + input.value = '0.9'; + checkValidity(input, true, apply); + + input.value = '0.1'; + checkValidity(input, false, apply, { low: -0.1, high: 0.9 }); + + // When min is set to NaN, there is no step base (step base=0 actually). + input.min = 'foo'; + input.step = '1'; + input.value = '1'; + checkValidity(input, true, apply); + + input.value = '0.5'; + checkValidity(input, false, apply, { low: 0, high: 1 }); + + input.min = ''; + input.value = '1'; + checkValidity(input, true, apply); + + input.value = '0.5'; + checkValidity(input, false, apply, { low: 0, high: 1 }); + + input.removeAttribute('min'); + + // If value isn't a number, the element isn't invalid. + input.value = ''; + checkValidity(input, true, apply); + + // Regular situations. + input.step = '2'; + input.value = '1.5'; + checkValidity(input, false, apply, { low: 0, high: 2 }); + + input.value = '42.0'; + checkValidity(input, true, apply); + + input.step = '0.1'; + input.value = '-0.1'; + checkValidity(input, true, apply); + + input.step = '2'; + input.removeAttribute('min'); + input.max = '10'; + input.value = '-9'; + checkValidity(input, false, apply, {low: -10, high: -8}); + + // If there is a value defined but no min, the step base is the value. + input = getFreshElement(test.type); + input.setAttribute('value', '1'); + input.step = 2; + checkValidity(input, true, apply); + + input.value = 3; + checkValidity(input, true, apply); + + input.value = 2; + checkValidity(input, false, apply, {low: 1, high: 3}); + + // Should also work with defaultValue. + input = getFreshElement(test.type); + input.defaultValue = 1; + input.step = 2; + checkValidity(input, true, apply); + + input.value = 3; + checkValidity(input, true, apply); + + input.value = 2; + checkValidity(input, false, apply, {low: 1, high: 3}); + + // Rounding issues. + input = getFreshElement(test.type); + input.min = 0.1; + input.step = 0.2; + input.value = 0.3; + checkValidity(input, true, apply); + + // Check that when the higher value is higher than max, we don't show it. + input = getFreshElement(test.type); + input.step = '2'; + input.min = '1'; + input.max = '10.9'; + input.value = '10'; + + is(input.validationMessage, "Please select a valid value. " + + "The nearest valid value is 9.", + "The validation message should not include the higher value."); + break; + case 'range': + // Range is special in that it clamps to valid values, so it is much + // rarer for it to be invalid. + + // When step=0, the allowed value step is 1. + input.step = '0'; + input.value = '1.2'; + is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.value = '1'; + is(input.value, '1', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = '0'; + is(input.value, '0', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + // When step is NaN, the allowed step value is 1. + input.step = 'foo'; + input.value = '1'; + is(input.value, '1', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = '1.5'; + is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + // When step is negative, the allowed step value is 1. + input.step = '-0.1'; + is(input.value, '2', "check that the value still coincides with a step"); + checkValidity(input, true, apply); + + input.value = '1'; + is(input.value, '1', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + // When step is missing, the allowed step value is 1. + input.removeAttribute('step'); + input.value = '1.5'; + is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.value = '1'; + is(input.value, '1', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + // When step is 'any', all values are fine wrt to step. + input.step = 'any'; + checkValidity(input, true, apply); + + input.step = 'aNy'; + input.value = '97'; + is(input.value, '97', "check that the value for step=aNy is unchanged"); + checkValidity(input, true, apply); + + input.step = 'AnY'; + input.value = '0.1'; + is(input.value, '0.1', "check that a positive fractional value with step=AnY is unchanged"); + checkValidity(input, true, apply); + + input.step = 'ANY'; + input.min = -100; + input.value = '-13.37'; + is(input.value, '-13.37', "check that a negative fractional value with step=ANY is unchanged"); + checkValidity(input, true, apply); + + // When min is set to a valid float, there is a step base. + input.min = '1'; // the step base + input.step = '2'; + input.value = '3'; + is(input.value, '3', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = '2'; + is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.value = '1.99'; + is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.removeAttribute('step'); // step = 1 + input.min = '0.5'; // step base + input.value = '5.5'; + is(input.value, '5.5', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = '1'; + is(input.value, '1.5', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.min = '-0.1'; // step base + input.step = '1'; + input.value = '0.9'; + is(input.value, '0.9', "the value should be a valid step"); + checkValidity(input, true, apply); + + input.value = '0.1'; + is(input.value, '-0.1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + // When min is set to NaN, the step base is the value. + input.min = 'foo'; + input.step = '1'; + input.value = '1'; + is(input.value, '1', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = '0.5'; + is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.min = ''; + input.value = '1'; + is(input.value, '1', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = '0.5'; + is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.removeAttribute('min'); + + // Test when the value isn't a number + input.value = ''; + is(input.value, '50', "value be should default to the value midway between the minimum (0) and the maximum (100)"); + checkValidity(input, true, apply); + + // Regular situations. + input.step = '2'; + input.value = '1.5'; + is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.value = '42.0'; + is(input.value, '42.0', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.step = '0.1'; + input.value = '-0.1'; + is(input.value, '0', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.step = '2'; + input.removeAttribute('min'); + input.max = '10'; + input.value = '-9'; + is(input.value, '0', "check the value is clamped to the minimum's default of zero"); + checkValidity(input, true, apply); + + // If @value is defined but not @min, the step base is @value. + input = getFreshElement(test.type); + input.setAttribute('value', '1'); + input.step = 2; + is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + input.value = 3; + is(input.value, '3', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = 2; + is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + // Should also work with defaultValue. + input = getFreshElement(test.type); + input.defaultValue = 1; + input.step = 2; + is(input.value, '1', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = 3; + is(input.value, '3', "check that the value coincides with a step"); + checkValidity(input, true, apply); + + input.value = 2; + is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close"); + checkValidity(input, true, apply); + + // Check contrived error case where there are no valid steps in range: + // No @min, so the step base is the default minimum, zero, the valid + // range is 0-1, -1 gets clamped to zero. + input = getFreshElement(test.type); + input.step = '3'; + input.max = '1'; + input.defaultValue = '-1'; + is(input.value, '0', "the value should have been clamped to the default minimum, zero"); + checkValidity(input, false, apply, {low: -1, high: -1}); + + // Check that when the closest of the two steps that the value is between + // is greater than the maximum we sanitize to the lower step. + input = getFreshElement(test.type); + input.step = '2'; + input.min = '1'; + input.max = '10.9'; + input.value = '10.8'; // closest step in 11, but 11 > maximum + is(input.value, '9', "check that the value coincides with a step"); + + // The way that step base is defined, the converse (the value not being + // on a step, and the nearest step being a value that would be underflow) + // is not possible, so nothing to test there. + + is(input.validationMessage, "", + "The validation message should be empty."); + break; + case 'time': + // Tests invalid step values. That defaults to step = 1 minute (60). + var values = [ '0', '-1', 'foo', 'any', 'ANY', 'aNy' ]; + for (var value of values) { + input.step = value; + input.value = '19:06:00'; + checkValidity(input, true, apply); + input.value = '19:06:51'; + if (value.toLowerCase() != 'any') { + checkValidity(input, false, apply, {low: '19:06', high: '19:07'}); + } else { + checkValidity(input, true, apply); + } + } + + // No step means that we use the default step value. + input.removeAttribute('step'); + input.value = '19:06:00'; + checkValidity(input, true, apply); + input.value = '19:06:51'; + checkValidity(input, false, apply, {low: '19:06', high: '19:07'}); + + var tests = [ + // With step=1, we allow values by the second. + { step: '1', value: '19:11:01', min: '00:00', result: true }, + { step: '1', value: '19:11:01.001', min: '00:00', result: false, + low: '19:11:01', high: '19:11:02' }, + { step: '1', value: '19:11:01.1', min: '00:00', result: false, + low: '19:11:01', high: '19:11:02' }, + // When step >= 86400000, only the minimum value is valid. + // This is actually @value if there is no @min. + { step: '86400000', value: '00:00', result: true }, + { step: '86400000', value: '00:01', result: true }, + { step: '86400000', value: '00:00', min: '00:01', result: false }, + { step: '86400000', value: '00:01', min: '00:00', result: false, + low: '00:00', high: '00:00' }, + // When step < 1, it should just work. + { step: '0.1', value: '15:05:05.1', min: '00:00', result: true }, + { step: '0.1', value: '15:05:05.101', min: '00:00', result: false, + low: '15:05:05.100', high: '15:05:05.200' }, + { step: '0.2', value: '15:05:05.2', min: '00:00', result: true }, + { step: '0.2', value: '15:05:05.1', min: '00:00', result: false, + low: '15:05:05', high: '15:05:05.200' }, + { step: '0.01', value: '15:05:05.01', min: '00:00', result: true }, + { step: '0.01', value: '15:05:05.011', min: '00:00', result: false, + low: '15:05:05.010', high: '15:05:05.020' }, + { step: '0.02', value: '15:05:05.02', min: '00:00', result: true }, + { step: '0.02', value: '15:05:05.01', min: '00:00', result: false, + low: '15:05:05', high: '15:05:05.020' }, + { step: '0.002', value: '15:05:05.002', min: '00:00', result: true }, + { step: '0.002', value: '15:05:05.001', min: '00:00', result: false, + low: '15:05:05', high: '15:05:05.002' }, + // When step<=0.001, any value is allowed. + { step: '0.001', value: '15:05:05.001', min: '00:00', result: true }, + { step: '0.001', value: '15:05:05', min: '00:00', result: true }, + { step: '0.000001', value: '15:05:05', min: '00:00', result: true }, + // This value has conversion to double issues. + { step: '0.0000001', value: '15:05:05', min: '00:00', result: true }, + // Some random values. + { step: '100', value: '15:06:40', min: '00:00', result: true }, + { step: '100', value: '15:05:05.010', min: '00:00', result: false, + low: '15:05', high: '15:06:40' }, + { step: '3600', value: '15:00', min: '00:00', result: true }, + { step: '3600', value: '15:14', min: '00:00', result: false, + low: '15:00', high: '16:00' }, + { step: '7200', value: '14:00', min: '00:00', result: true }, + { step: '7200', value: '15:14', min: '00:00', result: false, + low: '14:00', high: '16:00' }, + { step: '7260', value: '14:07', min: '00:00', result: true }, + { step: '7260', value: '15:14', min: '00:00', result: false, + low: '14:07', high: '16:08' }, + ]; + + var type = test.type; + for (var test of tests) { + var input = getFreshElement(type); + input.step = test.step; + input.setAttribute('value', test.value); + if (test.min !== undefined) { + input.min = test.min; + } + + if (test.todo) { + todo(input.validity.valid, test.result, + "This test should fail for the moment because of precission issues"); + continue; + } + + if (test.result) { + checkValidity(input, true, apply); + } else { + checkValidity(input, false, apply, + { low: test.low, high: test.high }); + } + } + + break; + case 'month': + // When step is invalid, every date is valid + input.step = 0; + input.value = '2016-07'; + checkValidity(input, true, apply); + + input.step = 'foo'; + input.value = '1970-01'; + checkValidity(input, true, apply); + + input.step = '-1'; + input.value = '1970-01'; + checkValidity(input, true, apply); + + input.removeAttribute('step'); + input.value = '1500-01'; + checkValidity(input, true, apply); + + input.step = 'any'; + input.value = '1966-12'; + checkValidity(input, true, apply); + + input.step = 'ANY'; + input.value = '2013-02'; + checkValidity(input, true, apply); + + // When min is set to a valid month, there is a step base. + input.min = '2000-01'; + input.step = '2'; + input.value = '2000-03'; + checkValidity(input, true, apply); + + input.value = '2000-02'; + checkValidity(input, false, apply, { low: "2000-01", high: "2000-03" }); + + input.min = '2012-12'; + input.value = '2013-01'; + checkValidity(input, false, apply, { low: "2012-12", high: "2013-02" }); + + input.min = '2010-10'; + input.value = '2010-11'; + checkValidity(input, false, apply, { low: "2010-10", high: "2010-12" }); + + input.min = '2010-01'; + input.step = '1.1'; + input.value = '2010-02'; + checkValidity(input, true, apply); + + input.min = '2010-05'; + input.step = '1.9'; + input.value = '2010-06'; + checkValidity(input, false, apply, { low: "2010-05", high: "2010-07" }); + + // Without any step attribute the date is valid + input.removeAttribute('step'); + checkValidity(input, true, apply); + + input.min = '1950-01'; + input.step = '13'; + input.value = '1951-01'; + checkValidity(input, false, apply, { low: "1950-01", high: "1951-02" }); + + input.min = '1951-01'; + input.step = '12'; + input.value = '1952-01'; + checkValidity(input, true, apply); + + input.step = '0.9'; + input.value = '1951-02'; + checkValidity(input, true, apply); + + input.step = '1.5'; + input.value = '1951-04'; + checkValidity(input, false, apply, { low: "1951-03", high: "1951-05" }); + + input.value = '1951-08'; + checkValidity(input, false, apply, { low: "1951-07", high: "1951-09" }); + + input.step = '300'; + input.min= '1968-01'; + input.value = '1968-05'; + checkValidity(input, false, apply, { low: "1968-01", high: "1993-01" }); + + input.value = '1971-01'; + checkValidity(input, false, apply, { low: "1968-01", high: "1993-01" }); + + input.value = '1994-01'; + checkValidity(input, false, apply, { low: "1993-01", high: "2018-01" }); + + input.value = '2018-01'; + checkValidity(input, true, apply); + + input.value = '2043-01'; + checkValidity(input, true, apply); + + input.step = '2.1'; + input.min = '1991-01'; + input.value = '1991-01'; + checkValidity(input, true, apply); + + input.value = '1991-02'; + checkValidity(input, false, apply, { low: "1991-01", high: "1991-03" }); + + input.value = '1991-03'; + checkValidity(input, true, apply); + + input.step = '2.1'; + input.min = '1969-12'; + input.value = '1969-12'; + checkValidity(input, true, apply); + + input.value = '1970-01'; + checkValidity(input, false, apply, { low: "1969-12", high: "1970-02" }); + + input.value = '1970-02'; + checkValidity(input, true, apply); + + break; + case 'week': + // When step is invalid, every week is valid + input.step = 0; + input.value = '2016-W30'; + checkValidity(input, true, apply); + + input.step = 'foo'; + input.value = '1970-W01'; + checkValidity(input, true, apply); + + input.step = '-1'; + input.value = '1970-W01'; + checkValidity(input, true, apply); + + input.removeAttribute('step'); + input.value = '1500-W01'; + checkValidity(input, true, apply); + + input.step = 'any'; + input.value = '1966-W52'; + checkValidity(input, true, apply); + + input.step = 'ANY'; + input.value = '2013-W10'; + checkValidity(input, true, apply); + + // When min is set to a valid week, there is a step base. + input.min = '2000-W01'; + input.step = '2'; + input.value = '2000-W03'; + checkValidity(input, true, apply); + + input.value = '2000-W02'; + checkValidity(input, false, apply, { low: "2000-W01", high: "2000-W03" }); + + input.min = '2012-W52'; + input.value = '2013-W01'; + checkValidity(input, false, apply, { low: "2012-W52", high: "2013-W02" }); + + input.min = '2010-W01'; + input.step = '1.1'; + input.value = '2010-W02'; + checkValidity(input, true, apply); + + input.min = '2010-W05'; + input.step = '1.9'; + input.value = '2010-W06'; + checkValidity(input, false, apply, { low: "2010-W05", high: "2010-W07" }); + + // Without any step attribute the week is valid + input.removeAttribute('step'); + checkValidity(input, true, apply); + + input.min = '1950-W01'; + input.step = '53'; + input.value = '1951-W01'; + checkValidity(input, false, apply, { low: "1950-W01", high: "1951-W02" }); + + input.min = '1951-W01'; + input.step = '52'; + input.value = '1952-W01'; + checkValidity(input, true, apply); + + input.step = '0.9'; + input.value = '1951-W02'; + checkValidity(input, true, apply); + + input.step = '1.5'; + input.value = '1951-W04'; + checkValidity(input, false, apply, { low: "1951-W03", high: "1951-W05" }); + + input.value = '1951-W20'; + checkValidity(input, false, apply, { low: "1951-W19", high: "1951-W21" }); + + input.step = '300'; + input.min= '1968-W01'; + input.value = '1968-W05'; + checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" }); + + input.value = '1971-W01'; + checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" }); + + input.value = '1975-W01'; + checkValidity(input, false, apply, { low: "1973-W40", high: "1979-W27" }); + + input.value = '1985-W14'; + checkValidity(input, true, apply); + + input.step = '2.1'; + input.min = '1991-W01'; + input.value = '1991-W01'; + checkValidity(input, true, apply); + + input.value = '1991-W02'; + checkValidity(input, false, apply, { low: "1991-W01", high: "1991-W03" }); + + input.value = '1991-W03'; + checkValidity(input, true, apply); + + input.step = '2.1'; + input.min = '1969-W52'; + input.value = '1969-W52'; + checkValidity(input, true, apply); + + input.value = '1970-W01'; + checkValidity(input, false, apply, { low: "1969-W52", high: "1970-W02" }); + + input.value = '1970-W02'; + checkValidity(input, true, apply); + + break; + case 'datetime-local': + // TODO: this is temporary until bug 888331 is fixed. + + break; + default: + ok(false, "Implement the tests for <input type='" + test.type + " >"); + break; + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_stepup_stepdown.html b/dom/html/test/forms/test_stepup_stepdown.html new file mode 100644 index 000000000..d96895180 --- /dev/null +++ b/dom/html/test/forms/test_stepup_stepdown.html @@ -0,0 +1,1018 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=636627 +--> +<head> + <title>Test for Bug 636627</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636627">Mozilla Bug 636627</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 636627 **/ + +/** + * This test is testing stepDown() and stepUp(). + */ + +function checkPresence() +{ + var input = document.createElement('input'); + is('stepDown' in input, true, 'stepDown() should be an input function'); + is('stepUp' in input, true, 'stepUp() should be an input function'); +} + +function checkAvailability() +{ + var testData = + [ + ["text", false], + ["password", false], + ["search", false], + ["telephone", false], + ["email", false], + ["url", false], + ["hidden", false], + ["checkbox", false], + ["radio", false], + ["file", false], + ["submit", false], + ["image", false], + ["reset", false], + ["button", false], + ["number", true], + ["range", true], + ["date", true], + ["time", true], + ["month", true], + ["week", true], + ["color", false], + ]; + + var todoList = + [ + ["datetime", true], + ["datetime-local", true], + ]; + + var element = document.createElement("input"); + element.setAttribute('value', '0'); + + for (data of testData) { + var exceptionCaught = false; + element.type = data[0]; + try { + element.stepDown(); + } catch (e) { + exceptionCaught = true; + } + is(exceptionCaught, !data[1], "stepDown() availability is not correct"); + + exceptionCaught = false; + try { + element.stepUp(); + } catch (e) { + exceptionCaught = true; + } + is(exceptionCaught, !data[1], "stepUp() availability is not correct"); + } + + for (data of todoList) { + var exceptionCaught = false; + element.type = data[0]; + try { + element.stepDown(); + } catch (e) { + exceptionCaught = true; + } + todo_is(exceptionCaught, !data[1], + "stepDown() availability is not correct"); + + exceptionCaught = false; + try { + element.stepUp(); + } catch (e) { + exceptionCaught = true; + } + todo_is(exceptionCaught, !data[1], + "stepUp() availability is not correct"); + } +} + +function checkStepDown() +{ + // This testData is very similar to the one in checkStepUp with some changes + // relative to stepDown. + var testData = [ + /* Initial value | step | min | max | stepDown arg | final value | exception */ + { type: 'number', data: [ + // Regular case. + [ '1', null, null, null, null, '0', false ], + // Argument testing. + [ '1', null, null, null, 1, '0', false ], + [ '9', null, null, null, 9, '0', false ], + [ '1', null, null, null, -1, '2', false ], + [ '1', null, null, null, 0, '1', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '1', null, null, null, 1.1, '0', false ], + // With step values. + [ '1', '0.5', null, null, null, '0.5', false ], + [ '1', '0.25', null, null, 4, '0', false ], + // step = 0 isn't allowed (-> step = 1). + [ '1', '0', null, null, null, '0', false ], + // step < 0 isn't allowed (-> step = 1). + [ '1', '-1', null, null, null, '0', false ], + // step = NaN isn't allowed (-> step = 1). + [ '1', 'foo', null, null, null, '0', false ], + // Min values testing. + [ '1', '1', 'foo', null, null, '0', false ], + [ '1', null, '-10', null, null, '0', false ], + [ '1', null, '0', null, null, '0', false ], + [ '1', null, '10', null, null, '1', false ], + [ '1', null, '2', null, null, '1', false ], + [ '1', null, '1', null, null, '1', false ], + // Max values testing. + [ '1', '1', null, 'foo', null, '0', false ], + [ '1', null, null, '10', null, '0', false ], + [ '1', null, null, '0', null, '0', false ], + [ '1', null, null, '-10', null, '-10', false ], + [ '1', null, null, '1', null, '0', false ], + [ '5', null, null, '3', '3', '2', false ], + [ '5', '2', '-6', '3', '2', '2', false ], + [ '-3', '5', '-10', '-3', null, '-5', false ], + // Step mismatch. + [ '1', '2', '-2', null, null, '0', false ], + [ '3', '2', '-2', null, null, '2', false ], + [ '3', '2', '-2', null, '2', '0', false ], + [ '3', '2', '-2', null, '-2', '6', false ], + [ '1', '2', '-6', null, null, '0', false ], + [ '1', '2', '-2', null, null, '0', false ], + [ '1', '3', '-6', null, null, '0', false ], + [ '2', '3', '-6', null, null, '0', false ], + [ '2', '3', '1', null, null, '1', false ], + [ '5', '3', '1', null, null, '4', false ], + [ '3', '2', '-6', null, null, '2', false ], + [ '5', '2', '-6', null, null, '4', false ], + [ '6', '2', '1', null, null, '5', false ], + [ '8', '3', '1', null, null, '7', false ], + [ '9', '2', '-10', null, null, '8', false ], + [ '7', '3', '-10', null, null, '5', false ], + [ '-2', '3', '-10', null, null, '-4', false ], + // Clamping. + [ '0', '2', '-1', null, null, '-1', false ], + [ '10', '2', '0', '4', '10', '0', false ], + [ '10', '2', '0', '4', '5', '0', false ], + // value = "" (NaN). + [ '', null, null, null, null, '-1', false ], + [ '', '2', null, null, null, '-2', false ], + [ '', '2', '3', null, null, '3', false ], + [ '', null, '3', null, null, '3', false ], + [ '', '2', '3', '8', null, '3', false ], + [ '', null, '-10', '10', null, '-1', false ], + [ '', '3', '-10', '10', null, '-1', false ], + // With step = 'any'. + [ '0', 'any', null, null, 1, null, true ], + [ '0', 'ANY', null, null, 1, null, true ], + [ '0', 'AnY', null, null, 1, null, true ], + [ '0', 'aNy', null, null, 1, null, true ], + // With @value = step base. + [ '1', '2', null, null, null, '-1', false ], + ]}, + { type: 'range', data: [ + // Regular case. + [ '1', null, null, null, null, '0', false ], + // Argument testing. + [ '1', null, null, null, 1, '0', false ], + [ '9', null, null, null, 9, '0', false ], + [ '1', null, null, null, -1, '2', false ], + [ '1', null, null, null, 0, '1', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '1', null, null, null, 1.1, '0', false ], + // With step values. + [ '1', '0.5', null, null, null, '0.5', false ], + [ '1', '0.25', null, null, 4, '0', false ], + // step = 0 isn't allowed (-> step = 1). + [ '1', '0', null, null, null, '0', false ], + // step < 0 isn't allowed (-> step = 1). + [ '1', '-1', null, null, null, '0', false ], + // step = NaN isn't allowed (-> step = 1). + [ '1', 'foo', null, null, null, '0', false ], + // Min values testing. + [ '1', '1', 'foo', null, null, '0', false ], + [ '1', null, '-10', null, null, '0', false ], + [ '1', null, '0', null, null, '0', false ], + [ '1', null, '10', null, null, '10', false ], + [ '1', null, '2', null, null, '2', false ], + [ '1', null, '1', null, null, '1', false ], + // Max values testing. + [ '1', '1', null, 'foo', null, '0', false ], + [ '1', null, null, '10', null, '0', false ], + [ '1', null, null, '0', null, '0', false ], + [ '1', null, null, '-10', null, '0', false ], + [ '1', null, null, '1', null, '0', false ], + [ '5', null, null, '3', '3', '0', false ], + [ '5', '2', '-6', '3', '2', '-2', false ], + [ '-3', '5', '-10', '-3', null, '-10', false ], + // Step mismatch. + [ '1', '2', '-2', null, null, '0', false ], + [ '3', '2', '-2', null, null, '2', false ], + [ '3', '2', '-2', null, '2', '0', false ], + [ '3', '2', '-2', null, '-2', '8', false ], + [ '1', '2', '-6', null, null, '0', false ], + [ '1', '2', '-2', null, null, '0', false ], + [ '1', '3', '-6', null, null, '-3', false ], + [ '2', '3', '-6', null, null, '0', false ], + [ '2', '3', '1', null, null, '1', false ], + [ '5', '3', '1', null, null, '1', false ], + [ '3', '2', '-6', null, null, '2', false ], + [ '5', '2', '-6', null, null, '4', false ], + [ '6', '2', '1', null, null, '5', false ], + [ '8', '3', '1', null, null, '4', false ], + [ '9', '2', '-10', null, null, '8', false ], + [ '7', '3', '-10', null, null, '5', false ], + [ '-2', '3', '-10', null, null, '-4', false ], + // Clamping. + [ '0', '2', '-1', null, null, '-1', false ], + [ '10', '2', '0', '4', '10', '0', false ], + [ '10', '2', '0', '4', '5', '0', false ], + // value = "" (default will be 50). + [ '', null, null, null, null, '49', false ], + // With step = 'any'. + [ '0', 'any', null, null, 1, null, true ], + [ '0', 'ANY', null, null, 1, null, true ], + [ '0', 'AnY', null, null, 1, null, true ], + [ '0', 'aNy', null, null, 1, null, true ], + // With @value = step base. + [ '1', '2', null, null, null, '1', false ], + ]}, + { type: 'date', data: [ + // Regular case. + [ '2012-07-09', null, null, null, null, '2012-07-08', false ], + // Argument testing. + [ '2012-07-09', null, null, null, 1, '2012-07-08', false ], + [ '2012-07-09', null, null, null, 5, '2012-07-04', false ], + [ '2012-07-09', null, null, null, -1, '2012-07-10', false ], + [ '2012-07-09', null, null, null, 0, '2012-07-09', false ], + // Month/Year wrapping. + [ '2012-08-01', null, null, null, 1, '2012-07-31', false ], + [ '1969-01-02', null, null, null, 4, '1968-12-29', false ], + [ '1969-01-01', null, null, null, -365, '1970-01-01', false ], + [ '2012-02-29', null, null, null, -1, '2012-03-01', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '2012-01-02', null, null, null, 1.1, '2012-01-01', false ], + [ '2012-01-02', null, null, null, 1.9, '2012-01-01', false ], + // With step values. + [ '2012-01-03', '0.5', null, null, null, '2012-01-02', false ], + [ '2012-01-02', '0.5', null, null, null, '2012-01-01', false ], + [ '2012-01-01', '2', null, null, null, '2011-12-30', false ], + [ '2012-01-02', '0.25',null, null, 4, '2011-12-29', false ], + [ '2012-01-15', '1.1', '2012-01-01', null, 1, '2012-01-14', false ], + [ '2012-01-12', '1.1', '2012-01-01', null, 2, '2012-01-10', false ], + [ '2012-01-23', '1.1', '2012-01-01', null, 10, '2012-01-13', false ], + [ '2012-01-23', '1.1', '2012-01-01', null, 11, '2012-01-12', false ], + [ '1968-01-12', '1.1', '1968-01-01', null, 8, '1968-01-04', false ], + // step = 0 isn't allowed (-> step = 1). + [ '2012-01-02', '0', null, null, null, '2012-01-01', false ], + // step < 0 isn't allowed (-> step = 1). + [ '2012-01-02', '-1', null, null, null, '2012-01-01', false ], + // step = NaN isn't allowed (-> step = 1). + [ '2012-01-02', 'foo', null, null, null, '2012-01-01', false ], + // Min values testing. + [ '2012-01-03', '1', 'foo', null, 2, '2012-01-01', false ], + [ '2012-01-02', '1', '2012-01-01', null, null, '2012-01-01', false ], + [ '2012-01-01', '1', '2012-01-01', null, null, '2012-01-01', false ], + [ '2012-01-01', '1', '2012-01-10', null, 1, '2012-01-01', false ], + [ '2012-01-05', '3', '2012-01-01', null, null, '2012-01-04', false ], + [ '1969-01-01', '5', '1969-01-01', '1969-01-02', null, '1969-01-01', false ], + // Max values testing. + [ '2012-01-02', '1', null, 'foo', null, '2012-01-01', false ], + [ '2012-01-02', null, null, '2012-01-05', null, '2012-01-01', false ], + [ '2012-01-03', null, null, '2012-01-03', null, '2012-01-02', false ], + [ '2012-01-07', null, null, '2012-01-04', 4, '2012-01-03', false ], + [ '2012-01-07', '2', null, '2012-01-04', 3, '2012-01-01', false ], + // Step mismatch. + [ '2012-01-04', '2', '2012-01-01', null, null, '2012-01-03', false ], + [ '2012-01-06', '2', '2012-01-01', null, 2, '2012-01-03', false ], + [ '2012-01-05', '2', '2012-01-04', '2012-01-08', null, '2012-01-04', false ], + [ '1970-01-04', '2', null, null, null, '1970-01-02', false ], + [ '1970-01-09', '3', null, null, null, '1970-01-06', false ], + // Clamping. + [ '2012-05-01', null, null, '2012-01-05', null, '2012-01-05', false ], + [ '1970-01-05', '2', '1970-01-02', '1970-01-05', null, '1970-01-04', false ], + [ '1970-01-01', '5', '1970-01-02', '1970-01-09', 10, '1970-01-01', false ], + [ '1970-01-07', '5', '1969-12-27', '1970-01-06', 2, '1970-01-01', false ], + [ '1970-03-08', '3', '1970-02-01', '1970-02-07', 15, '1970-02-01', false ], + [ '1970-01-10', '3', '1970-01-01', '1970-01-06', 2, '1970-01-04', false ], + // value = "" (NaN). + [ '', null, null, null, null, '1969-12-31', false ], + // With step = 'any'. + [ '2012-01-01', 'any', null, null, 1, null, true ], + [ '2012-01-01', 'ANY', null, null, 1, null, true ], + [ '2012-01-01', 'AnY', null, null, 1, null, true ], + [ '2012-01-01', 'aNy', null, null, 1, null, true ], + ]}, + { type: 'time', data: [ + // Regular case. + [ '16:39', null, null, null, null, '16:38', false ], + // Argument testing. + [ '16:40', null, null, null, 1, '16:39', false ], + [ '16:40', null, null, null, 5, '16:35', false ], + [ '16:40', null, null, null, -1, '16:41', false ], + [ '16:40', null, null, null, 0, '16:40', false ], + // hour/minutes/seconds wrapping. + [ '05:00', null, null, null, null, '04:59', false ], + [ '05:00:00', 1, null, null, null, '04:59:59', false ], + [ '05:00:00', 0.1, null, null, null, '04:59:59.900', false ], + [ '05:00:00', 0.01, null, null, null, '04:59:59.990', false ], + [ '05:00:00', 0.001, null, null, null, '04:59:59.999', false ], + // stepDown() on '00:00' gives '23:59'. + [ '00:00', null, null, null, 1, '23:59', false ], + [ '00:00', null, null, null, 3, '23:57', false ], + // Some random step values.. + [ '16:56', '0.5', null, null, null, '16:55:59.500', false ], + [ '16:56', '2', null, null, null, '16:55:58', false ], + [ '16:56', '0.25',null, null, 4, '16:55:59', false ], + [ '16:57', '1.1', '16:00', null, 1, '16:56:59.900', false ], + [ '16:57', '1.1', '16:00', null, 2, '16:56:58.800', false ], + [ '16:57', '1.1', '16:00', null, 10, '16:56:50', false ], + [ '16:57', '1.1', '16:00', null, 11, '16:56:48.900', false ], + [ '16:57', '1.1', '16:00', null, 8, '16:56:52.200', false ], + // Invalid @step, means that we use the default value. + [ '17:01', '0', null, null, null, '17:00', false ], + [ '17:01', '-1', null, null, null, '17:00', false ], + [ '17:01', 'foo', null, null, null, '17:00', false ], + // Min values testing. + [ '17:02', '60', 'foo', null, 2, '17:00', false ], + [ '17:10', '60', '17:09', null, null, '17:09', false ], + [ '17:10', '60', '17:10', null, null, '17:10', false ], + [ '17:10', '60', '17:30', null, 1, '17:10', false ], + [ '17:10', '180', '17:05', null, null, '17:08', false ], + [ '17:10', '300', '17:10', '17:11', null, '17:10', false ], + // Max values testing. + [ '17:15', '60', null, 'foo', null, '17:14', false ], + [ '17:15', null, null, '17:20', null, '17:14', false ], + [ '17:15', null, null, '17:15', null, '17:14', false ], + [ '17:15', null, null, '17:13', 4, '17:11', false ], + [ '17:15', '120', null, '17:13', 3, '17:09', false ], + // Step mismatch. + [ '17:19', '120', '17:10', null, null, '17:18', false ], + [ '17:19', '120', '17:10', null, 2, '17:16', false ], + [ '17:19', '120', '17:18', '17:25', null, '17:18', false ], + [ '17:19', '120', null, null, null, '17:17', false ], + [ '17:19', '180', null, null, null, '17:16', false ], + // Clamping. + [ '17:22', null, null, '17:11', null, '17:11', false ], + [ '17:22', '120', '17:20', '17:22', null, '17:20', false ], + [ '17:22', '300', '17:12', '17:20', 10, '17:12', false ], + [ '17:22', '300', '17:18', '17:20', 2, '17:18', false ], + [ '17:22', '180', '17:00', '17:20', 15, '17:00', false ], + [ '17:22', '180', '17:10', '17:20', 2, '17:16', false ], + // value = "" (NaN). + [ '', null, null, null, null, '23:59', false ], + // With step = 'any'. + [ '17:26', 'any', null, null, 1, null, true ], + [ '17:26', 'ANY', null, null, 1, null, true ], + [ '17:26', 'AnY', null, null, 1, null, true ], + [ '17:26', 'aNy', null, null, 1, null, true ], + ]}, + { type: 'month', data: [ + // Regular case. + [ '2016-08', null, null, null, null, '2016-07', false ], + // Argument testing. + [ '2016-08', null, null, null, 1, '2016-07', false ], + [ '2016-08', null, null, null, 5, '2016-03', false ], + [ '2016-08', null, null, null, -1, '2016-09', false ], + [ '2016-08', null, null, null, 0, '2016-08', false ], + // Month/Year wrapping. + [ '2016-01', null, null, null, 1, '2015-12', false ], + [ '1969-02', null, null, null, 4, '1968-10', false ], + [ '1969-01', null, null, null, -12, '1970-01', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '2016-08', null, null, null, 1.1, '2016-07', false ], + [ '2016-01', null, null, null, 1.9, '2015-12', false ], + // With step values. + [ '2016-03', '0.5', null, null, null, '2016-02', false ], + [ '2016-03', '2', null, null, null, '2016-01', false ], + [ '2016-03', '0.25',null, null, 4, '2015-11', false ], + [ '2016-12', '1.1', '2016-01', null, 1, '2016-11', false ], + [ '2016-12', '1.1', '2016-01', null, 2, '2016-10', false ], + [ '2016-12', '1.1', '2016-01', null, 10, '2016-02', false ], + [ '2016-12', '1.1', '2016-01', null, 12, '2016-01', false ], + [ '1968-12', '1.1', '1968-01', null, 8, '1968-04', false ], + // step = 0 isn't allowed (-> step = 1). + [ '2016-02', '0', null, null, null, '2016-01', false ], + // step < 0 isn't allowed (-> step = 1). + [ '2016-02', '-1', null, null, null, '2016-01', false ], + // step = NaN isn't allowed (-> step = 1). + [ '2016-02', 'foo', null, null, null, '2016-01', false ], + // Min values testing. + [ '2016-03', '1', 'foo', null, 2, '2016-01', false ], + [ '2016-02', '1', '2016-01', null, null, '2016-01', false ], + [ '2016-01', '1', '2016-01', null, null, '2016-01', false ], + [ '2016-01', '1', '2016-01', null, 1, '2016-01', false ], + [ '2016-05', '3', '2016-01', null, null, '2016-04', false ], + [ '1969-01', '5', '1969-01', '1969-02', null, '1969-01', false ], + // Max values testing. + [ '2016-02', '1', null, 'foo', null, '2016-01', false ], + [ '2016-02', null, null, '2016-05', null, '2016-01', false ], + [ '2016-03', null, null, '2016-03', null, '2016-02', false ], + [ '2016-07', null, null, '2016-04', 4, '2016-03', false ], + [ '2016-07', '2', null, '2016-04', 3, '2016-01', false ], + // Step mismatch. + [ '2016-04', '2', '2016-01', null, null, '2016-03', false ], + [ '2016-06', '2', '2016-01', null, 2, '2016-03', false ], + [ '2016-05', '2', '2016-04', '2016-08', null, '2016-04', false ], + [ '1970-04', '2', null, null, null, '1970-02', false ], + [ '1970-09', '3', null, null, null, '1970-06', false ], + // Clamping. + [ '2016-05', null, null, '2016-01', null, '2016-01', false ], + [ '1970-05', '2', '1970-02', '1970-05', null, '1970-04', false ], + [ '1970-01', '5', '1970-02', '1970-09', 10, '1970-01', false ], + [ '1970-07', '5', '1969-12', '1970-10', 2, '1969-12', false ], + [ '1970-08', '3', '1970-01', '1970-07', 15, '1970-01', false ], + [ '1970-10', '3', '1970-01', '1970-06', 2, '1970-04', false ], + // value = "" (NaN). + [ '', null, null, null, null, '1969-12', false ], + // With step = 'any'. + [ '2016-01', 'any', null, null, 1, null, true ], + [ '2016-01', 'ANY', null, null, 1, null, true ], + [ '2016-01', 'AnY', null, null, 1, null, true ], + [ '2016-01', 'aNy', null, null, 1, null, true ], + ]}, + { type: 'week', data: [ + // Regular case. + [ '2016-W40', null, null, null, null, '2016-W39', false ], + // Argument testing. + [ '2016-W40', null, null, null, 1, '2016-W39', false ], + [ '2016-W40', null, null, null, 5, '2016-W35', false ], + [ '2016-W40', null, null, null, -1, '2016-W41', false ], + [ '2016-W40', null, null, null, 0, '2016-W40', false ], + // Week/Year wrapping. + [ '2016-W01', null, null, null, 1, '2015-W53', false ], + [ '1969-W02', null, null, null, 4, '1968-W50', false ], + [ '1969-W01', null, null, null, -52, '1970-W01', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '2016-W40', null, null, null, 1.1, '2016-W39', false ], + [ '2016-W01', null, null, null, 1.9, '2015-W53', false ], + // With step values. + [ '2016-W03', '0.5', null, null, null, '2016-W02', false ], + [ '2016-W03', '2', null, null, null, '2016-W01', false ], + [ '2016-W03', '0.25', null, null, 4, '2015-W52', false ], + [ '2016-W52', '1.1', '2016-W01', null, 1, '2016-W51', false ], + [ '2016-W52', '1.1', '2016-W01', null, 2, '2016-W50', false ], + [ '2016-W52', '1.1', '2016-W01', null, 10, '2016-W42', false ], + [ '2016-W52', '1.1', '2016-W01', null, 52, '2016-W01', false ], + [ '1968-W52', '1.1', '1968-W01', null, 8, '1968-W44', false ], + // step = 0 isn't allowed (-> step = 1). + [ '2016-W02', '0', null, null, null, '2016-W01', false ], + // step < 0 isn't allowed (-> step = 1). + [ '2016-W02', '-1', null, null, null, '2016-W01', false ], + // step = NaN isn't allowed (-> step = 1). + [ '2016-W02', 'foo', null, null, null, '2016-W01', false ], + // Min values testing. + [ '2016-W03', '1', 'foo', null, 2, '2016-W01', false ], + [ '2016-W02', '1', '2016-01', null, null, '2016-W01', false ], + [ '2016-W01', '1', '2016-W01', null, null, '2016-W01', false ], + [ '2016-W01', '1', '2016-W01', null, 1, '2016-W01', false ], + [ '2016-W05', '3', '2016-W01', null, null, '2016-W04', false ], + [ '1969-W01', '5', '1969-W01', '1969-W02', null, '1969-W01', false ], + // Max values testing. + [ '2016-W02', '1', null, 'foo', null, '2016-W01', false ], + [ '2016-W02', null, null, '2016-W05', null, '2016-W01', false ], + [ '2016-W03', null, null, '2016-W03', null, '2016-W02', false ], + [ '2016-W07', null, null, '2016-W04', 4, '2016-W03', false ], + [ '2016-W07', '2', null, '2016-W04', 3, '2016-W01', false ], + // Step mismatch. + [ '2016-W04', '2', '2016-W01', null, null, '2016-W03', false ], + [ '2016-W06', '2', '2016-W01', null, 2, '2016-W03', false ], + [ '2016-W05', '2', '2016-W04', '2016-W08', null, '2016-W04', false ], + [ '1970-W04', '2', null, null, null, '1970-W02', false ], + [ '1970-W09', '3', null, null, null, '1970-W06', false ], + // Clamping. + [ '2016-W05', null, null, '2016-W01', null, '2016-W01', false ], + [ '1970-W05', '2', '1970-W02', '1970-W05', null, '1970-W04', false ], + [ '1970-W01', '5', '1970-W02', '1970-W09', 10, '1970-W01', false ], + [ '1970-W07', '5', '1969-W52', '1970-W10', 2, '1969-W52', false ], + [ '1970-W08', '3', '1970-W01', '1970-W07', 15, '1970-W01', false ], + [ '1970-W10', '3', '1970-W01', '1970-W06', 2, '1970-W04', false ], + // value = "" (NaN). + [ '', null, null, null, null, '1970-W01', false ], + // With step = 'any'. + [ '2016-W01', 'any', null, null, 1, null, true ], + [ '2016-W01', 'ANY', null, null, 1, null, true ], + [ '2016-W01', 'AnY', null, null, 1, null, true ], + [ '2016-W01', 'aNy', null, null, 1, null, true ], + ]}, + ]; + + for (var test of testData) { + for (var data of test.data) { + var element = document.createElement("input"); + element.type = test.type; + + if (data[1] != null) { + element.step = data[1]; + } + + if (data[2] != null) { + element.min = data[2]; + } + + if (data[3] != null) { + element.max = data[3]; + } + + // Set 'value' last for type=range, because the final sanitized value + // after setting 'step', 'min' and 'max' can be affected by the order in + // which those attributes are set. Setting 'value' last makes it simpler + // to reason about what the final value should be. + if (data[0] != null) { + element.setAttribute('value', data[0]); + } + + var exceptionCaught = false; + try { + if (data[4] != null) { + element.stepDown(data[4]); + } else { + element.stepDown(); + } + + is(element.value, data[5], "The value for type=" + test.type + " should be " + data[5]); + } catch (e) { + exceptionCaught = true; + is(element.value, data[0], e.name + "The value should not have changed"); + is(e.name, 'InvalidStateError', + "It should be a InvalidStateError exception."); + } finally { + is(exceptionCaught, data[6], "exception status should be " + data[6]); + } + } + } +} + +function checkStepUp() +{ + // This testData is very similar to the one in checkStepDown with some changes + // relative to stepUp. + var testData = [ + /* Initial value | step | min | max | stepUp arg | final value | exception */ + { type: 'number', data: [ + // Regular case. + [ '1', null, null, null, null, '2', false ], + // Argument testing. + [ '1', null, null, null, 1, '2', false ], + [ '9', null, null, null, 9, '18', false ], + [ '1', null, null, null, -1, '0', false ], + [ '1', null, null, null, 0, '1', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '1', null, null, null, 1.1, '2', false ], + // With step values. + [ '1', '0.5', null, null, null, '1.5', false ], + [ '1', '0.25', null, null, 4, '2', false ], + // step = 0 isn't allowed (-> step = 1). + [ '1', '0', null, null, null, '2', false ], + // step < 0 isn't allowed (-> step = 1). + [ '1', '-1', null, null, null, '2', false ], + // step = NaN isn't allowed (-> step = 1). + [ '1', 'foo', null, null, null, '2', false ], + // Min values testing. + [ '1', '1', 'foo', null, null, '2', false ], + [ '1', null, '-10', null, null, '2', false ], + [ '1', null, '0', null, null, '2', false ], + [ '1', null, '10', null, null, '10', false ], + [ '1', null, '2', null, null, '2', false ], + [ '1', null, '1', null, null, '2', false ], + [ '0', null, '4', null, '5', '5', false ], + [ '0', '2', '5', null, '3', '5', false ], + // Max values testing. + [ '1', '1', null, 'foo', null, '2', false ], + [ '1', null, null, '10', null, '2', false ], + [ '1', null, null, '0', null, '1', false ], + [ '1', null, null, '-10', null, '1', false ], + [ '1', null, null, '1', null, '1', false ], + [ '-3', '5', '-10', '-3', null, '-3', false ], + // Step mismatch. + [ '1', '2', '0', null, null, '2', false ], + [ '1', '2', '0', null, '2', '4', false ], + [ '8', '2', null, '9', null, '8', false ], + [ '-3', '2', '-6', null, null, '-2', false ], + [ '9', '3', '-10', null, null, '11', false ], + [ '7', '3', '-10', null, null, '8', false ], + [ '7', '3', '5', null, null, '8', false ], + [ '9', '4', '3', null, null, '11', false ], + [ '-2', '3', '-6', null, null, '0', false ], + [ '7', '3', '6', null, null, '9', false ], + // Clamping. + [ '1', '2', '0', '3', null, '2', false ], + [ '0', '5', '1', '8', '10', '6', false ], + [ '-9', '3', '-8', '-1', '5', '-2', false ], + [ '-9', '3', '8', '15', '15', '14', false ], + [ '-1', '3', '-1', '4', '3', '2', false ], + [ '-3', '2', '-6', '-2', null, '-2', false ], + [ '-3', '2', '-6', '-1', null, '-2', false ], + // value = "" (NaN). + [ '', null, null, null, null, '1', false ], + [ '', null, null, null, null, '1', false ], + [ '', '2', null, null, null, '2', false ], + [ '', '2', '3', null, null, '3', false ], + [ '', null, '3', null, null, '3', false ], + [ '', '2', '3', '8', null, '3', false ], + [ '', null, '-10', '10', null, '1', false ], + [ '', '3', '-10', '10', null, '2', false ], + // With step = 'any'. + [ '0', 'any', null, null, 1, null, true ], + [ '0', 'ANY', null, null, 1, null, true ], + [ '0', 'AnY', null, null, 1, null, true ], + [ '0', 'aNy', null, null, 1, null, true ], + // With @value = step base. + [ '1', '2', null, null, null, '3', false ], + ]}, + { type: 'range', data: [ + // Regular case. + [ '1', null, null, null, null, '2', false ], + // Argument testing. + [ '1', null, null, null, 1, '2', false ], + [ '9', null, null, null, 9, '18', false ], + [ '1', null, null, null, -1, '0', false ], + [ '1', null, null, null, 0, '1', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '1', null, null, null, 1.1, '2', false ], + // With step values. + [ '1', '0.5', null, null, null, '1.5', false ], + [ '1', '0.25', null, null, 4, '2', false ], + // step = 0 isn't allowed (-> step = 1). + [ '1', '0', null, null, null, '2', false ], + // step < 0 isn't allowed (-> step = 1). + [ '1', '-1', null, null, null, '2', false ], + // step = NaN isn't allowed (-> step = 1). + [ '1', 'foo', null, null, null, '2', false ], + // Min values testing. + [ '1', '1', 'foo', null, null, '2', false ], + [ '1', null, '-10', null, null, '2', false ], + [ '1', null, '0', null, null, '2', false ], + [ '1', null, '10', null, null, '11', false ], + [ '1', null, '2', null, null, '3', false ], + [ '1', null, '1', null, null, '2', false ], + [ '0', null, '4', null, '5', '9', false ], + [ '0', '2', '5', null, '3', '11', false ], + // Max values testing. + [ '1', '1', null, 'foo', null, '2', false ], + [ '1', null, null, '10', null, '2', false ], + [ '1', null, null, '0', null, '0', false ], + [ '1', null, null, '-10', null, '0', false ], + [ '1', null, null, '1', null, '1', false ], + [ '-3', '5', '-10', '-3', null, '-5', false ], + // Step mismatch. + [ '1', '2', '0', null, null, '4', false ], + [ '1', '2', '0', null, '2', '6', false ], + [ '8', '2', null, '9', null, '8', false ], + [ '-3', '2', '-6', null, null, '0', false ], + [ '9', '3', '-10', null, null, '11', false ], + [ '7', '3', '-10', null, null, '11', false ], + [ '7', '3', '5', null, null, '11', false ], + [ '9', '4', '3', null, null, '15', false ], + [ '-2', '3', '-6', null, null, '0', false ], + [ '7', '3', '6', null, null, '9', false ], + // Clamping. + [ '1', '2', '0', '3', null, '2', false ], + [ '0', '5', '1', '8', '10', '6', false ], + [ '-9', '3', '-8', '-1', '5', '-2', false ], + [ '-9', '3', '8', '15', '15', '14', false ], + [ '-1', '3', '-1', '4', '3', '2', false ], + [ '-3', '2', '-6', '-2', null, '-2', false ], + [ '-3', '2', '-6', '-1', null, '-2', false ], + // value = "" (default will be 50). + [ '', null, null, null, null, '51', false ], + // With step = 'any'. + [ '0', 'any', null, null, 1, null, true ], + [ '0', 'ANY', null, null, 1, null, true ], + [ '0', 'AnY', null, null, 1, null, true ], + [ '0', 'aNy', null, null, 1, null, true ], + // With @value = step base. + [ '1', '2', null, null, null, '3', false ], + ]}, + { type: 'date', data: [ + // Regular case. + [ '2012-07-09', null, null, null, null, '2012-07-10', false ], + // Argument testing. + [ '2012-07-09', null, null, null, 1, '2012-07-10', false ], + [ '2012-07-09', null, null, null, 9, '2012-07-18', false ], + [ '2012-07-09', null, null, null, -1, '2012-07-08', false ], + [ '2012-07-09', null, null, null, 0, '2012-07-09', false ], + // Month/Year wrapping. + [ '2012-07-31', null, null, null, 1, '2012-08-01', false ], + [ '1968-12-29', null, null, null, 4, '1969-01-02', false ], + [ '1970-01-01', null, null, null, -365, '1969-01-01', false ], + [ '2012-03-01', null, null, null, -1, '2012-02-29', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '2012-01-01', null, null, null, 1.1, '2012-01-02', false ], + [ '2012-01-01', null, null, null, 1.9, '2012-01-02', false ], + // With step values. + [ '2012-01-01', '0.5', null, null, null, '2012-01-02', false ], + [ '2012-01-01', '2', null, null, null, '2012-01-03', false ], + [ '2012-01-01', '0.25', null, null, 4, '2012-01-05', false ], + [ '2012-01-01', '1.1', '2012-01-01', null, 1, '2012-01-02', false ], + [ '2012-01-01', '1.1', '2012-01-01', null, 2, '2012-01-03', false ], + [ '2012-01-01', '1.1', '2012-01-01', null, 10, '2012-01-11', false ], + [ '2012-01-01', '1.1', '2012-01-01', null, 11, '2012-01-12', false ], + // step = 0 isn't allowed (-> step = 1). + [ '2012-01-01', '0', null, null, null, '2012-01-02', false ], + // step < 0 isn't allowed (-> step = 1). + [ '2012-01-01', '-1', null, null, null, '2012-01-02', false ], + // step = NaN isn't allowed (-> step = 1). + [ '2012-01-01', 'foo', null, null, null, '2012-01-02', false ], + // Min values testing. + [ '2012-01-01', '1', 'foo', null, null, '2012-01-02', false ], + [ '2012-01-01', null, '2011-12-01', null, null, '2012-01-02', false ], + [ '2012-01-01', null, '2012-01-02', null, null, '2012-01-02', false ], + [ '2012-01-01', null, '2012-01-01', null, null, '2012-01-02', false ], + [ '2012-01-01', null, '2012-01-04', null, 4, '2012-01-05', false ], + [ '2012-01-01', '2', '2012-01-04', null, 3, '2012-01-06', false ], + // Max values testing. + [ '2012-01-01', '1', null, 'foo', 2, '2012-01-03', false ], + [ '2012-01-01', '1', null, '2012-01-10', 1, '2012-01-02', false ], + [ '2012-01-02', null, null, '2012-01-01', null, '2012-01-02', false ], + [ '2012-01-02', null, null, '2012-01-02', null, '2012-01-02', false ], + [ '1969-01-02', '5', '1969-01-01', '1969-01-02', null, '1969-01-02', false ], + // Step mismatch. + [ '2012-01-02', '2', '2012-01-01', null, null, '2012-01-03', false ], + [ '2012-01-02', '2', '2012-01-01', null, 2, '2012-01-05', false ], + [ '2012-01-05', '2', '2012-01-01', '2012-01-06', null, '2012-01-05', false ], + [ '1970-01-02', '2', null, null, null, '1970-01-04', false ], + [ '1970-01-05', '3', null, null, null, '1970-01-08', false ], + [ '1970-01-03', '3', null, null, null, '1970-01-06', false ], + [ '1970-01-03', '3', '1970-01-02', null, null, '1970-01-05', false ], + // Clamping. + [ '2012-01-01', null, '2012-01-31', null, null, '2012-01-31', false ], + [ '1970-01-02', '2', '1970-01-01', '1970-01-04', null, '1970-01-03', false ], + [ '1970-01-01', '5', '1970-01-02', '1970-01-09', 10, '1970-01-07', false ], + [ '1969-12-28', '5', '1969-12-29', '1970-01-06', 3, '1970-01-03', false ], + [ '1970-01-01', '3', '1970-02-01', '1970-02-07', 15, '1970-02-07', false ], + [ '1970-01-01', '3', '1970-01-01', '1970-01-06', 2, '1970-01-04', false ], + // value = "" (NaN). + [ '', null, null, null, null, '1970-01-02', false ], + // With step = 'any'. + [ '2012-01-01', 'any', null, null, 1, null, true ], + [ '2012-01-01', 'ANY', null, null, 1, null, true ], + [ '2012-01-01', 'AnY', null, null, 1, null, true ], + [ '2012-01-01', 'aNy', null, null, 1, null, true ], + ]}, + { type: 'time', data: [ + // Regular case. + [ '16:39', null, null, null, null, '16:40', false ], + // Argument testing. + [ '16:40', null, null, null, 1, '16:41', false ], + [ '16:40', null, null, null, 5, '16:45', false ], + [ '16:40', null, null, null, -1, '16:39', false ], + [ '16:40', null, null, null, 0, '16:40', false ], + // hour/minutes/seconds wrapping. + [ '04:59', null, null, null, null, '05:00', false ], + [ '04:59:59', 1, null, null, null, '05:00', false ], + [ '04:59:59.900', 0.1, null, null, null, '05:00', false ], + [ '04:59:59.990', 0.01, null, null, null, '05:00', false ], + [ '04:59:59.999', 0.001, null, null, null, '05:00', false ], + // stepUp() on '23:59' gives '00:00'. + [ '23:59', null, null, null, 1, '00:00', false ], + [ '23:59', null, null, null, 3, '00:02', false ], + // Some random step values.. + [ '16:56', '0.5', null, null, null, '16:56:00.500', false ], + [ '16:56', '2', null, null, null, '16:56:02', false ], + [ '16:56', '0.25',null, null, 4, '16:56:01', false ], + [ '16:57', '1.1', '16:00', null, 1, '16:57:01', false ], + [ '16:57', '1.1', '16:00', null, 2, '16:57:02.100', false ], + [ '16:57', '1.1', '16:00', null, 10, '16:57:10.900', false ], + [ '16:57', '1.1', '16:00', null, 11, '16:57:12', false ], + [ '16:57', '1.1', '16:00', null, 8, '16:57:08.700', false ], + // Invalid @step, means that we use the default value. + [ '17:01', '0', null, null, null, '17:02', false ], + [ '17:01', '-1', null, null, null, '17:02', false ], + [ '17:01', 'foo', null, null, null, '17:02', false ], + // Min values testing. + [ '17:02', '60', 'foo', null, 2, '17:04', false ], + [ '17:10', '60', '17:09', null, null, '17:11', false ], + [ '17:10', '60', '17:10', null, null, '17:11', false ], + [ '17:10', '60', '17:30', null, 1, '17:30', false ], + [ '17:10', '180', '17:05', null, null, '17:11', false ], + [ '17:10', '300', '17:10', '17:11', null,'17:10', false ], + // Max values testing. + [ '17:15', '60', null, 'foo', null, '17:16', false ], + [ '17:15', null, null, '17:20', null, '17:16', false ], + [ '17:15', null, null, '17:15', null, '17:15', false ], + [ '17:15', null, null, '17:13', 4, '17:15', false ], + [ '17:15', '120', null, '17:13', 3, '17:15', false ], + // Step mismatch. + [ '17:19', '120', '17:10', null, null, '17:20', false ], + [ '17:19', '120', '17:10', null, 2, '17:22', false ], + [ '17:19', '120', '17:18', '17:25', null, '17:20', false ], + [ '17:19', '120', null, null, null, '17:21', false ], + [ '17:19', '180', null, null, null, '17:22', false ], + // Clamping. + [ '17:22', null, null, '17:11', null, '17:22', false ], + [ '17:22', '120', '17:20', '17:22', null, '17:22', false ], + [ '17:22', '300', '17:12', '17:20', 10, '17:22', false ], + [ '17:22', '300', '17:18', '17:20', 2, '17:22', false ], + [ '17:22', '180', '17:00', '17:20', 15, '17:22', false ], + [ '17:22', '180', '17:10', '17:20', 2, '17:22', false ], + // value = "" (NaN). + [ '', null, null, null, null, '00:01', false ], + // With step = 'any'. + [ '17:26', 'any', null, null, 1, null, true ], + [ '17:26', 'ANY', null, null, 1, null, true ], + [ '17:26', 'AnY', null, null, 1, null, true ], + [ '17:26', 'aNy', null, null, 1, null, true ], + ]}, + { type: 'month', data: [ + // Regular case. + [ '2016-08', null, null, null, null, '2016-09', false ], + // Argument testing. + [ '2016-08', null, null, null, 1, '2016-09', false ], + [ '2016-08', null, null, null, 9, '2017-05', false ], + [ '2016-08', null, null, null, -1, '2016-07', false ], + [ '2016-08', null, null, null, 0, '2016-08', false ], + // Month/Year wrapping. + [ '2015-12', null, null, null, 1, '2016-01', false ], + [ '1968-12', null, null, null, 4, '1969-04', false ], + [ '1970-01', null, null, null, -12, '1969-01', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '2016-01', null, null, null, 1.1, '2016-02', false ], + [ '2016-01', null, null, null, 1.9, '2016-02', false ], + // With step values. + [ '2016-01', '0.5', null, null, null, '2016-02', false ], + [ '2016-01', '2', null, null, null, '2016-03', false ], + [ '2016-01', '0.25', null, null, 4, '2016-05', false ], + [ '2016-01', '1.1', '2016-01', null, 1, '2016-02', false ], + [ '2016-01', '1.1', '2016-01', null, 2, '2016-03', false ], + [ '2016-01', '1.1', '2016-01', null, 10, '2016-11', false ], + [ '2016-01', '1.1', '2016-01', null, 11, '2016-12', false ], + // step = 0 isn't allowed (-> step = 1). + [ '2016-01', '0', null, null, null, '2016-02', false ], + // step < 0 isn't allowed (-> step = 1). + [ '2016-01', '-1', null, null, null, '2016-02', false ], + // step = NaN isn't allowed (-> step = 1). + [ '2016-01', 'foo', null, null, null, '2016-02', false ], + // Min values testing. + [ '2016-01', '1', 'foo', null, null, '2016-02', false ], + [ '2016-01', null, '2015-12', null, null, '2016-02', false ], + [ '2016-01', null, '2016-02', null, null, '2016-02', false ], + [ '2016-01', null, '2016-01', null, null, '2016-02', false ], + [ '2016-01', null, '2016-04', null, 4, '2016-05', false ], + [ '2016-01', '2', '2016-04', null, 3, '2016-06', false ], + // Max values testing. + [ '2016-01', '1', null, 'foo', 2, '2016-03', false ], + [ '2016-01', '1', null, '2016-02', 1, '2016-02', false ], + [ '2016-02', null, null, '2016-01', null, '2016-02', false ], + [ '2016-02', null, null, '2016-02', null, '2016-02', false ], + [ '1969-02', '5', '1969-01', '1969-02', null, '1969-02', false ], + // Step mismatch. + [ '2016-02', '2', '2016-01', null, null, '2016-03', false ], + [ '2016-02', '2', '2016-01', null, 2, '2016-05', false ], + [ '2016-05', '2', '2016-01', '2016-06', null, '2016-05', false ], + [ '1970-02', '2', null, null, null, '1970-04', false ], + [ '1970-05', '3', null, null, null, '1970-08', false ], + [ '1970-03', '3', null, null, null, '1970-06', false ], + [ '1970-03', '3', '1970-02', null, null, '1970-05', false ], + // Clamping. + [ '2016-01', null, '2016-12', null, null, '2016-12', false ], + [ '1970-02', '2', '1970-01', '1970-04', null, '1970-03', false ], + [ '1970-01', '5', '1970-02', '1970-09', 10, '1970-07', false ], + [ '1969-11', '5', '1969-12', '1970-06', 3, '1970-05', false ], + [ '1970-01', '3', '1970-02', '1971-07', 15, '1971-05', false ], + [ '1970-01', '3', '1970-01', '1970-06', 2, '1970-04', false ], + // value = "" (NaN). + [ '', null, null, null, null, '1970-02', false ], + // With step = 'any'. + [ '2016-01', 'any', null, null, 1, null, true ], + [ '2016-01', 'ANY', null, null, 1, null, true ], + [ '2016-01', 'AnY', null, null, 1, null, true ], + [ '2016-01', 'aNy', null, null, 1, null, true ], + ]}, + { type: 'week', data: [ + // Regular case. + [ '2016-W40', null, null, null, null, '2016-W41', false ], + // Argument testing. + [ '2016-W40', null, null, null, 1, '2016-W41', false ], + [ '2016-W40', null, null, null, 20, '2017-W08', false ], + [ '2016-W40', null, null, null, -1, '2016-W39', false ], + [ '2016-W40', null, null, null, 0, '2016-W40', false ], + // Week/Year wrapping. + [ '2015-W53', null, null, null, 1, '2016-W01', false ], + [ '1968-W52', null, null, null, 4, '1969-W04', false ], + [ '1970-W01', null, null, null, -52, '1969-W01', false ], + // Float values are rounded to integer (1.1 -> 1). + [ '2016-W01', null, null, null, 1.1, '2016-W02', false ], + [ '2016-W01', null, null, null, 1.9, '2016-W02', false ], + // With step values. + [ '2016-W01', '0.5', null, null, null, '2016-W02', false ], + [ '2016-W01', '2', null, null, null, '2016-W03', false ], + [ '2016-W01', '0.25', null, null, 4, '2016-W05', false ], + [ '2016-W01', '1.1', '2016-01', null, 1, '2016-W02', false ], + [ '2016-W01', '1.1', '2016-01', null, 2, '2016-W03', false ], + [ '2016-W01', '1.1', '2016-01', null, 10, '2016-W11', false ], + [ '2016-W01', '1.1', '2016-01', null, 20, '2016-W21', false ], + // step = 0 isn't allowed (-> step = 1). + [ '2016-W01', '0', null, null, null, '2016-W02', false ], + // step < 0 isn't allowed (-> step = 1). + [ '2016-W01', '-1', null, null, null, '2016-W02', false ], + // step = NaN isn't allowed (-> step = 1). + [ '2016-W01', 'foo', null, null, null, '2016-W02', false ], + // Min values testing. + [ '2016-W01', '1', 'foo', null, null, '2016-W02', false ], + [ '2016-W01', null, '2015-W53', null, null, '2016-W02', false ], + [ '2016-W01', null, '2016-W02', null, null, '2016-W02', false ], + [ '2016-W01', null, '2016-W01', null, null, '2016-W02', false ], + [ '2016-W01', null, '2016-W04', null, 4, '2016-W05', false ], + [ '2016-W01', '2', '2016-W04', null, 3, '2016-W06', false ], + // Max values testing. + [ '2016-W01', '1', null, 'foo', 2, '2016-W03', false ], + [ '2016-W01', '1', null, '2016-W02', 1, '2016-W02', false ], + [ '2016-W02', null, null, '2016-W01', null, '2016-W02', false ], + [ '2016-W02', null, null, '2016-W02', null, '2016-W02', false ], + [ '1969-W02', '5', '1969-W01', '1969-W02', null, '1969-W02', false ], + // Step mismatch. + [ '2016-W02', '2', '2016-W01', null, null, '2016-W03', false ], + [ '2016-W02', '2', '2016-W01', null, 2, '2016-W05', false ], + [ '2016-W05', '2', '2016-W01', '2016-W06', null, '2016-W05', false ], + [ '1970-W02', '2', null, null, null, '1970-W04', false ], + [ '1970-W05', '3', null, null, null, '1970-W08', false ], + [ '1970-W03', '3', null, null, null, '1970-W06', false ], + [ '1970-W03', '3', '1970-W02', null, null, '1970-W05', false ], + // Clamping. + [ '2016-W01', null, '2016-W52', null, null, '2016-W52', false ], + [ '1970-W02', '2', '1970-W01', '1970-W04', null, '1970-W03', false ], + [ '1970-W01', '5', '1970-W02', '1970-W09', 10, '1970-W07', false ], + [ '1969-W50', '5', '1969-W52', '1970-W06', 3, '1970-W05', false ], + [ '1970-W01', '3', '1970-W02', '1971-W07', 15, '1970-W44', false ], + [ '1970-W01', '3', '1970-W01', '1970-W06', 2, '1970-W04', false ], + // value = "" (NaN). + [ '', null, null, null, null, '1970-W02', false ], + // With step = 'any'. + [ '2016-W01', 'any', null, null, 1, null, true ], + [ '2016-W01', 'ANY', null, null, 1, null, true ], + [ '2016-W01', 'AnY', null, null, 1, null, true ], + [ '2016-W01', 'aNy', null, null, 1, null, true ], + ]}, + ]; + + for (var test of testData) { + for (var data of test.data) { + var element = document.createElement("input"); + element.type = test.type; + + if (data[1] != null) { + element.step = data[1]; + } + + if (data[2] != null) { + element.min = data[2]; + } + + if (data[3] != null) { + element.max = data[3]; + } + + // Set 'value' last for type=range, because the final sanitized value + // after setting 'step', 'min' and 'max' can be affected by the order in + // which those attributes are set. Setting 'value' last makes it simpler + // to reason about what the final value should be. + if (data[0] != null) { + element.setAttribute('value', data[0]); + } + + var exceptionCaught = false; + try { + if (data[4] != null) { + element.stepUp(data[4]); + } else { + element.stepUp(); + } + + is(element.value, data[5], "The value for type=" + test.type + " should be " + data[5]); + } catch (e) { + exceptionCaught = true; + is(element.value, data[0], e.name + "The value should not have changed"); + is(e.name, 'InvalidStateError', + "It should be a InvalidStateError exception."); + } finally { + is(exceptionCaught, data[6], "exception status should be " + data[6]); + } + } + } +} + +checkPresence(); +checkAvailability(); + +checkStepDown(); +checkStepUp(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_submit_invalid_file.html b/dom/html/test/forms/test_submit_invalid_file.html new file mode 100644 index 000000000..3941bf2b6 --- /dev/null +++ b/dom/html/test/forms/test_submit_invalid_file.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=702949 +--> +<head> + <meta charset="utf-8"> + <title>Test invalid file submission</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=702949">Mozilla Bug 702949</a> +<p id="display"></p> +<div id="content" style="display: none"> + <form action='http://mochi.test:8888/chrome/dom/html/test/forms/submit_invalid_file.sjs' method='post' target='result' + enctype='multipart/form-data'> + <input type='file' name='file'> + </form> + <iframe name='result'></iframe> +</div> +<pre id="test"> +</pre> +<script type="application/javascript"> + /* + * Test invalid file submission by submitting a file that has been deleted + * from the file system before the form has been submitted. + * The form submission triggers a sjs file that shows its output in a frame. + * That means the test might time out if it fails. + */ + + SimpleTest.waitForExplicitFinish(); + addLoadEvent(function() { + var FileUtils = SpecialPowers.Cu.import("resource://gre/modules/FileUtils.jsm").FileUtils; + + var i = document.getElementsByTagName('input')[0]; + + var file = FileUtils.getDir("TmpD", [], false); + file.append("testfile"); + file.createUnique(SpecialPowers.Ci.nsIFile.NORMAL_FILE_TYPE, 0644); + + SpecialPowers.wrap(i).value = file.path; + file.remove(/* recursive = */ false); + + document.getElementsByName('result')[0].addEventListener('load', function() { + is(window.frames[0].document.body.textContent, "SUCCESS"); + SimpleTest.finish(); + }); + document.forms[0].submit(); + }); +</script> +</body> +</html> diff --git a/dom/html/test/forms/test_textarea_attributes_reflection.html b/dom/html/test/forms/test_textarea_attributes_reflection.html new file mode 100644 index 000000000..a285b9955 --- /dev/null +++ b/dom/html/test/forms/test_textarea_attributes_reflection.html @@ -0,0 +1,104 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLTextAreaElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="../reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLTextAreaElement attributes reflection **/ + +// .autofocus +reflectBoolean({ + element: document.createElement("textarea"), + attribute: "autofocus", +}); + +//.cols +reflectUnsignedInt({ + element: document.createElement("textarea"), + attribute: "cols", + nonZero: true, + defaultValue: 20, + fallback: true, +}); + +todo("dirName" in document.createElement("textarea"), + "dirName isn't implemented yet"); + +// .disabled +reflectBoolean({ + element: document.createElement("textarea"), + attribute: "disabled", +}); + +// TODO: form (HTMLFormElement) + +// .maxLength +reflectInt({ + element: document.createElement("textarea"), + attribute: "maxLength", + nonNegative: true, +}); + +// .name +reflectString({ + element: document.createElement("textarea"), + attribute: "name", + otherValues: [ "isindex", "_charset_" ], +}); + +// .placeholder +reflectString({ + element: document.createElement("textarea"), + attribute: "placeholder", + otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ], +}); + +// .readOnly +reflectBoolean({ + element: document.createElement("textarea"), + attribute: "readOnly", +}); + +// .required +reflectBoolean({ + element: document.createElement("textarea"), + attribute: "required", +}); + +// .rows +reflectUnsignedInt({ + element: document.createElement("textarea"), + attribute: "rows", + nonZero: true, + defaultValue: 2, + fallback: true, +}); + +// .wrap +// TODO: make it an enumerated attributes limited to only known values, bug 670869. +reflectString({ + element: document.createElement("textarea"), + attribute: "wrap", + otherValues: [ "soft", "hard" ], +}); + +// .type doesn't reflect a content attribute. +// .defaultValue doesn't reflect a content attribute. +// .value doesn't reflect a content attribute. +// .textLength doesn't reflect a content attribute. +// .willValidate doesn't reflect a content attribute. +// .validity doesn't reflect a content attribute. +// .validationMessage doesn't reflect a content attribute. +// .labels doesn't reflect a content attribute. + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_validation.html b/dom/html/test/forms/test_validation.html new file mode 100644 index 000000000..ee0a93a99 --- /dev/null +++ b/dom/html/test/forms/test_validation.html @@ -0,0 +1,358 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=345624 +--> +<head> + <title>Test for Bug 345624</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input, textarea, fieldset, button, select, keygen, output, object { background-color: rgb(0,0,0) !important; } + :valid { background-color: rgb(0,255,0) !important; } + :invalid { background-color: rgb(255,0,0) !important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a> +<p id="display"></p> +<div id="content" style="display: none"> + <fieldset id='f'></fieldset> + <input id='i' oninvalid="invalidEventHandler(event);"> + <button id='b' oninvalid="invalidEventHandler(event);"></button> + <select id='s' oninvalid="invalidEventHandler(event);"></select> + <textarea id='t' oninvalid="invalidEventHandler(event);"></textarea> + <output id='o' oninvalid="invalidEventHandler(event);"></output> + <keygen id='k'></keygen> + <object id='obj'></object> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 345624 **/ + +var gInvalid = false; + +function invalidEventHandler(aEvent) +{ + function checkInvalidEvent(aEvent) + { + is(aEvent.type, "invalid", "Invalid event type should be invalid"); + ok(!aEvent.bubbles, "Invalid event should not bubble"); + ok(aEvent.cancelable, "Invalid event should be cancelable"); + } + + checkInvalidEvent(aEvent); + + gInvalid = true; +} + +function checkConstraintValidationAPIExist(element) +{ + ok('willValidate' in element, "willValidate is not available in the DOM"); + ok('validationMessage' in element, "validationMessage is not available in the DOM"); + ok('validity' in element, "validity is not available in the DOM"); + + if ('validity' in element) { + validity = element.validity; + ok('valueMissing' in validity, "validity.valueMissing is not available in the DOM"); + ok('typeMismatch' in validity, "validity.typeMismatch is not available in the DOM"); + ok('badInput' in validity, "validity.badInput is not available in the DOM"); + ok('patternMismatch' in validity, "validity.patternMismatch is not available in the DOM"); + ok('tooLong' in validity, "validity.tooLong is not available in the DOM"); + ok('rangeUnderflow' in validity, "validity.rangeUnderflow is not available in the DOM"); + ok('rangeOverflow' in validity, "validity.rangeOverflow is not available in the DOM"); + ok('stepMismatch' in validity, "validity.stepMismatch is not available in the DOM"); + ok('customError' in validity, "validity.customError is not available in the DOM"); + ok('valid' in validity, "validity.valid is not available in the DOM"); + } +} + +function checkConstraintValidationAPIDefaultValues(element) +{ + // Not checking willValidate because the default value depends of the element + + is(element.validationMessage, "", "validationMessage default value should be empty string"); + + ok(!element.validity.valueMissing, "The element should not suffer from a constraint validation"); + ok(!element.validity.typeMismatch, "The element should not suffer from a constraint validation"); + ok(!element.validity.badInput, "The element should not suffer from a constraint validation"); + ok(!element.validity.patternMismatch, "The element should not suffer from a constraint validation"); + ok(!element.validity.tooLong, "The element should not suffer from a constraint validation"); + ok(!element.validity.rangeUnderflow, "The element should not suffer from a constraint validation"); + ok(!element.validity.rangeOverflow, "The element should not suffer from a constraint validation"); + ok(!element.validity.stepMismatch, "The element should not suffer from a constraint validation"); + ok(!element.validity.customError, "The element should not suffer from a constraint validation"); + ok(element.validity.valid, "The element should be valid by default"); + + ok(element.checkValidity(), "The element should be valid by default"); +} + +function checkDefaultPseudoClass() +{ + is(window.getComputedStyle(document.getElementById('f'), null) + .getPropertyValue('background-color'), "rgb(0, 255, 0)", + ":valid should apply"); + + is(window.getComputedStyle(document.getElementById('o'), null) + .getPropertyValue('background-color'), "rgb(0, 255, 0)", + ":valid should apply"); + + is(window.getComputedStyle(document.getElementById('obj'), null) + .getPropertyValue('background-color'), "rgb(0, 0, 0)", + "Nor :valid and :invalid should apply"); + + todo_is(window.getComputedStyle(document.getElementById('k'), null) + .getPropertyValue('background-color'), "rgb(0, 0, 0)", + "Nor :valid and :invalid should apply"); + + is(window.getComputedStyle(document.getElementById('s'), null) + .getPropertyValue('background-color'), "rgb(0, 255, 0)", + ":valid pseudo-class should apply"); + + is(window.getComputedStyle(document.getElementById('i'), null) + .getPropertyValue('background-color'), "rgb(0, 255, 0)", + ":valid pseudo-class should apply"); + + is(window.getComputedStyle(document.getElementById('t'), null) + .getPropertyValue('background-color'), "rgb(0, 255, 0)", + ":valid pseudo-class should apply"); + + is(window.getComputedStyle(document.getElementById('b'), null) + .getPropertyValue('background-color'), "rgb(0, 255, 0)", + ":valid pseudo-class should apply"); +} + +function checkSpecificWillValidate() +{ + // fieldset, output, object, keygen (TODO) and select elements + ok(!document.getElementById('f').willValidate, "Fielset element should be barred from constraint validation"); + ok(!document.getElementById('obj').willValidate, "Object element should be barred from constraint validation"); + todo(!document.getElementById('k').willValidate, "Keygen element should be barred from constraint validation"); + ok(document.getElementById('o').willValidate, "Output element should not be barred from constraint validation"); + ok(document.getElementById('s').willValidate, "Select element should not be barred from constraint validation"); + + // input element + i = document.getElementById('i'); + i.type = "hidden"; + ok(!i.willValidate, "Hidden state input should be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + i.type = "reset"; + ok(!i.willValidate, "Reset button state input should be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + i.type = "button"; + ok(!i.willValidate, "Button state input should be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + i.type = "image"; + ok(i.willValidate, "Image state input should not be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid and :invalid should apply"); + i.type = "submit"; + ok(i.willValidate, "Submit state input should not be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid and :invalid should apply"); + i.type = "number"; + ok(i.willValidate, "Number state input should not be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + i.type = ""; + i.readOnly = 'true'; + ok(!i.willValidate, "Readonly input should be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + i.removeAttribute('readOnly'); + ok(i.willValidate, "Default input element should not be barred from constraint validation"); + is(window.getComputedStyle(i, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + + // button element + b = document.getElementById('b'); + b.type = "reset"; + ok(!b.willValidate, "Reset state button should be barred from constraint validation"); + is(window.getComputedStyle(b, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + b.type = "button"; + ok(!b.willValidate, "Button state button should be barred from constraint validation"); + is(window.getComputedStyle(b, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + b.type = "submit"; + ok(b.willValidate, "Submit state button should not be barred from constraint validation"); + is(window.getComputedStyle(b, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid and :invalid should apply"); + b.type = ""; + ok(b.willValidate, "Default button element should not be barred from constraint validation"); + is(window.getComputedStyle(b, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + + // textarea element + t = document.getElementById('t'); + t.readOnly = true; + ok(!t.willValidate, "Readonly textarea should be barred from constraint validation"); + is(window.getComputedStyle(t, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + t.removeAttribute('readOnly'); + ok(t.willValidate, "Default textarea element should not be barred from constraint validation"); + is(window.getComputedStyle(t, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); + + // TODO: PROGRESS + // TODO: METER +} + +function checkCommonWillValidate(element) +{ + // Not checking the default value because it has been checked previously. + + // Not checking output elements because they can't be disabled. + if (element.tagName != 'OUTPUT') { + element.disabled = true; + ok(!element.willValidate, "Disabled element should be barred from constraint validation"); + + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 0, 0)", "Nor :valid and :invalid should apply"); + + element.removeAttribute('disabled'); + } + + // TODO: If an element has a datalist element ancestor, it is barred from constraint validation. +} + +function checkCustomError(element, isBarred) +{ + element.setCustomValidity("message"); + if (!isBarred) { + is(element.validationMessage, "message", + "When the element has a custom validity message, validation message should return it"); + } else { + is(element.validationMessage, "", + "An element barred from constraint validation can't have a validation message"); + } + ok(element.validity.customError, "The element should suffer from a custom error"); + ok(!element.validity.valid, "The element should not be valid with a custom error"); + + if (element.tagName == "FIELDSET") { + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + isBarred ? "rgb(0, 255, 0)" : "rgb(255, 0, 0)", + ":invalid pseudo-classs should apply" + element.tagName); + } + else { + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + isBarred ? "rgb(0, 0, 0)" : "rgb(255, 0, 0)", + ":invalid pseudo-classs should apply" + element.tagName); + } + + element.setCustomValidity(""); + is(element.validationMessage, "", "The element should not have a validation message when reseted"); + ok(!element.validity.customError, "The element should not suffer anymore from a custom error"); + ok(element.validity.valid, "The element should now be valid"); + + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + isBarred && element.tagName != "FIELDSET" ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)", + ":valid pseudo-classs should apply"); +} + +function checkCheckValidity(element) +{ + element.setCustomValidity("message"); + ok(!element.checkValidity(), "checkValidity() should return false when the element is not valid"); + + ok(gInvalid, "Invalid event should have been handled"); + + gInvalid = false; + element.setCustomValidity(""); + + ok(element.checkValidity(), "Element should be valid"); + ok(!gInvalid, "Invalid event should not have been handled"); +} + +function checkValidityStateObjectAliveWithoutElement(element) +{ + // We are creating a temporary element and getting it's ValidityState object. + // Then, we make sure it is removed by the garbage collector and we check the + // ValidityState default values (it should not crash). + + var v = document.createElement(element).validity; + SpecialPowers.gc(); + + ok(!v.valueMissing, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.typeMismatch, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.badInput, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.patternMismatch, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.tooLong, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.rangeUnderflow, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.rangeOverflow, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.stepMismatch, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(!v.customError, + "When the element is not alive, it shouldn't suffer from constraint validation"); + ok(v.valid, "When the element is not alive, it should be valid"); +} + +checkConstraintValidationAPIExist(document.getElementById('f')); +checkConstraintValidationAPIExist(document.getElementById('i')); +checkConstraintValidationAPIExist(document.getElementById('b')); +checkConstraintValidationAPIExist(document.getElementById('s')); +checkConstraintValidationAPIExist(document.getElementById('t')); +checkConstraintValidationAPIExist(document.getElementById('k')); +checkConstraintValidationAPIExist(document.getElementById('o')); +checkConstraintValidationAPIExist(document.getElementById('obj')); + +checkConstraintValidationAPIDefaultValues(document.getElementById('f')); +checkConstraintValidationAPIDefaultValues(document.getElementById('i')); +checkConstraintValidationAPIDefaultValues(document.getElementById('b')); +checkConstraintValidationAPIDefaultValues(document.getElementById('s')); +checkConstraintValidationAPIDefaultValues(document.getElementById('t')); +checkConstraintValidationAPIDefaultValues(document.getElementById('k')); +checkConstraintValidationAPIDefaultValues(document.getElementById('o')); +checkConstraintValidationAPIDefaultValues(document.getElementById('obj')); + +checkDefaultPseudoClass(); + +checkSpecificWillValidate(); + +// Not checking button, fieldset, object and keygen +// because they are always barred from constraint validation. +checkCommonWillValidate(document.getElementById('i')); +checkCommonWillValidate(document.getElementById('s')); +checkCommonWillValidate(document.getElementById('t')); +checkCommonWillValidate(document.getElementById('o')); + +/* TODO: add "keygen" element */ +checkCustomError(document.getElementById('i'), false); +checkCustomError(document.getElementById('s'), false); +checkCustomError(document.getElementById('t'), false); +checkCustomError(document.getElementById('o'), false); +checkCustomError(document.getElementById('b'), false); +checkCustomError(document.getElementById('f'), true); +checkCustomError(document.getElementById('obj'), true); + +// Not checking button, fieldset, object and keygen +// because they are always barred from constraint validation. +checkCheckValidity(document.getElementById('i')); +checkCheckValidity(document.getElementById('s')); +checkCheckValidity(document.getElementById('t')); +checkCheckValidity(document.getElementById('o')); + +/* TODO: add "keygen" element */ +checkValidityStateObjectAliveWithoutElement("fieldset"); +checkValidityStateObjectAliveWithoutElement("input"); +checkValidityStateObjectAliveWithoutElement("button"); +checkValidityStateObjectAliveWithoutElement("select"); +checkValidityStateObjectAliveWithoutElement("textarea"); +checkValidityStateObjectAliveWithoutElement("output"); +checkValidityStateObjectAliveWithoutElement("object"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_validation_not_in_doc.html b/dom/html/test/forms/test_validation_not_in_doc.html new file mode 100644 index 000000000..1500c6086 --- /dev/null +++ b/dom/html/test/forms/test_validation_not_in_doc.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for constraint validation of form controls not in documents</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var input = document.createElement('input'); + input.required = true; + assert_false(input.checkValidity()); +}, "Should validate input not in document"); + +test(function() { + var textarea = document.createElement('textarea'); + textarea.required = true; + assert_false(textarea.checkValidity()); +}, "Should validate textarea not in document"); +</script> diff --git a/dom/html/test/forms/test_valueAsDate_pref.html b/dom/html/test/forms/test_valueAsDate_pref.html new file mode 100644 index 000000000..8518c291b --- /dev/null +++ b/dom/html/test/forms/test_valueAsDate_pref.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=874640 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 874640</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 874640 **/ + var states = [ + // dom.experimental_forms, dom.forms.datepicker, dom.forms.datetime, expectedValueAsDate + [ 'true', 'true', 'true', 'true' ], + [ 'true', 'false', 'false', 'true' ], + [ 'false', 'true', 'false', 'true' ], + [ 'false', 'false', 'true', 'true' ], + [ 'false', 'false', 'false', 'false' ], + 'end' + ]; + + SimpleTest.waitForExplicitFinish(); + + function runTest(iframe) { + var state = states.shift(); + + if (state == 'end') { + SimpleTest.finish(); + return; + } + + SpecialPowers.pushPrefEnv({"set":[ + ["dom.experimental_forms", state[0] === 'true'], + ["dom.forms.datepicker", state[1] === 'true'], + ["dom.forms.datetime", state[2] === 'true']]}, + function() { + iframe.src = 'data:text/html,<script>' + + 'parent.is("valueAsDate" in document.createElement("input"), ' + + state[3] + ', "valueAsDate presence state should be ' + state[3] + '");' + + '<\/script>' + }); + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=874640">Mozilla Bug 874640</a> +<p id="display"></p> +<div id="content" style="display: none"> + <iframe onload='runTest(this);'></iframe> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/forms/test_valueasdate_attribute.html b/dom/html/test/forms/test_valueasdate_attribute.html new file mode 100644 index 000000000..8c19fefd9 --- /dev/null +++ b/dom/html/test/forms/test_valueasdate_attribute.html @@ -0,0 +1,649 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=769370 +--> +<head> + <title>Test for input.valueAsDate</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=769370">Mozilla Bug 769370</a> +<iframe name="testFrame" style="display: none"></iframe> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 769370**/ + +/** + * This test is checking .valueAsDate. + */ + +var element = document.createElement("input"); + +var validTypes = +[ + ["text", false], + ["password", false], + ["search", false], + ["tel", false], + ["email", false], + ["url", false], + ["hidden", false], + ["checkbox", false], + ["radio", false], + ["file", false], + ["submit", false], + ["image", false], + ["reset", false], + ["button", false], + ["number", false], + ["range", false], + ["date", true], + ["time", true], + ["color", false], + ["month", true], + ["week", true], + // TODO: temporary set to false until bug 888331 is fixed. + ["datetime-local", false], +]; + +function checkAvailability() +{ + for (let data of validTypes) { + var exceptionCatched = false; + element.type = data[0]; + try { + element.valueAsDate; + } catch (e) { + exceptionCatched = true; + } + is(exceptionCatched, false, + "valueAsDate shouldn't throw exception on getting"); + + exceptionCatched = false; + try { + element.valueAsDate = new Date(); + } catch (e) { + exceptionCatched = true; + } + is(exceptionCatched, !data[1], "valueAsDate for " + data[0] + + " availability is not correct"); + } +} + +function checkGarbageValues() +{ + for (let type of validTypes) { + if (!type[1]) { + continue; + } + type = type[0]; + + var element = document.createElement('input'); + element.type = type; + + element.value = "test"; + element.valueAsDate = null; + is(element.value, "", "valueAsDate should set the value to the empty string"); + + element.value = "test"; + element.valueAsDate = undefined; + is(element.value, "", "valueAsDate should set the value to the empty string"); + + element.value = "test"; + element.valueAsDate = new Date(NaN); + is(element.value, "", "valueAsDate should set the value to the empty string"); + + var illegalValues = [ + "foobar", 42, {}, function() { return 42; }, function() { return Date(); } + ]; + + for (let value of illegalValues) { + try { + var caught = false; + element.valueAsDate = value; + } catch(e) { + is(e.name, "TypeError", "Exception should be 'TypeError'."); + caught = true; + } + ok(caught, "Assigning " + value + " to .valueAsDate should throw"); + } + } +} + +function checkDateGet() +{ + var validData = + [ + [ "2012-07-12", 1342051200000 ], + [ "1970-01-01", 0 ], + [ "1970-01-02", 86400000 ], + [ "1969-12-31", -86400000 ], + [ "0311-01-31", -52350451200000 ], + [ "275760-09-13", 8640000000000000 ], + [ "0001-01-01", -62135596800000 ], + [ "2012-02-29", 1330473600000 ], + [ "2011-02-28", 1298851200000 ], + ]; + + var invalidData = + [ + [ "invaliddate" ], + [ "-001-12-31" ], + [ "901-12-31" ], + [ "1901-13-31" ], + [ "1901-12-32" ], + [ "1901-00-12" ], + [ "1901-01-00" ], + [ "1900-02-29" ], + [ "0000-01-01" ], + [ "" ], + // This date is valid for the input element, but is out of + // the date object range. In this case, on getting valueAsDate, + // a Date object will be created, but it will have a NaN internal value, + // and will return the string "Invalid Date". + [ "275760-09-14", true ], + ]; + + element.type = "date"; + for (let data of validData) { + element.value = data[0]; + is(element.valueAsDate.valueOf(), data[1], + "valueAsDate should return the " + + "valid date object representing this date"); + } + + for (let data of invalidData) { + element.value = data[0]; + if (data[1]) { + is(String(element.valueAsDate), "Invalid Date", + "valueAsDate should return an invalid Date object " + + "when the element value is not a valid date"); + } else { + is(element.valueAsDate, null, + "valueAsDate should return null " + + "when the element value is not a valid date"); + } + } +} + +function checkDateSet() +{ + var testData = + [ + [ 1342051200000, "2012-07-12" ], + [ 0, "1970-01-01" ], + // Maximum valid date (limited by the ecma date object range). + [ 8640000000000000, "275760-09-13" ], + // Minimum valid date (limited by the input element minimum valid value). + [ -62135596800000 , "0001-01-01" ], + [ 1330473600000, "2012-02-29" ], + [ 1298851200000, "2011-02-28" ], + // "Values must be truncated to valid dates" + [ 42.1234, "1970-01-01" ], + [ 123.123456789123, "1970-01-01" ], + [ 1e-1, "1970-01-01" ], + [ 1298851200010, "2011-02-28" ], + [ -1, "1969-12-31" ], + [ -86400000, "1969-12-31" ], + [ 86400000, "1970-01-02" ], + // Negative years, this is out of range for the input element, + // the corresponding date string is the empty string + [ -62135596800001, "" ], + // Invalid dates. + ]; + + element.type = "date"; + for (let data of testData) { + element.valueAsDate = new Date(data[0]); + is(element.value, data[1], "valueAsDate should set the value to " + + data[1]); + element.valueAsDate = new testFrame.Date(data[0]); + is(element.value, data[1], "valueAsDate with other-global date should " + + "set the value to " + data[1]); + } +} + +function checkTimeGet() +{ + var tests = [ + // Some invalid values to begin. + { value: "", result: null }, + { value: "foobar", result: null }, + { value: "00:", result: null }, + { value: "24:00", result: null }, + { value: "00:99", result: null }, + { value: "00:00:", result: null }, + { value: "00:00:99", result: null }, + { value: "00:00:00:", result: null }, + { value: "00:00:00.", result: null }, + { value: "00:00:00.0000", result: null }, + // Some simple valid values. + { value: "00:00", result: { time: 0, hours: 0, minutes: 0, seconds: 0, ms: 0 } }, + { value: "00:01", result: { time: 60000, hours: 0, minutes: 1, seconds: 0, ms: 0 } }, + { value: "01:00", result: { time: 3600000, hours: 1, minutes: 0, seconds: 0, ms: 0 } }, + { value: "01:01", result: { time: 3660000, hours: 1, minutes: 1, seconds: 0, ms: 0 } }, + { value: "13:37", result: { time: 49020000, hours: 13, minutes: 37, seconds: 0, ms: 0 } }, + // Valid values including seconds. + { value: "00:00:01", result: { time: 1000, hours: 0, minutes: 0, seconds: 1, ms: 0 } }, + { value: "13:37:42", result: { time: 49062000, hours: 13, minutes: 37, seconds: 42, ms: 0 } }, + // Valid values including seconds fractions. + { value: "00:00:00.001", result: { time: 1, hours: 0, minutes: 0, seconds: 0, ms: 1 } }, + { value: "00:00:00.123", result: { time: 123, hours: 0, minutes: 0, seconds: 0, ms: 123 } }, + { value: "00:00:00.100", result: { time: 100, hours: 0, minutes: 0, seconds: 0, ms: 100 } }, + { value: "00:00:00.000", result: { time: 0, hours: 0, minutes: 0, seconds: 0, ms: 0 } }, + { value: "20:17:31.142", result: { time: 73051142, hours: 20, minutes: 17, seconds: 31, ms: 142 } }, + // Highest possible value. + { value: "23:59:59.999", result: { time: 86399999, hours: 23, minutes: 59, seconds: 59, ms: 999 } }, + // Some values with one or two digits for the fraction of seconds. + { value: "00:00:00.1", result: { time: 100, hours: 0, minutes: 0, seconds: 0, ms: 100 } }, + { value: "00:00:00.14", result: { time: 140, hours: 0, minutes: 0, seconds: 0, ms: 140 } }, + { value: "13:37:42.7", result: { time: 49062700, hours: 13, minutes: 37, seconds: 42, ms: 700 } }, + { value: "23:31:12.23", result: { time: 84672230, hours: 23, minutes: 31, seconds: 12, ms: 230 } }, + ]; + + var element = document.createElement('input'); + element.type = 'time'; + + for (let test of tests) { + element.value = test.value; + if (test.result === null) { + is(element.valueAsDate, null, "element.valueAsDate should return null"); + } else { + var date = element.valueAsDate; + isnot(date, null, "element.valueAsDate should not be null"); + + is(date.getTime(), test.result.time); + is(date.getUTCHours(), test.result.hours); + is(date.getUTCMinutes(), test.result.minutes); + is(date.getUTCSeconds(), test.result.seconds); + is(date.getUTCMilliseconds(), test.result.ms); + } + } +} + +function checkTimeSet() +{ + var tests = [ + // Simple tests. + { value: 0, result: "00:00" }, + { value: 1, result: "00:00:00.001" }, + { value: 100, result: "00:00:00.100" }, + { value: 1000, result: "00:00:01" }, + { value: 60000, result: "00:01" }, + { value: 3600000, result: "01:00" }, + { value: 83622234, result: "23:13:42.234" }, + // Some edge cases. + { value: 86400000, result: "00:00" }, + { value: 86400001, result: "00:00:00.001" }, + { value: 170022234, result: "23:13:42.234" }, + { value: 432000000, result: "00:00" }, + { value: -1, result: "23:59:59.999" }, + { value: -86400000, result: "00:00" }, + { value: -86400001, result: "23:59:59.999" }, + { value: -56789, result: "23:59:03.211" }, + { value: 0.9, result: "00:00" }, + ]; + + var element = document.createElement('input'); + element.type = 'time'; + + for (let test of tests) { + element.valueAsDate = new Date(test.value); + is(element.value, test.result, + "element.value should have been changed by setting valueAsDate"); + } +} + +function checkWithBustedPrototype() +{ + for (let type of validTypes) { + if (!type[1]) { + continue; + } + + type = type[0]; + + var element = document.createElement('input'); + element.type = type; + + var backupPrototype = {}; + backupPrototype.getUTCFullYear = Date.prototype.getUTCFullYear; + backupPrototype.getUTCMonth = Date.prototype.getUTCMonth; + backupPrototype.getUTCDate = Date.prototype.getUTCDate; + backupPrototype.getTime = Date.prototype.getTime; + backupPrototype.setUTCFullYear = Date.prototype.setUTCFullYear; + + Date.prototype.getUTCFullYear = function() { return {}; }; + Date.prototype.getUTCMonth = function() { return {}; }; + Date.prototype.getUTCDate = function() { return {}; }; + Date.prototype.getTime = function() { return {}; }; + Date.prototype.setUTCFullYear = function(y,m,d) { }; + + element.valueAsDate = new Date(); + + isnot(element.valueAsDate, null, ".valueAsDate should not return null"); + // The object returned by element.valueAsDate should return a Date object + // with the same prototype: + is(element.valueAsDate.getUTCFullYear, Date.prototype.getUTCFullYear, + "prototype is the same"); + is(element.valueAsDate.getUTCMonth, Date.prototype.getUTCMonth, + "prototype is the same"); + is(element.valueAsDate.getUTCDate, Date.prototype.getUTCDate, + "prototype is the same"); + is(element.valueAsDate.getTime, Date.prototype.getTime, + "prototype is the same"); + is(element.valueAsDate.setUTCFullYear, Date.prototype.setUTCFullYear, + "prototype is the same"); + + // However the Date should have the correct information. + // Skip type=month for now, since .valueAsNumber returns number of months + // and not milliseconds. + if (type != "month") { + var witnessDate = new Date(element.valueAsNumber); + is(element.valueAsDate.valueOf(), witnessDate.valueOf(), "correct Date"); + } + + // Same test as above but using NaN instead of {}. + + Date.prototype.getUTCFullYear = function() { return NaN; }; + Date.prototype.getUTCMonth = function() { return NaN; }; + Date.prototype.getUTCDate = function() { return NaN; }; + Date.prototype.getTime = function() { return NaN; }; + Date.prototype.setUTCFullYear = function(y,m,d) { }; + + element.valueAsDate = new Date(); + + isnot(element.valueAsDate, null, ".valueAsDate should not return null"); + // The object returned by element.valueAsDate should return a Date object + // with the same prototype: + is(element.valueAsDate.getUTCFullYear, Date.prototype.getUTCFullYear, + "prototype is the same"); + is(element.valueAsDate.getUTCMonth, Date.prototype.getUTCMonth, + "prototype is the same"); + is(element.valueAsDate.getUTCDate, Date.prototype.getUTCDate, + "prototype is the same"); + is(element.valueAsDate.getTime, Date.prototype.getTime, + "prototype is the same"); + is(element.valueAsDate.setUTCFullYear, Date.prototype.setUTCFullYear, + "prototype is the same"); + + // However the Date should have the correct information. + // Skip type=month for now, since .valueAsNumber returns number of months + // and not milliseconds. + if (type != "month") { + var witnessDate = new Date(element.valueAsNumber); + is(element.valueAsDate.valueOf(), witnessDate.valueOf(), "correct Date"); + } + + Date.prototype.getUTCFullYear = backupPrototype.getUTCFullYear; + Date.prototype.getUTCMonth = backupPrototype.getUTCMonth; + Date.prototype.getUTCDate = backupPrototype.getUTCDate; + Date.prototype.getTime = backupPrototype.getTime; + Date.prototype.setUTCFullYear = backupPrototype.setUTCFullYear; + } +} + +function checkMonthGet() +{ + var validData = + [ + [ "2016-07", 1467331200000 ], + [ "1970-01", 0 ], + [ "1970-02", 2678400000 ], + [ "1969-12", -2678400000 ], + [ "0001-01", -62135596800000 ], + [ "275760-09", 8639998963200000 ], + ]; + + var invalidData = + [ + [ "invalidmonth" ], + [ "0000-01" ], + [ "2016-00" ], + [ "123-01" ], + [ "2017-13" ], + [ "" ], + // This month is valid for the input element, but is out of + // the date object range. In this case, on getting valueAsDate, + // a Date object will be created, but it will have a NaN internal value, + // and will return the string "Invalid Date". + [ "275760-10", true ], + ]; + + element.type = "month"; + for (let data of validData) { + element.value = data[0]; + is(element.valueAsDate.valueOf(), data[1], + "valueAsDate should return the " + + "valid date object representing this month"); + } + + for (let data of invalidData) { + element.value = data[0]; + if (data[1]) { + is(String(element.valueAsDate), "Invalid Date", + "valueAsDate should return an invalid Date object " + + "when the element value is not a valid month"); + } else { + is(element.valueAsDate, null, + "valueAsDate should return null " + + "when the element value is not a valid month"); + } + } +} + +function checkMonthSet() +{ + var testData = + [ + [ 1342051200000, "2012-07" ], + [ 0, "1970-01" ], + // Maximum valid month (limited by the ecma date object range). + [ 8640000000000000, "275760-09" ], + // Minimum valid month (limited by the input element minimum valid value). + [ -62135596800000 , "0001-01" ], + [ 1330473600000, "2012-02" ], + [ 1298851200000, "2011-02" ], + // "Values must be truncated to valid months" + [ 42.1234, "1970-01" ], + [ 123.123456789123, "1970-01" ], + [ 1e-1, "1970-01" ], + [ 1298851200010, "2011-02" ], + [ -1, "1969-12" ], + [ -86400000, "1969-12" ], + [ 86400000, "1970-01" ], + // Negative years, this is out of range for the input element, + // the corresponding month string is the empty string + [ -62135596800001, "" ], + ]; + + element.type = "month"; + for (let data of testData) { + element.valueAsDate = new Date(data[0]); + is(element.value, data[1], "valueAsDate should set the value to " + + data[1]); + element.valueAsDate = new testFrame.Date(data[0]); + is(element.value, data[1], "valueAsDate with other-global date should " + + "set the value to " + data[1]); + } +} + +function checkWeekGet() +{ + var validData = + [ + // Common years starting on different days of week. + [ "2007-W01", Date.UTC(2007, 0, 1) ], // Mon + [ "2013-W01", Date.UTC(2012, 11, 31) ], // Tue + [ "2014-W01", Date.UTC(2013, 11, 30) ], // Wed + [ "2015-W01", Date.UTC(2014, 11, 29) ], // Thu + [ "2010-W01", Date.UTC(2010, 0, 4) ], // Fri + [ "2011-W01", Date.UTC(2011, 0, 3) ], // Sat + [ "2017-W01", Date.UTC(2017, 0, 2) ], // Sun + // Common years ending on different days of week. + [ "2007-W52", Date.UTC(2007, 11, 24) ], // Mon + [ "2013-W52", Date.UTC(2013, 11, 23) ], // Tue + [ "2014-W52", Date.UTC(2014, 11, 22) ], // Wed + [ "2015-W53", Date.UTC(2015, 11, 28) ], // Thu + [ "2010-W52", Date.UTC(2010, 11, 27) ], // Fri + [ "2011-W52", Date.UTC(2011, 11, 26) ], // Sat + [ "2017-W52", Date.UTC(2017, 11, 25) ], // Sun + // Leap years starting on different days of week. + [ "1996-W01", Date.UTC(1996, 0, 1) ], // Mon + [ "2008-W01", Date.UTC(2007, 11, 31) ], // Tue + [ "2020-W01", Date.UTC(2019, 11, 30) ], // Wed + [ "2004-W01", Date.UTC(2003, 11, 29) ], // Thu + [ "2016-W01", Date.UTC(2016, 0, 4) ], // Fri + [ "2000-W01", Date.UTC(2000, 0, 3) ], // Sat + [ "2012-W01", Date.UTC(2012, 0, 2) ], // Sun + // Leap years ending on different days of week. + [ "2012-W52", Date.UTC(2012, 11, 24) ], // Mon + [ "2024-W52", Date.UTC(2024, 11, 23) ], // Tue + [ "1980-W52", Date.UTC(1980, 11, 22) ], // Wed + [ "1992-W53", Date.UTC(1992, 11, 28) ], // Thu + [ "2004-W53", Date.UTC(2004, 11, 27) ], // Fri + [ "1988-W52", Date.UTC(1988, 11, 26) ], // Sat + [ "2000-W52", Date.UTC(2000, 11, 25) ], // Sun + // Other normal cases. + [ "2016-W36", 1473033600000 ], + [ "1969-W52", -864000000 ], + [ "1970-W01", -259200000 ], + [ "275760-W37", 8639999568000000 ], + ]; + + var invalidData = + [ + [ "invalidweek" ], + [ "0000-W01" ], + [ "2016-W00" ], + [ "123-W01" ], + [ "2016-W53" ], + [ "" ], + // This week is valid for the input element, but is out of + // the date object range. In this case, on getting valueAsDate, + // a Date object will be created, but it will have a NaN internal value, + // and will return the string "Invalid Date". + [ "275760-W38", true ], + ]; + + element.type = "week"; + for (let data of validData) { + element.value = data[0]; + is(element.valueAsDate.valueOf(), data[1], + "valueAsDate should return the " + + "valid date object representing this week"); + } + + for (let data of invalidData) { + element.value = data[0]; + if (data[1]) { + is(String(element.valueAsDate), "Invalid Date", + "valueAsDate should return an invalid Date object " + + "when the element value is not a valid week"); + } else { + is(element.valueAsDate, null, + "valueAsDate should return null " + + "when the element value is not a valid week"); + } + } +} + +function checkWeekSet() +{ + var testData = + [ + // Common years starting on different days of week. + [ Date.UTC(2007, 0, 1), "2007-W01" ], // Mon + [ Date.UTC(2013, 0, 1), "2013-W01" ], // Tue + [ Date.UTC(2014, 0, 1), "2014-W01" ], // Wed + [ Date.UTC(2015, 0, 1), "2015-W01" ], // Thu + [ Date.UTC(2010, 0, 1), "2009-W53" ], // Fri + [ Date.UTC(2011, 0, 1), "2010-W52" ], // Sat + [ Date.UTC(2017, 0, 1), "2016-W52" ], // Sun + // Common years ending on different days of week. + [ Date.UTC(2007, 11, 31), "2008-W01" ], // Mon + [ Date.UTC(2013, 11, 31), "2014-W01" ], // Tue + [ Date.UTC(2014, 11, 31), "2015-W01" ], // Wed + [ Date.UTC(2015, 11, 31), "2015-W53" ], // Thu + [ Date.UTC(2010, 11, 31), "2010-W52" ], // Fri + [ Date.UTC(2011, 11, 31), "2011-W52" ], // Sat + [ Date.UTC(2017, 11, 31), "2017-W52" ], // Sun + // Leap years starting on different days of week. + [ Date.UTC(1996, 0, 1), "1996-W01" ], // Mon + [ Date.UTC(2008, 0, 1), "2008-W01" ], // Tue + [ Date.UTC(2020, 0, 1), "2020-W01" ], // Wed + [ Date.UTC(2004, 0, 1), "2004-W01" ], // Thu + [ Date.UTC(2016, 0, 1), "2015-W53" ], // Fri + [ Date.UTC(2000, 0, 1), "1999-W52" ], // Sat + [ Date.UTC(2012, 0, 1), "2011-W52" ], // Sun + // Leap years ending on different days of week. + [ Date.UTC(2012, 11, 31), "2013-W01" ], // Mon + [ Date.UTC(2024, 11, 31), "2025-W01" ], // Tue + [ Date.UTC(1980, 11, 31), "1981-W01" ], // Wed + [ Date.UTC(1992, 11, 31), "1992-W53" ], // Thu + [ Date.UTC(2004, 11, 31), "2004-W53" ], // Fri + [ Date.UTC(1988, 11, 31), "1988-W52" ], // Sat + [ Date.UTC(2000, 11, 31), "2000-W52" ], // Sun + // Other normal cases. + [ Date.UTC(2016, 8, 9), "2016-W36" ], + [ Date.UTC(2010, 0, 3), "2009-W53" ], + [ Date.UTC(2010, 0, 4), "2010-W01" ], + [ Date.UTC(2010, 0, 10), "2010-W01" ], + [ Date.UTC(2010, 0, 11), "2010-W02" ], + [ 0, "1970-W01" ], + // Maximum valid month (limited by the ecma date object range). + [ 8640000000000000, "275760-W37" ], + // Minimum valid month (limited by the input element minimum valid value). + [ -62135596800000 , "0001-W01" ], + // "Values must be truncated to valid week" + [ 42.1234, "1970-W01" ], + [ 123.123456789123, "1970-W01" ], + [ 1e-1, "1970-W01" ], + [ -1.1, "1970-W01" ], + [ -345600000, "1969-W52" ], + // Negative years, this is out of range for the input element, + // the corresponding week string is the empty string + [ -62135596800001, "" ], + ]; + + element.type = "week"; + for (let data of testData) { + element.valueAsDate = new Date(data[0]); + is(element.value, data[1], "valueAsDate should set the value to " + + data[1]); + element.valueAsDate = new testFrame.Date(data[0]); + is(element.value, data[1], "valueAsDate with other-global date should " + + "set the value to " + data[1]); + } +} + +checkAvailability(); +checkGarbageValues(); +checkWithBustedPrototype(); + +// Test <input type='date'>. +checkDateGet(); +checkDateSet(); + +// Test <input type='time'>. +checkTimeGet(); +checkTimeSet(); + +// Test <input type='month'>. +checkMonthGet(); +checkMonthSet(); + +// Test <input type='week'>. +checkWeekGet(); +checkWeekSet(); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/forms/test_valueasnumber_attribute.html b/dom/html/test/forms/test_valueasnumber_attribute.html new file mode 100644 index 000000000..d7471502b --- /dev/null +++ b/dom/html/test/forms/test_valueasnumber_attribute.html @@ -0,0 +1,744 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=636737 +--> +<head> + <title>Test for Bug input.valueAsNumber</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636737">Mozilla Bug 636737</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 636737 **/ + +/** + * This test is checking .valueAsNumber. + */ + +function checkAvailability() +{ + var testData = + [ + ["text", false], + ["password", false], + ["search", false], + ["tel", false], + ["email", false], + ["url", false], + ["hidden", false], + ["checkbox", false], + ["radio", false], + ["file", false], + ["submit", false], + ["image", false], + ["reset", false], + ["button", false], + ["number", true], + ["range", true], + ["date", true], + ["time", true], + ["color", false], + ["month", true], + ["week", true], + // TODO: temporary set to false until bug 888331 is fixed. + ["datetime-local", false], + ]; + + var element = document.createElement('input'); + + for (let data of testData) { + var exceptionCatched = false; + element.type = data[0]; + try { + element.valueAsNumber; + } catch (e) { + exceptionCatched = true; + } + is(exceptionCatched, false, + "valueAsNumber shouldn't throw exception on getting"); + + exceptionCatched = false; + try { + element.valueAsNumber = 42; + } catch (e) { + exceptionCatched = true; + } + is(exceptionCatched, !data[1], "valueAsNumber for " + data[0] + + " availability is not correct"); + } +} + +function checkNumberGet() +{ + var testData = + [ + ["42", 42], + ["-42", -42], // should work for negative values + ["42.1234", 42.1234], + ["123.123456789123", 123.123456789123], // double precision + ["1e2", 100], // e should be usable + ["2e1", 20], + ["1e-1", 0.1], // value after e can be negative + ["1E2", 100], // E can be used instead of e + ["e", null], + ["e2", null], + ["1e0.1", null], + ["", null], // the empty string is not a number + ["foo", null], + ["42,13", null], // comma can't be used as a decimal separator + ]; + + var element = document.createElement('input'); + element.type = "number"; + for (let data of testData) { + element.value = data[0]; + + // Given that NaN != NaN, we have to use null when the expected value is NaN. + if (data[1] != null) { + is(element.valueAsNumber, data[1], "valueAsNumber should return the " + + "floating point representation of the value"); + } else { + ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " + + "when the element value is not a number"); + } + } +} + +function checkNumberSet() +{ + var testData = + [ + [42, "42"], + [-42, "-42"], // should work for negative values + [42.1234, "42.1234"], + [123.123456789123, "123.123456789123"], // double precision + [1e2, "100"], // e should be usable + [2e1, "20"], + [1e-1, "0.1"], // value after e can be negative + [1E2, "100"], // E can be used instead of e + // Setting a string will set NaN. + ["foo", ""], + // "" is converted to 0. + ["", "0"], + [42, "42"], // Keep this here, it is used by the next test. + // Setting Infinity should throw and not change the current value. + [Infinity, "42", true], + [-Infinity, "42", true], + // Setting NaN should change the value to the empty string. + [NaN, ""], + ]; + + var element = document.createElement('input'); + element.type = "number"; + for (let data of testData) { + var caught = false; + try { + element.valueAsNumber = data[0]; + is(element.value, data[1], + "valueAsNumber should be able to set the value"); + } catch (e) { + caught = true; + } + + if (data[2]) { + ok(caught, "valueAsNumber should have thrown"); + is(element.value, data[1], "value should not have changed"); + } else { + ok(!caught, "valueAsNumber should not have thrown"); + } + } +} + +function checkRangeGet() +{ + // For type=range we should never get NaN since the user agent is required + // to fix up the input's value to be something sensible. + + var min = -200; + var max = 200; + var defaultValue = min + (max - min)/2; + + var testData = + [ + ["42", 42], + ["-42", -42], // should work for negative values + ["42.1234", 42.1234], + ["123.123456789123", 123.123456789123], // double precision + ["1e2", 100], // e should be usable + ["2e1", 20], + ["1e-1", 0.1], // value after e can be negative + ["1E2", 100], // E can be used instead of e + ["e", defaultValue], + ["e2", defaultValue], + ["1e0.1", defaultValue], + ["", defaultValue], + ["foo", defaultValue], + ["42,13", defaultValue], + ]; + + var element = document.createElement('input'); + element.type = "range"; + element.setAttribute("min", min); // avoids out of range sanitization + element.setAttribute("max", max); + element.setAttribute("step", "any"); // avoids step mismatch sanitization + for (let data of testData) { + element.value = data[0]; + + // Given that NaN != NaN, we have to use null when the expected value is NaN. + is(element.valueAsNumber, data[1], "valueAsNumber should return the " + + "floating point representation of the value"); + } +} + +function checkRangeSet() +{ + var min = -200; + var max = 200; + var defaultValue = String(min + (max - min)/2); + + var testData = + [ + [42, "42"], + [-42, "-42"], // should work for negative values + [42.1234, "42.1234"], + [123.123456789123, "123.123456789123"], // double precision + [1e2, "100"], // e should be usable + [2e1, "20"], + [1e-1, "0.1"], // value after e can be negative + [1E2, "100"], // E can be used instead of e + ["foo", defaultValue], + ["", defaultValue], + [42, "42"], // Keep this here, it is used by the next test. + // Setting Infinity should throw and not change the current value. + [Infinity, "42", true], + [-Infinity, "42", true], + // Setting NaN should change the value to the empty string. + [NaN, defaultValue], + ]; + + var element = document.createElement('input'); + element.type = "range"; + element.setAttribute("min", min); // avoids out of range sanitization + element.setAttribute("max", max); + element.setAttribute("step", "any"); // avoids step mismatch sanitization + for (let data of testData) { + var caught = false; + try { + element.valueAsNumber = data[0]; + is(element.value, data[1], + "valueAsNumber should be able to set the value"); + } catch (e) { + caught = true; + } + + if (data[2]) { + ok(caught, "valueAsNumber should have thrown"); + is(element.value, data[1], "value should not have changed"); + } else { + ok(!caught, "valueAsNumber should not have thrown"); + } + } +} + +function checkDateGet() +{ + var validData = + [ + [ "2012-07-12", 1342051200000 ], + [ "1970-01-01", 0 ], + // We are supposed to support at least until this date. + // (corresponding to the date object maximal value) + [ "275760-09-13", 8640000000000000 ], + // Minimum valid date (limited by the input element minimum valid value) + [ "0001-01-01", -62135596800000 ], + [ "2012-02-29", 1330473600000 ], + [ "2011-02-28", 1298851200000 ], + ]; + + var invalidData = + [ + "invaliddate", + "", + "275760-09-14", + "999-12-31", + "-001-12-31", + "0000-01-01", + "2011-02-29", + "1901-13-31", + "1901-12-32", + "1901-00-12", + "1901-01-00", + "1900-02-29", + ]; + + var element = document.createElement('input'); + element.type = "date"; + for (let data of validData) { + element.value = data[0]; + is(element.valueAsNumber, data[1], "valueAsNumber should return the " + + "timestamp representing this date"); + } + + for (let data of invalidData) { + element.value = data; + ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " + + "when the element value is not a valid date"); + } +} + +function checkDateSet() +{ + var testData = + [ + [ 1342051200000, "2012-07-12" ], + [ 0, "1970-01-01" ], + // Maximum valid date (limited by the ecma date object range). + [ 8640000000000000, "275760-09-13" ], + // Minimum valid date (limited by the input element minimum valid value) + [ -62135596800000, "0001-01-01" ], + [ 1330473600000, "2012-02-29" ], + [ 1298851200000, "2011-02-28" ], + // "Values must be truncated to valid dates" + [ 42.1234, "1970-01-01" ], + [ 123.123456789123, "1970-01-01" ], + [ 1e2, "1970-01-01" ], + [ 1E9, "1970-01-12" ], + [ 1e-1, "1970-01-01" ], + [ 2e10, "1970-08-20" ], + [ 1298851200010, "2011-02-28" ], + [ -1, "1969-12-31" ], + [ -86400000, "1969-12-31" ], + [ 86400000, "1970-01-02" ], + // Invalid numbers. + // Those are implicitly converted to numbers + [ "", "1970-01-01" ], + [ true, "1970-01-01" ], + [ false, "1970-01-01" ], + [ null, "1970-01-01" ], + // Those are converted to NaN, the corresponding date string is the empty string + [ "invaliddatenumber", "" ], + [ NaN, "" ], + [ undefined, "" ], + // Out of range, the corresponding date string is the empty string + [ -62135596800001, "" ], + // Infinity will keep the current value and throw (so we need to set a current value). + [ 1298851200010, "2011-02-28" ], + [ Infinity, "2011-02-28", true ], + [ -Infinity, "2011-02-28", true ], + ]; + + var element = document.createElement('input'); + element.type = "date"; + for (let data of testData) { + var caught = false; + + try { + element.valueAsNumber = data[0]; + is(element.value, data[1], "valueAsNumber should set the value to " + data[1]); + } catch(e) { + caught = true; + } + + if (data[2]) { + ok(caught, "valueAsNumber should have thrown"); + is(element.value, data[1], "the value should not have changed"); + } else { + ok(!caught, "valueAsNumber should not have thrown"); + } + } + +} + +function checkTimeGet() +{ + var tests = [ + // Some invalid values to begin. + { value: "", result: NaN }, + { value: "foobar", result: NaN }, + { value: "00:", result: NaN }, + { value: "24:00", result: NaN }, + { value: "00:99", result: NaN }, + { value: "00:00:", result: NaN }, + { value: "00:00:99", result: NaN }, + { value: "00:00:00:", result: NaN }, + { value: "00:00:00.", result: NaN }, + { value: "00:00:00.0000", result: NaN }, + // Some simple valid values. + { value: "00:00", result: 0 }, + { value: "00:01", result: 60000 }, + { value: "01:00", result: 3600000 }, + { value: "01:01", result: 3660000 }, + { value: "13:37", result: 49020000 }, + // Valid values including seconds. + { value: "00:00:01", result: 1000 }, + { value: "13:37:42", result: 49062000 }, + // Valid values including seconds fractions. + { value: "00:00:00.001", result: 1 }, + { value: "00:00:00.123", result: 123 }, + { value: "00:00:00.100", result: 100 }, + { value: "00:00:00.000", result: 0 }, + { value: "20:17:31.142", result: 73051142 }, + // Highest possible value. + { value: "23:59:59.999", result: 86399999 }, + // Some values with one or two digits for the fraction of seconds. + { value: "00:00:00.1", result: 100 }, + { value: "00:00:00.14", result: 140 }, + { value: "13:37:42.7", result: 49062700 }, + { value: "23:31:12.23", result: 84672230 }, + ]; + + var element = document.createElement('input'); + element.type = 'time'; + + for (let test of tests) { + element.value = test.value; + if (isNaN(test.result)) { + ok(isNaN(element.valueAsNumber), + "invalid value should have .valueAsNumber return NaN"); + } else { + is(element.valueAsNumber, test.result, + ".valueAsNumber should return " + test.result); + } + } +} + +function checkTimeSet() +{ + var tests = [ + // Some NaN values (should set to empty string). + { value: NaN, result: "" }, + { value: "foobar", result: "" }, + { value: function() {}, result: "" }, + // Inifinity (should throw). + { value: Infinity, throw: true }, + { value: -Infinity, throw: true }, + // "" converts to 0... JS is fun :) + { value: "", result: "00:00" }, + // Simple tests. + { value: 0, result: "00:00" }, + { value: 1, result: "00:00:00.001" }, + { value: 100, result: "00:00:00.100" }, + { value: 1000, result: "00:00:01" }, + { value: 60000, result: "00:01" }, + { value: 3600000, result: "01:00" }, + { value: 83622234, result: "23:13:42.234" }, + // Some edge cases. + { value: 86400000, result: "00:00" }, + { value: 86400001, result: "00:00:00.001" }, + { value: 170022234, result: "23:13:42.234" }, + { value: 432000000, result: "00:00" }, + { value: -1, result: "23:59:59.999" }, + { value: -86400000, result: "00:00" }, + { value: -86400001, result: "23:59:59.999" }, + { value: -56789, result: "23:59:03.211" }, + { value: 0.9, result: "00:00" }, + ]; + + var element = document.createElement('input'); + element.type = 'time'; + + for (let test of tests) { + try { + var caught = false; + element.valueAsNumber = test.value; + is(element.value, test.result, "value should return " + test.result); + } catch(e) { + caught = true; + } + + if (!test.throw) { + test.throw = false; + } + + is(caught, test.throw, "the test throwing status should be " + test.throw); + } +} + +function checkMonthGet() +{ + var validData = + [ + [ "2016-07", 558 ], + [ "1970-01", 0 ], + [ "1969-12", -1 ], + [ "0001-01", -23628 ], + [ "10000-12", 96371 ], + [ "275760-09", 3285488 ], + ]; + + var invalidData = + [ + "invalidmonth", + "0000-01", + "2000-00", + "2012-13", + // Out of range. + "275760-10", + ]; + + var element = document.createElement('input'); + element.type = "month"; + for (let data of validData) { + element.value = data[0]; + is(element.valueAsNumber, data[1], "valueAsNumber should return the " + + "integer value representing this month"); + } + + for (let data of invalidData) { + element.value = data; + ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " + + "when the element value is not a valid month"); + } +} + +function checkMonthSet() +{ + var testData = + [ + [ 558, "2016-07" ], + [ 0, "1970-01" ], + [ -1, "1969-12" ], + [ 96371, "10000-12" ], + [ 12, "1971-01" ], + [ -12, "1969-01" ], + // Maximum valid month (limited by the ecma date object range) + [ 3285488, "275760-09" ], + // Minimum valid month (limited by the input element minimum valid value) + [ -23628, "0001-01" ], + // "Values must be truncated to valid months" + [ 0.3, "1970-01" ], + [ -1.1, "1969-11" ], + [ 1e2, "1978-05" ], + [ 1e-1, "1970-01" ], + // Invalid numbers. + // Those are implicitly converted to numbers + [ "", "1970-01" ], + [ true, "1970-02" ], + [ false, "1970-01" ], + [ null, "1970-01" ], + // Those are converted to NaN, the corresponding month string is the empty string + [ "invalidmonth", "" ], + [ NaN, "" ], + [ undefined, "" ], + // Out of range, the corresponding month string is the empty string + [ -23629, "" ], + [ 3285489, "" ], + // Infinity will keep the current value and throw (so we need to set a current value) + [ 558, "2016-07" ], + [ Infinity, "2016-07", true ], + [ -Infinity, "2016-07", true ], + ]; + + var element = document.createElement('input'); + element.type = "month"; + for (let data of testData) { + var caught = false; + + try { + element.valueAsNumber = data[0]; + is(element.value, data[1], "valueAsNumber should set the value to " + data[1]); + } catch(e) { + caught = true; + } + + if (data[2]) { + ok(caught, "valueAsNumber should have thrown"); + is(element.value, data[1], "the value should not have changed"); + } else { + ok(!caught, "valueAsNumber should not have thrown"); + } + } +} + +function checkWeekGet() +{ + var validData = + [ + // Common years starting on different days of week. + [ "2007-W01", Date.UTC(2007, 0, 1) ], // Mon + [ "2013-W01", Date.UTC(2012, 11, 31) ], // Tue + [ "2014-W01", Date.UTC(2013, 11, 30) ], // Wed + [ "2015-W01", Date.UTC(2014, 11, 29) ], // Thu + [ "2010-W01", Date.UTC(2010, 0, 4) ], // Fri + [ "2011-W01", Date.UTC(2011, 0, 3) ], // Sat + [ "2017-W01", Date.UTC(2017, 0, 2) ], // Sun + // Common years ending on different days of week. + [ "2007-W52", Date.UTC(2007, 11, 24) ], // Mon + [ "2013-W52", Date.UTC(2013, 11, 23) ], // Tue + [ "2014-W52", Date.UTC(2014, 11, 22) ], // Wed + [ "2015-W53", Date.UTC(2015, 11, 28) ], // Thu + [ "2010-W52", Date.UTC(2010, 11, 27) ], // Fri + [ "2011-W52", Date.UTC(2011, 11, 26) ], // Sat + [ "2017-W52", Date.UTC(2017, 11, 25) ], // Sun + // Leap years starting on different days of week. + [ "1996-W01", Date.UTC(1996, 0, 1) ], // Mon + [ "2008-W01", Date.UTC(2007, 11, 31) ], // Tue + [ "2020-W01", Date.UTC(2019, 11, 30) ], // Wed + [ "2004-W01", Date.UTC(2003, 11, 29) ], // Thu + [ "2016-W01", Date.UTC(2016, 0, 4) ], // Fri + [ "2000-W01", Date.UTC(2000, 0, 3) ], // Sat + [ "2012-W01", Date.UTC(2012, 0, 2) ], // Sun + // Leap years ending on different days of week. + [ "2012-W52", Date.UTC(2012, 11, 24) ], // Mon + [ "2024-W52", Date.UTC(2024, 11, 23) ], // Tue + [ "1980-W52", Date.UTC(1980, 11, 22) ], // Wed + [ "1992-W53", Date.UTC(1992, 11, 28) ], // Thu + [ "2004-W53", Date.UTC(2004, 11, 27) ], // Fri + [ "1988-W52", Date.UTC(1988, 11, 26) ], // Sat + [ "2000-W52", Date.UTC(2000, 11, 25) ], // Sun + // Other normal cases. + [ "2015-W53", Date.UTC(2015, 11, 28) ], + [ "2016-W36", Date.UTC(2016, 8, 5) ], + [ "1970-W01", Date.UTC(1969, 11, 29) ], + [ "275760-W37", Date.UTC(275760, 8, 8) ], + ]; + + var invalidData = + [ + "invalidweek", + "0000-W01", + "2016-W00", + "2016-W53", + // Out of range. + "275760-W38", + ]; + + var element = document.createElement('input'); + element.type = "week"; + for (let data of validData) { + dump("Test: " + data[0]); + element.value = data[0]; + is(element.valueAsNumber, data[1], "valueAsNumber should return the " + + "integer value representing this week"); + } + + for (let data of invalidData) { + element.value = data; + ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " + + "when the element value is not a valid week"); + } +} + +function checkWeekSet() +{ + var testData = + [ + // Common years starting on different days of week. + [ Date.UTC(2007, 0, 1), "2007-W01" ], // Mon + [ Date.UTC(2013, 0, 1), "2013-W01" ], // Tue + [ Date.UTC(2014, 0, 1), "2014-W01" ], // Wed + [ Date.UTC(2015, 0, 1), "2015-W01" ], // Thu + [ Date.UTC(2010, 0, 1), "2009-W53" ], // Fri + [ Date.UTC(2011, 0, 1), "2010-W52" ], // Sat + [ Date.UTC(2017, 0, 1), "2016-W52" ], // Sun + // Common years ending on different days of week. + [ Date.UTC(2007, 11, 31), "2008-W01" ], // Mon + [ Date.UTC(2013, 11, 31), "2014-W01" ], // Tue + [ Date.UTC(2014, 11, 31), "2015-W01" ], // Wed + [ Date.UTC(2015, 11, 31), "2015-W53" ], // Thu + [ Date.UTC(2010, 11, 31), "2010-W52" ], // Fri + [ Date.UTC(2011, 11, 31), "2011-W52" ], // Sat + [ Date.UTC(2017, 11, 31), "2017-W52" ], // Sun + // Leap years starting on different days of week. + [ Date.UTC(1996, 0, 1), "1996-W01" ], // Mon + [ Date.UTC(2008, 0, 1), "2008-W01" ], // Tue + [ Date.UTC(2020, 0, 1), "2020-W01" ], // Wed + [ Date.UTC(2004, 0, 1), "2004-W01" ], // Thu + [ Date.UTC(2016, 0, 1), "2015-W53" ], // Fri + [ Date.UTC(2000, 0, 1), "1999-W52" ], // Sat + [ Date.UTC(2012, 0, 1), "2011-W52" ], // Sun + // Leap years ending on different days of week. + [ Date.UTC(2012, 11, 31), "2013-W01" ], // Mon + [ Date.UTC(2024, 11, 31), "2025-W01" ], // Tue + [ Date.UTC(1980, 11, 31), "1981-W01" ], // Wed + [ Date.UTC(1992, 11, 31), "1992-W53" ], // Thu + [ Date.UTC(2004, 11, 31), "2004-W53" ], // Fri + [ Date.UTC(1988, 11, 31), "1988-W52" ], // Sat + [ Date.UTC(2000, 11, 31), "2000-W52" ], // Sun + // Other normal cases. + [ Date.UTC(2008, 8, 26), "2008-W39" ], + [ Date.UTC(2016, 0, 4), "2016-W01" ], + [ Date.UTC(2016, 0, 10), "2016-W01" ], + [ Date.UTC(2016, 0, 11), "2016-W02" ], + // Maximum valid week (limited by the ecma date object range). + [ 8640000000000000, "275760-W37" ], + // Minimum valid week (limited by the input element minimum valid value) + [ -62135596800000, "0001-W01" ], + // "Values must be truncated to valid weeks" + [ 0.3, "1970-W01" ], + [ 1e-1, "1970-W01" ], + [ -1.1, "1970-W01" ], + [ -345600000, "1969-W52" ], + // Invalid numbers. + // Those are implicitly converted to numbers + [ "", "1970-W01" ], + [ true, "1970-W01" ], + [ false, "1970-W01" ], + [ null, "1970-W01" ], + // Those are converted to NaN, the corresponding week string is the empty string + [ "invalidweek", "" ], + [ NaN, "" ], + [ undefined, "" ], + // Infinity will keep the current value and throw (so we need to set a current value). + [ Date.UTC(2016, 8, 8), "2016-W36" ], + [ Infinity, "2016-W36", true ], + [ -Infinity, "2016-W36", true ], + ]; + + var element = document.createElement('input'); + element.type = "week"; + for (let data of testData) { + var caught = false; + + try { + element.valueAsNumber = data[0]; + is(element.value, data[1], "valueAsNumber should set the value to " + data[1]); + } catch(e) { + caught = true; + } + + if (data[2]) { + ok(caught, "valueAsNumber should have thrown"); + is(element.value, data[1], "the value should not have changed"); + } else { + ok(!caught, "valueAsNumber should not have thrown"); + } + } +} + +checkAvailability(); + +// <input type='number'> test +checkNumberGet(); +checkNumberSet(); + +// <input type='range'> test +checkRangeGet(); +checkRangeSet(); + +// <input type='date'> test +checkDateGet(); +checkDateSet(); + +// <input type='time'> test +checkTimeGet(); +checkTimeSet(); + +// <input type='month'> test +checkMonthGet(); +checkMonthSet(); + +// <input type='week'> test +checkWeekGet(); +checkWeekSet(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/head.js b/dom/html/test/head.js new file mode 100644 index 000000000..7f5db315e --- /dev/null +++ b/dom/html/test/head.js @@ -0,0 +1,54 @@ +function pushPrefs(...aPrefs) { + return new Promise(resolve => { + SpecialPowers.pushPrefEnv({"set": aPrefs}, resolve); + }); +} + +function promiseWaitForEvent(object, eventName, capturing = false, chrome = false) { + return new Promise((resolve) => { + function listener(event) { + info("Saw " + eventName); + object.removeEventListener(eventName, listener, capturing, chrome); + resolve(event); + } + + info("Waiting for " + eventName); + object.addEventListener(eventName, listener, capturing, chrome); + }); +} + +/** + * Waits for the next load to complete in any browser or the given browser. + * If a <tabbrowser> is given it waits for a load in any of its browsers. + * + * @return promise + */ +function waitForDocLoadComplete(aBrowser=gBrowser) { + return new Promise(resolve => { + let listener = { + onStateChange: function (webProgress, req, flags, status) { + let docStop = Ci.nsIWebProgressListener.STATE_IS_NETWORK | + Ci.nsIWebProgressListener.STATE_STOP; + info("Saw state " + flags.toString(16) + " and status " + status.toString(16)); + // When a load needs to be retargetted to a new process it is cancelled + // with NS_BINDING_ABORTED so ignore that case + if ((flags & docStop) == docStop && status != Cr.NS_BINDING_ABORTED) { + aBrowser.removeProgressListener(this); + waitForDocLoadComplete.listeners.delete(this); + let chan = req.QueryInterface(Ci.nsIChannel); + info("Browser loaded " + chan.originalURI.spec); + resolve(); + } + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, + Ci.nsISupportsWeakReference]) + }; + aBrowser.addProgressListener(listener); + waitForDocLoadComplete.listeners.add(listener); + info("Waiting for browser load"); + }); +} +// Keep a set of progress listeners for waitForDocLoadComplete() to make sure +// they're not GC'ed before we saw the page load. +waitForDocLoadComplete.listeners = new Set(); +registerCleanupFunction(() => waitForDocLoadComplete.listeners.clear()); diff --git a/dom/html/test/image-allow-credentials.png b/dom/html/test/image-allow-credentials.png Binary files differnew file mode 100644 index 000000000..df24ac6d3 --- /dev/null +++ b/dom/html/test/image-allow-credentials.png diff --git a/dom/html/test/image-allow-credentials.png^headers^ b/dom/html/test/image-allow-credentials.png^headers^ new file mode 100644 index 000000000..a03f99a9c --- /dev/null +++ b/dom/html/test/image-allow-credentials.png^headers^ @@ -0,0 +1,2 @@ +Access-Control-Allow-Origin: http://mochi.test:8888 +Access-Control-Allow-Credentials: true diff --git a/dom/html/test/image.png b/dom/html/test/image.png Binary files differnew file mode 100644 index 000000000..d26878c9f --- /dev/null +++ b/dom/html/test/image.png diff --git a/dom/html/test/imports/file_CSP_sandbox.html b/dom/html/test/imports/file_CSP_sandbox.html new file mode 100644 index 000000000..72d3bbeb3 --- /dev/null +++ b/dom/html/test/imports/file_CSP_sandbox.html @@ -0,0 +1,7 @@ +<!DOCTYPE html> +<head> +</head> +<body> + <link rel="import" href="file_CSP_sandbox_import.html" id="import"></link> +</body> + diff --git a/dom/html/test/imports/file_CSP_sandbox_import.html b/dom/html/test/imports/file_CSP_sandbox_import.html new file mode 100644 index 000000000..33f88aecc --- /dev/null +++ b/dom/html/test/imports/file_CSP_sandbox_import.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<head> +</head> +<body> +<script> + var scriptExecuted = true; +</script> +</body> + diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_A.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_A.html new file mode 100644 index 000000000..2a18604ed --- /dev/null +++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_A.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <script> + order.push("AS0"); + </script> + <link rel="import" href="file_blocking_DOMContentLoaded_B.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> +</body> +</html> diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_B.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_B.html new file mode 100644 index 000000000..a69a38d16 --- /dev/null +++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_B.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <script> + order.push("BS0"); + </script> + <link rel="import" href="file_blocking_DOMContentLoaded_C.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> +</body> +</html> diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_C.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_C.html new file mode 100644 index 000000000..76719b1b2 --- /dev/null +++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_C.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <script> + order.push("CS0"); + </script> + <link rel="import" href="file_blocking_DOMContentLoaded_D.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> +</body> +</html> diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_D.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_D.html new file mode 100644 index 000000000..0ae10e702 --- /dev/null +++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_D.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <script> + order.push("DS0"); + </script> +</head> +<body> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_1_A.html b/dom/html/test/imports/file_cycle_1_A.html new file mode 100644 index 000000000..17f2499d9 --- /dev/null +++ b/dom/html/test/imports/file_cycle_1_A.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_1_B.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("A"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_1_B.html b/dom/html/test/imports/file_cycle_1_B.html new file mode 100644 index 000000000..a7d77c823 --- /dev/null +++ b/dom/html/test/imports/file_cycle_1_B.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_1_C.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_1_A.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("B"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_1_C.html b/dom/html/test/imports/file_cycle_1_C.html new file mode 100644 index 000000000..0c563c6ce --- /dev/null +++ b/dom/html/test/imports/file_cycle_1_C.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_1_B.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_1_A.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("C"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_2_A.html b/dom/html/test/imports/file_cycle_2_A.html new file mode 100644 index 000000000..5e4b6bfd3 --- /dev/null +++ b/dom/html/test/imports/file_cycle_2_A.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_2_B.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("A"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_2_B.html b/dom/html/test/imports/file_cycle_2_B.html new file mode 100644 index 000000000..ed5c4acf6 --- /dev/null +++ b/dom/html/test/imports/file_cycle_2_B.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_2_A.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_2_C.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_2_D.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("B"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_2_C.html b/dom/html/test/imports/file_cycle_2_C.html new file mode 100644 index 000000000..4492c068a --- /dev/null +++ b/dom/html/test/imports/file_cycle_2_C.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> +</head> +<body> + <script> + order.push("C"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_2_D.html b/dom/html/test/imports/file_cycle_2_D.html new file mode 100644 index 000000000..eae5280e0 --- /dev/null +++ b/dom/html/test/imports/file_cycle_2_D.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> +</head> +<body> + <script> + order.push("D"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_3_A.html b/dom/html/test/imports/file_cycle_3_A.html new file mode 100644 index 000000000..bc2a31d1c --- /dev/null +++ b/dom/html/test/imports/file_cycle_3_A.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_3_C.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("A"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_3_B.html b/dom/html/test/imports/file_cycle_3_B.html new file mode 100644 index 000000000..19d51a6ed --- /dev/null +++ b/dom/html/test/imports/file_cycle_3_B.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_3_C.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("B"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_3_C.html b/dom/html/test/imports/file_cycle_3_C.html new file mode 100644 index 000000000..4b391c683 --- /dev/null +++ b/dom/html/test/imports/file_cycle_3_C.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_3_A.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_3_B.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("C"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_4_A.html b/dom/html/test/imports/file_cycle_4_A.html new file mode 100644 index 000000000..0668bdf80 --- /dev/null +++ b/dom/html/test/imports/file_cycle_4_A.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_4_B.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("A"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_4_B.html b/dom/html/test/imports/file_cycle_4_B.html new file mode 100644 index 000000000..596e5c3e7 --- /dev/null +++ b/dom/html/test/imports/file_cycle_4_B.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_4_C.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("B"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_4_C.html b/dom/html/test/imports/file_cycle_4_C.html new file mode 100644 index 000000000..7c676e85c --- /dev/null +++ b/dom/html/test/imports/file_cycle_4_C.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_4_D.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("C"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_4_D.html b/dom/html/test/imports/file_cycle_4_D.html new file mode 100644 index 000000000..31ae5de32 --- /dev/null +++ b/dom/html/test/imports/file_cycle_4_D.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_4_B.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_4_E.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("D"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_cycle_4_E.html b/dom/html/test/imports/file_cycle_4_E.html new file mode 100644 index 000000000..42cd3c296 --- /dev/null +++ b/dom/html/test/imports/file_cycle_4_E.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> + <link rel="import" href="file_cycle_4_C.html" onload="loaded()" onerror="failed()"></link> +</head> +<body> + <script> + order.push("E"); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_element_upgrade.html b/dom/html/test/imports/file_element_upgrade.html new file mode 100644 index 000000000..b41bd0a42 --- /dev/null +++ b/dom/html/test/imports/file_element_upgrade.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html lang="en-US"> +<head> +</head> +<body> + <x-foo></x-foo> + <script> + var prototype = Object.create(HTMLElement.prototype); + prototype.createdCallback = function() { + createdCallbackCalled = true; + } + document.registerElement('x-foo', {prototype: prototype}); + </script> +</body> +</html> diff --git a/dom/html/test/imports/file_encoding.html b/dom/html/test/imports/file_encoding.html new file mode 100644 index 000000000..d97bb0437 --- /dev/null +++ b/dom/html/test/imports/file_encoding.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<head> +<meta charset="EUC-KR"> +</head> +<body>Ignore my encoding</body>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importA1.html b/dom/html/test/imports/file_importA1.html new file mode 100644 index 000000000..ecce6f061 --- /dev/null +++ b/dom/html/test/imports/file_importA1.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importA2.html" id="A2" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("A1"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importA2.html b/dom/html/test/imports/file_importA2.html new file mode 100644 index 000000000..d03e80a4b --- /dev/null +++ b/dom/html/test/imports/file_importA2.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + </head> + <body> + <script> + order.push("A2"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importB1.html b/dom/html/test/imports/file_importB1.html new file mode 100644 index 000000000..82fb55f9f --- /dev/null +++ b/dom/html/test/imports/file_importB1.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importB2.html" id="B2" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("B1"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importB2.html b/dom/html/test/imports/file_importB2.html new file mode 100644 index 000000000..01b6cc215 --- /dev/null +++ b/dom/html/test/imports/file_importB2.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + </head> + <body> + <script> + order.push("B2"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC1.html b/dom/html/test/imports/file_importC1.html new file mode 100644 index 000000000..9ac117e65 --- /dev/null +++ b/dom/html/test/imports/file_importC1.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC2.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C1"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC10.html b/dom/html/test/imports/file_importC10.html new file mode 100644 index 000000000..801d0f085 --- /dev/null +++ b/dom/html/test/imports/file_importC10.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importE.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C10"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC2.html b/dom/html/test/imports/file_importC2.html new file mode 100644 index 000000000..f0193be44 --- /dev/null +++ b/dom/html/test/imports/file_importC2.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC3.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C2"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC3.html b/dom/html/test/imports/file_importC3.html new file mode 100644 index 000000000..eb942b707 --- /dev/null +++ b/dom/html/test/imports/file_importC3.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC4.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C3"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC4.html b/dom/html/test/imports/file_importC4.html new file mode 100644 index 000000000..5a172772a --- /dev/null +++ b/dom/html/test/imports/file_importC4.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC5.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C4"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC5.html b/dom/html/test/imports/file_importC5.html new file mode 100644 index 000000000..c29dc24ba --- /dev/null +++ b/dom/html/test/imports/file_importC5.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC6.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C5"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC6.html b/dom/html/test/imports/file_importC6.html new file mode 100644 index 000000000..a53b62bb4 --- /dev/null +++ b/dom/html/test/imports/file_importC6.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC7.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C6"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC7.html b/dom/html/test/imports/file_importC7.html new file mode 100644 index 000000000..1c7d60114 --- /dev/null +++ b/dom/html/test/imports/file_importC7.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC8.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C7"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC8.html b/dom/html/test/imports/file_importC8.html new file mode 100644 index 000000000..04bef617d --- /dev/null +++ b/dom/html/test/imports/file_importC8.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC9.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C8"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importC9.html b/dom/html/test/imports/file_importC9.html new file mode 100644 index 000000000..1a2749755 --- /dev/null +++ b/dom/html/test/imports/file_importC9.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importC10.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("C9"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importD.html b/dom/html/test/imports/file_importD.html new file mode 100644 index 000000000..a4fbda536 --- /dev/null +++ b/dom/html/test/imports/file_importD.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html lang="en-US"> + <body> + <script> + order.push("D"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_importE.html b/dom/html/test/imports/file_importE.html new file mode 100644 index 000000000..6a8792acf --- /dev/null +++ b/dom/html/test/imports/file_importE.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <link rel="import" href="file_importD.html" onload="loaded()" onerror="failed()"></link> + </head> + <body> + <script> + order.push("E"); + </script> + </body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/file_simple_import.html b/dom/html/test/imports/file_simple_import.html new file mode 100644 index 000000000..d9358bc38 --- /dev/null +++ b/dom/html/test/imports/file_simple_import.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<head> +</head> +<body>Simple import</body>
\ No newline at end of file diff --git a/dom/html/test/imports/mochitest.ini b/dom/html/test/imports/mochitest.ini new file mode 100644 index 000000000..88ad3a6f5 --- /dev/null +++ b/dom/html/test/imports/mochitest.ini @@ -0,0 +1,52 @@ +[DEFAULT] +support-files = + file_importA1.html + file_importA2.html + file_importB1.html + file_importB2.html + file_importC1.html + file_importC2.html + file_importC3.html + file_importC4.html + file_importC5.html + file_importC6.html + file_importC7.html + file_importC8.html + file_importC9.html + file_importC10.html + file_importD.html + file_importE.html + file_cycle_1_A.html + file_cycle_1_B.html + file_cycle_1_C.html + file_cycle_2_A.html + file_cycle_2_B.html + file_cycle_2_C.html + file_cycle_2_D.html + file_cycle_3_A.html + file_cycle_3_B.html + file_cycle_3_C.html + file_cycle_4_A.html + file_cycle_4_B.html + file_cycle_4_C.html + file_cycle_4_D.html + file_cycle_4_E.html + file_encoding.html + file_simple_import.html + file_blocking_DOMContentLoaded_A.html + file_blocking_DOMContentLoaded_B.html + file_blocking_DOMContentLoaded_C.html + file_blocking_DOMContentLoaded_D.html + file_element_upgrade.html + file_CSP_sandbox.html + file_CSP_sandbox_import.html + +[test_cycle_1.html] +[test_cycle_2.html] +[test_cycle_3.html] +[test_cycle_4.html] +[test_blocking_DOMContentLoaded.html] +[test_encoding.html] +[test_defaultView.html] +[test_element_upgrade.html] +[test_CSP_sandbox.html] diff --git a/dom/html/test/imports/test_CSP_sandbox.html b/dom/html/test/imports/test_CSP_sandbox.html new file mode 100644 index 000000000..c1df21289 --- /dev/null +++ b/dom/html/test/imports/test_CSP_sandbox.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1106713 +--> +<head> + <title>Test for Bug 1106713</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1106713">Mozilla Bug 1106713</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + function go() { + var ifr = document.getElementById('iframe1').contentWindow; + ok(!ifr.scriptExecuted, "script is not allowed to run"); + SimpleTest.finish(); + } + + </script> + <iframe src='file_CSP_sandbox.html' sandbox="allow-same-origin" onload="go()" id="iframe1"></iframe> +</body> +</html> + diff --git a/dom/html/test/imports/test_blocking_DOMContentLoaded.html b/dom/html/test/imports/test_blocking_DOMContentLoaded.html new file mode 100644 index 000000000..9fa32e5ca --- /dev/null +++ b/dom/html/test/imports/test_blocking_DOMContentLoaded.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1093028 +--> +<head> + <title>Test for Bug 1093028</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1093028">Mozilla Bug 1093028</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var order = []; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + <link rel="import" href="file_blocking_DOMContentLoaded_A.html" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + is(counter, 4, "Imports are loaded"); + is(fcounter, 0, "No error in imports"); + var expected = ["AS0","BS0","CS0","DS0"]; + for (i in expected) + is(order[i], expected[i], "import " + i + " should be " + expected[i]); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/imports/test_cycle_1.html b/dom/html/test/imports/test_cycle_1.html new file mode 100644 index 000000000..5d170a7de --- /dev/null +++ b/dom/html/test/imports/test_cycle_1.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1061469 +--> +<head> + <title>Test for Bug 1061469</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var order = []; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + <link rel="import" href="file_cycle_1_A.html" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + is(counter, 6, "Imports are loaded"); + is(fcounter, 0, "No error in imports"); + var expected = ["C","B","A"]; + for (i in expected) + is(order[i], expected[i], "import " + i + " should be " + expected[i]); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/imports/test_cycle_2.html b/dom/html/test/imports/test_cycle_2.html new file mode 100644 index 000000000..23daa5953 --- /dev/null +++ b/dom/html/test/imports/test_cycle_2.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1061469 +--> +<head> + <title>Test for Bug 1061469</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var order = []; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + <link rel="import" href="file_cycle_2_A.html" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + is(counter, 5, "Imports are loaded"); + is(fcounter, 0, "No error in imports"); + var expected = ["C","D","B","A"]; + for (i in expected) + is(order[i], expected[i], "import " + i + " should be " + expected[i]); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/imports/test_cycle_3.html b/dom/html/test/imports/test_cycle_3.html new file mode 100644 index 000000000..8db664601 --- /dev/null +++ b/dom/html/test/imports/test_cycle_3.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1061469 +--> +<head> + <title>Test for Bug 1061469</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var order = []; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + <link rel="import" href="file_cycle_3_A.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_3_B.html" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + is(counter, 6, "Imports are loaded"); + is(fcounter, 0, "No error in imports"); + var expected = ["B","C","A"]; + for (i in expected) + is(order[i], expected[i], "import " + i + " should be " + expected[i]); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/imports/test_cycle_4.html b/dom/html/test/imports/test_cycle_4.html new file mode 100644 index 000000000..441ffbac8 --- /dev/null +++ b/dom/html/test/imports/test_cycle_4.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1061469 +--> +<head> + <title>Test for Bug 1061469</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var order = []; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + <link rel="import" href="file_cycle_4_A.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="file_cycle_4_D.html" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + is(counter, 8, "Imports are loaded"); + is(fcounter, 0, "No error in imports"); + var expected = ["E","D","C","B","A"]; + for (i in expected) + is(order[i], expected[i], "import " + i + " should be " + expected[i]); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/imports/test_defaultView.html b/dom/html/test/imports/test_defaultView.html new file mode 100644 index 000000000..5f9c02bd8 --- /dev/null +++ b/dom/html/test/imports/test_defaultView.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1061469 +--> +<head> + <title>Test for Bug 1061469</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var success = false; + function loaded() { + success = true; + } + function failed() { + ok(false, "Import loading failed"); + } + </script> + <link rel="import" href="file_simple_import.html" id="import" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + document.defaultView; + is(document.getElementById("import").import.defaultView, null, "defaultView is always null for imports"); + SimpleTest.finish(); + </script> +</body> +</html>
\ No newline at end of file diff --git a/dom/html/test/imports/test_element_upgrade.html b/dom/html/test/imports/test_element_upgrade.html new file mode 100644 index 000000000..006d56d35 --- /dev/null +++ b/dom/html/test/imports/test_element_upgrade.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1081107 +--> +<head> + <title>Test for Bug 1081107</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081107">Mozilla Bug 1081107</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var createdCallbackCalled = false; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + <link rel="import" href="file_element_upgrade.html" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + is(counter, 1, "Imports are loaded"); + is(fcounter, 0, "No error in imports"); + ok(createdCallbackCalled, "custom element in import has been upgraded"); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/imports/test_encoding.html b/dom/html/test/imports/test_encoding.html new file mode 100644 index 000000000..fa4033f20 --- /dev/null +++ b/dom/html/test/imports/test_encoding.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1061469 +--> +<head> + <title>Test for Bug 1061469</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var success = false; + function loaded() { + success = true; + } + function failed() { + ok(false, "Import loading failed"); + } + </script> + <link rel="import" href="file_encoding.html" id="import" onload="loaded()" onerror="failed()"></link> + <script type="text/javascript"> + is(document.getElementById("import").import.characterSet, "UTF-8", "characterSet should be UTF-8 for imports"); + SimpleTest.finish(); + </script> +</body> +</html>
\ No newline at end of file diff --git a/dom/html/test/mochitest.ini b/dom/html/test/mochitest.ini new file mode 100644 index 000000000..99b425df8 --- /dev/null +++ b/dom/html/test/mochitest.ini @@ -0,0 +1,608 @@ +[DEFAULT] +support-files = + 347174transform.xsl + 347174transformable.xml + allowMedia.sjs + bug100533_iframe.html + bug100533_load.html + bug196523-subframe.html + bug199692-nested-d2.html + bug199692-nested.html + bug199692-popup.html + bug199692-scrolled.html + bug242709_iframe.html + bug242709_load.html + bug277724_iframe1.html + bug277724_iframe2.xhtml + bug277890_iframe.html + bug277890_load.html + bug340800_iframe.txt + bug369370-popup.png + bug372098-link-target.html + bug392567.jar + bug392567.jar^headers^ + bug441930_iframe.html + bug445004-inner.html + bug445004-inner.js + bug445004-outer-abs.html + bug445004-outer-rel.html + bug445004-outer-write.html + bug446483-iframe.html + bug448564-echo.sjs + bug448564-iframe-1.html + bug448564-iframe-2.html + bug448564-iframe-3.html + bug448564-submit.js + bug499092.html + bug499092.xml + bug514856_iframe.html + bug1260704_iframe.html + bug1260704_iframe_empty.html + bug1292522_iframe.html + bug1292522_page.html + bug1315146-iframe.html + bug1315146-main.html + ../../plugins/test/mochitest/plugin-utils.js + test_non-ascii-cookie.html^headers^ + file_bug209275_1.html + file_bug209275_2.html + file_bug209275_3.html + file_bug297761.html + file_bug417760.png + file_bug893537.html + file_bug1260704.png + file_formSubmission_img.jpg + file_formSubmission_text.txt + file_fullscreen-api.html + file_fullscreen-backdrop.html + file_fullscreen-denied-inner.html + file_fullscreen-denied.html + file_fullscreen-esc-exit-inner.html + file_fullscreen-esc-exit.html + file_fullscreen-hidden.html + file_fullscreen-lenient-setters.html + file_fullscreen-multiple-inner.html + file_fullscreen-multiple.html + file_fullscreen-navigation.html + file_fullscreen-nested.html + file_fullscreen-prefixed.html + file_fullscreen-plugins.html + file_fullscreen-rollback.html + file_fullscreen-scrollbar.html + file_fullscreen-selector.html + file_fullscreen-svg-element.html + file_fullscreen-top-layer.html + file_fullscreen-unprefix-disabled-inner.html + file_fullscreen-unprefix-disabled.html + file_fullscreen-utils.js + file_iframe_sandbox_a_if1.html + file_iframe_sandbox_a_if10.html + file_iframe_sandbox_a_if11.html + file_iframe_sandbox_a_if12.html + file_iframe_sandbox_a_if13.html + file_iframe_sandbox_a_if14.html + file_iframe_sandbox_a_if15.html + file_iframe_sandbox_a_if16.html + file_iframe_sandbox_a_if17.html + file_iframe_sandbox_a_if18.html + file_iframe_sandbox_a_if19.html + file_iframe_sandbox_a_if2.html + file_iframe_sandbox_a_if3.html + file_iframe_sandbox_a_if4.html + file_iframe_sandbox_a_if5.html + file_iframe_sandbox_a_if6.html + file_iframe_sandbox_a_if7.html + file_iframe_sandbox_a_if8.html + file_iframe_sandbox_a_if9.html + file_iframe_sandbox_b_if1.html + file_iframe_sandbox_b_if2.html + file_iframe_sandbox_b_if3.html + file_iframe_sandbox_c_if1.html + file_iframe_sandbox_c_if2.html + file_iframe_sandbox_c_if3.html + file_iframe_sandbox_c_if4.html + file_iframe_sandbox_c_if5.html + file_iframe_sandbox_c_if6.html + file_iframe_sandbox_c_if7.html + file_iframe_sandbox_c_if8.html + file_iframe_sandbox_c_if9.html + file_iframe_sandbox_close.html + file_iframe_sandbox_d_if1.html + file_iframe_sandbox_d_if10.html + file_iframe_sandbox_d_if11.html + file_iframe_sandbox_d_if12.html + file_iframe_sandbox_d_if13.html + file_iframe_sandbox_d_if14.html + file_iframe_sandbox_d_if15.html + file_iframe_sandbox_d_if16.html + file_iframe_sandbox_d_if17.html + file_iframe_sandbox_d_if18.html + file_iframe_sandbox_d_if19.html + file_iframe_sandbox_d_if2.html + file_iframe_sandbox_d_if20.html + file_iframe_sandbox_d_if21.html + file_iframe_sandbox_d_if22.html + file_iframe_sandbox_d_if23.html + file_iframe_sandbox_d_if3.html + file_iframe_sandbox_d_if4.html + file_iframe_sandbox_d_if5.html + file_iframe_sandbox_d_if6.html + file_iframe_sandbox_d_if7.html + file_iframe_sandbox_d_if8.html + file_iframe_sandbox_d_if9.html + file_iframe_sandbox_e_if1.html + file_iframe_sandbox_e_if10.html + file_iframe_sandbox_e_if11.html + file_iframe_sandbox_e_if12.html + file_iframe_sandbox_e_if13.html + file_iframe_sandbox_e_if14.html + file_iframe_sandbox_e_if15.html + file_iframe_sandbox_e_if16.html + file_iframe_sandbox_e_if2.html + file_iframe_sandbox_e_if3.html + file_iframe_sandbox_e_if4.html + file_iframe_sandbox_e_if5.html + file_iframe_sandbox_e_if6.html + file_iframe_sandbox_e_if7.html + file_iframe_sandbox_e_if8.html + file_iframe_sandbox_e_if9.html + file_iframe_sandbox_f_if1.html + file_iframe_sandbox_f_if2.html + file_iframe_sandbox_f_if2.html^headers^ + file_iframe_sandbox_fail.js + file_iframe_sandbox_form_fail.html + file_iframe_sandbox_form_pass.html + file_iframe_sandbox_g_if1.html + file_iframe_sandbox_h_if1.html + file_iframe_sandbox_j_if1.html + file_iframe_sandbox_j_if2.html + file_iframe_sandbox_j_if3.html + file_iframe_sandbox_k_if1.html + file_iframe_sandbox_k_if2.html + file_iframe_sandbox_k_if3.html + file_iframe_sandbox_k_if4.html + file_iframe_sandbox_k_if5.html + file_iframe_sandbox_k_if6.html + file_iframe_sandbox_k_if7.html + file_iframe_sandbox_k_if8.html + file_iframe_sandbox_k_if9.html + file_iframe_sandbox_navigation_fail.html + file_iframe_sandbox_navigation_pass.html + file_iframe_sandbox_navigation_start.html + file_iframe_sandbox_open_window_fail.html + file_iframe_sandbox_open_window_pass.html + file_iframe_sandbox_pass.js + file_iframe_sandbox_redirect.html + file_iframe_sandbox_redirect.html^headers^ + file_iframe_sandbox_redirect_target.html + file_iframe_sandbox_refresh.html + file_iframe_sandbox_refresh.html^headers^ + file_iframe_sandbox_top_navigation_fail.html + file_iframe_sandbox_top_navigation_pass.html + file_iframe_sandbox_window_form_fail.html + file_iframe_sandbox_window_form_pass.html + file_iframe_sandbox_window_navigation_fail.html + file_iframe_sandbox_window_navigation_pass.html + file_iframe_sandbox_window_top_navigation_pass.html + file_iframe_sandbox_window_top_navigation_fail.html + file_iframe_sandbox_worker.js + file_imports_basics.html + file_imports_redirect.html + file_imports_redirect.html^headers^ + file_imports_redirected.html + file_srcdoc-2.html + file_srcdoc.html + file_window_open_close_outer.html + file_window_open_close_inner.html + formSubmission_chrome.js + form_submit_server.sjs + formData_worker.js + formData_test.js + image.png + image-allow-credentials.png + image-allow-credentials.png^headers^ + nnc_lockup.gif + reflect.js + file_ignoreuserfocus.html + simpleFileOpener.js + file_mozaudiochannel.html + file_bug1166138_1x.png + file_bug1166138_2x.png + file_bug1166138_def.png + +[test_a_text.html] +[test_anchor_href_cache_invalidation.html] +[test_applet_attributes_reflection.html] +[test_base_attributes_reflection.html] +[test_bug100533.html] +[test_bug109445.html] +[test_bug109445.xhtml] +[test_bug1297.html] +[test_bug1366.html] +[test_bug1400.html] +[test_bug143220.html] +[test_bug182279.html] +[test_bug2082.html] +[test_bug209275.xhtml] +skip-if = toolkit == 'android' #TIMED_OUT +[test_bug237071.html] +[test_bug242709.html] +[test_bug24958.html] +[test_bug274626.html] +[test_bug277724.html] +[test_bug277890.html] +[test_bug287465.html] +[test_bug295561.html] +[test_bug297761.html] +[test_bug300691-1.html] +[test_bug300691-2.html] +[test_bug300691-3.xhtml] +[test_bug330705-1.html] +[test_bug332246.html] +[test_bug332893-1.html] +[test_bug332893-2.html] +[test_bug332893-3.html] +[test_bug332893-4.html] +[test_bug332893-5.html] +[test_bug332893-6.html] +[test_bug332893-7.html] +[test_bug3348.html] +[test_bug340800.html] +[test_bug347174.html] +[test_bug347174_write.html] +[test_bug347174_xsl.html] +[test_bug347174_xslp.html] +[test_bug353415-1.html] +[test_bug353415-2.html] +[test_bug371375.html] +[test_bug372098.html] +[test_bug373589.html] +[test_bug375003-1.html] +[test_bug375003-2.html] +[test_bug377624.html] +[test_bug383383.html] +[test_bug383383_2.xhtml] +[test_bug384419.html] +[test_bug386496.html] +[test_bug386728.html] +[test_bug386996.html] +[test_bug388558.html] +[test_bug388746.html] +[test_bug388794.html] +[test_bug389797.html] +[test_bug390975.html] +[test_bug391994.html] +[test_bug392567.html] +[test_bug394700.html] +[test_bug395107.html] +[test_bug401160.xhtml] +[test_bug405242.html] +[test_bug406596.html] +[test_bug417760.html] +[test_bug421640.html] +[test_bug424698.html] +[test_bug428135.xhtml] +[test_bug430351.html] +[test_bug430392.html] +[test_bug441930.html] +[test_bug442801.html] +[test_bug448166.html] +[test_bug456229.html] +[test_bug458037.xhtml] +[test_bug460568.html] +[test_bug481335.xhtml] +skip-if = toolkit == 'android' #TIMED_OUT +[test_bug500885.html] +[test_bug514856.html] +skip-if = toolkit == 'android' +[test_bug518122.html] +[test_bug519987.html] +[test_bug523771.html] +[test_bug529819.html] +[test_bug529859.html] +[test_bug535043.html] +[test_bug536891.html] +[test_bug536895.html] +[test_bug546995.html] +[test_bug547850.html] +[test_bug551846.html] +[test_bug555567.html] +[test_bug556645.html] +[test_bug557087-1.html] +[test_bug557087-2.html] +skip-if = toolkit == 'android' #TIMED_OUT +[test_bug557087-3.html] +[test_bug557087-4.html] +[test_bug557087-5.html] +[test_bug557087-6.html] +[test_bug557620.html] +[test_bug558788-1.html] +[test_bug558788-2.html] +[test_bug560112.html] +[test_bug561634.html] +[test_bug561636.html] +[test_bug561640.html] +[test_bug564001.html] +[test_bug566046.html] +[test_bug567938-1.html] +[test_bug567938-2.html] +[test_bug567938-3.html] +[test_bug567938-4.html] +[test_bug569955.html] +[test_bug573969.html] +[test_bug579079.html] +[test_bug582412-1.html] +[test_bug582412-2.html] +[test_bug583514.html] +[test_bug583533.html] +[test_bug586763.html] +[test_bug586786.html] +[test_bug587469.html] +[test_bug589.html] +[test_bug590353-1.html] +[test_bug590353-2.html] +[test_bug590363.html] +[test_bug592802.html] +[test_bug593689.html] +[test_bug595429.html] +[test_bug595447.html] +[test_bug595449.html] +[test_bug596350.html] +[test_bug596511.html] +[test_bug598643.html] +[test_bug598833-1.html] +[test_bug600155.html] +[test_bug601030.html] +[test_bug605124-1.html] +[test_bug605124-2.html] +[test_bug605125-1.html] +[test_bug605125-2.html] +[test_bug606817.html] +[test_bug607145.html] +[test_bug610212.html] +[test_bug610687.html] +[test_bug611189.html] +[test_bug612730.html] +skip-if = toolkit == 'android' # form control not selected/checked with synthesizeMouse +[test_bug613113.html] +[test_bug613019.html] +[test_bug613722.html] +[test_bug613979.html] +[test_bug615595.html] +[test_bug615833.html] +skip-if = toolkit == 'android' || os == 'mac' #TIMED_OUT # form control not selected/checked with synthesizeMouse, osx(bug 1275664) +[test_bug617528.html] +[test_bug618948.html] +[test_bug619278.html] +[test_bug622558.html] +[test_bug622597.html] +[test_bug623291.html] +[test_bug6296.html] +[test_bug629801.html] +[test_bug633058.html] +[test_bug636336.html] +[test_bug641219.html] +[test_bug643051.html] +[test_bug646157.html] +[test_bug649134.html] +# This extra subdirectory is needed due to the nature of this test. +# With the bug, the test loads the base URL of the bug649134/file_*.sjs +# files, and the mochitest server responds with the contents of index.html if +# it exists in that case, which we use to detect failure. +# We cannot have index.html in this directory because it would prevent +# running the tests here. +support-files = + bug649134/file_bug649134-1.sjs + bug649134/file_bug649134-2.sjs + bug649134/index.html +[test_bug651956.html] +[test_bug658746.html] +[test_bug659596.html] +[test_bug659743.xml] +[test_bug660663.html] +[test_bug660959-1.html] +[test_bug660959-2.html] +[test_bug660959-3.html] +[test_bug666200.html] +[test_bug666666.html] +[test_bug669012.html] +[test_bug674558.html] +[test_bug674927.html] +[test_bug677463.html] +[test_bug677658.html] +[test_bug682886.html] +[test_bug691.html] +[test_bug694.html] +[test_bug694503.html] +[test_bug696.html] +[test_bug717819.html] +[test_bug742030.html] +[test_bug742549.html] +[test_bug745685.html] +[test_bug763626.html] +[test_bug780993.html] +[test_bug787134.html] +[test_bug797113.html] +[test_bug803677.html] +[test_bug821307.html] +[test_bug827126.html] +[test_bug838582.html] +[test_bug839371.html] +[test_bug839913.html] +[test_bug841466.html] +[test_bug845057.html] +[test_bug869040.html] +[test_bug870787.html] +[test_bug874758.html] +[test_bug879319.html] +[test_bug885024.html] +[test_bug893537.html] +[test_bug95530.html] +[test_bug969346.html] +[test_bug982039.html] +[test_bug1003539.html] +[test_bug1045270.html] +[test_bug1146116.html] +[test_bug1264157.html] +[test_bug1287321.html] +[test_change_crossorigin.html] +[test_checked.html] +[test_dir_attributes_reflection.html] +[test_dl_attributes_reflection.html] +[test_element_prototype.html] +[test_embed_attributes_reflection.html] +[test_focusshift_button.html] +[test_formData.html] +[test_formSubmission.html] +skip-if = toolkit == 'android' #TIMED_OUT +[test_formSubmission2.html] +skip-if = toolkit == 'android' +[test_formelements.html] +[test_fullscreen-api.html] +tags = fullscreen +skip-if = toolkit == 'android' +[test_fullscreen-api-race.html] +tags = fullscreen +skip-if = toolkit == 'android' # just copy the conditions from the test above +[test_hidden.html] +[test_html_attributes_reflection.html] +[test_htmlcollection.html] +[test_iframe_sandbox_general.html] +tags = openwindow +[test_iframe_sandbox_inheritance.html] +tags = openwindow +[test_iframe_sandbox_modal.html] +tags = openwindow +skip-if = toolkit == 'android' || e10s #modal tests fail on android +[test_iframe_sandbox_navigation.html] +tags = openwindow +[test_iframe_sandbox_navigation2.html] +tags = openwindow +[test_iframe_sandbox_plugins.html] +skip-if = toolkit == 'android' # plugins not supported +[test_iframe_sandbox_popups.html] +tags = openwindow +[test_iframe_sandbox_popups_inheritance.html] +tags = openwindow +skip-if = toolkit == 'android' # bug 939642 +[test_iframe_sandbox_redirect.html] +[test_iframe_sandbox_refresh.html] +[test_iframe_sandbox_same_origin.html] +[test_iframe_sandbox_workers.html] +[test_img_attributes_reflection.html] +[test_imageSrcSet.html] +[test_imports_basics.html] +[test_imports_redirect.html] +[test_imports_nonhttp.html] +[test_imports_nested.html] +[test_imports_nested_2.html] +[test_li_attributes_reflection.html] +[test_link_attributes_reflection.html] +[test_link_sizes.html] +[test_map_attributes_reflection.html] +[test_meta_attributes_reflection.html] +[test_mod_attributes_reflection.html] +[test_mozaudiochannel.html] +[test_named_options.html] +[test_nested_invalid_fieldsets.html] +[test_object_attributes_reflection.html] +[test_object_plugin_nav.html] +skip-if = toolkit == 'android' # plugins not supported +[test_ol_attributes_reflection.html] +[test_option_defaultSelected.html] +[test_option_selected_state.html] +[test_param_attributes_reflection.html] +[test_q_attributes_reflection.html] +[test_restore_from_parser_fragment.html] +[test_rowscollection.html] +[test_srcdoc-2.html] +[test_srcdoc.html] +[test_style_attributes_reflection.html] +[test_track.html] +[test_ul_attributes_reflection.html] +[test_input_files_not_nsIFile.html] +[test_ignoreuserfocus.html] +[test_fragment_form_pointer.html] +[test_bug1682.html] +[test_bug1823.html] +[test_bug57600.html] +[test_bug196523.html] +[test_bug199692.html] +skip-if = toolkit == 'android' #bug 811644 +[test_bug172261.html] +[test_bug255820.html] +[test_bug259332.html] +[test_bug311681.html] +[test_bug311681.xhtml] +[test_bug324378.html] +[test_bug332848.xhtml] +[test_bug340017.xhtml] +[test_bug359657.html] +[test_bug369370.html] +skip-if = toolkit == "android" || toolkit == "windows" # disabled on Windows because of bug 1234520 +[test_bug380383.html] +[test_bug391777.html] +skip-if = toolkit == 'android' || e10s +[test_bug402680.html] +[test_bug403868.html] +[test_bug403868.xhtml] +[test_bug435128.html] +skip-if = true # Disabled for timeouts. +[test_bug463104.html] +[test_form-parsing.html] +[test_viewport.html] +[test_documentAll.html] +[test_document-element-inserted.html] +[test_document.watch.html] +[test_bug445004.html] +skip-if = true || toolkit == 'android' # Disabled permanently (bug 559932). +[test_bug446483.html] +skip-if = toolkit == 'android' +[test_bug448564.html] +[test_bug478251.html] +[test_bug481440.html] +[test_bug481647.html] +[test_bug482659.html] +[test_bug486741.html] +[test_bug489532.html] +[test_bug497242.xhtml] +[test_bug499092.html] +[test_bug512367.html] +[test_bug677495.html] +[test_bug677495-1.html] +[test_bug741266.html] +skip-if = toolkit == "android" || toolkit == "windows" # Android: needs control of popup window size, windows(bug 1234520) +[test_non-ascii-cookie.html] +support-files = file_cookiemanager.js +[test_bug765780.html] +[test_bug871161.html] +support-files = file_bug871161-1.html file_bug871161-2.html +[test_bug1013316.html] +[test_hash_encoded.html] +[test_bug1081037.html] +[test_window_open_close.html] +tags = openwindow +[test_viewport_resize.html] +[test_image_clone_load.html] +[test_bug1203668.html] +[test_bug1166138.html] +[test_bug1230665.html] +[test_filepicker_default_directory.html] +skip-if = toolkit == 'android' +[test_bug1233598.html] +[test_bug1250401.html] +[test_bug1260664.html] +[test_bug1261673.html] +skip-if = (os == 'android' || os == 'mac') +[test_bug1261674-1.html] +skip-if = (os == 'android' || os == 'mac') +[test_bug1261674-2.html] +skip-if = (os == 'android' || os == 'mac') +[test_bug1260704.html] +[test_allowMedia.html] +[test_bug1292522_same_domain_with_different_port_number.html] +[test_bug1295719_event_sequence_for_arrow_keys.html] +skip-if = os == "android" # up/down arrow keys not supported on android +[test_bug1295719_event_sequence_for_number_keys.html] +[test_bug1310865.html] +[test_bug1315146.html] diff --git a/dom/html/test/nnc_lockup.gif b/dom/html/test/nnc_lockup.gif Binary files differnew file mode 100644 index 000000000..f746bb71d --- /dev/null +++ b/dom/html/test/nnc_lockup.gif diff --git a/dom/html/test/reflect.js b/dom/html/test/reflect.js new file mode 100644 index 000000000..abc2697a9 --- /dev/null +++ b/dom/html/test/reflect.js @@ -0,0 +1,625 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * reflect.js is a collection of methods to test HTML attribute reflection. + * Each of attribute is reflected differently, depending on various parameters, + * see: + * http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes + * + * Do not forget to add these line at the beginning of each new reflect* method: + * ok(attr in element, attr + " should be an IDL attribute of this element"); + * is(typeof element[attr], <type>, attr + " IDL attribute should be a <type>"); + */ + +/** + * Checks that a given attribute is correctly reflected as a string. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + * - otherValues Array [optional] other values to test in addition of the default ones + * - extendedAttributes Object object which can have 'TreatNullAs': "EmptyString" + */ +function reflectString(aParameters) +{ + var element = aParameters.element; + var contentAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.content; + var idlAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.idl; + var otherValues = aParameters.otherValues !== undefined + ? aParameters.otherValues : []; + var treatNullAs = aParameters.extendedAttributes ? + aParameters.extendedAttributes.TreatNullAs : null; + + ok(idlAttr in element, + idlAttr + " should be an IDL attribute of this element"); + is(typeof element[idlAttr], "string", + "'" + idlAttr + "' IDL attribute should be a string"); + + // Tests when the attribute isn't set. + is(element.getAttribute(contentAttr), null, + "When not set, the content attribute should be null."); + is(element[idlAttr], "", + "When not set, the IDL attribute should return the empty string"); + + /** + * TODO: as long as null stringification doesn't follow the WebIDL + * specifications, don't add it to the loop below and keep it here. + */ + element.setAttribute(contentAttr, null); + is(element.getAttribute(contentAttr), "null", + "null should have been stringified to 'null' for '" + contentAttr + "'"); + is(element[idlAttr], "null", + "null should have been stringified to 'null' for '" + idlAttr + "'"); + element.removeAttribute(contentAttr); + + element[idlAttr] = null; + if (treatNullAs == "EmptyString") { + is(element.getAttribute(contentAttr), "", + "null should have been stringified to '' for '" + contentAttr + "'"); + is(element[idlAttr], "", + "null should have been stringified to '' for '" + idlAttr + "'"); + } else { + is(element.getAttribute(contentAttr), "null", + "null should have been stringified to 'null' for '" + contentAttr + "'"); + is(element[idlAttr], "null", + "null should have been stringified to 'null' for '" + contentAttr + "'"); + } + element.removeAttribute(contentAttr); + + // Tests various strings. + var stringsToTest = [ + // [ test value, expected result ] + [ "", "" ], + [ "null", "null" ], + [ "undefined", "undefined" ], + [ "foo", "foo" ], + [ contentAttr, contentAttr ], + [ idlAttr, idlAttr ], + // TODO: uncomment this when null stringification will follow the specs. + // [ null, "null" ], + [ undefined, "undefined" ], + [ true, "true" ], + [ false, "false" ], + [ 42, "42" ], + // ES5, verse 8.12.8. + [ { toString: function() { return "foo" } }, + "foo" ], + [ { valueOf: function() { return "foo" } }, + "[object Object]" ], + [ { valueOf: function() { return "quux" }, + toString: undefined }, + "quux" ], + [ { valueOf: function() { return "foo" }, + toString: function() { return "bar" } }, + "bar" ] + ]; + + otherValues.forEach(function(v) { stringsToTest.push([v, v]) }); + + stringsToTest.forEach(function([v, r]) { + element.setAttribute(contentAttr, v); + is(element[idlAttr], r, + "IDL attribute '" + idlAttr + "' should return the value it has been set to."); + is(element.getAttribute(contentAttr), r, + "Content attribute '" + contentAttr + "'should return the value it has been set to."); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + is(element[idlAttr], r, + "IDL attribute '" + idlAttr + "' should return the value it has been set to."); + is(element.getAttribute(contentAttr), r, + "Content attribute '" + contentAttr + "' should return the value it has been set to."); + element.removeAttribute(contentAttr); + }); + + // Tests after removeAttribute() is called. Should be equivalent with not set. + is(element.getAttribute(contentAttr), null, + "When not set, the content attribute should be null."); + is(element[idlAttr], "", + "When not set, the IDL attribute should return the empty string"); +} + +/** + * Checks that a given attribute name for a given element is correctly reflected + * as an unsigned int. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * - nonZero Boolean whether the attribute should be non-null + * - defaultValue Integer [optional] default value, if different from the default one + */ +function reflectUnsignedInt(aParameters) +{ + var element = aParameters.element; + var attr = aParameters.attribute; + var nonZero = aParameters.nonZero; + var defaultValue = aParameters.defaultValue; + var fallback = aParameters.fallback; + + if (defaultValue === undefined) { + if (nonZero) { + defaultValue = 1; + } else { + defaultValue = 0; + } + } + + if (fallback === undefined) { + fallback = false; + } + + ok(attr in element, attr + " should be an IDL attribute of this element"); + is(typeof element[attr], "number", attr + " IDL attribute should be a number"); + + // Check default value. + is(element[attr], defaultValue, "default value should be " + defaultValue); + ok(!element.hasAttribute(attr), attr + " shouldn't be present"); + + var values = [ 1, 3, 42, 2147483647 ]; + + for (var value of values) { + element[attr] = value; + is(element[attr], value, "." + attr + " should be equals " + value); + is(element.getAttribute(attr), String(value), + "@" + attr + " should be equals " + value); + + element.setAttribute(attr, value); + is(element[attr], value, "." + attr + " should be equals " + value); + is(element.getAttribute(attr), String(value), + "@" + attr + " should be equals " + value); + } + + // -3000000000 is equivalent to 1294967296 when using the IDL attribute. + element[attr] = -3000000000; + is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296"); + is(element.getAttribute(attr), "1294967296", + "@" + attr + " should be equals to 1294967296"); + + // When setting the content attribute, it's a string so it will be invalid. + element.setAttribute(attr, -3000000000); + is(element.getAttribute(attr), "-3000000000", + "@" + attr + " should be equals to " + -3000000000); + is(element[attr], defaultValue, + "." + attr + " should be equals to " + defaultValue); + + // When interpreted as unsigned 32-bit integers, all of these fall between + // 2^31 and 2^32 - 1, so per spec they return the default value. + var nonValidValues = [ -2147483648, -1, 3147483647]; + + for (var value of nonValidValues) { + element[attr] = value; + is(element.getAttribute(attr), String(defaultValue), + "@" + attr + " should be equals to " + defaultValue); + is(element[attr], defaultValue, + "." + attr + " should be equals to " + defaultValue); + } + + for (var values of nonValidValues) { + element.setAttribute(attr, values[0]); + is(element.getAttribute(attr), String(values[0]), + "@" + attr + " should be equals to " + values[0]); + is(element[attr], defaultValue, + "." + attr + " should be equals to " + defaultValue); + } + + // Setting to 0 should throw an error if nonZero is true. + var caught = false; + try { + element[attr] = 0; + } catch(e) { + caught = true; + is(e.name, "IndexSizeError", "exception should be IndexSizeError"); + is(e.code, DOMException.INDEX_SIZE_ERR, "exception code should be INDEX_SIZE_ERR"); + } + + if (nonZero && !fallback) { + ok(caught, "an exception should have been caught"); + } else { + ok(!caught, "no exception should have been caught"); + } + + // If 0 is set in @attr, it will be ignored when calling .attr. + element.setAttribute(attr, "0"); + is(element.getAttribute(attr), "0", "@" + attr + " should be equals to 0"); + if (nonZero) { + is(element[attr], defaultValue, + "." + attr + " should be equals to " + defaultValue); + } else { + is(element[attr], 0, "." + attr + " should be equals to 0"); + } +} + +/** + * Checks that a given attribute is correctly reflected as limited to known + * values enumerated attribute. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + * - validValues Array valid values we support + * - invalidValues Array invalid values + * - defaultValue String [optional] default value when no valid value is set + * OR + * defaultValue Object [optional] object containing two attributes, 'invalid' and 'missing' + * - unsupportedValues Array [optional] valid values we do not support + * - nullable boolean [optional] whether the attribute is nullable + */ +function reflectLimitedEnumerated(aParameters) +{ + var element = aParameters.element; + var contentAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.content; + var idlAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.idl; + var validValues = aParameters.validValues; + var invalidValues = aParameters.invalidValues; + var defaultValueInvalid = aParameters.defaultValue === undefined + ? "" : typeof aParameters.defaultValue === "string" + ? aParameters.defaultValue : aParameters.defaultValue.invalid + var defaultValueMissing = aParameters.defaultValue === undefined + ? "" : typeof aParameters.defaultValue === "string" + ? aParameters.defaultValue : aParameters.defaultValue.missing + var unsupportedValues = aParameters.unsupportedValues !== undefined + ? aParameters.unsupportedValues : []; + var nullable = aParameters.nullable; + + ok(idlAttr in element, idlAttr + " should be an IDL attribute of this element"); + if (nullable) { + // The missing value default is null, which is typeof == "object" + is(typeof element[idlAttr], "object", "'" + idlAttr + "' IDL attribute should be null, which has typeof == object"); + is(element[idlAttr], null, "'" + idlAttr + "' IDL attribute should be null"); + } else { + is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string"); + } + + if (nullable) { + element.setAttribute(contentAttr, "something"); + // Now it will be a string + is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string"); + } + + // Explicitly check the default value. + element.removeAttribute(contentAttr); + is(element[idlAttr], defaultValueMissing, + "When no attribute is set, the value should be the default value."); + + // Check valid values. + validValues.forEach(function (v) { + element.setAttribute(contentAttr, v); + is(element[idlAttr], v, + "'" + v + "' should be accepted as a valid value for " + idlAttr); + is(element.getAttribute(contentAttr), v, + "Content attribute should return the value it has been set to."); + element.removeAttribute(contentAttr); + + element.setAttribute(contentAttr, v.toUpperCase()); + is(element[idlAttr], v, + "Enumerated attributes should be case-insensitive."); + is(element.getAttribute(contentAttr), v.toUpperCase(), + "Content attribute should not be lower-cased."); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + is(element[idlAttr], v, + "'" + v + "' should be accepted as a valid value for " + idlAttr); + is(element.getAttribute(contentAttr), v, + "Content attribute should return the value it has been set to."); + element.removeAttribute(contentAttr); + + element[idlAttr] = v.toUpperCase(); + is(element[idlAttr], v, + "Enumerated attributes should be case-insensitive."); + is(element.getAttribute(contentAttr), v.toUpperCase(), + "Content attribute should not be lower-cased."); + element.removeAttribute(contentAttr); + }); + + // Check invalid values. + invalidValues.forEach(function (v) { + element.setAttribute(contentAttr, v); + is(element[idlAttr], defaultValueInvalid, + "When the content attribute is set to an invalid value, the default value should be returned."); + is(element.getAttribute(contentAttr), v, + "Content attribute should not have been changed."); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + is(element[idlAttr], defaultValueInvalid, + "When the value is set to an invalid value, the default value should be returned."); + is(element.getAttribute(contentAttr), v, + "Content attribute should not have been changed."); + element.removeAttribute(contentAttr); + }); + + // Check valid values we currently do not support. + // Basically, it's like the checks for the valid values but with some todo's. + unsupportedValues.forEach(function (v) { + element.setAttribute(contentAttr, v); + todo_is(element[idlAttr], v, + "'" + v + "' should be accepted as a valid value for " + idlAttr); + is(element.getAttribute(contentAttr), v, + "Content attribute should return the value it has been set to."); + element.removeAttribute(contentAttr); + + element.setAttribute(contentAttr, v.toUpperCase()); + todo_is(element[idlAttr], v, + "Enumerated attributes should be case-insensitive."); + is(element.getAttribute(contentAttr), v.toUpperCase(), + "Content attribute should not be lower-cased."); + element.removeAttribute(contentAttr); + + element[idlAttr] = v; + todo_is(element[idlAttr], v, + "'" + v + "' should be accepted as a valid value for " + idlAttr); + is(element.getAttribute(contentAttr), v, + "Content attribute should return the value it has been set to."); + element.removeAttribute(contentAttr); + + element[idlAttr] = v.toUpperCase(); + todo_is(element[idlAttr], v, + "Enumerated attributes should be case-insensitive."); + is(element.getAttribute(contentAttr), v.toUpperCase(), + "Content attribute should not be lower-cased."); + element.removeAttribute(contentAttr); + }); + + if (nullable) { + is(defaultValueMissing, null, + "Missing default value should be null for nullable attributes"); + ok(validValues.length > 0, "We better have at least one valid value"); + element.setAttribute(contentAttr, validValues[0]); + ok(element.hasAttribute(contentAttr), + "Should have content attribute: we just set it"); + element[idlAttr] = null; + ok(!element.hasAttribute(contentAttr), + "Should have removed content attribute"); + } +} + +/** + * Checks that a given attribute is correctly reflected as a boolean. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + */ +function reflectBoolean(aParameters) +{ + var element = aParameters.element; + var contentAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.content; + var idlAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.idl; + + ok(idlAttr in element, + idlAttr + " should be an IDL attribute of this element"); + is(typeof element[idlAttr], "boolean", + idlAttr + " IDL attribute should be a boolean"); + + // Tests when the attribute isn't set. + is(element.getAttribute(contentAttr), null, + "When not set, the content attribute should be null."); + is(element[idlAttr], false, + "When not set, the IDL attribute should return false"); + + /** + * Test various values. + * Each value to test is actually an object containing a 'value' property + * containing the value to actually test, a 'stringified' property containing + * the stringified value and a 'result' property containing the expected + * result when the value is set to the IDL attribute. + */ + var valuesToTest = [ + { value: true, stringified: "true", result: true }, + { value: false, stringified: "false", result: false }, + { value: "true", stringified: "true", result: true }, + { value: "false", stringified: "false", result: true }, + { value: "foo", stringified: "foo", result: true }, + { value: idlAttr, stringified: idlAttr, result: true }, + { value: contentAttr, stringified: contentAttr, result: true }, + { value: "null", stringified: "null", result: true }, + { value: "undefined", stringified: "undefined", result: true }, + { value: "", stringified: "", result: false }, + { value: undefined, stringified: "undefined", result: false }, + { value: null, stringified: "null", result: false }, + { value: +0, stringified: "0", result: false }, + { value: -0, stringified: "0", result: false }, + { value: NaN, stringified: "NaN", result: false }, + { value: 42, stringified: "42", result: true }, + { value: Infinity, stringified: "Infinity", result: true }, + { value: -Infinity, stringified: "-Infinity", result: true }, + // ES5, verse 9.2. + { value: { toString: function() { return "foo" } }, stringified: "foo", + result: true }, + { value: { valueOf: function() { return "foo" } }, + stringified: "[object Object]", result: true }, + { value: { valueOf: function() { return "quux" }, toString: undefined }, + stringified: "quux", result: true }, + { value: { valueOf: function() { return "foo" }, + toString: function() { return "bar" } }, stringified: "bar", + result: true }, + { value: { valueOf: function() { return false } }, + stringified: "[object Object]", result: true }, + { value: { foo: false, bar: false }, stringified: "[object Object]", + result: true }, + { value: { }, stringified: "[object Object]", result: true }, + ]; + + valuesToTest.forEach(function(v) { + element.setAttribute(contentAttr, v.value); + is(element[idlAttr], true, + "IDL attribute should return always return 'true' if the content attribute has been set"); + is(element.getAttribute(contentAttr), v.stringified, + "Content attribute should return the stringified value it has been set to."); + element.removeAttribute(contentAttr); + + element[idlAttr] = v.value; + is(element[idlAttr], v.result, "IDL attribute should return " + v.result); + is(element.getAttribute(contentAttr), v.result ? "" : null, + v.result ? "Content attribute should return the empty string." + : "Content attribute should return null."); + is(element.hasAttribute(contentAttr), v.result, + v.result ? contentAttr + " should not be present" + : contentAttr + " should be present"); + element.removeAttribute(contentAttr); + }); + + // Tests after removeAttribute() is called. Should be equivalent with not set. + is(element.getAttribute(contentAttr), null, + "When not set, the content attribute should be null."); + is(element[contentAttr], false, + "When not set, the IDL attribute should return false"); +} + +/** + * Checks that a given attribute name for a given element is correctly reflected + * as an signed integer. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test on + * - attribute String name of the attribute + * - nonNegative Boolean true if the attribute is limited to 'non-negative numbers', false otherwise + * - defaultValue Integer [optional] default value, if one exists + */ +function reflectInt(aParameters) +{ + // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute(). + function expectedGetAttributeResult(value) { + return String(value); + } + + function stringToInteger(value, nonNegative, defaultValue) { + // Parse: Ignore leading whitespace, find [+/-][numbers] + var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value); + if (result) { + var resultInt = parseInt(result[1], 10); + if ((nonNegative ? 0 : -0x80000000) <= resultInt && resultInt <= 0x7FFFFFFF) { + // If the value is within allowed value range for signed/unsigned + // integer, return it -- but add 0 to it to convert a possible -0 into + // +0, the only zero present in the signed integer range. + return resultInt + 0; + } + } + return defaultValue; + } + + // Expected value returned by .getAttribute(attr) or .attr if |value| has been set via the IDL attribute. + function expectedIdlAttributeResult(value) { + // This returns the result of calling the ES ToInt32 algorithm on value. + return value << 0; + } + + var element = aParameters.element; + var attr = aParameters.attribute; + var nonNegative = aParameters.nonNegative; + + var defaultValue = aParameters.defaultValue !== undefined + ? aParameters.defaultValue + : nonNegative ? -1 : 0; + + ok(attr in element, attr + " should be an IDL attribute of this element"); + is(typeof element[attr], "number", attr + " IDL attribute should be a number"); + + // Check default value. + is(element[attr], defaultValue, "default value should be " + defaultValue); + ok(!element.hasAttribute(attr), attr + " shouldn't be present"); + + /** + * Test various values. + * value: The test value that will be set using both setAttribute(value) and + * element[attr] = value + */ + var valuesToTest = [ + // Test numeric inputs up to max signed integer + 0, 1, 55555, 2147483647, +42, + // Test string inputs up to max signed integer + "0", "1", "777777", "2147483647", "+42", + // Test negative numeric inputs up to min signed integer + -0, -1, -3333, -2147483648, + // Test negative string inputs up to min signed integer + "-0", "-1", "-222", "-2147483647", "-2147483648", + // Test numeric inputs that are outside legal 32 bit signed values + -2147483649, -3000000000, -4294967296, 2147483649, 4000000000, -4294967297, + // Test string inputs with extra padding + " 1111111", " 23456 ", + // Test non-numeric string inputs + "", " ", "+", "-", "foo", "+foo", "-foo", "+ foo", "- foo", "+-2", "-+2", "++2", "--2", "hello1234", "1234hello", + "444 world 555", "why 567 what", "-3 nots", "2e5", "300e2", "42+-$", "+42foo", "-514not", "\vblah", "0x10FFFF", "-0xABCDEF", + // Test decimal numbers + 1.2345, 42.0, 3456789.1, -2.3456, -6789.12345, -2147483649.1234, + // Test decimal strings + "1.2345", "42.0", "3456789.1", "-2.3456", "-6789.12345", "-2147483649.1234", + // Test special values + undefined, null, NaN, Infinity, -Infinity, + ]; + + valuesToTest.forEach(function(v) { + var intValue = stringToInteger(v, nonNegative, defaultValue); + + element.setAttribute(attr, v); + + is(element.getAttribute(attr), expectedGetAttributeResult(v), element.localName + ".setAttribute(" + + attr + ", " + v + "), " + element.localName + ".getAttribute(" + attr + ") "); + + is(element[attr], intValue, element.localName + + ".setAttribute(" + attr + ", " + v + "), " + element.localName + "[" + attr + "] "); + element.removeAttribute(attr); + + if (nonNegative && expectedIdlAttributeResult(v) < 0) { + try { + element[attr] = v; + ok(false, element.localName + "[" + attr + "] = " + v + " should throw IndexSizeError"); + } catch(e) { + is(e.name, "IndexSizeError", element.localName + "[" + attr + "] = " + v + + " should throw IndexSizeError"); + is(e.code, DOMException.INDEX_SIZE_ERR, element.localName + "[" + attr + "] = " + v + + " should throw INDEX_SIZE_ERR"); + } + } else { + element[attr] = v; + is(element[attr], expectedIdlAttributeResult(v), element.localName + "[" + attr + "] = " + v + + ", " + element.localName + "[" + attr + "] "); + is(element.getAttribute(attr), String(expectedIdlAttributeResult(v)), + element.localName + "[" + attr + "] = " + v + ", " + + element.localName + ".getAttribute(" + attr + ") "); + } + element.removeAttribute(attr); + }); + + // Tests after removeAttribute() is called. Should be equivalent with not set. + is(element.getAttribute(attr), null, + "When not set, the content attribute should be null."); + is(element[attr], defaultValue, + "When not set, the IDL attribute should return default value."); +} + +/** + * Checks that a given attribute is correctly reflected as a url. + * + * @param aParameters Object object containing the parameters, which are: + * - element Element node to test + * - attribute String name of the attribute + * OR + * attribute Object object containing two attributes, 'content' and 'idl' + */ +function reflectURL(aParameters) +{ + var element = aParameters.element; + var contentAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.content; + var idlAttr = typeof aParameters.attribute === "string" + ? aParameters.attribute : aParameters.attribute.idl; + + element[idlAttr] = ""; + is(element[idlAttr], document.URL, "Empty string should resolve to document URL"); +} diff --git a/dom/html/test/simpleFileOpener.js b/dom/html/test/simpleFileOpener.js new file mode 100644 index 000000000..eeffdb6a1 --- /dev/null +++ b/dom/html/test/simpleFileOpener.js @@ -0,0 +1,32 @@ +var { classes: Cc, interfaces: Ci, utils: Cu } = Components; +Cu.importGlobalProperties(["File"]); + +var file; + +addMessageListener("file.open", function (stem) { + try { + if (!file) { + file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile); + file.append(stem); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + } + sendAsyncMessage("file.opened", { + fullPath: file.path, + leafName: file.leafName, + domFile: File.createFromNsIFile(file), + }); + } catch(e) { + sendAsyncMessage("fail", e.toString()); + } +}); + +addMessageListener("file.remove", function () { + try { + file.remove(/* recursive: */ false); + file = undefined; + sendAsyncMessage("file.removed", null); + } catch(e) { + sendAsyncMessage("fail", e.toString()); + } +}); diff --git a/dom/html/test/test_a_text.html b/dom/html/test/test_a_text.html new file mode 100644 index 000000000..5ffc1995f --- /dev/null +++ b/dom/html/test/test_a_text.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for a.text</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> + <link rel="help" href="http://www.whatwg.org/html/#dom-a-text"/> +</head> +<body> +<div id="content"> +<a href="a">a b c</a> +<a href="b">a <!--b--> c</a> +<a href="c">a <b>b</b> c</a> +</div> +<pre id="test"> +<script> +var d = document.getElementById("content") + .appendChild(document.createElement("a")); +d.href = "d"; +d.appendChild(document.createTextNode("a ")); +d.appendChild(document.createTextNode("b ")); +d.appendChild(document.createTextNode("c ")); +var expected = ["a b c", "a c", "a b c", "a b c "]; +var list = document.getElementById("content").getElementsByTagName("a"); +for (var i = 0, il = list.length; i < il; ++i) { + is(list[i].text, list[i].textContent); + is(list[i].text, expected[i]); + + list[i].text = "x"; + is(list[i].text, "x"); + is(list[i].textContent, "x"); + is(list[i].firstChild.data, "x"); + is(list[i].childNodes.length, 1); + + list[i].textContent = "y"; + is(list[i].text, "y"); + is(list[i].textContent, "y"); + is(list[i].firstChild.data, "y"); + is(list[i].childNodes.length, 1); +} +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_allowMedia.html b/dom/html/test/test_allowMedia.html new file mode 100644 index 000000000..f4e7b5c67 --- /dev/null +++ b/dom/html/test/test_allowMedia.html @@ -0,0 +1,99 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=759964 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 759964</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 759964 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runNextTest); + +var SJS = "http://mochi.test:8888/tests/dom/html/test/allowMedia.sjs"; +var TEST_PAGE = "data:text/html,<audio src='" + SJS + "?audio'></audio>"; + +var Ci = Components.interfaces; + +function runNextTest() { + var test = tests.shift(); + if (!test) { + SimpleTest.finish(); + return; + } + test(); +} + +var tests = [ + + // Set allowMedia = false, load a page with <audio>, verify the <audio> + // doesn't load its source. + function basic() { + var iframe = insertIframe(); + SpecialPowers.allowMedia(iframe.contentWindow, false); + loadIframe(iframe, TEST_PAGE, function () { + verifyPass(); + iframe.remove(); + runNextTest(); + }); + }, + + // Set allowMedia = false on parent docshell, load a page with <audio> in a + // child iframe, verify the <audio> doesn't load its source. + function inherit() { + SpecialPowers.allowMedia(window, false); + + var iframe = insertIframe(); + loadIframe(iframe, TEST_PAGE, function () { + verifyPass(); + iframe.remove(); + SpecialPowers.allowMedia(window, true); + runNextTest(); + }); + }, + + // In a display:none iframe, set allowMedia = false, load a page with <audio>, + // verify the <audio> doesn't load its source. + function displayNone() { + var iframe = insertIframe(); + iframe.style.display = "none"; + SpecialPowers.allowMedia(iframe.contentWindow, false); + loadIframe(iframe, TEST_PAGE, function () { + verifyPass(); + iframe.remove(); + runNextTest(); + }); + }, +]; + +function insertIframe() { + var iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + return iframe; +} + +function loadIframe(iframe, url, onDone) { + iframe.setAttribute("src", url); + iframe.addEventListener("load", onDone); +} + +function verifyPass() { + var xhr = new XMLHttpRequest(); + xhr.open("GET", SJS, false); + xhr.send(); + is(xhr.responseText, "PASS", "<audio> source should not have been loaded."); +} + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=759964">Mozilla Bug 759964</a> +<p id="display"> +</p> +</body> +</html> diff --git a/dom/html/test/test_anchor_href_cache_invalidation.html b/dom/html/test/test_anchor_href_cache_invalidation.html new file mode 100644 index 000000000..554f35e10 --- /dev/null +++ b/dom/html/test/test_anchor_href_cache_invalidation.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for anchor cache invalidation</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + <a id="x" href="http://example.com"></a> +</div> +<pre id="test"> +<script type="application/javascript"> + +is($("x").href, "http://example.com/"); +is($("x").host, "example.com"); + +$("x").href = "http://www.example.com"; + +is($("x").href, "http://www.example.com/"); +is($("x").host, "www.example.com"); + +$("x").setAttribute("href", "http://www.example.net/"); +is($("x").host, "www.example.net"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_anchor_ping.html b/dom/html/test/test_anchor_ping.html new file mode 100644 index 000000000..4a39bcefe --- /dev/null +++ b/dom/html/test/test_anchor_ping.html @@ -0,0 +1,309 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=786347 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 786347</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript;version=1.8"> + + /** Test for Bug 786347 **/ + +SimpleTest.waitForExplicitFinish(); + +var Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://testing-common/httpd.js"); +Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); + +addLoadEvent(function () { + Task.spawn(function run_tests() { + while (tests.length) { + let test = tests.shift(); + info("-- running " + test.name); + yield Task.spawn(test); + } + + SimpleTest.finish(); + }); +}); + +let tests = [ + + // Ensure that sending pings is enabled. + function* setup() { + Services.prefs.setBoolPref("browser.send_pings", true); + Services.prefs.setIntPref("browser.send_pings.max_per_link", -1); + Services.prefs.setBoolPref("security.mixed_content.block_active_content", false); + // The server we create can't handle the priming HEAD requests + Services.prefs.setBoolPref("security.mixed_content.send_hsts_priming", false); + + SimpleTest.registerCleanupFunction(() => { + Services.prefs.clearUserPref("browser.send_pings"); + Services.prefs.clearUserPref("browser.send_pings.max_per_link"); + Services.prefs.clearUserPref("security.mixed_content.block_active_content"); + Services.prefs.clearUserPref("security.mixed_content.send_hsts_priming"); + }); + }, + + // If both the address of the document containing the hyperlink being audited + // and ping URL have the same origin then the request must include a Ping-From + // HTTP header with, as its value, the address of the document containing the + // hyperlink, and a Ping-To HTTP header with, as its value, the target URL. + // The request must not include a Referer (sic) HTTP header. + function* same_origin() { + let from = "/ping-from/" + Math.random(); + let to = "/ping-to/" + Math.random(); + let ping = "/ping/" + Math.random(); + + let base; + let server = new HttpServer(); + + // The page that contains the link. + createFromPathHandler(server, from, to, () => ping); + + // The page that the link's href points to. + let promiseHref = createToPathHandler(server, to); + + // The ping we want to receive. + let promisePing = createPingPathHandler(server, ping, () => { + return {from: base + from, to: base + to}; + }); + + // Start the server, get its base URL and run the test. + server.start(-1); + base = "http://localhost:" + server.identity.primaryPort; + navigate(base + from); + + // Wait until the target and ping url have loaded. + yield Promise.all([promiseHref, promisePing]); + + // Cleanup. + yield stopServer(server); + }, + + // If the origins are different, but the document containing the hyperlink + // being audited was not retrieved over an encrypted connection then the + // request must include a Referer (sic) HTTP header with, as its value, the + // address of the document containing the hyperlink, a Ping-From HTTP header + // with the same value, and a Ping-To HTTP header with, as its value, target + // URL. + function* diff_origin() { + let from = "/ping-from/" + Math.random(); + let to = "/ping-to/" + Math.random(); + let ping = "/ping/" + Math.random(); + + // We will use two servers to simulate two different origins. + let base, base2; + let server = new HttpServer(); + let server2 = new HttpServer(); + + // The page that contains the link. + createFromPathHandler(server, from, to, () => base2 + ping); + + // The page that the link's href points to. + let promiseHref = createToPathHandler(server, to); + + // Start the first server and get its base URL. + server.start(-1); + base = "http://localhost:" + server.identity.primaryPort; + + // The ping we want to receive. + let promisePing = createPingPathHandler(server2, ping, () => { + return {referrer: base + from, from: base + from, to: base + to}; + }); + + // Start the second server, get its base URL and run the test. + server2.start(-1); + base2 = "http://localhost:" + server2.identity.primaryPort; + navigate(base + from); + + // Wait until the target and ping url have loaded. + yield Promise.all([promiseHref, promisePing]); + + // Cleanup. + yield stopServer(server); + yield stopServer(server2); + }, + + // If the origins are different and the document containing the hyperlink + // being audited was retrieved over an encrypted connection then the request + // must include a Ping-To HTTP header with, as its value, target URL. The + // request must neither include a Referer (sic) HTTP header nor include a + // Ping-From HTTP header. + function* diff_origin_secure_referrer() { + let ping = "/ping/" + Math.random(); + let server = new HttpServer(); + + // The ping we want to receive. + let promisePing = createPingPathHandler(server, ping, () => { + return {to: "https://example.com/"}; + }); + + // Start the server and run the test. + server.start(-1); + + // The referrer will be loaded using a secure channel. + navigate("https://example.com/chrome/dom/html/test/" + + "file_anchor_ping.html?" + "http://localhost:" + + server.identity.primaryPort + ping); + + // Wait until the ping has been sent. + yield promisePing; + + // Cleanup. + yield stopServer(server); + }, + + // Test that the <a ping> attribute is properly tokenized using ASCII white + // space characters as separators. + function* tokenize_white_space() { + let from = "/ping-from/" + Math.random(); + let to = "/ping-to/" + Math.random(); + + let base; + let server = new HttpServer(); + + let pings = [ + "/ping1/" + Math.random(), + "/ping2/" + Math.random(), + "/ping3/" + Math.random(), + "/ping4/" + Math.random() + ]; + + // The page that contains the link. + createFromPathHandler(server, from, to, () => { + return " " + pings[0] + " \r " + pings[1] + " \t " + + pings[2] + " \n " + pings[3] + " "; + }); + + // The page that the link's href points to. + let promiseHref = createToPathHandler(server, to); + + // The pings we want to receive. + let pingPathHandlers = createPingPathHandlers(server, pings, () => { + return {from: base + from, to: base + to}; + }); + + // Start the server, get its base URL and run the test. + server.start(-1); + base = "http://localhost:" + server.identity.primaryPort; + navigate(base + from); + + // Wait until the target and ping url have loaded. + yield Promise.all([promiseHref, ...pingPathHandlers]); + + // Cleanup. + yield stopServer(server); + } +]; + +// Navigate the iframe used for testing to a new URL. +function navigate(uri) { + document.getElementById("frame").src = uri; +} + +// Registers a path handler for the given server that will serve a page +// containing an <a ping> element. The page will automatically simulate +// clicking the link after it has loaded. +function createFromPathHandler(server, path, href, lazyPing) { + server.registerPathHandler(path, function (request, response) { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html;charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + + let body = '<body onload="document.body.firstChild.click()">' + + '<a href="' + href + '" ping="' + lazyPing() + '"></a></body>'; + response.write(body); + }); +} + +// Registers a path handler for the given server that will serve a simple empty +// page we can use as the href attribute for links. It returns a promise that +// will be resolved once the page has been requested. +function createToPathHandler(server, path) { + let deferred = Promise.defer(); + + server.registerPathHandler(path, function (request, response) { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html;charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + response.write("OK"); + + deferred.resolve(); + }); + + return deferred.promise; +} + +// Register multiple path handlers for the given server that will receive +// pings as sent when an <a ping> element is clicked. This method uses +// createPingPathHandler() defined below to ensure all headers are sent +// and received as expected. +function createPingPathHandlers(server, paths, lazyHeaders) { + return Array.from(paths, (path) => createPingPathHandler(server, path, lazyHeaders)); +} + +// Registers a path handler for the given server that will receive pings as +// sent when an <a ping> element has been clicked. It will check that the +// correct http method has been used, the post data is correct and all headers +// are given as expected. It returns a promise that will be resolved once the +// ping has been received. +function createPingPathHandler(server, path, lazyHeaders) { + let deferred = Promise.defer(); + + server.registerPathHandler(path, function (request, response) { + let headers = lazyHeaders(); + + is(request.method, "POST", "correct http method used"); + is(request.getHeader("Ping-To"), headers.to, "valid ping-to header"); + + if ("from" in headers) { + is(request.getHeader("Ping-From"), headers.from, "valid ping-from header"); + } else { + ok(!request.hasHeader("Ping-From"), "no ping-from header"); + } + + if ("referrer" in headers) { + is(request.getHeader("Referer"), headers.referrer, "valid referer header"); + } else { + ok(!request.hasHeader("Referer"), "no referer header"); + } + + let bs = request.bodyInputStream; + let body = NetUtil.readInputStreamToString(bs, bs.available()); + is(body, "PING", "correct body sent"); + + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html;charset=utf-8", false); + response.setHeader("Cache-Control", "no-cache", false); + response.write("OK"); + + deferred.resolve(); + }); + + return deferred.promise; +} + +// Returns a promise that is resolved when the given http server instance has +// been stopped. +function stopServer(server) { + let deferred = Promise.defer(); + server.stop(deferred.resolve); + return deferred.promise; +} + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786347">Mozilla Bug 786347</a> +<p id="display"></p> +<iframe id="frame" /> +</body> +</html> diff --git a/dom/html/test/test_applet_attributes_reflection.html b/dom/html/test/test_applet_attributes_reflection.html new file mode 100644 index 000000000..dd04a2022 --- /dev/null +++ b/dom/html/test/test_applet_attributes_reflection.html @@ -0,0 +1,86 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLAppletElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLAppletElement attributes reflection **/ + +// .align (String) +reflectString({ + element: document.createElement("applet"), + attribute: "align", +}); + +// .alt (String) +reflectString({ + element: document.createElement("applet"), + attribute: "alt", +}); + +// .archive (String) +reflectString({ + element: document.createElement("applet"), + attribute: "archive", +}); + +// .code (String) +reflectString({ + element: document.createElement("applet"), + attribute: "code", +}); + +// .codeBase (URL) +reflectURL({ + element: document.createElement("applet"), + attribute: "codeBase", +}); + +// .height (String) +reflectString({ + element: document.createElement("applet"), + attribute: "height", +}); + +// .hspace (unsigned int) +reflectUnsignedInt({ + element: document.createElement("applet"), + attribute: "hspace", +}); + +// .name (String) +reflectString({ + element: document.createElement("applet"), + attribute: "name", +}); + +// .object (URL) +reflectURL({ + element: document.createElement("applet"), + attribute: "object", +}); + +// .vspace (unsigned int) +reflectUnsignedInt({ + element: document.createElement("applet"), + attribute: "vspace", +}); + +// .width (String) +reflectString({ + element: document.createElement("applet"), + attribute: "width", +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_audio_wakelock.html b/dom/html/test/test_audio_wakelock.html new file mode 100644 index 000000000..a45f2405b --- /dev/null +++ b/dom/html/test/test_audio_wakelock.html @@ -0,0 +1,125 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=868943 +--> +<head> + <title>Test for Bug 868943</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=868943">Mozilla Bug 868943</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 868943 **/ + +function testAudioPlayPause() { + var lockState = true; + var count = 0; + + var content = document.getElementById('content'); + + var audio = document.createElement('audio'); + audio.src = "wakelock.ogg"; + content.appendChild(audio); + + var startDate; + function testAudioPlayListener(topic, state) { + is(topic, "cpu", "#1 Audio element locked the target == cpu"); + var locked = state == "locked-foreground" || + state == "locked-background"; + + var s = locked ? "locked" : "unlocked"; + is(locked, lockState, "#1 Audio element " + s + " the cpu"); + count++; + + // count == 1 is when the cpu wakelock is created + // count == 2 is when the cpu wakelock is released + + if (count == 1) { + // The next step is to unlock the resource. + lockState = false; + audio.pause(); + startDate = new Date(); + return; + } + + is(count, 2, "The count should be 2 which indicates wakelock release"); + + if (count == 2) { + var diffDate = (new Date() - startDate); + ok(diffDate > 200, "#1 There was at least 200 milliseconds between the stop and the wakelock release"); + + content.removeChild(audio); + navigator.mozPower.removeWakeLockListener(testAudioPlayListener); + runTests(); + } + }; + + navigator.mozPower.addWakeLockListener(testAudioPlayListener); + audio.play(); +} + +function testAudioPlay() { + var lockState = true; + var count = 0; + + var content = document.getElementById('content'); + + var audio = document.createElement('audio'); + audio.src = "wakelock.ogg"; + content.appendChild(audio); + + function testAudioPlayListener(topic, state) { + is(topic, "cpu", "#2 Audio element locked the target == cpu"); + var locked = state == "locked-foreground" || + state == "locked-background"; + + var s = locked ? "locked" : "unlocked"; + is(locked, lockState, "#2 Audio element " + s + " the cpu"); + count++; + + // count == 1 is when the cpu wakelock is created: the wakelock must be + // created when the media element starts playing. + // count == 2 is when the cpu wakelock is released. + + if (count == 1) { + // The next step is to unlock the resource. + lockState = false; + } else if (count == 2) { + content.removeChild(audio); + navigator.mozPower.removeWakeLockListener(testAudioPlayListener); + runTests(); + } + }; + + navigator.mozPower.addWakeLockListener(testAudioPlayListener); + audio.play(); +} + +var tests = [ testAudioPlayPause, testAudioPlay ]; +function runTests() { + if (!tests.length) { + SimpleTest.finish(); + return; + } + + var test = tests.pop(); + test(); +}; + +SpecialPowers.pushPrefEnv({"set": [["media.wakelock_timeout", 500]]}, runTests); + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_base_attributes_reflection.html b/dom/html/test/test_base_attributes_reflection.html new file mode 100644 index 000000000..e8398f88a --- /dev/null +++ b/dom/html/test/test_base_attributes_reflection.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLBaseElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLBaseElement attributes reflection **/ + +// .href is sort of like a URL reflection, but with some special rules. Watch +// out for that! +reflectURL({ + element: document.createElement("base"), + attribute: "href" +}); + +// .target +reflectString({ + element: document.createElement("base"), + attribute: "target" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1003539.html b/dom/html/test/test_bug1003539.html new file mode 100644 index 000000000..041e813d2 --- /dev/null +++ b/dom/html/test/test_bug1003539.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1003539 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1003539</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1003539 **/ +// Refering to this specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#dom-table-insertrow +var tab; +tab = document.createElement("table"); +tab.createTHead(); +tab.insertRow(); +is(tab.innerHTML, '<thead></thead><tbody><tr></tr></tbody>', "Row should be inserted in the tbody."); + +tab = document.createElement("table"); +tab.createTBody(); +tab.createTBody(); +tab.insertRow(); +is(tab.innerHTML, '<tbody></tbody><tbody><tr></tr></tbody>', "Row should be inserted in the last tbody."); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1003539">Mozilla Bug 1003539</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug100533.html b/dom/html/test/test_bug100533.html new file mode 100644 index 000000000..d5e45fa47 --- /dev/null +++ b/dom/html/test/test_bug100533.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=100533 +--> +<head> + <title>Test for Bug 100533</title> + <script type="text/javascript" src="/MochiKit/Base.js"></script> + <script type="text/javascript" src="/MochiKit/DOM.js"></script> + <script type="text/javascript" src="/MochiKit/Style.js"></script> + <script type="text/javascript" src="/MochiKit/Signal.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=100533">Mozilla Bug 100533</a> +<p id="display"></p> +<div id="content" > + +<button id="thebutton">Test</button> +<iframe style='display: none;' src='bug100533_iframe.html' id='a'></iframe> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); + +/** Test for Bug 100533 **/ +var submitIframeForm = function() { + $('a').contentDocument.getElementById('b').submit(); +} + +submitted = function() { + ok(true, "Finished. Form submits when located in iframe set to display:none;"); + SimpleTest.finish(); +}; + +addLoadEvent(function() { + connect("thebutton", "click", submitIframeForm); + signal("thebutton", "click"); +}); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug1013316.html b/dom/html/test/test_bug1013316.html new file mode 100644 index 000000000..bb7aa928f --- /dev/null +++ b/dom/html/test/test_bug1013316.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1013316 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1013316</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1013316 **/ + SimpleTest.waitForExplicitFinish(); + addLoadEvent(function() { + is(Object.keys(document.all).length, 15, "We have 15 indexed props"); + var props = Object.getOwnPropertyNames(document.all); + is(props.length, 20, "Should have five names"); + is(props[15], "display", "display first"); + is(props[16], "content", "content second"); + is(props[17], "bar", "bar third"); + is(props[18], "foo", "foo fourth"); + is(props[19], "test", "test fifth"); + + is(Object.keys(document.images).length, 2, "We have 2 indexed props"); + props = Object.getOwnPropertyNames(document.images); + is(props.length, 5, "Should have 3 names"); + is(props[2], "display", "display first on document.images"); + is(props[3], "bar", "bar second on document.images"); + is(props[4], "foo", "foo third on document.images"); + SimpleTest.finish(); + }) + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013316">Mozilla Bug 1013316</a> +<p id="display"></p> +<div id="content" style="display: none"> + <img id="display"> + <img name="foo" id="bar"> + <div name="baz"> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1045270.html b/dom/html/test/test_bug1045270.html new file mode 100644 index 000000000..9011f91ec --- /dev/null +++ b/dom/html/test/test_bug1045270.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> + <!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1045270 +--> + <head> + <title>Test for Bug 583514</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + </head> + <body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1045270">Mozilla Bug 1045270</a> + <p id="display"></p> + <div id="content"> + <input type=number> + </div> + <pre id="test"> + <script type="application/javascript"> + + /** Test for Bug 1045270 **/ + + var input = document.querySelector("input"); + SimpleTest.waitForExplicitFinish(); + SimpleTest.waitForFocus(function() { + input.focus(); + input.addEventListener("input", function() { + // reframe + document.body.style.display = "none"; + document.body.style.display = ""; + document.body.offsetLeft; // flush + }, false); + synthesizeKey("1", {}); + SimpleTest.executeSoon(function() { + synthesizeKey("2", {}); + SimpleTest.executeSoon(function() { + is(input.value, "12", "Reframe should restore focus and selection properly"); + SimpleTest.finish(); + }); + }); + }); + + </script> + </pre> + </body> +</html> diff --git a/dom/html/test/test_bug1081037.html b/dom/html/test/test_bug1081037.html new file mode 100644 index 000000000..9d8782580 --- /dev/null +++ b/dom/html/test/test_bug1081037.html @@ -0,0 +1,133 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1081037 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1081037</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1081037 **/ + +function shouldThrow(fun, msg, ex, todo) { + try { + fun(); + ok(todo, msg); + } catch (e) { + ok(new RegExp(ex).test(e), msg + " (thrown:" + e + ")") + } +} + +var Foo = document.registerElement('x-foo', { + prototype: {bar: 5} +}); + +Foo.prototype.bar = 6; +var foo = new Foo(); +is(foo.bar, 6, "prototype of the ctor returned from registerElement works"); + +var protoDesc = Object.getOwnPropertyDescriptor(Foo, "prototype"); +is(protoDesc.configurable, false, "proto should be non-configurable"); +is(protoDesc.enumerable, false, "proto should be non-enumerable"); +is(protoDesc.writable, false, "proto should be non-writable"); + +// TODO: FIXME! +shouldThrow(function() { + document.registerElement('x-foo2', { + prototype: Foo.prototype + }); + }, + "if proto is an interface prototype object, registerElement should throw", + "not supported", + /* todo = */ true); + +var nonConfigReadonlyProto = Object.create(HTMLElement.prototype, + { constructor: { configurable: false, writable: false, value: 42 } }); + +shouldThrow(function() { + document.registerElement('x-nonconfig-readonly', { + prototype: nonConfigReadonlyProto + }); + }, + "non-configurable and not-writable constructor property", + "not supported"); + + +// this is not defined in current spec: +var readonlyProto = Object.create(HTMLElement.prototype, + { constructor: { configurable: true, writable: false, value: 42 } }); + +var Readonly = document.registerElement('x-nonconfig-readonly', { + prototype: readonlyProto +}); + +is(Readonly.prototype, readonlyProto, "configurable readonly constructor property"); + +var handler = { + getOwnPropertyDescriptor: function(target, name) { + return name == "constructor" ? undefined : Object.getOwnPropertyDescriptor(target,name); + }, + defineProperty: function(target, name, propertyDescriptor) { + if (name == "constructor") { + throw "spec this"; + } + + return Object.defineProperty(target, name, propertyDescriptor); + }, + has: function(target, name) { + if (name == "constructor") { + return false; + } + return name in target; + } +}; +var proxy = new Proxy({}, handler); + +shouldThrow(function() { + document.registerElement('x-proxymagic', { + prototype: proxy + }); + }, + "proxy magic", + "spec this"); + +var getOwn = 0; +var defineProp = 0; +var handler2 = { + getOwnPropertyDescriptor: function(target, name) { + if (name == "constructor") { + getOwn++; + } + return Object.getOwnPropertyDescriptor(target,name); + }, + defineProperty: function(target, name, propertyDescriptor) { + if (name == "constructor") { + defineProp++; + } + return Object.defineProperty(target, name, propertyDescriptor); + } +}; +var proxy2 = new Proxy({}, handler2); + +document.registerElement('x-proxymagic2', { + prototype: proxy2 +}); + +is(getOwn, 1, "number of getOwnPropertyDescriptor calls from registerElement: " + getOwn); +is(defineProp, 1, "number of defineProperty calls from registerElement: " + defineProp); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081037">Mozilla Bug 1081037</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug109445.html b/dom/html/test/test_bug109445.html new file mode 100644 index 000000000..27ffe2294 --- /dev/null +++ b/dom/html/test/test_bug109445.html @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=109445 +--> +<head> + <title>Test for Bug 109445</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=109445">Mozilla Bug 109445</a> +<p id="display"> +<map name=a> +<area shape=rect coords=25,25,75,75 href=#x> +</map> +<map id=b> +<area shape=rect coords=25,25,75,75 href=#y> +</map> +<map name=a> +<area shape=rect coords=25,25,75,75 href=#FAIL> +</map> +<map id=b> +<area shape=rect coords=25,25,75,75 href=#FAIL> +</map> + +<img usemap=#a src=image.png> +<img usemap=#b src=image.png> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 109445 **/ +SimpleTest.waitForExplicitFinish(); +var images = document.getElementsByTagName("img"); +var second = false; +onhashchange = function() { + if (!second) { + second = true; + is(location.hash, "#x", "First map"); + SimpleTest.waitForFocus(() => synthesizeMouse(images[1], 50, 50, {})); + } else { + is(location.hash, "#y", "Second map"); + SimpleTest.finish(); + } +}; +SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {})); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug109445.xhtml b/dom/html/test/test_bug109445.xhtml new file mode 100644 index 000000000..b1524c8ea --- /dev/null +++ b/dom/html/test/test_bug109445.xhtml @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=109445 +--> +<head> + <title>Test for Bug 109445</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=109445">Mozilla Bug 109445</a> +<p id="display"> +<map name="a"> +<area shape="rect" coords="25,25,75,75" href="#x"/> +</map> +<map id="b"> +<area shape="rect" coords="25,25,75,75" href="#y"/> +</map> +<map name="a"> +<area shape="rect" coords="25,25,75,75" href="#FAIL"/> +</map> +<map id="b"> +<area shape="rect" coords="25,25,75,75" href="#FAIL"/> +</map> + +<img usemap="#a" src="image.png"/> +<img usemap="#b" src="image.png"/> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 109445 **/ +SimpleTest.waitForExplicitFinish(); +var images = document.getElementsByTagName("img"); +var second = false; +onhashchange = function() { + if (!second) { + second = true; + is(location.hash, "#x", "First map"); + SimpleTest.waitForFocus(() => synthesizeMouse(images[1], 50, 50, {})); + } else { + is(location.hash, "#y", "Second map"); + SimpleTest.finish(); + } +}; +SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {})); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1146116.html b/dom/html/test/test_bug1146116.html new file mode 100644 index 000000000..a4a4431cf --- /dev/null +++ b/dom/html/test/test_bug1146116.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1146116 +--> +<head> + <title>Test for Bug 1146116</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1146116">Mozilla Bug 1146116</a> +<p id="display"> + <input type="file" id="file"> +</p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript;version=1.7"> +/** Test for bug 1146116 **/ + +SimpleTest.waitForExplicitFinish(); + +const helperURL = SimpleTest.getTestFileURL("simpleFileOpener.js"); +const helper = SpecialPowers.loadChromeScript(helperURL); +helper.addMessageListener("fail", function onFail(message) { + is(message, null, "chrome script failed"); + SimpleTest.finish(); +}); +helper.addMessageListener("file.opened", onFileOpened); +helper.sendAsyncMessage("file.open", "test_bug1146116.txt"); + +function getGlobal(thing) { + return SpecialPowers.unwrap(SpecialPowers.Cu.getGlobalForObject(thing)); +} + +function onFileOpened(message) { + const file = message.domFile; + const elem = document.getElementById("file"); + is(getGlobal(elem), window, + "getGlobal() works as expected"); + isnot(getGlobal(file), window, + "File from MessageManager is wrapped"); + SpecialPowers.wrap(elem).mozSetFileArray([file]); + is(getGlobal(elem.files[0]), window, + "File read back from input element is not wrapped"); + helper.addMessageListener("file.removed", onFileRemoved); + helper.sendAsyncMessage("file.remove", null); +} + +function onFileRemoved() { + helper.destroy(); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1166138.html b/dom/html/test/test_bug1166138.html new file mode 100644 index 000000000..889416775 --- /dev/null +++ b/dom/html/test/test_bug1166138.html @@ -0,0 +1,130 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1166138 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1166138</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1166138">Mozilla Bug 1166138</a> + <p id="display"></p> + <div id="content" style="display: none"> + </div> + + <img srcset="file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x" + src="file_bug1166138_def.png" + onload="onLoad()"> + + <script type="application/javascript"> + var img1x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_1x.png"; + var img2x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_2x.png"; + var imgdef = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_def.png"; + var onLoadCallback = null; + var done = false; + + var startPromise = new Promise((a) => { + onLoadCallback = () => { + var image = document.querySelector('img'); + // If we aren't starting at 2x scale, resize to 2x scale, and wait for a load + if (image.currentSrc != img2x) { + onLoadCallback = a; + SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]}); + } else { + a(); + } + }; + }); + + // if aLoad is true, waits for a load event. Otherwise, spins the event loop twice to + // ensure that no events were queued to be fired. + function spin(aLoad) { + if (aLoad) { + return new Promise((a) => { + ok(!onLoadCallback, "Shouldn't be an existing callback"); + onLoadCallback = a; + }); + } else { + return new Promise((a) => SimpleTest.executeSoon(() => SimpleTest.executeSoon(a))); + } + } + + function onLoad() { + if (done) return; + ok(onLoadCallback, "Expected a load event"); + if (onLoadCallback) { + var cb = onLoadCallback; + onLoadCallback = null; + cb(); + } + } + + add_task(function* () { + yield startPromise; + var image = document.querySelector('img'); + is(image.currentSrc, img2x, "initial scale must be 2x"); + + SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]}); + yield spin(true); + is(image.currentSrc, img1x, "pre-existing img tag to 1x"); + + SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]}); + yield spin(true); + is(image.currentSrc, img2x, "pre-existing img tag to 2x"); + + // Try removing & re-adding the image + document.body.removeChild(image); + + SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]}); + yield spin(false); // No load should occur because the element is unbound + + document.body.appendChild(image); + yield spin(true); + is(image.currentSrc, img1x, "remove and re-add tag after changing to 1x"); + + document.body.removeChild(image); + SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]}); + yield spin(false); // No load should occur because the element is unbound + + document.body.appendChild(image); + yield spin(true); + is(image.currentSrc, img2x, "remove and re-add tag after changing to 2x"); + + // get rid of the srcset attribute! It should become the default + image.removeAttribute('srcset'); + yield spin(true); + is(image.currentSrc, imgdef, "remove srcset attribute"); + + // Setting srcset again should return it to the correct value + image.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x"); + yield spin(true); + is(image.currentSrc, img2x, "restore srcset attribute"); + + // Create a new image + var newImage = document.createElement('img'); + // Switch load listening over to newImage + newImage.addEventListener('load', onLoad); + image.removeEventListener('load', onLoad); + + document.body.appendChild(newImage); + yield spin(false); // no load event should fire - as the image has no attributes + is(newImage.currentSrc, "", "New element with no attributes"); + newImage.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x"); + yield spin(true); + is(newImage.currentSrc, img2x, "Adding srcset attribute"); + + SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]}); + yield spin(true); + is(newImage.currentSrc, img1x, "new image after switching to 1x"); + is(image.currentSrc, img1x, "old image after switching to 1x"); + + // Clear the listener + done = true; + }); + </script> +</body> +</html> diff --git a/dom/html/test/test_bug1203668.html b/dom/html/test/test_bug1203668.html new file mode 100644 index 000000000..8d9ad9a63 --- /dev/null +++ b/dom/html/test/test_bug1203668.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1203668 +--> +<head> + <title>Test for Bug 1203668</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1203668">Mozilla Bug 1203668</a> +<p id="display"></p> +<div id="content"> + <select class="select" multiple> + <option value="foo" selected>foo</option> + <option value="bar" selected>bar</option> + </select> + <select class="select" multiple> + <option value="foo">foo</option> + <option value="bar" selected>bar</option> + </select> + <select class="select" multiple> + <option value="foo">foo</option> + <option value="bar">bar</option> + </select> + <select class="select" size=1> + <option value="foo">foo</option> + <option value="bar" selected>bar</option> + </select> + <select class="select" size=1> + <option value="foo">foo</option> + <option value="bar">bar</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1203668 **/ + +SimpleTest.waitForExplicitFinish(); + +function runTest() +{ + var selects = document.querySelectorAll('.select'); + for (i=0; i < selects.length; i++) { + var select = selects[i]; + select.value = "bogus" + is(select.selectedIndex, -1, "no option is selected"); + is(select.children[0].selected, false, "first option is not selected"); + is(select.children[1].selected, false, "second option is not selected"); + } + + SimpleTest.finish(); +} + +SimpleTest.waitForFocus(runTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1230665.html b/dom/html/test/test_bug1230665.html new file mode 100644 index 000000000..2bad51cdb --- /dev/null +++ b/dom/html/test/test_bug1230665.html @@ -0,0 +1,46 @@ +<html> +<head> + <title>Test for Bug 1230665</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<script> +SimpleTest.waitForExplicitFinish(); + +SimpleTest.waitForFocus(function() { + document.getElementById("flexbutton1").focus(); + synthesizeKey("VK_TAB", { }); + var e = document.getElementById("flexbutton2"); + is(document.activeElement, e, "focus in flexbutton2 after TAB"); + + document.getElementById("gridbutton1").focus(); + synthesizeKey("VK_TAB", { }); + e = document.getElementById("gridbutton2"); + is(document.activeElement, e, "focus in gridbutton2 after TAB"); + + SimpleTest.finish(); +}); + +</script> + +<div tabindex="0" style="display:flex"> + <button id="flexbutton1"></button> + text <!-- this text will force a :-moz-anonymous-flex-item frame --> + <div style=""> + <button id="flexbutton2"></button> + </div> +</div> + + +<div tabindex="0" style="display:grid"> + <button id="gridbutton1"></button> + text <!-- this text will force a :-moz-anonymous-grid-item frame --> + <div style=""> + <button id="gridbutton2"></button> + </div> +</div> + +</body> +</html> diff --git a/dom/html/test/test_bug1233598.html b/dom/html/test/test_bug1233598.html new file mode 100644 index 000000000..c193219ed --- /dev/null +++ b/dom/html/test/test_bug1233598.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1233598 +--> +<head> + <title>Test for Bug 1233598</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1233598">Mozilla Bug 1233598</a> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1233598 **/ + +var i; // must be out here to trigger the leak + +function runTest() +{ + i = document.createElement("input"); + i.setAttribute("type", "file"); + i.getFilesAndDirectories(); // returns a promise + ok(true, "Are we leaking?"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set":[["dom.input.dirpicker", true]]}, runTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1250401.html b/dom/html/test/test_bug1250401.html new file mode 100644 index 000000000..ec9fc6cbf --- /dev/null +++ b/dom/html/test/test_bug1250401.html @@ -0,0 +1,97 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1250401 +--> +<head> + <title>Test for Bug 1250401</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1250401">Bug 1250401</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 1250401 **/ +function test_add() { + var select = document.createElement("select"); + + var g1 = document.createElement("optgroup"); + var o1 = document.createElement("option"); + g1.appendChild(o1); + select.appendChild(g1); + + var g2 = document.createElement("optgroup"); + var o2 = document.createElement("option"); + g2.appendChild(o2); + select.add(g2, 0); + + is(select.children.length, 1, "Select has 1 item"); + is(select.firstChild, g1, "First item is g1"); + is(select.firstChild.children.length, 2, "g2 has 2 children"); + is(select.firstChild.children[0], g2, "g1 has 2 children: g2"); + is(select.firstChild.children[1], o1, "g1 has 2 children: o1"); + is(o1.index, 0, "o1.index should be 0"); + is(o2.index, 0, "o2.index should be 0"); +} + +function test_append() { + var select = document.createElement("select"); + + var g1 = document.createElement("optgroup"); + var o1 = document.createElement("option"); + g1.appendChild(o1); + select.appendChild(g1); + + var g2 = document.createElement("optgroup"); + var o2 = document.createElement("option"); + g2.appendChild(o2); + g1.appendChild(g2); + + is(select.children.length, 1, "Select has 1 item"); + is(select.firstChild, g1, "First item is g1"); + is(select.firstChild.children.length, 2, "g2 has 2 children"); + is(select.firstChild.children[0], o1, "g1 has 2 children: o1"); + is(select.firstChild.children[1], g2, "g1 has 2 children: g1"); + is(o1.index, 0, "o1.index should be 0"); + is(o2.index, 0, "o2.index should be 0"); +} + +function test_no_select() { + var g1 = document.createElement("optgroup"); + var o1 = document.createElement("option"); + g1.appendChild(o1); + + var g2 = document.createElement("optgroup"); + var o2 = document.createElement("option"); + g2.appendChild(o2); + g1.appendChild(g2); + + is(g1.children.length, 2, "g2 has 2 children"); + is(g1.children[0], o1, "g1 has 2 children: o1"); + is(g1.children[1], g2, "g1 has 2 children: g1"); + is(o1.index, 0, "o1.index should be 0"); + is(o2.index, 0, "o2.index should be 0"); +} + +function test_no_parent() { + var o1 = document.createElement("option"); + var o2 = document.createElement("option"); + + is(o1.index, 0, "o1.index should be 0"); + is(o2.index, 0, "o2.index should be 0"); +} + +test_add(); +test_append(); +test_no_select(); +test_no_parent(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1260664.html b/dom/html/test/test_bug1260664.html new file mode 100644 index 000000000..f03432895 --- /dev/null +++ b/dom/html/test/test_bug1260664.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1260664 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1260664</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1260664">Mozilla Bug 1260664</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1260664 **/ +SpecialPowers.setBoolPref("network.http.enablePerElementReferrer", true); + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + +function runTests() { + var elements = [ "iframe", "img", "a", "area", "link" ]; + + for (var i = 0; i < elements.length; ++i) { + reflectLimitedEnumerated({ + element: document.createElement(elements[i]), + attribute: { content: "referrerpolicy", idl: "referrerPolicy" }, + validValues: [ "no-referrer", + "origin", + /** These 2 below values are still invalid, please see + Bug 1178337 - Valid referrer attribute values **/ + /** "no-referrer-when-downgrade", + "origin-when-cross-origin", **/ + "unsafe-url" ], + invalidValues: [ + "", " orIgin ", " unsafe-uRl ", " No-RefeRRer ", " fOoBaR " + ], + defaultValue: "", + }); + } + + SpecialPowers.clearUserPref("network.http.enablePerElementReferrer"); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1260704.html b/dom/html/test/test_bug1260704.html new file mode 100644 index 000000000..36eead3a2 --- /dev/null +++ b/dom/html/test/test_bug1260704.html @@ -0,0 +1,90 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1260704 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1260704</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="text/javascript"> + /** Test for Bug 1260704 **/ + +function runTests() { + let testIdx = -1; + let testUrls = [ + "bug1260704_iframe.html?noDefault=true&isMap=true", + "bug1260704_iframe.html?noDefault=true&isMap=false", + "bug1260704_iframe.html?noDefault=false&isMap=true", + "bug1260704_iframe.html?noDefault=false&isMap=false" + ]; + + let runningTest = false; + let iframe = document.getElementById("testFrame"); + let iframeWin = iframe.contentWindow; + let rect; + let x; + let y; + + window.addEventListener("message", event => { + if (event.data == "started") { + ok(!runningTest, "Start to test " + testIdx); + runningTest = true; + rect = iframeWin.document.getElementById("testImage").getBoundingClientRect(); + x = rect.width / 2; + y = rect.height / 2; + synthesizeMouseAtPoint(rect.left + x, rect.top + y, { type: 'mousedown' }, iframeWin); + synthesizeMouseAtPoint(rect.left + x, rect.top + y, { type: 'mouseup' }, iframeWin); + } + else if (runningTest && event.data == "empty_frame_loaded") { + ok(testUrls[testIdx].includes("noDefault=false"), "Page unload"); + let search = iframeWin.location.search; + if (testUrls[testIdx].includes("isMap=true")) { + // url trigger by image with ismap attribute should contains coordinates + // try to parse coordinates and check them with small tolerance + let coorStr = search.split("?"); + let coordinates = coorStr[1].split(","); + ok(Math.abs(coordinates[0] - x) <= 1, "expect X=" + x + " got " + coordinates[0]); + ok(Math.abs(coordinates[1] - y) <= 1, "expect Y=" + y + " got " + coordinates[1]); + } else { + ok(search == "", "expect empty search string got:" + search); + } + nextTest(); + } + else if (runningTest && event.data == "finished") { + ok(testUrls[testIdx].includes("noDefault=true"), "Page should not leave"); + nextTest(); + } + }, false); + + function nextTest() { + testIdx++; + runningTest = false; + if (testIdx >= testUrls.length) { + SimpleTest.finish(); + } else { + ok(true, "Test " + testIdx + " - Set url to " + testUrls[testIdx]); + iframeWin.location.href = testUrls[testIdx]; + } + } + nextTest(); +} + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + + </script> +</head> +<body> + +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<iframe id="testFrame" src="about:blank" width="400" height="400"> +</iframe> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1261673.html b/dom/html/test/test_bug1261673.html new file mode 100644 index 000000000..006b229e1 --- /dev/null +++ b/dom/html/test/test_bug1261673.html @@ -0,0 +1,77 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1261673 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1261673</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1261673">Mozilla Bug 1261673</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<input id="test_number" type="number" value=5> +<script type="text/javascript"> + +/** Test for Bug 1261673 **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + +function runTests() { + let input = window.document.getElementById("test_number"); + + // focus: whether the target input element is focused + // deltaY: deltaY of WheelEvent + // deltaMode: deltaMode of WheelEvent + // valueChanged: expected value changes after input element handled the wheel event + let params = [ + {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: -1}, + {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 1}, + {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: -1}, + {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: 1}, + {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0}, + {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0}, + {focus: false, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0}, + {focus: false, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0} + ]; + + let testIdx = 0; + let result = parseInt(input.value); + let numberChange = 0; + let expectChange = 0; + + input.addEventListener("change", () => { + ++numberChange; + }, false); + + function runNext() { + let p = params[testIdx]; + (p["focus"]) ? input.focus() : input.blur(); + expectChange = p["valueChanged"] == 0 ? expectChange : expectChange + 1; + result += parseInt(p["valueChanged"]); + synthesizeWheel(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }); + window.postMessage("finished", "http://mochi.test:8888"); + testIdx++; + } + + window.addEventListener("message", event => { + if (event.data == "finished") { + ok(input.value == result, + "Handle wheel in number input test-" + testIdx + " expect " + result + + " get " + input.value); + ok(numberChange == expectChange, + "UA should fire change event when input's value changed, expect " + expectChange + " get " + numberChange); + (testIdx >= params.length) ? SimpleTest.finish() : runNext(); + } + }); + runNext(); +} + +</script> +</body> +</html> diff --git a/dom/html/test/test_bug1261674-1.html b/dom/html/test/test_bug1261674-1.html new file mode 100644 index 000000000..3745c1930 --- /dev/null +++ b/dom/html/test/test_bug1261674-1.html @@ -0,0 +1,77 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1261674 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1261674</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1261674">Mozilla Bug 1261674</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<input id="test_input" type="range" value=5 max=10 min=0> +<script type="text/javascript"> + +/** Test for Bug 1261674 **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + +function runTests() { + let input = window.document.getElementById("test_input"); + + // focus: whether the target input element is focused + // deltaY: deltaY of WheelEvent + // deltaMode: deltaMode of WheelEvent + // valueChanged: expected value changes after input element handled the wheel event + let params = [ + {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: -1}, + {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 1}, + {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: -1}, + {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: 1}, + {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0}, + {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0}, + {focus: false, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0}, + {focus: false, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0} + ]; + + let testIdx = 0; + let result = parseInt(input.value); + let rangeChange = 0; + let expectChange = 0; + + input.addEventListener("change", () => { + ++rangeChange; + }, false); + + function runNext() { + let p = params[testIdx]; + (p["focus"]) ? input.focus() : input.blur(); + expectChange = p["valueChanged"] == 0 ? expectChange : expectChange + 1; + result += parseInt(p["valueChanged"]); + sendWheelAndPaint(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }, () => { + ok(input.value == result, + "Handle wheel in range input test-" + testIdx + " expect " + result + " get " + input.value); + ok(rangeChange == expectChange, + "UA should fire change event when input's value changed, expect " + expectChange + " get " + rangeChange); + (++testIdx >= params.length) ? SimpleTest.finish() : runNext(); + }); + } + + input.addEventListener("input", () => { + ok(input.value == result, + "Test-" + testIdx + " receive input event, expect " + result + " get " + input.value); + }, false); + + runNext(); +} + +</script> +</body> +</html> diff --git a/dom/html/test/test_bug1261674-2.html b/dom/html/test/test_bug1261674-2.html new file mode 100644 index 000000000..ffb42ee6d --- /dev/null +++ b/dom/html/test/test_bug1261674-2.html @@ -0,0 +1,70 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1261674 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1261674</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1261674">Mozilla Bug 1261674</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<input id="test_input" type="range" max=0 min=10> +<script type="text/javascript"> + +/** Test for Bug 1261674 **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + +function runTests() { + let input = window.document.getElementById("test_input"); + + // deltaY: deltaY of WheelEvent + // deltaMode: deltaMode of WheelEvent + let params = [ + {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE}, + {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE}, + {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE}, + {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE}, + {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL}, + {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL}, + {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE}, + {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE} + ]; + + let testIdx = 0; + let result = parseInt(input.value); + let rangeChange = 0; + + input.addEventListener("change", () => { + ++rangeChange; + }, false); + + function runNext() { + let p = params[testIdx]; + (p["focus"]) ? input.focus() : input.blur(); + sendWheelAndPaint(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }, () => { + ok(input.value == result, + "Handle wheel in range input test-" + testIdx + " expect " + result + " get " + input.value); + ok(rangeChange == 0, "Wheel event should not trigger change event when max < min"); + testIdx++; + (testIdx >= params.length) ? SimpleTest.finish() : runNext(); + }); + } + + input.addEventListener("input", () => { + ok(false, "Wheel event should be no effect to range input element with max < min"); + }, false); + + runNext(); +} +</script> +</body> +</html> diff --git a/dom/html/test/test_bug1264157.html b/dom/html/test/test_bug1264157.html new file mode 100644 index 000000000..a087b0f41 --- /dev/null +++ b/dom/html/test/test_bug1264157.html @@ -0,0 +1,90 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=535043 +--> +<head> + <title>Test for Bug 535043</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input { + outline: 2px solid lime; + } + input:in-range { + outline: 2px solid red; + } + input:out-of-range { + outline: 2px solid orange; + } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=535043">Mozilla Bug 535043</a> +<p id="display"></p> +<div id="content"> + +</head> +<body> + <input type="number" value=0 min=0 max=10> Active in-range + <br><br> + <input type="number" value=0 min=0 max=10 disabled> Disabled in-range + <br><br> + <input type="number" value=0 min=0 max=10 readonly> Read-only in-range + <br><br> + <input type="number" value=11 min=0 max=10> Active out-of-range + <br><br> + <input type="number" value=11 min=0 max=10 disabled> Disabled out-of-range + <br><br> + <input type="number" value=11 min=0 max=10 readonly> Read-only out-of-range +</div> +<pre id="test"> +<script type="text/javascript"> + +/** Test for Bug 1264157 **/ +SimpleTest.waitForFocus(function() { + // Check the initial values. + let active = [].slice.call(document.querySelectorAll("input:not(:disabled):not(:-moz-read-only)")); + let disabled = [].slice.call(document.querySelectorAll("input:disabled")); + let readonly = [].slice.call(document.querySelectorAll("input:-moz-read-only")); + ok(active.length == 2, "Test is messed up: missing non-disabled/non-readonly inputs"); + ok(disabled.length == 2, "Test is messed up: missing disabled inputs"); + ok(readonly.length == 2, "Test is messed up: missing readonly inputs"); + + is(document.querySelectorAll("input:in-range").length, 1, + "Wrong number of in-range elements selected."); + is(document.querySelectorAll("input:out-of-range").length, 1, + "Wrong number of out-of-range elements selected."); + + // Dynamically change the values to see if that works too. + active[0].value = -1; + is(document.querySelectorAll("input:in-range").length, 0, + "Wrong number of in-range elements selected after value changed."); + is(document.querySelectorAll("input:out-of-range").length, 2, + "Wrong number of out-of-range elements selected after value changed."); + active[0].value = 0; + is(document.querySelectorAll("input:in-range").length, 1, + "Wrong number of in-range elements selected after value changed back."); + is(document.querySelectorAll("input:out-of-range").length, 1, + "Wrong number of out-of-range elements selected after value changed back."); + + // Dynamically change the attributes to see if that works too. + disabled.forEach(function(e) { e.removeAttribute("disabled"); }); + readonly.forEach(function(e) { e.removeAttribute("readonly"); }); + active.forEach(function(e) { e.setAttribute("readonly", true); }); + + is(document.querySelectorAll("input:in-range").length, 2, + "Wrong number of in-range elements selected after attribute changed."); + is(document.querySelectorAll("input:out-of-range").length, 2, + "Wrong number of out-of-range elements selected after attribute changed."); + + SimpleTest.finish(); +}); + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1287321.html b/dom/html/test/test_bug1287321.html new file mode 100644 index 000000000..2de0bd0f2 --- /dev/null +++ b/dom/html/test/test_bug1287321.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1287321 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1287321</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1287321 **/ + + function test() { + var r = document.getElementById("range"); + var rect = r.getBoundingClientRect(); + var y = parseInt((rect.height / 2)); + var movement = parseInt(rect.width / 10); + var x = movement; + synthesizeMouse(r, x, y, { type: "mousedown" }); + x += movement; + var eventCount = 0; + r.oninput = function() { + ++eventCount; + } + synthesizeMouse(r, x, y, { type: "mousemove" }); + is(eventCount, 1, "Got the expected input event"); + + x += movement; + synthesizeMouse(r, x, y, { type: "mousemove" }); + is(eventCount, 2, "Got the expected input event"); + + synthesizeMouse(r, x, y, { type: "mousemove" }); + is(eventCount, 2, "Got the expected input event"); + + x += movement; + synthesizeMouse(r, x, y, { type: "mousemove" }); + is(eventCount, 3, "Got the expected input event"); + + synthesizeMouse(r, x, y, { type: "mouseup" }); + is(eventCount, 3, "Got the expected input event"); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + SimpleTest.waitForFocus(test); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1287321">Mozilla Bug 1287321</a> +<input type="range" id="range"> +</body> +</html> diff --git a/dom/html/test/test_bug1292522_same_domain_with_different_port_number.html b/dom/html/test/test_bug1292522_same_domain_with_different_port_number.html new file mode 100644 index 000000000..0dec91558 --- /dev/null +++ b/dom/html/test/test_bug1292522_same_domain_with_different_port_number.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1292522 +If we set domain using document.domain = "...", a page and iframe must be +treated as the same domain if they differ in port number, +e.g. test1.example.org:8000 and test2.example.org:80 are the same domain if +document.domain = "example.org". +--> +<head> + <title>Test for Bug 1292522</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> + <body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1292522">Mozilla Bug 1292522</a> + <p id="display"></p> + + <pre id="test"> + <script class="testbody" type="text/javascript"> + + if (navigator.platform.startsWith("Linux")) { + SimpleTest.expectAssertions(0, 1); + } + SimpleTest.waitForExplicitFinish(); + window.addEventListener("message", onMessageReceived, false); + + var page; + + function onMessageReceived(event) + { + is(event.data, "testiframe", "Must be able to access the variable," + + " because page and iframe are the " + + "same domain."); + page.close(); + SimpleTest.finish(); + } + + page = window.open("http://test1.example.org:8000/tests/dom/html/test/bug1292522_page.html"); + </script> + </pre> + </body> +</html> diff --git a/dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html b/dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html new file mode 100644 index 000000000..b780cb913 --- /dev/null +++ b/dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1295719 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1295719</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295719">Mozilla Bug 1295719</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<input id="test_number" type="number" value=50> +<input id="test_range" type="range" value=50 max=100 min=0> +<script type="text/javascript"> + +/** Test for Bug 1295719 **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + +function runTests() { + let number = window.document.getElementById("test_number"); + let range = window.document.getElementById("test_range"); + let waiting_event_sequence = ["keydown", "keypress", "input", "change"]; + + let waiting_event_idx = 0; + waiting_event_sequence.forEach((eventType) => { + number.addEventListener(eventType, (event) => { + let waiting_event = waiting_event_sequence[waiting_event_idx]; + is(waiting_event, eventType, "Waiting " + waiting_event + " get " + eventType); + // Input element will fire input and change events when handling keypress + // with keycode=arrows. When user press and hold the keyboard, we expect + // that input element repeatedly fires "keydown", "keypress", "input", and + // "change" events until user release the keyboard. Using + // waiting_event_sequence as a circular buffer and reset waiting_event_idx + // when it point to the end of buffer. + waiting_event_idx = waiting_event_idx == waiting_event_sequence.length -1 ? 0 : waiting_event_idx + 1; + }, false); + range.addEventListener(eventType, (event) => { + let waiting_event = waiting_event_sequence[waiting_event_idx]; + is(waiting_event, eventType, "Waiting " + waiting_event + " get " + eventType); + waiting_event_idx = waiting_event_idx == waiting_event_sequence.length - 1 ? 0 : waiting_event_idx + 1; + }, false); + }); + + number.focus(); + synthesizeKey("VK_DOWN", {type: "keydown"}); + synthesizeKey("VK_DOWN", {type: "keydown"}); + synthesizeKey("VK_DOWN", {type: "keyup"}); + number.blur(); + range.focus(); + waiting_event_idx = 0; + synthesizeKey("VK_DOWN", {type: "keydown"}); + synthesizeKey("VK_DOWN", {type: "keydown"}); + synthesizeKey("VK_DOWN", {type: "keyup"}); + + SimpleTest.finish(); +} + +</script> +</body> +</html> diff --git a/dom/html/test/test_bug1295719_event_sequence_for_number_keys.html b/dom/html/test/test_bug1295719_event_sequence_for_number_keys.html new file mode 100644 index 000000000..2dac8c55b --- /dev/null +++ b/dom/html/test/test_bug1295719_event_sequence_for_number_keys.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1295719 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1295719</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295719">Mozilla Bug 1295719</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<input id="test_number" type="number" value=50> +<script type="text/javascript"> + +/** Test for Bug 1295719 **/ +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTests); + +function runTests() { + let number = window.document.getElementById("test_number"); + let waiting_event_sequence = ["keydown", "keypress", "input"]; + let change_event_of_number = 0; + let keyup_event_of_number = 0; + let waiting_event_idx = 0; + waiting_event_sequence.forEach((eventType) => { + number.addEventListener(eventType, (event) => { + let waiting_event = waiting_event_sequence[waiting_event_idx]; + is(eventType, waiting_event, "Waiting " + waiting_event + " get " + eventType); + // Input element will fire input event when handling keypress with + // keycode=numbers. When user press and hold the keyboard, we expect that + // input element repeatedly fires "keydown", "keypress", and "input" until + // user release the keyboard. Input element will fire change event when + // it's blurred. Using waiting_event_sequence as a circular buffer and + // reset waiting_event_idx when it point to the end of buffer. + waiting_event_idx = waiting_event_idx == waiting_event_sequence.length - 1 ? 0 : waiting_event_idx + 1; + }, false); + }); + number.addEventListener("change", (event) => { + is(keyup_event_of_number, 1, "change event should be fired after blurred"); + ++change_event_of_number; + }, false); + number.addEventListener("keyup", (event) => { + is(keyup_event_of_number, 0, "keyup event should be fired once"); + is(change_event_of_number, 0, "keyup event should be fired before change event"); + ++keyup_event_of_number; + }, false); + number.focus(); + synthesizeKey("5", {type: "keydown"}); + synthesizeKey("5", {type: "keydown"}); + synthesizeKey("5", {type: "keyup"}); + is(change_event_of_number, 0, "change event shouldn't be fired when input element is focused"); + number.blur(); + is(change_event_of_number, 1, "change event should be fired when input element is blurred"); + SimpleTest.finish(); +} + +</script> +</body> +</html> diff --git a/dom/html/test/test_bug1297.html b/dom/html/test/test_bug1297.html new file mode 100644 index 000000000..8b9dc3039 --- /dev/null +++ b/dom/html/test/test_bug1297.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1297 +--> +<head> + <title>Test for Bug 1297</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1297">Mozilla Bug 1297</a> +<p id="display"></p> +<div id="content" style="display: none"> +<table border=1> +<tr> +<td id="td1" onmousedown="alert(this.cellIndex)">cellIndex=0</td> +<td id="td2" onmousedown="alert(this.cellIndex)">cellIndex=1</td> +<td id="td3" onmousedown="alert(this.cellIndex)">cellIndex=2</td> +<tr id="tr1" +onmousedown="alert(this.rowIndex)"><td>rowIndex=1<td>rowIndex=1<td>rowIndex=1</t +r> +<tr id="tr2" +onmousedown="alert(this.rowIndex)"><td>rowIndex=2<td>rowIndex=2<td>rowIndex=2</t +r> +</tr> +</table> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 1297 **/ +is($('td1').cellIndex, 0, "cellIndex / rowIndex working td1"); +is($('td2').cellIndex, 1, "cellIndex / rowIndex working td2"); +is($('td3').cellIndex, 2, "cellIndex / rowIndex working td3"); +is($('tr1').rowIndex, 1, "cellIndex / rowIndex working tr1"); +is($('tr2').rowIndex, 2, "cellIndex / rowIndex working tr2"); + + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug1310865.html b/dom/html/test/test_bug1310865.html new file mode 100644 index 000000000..4dcccbfa0 --- /dev/null +++ b/dom/html/test/test_bug1310865.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>Test for Bug 1310865</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="/tests/SimpleTest/EventUtils.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"> +<input value="a +b" type="hidden"> +<input type="hidden" value="a +b"> +<script> +var input1 = document.querySelector("input"); +var input2 = document.querySelector("input + input"); +var clone1 = input1.cloneNode(false); +var clone2 = input2.cloneNode(false); +// Newlines must not be stripped +is(clone1.value, "a\nb"); +is(clone2.value, "a\nb"); +</script> diff --git a/dom/html/test/test_bug1315146.html b/dom/html/test/test_bug1315146.html new file mode 100644 index 000000000..261b815b5 --- /dev/null +++ b/dom/html/test/test_bug1315146.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1315146 +--> +<head> + <title>Test for Bug 1315146</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315146">Mozilla Bug 1315146</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 1315146 **/ + +SimpleTest.waitForExplicitFinish(); +onmessage = function(e) { + win.close(); + is(e.data.start, 2, "Correct start offset expected"); + is(e.data.end, 2, "Correct end offset expected"); + SimpleTest.finish(); +}; +let win = window.open("http://test1.example.org/tests/dom/html/test/bug1315146-main.html", "_blank"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1366.html b/dom/html/test/test_bug1366.html new file mode 100644 index 000000000..f5b4f880d --- /dev/null +++ b/dom/html/test/test_bug1366.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1366 +--> +<head> + <title>Test for Bug 1366</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1366">Mozilla Bug 1366</a> +<p id="display"></p> +<div id="content" style="display: none"> +<table id="testtable" width=150 border> + <tbody id="testbody"> + <tr> + <td>cell content</td> + </tr> + </tbody> +</table> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 1366 **/ +$('testtable').removeChild($('testbody')); +$('display').innerHTML = "SCRIPT: deleted first ROWGROUP\n"; +is($('testbody'), null, "deleting tbody works"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug1400.html b/dom/html/test/test_bug1400.html new file mode 100644 index 000000000..12f36833b --- /dev/null +++ b/dom/html/test/test_bug1400.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1400 +--> +<head> + <title>Test for Bug 1400</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1400">Mozilla Bug 1400</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 1400 **/ + +table = document.createElement("TABLE"); +thead = table.createTHead(); +thead2 = table.createTHead(); + +table.appendChild(thead); +table.appendChild(thead); +table.appendChild(thead); +table.appendChild(thead2); +table.appendChild(thead2); +table.appendChild(thead2); +table.appendChild(thead); +table.appendChild(thead2); + +is(table.childNodes.length, 1, + "adding multiple theads results in one thead child"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug143220.html b/dom/html/test/test_bug143220.html new file mode 100644 index 000000000..355e91ea2 --- /dev/null +++ b/dom/html/test/test_bug143220.html @@ -0,0 +1,72 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=143220 +--> +<head> + <title>Test for Bug 143220</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=143220">Mozilla Bug 143220</a> +<p id="display"> + <input type="file" id="i1"> + <input type="file" id="i2"> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript;version=1.7"> + +/** Test for Bug 143220 **/ +SimpleTest.waitForExplicitFinish(); +const helperURL = SimpleTest.getTestFileURL("simpleFileOpener.js"); +const helper = SpecialPowers.loadChromeScript(helperURL); +helper.addMessageListener("fail", function onFail(message) { + is(message, null, "chrome script failed"); + SimpleTest.finish(); +}); +helper.addMessageListener("file.opened", onFileOpened); +helper.sendAsyncMessage("file.open", "test_bug143220.txt"); + +function onFileOpened(message) { + const { leafName, fullPath, domFile } = message; + + function initControl1() { + SpecialPowers.wrap($("i1")).mozSetFileArray([domFile]); + } + + function initControl2() { + SpecialPowers.wrap($("i2")).mozSetFileArray([domFile]); + } + + // Check that we can't just set the value + try { + $("i1").value = fullPath; + is(0, 1, "Should have thrown exception on set!"); + } catch(e) { + is($("i1").value, "", "Shouldn't have value here"); + } + + initControl1(); + initControl2(); + + is($("i1").value, leafName, "Leaking full value?"); + is($("i2").value, leafName, "Leaking full value?"); + + helper.addMessageListener("file.removed", onFileRemoved); + helper.sendAsyncMessage("file.remove", null); +} + +function onFileRemoved() { + helper.destroy(); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug1682.html b/dom/html/test/test_bug1682.html new file mode 100644 index 000000000..c8e5b830d --- /dev/null +++ b/dom/html/test/test_bug1682.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1682 +--> +<head> + <title>Test for Bug 1682</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1682">Mozilla Bug 1682</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 1682 **/ +var count = 1; + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function () { + is(count, 1, "onload executes once"); + ++count; +}); +addLoadEvent(SimpleTest.finish); + + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug172261.html b/dom/html/test/test_bug172261.html new file mode 100644 index 000000000..2b5d752cd --- /dev/null +++ b/dom/html/test/test_bug172261.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=172261 +--> +<head> + <title>Test for Bug 172261</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=172261">Mozilla Bug 172261</a> +<p id="display"> + <iframe id="test"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + /** Test for Bug 172261 **/ + SimpleTest.waitForExplicitFinish(); + SimpleTest.requestFlakyTimeout("untriaged"); + + var callable = false; + function toggleCallable() { callable = true; } + + var doTestInIframe = false; + + // Shouldn't do history stuff from inside onload + addLoadEvent(function() { setTimeout(startTest, 10) }); + + function startTest() { + // First, create a dummy document. Use onunload handlers to make sure + // bfcache doesn't screw us up. + var doc = $("test").contentDocument; + + doc.write("<html><body onunload=''>First</body></html>"); + doc.close(); + + // Now write our test document + doc.write("<html><script>window.onerror = parent.onerror; if (parent.doTestInIframe) { parent.is(document.domain, parent.document.domain, 'Domains should match'); parent.toggleCallable(); } <" + "/script><body>Second</body></html>"); + doc.close(); + + $("test").onload = goForward; + history.back(); + } + + function goForward() { + $("test").onload = doTest; + doTestInIframe = true; + history.forward(); + } + + function doTest() { + is($("test").contentDocument.domain, document.domain, + "Domains should match 2"); + is($("test").contentDocument.location.href, location.href, + "Locations should match"); + is(callable, true, "Subframe should be able to call us"); + SimpleTest.finish(); + } +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug182279.html b/dom/html/test/test_bug182279.html new file mode 100644 index 000000000..56c73a676 --- /dev/null +++ b/dom/html/test/test_bug182279.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=182279 +--> +<head> + <title>Test for Bug 182279</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=182279">Moozilla Bug 182279</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +/** Test for Bug 182279 **/ +var sel = document.createElement("select"); +var opt1 = new Option(); +var opt2 = new Option(); +var opt3 = new Option(); +opt1.value = 1; +opt2.value = 2; +opt3.value = 3; +sel.add(opt1, null); +sel.add(opt2, opt1); +sel.add(opt3); +is(sel[0], opt2, "1st item should be 2"); +is(sel[1], opt1, "2nd item should be 1"); +is(sel[2], opt3, "3rd item should be 3"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug1823.html b/dom/html/test/test_bug1823.html new file mode 100644 index 000000000..1297b0dd6 --- /dev/null +++ b/dom/html/test/test_bug1823.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1823 +--> +<head> + <title>Test for Bug 1823</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1823">Mozilla Bug 1823</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 1823 **/ +ok((document.location + "").indexOf("[") == -1, "location object has a toString()"); + + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug196523.html b/dom/html/test/test_bug196523.html new file mode 100644 index 000000000..a380fe06c --- /dev/null +++ b/dom/html/test/test_bug196523.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=196523 +--> +<head> + <title>Test for Bug 196523</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=196523">Mozilla Bug 196523</a> +<script> + var expectedMessages = 2; + SimpleTest.waitForExplicitFinish(); + window.addEventListener("message", function(e) { + --expectedMessages; + var str = e.data; + var idx = str.indexOf(';'); + var val = str.substring(0, idx); + var msg = str.substring(idx+1); + ok(val == "true", msg); + if (!expectedMessages) { SimpleTest.finish(); } + }, false); +</script> +<p id="display"> + <iframe src="http://test1.example.org/tests/dom/html/test/bug196523-subframe.html"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 196523 **/ + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug199692.html b/dom/html/test/test_bug199692.html new file mode 100644 index 000000000..91f99ccc4 --- /dev/null +++ b/dom/html/test/test_bug199692.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=199692 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>Test for Bug 199692</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + + // The popup calls MochiTest methods in this window through window.opener + window.open("bug199692-popup.html", "bug199692", "width=600,height=600"); + </script> +</body> +</html> + diff --git a/dom/html/test/test_bug2082.html b/dom/html/test/test_bug2082.html new file mode 100644 index 000000000..b693e96d1 --- /dev/null +++ b/dom/html/test/test_bug2082.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=2082 +--> +<head> + <title>Test for Bug 2082</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=2082">Mozilla Bug 2082</a> +<p id="display"></p> +<div id="content" style="display: none"> +<FORM name="gui" id="gui"> +<INPUT TYPE="text" NAME="field" VALUE="some value"> +</FORM> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 2082 **/ +var guiform = document.getElementById("gui"); +ok(document.getElementById("gui").hasChildNodes(), "form elements should be treated as form's children"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug209275.xhtml b/dom/html/test/test_bug209275.xhtml new file mode 100644 index 000000000..f74e5e5fb --- /dev/null +++ b/dom/html/test/test_bug209275.xhtml @@ -0,0 +1,261 @@ +<!DOCTYPE html [ +<!ATTLIST foo:base + id ID #IMPLIED +> +]> +<html xmlns:foo="http://foo.com" xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=209275 +--> +<head> + <title>Test for Bug 209275</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + + <style> + @namespace svg url("http://www.w3.org/2000/svg"); + svg|a { fill:blue; } + svg|a:visited { fill:purple; } + </style> + + <!-- + base0 should be ignored because it's not in the XHTML namespace + --> + <foo:base id="base0" href="http://www.foo.com" /> + + <!-- + baseEmpty should be ignored because it has no href and never gets one. + --> + <base id="baseEmpty" /> + + <!-- + baseWrongAttrNS should be ignored because its href attribute isn't in the empty + namespace. + --> + <base id="baseWrongAttrNS" foo:href="http://foo.com" /> + + <base id="base1" /> + <base id="base2" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=209275">Mozilla Bug 209275</a> +<p id="display"> +</p> +<div id="content"> + <a href="/" id="link1">link1</a> + <div style="display:none"> + <a href="/" id="link2">link2</a> + </div> + <a href="/" id="link3" style="display:none">link3</a> + <a href="#" id="link4">link4</a> + <a href="" id="colorlink">colorlink</a> + <a href="#" id="link5">link5</a> + <iframe id="iframe"></iframe> + + <svg width="5cm" height="3cm" viewBox="0 0 5 3" version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <a xlink:href="" id="ellipselink"> + <ellipse cx="2.5" cy="1.5" rx="2" ry="1" id="ellipse" /> + </a> + </svg> + +</div> +<pre id="test"> +<script type="text/javascript;version=1.7"> +<![CDATA[ + +/** Test for Bug 209275 **/ +SimpleTest.waitForExplicitFinish(); + +function link123HrefIs(href, testNum) { + is($('link1').href, href, "link1 test " + testNum); + is($('link2').href, href, "link2 test " + testNum); + is($('link3').href, href, "link3 test " + testNum); +} + +var gGen; + +function visitedDependentComputedStyle(win, elem, property) { + var utils = SpecialPowers.getDOMWindowUtils(window); + return utils.getVisitedDependentComputedStyle(elem, "", property); +} + +function getColor(elem) { + return visitedDependentComputedStyle(document.defaultView, elem, "color"); +} + +function getFill(elem) { + return visitedDependentComputedStyle(document.defaultView, elem, "fill"); +} + +function setXlinkHref(elem, href) { + elem.setAttributeNS("http://www.w3.org/1999/xlink", "href", href); +} + +function continueTest() { + gGen.next(); +} + +var iframe = document.getElementById("iframe"); +var iframeCw = iframe.contentWindow; + +function run() { + var iframe = document.getElementById("iframe"); + var iframeCw = iframe.contentWindow; + + // First, set the visited/unvisited link/ellipse colors. + const unvisitedColor = "rgb(0, 0, 238)"; + const visitedColor = "rgb(85, 26, 139)"; + const unvisitedFill = "rgb(0, 0, 255)"; + const visitedFill = "rgb(128, 0, 128)"; + + const rand = Date.now() + "-" + Math.random(); + + // Now we can start the tests in earnest. + + var loc = location; + // everything from the location up to and including the final forward slash + var path = /(.*\/)[^\/]*/.exec(location)[1]; + + // Set colorlink's href so we can check that it changes colors after we + // change the base href. + $('colorlink').href = "http://example.com/" + rand; + setXlinkHref($("ellipselink"), "http://example.com/" + rand); + + // Load http://example.com/${rand} into an iframe so we can test that changing + // the document's base changes the visitedness of our links. + iframe.onload = continueTest; + iframeCw.location = "http://example.com/" + rand; + yield undefined; // wait for onload to fire. + + // Make sure things are what as we expect them at the beginning. + link123HrefIs("http://mochi.test:8888/", 1); + is($('link4').href, loc + "#", "link 4 test 1"); + is($('link5').href, loc + "#", "link 5 test 1"); + + // Remove link5 from the document. We're going to test that its href changes + // properly when we change our base. + var link5 = $('link5'); + link5.parentNode.removeChild(link5); + + $('base1').href = "http://example.com"; + + // Were the links' hrefs updated after the base change? + link123HrefIs("http://example.com/", 2); + is($('link4').href, "http://example.com/#", "link 4 test 2"); + is(link5.href, "http://example.com/#", "link 5 test 2"); + + // Were colorlink's color and ellipse's fill updated appropriately? + // Because link coloring is asynchronous, we wait until it is updated (or we + // timeout and fail anyway). + while (getColor($('colorlink')) != visitedColor) { + setTimeout(continueTest, 0); + yield undefined; + } + is(getColor($('colorlink')), visitedColor, + "Wrong link color after base change."); + while (getFill($('ellipselink')) != visitedFill) { + setTimeout(continueTest, 0); + yield undefined; + } + is(getFill($('ellipselink')), visitedFill, + "Wrong ellipse fill after base change."); + + $('base1').href = "foo/"; + // Should be interpreted relative to current URI (not the current base), so + // base should now be http://mochi.test:8888/foo/ + + link123HrefIs("http://mochi.test:8888/", 3); + is($('link4').href, path + "foo/#", "link 4 test 3"); + + // Changing base2 shouldn't affect anything, because it's not the first base + // tag. + $('base2').href = "http://example.org/bar/"; + link123HrefIs("http://mochi.test:8888/", 4); + is($('link4').href, path + "foo/#", "link 4 test 4"); + + // If we unset base1's href attribute, the document's base should come from + // base2, whose href is http://example.org/bar/. + $('base1').removeAttribute("href"); + link123HrefIs("http://example.org/", 5); + is($('link4').href, "http://example.org/bar/#", "link 4 test 5"); + + // If we remove base1, base2 should become the first base tag, and the hrefs + // of all the links should change accordingly. + $('base1').parentNode.removeChild($('base1')); + link123HrefIs("http://example.org/", 6); + is($('link4').href, "http://example.org/bar/#", "link 4 test 6"); + + // If we add a new base after base2, nothing should change. + var base3 = document.createElement("base"); + base3.href = "http://base3.example.org/"; + $('base2').parentNode.insertBefore(base3, $('base2').nextSibling); + link123HrefIs("http://example.org/", 7); + is($('link4').href, "http://example.org/bar/#", "link 4 test 7"); + + // But now if we add a new base before base 2, it should become the primary + // base. + var base4 = document.createElement("base"); + base4.href = "http://base4.example.org/"; + $('base2').parentNode.insertBefore(base4, $('base2')); + link123HrefIs("http://base4.example.org/", 8); + is($('link4').href, "http://base4.example.org/#", "link 4 test 8"); + + // Now if we remove all the base tags, the base should become the page's URI + // again. + $('base2').parentNode.removeChild($('base2')); + base3.parentNode.removeChild(base3); + base4.parentNode.removeChild(base4); + + link123HrefIs("http://mochi.test:8888/", 9); + is($('link4').href, loc + "#", "link 4 test 9"); + + // Setting the href of base0 shouldn't do anything because it's not in the + // XHTML namespace. + $('base0').href = "http://bar.com"; + link123HrefIs("http://mochi.test:8888/", 10); + is($('link4').href, loc + "#", "link 4 test 10"); + + // We load into an iframe a document with a <base href="...">, then remove + // the document element. Then we add an <html>, <body>, and <a>, and make + // sure that the <a> is resolved relative to the page's location, not its + // original base. We do this twice, rebuilding the document in a different + // way each time. + + iframe.onload = null; + iframeCw.location = "file_bug209275_1.html"; + yield undefined; // wait for our child to call us back. + is(iframeCw.document.getElementById("link").href, + path + "file_bug209275_1.html#", + "Wrong href after nuking document."); + + iframeCw.location = "file_bug209275_2.html"; + yield undefined; // wait for callback from child + is(iframeCw.document.getElementById("link").href, + "http://mochi.test:8888/", + "Wrong href after nuking document second time."); + + // Make sure that document.open() makes the document forget about any <base> + // tags it has. + iframeCw.location = "file_bug209275_3.html"; + yield undefined; // wait for callback from child + is(iframeCw.document.getElementById("link").href, + "http://mochi.test:8888/", + "Wrong href after document.open()."); + + SimpleTest.finish(); + yield undefined; +} + +window.addEventListener("load", function() { + gGen = run(); + gGen.next(); +}, false); + +]]> +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug237071.html b/dom/html/test/test_bug237071.html new file mode 100644 index 000000000..82bb68dbc --- /dev/null +++ b/dom/html/test/test_bug237071.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=237071 +--> +<head> + <title>Test for Bug 237071</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=237071">Mozilla Bug 237071</a> +<p id="display"></p> +<div id="content" > + <ol id="theOL" start="22"> + <li id="foo" >should be 22</li> + <li id="foo23">should be 23</li> + </ol> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +/** Test for Bug 237071 **/ +is($('theOL').start, 22, "OL start attribute mapped to .start, not just text attribute"); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug242709.html b/dom/html/test/test_bug242709.html new file mode 100644 index 000000000..af49eb93c --- /dev/null +++ b/dom/html/test/test_bug242709.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=242709 +--> +<head> + <title>Test for Bug 242709</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=242709">Mozilla Bug 242709</a> +<p id="display"></p> +<div id="content"> +<iframe src="bug242709_iframe.html" id="a"></iframe> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 242709 **/ + +SimpleTest.waitForExplicitFinish(); + +var submitted = function() { + ok(true, "Disabling button after form submission doesn't prevent submitting"); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug24958.html b/dom/html/test/test_bug24958.html new file mode 100644 index 000000000..3d62dae18 --- /dev/null +++ b/dom/html/test/test_bug24958.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=24958 +--> +<head> + <title>Test for Bug 24958</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <SCRIPT id="foo" TYPE="text/javascript">/*This space intentionally left blank*/</SCRIPT> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=24958">Mozilla Bug 24958</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 24958 **/ +ok($("foo").text, "\/*This space intentionally left blank*\/", "HTMLScriptElement.text should return text") + + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug255820.html b/dom/html/test/test_bug255820.html new file mode 100644 index 000000000..20727fee4 --- /dev/null +++ b/dom/html/test/test_bug255820.html @@ -0,0 +1,123 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=255820 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>Test for Bug 255820</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=255820">Mozilla Bug 255820</a> +<p id="display"> + <iframe id="f1"></iframe> + <iframe id="f2"></iframe> + <iframe id="f3"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 255820 **/ +SimpleTest.waitForExplicitFinish(); + +is(document.characterSet, "UTF-8", + "Unexpected character set for our document"); + +var testsLeft = 4; + +function testFinished() { + --testsLeft; + if (testsLeft == 0) { + SimpleTest.finish(); + } +} + +function charsetTestFinished(id, doc, charsetTarget) { + is(doc.characterSet, charsetTarget, "Unexpected charset for subframe " + id); + testFinished(); +} + +function f2Continue() { +// Commented out pending discussion at the WHATWG +// $("f2"). +// setAttribute("onload", +// "charsetTestFinished('f2 reloaded', this.contentDocument, 'us-ascii');"); + $("f2"). + setAttribute("onload", + "testFinished();"); + $("f2").contentWindow.location.reload(); +} + +function f3Continue() { + var doc = $("f3").contentDocument; + is(doc.defaultView.getComputedStyle(doc.body, "").color, "rgb(0, 180, 0)", + "Wrong color before reload"); + $("f3"). + setAttribute("onload", + 'var doc = this.contentDocument; ' + + 'is(doc.defaultView.getComputedStyle(doc.body, "").color, ' + + ' "rgb(0, 180, 0)",' + + ' "Wrong color after reload");' + + "charsetTestFinished('f1', this.contentDocument, 'UTF-8')"); + $("f3").contentWindow.location.reload(); +} + +function runTest() { + var doc = $("f1").contentDocument; + is(doc.characterSet, "UTF-8", + "Unexpected initial character set for first frame"); + doc.open(); + doc.write('<html></html>'); + doc.close(); + is(doc.characterSet, "UTF-8", + "Unexpected character set for first frame after write"); + $("f1"). + setAttribute("onload", + "charsetTestFinished('f1', this.contentDocument, 'UTF-8')"); + $("f1").contentWindow.location.reload(); + + doc = $("f2").contentDocument; + is(doc.characterSet, "UTF-8", + "Unexpected initial character set for second frame"); + doc.open(); + var str = '<html><head>'; + str += '<script src="data:application/javascript,"><'+'/script>'; + str += '<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">'; + str += '</head><body>'; + str += '</body></html>'; + doc.write(str); + doc.close(); + is(doc.characterSet, "UTF-8", + "Unexpected character set for second frame after write"); + $("f2"). + setAttribute("onload", + "charsetTestFinished('f2', this.contentDocument, 'UTF-8');" + + "f2Continue()"); + + doc = $("f3").contentDocument; + is(doc.characterSet, "UTF-8", + "Unexpected initial character set for first frame"); + doc.open(); + var str = '<html><head>'; + str += '<style>body { color: rgb(255, 0, 0) }</style>'; + str += '<link type="text/css" rel="stylesheet" href="data:text/css, body { color: rgb(0, 180, 0) }">'; + str += '</head><body>'; + str += '</body></html>'; + doc.write(str); + doc.close(); + is(doc.characterSet, "UTF-8", + "Unexpected character set for first frame after write"); + $("f3").setAttribute("onload", "f3Continue()"); +} + +addLoadEvent(runTest); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug259332.html b/dom/html/test/test_bug259332.html new file mode 100644 index 000000000..a0ad61f40 --- /dev/null +++ b/dom/html/test/test_bug259332.html @@ -0,0 +1,64 @@ +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=259332 +--> +<head> + <title>Test for Bug 259332</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=259332">Mozilla Bug 259332</a> +<p id="display"></p> +<div id="content"> + <div id="a">a + <div id="a">a</div> + <input name="a" value="a"> + <div id="b">b</div> + <input name="b" value="b"> + <div id="c">c</div> + </div> + <input name="write"> + <input name="write"> + <input id="write"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 259332 **/ + +list = document.all.a; +ok(list.length == 3, "initial a length"); + +blist = document.all.b; +ok(document.all.b.length == 2, "initial b length"); +document.getElementById('b').id = 'a'; +ok(document.all.b.nodeName == "INPUT", "just one b"); + +ok(blist.length == 1, "just one b"); +ok(list.length == 4, "one more a"); + +newDiv = document.createElement('div'); +newDiv.id = 'a'; +newDiv.innerHTML = 'a'; +list[0].appendChild(newDiv); +ok(list.length == 5, "two more a"); + +ok(document.all.c.textContent == 'c', "one c"); +document.all.c.id = 'a'; +ok(!document.all.c, "no c"); +ok(list.length == 6, "three more a"); + +ok(document.all.write.length == 3, "name is write"); + +newDiv = document.createElement('div'); +newDiv.id = 'd'; +newDiv.innerHTML = 'd'; +list[0].appendChild(newDiv); +ok(document.all.d.textContent == 'd', "new d"); + + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug274626.html b/dom/html/test/test_bug274626.html new file mode 100644 index 000000000..f4f045b21 --- /dev/null +++ b/dom/html/test/test_bug274626.html @@ -0,0 +1,97 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=274626 +--> +<head> + <title>Test for Bug 274626</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=274626">Mozilla Bug 274626</a> +<br> + +<input id='textbox_enabled' title='hello' value='hello' /> +<input id='textbox_disabled' title='hello' value='hello' disabled/> + +<br> +<input id='input_button_enabled' title='hello' value='hello' type='button' /> +<input id='input_button_disabled' title='hello' value='hello' type='button' disabled /> + +<br> +<input id='checkbox_enabled' title='hello' type='checkbox'>hello</input> +<input id='checkbox_disabled' title='hello' type='checkbox' disabled >hello</input> + +<br> +<button id='button_enabled' title='hello' value='hello' type='button'>test</button> +<button id='button_disabled' title='hello' value='hello' type='button' disabled>test</button> + +<br> +<textarea id='textarea_enabled' title='hello' value='hello' onclick="alert('click event');"> </textarea> +<textarea id='textarea_disabled' title='hello' value='hello' onclick="alert('click event');" disabled></textarea> + + +<br> +<select id='select_enabled' title='hello' onclick="alert('click event');"> + <option value='item1'>item1</option> + <option value='item2'>item2</option> +</select> +<select id='select_disabled' title='hello' onclick="alert('click event');" disabled> + <option value='item1'>item1</option> + <option value='item2'>item2</option> +</select> + +<br> +<form> + <fieldset id='fieldset_enabled' title='hello' onclick="alert('click event');"> + <legend>Enabled fieldset:</legend> + Name: <input type='text' size='30' /><br /> + Email: <input type='text' size='30' /><br /> + Date of birth: <input type='text' size='10' /> + </fieldset> +</form> +<form> + <fieldset id='fieldset_disabled' title='hello' onclick="alert('click event');" disabled> + <legend>Disabled fieldset:</legend> + Name: <input type='text' size='30' /><br /> + Email: <input type='text' size='30' /><br /> + Date of birth: <input type='text' size='10' /> + </fieldset> +</form> + +<script class="testbody" type="application/javascript"> + +/** Test for Bug 274626 **/ + + function HandlesMouseMove(evt) { + evt.target.handlesMouseMove = true; + } + + var controls=["textbox_enabled","textbox_disabled", + "input_button_enabled", "input_button_disabled", "checkbox_enabled", + "checkbox_disabled", "button_enabled", "button_disabled", + "textarea_enabled", "textarea_disabled", "select_enabled", + "select_disabled", "fieldset_enabled", "fieldset_disabled"]; + + for (id of controls) { + var ctrl = document.getElementById(id); + ctrl.addEventListener('mousemove', HandlesMouseMove, false); + ctrl.handlesMouseMove = false; + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("mousemove", true, true, window, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + ctrl.dispatchEvent(evt); + + // Mouse move events are what causes tooltips to show up. + // Before this fix we would not allow mouse move events to go through + // which in turn did not allow tooltips to be displayed. + // This test will ensure that all HTML elements handle mouse move events + // so that tooltips can be displayed + ok(ctrl.handlesMouseMove, "Disabled element need mouse move for tooltips"); + } + +</script> +</body> +</html> diff --git a/dom/html/test/test_bug277724.html b/dom/html/test/test_bug277724.html new file mode 100644 index 000000000..39b54cb7d --- /dev/null +++ b/dom/html/test/test_bug277724.html @@ -0,0 +1,141 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=277724 +--> +<head> + <title>Test for Bug 277724</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=277724">Mozilla Bug 277724</a> +<p id="display"></p> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 277724 **/ + +var childUnloaded = false; + +var nodes = [ + [ "select", HTMLSelectElement ], + [ "textarea", HTMLTextAreaElement ], + [ "text", HTMLInputElement ], + [ "password", HTMLInputElement ], + [ "checkbox", HTMLInputElement ], + [ "radio", HTMLInputElement ], + [ "image", HTMLInputElement ], + [ "submit", HTMLInputElement ], + [ "reset", HTMLInputElement ], + [ "button input", HTMLInputElement ], + [ "hidden", HTMLInputElement ], + [ "file", HTMLInputElement ], + [ "submit button", HTMLButtonElement ], + [ "reset button", HTMLButtonElement ], + [ "button", HTMLButtonElement ] +]; + +function soon(f) { + return function() { setTimeout(f, 0); } +} + +function startTest(frameid) { + is(childUnloaded, false, "Child not unloaded yet"); + + var doc = $(frameid).contentDocument; + ok(doc instanceof Document, "Check for doc", "doc should be a document"); + + for (var i = 0; i < nodes.length; ++i) { + var id = nodes[i][0]; + var node = doc.getElementById(id); + ok(node instanceof nodes[i][1], + "Check for " + id, id + " should be a " + nodes[i][1]); + is(node.disabled, false, "check for " + id + " state"); + node.disabled = true; + is(node.disabled, true, "check for " + id + " state change"); + } + + $(frameid).onload = soon(function() { continueTest(frameid) }); + + // Do this off a timeout so it's not treated like a replace load. + function loadBlank() { + $(frameid).contentWindow.location = "about:blank"; + } + setTimeout(loadBlank, 0); +} + +function continueTest(frameid) { + is(childUnloaded, true, "Unload handler should have fired"); + var doc = $(frameid).contentDocument; + ok(doc instanceof Document, "Check for doc", "doc should be a document"); + + for (var i = 0; i < nodes.length; ++i) { + var id = nodes[i][0]; + var node = doc.getElementById(id); + ok(node === null, + "Check for " + id, id + " should be null"); + } + + $(frameid).onload = soon(function() { finishTest(frameid); }); + + // Do this off a timeout too. Why, I'm not sure. Something in session + // history creates another history state if we don't. :( + function goBack() { + $(frameid).contentWindow.history.back(); + } + setTimeout(goBack, 0); +} + +// XXXbz this is a nasty hack to work around the XML content sink not being +// incremental, so that the _first_ control we test is ok but others are not. +var testIs = is; +var once = false; +function flipper(a, b, c) { + if (once) { + todo(a == b, c); + } else { + once = true; + is(a, b, c); + } +} + +function finishTest(frameid) { + var doc = $(frameid).contentDocument; + ok(doc instanceof Document, "Check for doc", "doc should be a document"); + + for (var i = 0; i < nodes.length; ++i) { + var id = nodes[i][0]; + var node = doc.getElementById(id); + ok(node instanceof nodes[i][1], + "Check for " + id, id + " should be a " + nodes[i][1]); + //testIs(node.disabled, true, "check for " + id + " state restore"); + } + + if (frameid == "frame2") { + SimpleTest.finish(); + } else { + childUnloaded = false; + + // XXXbz this is a nasty hack to deal with the content sink. See above. + testIs = flipper; + + $("frame2").onload = soon(function() { startTest("frame2"); }); + $("frame2").src = "bug277724_iframe2.xhtml"; + } +} + +SimpleTest.waitForExplicitFinish(); +</script> +</pre> + +<!-- Don't use display:none, since we don't support framestate restoration + without a frame tree --> +<div id="content" style="visibility: hidden"> + <iframe src="bug277724_iframe1.html" id="frame1" + onload="setTimeout(function() { startTest('frame1') }, 0)"></iframe> + <iframe src="" id="frame2"></iframe> +</div> +</body> +</html> + diff --git a/dom/html/test/test_bug277890.html b/dom/html/test/test_bug277890.html new file mode 100644 index 000000000..066271bd0 --- /dev/null +++ b/dom/html/test/test_bug277890.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=277890 +--> +<head> + <title>Test for Bug 277890</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=277890">Mozilla Bug 277890</a> +<p id="display"></p> +<div id="content"> +<iframe src="bug277890_iframe.html" id="a"></iframe> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 277890 **/ + +SimpleTest.waitForExplicitFinish(); + +var submitted = function() { + ok(true, "Disabling button after form submission doesn't prevent submitting"); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug287465.html b/dom/html/test/test_bug287465.html new file mode 100644 index 000000000..fb5430e95 --- /dev/null +++ b/dom/html/test/test_bug287465.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=287465 +--> +<head> + <title>Test for Bug 287465</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=287465">Mozilla Bug 287465</a> +<p id="display"></p> +<div id="content" style="display:none"> + +<iframe id="i1" src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>"></iframe> +<object id="o1" data="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>"></object> +<iframe id="i2" src="data:text/html,<html></html>"></iframe> +<object id="o2" data="data:text/html,<html></html>"></object> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(doTest); + +function doTest() { + function checkSVGDocument(id) { + var e = document.getElementById(id); + ok(e.contentDocument != null, "check nonnull contentDocument '" + id + "'"); + is(e.contentDocument, e.getSVGDocument(), "check documents match '" + id + "'"); + } + + checkSVGDocument("o1"); + checkSVGDocument("i1"); + checkSVGDocument("o2"); + checkSVGDocument("i2"); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug295561.html b/dom/html/test/test_bug295561.html new file mode 100644 index 000000000..e283092a7 --- /dev/null +++ b/dom/html/test/test_bug295561.html @@ -0,0 +1,86 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=295561 +--> +<head> + <title>Test for Bug 295561</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=295561">Mozilla Bug 295561</a> +<p id="display"></p> +<div id="content" style="display: none"> + +<table id="testTable"> +<thead> +<tr id="headRow"><td></td></tr> +</thead> +<tfoot> +<tr id="footRow"><td></td></tr> +</tfoot> +<tbody id="tBody" name="namedTBody"> +<tr id="trow" name="namedTRow"> +<td id="tcell" name="namedTCell"></td> +<th id="tcellh" name="namedTH"></th> +</tr> +<tr><td></td></tr> +</tbody> +<tbody id="tBody2" name="namedTBody2"> +<tr id="trow2" name="namedTRow2"> +<td id="tcell2" name="namedTCell2"></td> +<th id="tcellh2" name="namedTH2"></th> +</tr> +</table> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +function testItById(id, collection, collectionName) { + is(collection[id], $(id), + "Should be able to get by id '" + id + "' from " + collectionName + + " collection using square brackets.") + is(collection.namedItem(id), $(id), + "Should be able to get by id '" + id + "' from " + collectionName + + " collection using namedItem.") +} + +function testItByName(name, id, collection, collectionName) { + is(collection[name], $(id), + "Should be able to get by name '" + name + "' from " + collectionName + + " collection using square brackets.") + is(collection.namedItem(name), $(id), + "Should be able to get by name '" + name + "' from " + collectionName + + " collection using namedItem.") +} + +function testIt(name, id, collection, collectionName) { + testItByName(name, id, collection, collectionName); + testItById(id, collection, collectionName); +} + +var table = $("testTable") +testIt("namedTBody", "tBody", table.tBodies, "tBodies") +testIt("namedTRow", "trow", table.rows, "table rows") +testIt("namedTRow", "trow", $("tBody").rows, "tbody rows") +testIt("namedTCell", "tcell", $("trow").cells, "cells") +testIt("namedTH", "tcellh", $("trow").cells, "cells") +testIt("namedTBody2", "tBody2", table.tBodies, "tBodies") +testIt("namedTRow2", "trow2", table.rows, "table rows") +testIt("namedTRow2", "trow2", $("tBody2").rows, "tbody rows") +testIt("namedTCell2", "tcell2", $("trow2").cells, "cells") +testIt("namedTH2", "tcellh2", $("trow2").cells, "cells") +is(table.tBodies.length, 2, "Incorrect tBodies length"); +is(table.rows.length, 5, "Incorrect rows length"); +is(table.rows[0], $("headRow"), "THead row in wrong spot"); +is(table.rows[1], $("trow"), "First tbody row in wrong spot"); +is(table.rows[3], $("trow2"), "Second tbody row in wrong spot"); +is(table.rows[4], $("footRow"), "TFoot row in wrong spot"); + + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug297761.html b/dom/html/test/test_bug297761.html new file mode 100644 index 000000000..02d79f9bc --- /dev/null +++ b/dom/html/test/test_bug297761.html @@ -0,0 +1,77 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=297761 +--> +<head> + <title>Test for Bug 297761</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=297761">Mozilla Bug 297761</a> +<p id="display"></p> +<div id="content"> + <iframe src="file_bug297761.html"></iframe> + <iframe src="file_bug297761.html"></iframe> + <iframe src="file_bug297761.html"></iframe> + <iframe src="file_bug297761.html"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 297761 **/ + +SimpleTest.waitForExplicitFinish(); + +var nbTests = 4; +var curTest = 0; + +function nextTest() +{ + if (curTest == 3) { + frames[curTest].document.forms[0].submit(); + } else { + var el = null; + if (curTest == 2) { + el = frames[curTest].document.getElementById('i'); + } else { + el = frames[curTest].document.forms[0].elements[curTest]; + } + + el.focus(); + el.click(); + } +} + +function frameLoaded(aFrame) +{ + var documentLocation = location.href.replace(/\.html.*/, "\.html"); + is(aFrame.contentWindow.location.href.replace(/\?x=0&y=0/, ""), + documentLocation.replace(/test_bug/, "file_bug"), + "form should have been submitted to the document location"); + + if (++curTest == nbTests) { + SimpleTest.finish(); + } else { + nextTest(); + } +} + +function runTest() +{ + // Initialize event handlers. + var frames = document.getElementsByTagName('iframe'); + for (var i=0; i<nbTests; ++i) { + frames[i].setAttribute('onload', "frameLoaded(this);"); + } + + nextTest(); +} + +addLoadEvent(runTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug300691-1.html b/dom/html/test/test_bug300691-1.html new file mode 100644 index 000000000..40d12f9bf --- /dev/null +++ b/dom/html/test/test_bug300691-1.html @@ -0,0 +1,120 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=300691 +--> +<head> + <title>Test for Bug 300691</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=300691">Mozilla Bug 300691</a> +<p id="display"> + <textarea id="target"></textarea> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +var t = $("target"); + +/** Test for Bug 300691 **/ +function valueIs(arg, reason) { + is(t.value, arg, reason); +} + +function defValueIs(arg, reason) { + is(t.defaultValue, arg, reason); +} + +valueIs("", "Nothing in the textarea"); +defValueIs("", "Nothing in the textarea 2"); + +t.appendChild(document.createTextNode("ab")); +valueIs("ab", "Appended textnode"); +defValueIs("ab", "Appended textnode 2"); + +t.firstChild.data = "abcd"; +valueIs("abcd", "Modified textnode text"); +defValueIs("abcd", "Modified textnode text 2"); + +t.appendChild(document.createTextNode("efgh")); +valueIs("abcdefgh", "Appended another textnode"); +defValueIs("abcdefgh", "Appended another textnode 2"); + +t.removeChild(t.lastChild); +valueIs("abcd", "Removed textnode"); +defValueIs("abcd", "Removed textnode 2"); + +t.appendChild(document.createTextNode("efgh")); +valueIs("abcdefgh", "Appended yet another textnode"); +defValueIs("abcdefgh", "Appended yet another textnode 2"); + +t.normalize(); +valueIs("abcdefgh", "Normalization changes nothing for the value"); +defValueIs("abcdefgh", "Normalization changes nothing for the value 2"); + +t.defaultValue = "abc"; +valueIs("abc", "Just set the default value on non-edited textarea"); +defValueIs("abc", "Just set the default value on non-edited textarea 2"); + +t.appendChild(document.createTextNode("defgh")); +valueIs("abcdefgh", "Appended another textnode again"); +defValueIs("abcdefgh", "Appended another textnode again 2"); + +t.focus(); // This puts the caret at the end of the textarea, and doing + // something like "home" in a cross-platform way is kinda hard. +sendKey("left"); +sendKey("left"); +sendKey("left"); +sendString("Test"); + +valueIs("abcdeTestfgh", "Typed 'Test' after three left-arrows starting from end"); +defValueIs("abcdefgh", "Typing 'Test' shouldn't affect default value"); + +sendKey("right"); +sendKey("right"); +sendKey("back_space"); +sendKey("back_space"); + +valueIs("abcdeTesth", + "Backspaced twice after two right-arrows starting from end of typing"); +defValueIs("abcdefgh", "Deleting shouldn't affect default value"); + +t.appendChild(document.createTextNode("ijk")); +valueIs("abcdeTesth", + "Appending textnode shouldn't affect value in edited textarea"); +defValueIs("abcdefghijk", "Appended textnode 3"); + +t.lastChild.data = "lmno"; +valueIs("abcdeTesth", + "Modifying textnode text shouldn't affect value in edited textarea"); +defValueIs("abcdefghlmno", "Modified textnode text 3"); + +t.removeChild(t.firstChild); +valueIs("abcdeTesth", + "Removing child textnode shouldn't affect value in edited textarea"); +defValueIs("defghlmno", "Removed textnode 3"); + +t.insertBefore(document.createTextNode("abc"), t.firstChild); +valueIs("abcdeTesth", + "Inserting child textnode shouldn't affect value in edited textarea"); +defValueIs("abcdefghlmno", "Inserted a text node"); + +t.normalize(); +valueIs("abcdeTesth", "Normalization changes nothing for the value 3"); +defValueIs("abcdefghlmno", "Normalization changes nothing for the value 4"); + +t.defaultValue = "abc"; +valueIs("abcdeTesth", "Setting default value shouldn't affect edited textarea"); +defValueIs("abc", "Just set the default value textarea"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug300691-2.html b/dom/html/test/test_bug300691-2.html new file mode 100644 index 000000000..6dfa42621 --- /dev/null +++ b/dom/html/test/test_bug300691-2.html @@ -0,0 +1,142 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=300691 +--> +<head> + <title>Test for Bug 300691</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=300691">Mozilla Bug 300691</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="text/javascript"> + // First, setup. We'll be toggling these variables as we go. + var test1Ran = false; + var test2Ran = false; + var test3Ran = false; + var test4Ran = false; + var test5Ran = false; + var test6Ran = false; + var test7Ran = false; + var test8Ran = false; + var test9Ran = false; + var test10Ran = false; + var test11Ran = false; + var test12Ran = false; + var test13Ran = false; + var test14aRan = false; + var test14bRan = false; + var test15aRan = false; + var test15bRan = false; +</script> +<script id="test1" type="text/javascript">test1Ran = true;</script> +<script id="test2" type="text/javascript"></script> +<script id="test3" type="text/javascript">;</script> +<script id="test4" type="text/javascript"> </script> +<script id="test5" type="text/javascript"></script> +<script id="test6" type="text/javascript"></script> +<script id="test7" type="text/javascript"></script> +<script id="test8" type="text/javascript"></script> +<script id="test9" type="text/javascript"></script> +<script id="test10" type="text/javascript" src="data:text/javascript,"> + test10Ran = true; +</script> +<script id="test11" type="text/javascript" + src="data:text/javascript,test11Ran = true"> + test11Ran = false; +</script> +<script id="test12" type="text/javascript"></script> +<script id="test13" type="text/javascript"></script> +<script id="test14" type="text/javascript"></script> +<script id="test15" type="text/javascript"></script> +<script class="testbody" type="text/javascript"> + /** Test for Bug 300691 **/ + $("test2").appendChild(document.createTextNode("test2Ran = true")); + is(test2Ran, true, "Should be 2!"); + + $("test3").appendChild(document.createTextNode("test3Ran = true")); + is(test3Ran, false, "Should have run already 3!"); + + $("test4").appendChild(document.createTextNode("test4Ran = true")); + is(test4Ran, false, "Should have run already 4!"); + + $("test5").appendChild(document.createTextNode(" ")); + $("test5").appendChild(document.createTextNode("test5Ran = true")); + is(test5Ran, false, "Should have run already 5!"); + + $("test6").appendChild(document.createTextNode(" ")); + + $("test7").appendChild(document.createTextNode("")); + + $("test8").appendChild(document.createTextNode("")); + + $("test9").appendChild(document.createTextNode("")); + + $("test12").src = "data:text/javascript,test12Ran = true;"; + is(test12Ran, false, "Not yet 12!"); + + $("test13").setAttribute("src", "data:text/javascript,test13Ran = true;"); + is(test13Ran, false, "Not yet 13!"); + + $("test14").src = "data:text/javascript,test14aRan = true;"; + $("test14").appendChild(document.createTextNode("test14bRan = true")); + is(test14aRan, false, "Not yet 14a!"); + is(test14bRan, false, "Not yet 14b!"); + + $("test15").src = "data:text/javascript,test15aRan = true;"; + $("test15").appendChild(document.createTextNode("test15bRan = true")); + $("test15").removeAttribute("src"); + is(test15aRan, false, "Not yet 15a!"); + is(test15bRan, false, "Not yet 15b!"); +</script> +<script type="text/javascript"> + // Follow up on some of those + $("test6").appendChild(document.createTextNode("test6Ran = true")); + is(test6Ran, false, "Should have run already 6!"); + + $("test7").appendChild(document.createTextNode("test7Ran = true")); + is(test7Ran, true, "Should be 7!"); + + $("test8").insertBefore(document.createTextNode("test8Ran = true"), + $("test8").firstChild); + is(test8Ran, true, "Should be 8!"); + + $("test9").firstChild.data = "test9Ran = true"; + is(test9Ran, true, "Should be 9!"); +</script> +<script type="text/javascript"> +function done() { + is(test1Ran, true, "Should have run!"); + is(test3Ran, false, "Already executed test3 script once"); + is(test4Ran, false, + "Should have executed whitespace-only script already"); + is(test5Ran, false, + "Should have executed once the whitespace node was added"); + is(test6Ran, false, + "Should have executed once the whitespace node was added 2"); + is(test10Ran, false, "Has an src; inline part shouldn't run"); + is(test11Ran, true, "Script with src should have run"); + is(test12Ran, true, "Setting src should execute script"); + is(test13Ran, true, "Setting src attribute should execute script"); + is(test14aRan, true, "src attribute takes precedence over inline content"); + is(test14bRan, false, "src attribute takes precedence over inline content 2"); + is(test15aRan, true, + "src attribute load should have started before the attribute got removed"); + is(test15bRan, false, + "src attribute still got executed, so this shouldn't have been"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(done); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug300691-3.xhtml b/dom/html/test/test_bug300691-3.xhtml new file mode 100644 index 000000000..84c732c2b --- /dev/null +++ b/dom/html/test/test_bug300691-3.xhtml @@ -0,0 +1,48 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=300691 +--> +<head> + <title>Test for Bug 300691</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=300691">Mozilla Bug 300691</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="text/javascript"> + // First, setup. We'll be toggling these variables as we go. + // Note that scripts don't execute immediately when you put text in them -- + // they wait for the currently-running script to finish. + var test1Ran = false; + var test2Ran = false; + var test3Ran = false; +</script> +<script id="test1" type="text/javascript">test1Ran = true;</script> +<script id="test2" type="text/javascript"></script> +<script id="test3" type="text/javascript"></script> +<script class="testbody" type="text/javascript"> +<![CDATA[ + /** Test for Bug 300691 **/ + $("test2").appendChild(document.createCDATASection("test2Ran = true")); + is(test2Ran, true, "Should be 2!"); + + $("test3").appendChild(document.createCDATASection("")); +]]> +</script> +<script type="text/javascript"> + // Follow up on some of those + $("test3").firstChild.data = "test3Ran = true"; + is(test3Ran, true, "Should be 3!"); +</script> +<script type="text/javascript"> + is(test1Ran, true, "Should have run!"); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug311681.html b/dom/html/test/test_bug311681.html new file mode 100644 index 000000000..b9139a391 --- /dev/null +++ b/dom/html/test/test_bug311681.html @@ -0,0 +1,99 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=311681 +--> +<head> + <title>Test for Bug 311681</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=311681">Mozilla Bug 311681</a> +<script class="testbody" type="text/javascript"> + // Setup script + SimpleTest.waitForExplicitFinish(); + + // Make sure to trigger the hashtable case by asking for enough elements + // by ID. + for (var i = 0; i < 256; ++i) { + var x = document.getElementById(i); + } + + // save off the document.getElementById function, since getting it as a + // property off the document it causes a content flush. + var fun = document.getElementById; + + // Slot for our initial element with id "content" + var testNode; + + function getCont() { + return fun.call(document, "content"); + } + + function testClone() { + // Test to make sure that if we have multiple nodes with the same ID in + // a document we don't forget about one of them when the other is + // removed. + var newParent = $("display"); + var node = testNode.cloneNode(true); + isnot(node, testNode, "Clone should be a different node"); + + newParent.appendChild(node); + + // Check what getElementById returns, no flushing + is(getCont(), node, "Should be getting new node pre-flush 1"); + + // Trigger a layout flush, just in case. + var itemHeight = newParent.offsetHeight/10; + + // Check what getElementById returns now. + is(getCont(), node, "Should be getting new node post-flush 1"); + + clear(newParent); + + // Check what getElementById returns, no flushing + is(getCont(), testNode, "Should be getting orig node pre-flush 2"); + + // Trigger a layout flush, just in case. + var itemHeight = newParent.offsetHeight/10; + + // Check what getElementById returns now. + is(getCont(), testNode, "Should be getting orig node post-flush 2"); + + node = testNode.cloneNode(true); + newParent.appendChild(node); + testNode.parentNode.removeChild(testNode); + + // Check what getElementById returns, no flushing + is(getCont(), node, "Should be getting clone pre-flush"); + + // Trigger a layout flush, just in case. + var itemHeight = newParent.offsetHeight/10; + + // Check what getElementById returns now. + is(getCont(), node, "Should be getting clone post-flush"); + + } + + function clear(node) { + while (node.hasChildNodes()) { + node.removeChild(node.firstChild); + } + } + + addLoadEvent(testClone); + addLoadEvent(SimpleTest.finish); +</script> +<p id="display"></p> +<div id="content" style="display: none"> + <script class="testbody" type="text/javascript"> + testNode = fun.call(document, "content"); + isnot(testNode, null, "Should have node here"); + </script> +</div> +<pre id="test"> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug311681.xhtml b/dom/html/test/test_bug311681.xhtml new file mode 100644 index 000000000..0c7d5fd6f --- /dev/null +++ b/dom/html/test/test_bug311681.xhtml @@ -0,0 +1,102 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=311681 +--> +<head> + <title>Test for Bug 311681</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=311681">Mozilla Bug 311681</a> +<script class="testbody" type="text/javascript"> +<![CDATA[ + // Setup script + SimpleTest.waitForExplicitFinish(); + + // Make sure to trigger the hashtable case by asking for enough elements + // by ID. + for (var i = 0; i < 256; ++i) { + var x = document.getElementById(i); + } + + // save off the document.getElementById function, since getting it as a + // property off the document it causes a content flush. + var fun = document.getElementById; + + // Slot for our initial element with id "content" + var testNode; + + function getCont() { + return fun.call(document, "content"); + } + + function testClone() { + // Test to make sure that if we have multiple nodes with the same ID in + // a document we don't forget about one of them when the other is + // removed. + var newParent = $("display"); + var node = testNode.cloneNode(true); + isnot(node, testNode, "Clone should be a different node"); + + newParent.appendChild(node); + + // Check what getElementById returns, no flushing + is(getCont(), node, "Should be getting new node pre-flush 1"); + + // Trigger a layout flush, just in case. + var itemHeight = newParent.offsetHeight/10; + + // Check what getElementById returns now. + is(getCont(), node, "Should be getting new node post-flush 1"); + + clear(newParent); + + // Check what getElementById returns, no flushing + is(getCont(), testNode, "Should be getting orig node pre-flush 2"); + + // Trigger a layout flush, just in case. + var itemHeight = newParent.offsetHeight/10; + + // Check what getElementById returns now. + is(getCont(), testNode, "Should be getting orig node post-flush 2"); + + node = testNode.cloneNode(true); + newParent.appendChild(node); + testNode.parentNode.removeChild(testNode); + + // Check what getElementById returns, no flushing + is(getCont(), node, "Should be getting clone pre-flush"); + + // Trigger a layout flush, just in case. + var itemHeight = newParent.offsetHeight/10; + + // Check what getElementById returns now. + is(getCont(), node, "Should be getting clone post-flush"); + + } + + function clear(node) { + while (node.hasChildNodes()) { + node.removeChild(node.firstChild); + } + } + + addLoadEvent(testClone); + addLoadEvent(SimpleTest.finish); +]]> +</script> +<p id="display"></p> +<div id="content" style="display: none"> + <script class="testbody" type="text/javascript"> + <![CDATA[ + testNode = fun.call(document, "content"); + ok(testNode != null, "Should have node here"); + ]]> + </script> +</div> +<pre id="test"> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug324378.html b/dom/html/test/test_bug324378.html new file mode 100644 index 000000000..166e4f149 --- /dev/null +++ b/dom/html/test/test_bug324378.html @@ -0,0 +1,76 @@ +<!DOCTYPE HTML> +<html id="a" id="b"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=324378 +--> +<head id="c" id="d"> + <head id="j" foo="k" foo="l"> + <title>Test for Bug 324378</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body id="e" id="f"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=324378">Mozilla Bug 324378</a> +<script> + var html = document.documentElement; + is(document.getElementsByTagName("html").length, 1, + "Unexpected number of htmls"); + is(document.getElementsByTagName("html")[0], html, + "Unexpected <html> element"); + is(document.getElementsByTagName("head").length, 1, + "Unexpected number of heads"); + is(html.getElementsByTagName("head").length, 1, + "Unexpected number of heads in <html>"); + is(document.getElementsByTagName("body").length, 1, + "Unexpected number of bodies"); + is(html.getElementsByTagName("body").length, 1, + "Unexpected number of bodies in <html>"); + var head = document.getElementsByTagName("head")[0]; + var body = document.getElementsByTagName("body")[0]; +</script> +<p id="display"></p> +<div id="content" style="display: none"> + <html id="g" foo="h" foo="i"> + <body id="m" foo="n" foo="o"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 324378 **/ + is(document.getElementsByTagName("html").length, 1, + "Unexpected number of htmls after additions"); + is(document.getElementsByTagName("html")[0], html, + "Unexpected <html> element"); + is(document.documentElement, html, + "Unexpected root node"); + is(document.getElementsByTagName("head").length, 1, + "Unexpected number of heads after additions"); + is(document.getElementsByTagName("head")[0], head, + "Unexpected <head> element"); + is(document.getElementsByTagName("body").length, 1, + "Unexpected number of bodies after additions"); + is(document.getElementsByTagName("body")[0], body, + "Unexpected <body> element"); + + is(html.id, "a", "Unexpected <html> id"); + is(head.id, "c", "Unexpected <head> id"); + is(body.id, "e", "Unexpected <body> id"); + is($("a"), html, "Unexpected node with id=a"); + is($("b"), null, "Unexpected node with id=b"); + is($("c"), head, "Unexpected node with id=c"); + is($("d"), null, "Unexpected node with id=d"); + is($("e"), body, "Unexpected node with id=e"); + is($("f"), null, "Unexpected node with id=f"); + is($("g"), null, "Unexpected node with id=g"); + is($("j"), null, "Unexpected node with id=j"); + is($("m"), null, "Unexpected node with id=m"); + + is(html.getAttribute("foo"), "h", "Unexpected 'foo' value on <html>"); + is(head.getAttribute("foo"), null, "Unexpected 'foo' value on <head>"); + is(body.getAttribute("foo"), "n", "Unexpected 'foo' value on <body>"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug330705-1.html b/dom/html/test/test_bug330705-1.html new file mode 100644 index 000000000..2a5c737ed --- /dev/null +++ b/dom/html/test/test_bug330705-1.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=330705 +--> +<head> + <title>Test for Bug 330705</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <script> + /* variable is true if the element is focused, false otherwise */ + var inputFocused = false; + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=330705">Mozilla Bug 330705</a> +<p id="display"> + <input onfocus="inputFocused = true" onblur="inputFocused = false" type="text"> + <button></button> +</p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +/** Test for Bug 330705 **/ + SimpleTest.waitForExplicitFinish(); + var isFocused = false; + + function onLoad() { + document.getElementsByTagName('input')[0].focus(); + document.getElementsByTagName('button')[0].blur(); + ok(inputFocused == true, "the input element is still focused after blur() has been called on the unfocused element"); + SimpleTest.finish(); + } + + addLoadEvent(onLoad); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug332246.html b/dom/html/test/test_bug332246.html new file mode 100644 index 000000000..e1acbe309 --- /dev/null +++ b/dom/html/test/test_bug332246.html @@ -0,0 +1,75 @@ +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=332246 +--> +<head> + <title>Test for Bug 332246 - scrollIntoView(false) doesn't work correctly for inline elements that wrap at multiple lines</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332246">Mozilla Bug 332246</a> +<p id="display"></p> +<div id="content"> + +<div id="a1" style="height: 100px; width: 100px; overflow: hidden; outline:1px dotted black;"> +<div style="height: 100px"></div> +<a id="a2" href="#" style="display:block; background:yellow; height:200px;">Top</a> +<div style="height: 100px"></div> +</div> + +<div id="b1" style="height: 100px; width: 100px; overflow: hidden; outline:1px dotted black;"> +<div style="height: 100px"></div> +<div id="b2" href="#" style="border:10px solid black; background:yellow; height:200px;"></div> +<div style="height: 100px"></div> +</div> + +<br> + +<div id="c1" style="height: 100px; width: 100px; overflow: hidden; position: relative; outline:1px dotted black;"> +<div id="c2" style="border: 10px solid black; height: 200px; width: 50px; position: absolute; top: 100px;"></div> +<div style="height: 100px"></div> +</div> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 332246 **/ + +function isWithFuzz(itIs, itShouldBe, fuzz, description) { + ok(Math.abs(itIs - itShouldBe) <= fuzz, `${description} - expected a value between ${itShouldBe - fuzz} and ${itShouldBe + fuzz}, got ${itIs}`); +} + +var a1 = document.getElementById('a1'); +var a2 = document.getElementById('a2'); +isWithFuzz(a1.scrollHeight, 400, 1, "Wrong a1.scrollHeight"); +is(a1.offsetHeight, 100, "Wrong a1.offsetHeight"); +a2.scrollIntoView(true); +is(a1.scrollTop, 100, "Wrong scrollTop value after a2.scrollIntoView(true)"); +a2.scrollIntoView(false); +is(a1.scrollTop, 200, "Wrong scrollTop value after a2.scrollIntoView(false)"); + +var b1 = document.getElementById('b1'); +var b2 = document.getElementById('b2'); +isWithFuzz(b1.scrollHeight, 420, 1, "Wrong b1.scrollHeight"); +is(b1.offsetHeight, 100, "Wrong b1.offsetHeight"); +b2.scrollIntoView(true); +is(b1.scrollTop, 100, "Wrong scrollTop value after b2.scrollIntoView(true)"); +b2.scrollIntoView(false); +is(b1.scrollTop, 220, "Wrong scrollTop value after b2.scrollIntoView(false)"); + +var c1 = document.getElementById('c1'); +var c2 = document.getElementById('c2'); +isWithFuzz(c1.scrollHeight, 320, 1, "Wrong c1.scrollHeight"); +is(c1.offsetHeight, 100, "Wrong c1.offsetHeight"); +c2.scrollIntoView(true); +is(c1.scrollTop, 100, "Wrong scrollTop value after c2.scrollIntoView(true)"); +c2.scrollIntoView(false); +isWithFuzz(c1.scrollTop, 220, 1, "Wrong scrollTop value after c2.scrollIntoView(false)"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug332848.xhtml b/dom/html/test/test_bug332848.xhtml new file mode 100644 index 000000000..2b19e6b78 --- /dev/null +++ b/dom/html/test/test_bug332848.xhtml @@ -0,0 +1,86 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=332848 +--> +<head> + <title>Test for Bug 332848</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332848">Mozilla Bug 332848</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +<![CDATA[ + +/** Test for Bug 332848 **/ + +// parseChecker will become true if we keep parsing after calling close(). +var parseChecker = false; + +function test() { + try { + document.open(); + is(0, 1, "document.open succeeded"); + } catch (e) { + is (e.name, "InvalidStateError", + "Wrong exception from document.open"); + is (e.code, DOMException.INVALID_STATE_ERR, + "Wrong exception from document.open"); + } + + try { + document.write("aaa"); + is(0, 1, "document.write succeeded"); + } catch (e) { + is (e.name, "InvalidStateError", + "Wrong exception from document.write"); + is (e.code, DOMException.INVALID_STATE_ERR, + "Wrong exception from document.write"); + } + + try { + document.writeln("aaa"); + is(0, 1, "document.write succeeded"); + } catch (e) { + is (e.name, "InvalidStateError", + "Wrong exception from document.write"); + is (e.code, DOMException.INVALID_STATE_ERR, + "Wrong exception from document.write"); + } + + try { + document.close(); + is(0, 1, "document.close succeeded"); + } catch (e) { + is (e.name, "InvalidStateError", + "Wrong exception from document.close"); + is (e.code, DOMException.INVALID_STATE_ERR, + "Wrong exception from document.close"); + } +} + +function loadTest() { + is(parseChecker, true, "Parsing stopped"); + test(); + SimpleTest.finish(); +} + +window.onload = loadTest; + +SimpleTest.waitForExplicitFinish(); + +test(); +]]> +</script> +<script> + parseChecker = true; +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug332893-1.html b/dom/html/test/test_bug332893-1.html new file mode 100644 index 000000000..4136c73e6 --- /dev/null +++ b/dom/html/test/test_bug332893-1.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> + +<form id="form1"> + <input id="F1I1" type="input" value="11"/> + <input id="F1I2" type="input" value="12"/> +</form> +<form id="form2"> + <input id="F2I1" type="input" value="21"/> + <input id="F2I2" type="input" value="22"/> +</form> +<script> +<!-- Create a new input, add it to the first form, move it to the 2nd form, then move it back to the first --> + var form1 = document.getElementById("form1"); + var form2 = document.getElementById("form2"); + var newInput = document.createElement("input"); + newInput.value = "13"; + form1.insertBefore(newInput, form1.firstChild); + var F2I2 = document.getElementById("F2I2"); + form2.insertBefore(newInput, F2I2); + form1.insertBefore(newInput, form1.firstChild); + + is(form1.elements.length, 3, "Form 1 has the correct length"); + is(form1.elements[0].value, "13", "Form 1 element 1 is correct"); + is(form1.elements[1].value, "11", "Form 1 element 2 is correct"); + is(form1.elements[2].value, "12", "Form 1 element 3 is correct"); + + is(form2.elements.length, 2, "Form 2 has the correct length"); + is(form2.elements[0].value, "21", "Form 2 element 1 is correct"); + is(form2.elements[1].value, "22", "Form 2 element 2 is correct"); +</script> +</body> +</html> diff --git a/dom/html/test/test_bug332893-2.html b/dom/html/test/test_bug332893-2.html new file mode 100644 index 000000000..36083b6a1 --- /dev/null +++ b/dom/html/test/test_bug332893-2.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> + + +<form id="form1"> + <table> + <tbody id="table1"> + <tr id="F1I0"><td><input form='form1' type="input" value="10"/></td></tr> + <tr id="F1I1"><td><input type="input" value="11"/></td></tr> + <tr id="F1I2"><td><input type="input" value="12"/></td></tr> + </tbody> + </table> +</form> +<form id="form2"> + <table> + <tbody id="table2"> + <tr id="F2I1"><td><input type="input" value="21"/></td></tr> + <tr id="F2I2"><td><input type="input" value="22"/></td></tr> + </tbody> + </table> +</form> + +<script> + var table1 = document.getElementById("table1"); + var F1I0 = table1.getElementsByTagName("tr")[0]; + var F1I1 = table1.getElementsByTagName("tr")[1]; + table1.removeChild(F1I0); + table1.removeChild(F1I1); + + var table2 = document.getElementById("table2"); + table2.insertBefore(F1I0, table2.firstChild); + table2.insertBefore(F1I1, table2.firstChild); + + var form1 = document.getElementById("form1"); + var form2 = document.getElementById("form2"); + + is(form1.elements.length, 2, "Form 1 length is correct"); + is(form1.elements[0].value, "12", "Form 1 first element is correct"); + is(form1.elements[1].value, "10", "Form 2 second element is correct"); + is(form2.elements.length, 3, "Form 2 length is correct"); + is(form2.elements[0].value, "11", "Form 2 element 1 is correct"); + is(form2.elements[1].value, "21", "Form 2 element 2 is correct"); + is(form2.elements[2].value, "22", "Form 2 element 3 is correct"); + +</script> + +</body> +</html> diff --git a/dom/html/test/test_bug332893-3.html b/dom/html/test/test_bug332893-3.html new file mode 100644 index 000000000..372319c22 --- /dev/null +++ b/dom/html/test/test_bug332893-3.html @@ -0,0 +1,58 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<form id="form1"> + <table> + <tbody> + <tr> + <td> + <table> + <tbody id="table1"> + <tr id="F1I0"><td><input form='form1' type="input" value="10"/></td></tr> + <tr id="F1I1"><td><input type="input" value="11"/></td></tr> + <tr id="F1I2"><td><input type="input" value="12"/></td></tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> +</form> +<form id="form2"> + <table> + <tbody id="table2"> + <tr id="F2I1"><td><input type="input" value="21"/></td></tr> + <tr id="F2I2"><td><input type="input" value="22"/></td></tr> + </tbody> + </table> +</form> + +<script> + var table1 = document.getElementById("table1"); + var F1I0 = table1.getElementsByTagName("tr")[0]; + var F1I1 = table1.getElementsByTagName("tr")[1]; + table1.removeChild(F1I0); + table1.removeChild(F1I1); + + var table2 = document.getElementById("table2"); + table2.insertBefore(F1I0, table2.firstChild); + table2.insertBefore(F1I1, table2.firstChild); + + var form1 = document.getElementById("form1"); + var form2 = document.getElementById("form2"); + + is(form1.elements.length, 2, "Form 1 has the correct length"); + is(form1.elements[0].value, "12", "Form 1 element 1 is correct"); + is(form1.elements[1].value, "10", "Form 1 element 2 is correct"); + + is(form2.elements.length, 3, "Form 2 has the correct length"); + is(form2.elements[0].value, "11", "Form 2 element 1 is correct"); + is(form2.elements[1].value, "21", "Form 2 element 2 is correct"); + is(form2.elements[2].value, "22", "Form 2 element 2 is correct"); +</script> +</body> +</html> diff --git a/dom/html/test/test_bug332893-4.html b/dom/html/test/test_bug332893-4.html new file mode 100644 index 000000000..abbc60ca6 --- /dev/null +++ b/dom/html/test/test_bug332893-4.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<form id="form1"> + <input id="input1" type="input" name="input" value="1"/> + <input id="input2" type="input" name="input" value="2"/> + <input id="input3" type="input" name="input" value="3"/> +</form> +<script> + var input1 = document.getElementById("input1"); + var input2 = document.getElementById("input2"); + var form1 = document.getElementById("form1"); + form1.insertBefore(input2, input1); + + is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length"); + is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct"); + is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct"); + is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct"); + + is(form1.elements["input"][0].id, "input2", "Form 1 element 1 id is correct"); + is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct"); + is(form1.elements["input"][2].id, "input3", "Form 1 element 3 id is correct"); +</script> +</body> +</html> diff --git a/dom/html/test/test_bug332893-5.html b/dom/html/test/test_bug332893-5.html new file mode 100644 index 000000000..6898f9157 --- /dev/null +++ b/dom/html/test/test_bug332893-5.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<form id="form1"> + <input id="input1" type="input" name="input" value="1"/> + <input id="input" type="input" name="input_other" value="2"/> + <input id="input3" type="input" name="input" value="3"/> +</form> +<script> + var input1 = document.getElementById("input1"); + var input2 = document.getElementById("input"); + var form1 = document.getElementById("form1"); + form1.insertBefore(input2, input1); + + is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length"); + is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct"); + is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct"); + is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct"); + + is(form1.elements["input"][0].id, "input", "Form 1 element 1 id is correct"); + is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct"); + is(form1.elements["input"][2].id, "input3", "Form 1 element 3 id is correct"); +</script> +</body> +</html> diff --git a/dom/html/test/test_bug332893-6.html b/dom/html/test/test_bug332893-6.html new file mode 100644 index 000000000..c5e6fe376 --- /dev/null +++ b/dom/html/test/test_bug332893-6.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<form id="form1"> + <input id="input1" type="input" name="input" value="1"/> + <input id="input" type="input" name="input_other" value="2"/> + <input id="input3" type="input" name="input" value="3"/> +</form> +<script> + var input1 = document.getElementById("input1"); + var input2 = document.getElementById("input"); + var form1 = document.getElementById("form1"); + form1.insertBefore(input2, input1); + + is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length"); + is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct"); + is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct"); + + is(form1.elements["input"][0].id, "input", "Form 1 element 1 id is correct"); + is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct"); +</script> +</body> +</html> diff --git a/dom/html/test/test_bug332893-7.html b/dom/html/test/test_bug332893-7.html new file mode 100644 index 000000000..7939b34ae --- /dev/null +++ b/dom/html/test/test_bug332893-7.html @@ -0,0 +1,69 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<form id="form1"> + <input id="input1" type="input" name="input" value="1"/> + <input id="input2" type="input" name="input" value="2"/> + <input id="input3" type="input" name="input" value="3"/> + <input id="input4" type="input" name="input" value="4"/> + <input id="input5" type="input" name="input" value="5"/> + <input id="input6" type="input" name="input" value="6"/> + <input id="input7" type="input" name="input" value="7"/> + <input id="input8" type="input" name="input" value="8"/> + <input id="input9" type="input" name="input" value="9"/> + <input id="input10" type="input" name="input" value="10"/> + + + + +</form> +<script> + var input1 = document.getElementById("input1"); + var input2 = document.getElementById("input2"); + var input3 = document.getElementById("input3"); + var input4 = document.getElementById("input4"); + var input5 = document.getElementById("input5"); + var input6 = document.getElementById("input6"); + var input7 = document.getElementById("input7"); + var input8 = document.getElementById("input8"); + var input9 = document.getElementById("input9"); + var input10 = document.getElementById("input10"); + + + var form1 = document.getElementById("form1"); + + form1.insertBefore(input2, input1); + form1.insertBefore(input10, input6); + form1.insertBefore(input8, input4); + form1.insertBefore(input9, input2); + + is(form1.elements["input"].length, 10, "Form 1 'input' has the correct length"); + is(form1.elements["input"][0].value, "9", "Form 1 element 1 is correct"); + is(form1.elements["input"][1].value, "2", "Form 1 element 2 is correct"); + is(form1.elements["input"][2].value, "1", "Form 1 element 3 is correct"); + is(form1.elements["input"][3].value, "3", "Form 1 element 4 is correct"); + is(form1.elements["input"][4].value, "8", "Form 1 element 5 is correct"); + is(form1.elements["input"][5].value, "4", "Form 1 element 6 is correct"); + is(form1.elements["input"][6].value, "5", "Form 1 element 7 is correct"); + is(form1.elements["input"][7].value, "10", "Form 1 element 8 is correct"); + is(form1.elements["input"][8].value, "6", "Form 1 element 9 is correct"); + is(form1.elements["input"][9].value, "7", "Form 1 element 10 is correct"); + + is(form1.elements["input"][0].id, "input9", "Form 1 element 1 id is correct"); + is(form1.elements["input"][1].id, "input2", "Form 1 element 2 id is correct"); + is(form1.elements["input"][2].id, "input1", "Form 1 element 3 id is correct"); + is(form1.elements["input"][3].id, "input3", "Form 1 element 4 id is correct"); + is(form1.elements["input"][4].id, "input8", "Form 1 element 5 id is correct"); + is(form1.elements["input"][5].id, "input4", "Form 1 element 6 id is correct"); + is(form1.elements["input"][6].id, "input5", "Form 1 element 7 id is correct"); + is(form1.elements["input"][7].id, "input10", "Form 1 element 8 id is correct"); + is(form1.elements["input"][8].id, "input6", "Form 1 element 9 id is correct"); + is(form1.elements["input"][9].id, "input7", "Form 1 element 10 id is correct"); + +</script> +</body> +</html> diff --git a/dom/html/test/test_bug3348.html b/dom/html/test/test_bug3348.html new file mode 100644 index 000000000..50280e0a4 --- /dev/null +++ b/dom/html/test/test_bug3348.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=3348 +--> +<head> + <title>Test for Bug 3348</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=3348">Mozilla Bug 3348</a> +<p id="display"></p> +<div id="content" style="display: none"> + +<form id="form1"> +<input type="button" value="click here" onclick="buttonClick();"> +</form> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 3348 **/ + +var oForm = document.getElementById("form1"); +is(oForm.tagName, "FORM", "tagName of HTML element gives tag in upper case"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug340017.xhtml b/dom/html/test/test_bug340017.xhtml new file mode 100644 index 000000000..eabef837e --- /dev/null +++ b/dom/html/test/test_bug340017.xhtml @@ -0,0 +1,27 @@ +<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=340017
+-->
+<head>
+ <title>Test for Bug 340017</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=340017">Mozilla Bug 340017</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form id="frmfoo" name="foo" action="" />
+</div>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 340017 **/
+is(document.foo, document.getElementById("frmfoo"),
+ "The form with name 'foo' should be a document accessible property");
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug340800.html b/dom/html/test/test_bug340800.html new file mode 100644 index 000000000..68e6ed0e4 --- /dev/null +++ b/dom/html/test/test_bug340800.html @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=340800 +--> +<head> + <title>Test for Bug 340800</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=340800">Mozilla Bug 340800</a> +<p id="display"></p> +<div id="content" style="display: none"> + <h1>iframe text/plain as DOM test</h1> + + <div> + + <iframe name="iframe1" width="100%" height="200" + src="bug340800_iframe.txt"></iframe> + </div> + + <div> + <h2>textarea with iframe content</h2> + <textarea rows="10" cols="80" id="textarea1"></textarea> + </div> + + <div> + <h2>div with white-space: pre and iframe content</h2> + <div id="div1"></div> + </div> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 340800 **/ +function populateIframes () { + var iframe, iframeBody; + if ((iframe = window.frames.iframe1) && (iframeBody = iframe.document.body)) { + $('div1').innerHTML = iframeBody.innerHTML; + $('textarea1').value = iframeBody.innerHTML; + } + is($('div1').firstChild.tagName, "PRE", "innerHTML from txt iframe works with div"); + ok($('textarea1').value.indexOf("<pre>") > -1, "innerHTML from txt iframe works with textarea.value"); + SimpleTest.finish(); +} + +addLoadEvent(populateIframes); +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug347174.html b/dom/html/test/test_bug347174.html new file mode 100644 index 000000000..aadef4423 --- /dev/null +++ b/dom/html/test/test_bug347174.html @@ -0,0 +1,64 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=347174 +--> +<head> + <title>Test for Bug 347174</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 347174 **/ +// simple test of readyState during loading, DOMContentLoaded, and complete +// this test passes in IE7 +window.readyStateText = []; +window.readyStateText.push("script tag: " + document.readyState); +is(document.readyState, "loading", "document.readyState should be 'loading' when scripts runs initially"); + +function attachCustomEventListener(element, eventName, command) { + if (window.addEventListener && !window.opera) + element.addEventListener(eventName, command, true); + else if (window.attachEvent) + element.attachEvent("on" + eventName, command); +} + +function showMessage(msg) { + window.readyStateText.push(msg); + document.getElementById("display").innerHTML = readyStateText.join("<br>"); +} + +function load() { + is(document.readyState, "complete", "document.readyState should be 'complete' on load"); + showMessage("load: " + document.readyState); + SimpleTest.finish(); +} + +function readyStateChange() { + showMessage("readyStateChange: " + document.readyState); +} + +function DOMContentLoaded() { + is(document.readyState, "interactive", "document.readyState should be 'interactive' on DOMContentLoaded"); + showMessage("DOMContentLoaded: " + document.readyState); +} + +window.onload=load; + +attachCustomEventListener(document, "readystatechange", readyStateChange); +attachCustomEventListener(document, "DOMContentLoaded", DOMContentLoaded); + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug347174_write.html b/dom/html/test/test_bug347174_write.html new file mode 100644 index 000000000..1ff870de2 --- /dev/null +++ b/dom/html/test/test_bug347174_write.html @@ -0,0 +1,71 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=347174 +--> +<head> + <title>Test for Bug 347174</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a> +<p id="display"></p> + +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 347174 **/ +// simple test of readyState during loading, DOMContentLoaded, and complete +// this test passes in IE7 +window.readyStateText = []; +window.loaded = false; +function attachCustomEventListener(element, eventName, command) { + if (window.addEventListener && !window.opera) + element.addEventListener(eventName, command, true); + else if (window.attachEvent) + element.attachEvent("on" + eventName, command); +} + +function showMessage(msg) { + window.readyStateText.push(msg); + document.getElementById("display").innerHTML = readyStateText.join("<br>"); +} + +function frameLoad() { + var doc = $('iframe').contentWindow.document; + is(doc.readyState, "complete", "frame document.readyState should be 'complete' on load"); + showMessage("frame load: " + doc.readyState); + if (window.loaded) SimpleTest.finish(); +} + +function load() { + window.loaded = true; + + var imgsrc = "<img onload ='window.parent.imgLoad()' src='image.png?noCache=" + + (new Date().getTime()) + "'>\n"; + var doc = $('iframe').contentWindow.document; + doc.writeln(imgsrc); + doc.close(); + showMessage("frame after document.write: " + doc.readyState); + isnot(doc.readyState, "complete", "frame document.readyState should not be 'complete' after document.write"); +} + +function imgLoad() { + var doc = $('iframe').contentWindow.document; + showMessage("frame after imgLoad: " + doc.readyState); + is(doc.readyState, "interactive", "frame document.readyState should still be 'interactive' after img loads"); +} + +window.onload=load; + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +<iframe src="404doesnotexist" id="iframe" onload="frameLoad();"></iframe> +</body> +</html> diff --git a/dom/html/test/test_bug347174_xsl.html b/dom/html/test/test_bug347174_xsl.html new file mode 100644 index 000000000..4fdfd9122 --- /dev/null +++ b/dom/html/test/test_bug347174_xsl.html @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=347174 +--> +<head> + <title>Test for Bug 347174</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a> +<p id="display"></p> +<div id="content" style="display: none"> + <iframe src="347174transformable.xml" id="iframe"></iframe> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 347174 **/ +// Test of readyState of XML document transformed via XSLT to HTML +// this test passes in IE7 +window.readyStateText = []; + +function showMessage(msg) { + window.readyStateText.push(msg); + document.getElementById("display").innerHTML = readyStateText.join("<br>"); +} + +function frameScriptTag(readyState) { + isnot(readyState, "complete", "document.readyState should not be 'complete' when scripts run initially"); + showMessage("script tag: " + readyState); +} + +function frameLoad(readyState) { + is(readyState, "complete", "document.readyState should be 'complete' on load"); + showMessage("load: " + readyState); + SimpleTest.finish(); +} + +function frameReadyStateChange(readyState) { + showMessage("readyStateChange: " + readyState); +} + +function frameDOMContentLoaded(readyState) { + is(readyState, "interactive", "document.readyState should be 'interactive' on DOMContentLoaded"); + showMessage("DOMContentLoaded: " + readyState); +} + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug347174_xslp.html b/dom/html/test/test_bug347174_xslp.html new file mode 100644 index 000000000..ea4fc79b5 --- /dev/null +++ b/dom/html/test/test_bug347174_xslp.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=347174 +--> +<head> + <title>Test for Bug 347174</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> + +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 347174 **/ +// verifies that documents created with createDocument are born in "complete" state +// (so we don't accidentally leave them in "interactive" state) +window.readyStateText = []; + +function xmlLoaded(e) { + var xslDoc = document.implementation.createDocument("", "test", null); + xslDoc.async=false; + xslDoc.load("347174transform.xsl"); + + var processor = new XSLTProcessor(); + processor.importStylesheet(xslDoc); + + window.transformedDoc = processor.transformToDocument(xmlDoc); + + showMessage("loaded: " + xmlDoc.readyState); + is(xmlDoc.readyState, "complete", "XML document.readyState should be 'complete' after transform"); + SimpleTest.finish(); +} + +var xmlDoc = document.implementation.createDocument("", "test", null); +showMessage("createDocument: " + xmlDoc.readyState); +is(xmlDoc.readyState, "complete", "created document readyState should be 'complete' before being associated with a parser"); +xmlDoc.async=true; +xmlDoc.addEventListener("load", xmlLoaded, false); +xmlDoc.load("347174transformable.xml"); +showMessage("load called: " + xmlDoc.readyState); +isnot(xmlDoc.readyState, "complete", "created document readyState should not be 'complete' after load called"); + + +function showMessage(msg) { + window.readyStateText.push(msg); + $("display").innerHTML = readyStateText.join("<br>"); +} + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug353415-1.html b/dom/html/test/test_bug353415-1.html new file mode 100644 index 000000000..1f528ae6f --- /dev/null +++ b/dom/html/test/test_bug353415-1.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<iframe name="submit_frame"></iframe> +<form method="get" id="form1" target="submit_frame" action="../../../../../blah"> +<input type="text" name="field1" value="teststring"><br> +<input type="radio" name="field2" value="0" checked> 0 +<input type="radio" name="field3" value="1"> 1<br> +<input type="checkbox" name="field4" value="1" checked> 1 +<input type="checkbox" name="field5" value="2"> 2 +<input type="checkbox" name="field6" value="3" checked> 3 +<select name="field7"> +<option value="1">1</option> +<option value="2" selected>2</option> +<option value="3">3</option> +<option value="4">4</option> +</select> +<input name="field8" value="8"> +<input name="field9" value="9"> +<input type="image" name="field10"> +<label name="field11"> +<input name="field12"> +<input type="button" name="field13" value="button"> +</form> +<script> + SimpleTest.waitForExplicitFinish(); + + addLoadEvent(function() { + document.getElementsByName('submit_frame')[0].onload = function() { + is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=", "Submit string was correct."); + SimpleTest.finish(); + }; + + document.forms[0].submit(); + }); +</script> +</body> +</html> diff --git a/dom/html/test/test_bug353415-2.html b/dom/html/test/test_bug353415-2.html new file mode 100644 index 000000000..9e82e9df8 --- /dev/null +++ b/dom/html/test/test_bug353415-2.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<iframe name="submit_frame"></iframe> +<form method="get" id="form1" target="submit_frame" action="../../../../../blah"> +<table> +<tr><td> +<input type="text" name="field1" value="teststring"><br> +<input type="radio" name="field2" value="0" checked> 0 +<input type="radio" name="field3" value="1"> 1<br> +<input type="checkbox" name="field4" value="1" checked> 1 +<input type="checkbox" name="field5" value="2"> 2 +<input type="checkbox" name="field6" value="3" checked> 3 +<select name="field7"> +<option value="1">1</option> +<option value="2" selected>2</option> +<option value="3">3</option> +<option value="4">4</option> +</select> +<input name="field8" value="8"> +<input name="field9" value="9"> +<input type="image" name="field10"> +<label name="field11"></label> +<input name="field12"> +<input type="button" name="field13" value="button"> +<input type="hidden" name="field14" value="14"> +</td> +<input type="text" name="field1-2" value="teststring"><br> +<input type="radio" name="field2-2" value="0" checked> 0 +<input type="radio" name="field3-2" value="1"> 1<br> +<input type="checkbox" name="field4-2" value="1" checked> 1 +<input type="checkbox" name="field5-2" value="2"> 2 +<input type="checkbox" name="field6-2" value="3" checked> 3 +<select name="field7-2"> +<option value="1">1</option> +<option value="2" selected>2</option> +<option value="3">3</option> +<option value="4">4</option> +</select> +<input name="field8-2" value="8"> +<input name="field9-2" value="9"> +<input type="image" name="field10-2"> +<label name="field11-2"></label> +<input name="field12-2"> +<input type="button" name="field13-2" value="button"> +<input type="hidden" name="field14-2" value="14"> +</tr> +</table> +</form> +<script> + SimpleTest.waitForExplicitFinish(); + + addLoadEvent(function() { + document.getElementsByName('submit_frame')[0].onload = function() { + is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14&field14-2=14", "Submit string was correct."); + SimpleTest.finish(); + }; + + document.forms[0].submit(); + }); +</script> +</body> +</html> diff --git a/dom/html/test/test_bug359657.html b/dom/html/test/test_bug359657.html new file mode 100644 index 000000000..f6fcb716e --- /dev/null +++ b/dom/html/test/test_bug359657.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=359657 +--> +<head> + <title>Test for Bug 359657</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=359657">Mozilla Bug 359657</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); + +/** Test for Bug 359657 **/ +function runTest() { + var span = document.createElement("span"); + $("test").insertBefore(span, $("test").firstChild); + ok(true, "Reachability", "We should get here without crashing"); + is($("test").firstChild, span, "First child is correct"); + SimpleTest.finish(); +} +</script> +<div> + <iframe src=""></iframe> + <!-- Important: This test needs to run async at this point. The actual test + is not crashing while running this test! --> + <script type="text/javascript" src="data:text/javascript,runTest()"></script> +</div> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug369370.html b/dom/html/test/test_bug369370.html new file mode 100644 index 000000000..6b27b3849 --- /dev/null +++ b/dom/html/test/test_bug369370.html @@ -0,0 +1,151 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=369370 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>Test for Bug 369370</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> + <script type="text/javascript"> + /* + * Test strategy: + */ + function makeClickFor(x, y) { + var event = kidDoc.createEvent("mouseevent"); + event.initMouseEvent("click", + true, true, kidWin, 1, // bubbles, cancelable, view, single-click + x, y, x, y, // screen X/Y, client X/Y + false, false, false, false, // no key modifiers + 0, null); // left click, not relatedTarget + return event; + } + + function childLoaded() { + kidDoc = kidWin.document; + ok(true, "Child window loaded"); + + var elements = kidDoc.getElementsByTagName("img"); + is(elements.length, 1, "looking for imagedoc img"); + var img = elements[0]; + + // Need to use innerWidth/innerHeight of the window + // since the containing image is absolutely positioned, + // causing clientHeight to be zero. + is(kidWin.innerWidth, 400, "Checking doc width"); + is(kidWin.innerHeight, 300, "Checking doc height"); + + // Image just loaded and is scaled to window size. + is(img.width, 400, "image width"); + is(img.height, 300, "image height"); + is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft"); + is(kidDoc.body.scrollTop, 0, "Checking scrollTop"); + + // ========== test 1 ========== + // Click in the upper left to zoom in + var event = makeClickFor(25,25); + img.dispatchEvent(event); + ok(true, "----- click 1 -----"); + + is(img.width, 800, "image width"); + is(img.height, 600, "image height"); + is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft"); + is(kidDoc.body.scrollTop, 0, "Checking scrollTop"); + + // ========== test 2 ========== + // Click there again to zoom out + event = makeClickFor(25,25); + img.dispatchEvent(event); + ok(true, "----- click 2 -----"); + + is(img.width, 400, "image width"); + is(img.height, 300, "image height"); + is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft"); + is(kidDoc.body.scrollTop, 0, "Checking scrollTop"); + + // ========== test 3 ========== + // Click in the lower right to zoom in + event = makeClickFor(350, 250); + img.dispatchEvent(event); + ok(true, "----- click 3 -----"); + + is(img.width, 800, "image width"); + is(img.height, 600, "image height"); + is(kidDoc.body.scrollLeft, 400, "Checking scrollLeft"); + is(kidDoc.body.scrollTop, 300, "Checking scrollTop"); + + // ========== test 4 ========== + // Click there again to zoom out + event = makeClickFor(350, 250); + img.dispatchEvent(event); + ok(true, "----- click 4 -----"); + + is(img.width, 400, "image width"); + is(img.height, 300, "image height"); + is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft"); + is(kidDoc.body.scrollTop, 0, "Checking scrollTop"); + + // ========== test 5 ========== + // Click in the upper left to zoom in again + event = makeClickFor(25, 25); + img.dispatchEvent(event); + ok(true, "----- click 5 -----"); + is(img.width, 800, "image width"); + is(img.height, 600, "image height"); + is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft"); + is(kidDoc.body.scrollTop, 0, "Checking scrollTop"); + is(img.getBoundingClientRect().top, 0, "Image is in view vertically"); + + // ========== test 6 ========== + // Now try resizing the window so the image fits vertically. + function test6() { + kidWin.addEventListener("resize", function resizeListener() { + kidWin.removeEventListener("resize", resizeListener); + // Give the image document time to respond + SimpleTest.executeSoon(function() { + is(img.height, 600, "image height"); + is(img.getBoundingClientRect().top, 25, "Image is vertically centered"); + test7(); + }); + }); + + var decorationSize = kidWin.outerHeight - kidWin.innerHeight; + kidWin.resizeTo(400, 600 + 50 + decorationSize); + } + + // ========== test 7 ========== + // Now try resizing the window so the image no longer fits vertically. + function test7() { + kidWin.addEventListener("resize", function resizeListener() { + kidWin.removeEventListener("resize", resizeListener); + // Give the image document time to respond + SimpleTest.executeSoon(function() { + is(img.height, 600, "image height"); + is(img.getBoundingClientRect().top, 0, "Image is at top again"); + kidWin.close(); + SimpleTest.finish(); + }); + }); + + var decorationSize = kidWin.outerHeight - kidWin.innerHeight; + kidWin.resizeTo(400, 300 + decorationSize); + } + + test6(); + } + var kidWin; + var kidDoc; + + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({"set":[["browser.enable_automatic_image_resizing", true]]}, function() { + kidWin = window.open("bug369370-popup.png", "bug369370", "width=400,height=300,scrollbars=no"); + // will init onload + ok(kidWin, "opened child window"); + kidWin.onload = childLoaded; + }); + </script> +</body> +</html> diff --git a/dom/html/test/test_bug371375.html b/dom/html/test/test_bug371375.html new file mode 100644 index 000000000..e0e48656c --- /dev/null +++ b/dom/html/test/test_bug371375.html @@ -0,0 +1,58 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=371375 +--> +<head> + <title>Test for Bug 371375</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=371375">Mozilla Bug 371375</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + + /** Test for Bug 371375 **/ + var load1Called = false; + var error1Called = false; + var s = document.createElement('script'); + s.type = 'text/javascript'; + s.onload = function() { load1Called = true; }; + s.onerror = function(event) { error1Called = true; event.stopPropagation(); }; + s.src = 'about:cache-entry?client=image&sb=0&key=http://www.google.com'; + document.body.appendChild(s); + + var load2Called = false; + var error2Called = false; + var s2 = document.createElement('script'); + s2.type = 'text/javascript'; + s2.onload = function() { load2Called = true; }; + s2.onerror = function(event) { error2Called = true; event.stopPropagation(); }; + s2.src = 'data:text/plain, var x = 1;' + document.body.appendChild(s2); + + SimpleTest.waitForExplicitFinish(); + addLoadEvent(function() { + is(load1Called, false, "Load handler should not be called"); + is(error1Called, true, "Error handler should be called"); + is(load2Called, true, "Load handler for valid script should be called"); + is(error2Called, false, + "Error handler for valid script should not be called"); + SimpleTest.finish(); + }); +</script> +</body> +</html> + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug372098.html b/dom/html/test/test_bug372098.html new file mode 100644 index 000000000..1f00868a7 --- /dev/null +++ b/dom/html/test/test_bug372098.html @@ -0,0 +1,75 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=372098 +--> +<head> + <title>Test for Bug 372098</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <base target="bug372098"></base> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=372098">Mozilla Bug 372098</a> + <p id="display"></p> + <div id="content" style="display:none;"> + <iframe name="bug372098"></iframe> + <a id="a" href="bug372098-link-target.html?a" target="">link</a> + <link id="link" href="bug372098-link-target.html?link" target=""/> + <map> + <area id="area" shape="default" href="bug372098-link-target.html?area" target=""/> + </map> + </div> + <pre id="test"> + <script class="testbody" type="text/javascript"> + +var a_passed = false; +var link_passed = false; +var area_passed = false; + +/* Start the test */ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(handle_load); + +function handle_load() +{ + sendMouseEvent({type:'click'}, 'a'); +} + +/* Finish the test */ + +function finish_test() +{ + ok(a_passed, "The 'a' element used the correct target."); + ok(link_passed, "The 'link' element used the correct target."); + ok(area_passed, "The 'area' element used the correct target."); + SimpleTest.finish(); +} + +/* Callback function used by the linked document */ + +function callback(tag) +{ + switch (tag) { + case 'a': + a_passed = true; + sendMouseEvent({type:'click'}, 'link'); + return; + case 'link': + link_passed = true; + sendMouseEvent({type:'click'}, 'area'); + return; + case 'area': + area_passed = true; + finish_test(); + return; + } + throw new Error("Eh??? We only test the 'a', 'link' and 'area' elements."); +} + + </script> + </pre> + +</body> +</html> diff --git a/dom/html/test/test_bug373589.html b/dom/html/test/test_bug373589.html new file mode 100644 index 000000000..eba0d9284 --- /dev/null +++ b/dom/html/test/test_bug373589.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=373589
+-->
+<head>
+ <title>Test for Bug 373589</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=373589">Mozilla Bug 373589</a>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 373589 **/
+ var docElem = document.documentElement;
+ var body = document.body;
+ var numChildren = docElem.childNodes.length;
+ docElem.removeChild(body);
+ ok(numChildren > docElem.childNodes.length, "body was removed");
+ body.link;
+ ok(true, "didn't crash");
+ docElem.appendChild(body);
+ is(numChildren, docElem.childNodes.length, "body re-added");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug375003-1.html b/dom/html/test/test_bug375003-1.html new file mode 100644 index 000000000..94f5aa7a8 --- /dev/null +++ b/dom/html/test/test_bug375003-1.html @@ -0,0 +1,156 @@ +<!DOCTYPE HTML> +<html id="html"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=375003 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>Test 1 for bug 375003</title> + + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + + <style type="text/css"> + + html,body { + color:black; background-color:white; font-size:16px; padding:0; margin:0; + } + + .s { display:block; width:20px; height:20px; background-color:lime; } + table { background:pink; } + #td5,#td6 { border:7px solid blue;} + </style> + +<script> +var x = [ 'Left','Top','Width','Height' ]; +function test(id,s,expected) { + var el = document.getElementById(id); + for(var i = 0; i < x.length; ++i) { + var actual = eval('el.'+s+x[i]); + if (expected[i] != -1 && s+x[i]!='scrollHeight') + is(actual, expected[i], id+"."+s+x[i]); + } +} +function t3(id,c,o,s,pid) { + test(id,'client',c); + test(id,'offset',o); + test(id,'scroll',s); + var p = document.getElementById(id).offsetParent; + is(p.id, pid, id+".offsetParent"); +} + +function run_test() { + t3('span1',[0,0,20,20],[12,12,20,20],[0,0,20,20],'td1'); + t3('td1' ,[1,1,69,44],[16,16,71,46],[0,0,69,46],'table1'); + t3('tr1' ,[0,0,71,46],[16,16,71,46],[0,0,71,44],'table1'); + t3('span2',[10,0,20,20],[27,12,30,20],[0,0,20,20],'td2'); + t3('table1',[9,9,85,113],[10,10,103,131],[0,0,85,50],'body'); + t3('div1',[10,10,-1,131],[0,0,-1,151],[0,0,-1,85],'body'); + + t3('span2b',[10,0,20,20],[25,-1,30,20],[0,0,20,20],'body'); + // XXX not sure how to make reliable cross-platform tests for replaced-inline, inline + // t3('span2c',[10,2,18,2],[25,-1,30,6],[0,0,30,20],'body'); + // t3('span2d',[0,0,0,0],[25,-1,10,19],[0,0,10,20],'body'); + + t3('span3' ,[0,0,20,20],[15,0,20,20],[0,0,20,20],'td3'); + t3('td3' ,[0,0,35,20],[0,0,35,20],[0,0,35,20],'table3'); + t3('tr3' ,[0,0,35,20],[0,0,35,20],[0,0,35,22],'table3'); + t3('span4' ,[0,0,20,20],[0,0,20,20],[0,0,20,20],'td4'); + t3('table3',[0,0,35,40],[0,0,35,40],[0,0,35,50],'div3'); + t3('div3',[10,10,-1,40],[0,151,-1,60],[0,0,-1,70],'body'); + + t3('span5' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td5'); + t3('td5' ,[7,7,22,22],[2,2,36,36],[0,0,22,36],'table5'); + t3('tr5' ,[0,0,36,36],[2,2,36,36],[0,0,36,22],'table5'); + t3('span6' ,[0,0,20,20],[20,58,20,20],[0,0,20,20],'div5'); + t3('table5',[0,0,40,78],[0,0,40,78],[0,0,40,78],'div5'); + t3('div5',[10,10,-1,78],[0,211,-1,98],[0,0,-1,70],'body'); + + t3('span7' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td7'); + t3('td7' ,[1,1,37,22],[9,9,39,24],[0,0,37,22],'table7'); + t3('tr7' ,[0,0,39,24],[9,9,39,24],[0,0,39,22],'table7'); + t3('span8' ,[0,0,20,20],[26,37,20,20],[0,0,20,20],'table7'); + t3('table7',[7,7,43,54],[10,319,57,68],[0,0,43,50],'body'); + t3('div7',[10,10,-1,68],[0,309,-1,88],[0,0,-1,70],'body'); + + t3('span9' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td9'); + t3('td9' ,[1,1,22,22],[15,15,24,24],[0,0,22,24],'table9'); + t3('tr9' ,[0,0,24,24],[15,15,24,24],[0,0,24,22],'table9'); + t3('span10' ,[0,0,20,20],[17,43,20,20],[0,0,20,20],'table9'); + t3('table9',[13,13,28,34],[10,407,54,60],[0,0,28,50],'body'); + t3('div9',[10,10,-1,0],[0,397,-1,20],[0,0,-1,70],'body'); + + t3('span11' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td11'); + t3('td11' ,[0,0,22,22],[2,2,22,22],[0,0,22,22],'table11'); + t3('tr11' ,[0,0,22,22],[2,2,22,22],[0,0,22,22],'table11'); + t3('span12' ,[0,0,20,20],[28,454,20,20],[0,0,20,20],'body'); + t3('table11',[0,0,26,30],[10,427,26,30],[0,0,26,50],'body'); + t3('div11',[10,10,-1,30],[0,417,-1,50],[0,0,-1,70],'body'); +} +</script> +</head> +<body id="body"> + +<div id="content"> +<div id="div1" style="border:10px solid black"> +<table id="table1" cellspacing="7" cellpadding="12" border="9"> + <tbody id="tbody1"><tr id="tr1"><td id="td1"><div class="s" id="span1"></div></td></tr></tbody> + <tbody id="tbody2"><tr id="tr2"><td id="td2"><div class="s" id="span2" style="margin-left:15px; border-left:10px solid blue;"></div></td></tr></tbody> +</table> +</div> + +<div id="div3" style="border:10px solid black; position:relative"> +<table id="table3" cellpadding="0" cellspacing="0" border="0"> + <tbody id="tbody3"><tr id="tr3"><td id="td3"><div class="s" id="span3" style="margin-left:15px"></div></td></tr></tbody> + <tbody id="tbody4"><tr id="tr4"><td id="td4"><div class="s" id="span4"></div></td></tr></tbody> +</table> +</div> + +<div id="div5" style="border:10px solid black; position:relative"> +<table id="table5"> + <tbody id="tbody5"><tr id="tr5"><td id="td5"><div class="s" id="span5"></div></td></tr></tbody> + <tbody id="tbody6"><tr id="tr6"><td id="td6"><div class="s" id="span6" style="left:10px; top:10px; position:relative"></div></td></tr></tbody> +</table> +</div> + +<div id="div7" style="border:10px solid black;"> +<table id="table7" style="position:relative" border=7> + <tbody id="tbody7"><tr id="tr7"><td id="td7"><div class="s" id="span7"></div></td></tr></tbody> + <tbody id="tbody8"><tr id="tr8"><td id="td8"><div class="s" id="span8" style="position:relative; margin-left:15px"></div></td></tr></tbody> +</table> +</div> + +<div id="div9" style="border:10px solid black;"> +<table id="table9" style="position:absolute" border="13"> + <tbody id="tbody9"><tr id="tr9"><td id="td9"><div class="s" id="span9"></div></td></tr></tbody> + <tbody id="tbody10"><tr id="tr10"><td id="td10"><div class="s" id="span10" style="position:absolute"></div></td></tr></tbody> +</table> +</div> + +<div id="div11" style="border:10px solid black; "> +<table id="table11"> + <tbody id="tbody11"><tr id="tr11"><td id="td11"><div class="s" id="span11"></div></td></tr></tbody> + <tbody id="tbody12"><tr id="tr12"><td id="td12"><div class="s" id="span12" style="position:absolute;margin-left:15px"></div></td></tr></tbody> +</table> +</div> + +<div style="border:10px solid black"> +<div class="s" id="span2b" style="margin-left:15px; border-left:10px solid blue;"></div></div> + +<div style="border:10px solid black"> +<button id="span2c" style="margin-left:15px; border-left:10px solid blue;"></button></div> + +<div style="border:10px solid black"> +<span id="span2d" style="margin-left:15px; border-left:10px solid blue;"></span></div> +</div> + +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=375003">Mozilla Bug 375003</a> + +<pre id="test"> +<script class="testbody" type="text/javascript"> +run_test(); +</script> +</pre> + +</body> +</html> diff --git a/dom/html/test/test_bug375003-2.html b/dom/html/test/test_bug375003-2.html new file mode 100644 index 000000000..f22397a61 --- /dev/null +++ b/dom/html/test/test_bug375003-2.html @@ -0,0 +1,109 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=375003 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>Test 2 for bug 375003</title> + + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + + <style type="text/css"> + + html { + padding:0; margin:0; + } + body { + color:black; background-color:white; font-size:12px; padding:10px; margin:0; + } + + #div1,#abs1,#table1 { + border: 20px solid lime; + padding: 30px; + width: 100px; + height: 60px; + overflow:scroll; + } + #abs1,#table2parent { + position:absolute; + left:500px; + } + #table3parent { + position:fixed; + left:300px; + top:100px; + } + .content { + display:block; + width:200px; + height:200px; + background:yellow; + border: 0px dotted black; + } +</style> + + +<script type="text/javascript"> +var x = [ 'Left','Top','Width','Height' ]; +function test(id,s,expected) { + var el = document.getElementById(id); + for(var i = 0; i < x.length; ++i) { + var actual = eval('el.'+s+x[i]); + if (expected[i] != -1 && s+x[i]!='scrollHeight') + is(actual, expected[i], id+"."+s+x[i]); + } +} +function t3(id,c,o,s,pid) { + test(id,'client',c); + test(id,'offset',o); + test(id,'scroll',s); + var p = document.getElementById(id).offsetParent; + is(p.id, pid, id+".offsetParent"); +} + +function run_test() { + // XXX how test clientWidth/clientHeight (the -1 below) in cross-platform manner + // without hard-coding the scrollbar width? + t3('div1',[20,20,-1,-1],[10,10,200,160],[0,0,230,20],'body'); + t3('abs1',[20,20,-1,-1],[500,170,200,160],[0,0,230,20],'body'); + t3('table1',[20,20,266,266],[10,170,306,306],[0,0,266,20],'body'); + t3('table2',[0,0,206,206],[0,0,206,206],[0,0,206,20],'table2parent'); + t3('table3',[10,10,208,208],[0,0,228,228],[0,0,208,228],'table3parent'); + t3('table3parent',[0,0,228,228],[300,100,228,228],[0,0,228,228],'body'); +} +</script> + +</head> +<body id="body"> +<div id="content"> +<div id="div1parent"> + <div id="div1"><span class="content">DIV</span></div> +</div> + +<div id="abs1parent"> + <div id="abs1"><span class="content">abs.pos.DIV</span></div> +</div> + +<div id="table1parent"> + <table id="table1"><tbody><tr><td id="td1"><span class="content">TABLE</span></td></tr></tbody></table> +</div> + +<div id="table2parent"> + <table id="table2"><tbody><tr><td id="td2"><span class="content">TABLE in abs</span></td></tr></tbody></table> +</div> + +<div id="table3parent"> + <table id="table3" border="10"><tbody><tr><td id="td3"><span class="content">TABLE in fixed</span></td></tr></tbody></table> +</div> +</div> + +<pre id="test"> +<script class="testbody" type="text/javascript"> +run_test(); +</script> +</pre> + +</body> +</html> diff --git a/dom/html/test/test_bug377624.html b/dom/html/test/test_bug377624.html new file mode 100644 index 000000000..fa0a137ee --- /dev/null +++ b/dom/html/test/test_bug377624.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=377624 +--> +<head> + <title>Test for Bug 377624</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 377624</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 377624 **/ + +var input = document.createElement('input'); +ok("accept" in input, "'accept' is a valid input property"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug380383.html b/dom/html/test/test_bug380383.html new file mode 100644 index 000000000..c5d9823ae --- /dev/null +++ b/dom/html/test/test_bug380383.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=380383 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Test for Bug 380383</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=380383">Mozilla Bug 380383</a> +<p id="display"> + <iframe id="f1" name="f1"></iframe> + <iframe id="f2" name="f2"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + /** Test for Bug 380383 **/ + is($("f1").contentDocument.characterSet, "UTF-8", + "Unexpected charset for f1"); + + function runTest() { + is($("f2").contentDocument.characterSet, "UTF-8", + "Unexpected charset for f2"); + } + + addLoadEvent(runTest); + addLoadEvent(SimpleTest.finish); + SimpleTest.waitForExplicitFinish(); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug383383.html b/dom/html/test/test_bug383383.html new file mode 100644 index 000000000..922dc5b4f --- /dev/null +++ b/dom/html/test/test_bug383383.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=383383 +--> +<head> + <title>Test for Bug 383383</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=383383">Mozilla Bug 383383</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript" for=" window " event=" onload() "> + +var foo = "bar"; + +</script> + +<script class="testbody" type="text/javascript" for="object" event="handler"> + +// This script should fail to run +foo = "baz"; + +isnot(foo, "baz", "test failed"); + +</script> + +<script class="testbody" type="text/javascript"> + +ok(foo == "bar", "test passed"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug383383_2.xhtml b/dom/html/test/test_bug383383_2.xhtml new file mode 100644 index 000000000..4dccd381c --- /dev/null +++ b/dom/html/test/test_bug383383_2.xhtml @@ -0,0 +1,20 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Test for bug 383383</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> + <script> + SimpleTest.waitForExplicitFinish() + </script> + <script for="window" event="bar"> + // This script should not run, but should not cause a parse error either. + ok(false, "Script was unexpectedly run") + </script> + <script> + ok(true, "Script was run as it should") + SimpleTest.finish() + </script> +</body> +</html> diff --git a/dom/html/test/test_bug384419.html b/dom/html/test/test_bug384419.html new file mode 100644 index 000000000..c66a4c3ad --- /dev/null +++ b/dom/html/test/test_bug384419.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=384419 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>Test for bug 384419</title> + + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + + <style type="text/css"> + html,body { + color:black; background-color:white; font-size:16px; padding:0; margin:0; + } + body { margin: 10px; } + table { border:15px solid black; margin-left:100px; } +</style> + + +<script type="text/javascript"> +function t3(id,expected,pid) { + var el = document.getElementById(id); + var actual = el.offsetLeft; + is(actual, expected, id+".offsetLeft"); + + var p = document.getElementById(id).offsetParent; + is(p.id, pid, id+".offsetParent"); +} + +function run_test() { + t3('rel384419',135,'body'); + t3('abs384419',135,'body'); + t3('fix384419',135,'body'); +} +</script> + +</head> +<body id="body"> +<!-- It's important for the test that the tables below are directly inside body --> +<table cellpadding="7" cellspacing="3"><tr><td width="100"><div id="rel384419" style="position:relative;border:1px solid blue">X</div> relative</table> +<table cellpadding="7" cellspacing="3"><tr><td width="100"><div id="abs384419" style="position:absolute;border:1px solid blue">X</div> absolute</table> +<table cellpadding="7" cellspacing="3"><tr><td width="100"><div id="fix384419" style="position:fixed;border:1px solid blue">X</div> fixed</table> + + +<pre id="test"> +<script class="testbody" type="text/javascript"> +run_test(); +</script> +</pre> + +<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=384419">bug 384419</a> + +</body> +</html> diff --git a/dom/html/test/test_bug386496.html b/dom/html/test/test_bug386496.html new file mode 100644 index 000000000..2d4f14632 --- /dev/null +++ b/dom/html/test/test_bug386496.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=386496 +--> +<head> + <title>Test for Bug 386496</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <SCRIPT Type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386496">Mozilla Bug 386496</a> +<p id="display"></p> +<div id="content"> + <iframe style='display: block;' id="testIframe" + src="data:text/html,<div><a id='a' href='http://a.invalid/'>Link</a></div>"> + </iframe> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 386496 **/ + +var frame = document.getElementById("testIframe"); + +function testDesignMode() { + var unloadRequested = false; + + frame.contentDocument.designMode = "on"; + + frame.contentWindow.addEventListener("beforeunload", function() { + unloadRequested = true; + }, false); + + synthesizeMouseAtCenter(frame.contentDocument.getElementById("a"), {}, + frame.contentWindow); + + // The click has been sent. If 'beforeunload' event has been caught when we go + // back from the event loop that means the link has been activated. + setTimeout(function() { + ok(!unloadRequested, "The link should not be activated in designMode"); + SimpleTest.finish(); + }, 0); +} + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(testDesignMode); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug386728.html b/dom/html/test/test_bug386728.html new file mode 100644 index 000000000..5a10b31a8 --- /dev/null +++ b/dom/html/test/test_bug386728.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=386728 +--> +<head> + <title>Test for Bug 386728</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386728">Mozilla Bug 386728</a> +<p id="display"></p> +<div id="content"> + <div id="frameContent"> + <div id="edit">This text is editable</div> + <button id="button_on" onclick="document.getElementById('edit').setAttribute('contenteditable', 'true')"></button> + </div> + <iframe id="testIframe"></iframe> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 386728 **/ + +var frame = document.getElementById("testIframe"); + +function testContentEditable() { + frame.style.display = 'block'; + var frameContent = frame.contentDocument.adoptNode(document.getElementById("frameContent")); + frame.contentDocument.body.appendChild(frameContent); + frame.contentDocument.getElementById("edit").contentEditable = "true"; + frame.contentDocument.getElementById("edit").contentEditable = "false"; + frame.contentDocument.getElementById("button_on").click(); + is(frame.contentDocument.getElementById("edit").contentEditable, "true"); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(testContentEditable); +addLoadEvent(SimpleTest.finish); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug386996.html b/dom/html/test/test_bug386996.html new file mode 100644 index 000000000..4f667281f --- /dev/null +++ b/dom/html/test/test_bug386996.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=386996 +--> +<head> + <title>Test for Bug 386996</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386996">Mozilla Bug 386996</a> +<p id="display"></p> +<div id="content"> + <input id="input1"><input disabled><input id="input2"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 386996 **/ + +var frame = document.getElementById("testIframe"); + +function testContentEditable() { + var focusedElement; + document.getElementById("input1").onfocus = function() { focusedElement = this }; + document.getElementById("input2").onfocus = function() { focusedElement = this }; + + document.getElementById("input1").focus(); + synthesizeKey("VK_TAB", {}); + + is(focusedElement.id, "input2"); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(testContentEditable); +addLoadEvent(SimpleTest.finish); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug388558.html b/dom/html/test/test_bug388558.html new file mode 100644 index 000000000..8e5258777 --- /dev/null +++ b/dom/html/test/test_bug388558.html @@ -0,0 +1,76 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=388558 +--> +<head> + <title>Test for Bug 388558</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388558">Mozilla Bug 388558</a> +<p id="display"></p> +<div id="content"> + <input type="text" id="input" onchange="++inputChange;"> + <textarea id="textarea" onchange="++textareaChange;"></textarea> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 388558 **/ +var inputChange = 0; +var textareaChange = 0; + +function testUserInput() { + var input = document.getElementById("input"); + var textarea = SpecialPowers.wrap(document.getElementById("textarea")); + + input.focus(); + SpecialPowers.wrap(input).setUserInput("foo"); + input.blur(); + is(inputChange, 1, "Input element should have got one change event."); + + input.focus(); + input.value = "bar"; + input.blur(); + is(inputChange, 1, + "Change event dispatched when setting the value of the input element"); + + input.value = ""; + is(inputChange, 1, + "Change event dispatched when setting the value of the input element (2)."); + + SpecialPowers.wrap(input).setUserInput("foo"); + is(inputChange, 2, + "Change event dispatched when input element doesn't have focus."); + + textarea.focus(); + textarea.setUserInput("foo"); + textarea.blur(); + is(textareaChange, 1, "Textarea element should have got one change event."); + + textarea.focus(); + textarea.value = "bar"; + textarea.blur(); + is(textareaChange, 1, + "Change event dispatched when setting the value of the textarea element."); + + textarea.value = ""; + is(textareaChange, 1, + "Change event dispatched when setting the value of the textarea element (2)."); + + textarea.setUserInput("foo"); + is(textareaChange, 1, + "Change event dispatched when textarea element doesn't have focus."); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(testUserInput); +addLoadEvent(SimpleTest.finish); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug388746.html b/dom/html/test/test_bug388746.html new file mode 100644 index 000000000..8f5e0997b --- /dev/null +++ b/dom/html/test/test_bug388746.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=388746 +--> +<head> + <title>Test for Bug 388746</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388746">Mozilla Bug 388746</a> +<p id="display"></p> +<div id="content"> + <input> + <textarea></textarea> + <select> + <option>option1</option> + <optgroup label="optgroup"> + <option>option2</option> + </optgroup> + </select> + <button>Button</button> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 388746 **/ + +var previousEventTarget = ""; + +function handler(evt) { + if (evt.eventPhase == 2) { + previousEventTarget = evt.target.localName.toLowerCase(); + } +} + +function testElementType(type) { + var el = document.getElementsByTagName(type)[0]; + el.addEventListener("DOMAttrModified", handler, true); + el.setAttribute("foo", "bar"); + ok(previousEventTarget == type, + type + " element should have got DOMAttrModified event."); +} + +function test() { + testElementType("input"); + testElementType("textarea"); + testElementType("select"); + testElementType("option"); + testElementType("optgroup"); + testElementType("button"); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); +addLoadEvent(SimpleTest.finish); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug388794.html b/dom/html/test/test_bug388794.html new file mode 100644 index 000000000..0f3cfdbd2 --- /dev/null +++ b/dom/html/test/test_bug388794.html @@ -0,0 +1,104 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=388794 +--> +<head> + <title>Test for Bug 388794</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input { padding: 0; margin: 0; border: none; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388794">Mozilla Bug 388794</a> +<p id="display"> + <form action="data:text/html," target="test1" method="GET"> + <input id="test1image" type="image" name="testImage"> + </form> + <form action="data:text/html," target="test2" method="GET"> + <input id="test2image" type="image"> + </form> + <form action="data:text/html," target="test3" method="GET"> + <input id="test3image" type="image" src="nnc_lockup.gif" name="testImage"> + </form> + <form action="data:text/html," target="test4" method="GET"> + <input id="test4image" type="image" src="nnc_lockup.gif"> + </form> + <form action="data:text/html," target="test5" method="GET"> + <input id="test5image" type="image" src="nnc_lockup.gif" name="testImage"> + </form> + <form action="data:text/html," target="test6" method="GET"> + <input id="test6image" type="image" src="nnc_lockup.gif"> + </form> + <iframe name="test1" id="test1"></iframe> + <iframe name="test2" id="test2"></iframe> + <iframe name="test3" id="test3"></iframe> + <iframe name="test4" id="test4"></iframe> + <iframe name="test5" id="test5"></iframe> + <iframe name="test6" id="test6"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 388794 **/ +SimpleTest.waitForExplicitFinish(); + +var pendingLoads = 0; +/* Use regex due to rounding error in Fennec with C++APZ enabled */ +var hrefs = { + test1: /data:text\/html,\?testImage\.x=0&testImage\.y=0/, + test2: /data:text\/html,\?x=0&y=0/, + test3: /data:text\/html,\?testImage\.x=0&testImage\.y=0/, + test4: /data:text\/html,\?x=0&y=0/, + test5: /data:text\/html,\?testImage\.x=[4-6]&testImage\.y=[4-6]/, + test6: /data:text\/html,\?x=[4-6]&y=[4-6]/, +}; + +function submitForm(idNum) { + $("test"+idNum).setAttribute("onload", "frameLoaded(this)"); + $("test" + idNum + "image").focus(); + sendKey("return"); +} + +function submitFormMouse(idNum) { + $("test"+idNum).setAttribute("onload", "frameLoaded(this)"); + // Use 4.99 instead of 5 to guard against the possibility that the + // image's 'top' is exactly N + 0.5 pixels from the root. In that case + // we'd round up the widget mouse coordinate to N + 6, which relative + // to the image would be 5.5, which would get rounded up to 6 when + // submitting the form. Instead we round the widget mouse coordinate to + // N + 5, which relative to the image would be 4.5 which gets rounded up + // to 5. + synthesizeMouse($("test" + idNum + "image"), 4.99, 4.99, {}); +} + +addLoadEvent(function() { + // Need the timeout so painting has a chance to be unsuppressed. + setTimeout(function() { + submitForm(++pendingLoads); + submitForm(++pendingLoads); + submitForm(++pendingLoads); + submitForm(++pendingLoads); + submitFormMouse(++pendingLoads); + submitFormMouse(++pendingLoads); + }, 0); +}); + +function frameLoaded(frame) { + ok(hrefs[frame.name].test(frame.contentWindow.location.href), + "Unexpected href for frame " + frame.name, "expected to match: " + hrefs[frame.name].toString() + " got: " + frame.contentWindow.location.href); + if (--pendingLoads == 0) { + SimpleTest.finish(); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug389797.html b/dom/html/test/test_bug389797.html new file mode 100644 index 000000000..884348b12 --- /dev/null +++ b/dom/html/test/test_bug389797.html @@ -0,0 +1,267 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=389797 +--> +<head> + <title>Test for Bug 389797</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=389797">Mozilla Bug 389797</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 389797 **/ +var allTags = []; +var classInfos = {}; +var interfaces = {}; +var interfacesNonClassinfo = {}; + +function getClassName(tag) { + return "HTML" + classInfos[tag] + "Element"; +} + +function HTML_TAG(aTagName, aImplClass) { + allTags.push(aTagName); + classInfos[aTagName] = aImplClass; + interfaces[aTagName] = [ "nsIDOMEventTarget" ]; + + // Some interfaces don't appear in classinfo because other interfaces that + // inherit from them do. + interfacesNonClassinfo[aTagName] = + [ "nsIDOMNode", + "nsIDOMElement" ]; + + var interfaceName = "nsIDOM" + getClassName(aTagName); + if (interfaceName in SpecialPowers.Ci) { // no nsIDOMHTMLSpanElement + interfaces[aTagName].push(interfaceName); + interfacesNonClassinfo[aTagName].push("nsIDOMHTMLElement"); + } else { + // Inherits directly from nsIDOMHTMLElement. + interfaces[aTagName].push("nsIDOMHTMLElement"); + } + + var interfaceNameNS = "nsIDOMNS" + getClassName(aTagName); + if (interfaceNameNS in SpecialPowers.Ci) { + interfaces[aTagName].push(interfaceNameNS); + } + + if (arguments.length > 2) { + for (var i = 0; i < arguments[2].length; ++i) { + interfaces[aTagName].push(arguments[2][i]); + } + } + + if (arguments.length > 3) { + for (i = 0; i < arguments[3].length; ++i) { + interfacesNonClassinfo[aTagName].push(arguments[3][i]); + } + } +} + +const objectIfaces = [ + "imgINotificationObserver", "nsIRequestObserver", "nsIStreamListener", + "nsIFrameLoaderOwner", "nsIObjectLoadingContent", "nsIChannelEventSink" + ]; + +var objectIfaces2 = []; +for (var iface of objectIfaces) { + objectIfaces2.push(iface); +} +objectIfaces2.push("nsIImageLoadingContent"); + +/* List copy/pasted from nsHTMLTagList.h, with the second field modified to the + correct classinfo (instead of the impl class) in the following cases: + + applet + base + blockquote + dir + dl + embed + menu + ol + param + q + ul + wbr + head + html + */ + +HTML_TAG("a", "Anchor"); +HTML_TAG("abbr", ""); +HTML_TAG("acronym", ""); +HTML_TAG("address", ""); +HTML_TAG("applet", "Applet", [], objectIfaces); +HTML_TAG("area", "Area"); +HTML_TAG("article", ""); +HTML_TAG("aside", ""); +HTML_TAG("b", ""); +HTML_TAG("base", "Base"); +HTML_TAG("bdo", ""); +HTML_TAG("bgsound", "Unknown"); +HTML_TAG("big", ""); +HTML_TAG("blockquote", "Quote"); +HTML_TAG("body", "Body"); +HTML_TAG("br", "BR"); +HTML_TAG("button", "Button"); +HTML_TAG("canvas", "Canvas"); +HTML_TAG("caption", "TableCaption"); +HTML_TAG("center", ""); +HTML_TAG("cite", ""); +HTML_TAG("code", ""); +HTML_TAG("col", "TableCol"); +HTML_TAG("colgroup", "TableCol"); +HTML_TAG("data", "Data"); +HTML_TAG("datalist", "DataList"); +HTML_TAG("dd", ""); +HTML_TAG("del", "Mod"); +HTML_TAG("dfn", ""); +HTML_TAG("dir", "Directory"); +HTML_TAG("div", "Div"); +HTML_TAG("dl", "DList"); +HTML_TAG("dt", ""); +HTML_TAG("em", ""); +HTML_TAG("embed", "Embed", [], objectIfaces); +HTML_TAG("fieldset", "FieldSet"); +HTML_TAG("figcaption", "") +HTML_TAG("figure", "") +HTML_TAG("font", "Font"); +HTML_TAG("footer", "") +HTML_TAG("form", "Form", [], [ "nsIWebProgressListener" ]); +HTML_TAG("frame", "Frame", [ "nsIDOMMozBrowserFrame" ], [ "nsIFrameLoaderOwner" ]); +HTML_TAG("frameset", "FrameSet"); +HTML_TAG("h1", "Heading"); +HTML_TAG("h2", "Heading"); +HTML_TAG("h3", "Heading"); +HTML_TAG("h4", "Heading"); +HTML_TAG("h5", "Heading"); +HTML_TAG("h6", "Heading"); +HTML_TAG("head", "Head"); +HTML_TAG("header", "") +HTML_TAG("hgroup", "") +HTML_TAG("hr", "HR"); +HTML_TAG("html", "Html"); +HTML_TAG("i", ""); +HTML_TAG("iframe", "IFrame", [ "nsIDOMMozBrowserFrame" ], + [ "nsIFrameLoaderOwner" ]); +HTML_TAG("image", ""); +HTML_TAG("img", "Image", [ "nsIImageLoadingContent" ], []); +HTML_TAG("input", "Input", [], [ "imgINotificationObserver", + "nsIImageLoadingContent", + "nsIDOMNSEditableElement" ]); +HTML_TAG("ins", "Mod"); +HTML_TAG("kbd", ""); +HTML_TAG("keygen", "Span"); +HTML_TAG("label", "Label"); +HTML_TAG("legend", "Legend"); +HTML_TAG("li", "LI"); +HTML_TAG("link", "Link"); +HTML_TAG("listing", "Pre"); +HTML_TAG("main", ""); +HTML_TAG("map", "Map"); +HTML_TAG("mark", ""); +HTML_TAG("marquee", "Div"); +HTML_TAG("menu", "Menu"); +HTML_TAG("meta", "Meta"); +HTML_TAG("meter", "Meter"); +HTML_TAG("multicol", "Unknown"); +HTML_TAG("nav", "") +HTML_TAG("nobr", ""); +HTML_TAG("noembed", ""); +HTML_TAG("noframes", ""); +HTML_TAG("noscript", ""); +HTML_TAG("object", "Object", [], + objectIfaces.concat([ "nsIImageLoadingContent" ])); +HTML_TAG("ol", "OList"); +HTML_TAG("optgroup", "OptGroup"); +HTML_TAG("option", "Option"); +HTML_TAG("p", "Paragraph"); +HTML_TAG("param", "Param"); +HTML_TAG("plaintext", ""); +HTML_TAG("pre", "Pre"); +HTML_TAG("q", "Quote"); +HTML_TAG("rb", ""); +HTML_TAG("rp", ""); +HTML_TAG("rt", ""); +HTML_TAG("rtc", ""); +HTML_TAG("ruby", ""); +HTML_TAG("s", ""); +HTML_TAG("samp", ""); +HTML_TAG("script", "Script", [ "nsIScriptLoaderObserver" ], []); +HTML_TAG("section", "") +HTML_TAG("select", "Select", ["nsIDOMHTMLSelectElement"]); +HTML_TAG("small", ""); +HTML_TAG("span", "Span"); +HTML_TAG("strike", ""); +HTML_TAG("strong", ""); +HTML_TAG("style", "Style"); +HTML_TAG("sub", ""); +HTML_TAG("sup", ""); +HTML_TAG("table", "Table"); +HTML_TAG("tbody", "TableSection"); +HTML_TAG("td", "TableCell"); +HTML_TAG("textarea", "TextArea", [], [ "nsIDOMNSEditableElement" ]); +HTML_TAG("tfoot", "TableSection"); +HTML_TAG("th", "TableCell"); +HTML_TAG("thead", "TableSection"); +HTML_TAG("template", "Template"); +HTML_TAG("time", "Time"); +HTML_TAG("title", "Title"); +HTML_TAG("tr", "TableRow"); +HTML_TAG("tt", ""); +HTML_TAG("u", ""); +HTML_TAG("ul", "UList"); +HTML_TAG("var", ""); +HTML_TAG("wbr", ""); +HTML_TAG("xmp", "Pre"); + +function tagName(aTag) { + return "<" + aTag + ">"; +} + +for (var tag of allTags) { + var node = document.createElement(tag); + + // Have to use the proto's toString(), since HTMLAnchorElement and company + // override toString(). + var nodeString = HTMLElement.prototype.toString.apply(node); + + // Debug builds have extra info, so chop off after "Element" if it's followed + // by ' ' or ']' + nodeString = nodeString.replace(/Element[\] ].*/, "Element"); + + var classInfoString = getClassName(tag); + is(nodeString, "[object " + classInfoString, + "Unexpected classname for " + tagName(tag)); + is(node instanceof window[classInfoString], true, + tagName(tag) + " not an instance of " + classInfos[tag]); + + if (classInfoString != 'HTMLUnknownElement') { + is(node instanceof HTMLUnknownElement, false, + tagName(tag) + " is an instance of HTMLUnknownElement"); + } else { + is(node instanceof HTMLUnknownElement, true, + tagName(tag) + " is an instance of HTMLUnknownElement"); + } + + // Check that each node QIs to all the things we expect it to QI to + for (var iface of interfaces[tag].concat(interfacesNonClassinfo[tag])) { + is(iface in SpecialPowers.Ci, true, + iface + " not in Components.interfaces"); + is(node instanceof SpecialPowers.Ci[iface], true, + tagName(tag) + " does not QI to " + iface); + } +} +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug390975.html b/dom/html/test/test_bug390975.html new file mode 100644 index 000000000..9034d4e32 --- /dev/null +++ b/dom/html/test/test_bug390975.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=390975 +--> +<head> + <title>Test for Bug 390975</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=390975">Mozilla Bug 390975</a> +<p id="display"></p> +<div id="content" style="display: none"> + <table id="table1"> + <form id="form1"> + <input> + <input> + <tr><td> + <input> + <input> + <input> + </td></tr> + </form> + </table> + + <table id="table2"> + <form id="form2"> + <input> + <input> + <tr id="row2"><td> + <input> + <input> + <input> + </td></tr> + </form> + </table> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 390975 **/ +var form = $("form1"); +is(form.elements.length, 5, "Unexpected elements length"); + +$("table1").parentNode.removeChild($("table1")); +is(form.elements.length, 3, "Should have lost control outside table"); + +form.parentNode.removeChild(form); +is(form.elements.length, 0, "Should have lost control outside form"); + +form = $("form2"); +is(form.elements.length, 5, "Unexpected elements length"); + +$("row2").parentNode.removeChild($("row2")); +is(form.elements.length, 2, "Should have lost controls inside table row"); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug391777.html b/dom/html/test/test_bug391777.html new file mode 100644 index 000000000..aa01a45de --- /dev/null +++ b/dom/html/test/test_bug391777.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=391777 +--> +<head> + <title>Test for Bug 391777</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=391777">Mozilla Bug 391777</a> +<p id="display"></p> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 391777 **/ +var arg = {}; +arg.testVal = "foo"; +var result = window.showModalDialog("javascript:window.returnValue = window.dialogArguments.testVal; window.close(); 'This window should close on its own.';", arg); +ok(true, "We should get here without user interaction"); +is(result, "foo", "Unexpected result from showModalDialog"); + +</script> +</body> +</html> diff --git a/dom/html/test/test_bug391994.html b/dom/html/test/test_bug391994.html new file mode 100644 index 000000000..f26ac560c --- /dev/null +++ b/dom/html/test/test_bug391994.html @@ -0,0 +1,184 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=391994 +--> +<head> + <title>Test for Bug 391994</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=391994">Mozilla Bug 391994</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 391994 **/ +var testNumber = 0; + +function assertSelected(aOption, aExpectDefaultSelected, aExpectSelected) { + ++testNumber; + is(aOption.defaultSelected, aExpectDefaultSelected, + "Asserting default-selected state for option " + testNumber); + is(aOption.selected, aExpectSelected, + "Asserting selected state for option " + testNumber); +} + +function assertSame(aSel1, aSel2Str, aTestNumber) { + var div = document.createElement("div"); + div.innerHTML = aSel2Str; + sel2 = div.firstChild; + is(aSel1.options.length, sel2.options.length, + "Length should be same in select test " + aTestNumber); + is(aSel1.selectedIndex, sel2.selectedIndex, + "Selected index should be same in select test " + aTestNumber); + for (var i = 0; i < aSel1.options.length; ++i) { + is(aSel1.options[i].selected, sel2.options[i].selected, + "Options[" + i + "].selected should be the same in select test " + + aTestNumber); + is(aSel1.options[i].defaultSelected, sel2.options[i].defaultSelected, + "Options[" + i + + "].defaultSelected should be the same in select test " + + aTestNumber); + } +} + +// Creation methods +var opt = document.createElement("option"); +assertSelected(opt, false, false); + +opt = new Option(); +assertSelected(opt, false, false); + +// Setting of defaultSelected +opt = new Option(); +opt.setAttribute("selected", "selected"); +assertSelected(opt, true, true); + +opt = new Option(); +opt.defaultSelected = true; +assertSelected(opt, true, true); +is(opt.hasAttribute("selected"), true, "Attribute should be set"); +is(opt.getAttribute("selected"), "", + "Attribute should be set to empty string"); + +// Setting of selected +opt = new Option(); +opt.selected = false; +assertSelected(opt, false, false); + +opt = new Option(); +opt.selected = true; +assertSelected(opt, false, true); + +// Interaction of selected and defaultSelected +opt = new Option(); +opt.selected; +opt.setAttribute("selected", "selected"); +assertSelected(opt, true, true); + +opt = new Option(); +opt.selected = false; +opt.setAttribute("selected", "selected"); +assertSelected(opt, true, false); + +opt = new Option(); +opt.setAttribute("selected", "selected"); +opt.selected = true; +opt.removeAttribute("selected"); +assertSelected(opt, false, true); + +// First test of putting things in a <select>: Adding default-selected option +// should select it. +var sel = document.createElement("select"); +sel.appendChild(new Option()); +is(sel.selectedIndex, 0, "First option should be selected"); +assertSelected(sel.firstChild, false, true); + +sel.appendChild(new Option()); +is(sel.selectedIndex, 0, "First option should still be selected"); +assertSelected(sel.firstChild, false, true); +assertSelected(sel.firstChild.nextSibling, false, false); + +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +assertSelected(sel.firstChild, false, false); +assertSelected(sel.firstChild.nextSibling, false, false); +assertSelected(opt, true, true); +is(opt, sel.firstChild.nextSibling.nextSibling, "What happened here?"); +is(sel.options[0], sel.firstChild, "Unexpected option 0"); +is(sel.options[1], sel.firstChild.nextSibling, "Unexpected option 1"); +is(sel.options[2], opt, "Unexpected option 2"); +is(sel.selectedIndex, 2, "Unexpected selectedIndex in select test 1"); + +assertSame(sel, "<select><option><option><option selected></select>", 1); + +// Second test of putting things in a <select>: Adding two default-selected +// options should select the second one. +sel = document.createElement("select"); +sel.appendChild(new Option()); +sel.appendChild(new Option()); +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +assertSelected(sel.options[0], false, false); +assertSelected(sel.options[1], false, false); +assertSelected(sel.options[2], true, false); +assertSelected(sel.options[3], true, true); +is(sel.selectedIndex, 3, "Unexpected selectedIndex in select test 2"); + +assertSame(sel, + "<select><option><option><option selected><option selected></select>", 2); + +// Third test of putting things in a <select>: adding a selected option earlier +// than another selected option should make the new option selected. +sel = document.createElement("select"); +sel.appendChild(new Option()); +sel.appendChild(new Option()); +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +opt = new Option(); +opt.defaultSelected = true; +sel.options[0] = opt; +assertSelected(sel.options[0], true, true); +assertSelected(sel.options[1], false, false); +assertSelected(sel.options[2], true, false); +is(sel.selectedIndex, 0, "Unexpected selectedIndex in select test 3"); + +// Fourth test of putting things in a <select>: Just like second test, but with +// a <select multiple> +sel = document.createElement("select"); +sel.multiple = true; +sel.appendChild(new Option()); +sel.appendChild(new Option()); +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +assertSelected(sel.options[0], false, false); +assertSelected(sel.options[1], false, false); +assertSelected(sel.options[2], true, true); +assertSelected(sel.options[3], true, true); +is(sel.selectedIndex, 2, "Unexpected selectedIndex in select test 4"); + +assertSame(sel, + "<select multiple><option><option>" + + "<option selected><option selected></select>", + 4); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug392567.html b/dom/html/test/test_bug392567.html new file mode 100644 index 000000000..f58c69e9c --- /dev/null +++ b/dom/html/test/test_bug392567.html @@ -0,0 +1,88 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=392567 +--> +<head> + <title>Test for Bug 392567</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=392567">Mozilla Bug 392567</a> +<p id="display"><iframe name="testFrame" id="testFrame" style="visibility: hidden;"></iframe></p> +<div id="content" style="display: none"> + <form name="testForm" target="testFrame"> + <input type="text" name="key" /> + </form> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 392567 **/ + +SimpleTest.waitForExplicitFinish(); + +function runTests() +{ + if (window.location.search.match(/\?key=value/)) { + return; + } + + var dataUrl = "http://mochi.test:8888/tests/dom/html/test/bug392567.jar"; + var jarUrl = "jar:" + dataUrl + "!/index.html"; + var httpUrl = location.href.replace(/\.html.*/, "_404"); + var previousDir = location.href.replace(/test\/[^\/]*$/, ""); + var documentURL = location.href.replace(/\.html.*/, "\.html"); + + var form = document.forms.testForm; + var frame = frames.testFrame; + document.getElementById("testFrame").onload = processTestResult; + + // List of tests to run, each test consists of form action URL and expected result URL + var tests = [ + [jarUrl, jarUrl + "?$PARAMS"], + [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS"], + [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5"], + ["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS"], + ["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS"], + [httpUrl, httpUrl + "?$PARAMS"], + [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS"], + [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5"], + ["", documentURL + "?$PARAMS"], + [" ", documentURL + "?$PARAMS"], + ["../", previousDir + "?$PARAMS"], + ]; + + var currentTest = -1; + + runNextTest(); + + function runNextTest() { + currentTest++; + if (currentTest >= tests.length) { + SimpleTest.finish(); + return; + } + + form.setAttribute("action", tests[currentTest][0]); + form.key.value = "value" + currentTest; + form.submit(); + } + + function processTestResult() { + var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest); + is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]); + + setTimeout(runNextTest, 0); + } +} + +addLoadEvent(function() { + SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, runTests); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug394700.html b/dom/html/test/test_bug394700.html new file mode 100644 index 000000000..a2dd92129 --- /dev/null +++ b/dom/html/test/test_bug394700.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=394700 +--> +<head> + <title>Test for Bug 394700</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=394700">Mozilla Bug 394700</a> +<p id="display"></p> +<div id="content"> + <select><option id="A">A</option><option id="B">B</option></select> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 394700 **/ + +function remove(q1) { q1.parentNode.removeChild(q1); } + +function testSelectedIndex() +{ + document.addEventListener("DOMNodeRemoved", foo, false); + remove(document.getElementById("B")); + document.removeEventListener("DOMNodeRemoved", foo, false); + + function foo() + { + document.removeEventListener("DOMNodeRemoved", foo, false); + remove(document.getElementById("A")); + } + var selectElement = document.getElementsByTagName("select")[0]; + ok(selectElement.selectedIndex == -1, "Wrong selected index!"); + ok(selectElement.length == 0, "Select shouldn't have any options!") +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(testSelectedIndex); +addLoadEvent(SimpleTest.finish); + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug395107.html b/dom/html/test/test_bug395107.html new file mode 100644 index 000000000..22e5e110d --- /dev/null +++ b/dom/html/test/test_bug395107.html @@ -0,0 +1,108 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=395107 +--> +<head> + <title>Test for Bug 395107</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=395107">Mozilla Bug 395107</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 395107 **/ +var testNumber = 0; + +function assertSelected(aOption, aExpectDefaultSelected, aExpectSelected) { + ++testNumber; + is(aOption.defaultSelected, aExpectDefaultSelected, + "Asserting default-selected state for option " + testNumber); + is(aOption.selected, aExpectSelected, + "Asserting selected state for option " + testNumber); +} + +function assertSame(aSel1, aSel2Str, aTestNumber) { + var div = document.createElement("div"); + div.innerHTML = aSel2Str; + sel2 = div.firstChild; + is(aSel1.options.length, sel2.options.length, + "Length should be same in select test " + aTestNumber); + is(aSel1.selectedIndex, sel2.selectedIndex, + "Selected index should be same in select test " + aTestNumber); + for (var i = 0; i < aSel1.options.length; ++i) { + is(aSel1.options[i].selected, sel2.options[i].selected, + "Options[" + i + "].selected should be the same in select test " + + aTestNumber); + is(aSel1.options[i].defaultSelected, sel2.options[i].defaultSelected, + "Options[" + i + + "].defaultSelected should be the same in select test " + + aTestNumber); + } +} + +// In a single-select, setting an option selected should deselect an +// existing selected option. +var sel = document.createElement("select"); +sel.appendChild(new Option()); +is(sel.selectedIndex, 0, "First option should be selected"); +assertSelected(sel.firstChild, false, true); +sel.appendChild(new Option()); +is(sel.selectedIndex, 0, "First option should still be selected"); +assertSelected(sel.firstChild, false, true); +assertSelected(sel.firstChild.nextSibling, false, false); + +opt = new Option(); +sel.appendChild(opt); +opt.defaultSelected = true; +assertSelected(sel.firstChild, false, false); +assertSelected(sel.firstChild.nextSibling, false, false); +assertSelected(opt, true, true); +is(opt, sel.firstChild.nextSibling.nextSibling, "What happened here?"); +is(sel.options[0], sel.firstChild, "Unexpected option 0"); +is(sel.options[1], sel.firstChild.nextSibling, "Unexpected option 1"); +is(sel.options[2], opt, "Unexpected option 2"); +is(sel.selectedIndex, 2, "Unexpected selectedIndex in select test 1"); + +assertSame(sel, "<select><option><option><option selected></select>", 1); + +// Same, but with the option that gets set selected earlier in the select +sel = document.createElement("select"); +sel.appendChild(new Option()); +sel.appendChild(new Option()); +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +opt = new Option(); +sel.options[0] = opt; +opt.defaultSelected = true; +assertSelected(sel.options[0], true, true); +assertSelected(sel.options[1], false, false); +assertSelected(sel.options[2], true, false); +is(sel.selectedIndex, 0, "Unexpected selectedIndex in select test 2"); + +// And now try unselecting options +sel = document.createElement("select"); +sel.appendChild(new Option()); +opt = new Option(); +opt.defaultSelected = true; +sel.appendChild(opt); +sel.appendChild(new Option()); +opt.defaultSelected = false; + +assertSelected(sel.options[0], false, true); +assertSelected(sel.options[1], false, false); +assertSelected(sel.options[2], false, false); +is(sel.selectedIndex, 0, "Unexpected selectedIndex in select test 2"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug401160.xhtml b/dom/html/test/test_bug401160.xhtml new file mode 100644 index 000000000..b99341fe3 --- /dev/null +++ b/dom/html/test/test_bug401160.xhtml @@ -0,0 +1,27 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=401160 +--> +<head> + <title>Test for Bug 401160</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=401160">Mozilla Bug 401160</a> +<label id="label" contenteditable="true"><legend></legend><div></div></label> + +<pre id="test"> +<script type="text/javascript"> + +function do_test() { + document.getElementById('label').focus(); + ok(true, "This is crash test - the test succeeded if we reach this line") +} + +do_test(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug402680.html b/dom/html/test/test_bug402680.html new file mode 100644 index 000000000..191d2173d --- /dev/null +++ b/dom/html/test/test_bug402680.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=402680 +--> +<head> + <title>Test for Bug 402680</title> + <script> + var activeElementIsNull = (document.activeElement == null); + </script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=402680">Mozilla Bug 402680</a> +<p id="display"></p> +<div id="content"> + <input type="text"> + <textarea></textarea> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 402680 **/ + +ok(activeElementIsNull, + "Before document has body, active element should be null"); + +function testActiveElement() { + ok(document.body == document.activeElement, + "After page load body element should be the active element!"); + var input = document.getElementsByTagName("input")[0]; + input.focus(); + ok(document.activeElement == input, + "Input element isn't the active element!"); + var textarea = document.getElementsByTagName("textarea")[0]; + textarea.focus(); + ok(document.activeElement == textarea, + "Textarea element isn't the active element!"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(testActiveElement); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug403868.html b/dom/html/test/test_bug403868.html new file mode 100644 index 000000000..efcb5bdca --- /dev/null +++ b/dom/html/test/test_bug403868.html @@ -0,0 +1,87 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=403868 +--> +<head> + <title>Test for Bug 403868</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=403868">Mozilla Bug 403868</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 403868 **/ +function createSpan(id, insertionPoint) { + var s = document.createElement("span"); + s.id = id; + $("content").insertBefore(s, insertionPoint); + return s; +} + +var s1a = createSpan("test1", null); +is(document.getElementById("test1"), s1a, + "Only one span with id=test1 in the tree; should work!"); + +var s2a = createSpan("test1", null); +is(document.getElementById("test1"), s1a, + "Appending span with id=test1 doesn't change which one comes first"); + +var s3a = createSpan("test1", s2a); +is(document.getElementById("test1"), s1a, + "Inserting span with id=test1 not at the beginning; doesn't matter"); + +var s4a = createSpan("test1", s1a); +is(document.getElementById("test1"), s4a, + "Inserting span with id=test1 at the beginning changes which one is first"); + +s4a.parentNode.removeChild(s4a); +is(document.getElementById("test1"), s1a, + "First-created span with id=test1 is first again"); + +s1a.parentNode.removeChild(s1a); +is(document.getElementById("test1"), s3a, + "Third-created span with id=test1 is first now"); + +// Start the id hashtable +for (var i = 0; i < 256; ++i) { + document.getElementById("no-such-id-in-the-document" + i); +} + +var s1b = createSpan("test2", null); +is(document.getElementById("test2"), s1b, + "Only one span with id=test2 in the tree; should work!"); + +var s2b = createSpan("test2", null); +is(document.getElementById("test2"), s1b, + "Appending span with id=test2 doesn't change which one comes first"); + +var s3b = createSpan("test2", s2b); +is(document.getElementById("test2"), s1b, + "Inserting span with id=test2 not at the beginning; doesn't matter"); + +var s4b = createSpan("test2", s1b); +is(document.getElementById("test2"), s4b, + "Inserting span with id=test2 at the beginning changes which one is first"); + +s4b.parentNode.removeChild(s4b); +is(document.getElementById("test2"), s1b, + "First-created span with id=test2 is first again"); + +s1b.parentNode.removeChild(s1b); +is(document.getElementById("test2"), s3b, + "Third-created span with id=test2 is first now"); + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug403868.xhtml b/dom/html/test/test_bug403868.xhtml new file mode 100644 index 000000000..62fce0669 --- /dev/null +++ b/dom/html/test/test_bug403868.xhtml @@ -0,0 +1,86 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=403868 +--> +<head> + <title>Test for Bug 403868</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=403868">Mozilla Bug 403868</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +<![CDATA[ + +/** Test for Bug 403868 **/ +function createSpan(id, insertionPoint) { + var s = document.createElementNS("http://www.w3.org/1999/xhtml", "span"); + s.id = id; + $("content").insertBefore(s, insertionPoint); + return s; +} + +var s1a = createSpan("test1", null); +is(document.getElementById("test1"), s1a, + "Only one span with id=test1 in the tree; should work!"); + +var s2a = createSpan("test1", null); +is(document.getElementById("test1"), s1a, + "Appending span with id=test1 doesn't change which one comes first"); + +var s3a = createSpan("test1", s2a); +is(document.getElementById("test1"), s1a, + "Inserting span with id=test1 not at the beginning; doesn't matter"); + +var s4a = createSpan("test1", s1a); +is(document.getElementById("test1"), s4a, + "Inserting span with id=test1 at the beginning changes which one is first"); + +s4a.parentNode.removeChild(s4a); +is(document.getElementById("test1"), s1a, + "First-created span with id=test1 is first again"); + +s1a.parentNode.removeChild(s1a); +is(document.getElementById("test1"), s3a, + "Third-created span with id=test1 is first now"); + +// Start the id hashtable +for (var i = 0; i < 256; ++i) { + document.getElementById("no-such-id-in-the-document" + i); +} + +var s1b = createSpan("test2", null); +is(document.getElementById("test2"), s1b, + "Only one span with id=test2 in the tree; should work!"); + +var s2b = createSpan("test2", null); +is(document.getElementById("test2"), s1b, + "Appending span with id=test2 doesn't change which one comes first"); + +var s3b = createSpan("test2", s2b); +is(document.getElementById("test2"), s1b, + "Inserting span with id=test2 not at the beginning; doesn't matter"); + +var s4b = createSpan("test2", s1b); +is(document.getElementById("test2"), s4b, + "Inserting span with id=test2 at the beginning changes which one is first"); + +s4b.parentNode.removeChild(s4b); +is(document.getElementById("test2"), s1b, + "First-created span with id=test2 is first again"); + +s1b.parentNode.removeChild(s1b); +is(document.getElementById("test2"), s3b, + "Third-created span with id=test2 is first now"); + +]]> +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug405242.html b/dom/html/test/test_bug405242.html new file mode 100644 index 000000000..9ca3c1156 --- /dev/null +++ b/dom/html/test/test_bug405242.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=405242 +--> +<head> + <title>Test for Bug 405252</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=405242">Mozilla Bug 405242</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +/** Test for Bug 405242 **/ +var sel = document.createElement("select"); +sel.appendChild(new Option()); +sel.appendChild(new Option()); +sel.appendChild(new Option()); +opt = new Option(); +opt.value = 10; +sel.appendChild(opt); +sel.options.remove(0); +sel.options.remove(1000); +sel.options.remove(-1); +is(sel.length, 1, "Unexpected option collection length"); +is(sel[0].value, "10", "Unexpected remained option"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug406596.html b/dom/html/test/test_bug406596.html new file mode 100644 index 000000000..adc638052 --- /dev/null +++ b/dom/html/test/test_bug406596.html @@ -0,0 +1,83 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=406596 +--> +<head> + <title>Test for Bug 406596</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=406596">Mozilla Bug 406596</a> +<div id="content"> + <div id="edit" contenteditable="true">This text is editable, you can change its content <a href="#" id="a" tabindex="0">ABCDEFGHIJKLMNOPQRSTUV</a> <input type="submit" value="abcd" id="b"></input> <img src="foo.png" id="c"></div> + <div tabindex="0">This text is not editable but is focusable</div> + <div tabindex="0">This text is not editable but is focusable</div> + <a href="#" id="d" contenteditable="true">ABCDEFGHIJKLMNOPQRSTUV</a> + <div tabindex="0">This text is not editable but is focusable</div> + <div tabindex="0">This text is not editable but is focusable</div> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 406596 **/ + +function testTabbing(click, focus, selectionOffset) { + var wu = SpecialPowers.getDOMWindowUtils(window); + + var elem = document.getElementById(click); + var rect = elem.getBoundingClientRect(); + var selection = window.getSelection(); + + var x = (rect.left + rect.right) / 4; + var y = (rect.top + rect.bottom) / 2; + wu.sendMouseEvent("mousedown", x, y, 0, 1, 0); + wu.sendMouseEvent("mousemove", x + selectionOffset, y, 0, 1, 0); + wu.sendMouseEvent("mouseup", x + selectionOffset, y, 0, 1, 0); + if (selectionOffset) { + is(selection.rangeCount, 1, "there should be one range in the selection"); + var range = selection.getRangeAt(0); + } + var focusedElement = document.activeElement; + is(focusedElement, document.getElementById(focus), + "clicking should move focus to the contentEditable node"); + synthesizeKey("VK_TAB", {}); + synthesizeKey("VK_TAB", {}); + synthesizeKey("VK_TAB", { shiftKey: true }); + synthesizeKey("VK_TAB", { shiftKey: true }); + is(document.activeElement, focusedElement, + "tab/shift-tab should move focus back to the contentEditable node"); + if (selectionOffset) { + is(selection.rangeCount, 1, + "there should still be one range in the selection"); + var newRange = selection.getRangeAt(0); + is(newRange.compareBoundaryPoints(Range.START_TO_START, range), 0, + "the selection should be the same as before the tabbing"); + is(newRange.compareBoundaryPoints(Range.END_TO_END, range), 0, + "the selection should be the same as before the tabbing"); + } +} + +function test() { + window.getSelection().removeAllRanges(); + testTabbing("edit", "edit", 0); + testTabbing("a", "edit", 0); + testTabbing("d", "d", 0); + testTabbing("edit", "edit", 10); + testTabbing("a", "edit", 10); + testTabbing("d", "d", 10); + + SimpleTest.finish(); +} + +window.onload = function() { + SimpleTest.waitForExplicitFinish(); + setTimeout(test, 0); +}; + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug417760.html b/dom/html/test/test_bug417760.html new file mode 100644 index 000000000..7a16914a0 --- /dev/null +++ b/dom/html/test/test_bug417760.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=417760 +--> +<head> + <title>cannot focus() img with tabindex="-1"</title> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <style type="text/css"> + img { + border: 5px solid white; + } + img:focus { + border: 5px solid black; + } + </style> + + + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + + <script type="text/javascript"> + function checkFocus(aExpected, aTabIndex) + { + elemCurr = document.activeElement.getAttribute("id"); + is(elemCurr, aExpected, "Element with tabIndex " + aTabIndex + + " did not receive focus!"); + } + + function doTest() + { + // First, test img with tabindex = 0 + document.getElementById("img-tabindex-0").focus(); + checkFocus("img-tabindex-0", 0); + + // now test the img with tabindex = -1 + document.getElementById("img-tabindex-minus-1").focus(); + checkFocus("img-tabindex-minus-1", -1); + + // now test the img without tabindex, should NOT receive focus! + document.getElementById("img-no-tabindex").focus(); + checkFocus("img-tabindex-minus-1", null); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addLoadEvent(doTest); + </script> +</head> + +<body> + + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=417760">Mozilla Bug 417760</a> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + <br>img tabindex="0": + <img id="img-tabindex-0" + src="file_bug417760.png" + alt="MoCo logo" tabindex="0"/> + <br>img tabindex="-1": + <img id="img-tabindex-minus-1" + src="file_bug417760.png" + alt="MoCo logo" tabindex="-1"/> + <br>img without tabindex: + <img id="img-no-tabindex" + src="file_bug417760.png" + alt="MoCo logo"/> +</body> +</html> diff --git a/dom/html/test/test_bug421640.html b/dom/html/test/test_bug421640.html new file mode 100644 index 000000000..59bac6a92 --- /dev/null +++ b/dom/html/test/test_bug421640.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=421640 +--> +<head> + <title>Test for Bug 421640</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=421640">Mozilla Bug 421640</a> +<div id="content"> + <div id="edit" contenteditable="true">This text is editable</div> + <div><button id="button">Test</button></div> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 421640 **/ + +function test(click, focus, nextFocus) { + var wu = SpecialPowers.getDOMWindowUtils(window); + + var selection = window.getSelection(); + var edit = document.getElementById("edit"); + var text = edit.firstChild; + + selection.removeAllRanges(); + + var rect = edit.getBoundingClientRect(); + wu.sendMouseEvent("mousedown", rect.left + 1, rect.top + 1, 0, 1, 0); + wu.sendMouseEvent("mousemove", rect.right - 1, rect.top + 1, 0, 1, 0); + wu.sendMouseEvent("mouseup", rect.right - 1, rect.top + 1, 0, 1, 0); + + is(selection.anchorNode, text, ""); + + rect = document.getElementById("button").getBoundingClientRect(); + wu.sendMouseEvent("mousedown", rect.left + 10, rect.top + 1, 0, 1, 0); + wu.sendMouseEvent("mouseup", rect.left + 10, rect.top + 1, 0, 1, 0); + + is(selection.anchorNode, text, ""); + + SimpleTest.finish(); +} + +window.onload = function() { + SimpleTest.waitForExplicitFinish(); + setTimeout(test, 0); +}; + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug424698.html b/dom/html/test/test_bug424698.html new file mode 100644 index 000000000..9bd6ea5ff --- /dev/null +++ b/dom/html/test/test_bug424698.html @@ -0,0 +1,94 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=424698 +--> +<head> + <title>Test for Bug 424698</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=424698">Mozilla Bug 424698</a> +<p id="display"> +<input id="i1"> +<input id="target"> +<textarea id="i2"></textarea> +<textarea id="target2"></textarea> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 424698 **/ +var i = $("i1"); +is(i.value, "", "Value should be empty string"); +i.defaultValue = "test"; +is(i.value, "test", "Setting defaultValue should work"); +i.defaultValue = "test2"; +is(i.value, "test2", "Setting defaultValue multiple times should work"); + +// Now let's hide and reshow things +i.style.display = "none"; +is(i.offsetWidth, 0, "Input didn't hide?"); +i.style.display = ""; +isnot(i.offsetWidth, 0, "Input didn't show?"); +is(i.value, "test2", "Hiding/showing should not affect value"); +i.defaultValue = "test3"; +is(i.value, "test3", "Setting defaultValue after hide/show should work"); + +// Make sure typing works ok +i = $("target"); +i.focus(); // Otherwise editor gets confused when we send the key events +is(i.value, "", "Value should be empty string in second control"); +sendString("2test2"); +is(i.value, "2test2", 'We just typed the string "2test2"'); +i.defaultValue = "2test3"; +is(i.value, "2test2", "Setting defaultValue after typing should not work"); +i.style.display = "none"; +is(i.offsetWidth, 0, "Second input didn't hide?"); +i.style.display = ""; +isnot(i.offsetWidth, 0, "Second input didn't show?"); +is(i.value, "2test2", "Hiding/showing second input should not affect value"); +i.defaultValue = "2test4"; +is(i.value, "2test2", "Setting defaultValue after hide/show should not work if we typed"); + +i = $("i2"); +is(i.value, "", "Textarea value should be empty string"); +i.defaultValue = "test"; +is(i.value, "test", "Setting textarea defaultValue should work"); +i.defaultValue = "test2"; +is(i.value, "test2", "Setting textarea defaultValue multiple times should work"); + +// Now let's hide and reshow things +i.style.display = "none"; +is(i.offsetWidth, 0, "Textarea didn't hide?"); +i.style.display = ""; +isnot(i.offsetWidth, 0, "Textarea didn't show?"); +is(i.value, "test2", "Hiding/showing textarea should not affect value"); +i.defaultValue = "test3"; +is(i.value, "test3", "Setting textarea defaultValue after hide/show should work"); + +// Make sure typing works ok +i = $("target2"); +i.focus(); // Otherwise editor gets confused when we send the key events +is(i.value, "", "Textarea value should be empty string in second control"); +sendString("2test2"); +is(i.value, "2test2", 'We just typed the string "2test2"'); +i.defaultValue = "2test3"; +is(i.value, "2test2", "Setting textarea defaultValue after typing should not work"); +i.style.display = "none"; +is(i.offsetWidth, 0, "Second textarea didn't hide?"); +i.style.display = ""; +isnot(i.offsetWidth, 0, "Second textarea didn't show?"); +is(i.value, "2test2", "Hiding/showing second textarea should not affect value"); +i.defaultValue = "2test4"; +is(i.value, "2test2", "Setting textarea defaultValue after hide/show should not work if we typed"); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug428135.xhtml b/dom/html/test/test_bug428135.xhtml new file mode 100644 index 000000000..27ff7aeef --- /dev/null +++ b/dom/html/test/test_bug428135.xhtml @@ -0,0 +1,156 @@ +<?xml version="1.0"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=428135 +--> +<head> + <title>Test for Bug 428135</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=428135">Mozilla Bug 428135</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +<![CDATA[ + +/** Test for Bug 428135 **/ + +var expectedCurrentTargets = new Array(); + +function d(el, ename) { + var e = document.createEvent("Events"); + e.initEvent(ename, true, true); + el.dispatchEvent(e); +} + +function testListener(e) { + e.preventDefault(); + var expected = expectedCurrentTargets.shift(); + ok(expected == e.currentTarget, + "Unexpected current target [" + e.currentTarget + "], event=" + e.type + + ", phase=" + e.eventPhase + ", target should have been " + expected); +} + +function getAndAddListeners(elname) { + var el = document; + if (elname) { + el = document.getElementById(elname); + } + el.addEventListener("submit", testListener, true); + el.addEventListener("submit", testListener, false); + el.addEventListener("reset", testListener, true); + el.addEventListener("reset", testListener, false); + el.addEventListener("fooEvent", testListener, true); + el.addEventListener("fooEvent", testListener, false); + return el; +} + +function testSubmitResetEvents() { + getAndAddListeners(null); + var outerForm = getAndAddListeners("outerForm"); + var outerSubmit = getAndAddListeners("outerSubmit"); + var outerReset = getAndAddListeners("outerReset"); + var outerSubmitDispatcher = getAndAddListeners("outerSubmitDispatcher"); + var outerResetDispatcher = getAndAddListeners("outerResetDispatcher"); + var outerChild = getAndAddListeners("outerChild"); + var innerForm = getAndAddListeners("innerForm"); + var innerSubmit = getAndAddListeners("innerSubmit"); + var innerReset = getAndAddListeners("innerReset"); + var innerSubmitDispatcher = getAndAddListeners("innerSubmitDispatcher"); + var innerResetDispatcher = getAndAddListeners("innerResetDispatcher"); + + expectedCurrentTargets = new Array(document, outerForm, outerForm, document); + outerSubmit.click(); + ok(expectedCurrentTargets.length == 0, + "(1) expectedCurrentTargets isn't empty!"); + + expectedCurrentTargets = new Array(document, outerForm, outerForm, document); + outerReset.click(); + ok(expectedCurrentTargets.length == 0, + "(2) expectedCurrentTargets isn't empty!"); + + // Because of bug 428135, submit shouldn't propagate + // back to outerForm and document! + expectedCurrentTargets = + new Array(document, outerForm, outerSubmitDispatcher, outerSubmitDispatcher); + outerSubmitDispatcher.click(); + ok(expectedCurrentTargets.length == 0, + "(3) expectedCurrentTargets isn't empty!"); + + // Because of bug 428135, reset shouldn't propagate + // back to outerForm and document! + expectedCurrentTargets = + new Array(document, outerForm, outerResetDispatcher, outerResetDispatcher); + outerResetDispatcher.click(); + ok(expectedCurrentTargets.length == 0, + "(4) expectedCurrentTargets isn't empty!"); + + // Because of bug 428135, submit shouldn't propagate + // back to outerForm and document! + expectedCurrentTargets = + new Array(document, outerForm, outerChild, innerForm, innerForm, outerChild); + innerSubmit.click(); + ok(expectedCurrentTargets.length == 0, + "(5) expectedCurrentTargets isn't empty!"); + + // Because of bug 428135, reset shouldn't propagate + // back to outerForm and document! + expectedCurrentTargets = + new Array(document, outerForm, outerChild, innerForm, innerForm, outerChild); + innerReset.click(); + ok(expectedCurrentTargets.length == 0, + "(6) expectedCurrentTargets isn't empty!"); + + // Because of bug 428135, submit shouldn't propagate + // back to inner/outerForm or document! + expectedCurrentTargets = + new Array(document, outerForm, outerChild, innerForm, innerSubmitDispatcher, + innerSubmitDispatcher); + innerSubmitDispatcher.click(); + ok(expectedCurrentTargets.length == 0, + "(7) expectedCurrentTargets isn't empty!"); + + // Because of bug 428135, reset shouldn't propagate + // back to inner/outerForm or document! + expectedCurrentTargets = + new Array(document, outerForm, outerChild, innerForm, innerResetDispatcher, + innerResetDispatcher); + innerResetDispatcher.click(); + ok(expectedCurrentTargets.length == 0, + "(8) expectedCurrentTargets isn't empty!"); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(testSubmitResetEvents); +addLoadEvent(SimpleTest.finish); + + +]]> +</script> +</pre> +<form id="outerForm"> + <input type="submit" value="outer" id="outerSubmit"/> + <input type="reset" value="reset outer" id="outerReset"/> + <input type="button" value="dispatch submit" onclick="d(this, 'submit')" + id="outerSubmitDispatcher"/> + <input type="button" value="dispatch reset" onclick="d(this, 'reset')" + id="outerResetDispatcher"/> + <div id="outerChild"> + <form id="innerForm"> + <input type="submit" value="inner" id="innerSubmit"/> + <input type="reset" value="reset inner" id="innerReset"/> + <input type="button" value="dispatch submit" onclick="d(this, 'submit')" + id="innerSubmitDispatcher"/> + <input type="button" value="dispatch reset" onclick="d(this, 'reset')" + id="innerResetDispatcher"/> + </form> + </div> +</form> +</body> +</html> + diff --git a/dom/html/test/test_bug430351.html b/dom/html/test/test_bug430351.html new file mode 100644 index 000000000..585620e7d --- /dev/null +++ b/dom/html/test/test_bug430351.html @@ -0,0 +1,523 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=430351 +--> +<head> + <title>Test for Bug 430351</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430351">Mozilla Bug 430351</a> +<p id="display"></p> +<div id="content"> + <div id="parent"></div> + <div id="editableParent" contenteditable="true"></div> + <iframe id="frame"></iframe> + <map name="map"><area></map> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 430351 **/ + +var focusableElements = [ + "<a tabindex=\"-1\"></a>", + "<a tabindex=\"0\"></a>", + "<a tabindex=\"0\" disabled></a>", + "<a tabindex=\"1\"></a>", + "<a contenteditable=\"true\"></a>", + + "<a href=\"#\"></a>", + "<a href=\"#\" tabindex=\"-1\"></a>", + "<a href=\"#\" tabindex=\"0\"></a>", + "<a href=\"#\" tabindex=\"0\" disabled></a>", + "<a href=\"#\" tabindex=\"1\"></a>", + "<a href=\"#\" contenteditable=\"true\"></a>", + "<a href=\"#\" disabled></a>", + + "<button></button>", + "<button tabindex=\"-1\"></button>", + "<button tabindex=\"0\"></button>", + "<button tabindex=\"1\"></button>", + "<button contenteditable=\"true\"></button>", + + "<button type=\"reset\"></button>", + "<button type=\"reset\" tabindex=\"-1\"></button>", + "<button type=\"reset\" tabindex=\"0\"></button>", + "<button type=\"reset\" tabindex=\"1\"></button>", + "<button type=\"reset\" contenteditable=\"true\"></button>", + + "<button type=\"submit\"></button>", + "<button type=\"submit\" tabindex=\"-1\"></button>", + "<button type=\"submit\" tabindex=\"0\"></button>", + "<button type=\"submit\" tabindex=\"1\"></button>", + "<button type=\"submit\" contenteditable=\"true\"></button>", + + "<div tabindex=\"-1\"></div>", + "<div tabindex=\"0\"></div>", + "<div tabindex=\"1\"></div>", + "<div contenteditable=\"true\"></div>", + "<div tabindex=\"0\" disabled></div>", + + "<embed>", + "<embed tabindex=\"-1\">", + "<embed tabindex=\"0\">", + "<embed tabindex=\"0\" disabled>", + "<embed tabindex=\"1\">", + "<embed disabled>", + "<embed contenteditable=\"true\">", + + "<iframe contenteditable=\"true\"></iframe>", + + "<iframe src=\"about:blank\"></iframe>", + "<iframe src=\"about:blank\" disabled></iframe>", + "<iframe src=\"about:blank\" tabindex=\"-1\"></iframe>", + "<iframe src=\"about:blank\" tabindex=\"0\"></iframe>", + "<iframe src=\"about:blank\" tabindex=\"0\" disabled></iframe>", + "<iframe src=\"about:blank\" tabindex=\"1\"></iframe>", + "<iframe src=\"about:blank\" contenteditable=\"true\"></iframe>", + + "<iframe></iframe>", + "<iframe tabindex=\"-1\"></iframe>", + "<iframe tabindex=\"0\"></iframe>", + "<iframe tabindex=\"0\" disabled></iframe>", + "<iframe tabindex=\"1\"></iframe>", + "<iframe disabled></iframe>", + + "<img tabindex=\"-1\">", + "<img tabindex=\"0\">", + "<img tabindex=\"0\" disabled>", + "<img tabindex=\"1\">", + + "<input>", + "<input tabindex=\"-1\">", + "<input tabindex=\"0\">", + "<input tabindex=\"1\">", + "<input contenteditable=\"true\">", + + "<input type=\"button\">", + "<input type=\"button\" tabindex=\"-1\">", + "<input type=\"button\" tabindex=\"0\">", + "<input type=\"button\" tabindex=\"1\">", + "<input type=\"button\" contenteditable=\"true\">", + + "<input type=\"checkbox\">", + "<input type=\"checkbox\" tabindex=\"-1\">", + "<input type=\"checkbox\" tabindex=\"0\">", + "<input type=\"checkbox\" tabindex=\"1\">", + "<input type=\"checkbox\" contenteditable=\"true\">", + + "<input type=\"image\">", + "<input type=\"image\" tabindex=\"-1\">", + "<input type=\"image\" tabindex=\"0\">", + "<input type=\"image\" tabindex=\"1\">", + "<input type=\"image\" contenteditable=\"true\">", + + "<input type=\"password\">", + "<input type=\"password\" tabindex=\"-1\">", + "<input type=\"password\" tabindex=\"0\">", + "<input type=\"password\" tabindex=\"1\">", + "<input type=\"password\" contenteditable=\"true\">", + + "<input type=\"radio\">", + "<input type=\"radio\" tabindex=\"-1\">", + "<input type=\"radio\" tabindex=\"0\">", + "<input type=\"radio\" tabindex=\"1\">", + "<input type=\"radio\" contenteditable=\"true\">", + "<input type=\"radio\" checked>", + "<form><input type=\"radio\" name=\"foo\"></form>", + + "<input type=\"reset\">", + "<input type=\"reset\" tabindex=\"-1\">", + "<input type=\"reset\" tabindex=\"0\">", + "<input type=\"reset\" tabindex=\"1\">", + "<input type=\"reset\" contenteditable=\"true\">", + + "<input type=\"submit\">", + "<input type=\"submit\" tabindex=\"-1\">", + "<input type=\"submit\" tabindex=\"0\">", + "<input type=\"submit\" tabindex=\"1\">", + "<input type=\"submit\" contenteditable=\"true\">", + + "<input type=\"text\">", + "<input type=\"text\" tabindex=\"-1\">", + "<input type=\"text\" tabindex=\"0\">", + "<input type=\"text\" tabindex=\"1\">", + "<input type=\"text\" contenteditable=\"true\">", + + "<input type=\"number\">", + "<input type=\"number\" tabindex=\"-1\">", + "<input type=\"number\" tabindex=\"0\">", + "<input type=\"number\" tabindex=\"1\">", + "<input type=\"number\" contenteditable=\"true\">", + + "<object tabindex=\"-1\"></object>", + "<object tabindex=\"0\"></object>", + "<object tabindex=\"1\"></object>", + "<object contenteditable=\"true\"></object>", + + "<object classid=\"java:a\"></object>", + "<object classid=\"java:a\" tabindex=\"-1\"></object>", + "<object classid=\"java:a\" tabindex=\"0\"></object>", + "<object classid=\"java:a\" tabindex=\"0\" disabled></object>", + "<object classid=\"java:a\" tabindex=\"1\"></object>", + "<object classid=\"java:a\" disabled></object>", + "<object classid=\"java:a\" contenteditable=\"true\"></object>", + + "<select></select>", + "<select tabindex=\"-1\"></select>", + "<select tabindex=\"0\"></select>", + "<select tabindex=\"1\"></select>", + "<select contenteditable=\"true\"></select>", + + "<option tabindex='-1'></option>", + "<option tabindex='0'></option>", + "<option tabindex='1'></option>", + "<option contenteditable></option>", + + "<optgroup tabindex='-1'></optgroup>", + "<optgroup tabindex='0'></optgroup>", + "<optgroup tabindex='1'></optgroup>", + "<optgroup contenteditable></optgroup>" +]; + +var nonFocusableElements = [ + "<a></a>", + "<a disabled></a>", + + "<button tabindex=\"0\" disabled></button>", + "<button disabled></button>", + + "<button type=\"reset\" tabindex=\"0\" disabled></button>", + "<button type=\"reset\" disabled></button>", + + "<button type=\"submit\" tabindex=\"0\" disabled></button>", + "<button type=\"submit\" disabled></button>", + + "<div></div>", + "<div disabled></div>", + + "<img>", + "<img disabled>", + "<img contenteditable=\"true\">", + + "<img usemap=\"#map\">", + "<img usemap=\"#map\" tabindex=\"-1\">", + "<img usemap=\"#map\" tabindex=\"0\">", + "<img usemap=\"#map\" tabindex=\"0\" disabled>", + "<img usemap=\"#map\" tabindex=\"1\">", + "<img usemap=\"#map\" disabled>", + "<img usemap=\"#map\" contenteditable=\"true\">", + + "<input tabindex=\"0\" disabled>", + "<input disabled>", + + "<input type=\"button\" tabindex=\"0\" disabled>", + "<input type=\"button\" disabled>", + + "<input type=\"checkbox\" tabindex=\"0\" disabled>", + "<input type=\"checkbox\" disabled>", + + "<input type=\"file\" tabindex=\"0\" disabled>", + "<input type=\"file\" disabled>", + + "<input type=\"hidden\">", + "<input type=\"hidden\" tabindex=\"-1\">", + "<input type=\"hidden\" tabindex=\"0\">", + "<input type=\"hidden\" tabindex=\"0\" disabled>", + "<input type=\"hidden\" tabindex=\"1\">", + "<input type=\"hidden\" disabled>", + "<input type=\"hidden\" contenteditable=\"true\">", + + "<input type=\"image\" tabindex=\"0\" disabled>", + "<input type=\"image\" disabled>", + + "<input type=\"password\" tabindex=\"0\" disabled>", + "<input type=\"password\" disabled>", + + "<input type=\"radio\" tabindex=\"0\" disabled>", + "<input type=\"radio\" disabled>", + + "<input type=\"reset\" tabindex=\"0\" disabled>", + "<input type=\"reset\" disabled>", + + "<input type=\"submit\" tabindex=\"0\" disabled>", + "<input type=\"submit\" disabled>", + + "<input type=\"text\" tabindex=\"0\" disabled>", + "<input type=\"text\" disabled>", + + "<object></object>", + + "<select tabindex=\"0\" disabled></select>", + "<select disabled></select>", + + "<option></option>", + "<option tabindex='1' disabled></option>", + + "<optgroup></optgroup>", + "<optgroup tabindex='1' disabled></optgroup>" +]; + +var focusableInContentEditable = [ + "<button></button>", + "<button tabindex=\"-1\"></button>", + "<button tabindex=\"0\"></button>", + "<button tabindex=\"1\"></button>", + "<button contenteditable=\"true\"></button>", + + "<button type=\"reset\"></button>", + "<button type=\"reset\" tabindex=\"-1\"></button>", + "<button type=\"reset\" tabindex=\"0\"></button>", + "<button type=\"reset\" tabindex=\"1\"></button>", + "<button type=\"reset\" contenteditable=\"true\"></button>", + + "<button type=\"submit\"></button>", + "<button type=\"submit\" tabindex=\"-1\"></button>", + "<button type=\"submit\" tabindex=\"0\"></button>", + "<button type=\"submit\" tabindex=\"1\"></button>", + "<button type=\"submit\" contenteditable=\"true\"></button>", + + "<div tabindex=\"-1\"></div>", + "<div tabindex=\"0\"></div>", + "<div tabindex=\"1\"></div>", + "<div tabindex=\"0\" disabled></div>", + + "<embed>", + "<embed tabindex=\"-1\">", + "<embed tabindex=\"0\">", + "<embed tabindex=\"0\" disabled>", + "<embed tabindex=\"1\">", + "<embed disabled>", + "<embed contenteditable=\"true\">", + + "<iframe src=\"about:blank\"></iframe>", + "<iframe></iframe>", + "<iframe src=\"about:blank\" disabled></iframe>", + "<iframe disabled></iframe>", + "<iframe src=\"about:blank\" tabindex=\"-1\"></iframe>", + "<iframe tabindex=\"-1\"></iframe>", + "<iframe src=\"about:blank\" tabindex=\"0\"></iframe>", + "<iframe tabindex=\"0\"></iframe>", + "<iframe src=\"about:blank\" tabindex=\"0\" disabled></iframe>", + "<iframe tabindex=\"0\" disabled></iframe>", + "<iframe src=\"about:blank\" tabindex=\"1\"></iframe>", + "<iframe tabindex=\"1\"></iframe>", + "<iframe src=\"about:blank\" contenteditable=\"true\"></iframe>", + "<iframe contenteditable=\"true\"></iframe>", + + "<img tabindex=\"-1\">", + "<img tabindex=\"0\">", + "<img tabindex=\"0\" disabled>", + "<img tabindex=\"1\">", + + "<input>", + "<input tabindex=\"-1\">", + "<input tabindex=\"0\">", + "<input tabindex=\"1\">", + "<input contenteditable=\"true\">", + + "<input type=\"button\">", + "<input type=\"button\" tabindex=\"-1\">", + "<input type=\"button\" tabindex=\"0\">", + "<input type=\"button\" tabindex=\"1\">", + "<input type=\"button\" contenteditable=\"true\">", + + "<input type=\"file\">", + "<input type=\"file\" tabindex=\"-1\">", + "<input type=\"file\" tabindex=\"0\">", + "<input type=\"file\" tabindex=\"1\">", + "<input type=\"file\" contenteditable=\"true\">", + + "<input type=\"checkbox\">", + "<input type=\"checkbox\" tabindex=\"-1\">", + "<input type=\"checkbox\" tabindex=\"0\">", + "<input type=\"checkbox\" tabindex=\"1\">", + "<input type=\"checkbox\" contenteditable=\"true\">", + + "<input type=\"image\">", + "<input type=\"image\" tabindex=\"-1\">", + "<input type=\"image\" tabindex=\"0\">", + "<input type=\"image\" tabindex=\"1\">", + "<input type=\"image\" contenteditable=\"true\">", + + "<input type=\"password\">", + "<input type=\"password\" tabindex=\"-1\">", + "<input type=\"password\" tabindex=\"0\">", + "<input type=\"password\" tabindex=\"1\">", + "<input type=\"password\" contenteditable=\"true\">", + + "<input type=\"radio\">", + "<input type=\"radio\" tabindex=\"-1\">", + "<input type=\"radio\" tabindex=\"0\">", + "<input type=\"radio\" tabindex=\"1\">", + "<input type=\"radio\" contenteditable=\"true\">", + "<input type=\"radio\" checked>", + "<form><input type=\"radio\" name=\"foo\"></form>", + + "<input type=\"reset\">", + "<input type=\"reset\" tabindex=\"-1\">", + "<input type=\"reset\" tabindex=\"0\">", + "<input type=\"reset\" tabindex=\"1\">", + "<input type=\"reset\" contenteditable=\"true\">", + + "<input type=\"submit\">", + "<input type=\"submit\" tabindex=\"-1\">", + "<input type=\"submit\" tabindex=\"0\">", + "<input type=\"submit\" tabindex=\"1\">", + "<input type=\"submit\" contenteditable=\"true\">", + + "<input type=\"text\">", + "<input type=\"text\" tabindex=\"-1\">", + "<input type=\"text\" tabindex=\"0\">", + "<input type=\"text\" tabindex=\"1\">", + "<input type=\"text\" contenteditable=\"true\">", + + "<input type=\"number\">", + "<input type=\"number\" tabindex=\"-1\">", + "<input type=\"number\" tabindex=\"0\">", + "<input type=\"number\" tabindex=\"1\">", + "<input type=\"number\" contenteditable=\"true\">", + + "<object tabindex=\"-1\"></object>", + "<object tabindex=\"0\"></object>", + "<object tabindex=\"1\"></object>", + + // Disabled doesn't work for <object>. + "<object tabindex=\"0\" disabled></object>", + "<object disabled></object>", + + "<select></select>", + "<select tabindex=\"-1\"></select>", + "<select tabindex=\"0\"></select>", + "<select tabindex=\"1\"></select>", + "<select contenteditable=\"true\"></select>", + + "<option tabindex='-1'></option>", + "<option tabindex='0'></option>", + "<option tabindex='1'></option>", + + "<optgroup tabindex='-1'></optgroup>", + "<optgroup tabindex='0'></optgroup>", + "<optgroup tabindex='1'></optgroup>" +]; + +var focusableInDesignMode = [ + "<embed>", + "<embed tabindex=\"-1\">", + "<embed tabindex=\"0\">", + "<embed tabindex=\"0\" disabled>", + "<embed tabindex=\"1\">", + "<embed disabled>", + "<embed contenteditable=\"true\">", + + "<img tabindex=\"-1\">", + "<img tabindex=\"0\">", + "<img tabindex=\"0\" disabled>", + "<img tabindex=\"1\">", +]; + +// Can't currently test these, need a plugin. +var focusableElementsTODO = [ + "<object classid=\"java:a\"></object>", + "<object classid=\"java:a\" tabindex=\"-1\"></object>", + "<object classid=\"java:a\" tabindex=\"0\"></object>", + "<object classid=\"java:a\" tabindex=\"0\" disabled></object>", + "<object classid=\"java:a\" tabindex=\"1\"></object>", + "<object classid=\"java:a\" disabled></object>", + "<object classid=\"java:a\" contenteditable=\"true\"></object>", +]; + +var serializer = new XMLSerializer(); + +function testElements(parent, tags, shouldBeFocusable) +{ + var focusable, errorSuffix = ""; + if (parent.ownerDocument.designMode == "on") { + focusable = focusableInDesignMode; + errorSuffix = " in a document with designMode=on"; + } + else if (parent.contentEditable == "true") { + focusable = focusableInContentEditable; + } + + for (var tag of tags) { + parent.ownerDocument.body.focus(); + + if (focusableElementsTODO.indexOf(tag) > -1) { + todo_is(parent.ownerDocument.activeElement, parent.firstChild, + tag + " should be focusable" + errorSuffix); + continue; + } + + parent.innerHTML = tag; + + // Focus the deepest descendant. + var descendant = parent; + while ((descendant = descendant.firstChild)) + element = descendant; + + if (element.nodeName == "IFRAME" && element.hasAttribute("src")) + var foo = element.contentDocument; + + element.focus(); + + var errorPrefix = serializer.serializeToString(element) + " in " + + serializer.serializeToString(parent); + + try { + // Make sure activeElement doesn't point to a + // native anonymous element. + parent.ownerDocument.activeElement.localName; + } catch (ex) { + ok(false, ex + errorPrefix + errorSuffix); + } + if (focusable ? focusable.indexOf(tag) > -1 : shouldBeFocusable) { + is(parent.ownerDocument.activeElement, element, + errorPrefix + " should be focusable" + errorSuffix); + } + else { + isnot(parent.ownerDocument.activeElement, element, + errorPrefix + " should not be focusable" + errorSuffix); + } + + parent.innerHTML = ""; + } +} + +function test() +{ + var parent = document.getElementById("parent"); + var editableParent = document.getElementById("editableParent"); + + testElements(parent, focusableElements, true); + testElements(parent, nonFocusableElements, false); + + testElements(editableParent, focusableElements, true); + testElements(editableParent, nonFocusableElements, false); + + var frame = document.getElementById("frame"); + frame.contentDocument.body.innerHTML = document.getElementById("content").innerHTML; + frame.contentDocument.designMode = "on"; + parent = frame.contentDocument.getElementById("parent"); + editableParent = frame.contentDocument.getElementById("editableParent"); + + testElements(parent, focusableElements, false); + testElements(parent, nonFocusableElements, false); + + testElements(editableParent, focusableElements, false); + testElements(editableParent, nonFocusableElements, false); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); +addLoadEvent(SimpleTest.finish); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug430392.html b/dom/html/test/test_bug430392.html new file mode 100644 index 000000000..f483e454d --- /dev/null +++ b/dom/html/test/test_bug430392.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=430392 +--> +<head> + <title>Test for Bug 430392</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430392">Mozilla Bug 430392</a> +<p id="display"></p> +<div id="content"> + <div contenteditable="true" id="edit"> <span contenteditable="false">A</span> ; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span> </div> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 430392 **/ + +function test() { + var edit = document.getElementById("edit"); + var html = edit.innerHTML; + document.getElementById("edit").focus(); + + synthesizeKey("VK_RIGHT", {}); + synthesizeKey("VK_RIGHT", {}); + synthesizeKey("VK_RETURN", {}); + synthesizeKey("VK_RETURN", {}); + synthesizeKey("VK_BACK_SPACE", {}); + synthesizeKey("VK_BACK_SPACE", {}); + + is(edit.innerHTML, html, + "adding and then deleting returns should not change text"); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(test); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug435128.html b/dom/html/test/test_bug435128.html new file mode 100644 index 000000000..9d2c85b03 --- /dev/null +++ b/dom/html/test/test_bug435128.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=435128 +--> +<head> + <title>Test for Bug 435128</title> + <script type="application/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435128">Mozilla Bug 435128</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<iframe id="content" src="data:text/html;charset=utf-8,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%0A%3Ciframe%20id%3D%22a%22%3E%3C/iframe%3E%0A%3Cscript%3E%0Afunction%20doe%28%29%20%7B%0Avar%20x%20%3D%20window.frames%5B0%5D.document%3B%0A%0Avar%20y%3Ddocument.getElementById%28%27a%27%29%3B%0Ay.parentNode.removeChild%28y%29%3B%0A%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0A%7D%0AsetTimeout%28%27doe%28%29%27%2C20%29%3B%0A%3C/script%3E%0A%3C/body%3E%3C/html%3E" style="width: 1000px; height: 200px;"></iframe> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 435128 **/ + +SimpleTest.waitForExplicitFinish(); + +setTimeout(finish, 60000); + +function doe2() { + document.getElementById('content').src = document.getElementById('content').src; +} +setInterval(doe2, 400); + +function finish() +{ + ok(true, "This is a mochikit version of a crash test. To complete is to pass."); + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug441930.html b/dom/html/test/test_bug441930.html new file mode 100644 index 000000000..2a0b18130 --- /dev/null +++ b/dom/html/test/test_bug441930.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=441930 +--> +<head> + <title>Test for Bug 441930</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=441930">Mozilla Bug 441930</a> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 441930: see bug441930_iframe.html **/ + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +<p id="display"> + <iframe src="bug441930_iframe.html"></iframe> +</p> +<div id="content" style="display: none"> +</div> +</body> +</html> + diff --git a/dom/html/test/test_bug442801.html b/dom/html/test/test_bug442801.html new file mode 100644 index 000000000..b04b23ac8 --- /dev/null +++ b/dom/html/test/test_bug442801.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=442801 +--> +<head> + <title>Test for Bug 442801</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=442801">Mozilla Bug 442801</a> +<p id="display"></p> +<div id="content" style="display: none"> + +<div contenteditable="true"> +<p id="ce_true" contenteditable="true">contenteditable true</p> +</div> + +<div contenteditable="true"> +<p id="ce_false" contenteditable="false">contenteditable false</p> +</div> + +<div contenteditable="true"> +<p id="ce_empty" contenteditable="">contenteditable empty</p> +</div> + +<div contenteditable="true"> +<p id="ce_inherit" contenteditable="inherit">contenteditable inherit</p> +</div> + +<div contenteditable="true"> +<p id="ce_none" >contenteditable none</p> +</div> + + + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 442801 **/ + +is(window.getComputedStyle($("ce_true"), null).getPropertyValue("-moz-user-modify"), + "read-write", + "parent contenteditable is true, contenteditable is true; user-modify should be read-write"); +is(window.getComputedStyle($("ce_false"), null).getPropertyValue("-moz-user-modify"), + "read-only", + "parent contenteditable is true, contenteditable is false; user-modify should be read-only"); +is(window.getComputedStyle($("ce_empty"), null).getPropertyValue("-moz-user-modify"), + "read-write", + "parent contenteditable is true, contenteditable is empty; user-modify should be read-write"); +is(window.getComputedStyle($("ce_inherit"), null).getPropertyValue("-moz-user-modify"), + "read-write", + "parent contenteditable is true, contenteditable is inherit; user-modify should be read-write"); +is(window.getComputedStyle($("ce_none"), null).getPropertyValue("-moz-user-modify"), + "read-write", + "parent contenteditable is true, contenteditable is none; user-modify should be read-write"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug445004.html b/dom/html/test/test_bug445004.html new file mode 100644 index 000000000..ec98f56c8 --- /dev/null +++ b/dom/html/test/test_bug445004.html @@ -0,0 +1,138 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=445004 +--> +<head> + <title>Test for Bug 445004</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=445004">Mozilla Bug 445004</a> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 445004 **/ +is(window.location.hostname, "mochi.test", "Unexpected hostname"); +is(window.location.port, "8888", "Unexpected port; fix testcase"); + +SimpleTest.waitForExplicitFinish(); + +var loads = 1; + +function loadStarted() { + ++loads; +} +function loadEnded() { + --loads; + if (loads == 0) { + doTest(); + } +} + +window.onload = loadEnded; + +function getMessage(evt) { + ok(evt.data == "start" || evt.data == "end", "Must have start or end"); + if (evt.data == "start") + loadStarted(); + else + loadEnded(); +} + +window.addEventListener("message", getMessage, false); + +function checkURI(uri, name, type) { + var host = uri.match(/^http:\/\/([a-z.0-9]*)/)[1]; + var file = uri.match(/([^\/]*).png$/)[1]; + is(host, file, "Unexpected base URI for test " + name + + " when testing " + type); +} + +function checkFrame(num) { + // Just snarf our data + var outer = SpecialPowers.wrap(window.frames[num]); + name = outer.name; + + is(outer.document.baseURI, + "http://example.org/tests/dom/html/test/bug445004-outer.html", + "Unexpected base URI for " + name); + + var iswrite = name.match(/write/); + + var inner = outer.frames[0]; + if (iswrite) { + is(inner.document.baseURI, + "http://example.org/tests/dom/html/test/bug445004-outer.html", + "Unexpected inner base URI for " + name); + } else { + is(inner.document.baseURI, + "http://test1.example.org/tests/dom/html/test/bug445004-inner.html", + "Unexpected inner base URI for " + name); + } + + var isrel = name.match(/rel/); + var offsite = name.match(/offsite/); + + if (!iswrite) { + if ((isrel && !offsite) || (!isrel && offsite)) { + is(inner.location.hostname, outer.location.hostname, + "Unexpected hostnames for " + name); + } else { + isnot(inner.location.hostname, outer.location.hostname, + "Unexpected hostnames for " + name); + } + } + + checkURI(inner.frames[0].location.href, name, "direct location"); + checkURI(inner.frames[1].document.getElementsByTagName("img")[0].src, + name, "direct write"); + if (!iswrite) { + is(inner.frames[1].location.hostname, inner.location.hostname, + "Incorrect hostname for " + name + " direct write") + } + checkURI(inner.frames[2].location.href, name, "indirect location"); + checkURI(inner.frames[3].document.getElementsByTagName("img")[0].src, + name, "indirect write"); + if (!iswrite) { + is(inner.frames[3].location.hostname, outer.location.hostname, + "Incorrect hostname for " + name + " indirect write") + } + checkURI(inner.document.getElementsByTagName("img")[0].src, + name, "direct image load"); +} + + +function doTest() { + for (var num = 0; num < 5; ++num) { + checkFrame(num); + } + + SimpleTest.finish(); +} + +</script> +</pre> +<p id="display"> + <iframe + src="http://example.org/tests/dom/html/test/bug445004-outer-rel.html" + name="bug445004-outer-rel.html"></iframe> + <iframe + src="http://test1.example.org/tests/dom/html/test/bug445004-outer-rel.html" + name="bug445004-outer-rel.html offsite"></iframe> + <iframe + src="http://example.org/tests/dom/html/test/bug445004-outer-abs.html" + name="bug445004-outer-abs.html"></iframe> + <iframe + src="http://test1.example.org/tests/dom/html/test/bug445004-outer-abs.html" + name="bug445004-outer-abs.html offsite"></iframe> + <iframe + src="http://example.org/tests/dom/html/test/bug445004-outer-write.html" + name="bug445004-outer-write.html"></iframe> +</p> +</body> +</html> diff --git a/dom/html/test/test_bug446483.html b/dom/html/test/test_bug446483.html new file mode 100644 index 000000000..def6553d5 --- /dev/null +++ b/dom/html/test/test_bug446483.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=446483 +--> +<head> + <title>Test for Bug 446483</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=446483">Mozilla Bug 446483</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 446483 **/ + +function gc() { + SpecialPowers.gc(); +} + +function runTest() { + document.getElementById('display').innerHTML = + '<iframe src="bug446483-iframe.html"><\/iframe>\n' + + '<iframe src="bug446483-iframe.html"><\/iframe>\n'; + + setInterval(gc, 1000); + + setTimeout(function() { + document.getElementById('display').innerHTML = ''; + ok(true, ''); + SimpleTest.finish(); + }, 4000); +} + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +addLoadEvent(runTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug448166.html b/dom/html/test/test_bug448166.html new file mode 100644 index 000000000..ec4b3d1a4 --- /dev/null +++ b/dom/html/test/test_bug448166.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=448166 +--> +<head> + <title>Test for Bug 448166</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448166">Mozilla Bug 448166</a> +<p id="display"> + <a id="test" href="http://www.moz�illa.org">should not be Mozilla</a> + <a id="control" href="http://www.mozilla.org">should not be Mozilla</a> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 448166 **/ +isnot($("test").href, "http://www.mozilla.org/", + "Should notice unpaired surrogate"); +is($("test").href, "http://www.xn--mozilla-2e14b.org/", + "Should replace unpaired surrogate with replacement char"); +is($("control").href, "http://www.mozilla.org/", + "Just making sure .href works"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug448564.html b/dom/html/test/test_bug448564.html new file mode 100644 index 000000000..27d5a272f --- /dev/null +++ b/dom/html/test/test_bug448564.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=448564 +--> +<head> + <title>Test for Bug 448564</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448564">Mozilla Bug 448564</a> +<p id="display"> + <iframe src="bug448564-iframe-1.html"></iframe> + <iframe src="bug448564-iframe-2.html"></iframe> + <iframe src="bug448564-iframe-3.html"></iframe> +</p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 448564 **/ + +/** + * The three iframes are going to be loaded with some dirty constructed forms. + * Each of them will be submitted before the load event and a SJS will replace + * the frame content with the query string. + * Then, on the load event, our test file will check the content of each iframes + * and check if the query string were correctly formatted (implying that all + * iframes were correctly submitted. + */ + +function checkQueryString(frame) { + var queryString = frame.document.body.textContent; + is(queryString.split("&").sort().join("&"), + "a=aval&b=bval&c=cval&d=dval", + "Not all form fields were properly submitted."); +} + +SimpleTest.waitForExplicitFinish(); + +addLoadEvent(function() { + checkQueryString(frames[0]); + checkQueryString(frames[1]); + checkQueryString(frames[2]); + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug456229.html b/dom/html/test/test_bug456229.html new file mode 100644 index 000000000..bc12523c7 --- /dev/null +++ b/dom/html/test/test_bug456229.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=456229 +--> +<head> + <title>Test for Bug 456229</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=456229">Mozilla Bug 456229</a> +<p id="display"></p> +<div id="content" style="display: none"> + <input id='i' type="search"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 456229 **/ + +// More checks are done in test_bug551670.html. + +var i = document.getElementById('i'); +is(i.type, 'search', "Search state should be recognized"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug458037.xhtml b/dom/html/test/test_bug458037.xhtml new file mode 100644 index 000000000..965db499c --- /dev/null +++ b/dom/html/test/test_bug458037.xhtml @@ -0,0 +1,112 @@ +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=458037 +--> +<head> + <title>Test for Bug 458037</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=458037">Mozilla Bug 458037</a> +<p id="display"></p> +<div id="content" > +<div id="a"></div> +<div id="b" contenteditable="true"></div> +<div id="c" contenteditable="false"></div> +<div id="d" contenteditable="inherit"></div> +<div contenteditable="true"> + <div id="e"></div> +</div> +<div contenteditable="false"> + <div id="f"></div> +</div> +<div contenteditable="true"> + <div id="g" contenteditable="false"></div> +</div> +<div contenteditable="false"> + <div id="h" contenteditable="true"></div> +</div> +<div contenteditable="true"> + <div id="i" contenteditable="inherit"></div> +</div> +<div contenteditable="false"> + <div id="j" contenteditable="inherit"></div> +</div> +<div contenteditable="true"> + <xul:box> + <div id="k"></div> + </xul:box> +</div> +<div contenteditable="false"> + <xul:box> + <div id="l"></div> + </xul:box> +</div> +<div contenteditable="true"> + <xul:box> + <div id="m" contenteditable="inherit"></div> + </xul:box> +</div> +<div contenteditable="false"> + <xul:box> + <div id="n" contenteditable="inherit"></div> + </xul:box> +</div> +<div id="x"></div> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 458037 **/ + +function test(id, expected) { + is(document.getElementById(id).isContentEditable, expected, + "Element " + id + " should " + (expected ? "" : "not ") + "be editable"); +} + +document.addEventListener("DOMContentLoaded", function() { + test("a", false); + test("b", true); + test("c", false); + test("d", false); + test("e", true); + test("f", false); + test("g", false); + test("h", true); + test("i", true); + test("j", false); + test("k", true); + test("l", false); + test("m", true); + test("n", false); + + var d = document.getElementById("x"); + test("x", false); + d.setAttribute("contenteditable", "true"); + test("x", true); + d.setAttribute("contenteditable", "false"); + test("x", false); + d.setAttribute("contenteditable", "inherit"); + test("x", false); + d.removeAttribute("contenteditable"); + test("x", false); + d.contentEditable = "true"; + test("x", true); + d.contentEditable = "false"; + test("x", false); + d.contentEditable = "inherit"; + test("x", false); + + // Make sure that isContentEditable is read-only + var origValue = d.isContentEditable; + d.isContentEditable = !origValue; + is(d.isContentEditable, origValue, "isContentEditable should be read only"); +}, false); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug460568.html b/dom/html/test/test_bug460568.html new file mode 100644 index 000000000..14bcbbc78 --- /dev/null +++ b/dom/html/test/test_bug460568.html @@ -0,0 +1,147 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=460568 +--> +<head> + <title>Test for Bug 460568</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=460568">Mozilla Bug 460568</a> +<p id="display"><a href="" id="anchor">a[href]</a></p> +<div id="editor"> + <a href="" id="anchorInEditor">a[href] in editor</a> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 460568 **/ + +function runTest() +{ + var editor = document.getElementById("editor"); + var anchor = document.getElementById("anchor"); + var anchorInEditor = document.getElementById("anchorInEditor"); + + var focused; + anchorInEditor.onfocus = function() { focused = true; }; + + function isReallyEditable() + { + editor.focus(); + var range = document.createRange(); + range.selectNodeContents(editor); + var prevStr = range.toString(); + + var docShell = SpecialPowers.wrap(window) + .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor) + .getInterface(SpecialPowers.Ci.nsIWebNavigation) + .QueryInterface(SpecialPowers.Ci.nsIDocShell); + var controller = + docShell.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor) + .getInterface(SpecialPowers.Ci.nsISelectionDisplay) + .QueryInterface(SpecialPowers.Ci.nsISelectionController); + var sel = controller.getSelection(controller.SELECTION_NORMAL); + sel.collapse(anchorInEditor, 0); + synthesizeKey('a', {}); + range.selectNodeContents(editor); + return prevStr != range.toString(); + } + + focused = false; + anchor.focus(); + editor.setAttribute("contenteditable", "true"); + anchorInEditor.focus(); + is(focused, false, "focus moved to element in contenteditable=true"); + is(isReallyEditable(), true, "cannot edit by a key event"); + + // for bug 502273 + focused = false; + anchor.focus(); + editor.setAttribute("dummy", "dummy"); + editor.removeAttribute("dummy"); + anchorInEditor.focus(); + is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)"); + is(isReallyEditable(), true, "cannot edit by a key event"); + + focused = false; + anchor.focus(); + editor.setAttribute("contenteditable", "false"); + anchorInEditor.focus(); + is(focused, true, "focus didn't move to element in contenteditable=false"); + is(isReallyEditable(), false, "can edit by a key event"); + + // for bug 502273 + focused = false; + anchor.focus(); + editor.setAttribute("dummy", "dummy"); + editor.removeAttribute("dummy"); + anchorInEditor.focus(); + is(focused, true, "focus moved to element in contenteditable=true (after dummy attribute was removed)"); + is(isReallyEditable(), false, "cannot edit by a key event"); + + focused = false; + anchor.focus(); + editor.setAttribute("contenteditable", "true"); + anchorInEditor.focus(); + is(focused, false, "focus moved to element in contenteditable=true"); + is(isReallyEditable(), true, "cannot edit by a key event"); + + // for bug 502273 + focused = false; + anchor.focus(); + editor.setAttribute("dummy", "dummy"); + editor.removeAttribute("dummy"); + anchorInEditor.focus(); + is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)"); + is(isReallyEditable(), true, "cannot edit by a key event"); + + focused = false; + anchor.focus(); + editor.removeAttribute("contenteditable"); + anchorInEditor.focus(); + is(focused, true, "focus didn't move to element in contenteditable removed element"); + is(isReallyEditable(), false, "can edit by a key event"); + + focused = false; + anchor.focus(); + editor.contentEditable = true; + anchorInEditor.focus(); + is(focused, false, "focus moved to element in contenteditable=true by property"); + is(isReallyEditable(), true, "cannot edit by a key event"); + + focused = false; + anchor.focus(); + editor.contentEditable = false; + anchorInEditor.focus(); + is(focused, true, "focus didn't move to element in contenteditable=false by property"); + is(isReallyEditable(), false, "can edit by a key event"); + + focused = false; + anchor.focus(); + editor.setAttribute("contenteditable", "true"); + anchorInEditor.focus(); + is(focused, false, "focus moved to element in contenteditable=true"); + is(isReallyEditable(), true, "cannot edit by a key event"); + + // for bug 502273 + focused = false; + anchor.focus(); + editor.setAttribute("dummy", "dummy"); + editor.removeAttribute("dummy"); + anchorInEditor.focus(); + is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)"); + is(isReallyEditable(), true, "cannot edit by a key event"); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTest); +addLoadEvent(SimpleTest.finish); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug463104.html b/dom/html/test/test_bug463104.html new file mode 100644 index 000000000..f424cd183 --- /dev/null +++ b/dom/html/test/test_bug463104.html @@ -0,0 +1,25 @@ +<!DOCTYPE html>
+<html>
+<head>
+<title>Noninteger coordinates test</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<div id="a" style="position: fixed; left: 5.5px; top: 5.5px; width: 100px; height: 100px; background: blue"></div>
+<p style="margin-top: 110px">
+<script>
+var a = document.getElementById("a");
+isnot(a, document.elementFromPoint(5, 5), "a shouldn't be found");
+isnot(a, document.elementFromPoint(5.25, 5.25), "a shouldn't be found");
+is(a, document.elementFromPoint(5.5, 5.5), "a should be found");
+is(a, document.elementFromPoint(5.75, 5.75), "a should be found");
+is(a, document.elementFromPoint(6, 6), "a should be found");
+is(a, document.elementFromPoint(105, 105), "a should be found");
+is(a, document.elementFromPoint(105.25, 105.25), "a should be found");
+isnot(a, document.elementFromPoint(105.5, 105.5), "a shouldn't be found");
+isnot(a, document.elementFromPoint(105.75, 105.75), "a shouldn't be found");
+isnot(a, document.elementFromPoint(106, 106), "a shouldn't be found");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug478251.html b/dom/html/test/test_bug478251.html new file mode 100644 index 000000000..537ccf12e --- /dev/null +++ b/dom/html/test/test_bug478251.html @@ -0,0 +1,74 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=478251 +--> +<head> + <title>Test for Bug 478251</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=478251">Mozilla Bug 478251</a> +<p id="display"><iframe id="t"></iframe></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 478251 **/ +var doc = $("t").contentDocument; +doc.open(); +doc.write(); +doc.close(); +is(doc.documentElement.textContent, "", "Writing || failed"); + +doc.open(); +doc.write(null); +doc.close(); +is(doc.documentElement.textContent, "null", "Writing |null| failed"); + +doc.open(); +doc.write(null, null); +doc.close(); +is(doc.documentElement.textContent, "nullnull", "Writing |null, null| failed"); + +doc.open(); +doc.write(undefined); +doc.close(); +is(doc.documentElement.textContent, "undefined", "Writing |undefined| failed"); + +doc.open(); +doc.write(undefined, undefined); +doc.close(); +is(doc.documentElement.textContent, "undefinedundefined", "Writing |undefined, undefined| failed"); + +doc.open(); +doc.writeln(); +doc.close(); +ok(doc.documentElement.textContent == "\n" || doc.documentElement.textContent == "", "Writing |\\n| failed"); + +doc.open(); +doc.writeln(null); +doc.close(); +is(doc.documentElement.textContent, "null\n", "Writing |null\\n| failed"); + +doc.open(); +doc.writeln(null, null); +doc.close(); +is(doc.documentElement.textContent, "nullnull\n", "Writing |null, null\\n| failed"); + +doc.open(); +doc.writeln(undefined); +doc.close(); +is(doc.documentElement.textContent, "undefined\n", "Writing |undefined\\n| failed"); + +doc.open(); +doc.writeln(undefined, undefined); +doc.close(); +is(doc.documentElement.textContent, "undefinedundefined\n", "Writing |undefined, undefined\\n| failed"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug481335.xhtml b/dom/html/test/test_bug481335.xhtml new file mode 100644 index 000000000..f8a51df69 --- /dev/null +++ b/dom/html/test/test_bug481335.xhtml @@ -0,0 +1,120 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=481335 +--> +<head> + <title>Test for Bug 481335</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style type="text/css"> + a { color:blue; } + a:visited { color:red; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481335">Mozilla Bug 481335</a> +<p id="display"> + <a id="t">A link</a> + <iframe id="i"></iframe> +</p> +<p id="newparent" xml:base="http://www.example.com/"></p> +<div id="content" style="display: none"></div> +<pre id="test"> +<script type="application/javascript;version=1.7"> +<![CDATA[ + +/** Test for Bug 481335 **/ +SimpleTest.waitForExplicitFinish(); +var rand = Date.now() + "-" + Math.random(); + +is($("t").href, "", + "Unexpected href before set"); +is($("t").href, "", + "Unexpected cached href before set"); + +$("t").setAttribute("href", rand); +is($("t").href, + window.location.href.replace(/test_bug481335.xhtml([\?].*)?/, rand), + "Unexpected href after set"); +is($("t").href, + window.location.href.replace(/test_bug481335.xhtml([\?].*)?/, rand), + "Unexpected cached href after set"); +const unvisitedColor = "rgb(0, 0, 255)"; +const visitedColor = "rgb(255, 0, 0)"; + +let tests = testIterator(); +function continueTest() { + tests.next(); +} + +function checkLinkColor(aElmId, aExpectedColor, aMessage) { + // Because link coloring is asynchronous, we wait until we get the right + // result, or we will time out (resulting in a failure). + function getColor() { + var utils = SpecialPowers.getDOMWindowUtils(window); + return utils.getVisitedDependentComputedStyle($(aElmId), "", "color"); + } + while (getColor() != aExpectedColor) { + setTimeout(continueTest, 0); + return false; + } + is(getColor(), aExpectedColor, aMessage); + return true; +} + +function testIterator() { + // After first load + $("newparent").appendChild($("t")); + is($("t").href, "http://www.example.com/" + rand, + "Unexpected href after move"); + is($("t").href, "http://www.example.com/" + rand, + "Unexpected cached href after move"); + while (!checkLinkColor("t", unvisitedColor, "Should be unvisited now")) + yield undefined; + + $("i").src = $("t").href; + yield undefined; + + // After second load + while (!checkLinkColor("t", visitedColor, "Should be visited now")) + yield undefined; + $("t").pathname = rand; + while (!checkLinkColor("t", visitedColor, + "Should still be visited after setting pathname to its existing value")) { + yield undefined; + } + /* TODO uncomment this test with the landing of bug 534526. See + * https://bugzilla.mozilla.org/show_bug.cgi?id=461199#c167 + $("t").pathname += "x"; + while (!checkLinkColor("t", unvisitedColor, + "Should not be visited after changing pathname")) { + yield undefined; + } + $("t").pathname = $("t").pathname; + while (!checkLinkColor("t", unvisitedColor, + "Should not be visited after setting unvisited pathname to existing value")) { + yield undefined; + } + */ + + $("i").src = $("t").href; + yield undefined; + + // After third load + while (!checkLinkColor("t", visitedColor, + "Should be visited now after third load")) { + yield undefined; + } + SimpleTest.finish(); + yield undefined; +} + +addLoadEvent(function() { + $("i").onload = continueTest; + $("i").src = $("t").href; +}); +]]> +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug481440.html b/dom/html/test/test_bug481440.html new file mode 100644 index 000000000..b6b454232 --- /dev/null +++ b/dom/html/test/test_bug481440.html @@ -0,0 +1,30 @@ +<!--Test must be in quirks mode for document.all to work--> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=481440 +--> +<head> + <title>Test for Bug 481440</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481440">Mozilla Bug 481440</a> +<p id="display"></p> +<div id="content" style="display: none"> + <input name="x" id="y"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 481440 **/ +// Do a bunch of getElementById calls to catch hashtables auto-going live +for (var i = 0; i < 500; ++i) { + document.getElementById(i); +} +is(document.all["x"], document.getElementById("y"), + "Unexpected node"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug481647.html b/dom/html/test/test_bug481647.html new file mode 100644 index 000000000..24928bbf7 --- /dev/null +++ b/dom/html/test/test_bug481647.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=481647 +--> +<head> + <title>Test for Bug 481647</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481647">Mozilla Bug 481647</a> +<p id="display"> + <iframe src="javascript:'aaa'"></iframe> + <iframe src="javascript:document.write('aaa'); document.close();"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 481647 **/ +SimpleTest.waitForExplicitFinish() + +function testFrame(num) { + is(window.frames[num].document.baseURI, document.baseURI, + "Unexpected base URI in frame " + num); +} + +addLoadEvent(function() { + for (var i = 0; i < 2; ++i) { + testFrame(i); + } + + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug482659.html b/dom/html/test/test_bug482659.html new file mode 100644 index 000000000..2329ae999 --- /dev/null +++ b/dom/html/test/test_bug482659.html @@ -0,0 +1,64 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=482659 +--> +<head> + <title>Test for Bug 482659</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=482659">Mozilla Bug 482659</a> +<p id="display"> + <iframe></iframe> + <iframe src="about:blank"></iframe> + <iframe></iframe> + <iframe src="about:blank"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 482659 **/ +SimpleTest.waitForExplicitFinish() + +function testFrame(num) { + is(window.frames[num].document.baseURI, document.baseURI, + "Unexpected base URI in frame " + num); + is(window.frames[num].document.documentURI, "about:blank", + "Unexpected document URI in frame " + num); +} + +function appendScript(doc) { + var s = doc.createElement("script"); + s.textContent = "document.write('executed'); document.close()"; + doc.body.appendChild(s); +} + +function verifyScriptRan(num) { + is(window.frames[num].document.documentElement.textContent, "executed", + "write didn't happen in frame " + num); +} + +addLoadEvent(function() { +/* document.write part of test disabled due to bug 483818 + appendScript(window.frames[2].document); + appendScript(window.frames[3].document); + + verifyScriptRan(2); + verifyScriptRan(3); +*/ + for (var i = 0; i < 4; ++i) { + testFrame(i); + } + + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug486741.html b/dom/html/test/test_bug486741.html new file mode 100644 index 000000000..69b1e2265 --- /dev/null +++ b/dom/html/test/test_bug486741.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=486741 +--> +<head> + <title>Test for Bug 486741</title> + <script type="application/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=486741">Mozilla Bug 486741</a> +<p id="display"><iframe id="f"></iframe></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 486741 **/ +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + var d = $("f").contentDocument; + var root = d.documentElement; + is(root.tagName, "HTML", "Unexpected root"); + + d.open(); + isnot(d.documentElement, root, "Shouldn't have the old root element"); + + d.write("Test"); + d.close(); + + isnot(d.documentElement, root, "Still shouldn't have the old root element"); + is(d.documentElement.tagName, "HTML", "Unexpected new root after write"); + + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug489532.html b/dom/html/test/test_bug489532.html new file mode 100644 index 000000000..ac28c3548 --- /dev/null +++ b/dom/html/test/test_bug489532.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=489532 +--> +<head> + <title>Test for Bug 489532</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=489532">Mozilla Bug 489532</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script> +/** Test for Bug 489532 **/ +try { + document.createElement("<div>"); + ok(false, "Should throw.") +} catch (e) { + is(e.name, "InvalidCharacterError", + "Expected InvalidCharacterError."); + ok(e instanceof DOMException, "Expected DOMException."); + is(e.code, DOMException.INVALID_CHARACTER_ERR, + "Expected INVALID_CHARACTER_ERR."); +} +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug497242.xhtml b/dom/html/test/test_bug497242.xhtml new file mode 100644 index 000000000..ba3965ee2 --- /dev/null +++ b/dom/html/test/test_bug497242.xhtml @@ -0,0 +1,41 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=497242 +--> +<head> + <title>Test for Bug 497242</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=497242">Mozilla Bug 497242</a> +<p id="display"></p> +<div id="content" style="display: none"> + <form name="foo"/> + <form name="foo"/> + <form name="bar"/> + <form name="bar" xmlns=""/> +</div> +<pre id="test"> +<script type="application/javascript"> +<![CDATA[ + +/** Test for Bug 497242 **/ +is(document.getElementsByName("foo").length, 2, + "Should find both forms with name 'foo'"); +is(document.getElementsByName("foo")[0], + document.getElementsByTagName("form")[0], + "Unexpected first foo"); +is(document.getElementsByName("foo")[1], + document.getElementsByTagName("form")[1], + "Unexpected second foo"); +is(document.getElementsByName("bar").length, 1, + "Should find only the HTML form with name 'bar'"); +is(document.getElementsByName("bar")[0], + document.getElementsByTagName("form")[2], + "Unexpected bar"); +]]> +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug499092.html b/dom/html/test/test_bug499092.html new file mode 100644 index 000000000..d09dcb830 --- /dev/null +++ b/dom/html/test/test_bug499092.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=499092 +--> +<head> + <title>Test for Bug 499092</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=499092">Mozilla Bug 499092</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for Bug 499092 **/ +SimpleTest.waitForExplicitFinish(); +var content = document.getElementById("content"); + +function testHtml() { + is(this.contentDocument.title, "HTML OK"); + SimpleTest.finish(); +} + +function testXml() { + is(this.contentDocument.title, "XML OK"); + var iframeHtml = document.createElement("iframe"); + iframeHtml.onload = testHtml; + iframeHtml.src = "bug499092.html"; + content.appendChild(iframeHtml); +} + +var iframeXml = document.createElement("iframe"); +iframeXml.onload = testXml; +iframeXml.src = "bug499092.xml"; +content.appendChild(iframeXml); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug500885.html b/dom/html/test/test_bug500885.html new file mode 100644 index 000000000..3e7b24883 --- /dev/null +++ b/dom/html/test/test_bug500885.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=500885 +--> +<head> + <title>Test for Bug 500885</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=500885">Mozilla Bug 500885</a> +<div> + <input id="file" type="file" /> +</div> +<script type="text/javascript"> + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); +MockFilePicker.returnValue = MockFilePicker.returnOK; + +function test() { + // SpecialPowers.DOMWindowUtils doesn't appear to fire mouseEvents correctly + var wu = SpecialPowers.getDOMWindowUtils(window); + + try { + var domActivateEvents; + var fileInput = document.getElementById("file"); + var rect = fileInput.getBoundingClientRect(); + + fileInput.addEventListener ("DOMActivate", function (e) { + ok("detail" in e, "DOMActivate should have .detail"); + is(e.detail, 1, ".detail should be 1"); + domActivateEvents++; + }, false); + + domActivateEvents = 0; + wu.sendMouseEvent("mousedown", rect.left + 5, rect.top + 5, 0, 1, 0); + wu.sendMouseEvent("mouseup", rect.left + 5, rect.top + 5, 0, 1, 0); + is(domActivateEvents, 1, "click on button should fire 1 DOMActivate event"); + + domActivateEvents = 0; + wu.sendMouseEvent("mousedown", rect.right - 5, rect.top + 5, 0, 1, 0); + wu.sendMouseEvent("mouseup", rect.right - 5, rect.top + 5, 0, 1, 0); + is(domActivateEvents, 1, "click on text field should fire 1 DOMActivate event"); + + } finally { + SimpleTest.executeSoon(function() { + MockFilePicker.cleanup(); + SimpleTest.finish(); + }); + } +} + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(test); + +</script> +</body> + +</html> diff --git a/dom/html/test/test_bug512367.html b/dom/html/test/test_bug512367.html new file mode 100644 index 000000000..be10345a9 --- /dev/null +++ b/dom/html/test/test_bug512367.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=512367 +--> +<head> + <title>Test for Bug 512367</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=512367">Mozilla Bug 512367</a> +<p id="display"> + <iframe src="bug369370-popup.png" id="i" style="width:200px; height:200px"></iframe> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +var frame = document.getElementById("i"); + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + var viewer = + SpecialPowers.wrap(frame.contentWindow) + .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor) + .getInterface(SpecialPowers.Ci.nsIWebNavigation) + .QueryInterface(SpecialPowers.Ci.nsIDocShell) + .contentViewer; + + viewer.fullZoom = 1.5; + + setTimeout(function() { + synthesizeMouse(frame, 30, 30, {}); + + is(viewer.fullZoom, 1.5, "Zoom in the image frame should not have been reset"); + + SimpleTest.finish(); + }, 0); +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug514856.html b/dom/html/test/test_bug514856.html new file mode 100644 index 000000000..50617bbba --- /dev/null +++ b/dom/html/test/test_bug514856.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=514856 +--> +<head> + <title>Test for Bug 514856</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=514856">Mozilla Bug 514856</a> +<p id="display"></p> +<div id="content"> + <iframe id="testFrame" src="bug514856_iframe.html"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 514856 **/ + +function beginTest() { + var ifr = document.getElementById("testFrame"); + var win = ifr.contentWindow; + + // After the click, the load event should be fired. + ifr.addEventListener('load', function() { + testDone(); + }, false); + + // synthesizeMouse adds getBoundingClientRect left and top to the offsets but + // in that particular case, we don't want that. + var rect = ifr.getBoundingClientRect(); + var left = rect.left; + var top = rect.top; + + synthesizeMouse(ifr, 10 - left, 10 - top, { type: "mousemove" }, win); + synthesizeMouse(ifr, 12 - left, 12 - top, { type: "mousemove" }, win); + synthesizeMouse(ifr, 14 - left, 14 - top, { type: "mousemove" }, win); + synthesizeMouse(ifr, 16 - left, 16 - top, { }, win); +} + +function testDone() { + var ifr = document.getElementById("testFrame"); + var url = new String(ifr.contentWindow.location); + + is(url.indexOf("?10,10"), -1, "Shouldn't have ?10,10 in the URL!"); + is(url.indexOf("?12,12"), -1, "Shouldn't have ?12,12 in the URL!"); + is(url.indexOf("?14,14"), -1, "Shouldn't have ?14,14 in the URL!"); + isnot(url.indexOf("?16,16"), -1, "Should have ?16,16 in the URL!"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(beginTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug518122.html b/dom/html/test/test_bug518122.html new file mode 100644 index 000000000..66e9a95a3 --- /dev/null +++ b/dom/html/test/test_bug518122.html @@ -0,0 +1,126 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=518122 +--> +<head> + <title>Test for Bug 518122</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=518122">Mozilla Bug 518122</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 518122 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTests); + +var simple_tests = [ ["foo", "foo"], + ["", ""], + [null, ""], + [undefined , "undefined"], + ["\n", "\n"], + ["\r", "\n"], + ["\rfoo", "\nfoo"], + ["foo\r", "foo\n"], + ["foo\rbar", "foo\nbar"], + ["foo\rbar\r", "foo\nbar\n"], + ["\r\n", "\n"], + ["\r\nfoo", "\nfoo"], + ["foo\r\n", "foo\n"], + ["foo\r\nbar", "foo\nbar"], + ["foo\r\nbar\r\n", "foo\nbar\n"] ]; + +var value_append_tests = [ ["foo", "bar", "foobar"], + ["foo", "foo", "foofoo"], + ["foobar", "bar", "foobarbar"], + ["foobar", "foo", "foobarfoo"], + ["foo\n", "foo", "foo\nfoo"], + ["foo\r", "foo", "foo\nfoo"], + ["foo\r\n", "foo", "foo\nfoo"], + ["\n", "\n", "\n\n"], + ["\r", "\r", "\n\n"], + ["\r\n", "\r\n", "\n\n"], + ["\r", "\r\n", "\n\n"], + ["\r\n", "\r", "\n\n"], + [null, null, "null"], + [null, undefined, "undefined"], + ["", "", ""] + ]; + + +var simple_tests_for_input = [ ["foo", "foo"], + ["", ""], + [null, ""], + [undefined , "undefined"], + ["\n", ""], + ["\r", ""], + ["\rfoo", "foo"], + ["foo\r", "foo"], + ["foo\rbar", "foobar"], + ["foo\rbar\r", "foobar"], + ["\r\n", ""], + ["\r\nfoo", "foo"], + ["foo\r\n", "foo"], + ["foo\r\nbar", "foobar"], + ["foo\r\nbar\r\n", "foobar"] ]; + +var value_append_tests_for_input = [ ["foo", "bar", "foobar"], + ["foo", "foo", "foofoo"], + ["foobar", "bar", "foobarbar"], + ["foobar", "foo", "foobarfoo"], + ["foo\n", "foo", "foofoo"], + ["foo\r", "foo", "foofoo"], + ["foo\r\n", "foo", "foofoo"], + ["\n", "\n", ""], + ["\r", "\r", ""], + ["\r\n", "\r\n", ""], + ["\r", "\r\n", ""], + ["\r\n", "\r", ""], + [null, null, "null"], + [null, undefined, "undefined"], + ["", "", ""] + ]; +function runTestsFor(el, simpleTests, appendTests) { + for(var i = 0; i < simpleTests.length; ++i) { + el.value = simpleTests[i][0]; + is(el.value, simpleTests[i][1], "Wrong value (wrap=" + el.getAttribute('wrap') + ", simple_test=" + i + ")"); + } + for (var j = 0; j < appendTests.length; ++j) { + el.value = appendTests[j][0]; + el.value += appendTests[j][1]; + is(el.value, appendTests[j][2], "Wrong value (wrap=" + el.getAttribute('wrap') + ", value_append_test=" + j + ")"); + } +} + +function runTests() { + var textareas = document.getElementsByTagName("textarea"); + for (var i = 0; i < textareas.length; ++i) { + runTestsFor(textareas[i], simple_tests, value_append_tests); + } + var input = document.getElementsByTagName("input")[0]; + runTestsFor(input, simple_tests_for_input, value_append_tests_for_input); + // initialize the editor + input.focus(); + input.blur(); + runTestsFor(input, simple_tests_for_input, value_append_tests_for_input); + SimpleTest.finish(); +} + + +</script> +</pre> +<textarea cols="30" rows="7" wrap="none"></textarea> +<textarea cols="30" rows="7" wrap="off"></textarea><br> +<textarea cols="30" rows="7" wrap="soft"></textarea> +<textarea cols="30" rows="7" wrap="hard"></textarea> +<input type="text"> +</body> +</html> diff --git a/dom/html/test/test_bug519987.html b/dom/html/test/test_bug519987.html new file mode 100644 index 000000000..a10d5e0b8 --- /dev/null +++ b/dom/html/test/test_bug519987.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=519987 +--> +<head> + <title>Test for Bug 519987</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=519987">Mozilla Bug 519987</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 519987 **/ +var xmlns = 'http://www.w3.org/1999/xhtml'; +is((new Image()).namespaceURI, xmlns, "Unexpected namespace for new Image()"); +is((new Audio()).namespaceURI, xmlns, "Unexpected namespace for new Audio()"); +var titles = document.getElementsByTagName("title"); +var t = titles[0]; +t.parentNode.removeChild(t); +document.title = "abcdefg"; +is(titles[0].namespaceURI, xmlns, "Unexpected namespace for new <title>"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug523771.html b/dom/html/test/test_bug523771.html new file mode 100644 index 000000000..80527ff93 --- /dev/null +++ b/dom/html/test/test_bug523771.html @@ -0,0 +1,106 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=523771 +--> +<head> + <title>Test for Bug 523771</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=523771">Mozilla Bug 523771</a> +<p id="display"></p> +<iframe name="target_iframe" id="target_iframe"></iframe> +<form action="form_submit_server.sjs" target="target_iframe" id="form" +method="POST" enctype="multipart/form-data"> + <input id=singleFile name=singleFile type=file> + <input id=multiFile name=multiFile type=file multiple> +</form> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +singleFileInput = document.getElementById('singleFile'); +multiFileInput = document.getElementById('multiFile'); +var input1File = { name: "523771_file1", type: "", body: "file1 contents"}; +var input2Files = + [{ name: "523771_file2", type: "", body: "second file contents" }, + { name: "523771_file3.txt", type: "text/plain", body: "123456" }, + { name: "523771_file4.html", type: "text/html", body: "<html>content</html>" } + ]; + +SimpleTest.waitForExplicitFinish(); + +function setFileInputs () { + var f = createFileWithData(input1File.name, input1File.body, input1File.type); + SpecialPowers.wrap(singleFileInput).mozSetFileArray([f]); + + var input2FileNames = []; + for (file of input2Files) { + f = createFileWithData(file.name, file.body, file.type); + input2FileNames.push(f); + } + SpecialPowers.wrap(multiFileInput).mozSetFileArray(input2FileNames); +} + +function createFileWithData(fileName, fileData, fileType) { + return new File([fileData], fileName, { type: fileType }); +} + +function cleanupFiles() { + singleFileInput.value = ""; + multiFileInput.value = ""; +} + +is(singleFileInput.files.length, 0, "single-file .files.length"); // bug 524421 +is(multiFileInput.files.length, 0, "multi-file .files.length"); // bug 524421 + +setFileInputs(); + +is(singleFileInput.multiple, false, "single-file input .multiple"); +is(multiFileInput.multiple, true, "multi-file input .multiple"); +is(singleFileInput.value, input1File.name, "single-file input .value"); +is(multiFileInput.value, input2Files[0].name, "multi-file input .value"); +is(singleFileInput.files[0].name, input1File.name, "single-file input .files[n].name"); +is(singleFileInput.files[0].size, input1File.body.length, "single-file input .files[n].size"); +is(singleFileInput.files[0].type, input1File.type, "single-file input .files[n].type"); +for(i = 0; i < input2Files.length; ++i) { + is(multiFileInput.files[i].name, input2Files[i].name, "multi-file input .files[n].name"); + is(multiFileInput.files[i].size, input2Files[i].body.length, "multi-file input .files[n].size"); + is(multiFileInput.files[i].type, input2Files[i].type, "multi-file input .files[n].type"); +} + +document.getElementById('form').submit(); +iframe = document.getElementById('target_iframe'); +iframe.onload = function() { + response = JSON.parse(iframe.contentDocument.documentElement.textContent); + is(response[0].headers["Content-Disposition"], + "form-data; name=\"singleFile\"; filename=\"" + input1File.name + + "\"", + "singleFile Content-Disposition"); + is(response[0].headers["Content-Type"], input1File.type || "application/octet-stream", + "singleFile Content-Type"); + is(response[0].body, input1File.body, "singleFile body"); + + for(i = 0; i < input2Files.length; ++i) { + is(response[i + 1].headers["Content-Disposition"], + "form-data; name=\"multiFile\"; filename=\"" + input2Files[i].name + + "\"", + "multiFile Content-Disposition"); + is(response[i + 1].headers["Content-Type"], input2Files[i].type || "application/octet-stream", + "multiFile Content-Type"); + is(response[i + 1].body, input2Files[i].body, "multiFile body"); + } + + cleanupFiles(); + + is(singleFileInput.files.length, 0, "single-file .files.length"); // bug 524421 + is(multiFileInput.files.length, 0, "multi-file .files.length"); // bug 524421 + + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug529819.html b/dom/html/test/test_bug529819.html new file mode 100644 index 000000000..e744587a6 --- /dev/null +++ b/dom/html/test/test_bug529819.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=529819 +--> +<head> + <title>Test for Bug 529819</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529819">Mozilla Bug 529819</a> +<p id="display"></p> +<div id="content" style="display: none"> +<form id="form"> + <input name="foo" id="foo"> + <input name="bar" type="radio"> + <input name="bar" id="bar" type="radio"> +</form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 529819 **/ +is($("form").elements["foo"] instanceof HTMLInputElement, true, "Should have an element here"); +is($("form").elements["bar"] instanceof HTMLInputElement, false, "Should have a list here"); +is($("form").elements["bar"].length, 2, "Should have a list with two elements here"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug529859.html b/dom/html/test/test_bug529859.html new file mode 100644 index 000000000..282a5c060 --- /dev/null +++ b/dom/html/test/test_bug529859.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=529859 +--> +<head> + <title>Test for Bug 529859</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529859">Mozilla Bug 529859</a> +<div id="content"> + <iframe name="target_iframe" id="target_iframe"></iframe> + <form action="form_submit_server.sjs" target="target_iframe" id="form" + method="POST" enctype="multipart/form-data"> + <input id="emptyFileInput" name="emptyFileInput" type="file"> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 529859 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + $("target_iframe").onload = function() { + var response = JSON.parse(this.contentDocument.documentElement.textContent); + is(response.length, 1, "Unexpected number of inputs"); + is(response[0].headers["Content-Disposition"], + "form-data; name=\"emptyFileInput\"; filename=\"\"", + "Incorrect content-disposition"); + is(response[0].headers["Content-Type"], "application/octet-stream", + "Unexpected content-type"); + SimpleTest.finish(); + } + $("form").submit(); +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug535043.html b/dom/html/test/test_bug535043.html new file mode 100644 index 000000000..0123c4c2f --- /dev/null +++ b/dom/html/test/test_bug535043.html @@ -0,0 +1,90 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=535043 +--> +<head> + <title>Test for Bug 535043</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=535043">Mozilla Bug 535043</a> +<p id="display"></p> +<div id="content"> + <textarea></textarea> + <textarea maxlength="-1"></textarea> + <textarea maxlength="0"></textarea> + <textarea maxlength="2"></textarea> +</div> +<pre id="test"> +<script type="text/javascript"> + +/** Test for Bug 535043 **/ +function checkTextArea(textArea) { + textArea.value = ''; + textArea.focus(); + for (var j = 0; j < 3; j++) { + synthesizeKey('x', {}); + } + var htmlMaxLength = textArea.getAttribute('maxlength'); + var domMaxLength = textArea.maxLength; + if (htmlMaxLength == null) { + is(domMaxLength, -1, + 'maxlength is unset but maxLength DOM attribute is not -1'); + } else if (htmlMaxLength < 0) { + // Per the HTML5 spec, out-of-range values are supposed to translate to -1, + // not 0, but they don't? + is(domMaxLength, -1, + 'maxlength is out of range but maxLength DOM attribute is not -1'); + } else { + is(domMaxLength, parseInt(htmlMaxLength), + 'maxlength in DOM does not match provided value'); + } + if (textArea.maxLength == -1) { + is(textArea.value.length, 3, + 'textarea with maxLength -1 should have no length limit'); + } else { + is(textArea.value.length, textArea.maxLength, 'textarea has maxLength ' + + textArea.maxLength + ' but length ' + textArea.value.length ); + } +} + +SimpleTest.waitForFocus(function() { + var textAreas = document.getElementsByTagName('textarea'); + for (var i = 0; i < textAreas.length; i++) { + checkTextArea(textAreas[i]); + } + + textArea = textAreas[0]; + testNums = [-42, -1, 0, 2]; + for (var i = 0; i < testNums.length; i++) { + textArea.removeAttribute('maxlength'); + + var caught = false; + try { + textArea.maxLength = testNums[i]; + } catch (e) { + caught = true; + } + if (testNums[i] < 0) { + ok(caught, 'Setting negative maxLength should throw exception'); + } else { + ok(!caught, 'Setting nonnegative maxLength should not throw exception'); + } + checkTextArea(textArea); + + textArea.setAttribute('maxlength', testNums[i]); + checkTextArea(textArea); + } + + SimpleTest.finish(); +}); + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug536891.html b/dom/html/test/test_bug536891.html new file mode 100644 index 000000000..8fbfe0bc2 --- /dev/null +++ b/dom/html/test/test_bug536891.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=536891 +--> +<head> + <title>Test for Bug 536891</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=536891">Mozilla Bug 536891</a> +<p id="display"></p> +<div id="content" style="display: none"> +<textarea id="t" maxlength="-2" minlength="-2"></textarea> +<input id="i" type="text" maxlength="-2" minlength="-2"> +<input id="p" type="password" maxlength="-2" minlength="-2"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 536891 **/ + +function checkNegativeMinMaxLength(element) +{ + for(let type of ["min", "max"]) { + /* value is set to -2 initially in the document, see above */ + is(element[type + "Length"], -1, "negative " + type + "Length should be considered invalid and represented as -1"); + + // changing the property to an negative value should throw (see bug 536895). + for(let value of [-15, -2147483648]) { // PR_INT32_MIN + let threw = false; + try { + element[type + "Length"] = value; + } catch(e) { + threw = true; + } + is(threw, true, "setting " + type + "Length property to " + value + " should throw"); + } + element[type + "Length"] = "non-numerical value"; + is(element[type + "Length"], 0, "setting " + type + "Length property to a non-numerical value should set it to zero"); + + + element.setAttribute(type + 'Length', -15); + is(element[type + "Length"], -1, "negative " + type + "Length is not processed correctly when set dynamically"); + is(element.getAttribute(type + 'Length'), "-15", type + "Length attribute doesn't return the correct value"); + + element.setAttribute(type + 'Length', 0); + is(element[type + "Length"], 0, "zero " + type + "Length is not processed correctly"); + element.setAttribute(type + 'Length', 2147483647); // PR_INT32_MAX + is(element[type + "Length"], 2147483647, "negative " + type + "Length is not processed correctly"); + element.setAttribute(type + 'Length', -2147483648); // PR_INT32_MIN + is(element[type + "Length"], -1, "negative " + type + "Length is not processed correctly"); + element.setAttribute(type + 'Length', 'non-numerical-value'); + is(element[type + "Length"], -1, "non-numerical value should be considered invalid and represented as -1"); + } +} + +/* TODO: correct behavior may be checked for email, telephone, url and search input types */ +checkNegativeMinMaxLength(document.getElementById('t')); +checkNegativeMinMaxLength(document.getElementById('i')); +checkNegativeMinMaxLength(document.getElementById('p')); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug536895.html b/dom/html/test/test_bug536895.html new file mode 100644 index 000000000..7ff5bedb1 --- /dev/null +++ b/dom/html/test/test_bug536895.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=536895 +--> +<head> + <title>Test for Bug 536895</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=536895">Mozilla Bug 536895</a> +<p id="display"></p> +<div id="content" style="display: none"> +<textarea id="t"></textarea> +<input id="i" type="text"> +<input id="p" type="password"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 536895 **/ + +function checkNegativeMaxLengthException(element) +{ + caught = false; + try { + element.setAttribute('maxLength', -10); + } catch(e) { + caught = true; + } + ok(!caught, "Setting maxLength attribute to a negative value shouldn't throw an exception"); + + caught = false; + try { + element.maxLength = -20; + } catch(e) { + is(e.name, "IndexSizeError", "Should be an IndexSizeError exception"); + caught = true; + } + ok(caught, "Setting negative maxLength from the DOM should throw an exception"); + + is(element.getAttribute('maxLength'), "-10", "When the exception is raised, the maxLength attribute shouldn't change"); +} + +/* TODO: correct behavior may be checked for email, telephone, url and search input types */ +checkNegativeMaxLengthException(document.getElementById('t')); +checkNegativeMaxLengthException(document.getElementById('i')); +checkNegativeMaxLengthException(document.getElementById('p')); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug546995.html b/dom/html/test/test_bug546995.html new file mode 100644 index 000000000..0135da601 --- /dev/null +++ b/dom/html/test/test_bug546995.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=546995 +--> +<head> + <title>Test for Bug 546995</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=546995">Mozilla Bug 546995</a> +<p id="display"></p> +<div id="content" style="display: none"> + <select id='s'></select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 546995 **/ + +/* This test in only testing IDL reflection, another one is testing the behavior */ + +function checkAutofocusIDLAttribute(element) +{ + ok('autofocus' in element, "Element has the autofocus IDL attribute"); + ok(!element.autofocus, "autofocus default value is false"); + element.setAttribute('autofocus', 'autofocus'); + ok(element.autofocus, "autofocus should be enabled"); + element.removeAttribute('autofocus'); + ok(!element.autofocus, "autofocus should be disabled"); +} + +// TODO: keygen should be added when correctly implemented, see bug 101019. +checkAutofocusIDLAttribute(document.getElementById('s')); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug547850.html b/dom/html/test/test_bug547850.html new file mode 100644 index 000000000..977366518 --- /dev/null +++ b/dom/html/test/test_bug547850.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=547850 +--> +<head> + <title>Test for Bug 547850</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=547850">Mozilla Bug 547850</a> +<script> +document.write("<div id=content><f\u00c5></f\u00c5><r\u00e5></r\u00e5>"); +document.write("<span g\u00c5=a1 t\u00e5=a2></span></div>"); +</script> +<pre id="test"> +<script class="testbody" type="text/javascript"> +var ch = $('content').childNodes; +is(ch[0].localName, "f\u00c5", "upper case localName"); +is(ch[1].localName, "r\u00e5", "lower case localName"); +is(ch[0].nodeName, "F\u00c5", "upper case nodeName"); +is(ch[1].nodeName, "R\u00e5", "lower case nodeName"); +is(ch[0].tagName, "F\u00c5", "upper case tagName"); +is(ch[1].tagName, "R\u00e5", "lower case tagName"); +is(ch[2].getAttribute("g\u00c5"), "a1", "upper case attr name"); +is(ch[2].getAttribute("t\u00e5"), "a2", "lower case attr name"); +is(ch[2].getAttribute("G\u00c5"), "a1", "upper case attr name"); +is(ch[2].getAttribute("T\u00e5"), "a2", "lower case attr name"); +is(ch[2].getAttribute("g\u00e5"), null, "wrong lower case attr name"); +is(ch[2].getAttribute("t\u00c5"), null, "wrong upper case attr name"); +is($('content').getElementsByTagName("f\u00c5")[0], ch[0], "gEBTN upper case"); +is($('content').getElementsByTagName("f\u00c5").length, 1, "gEBTN upper case length"); +is($('content').getElementsByTagName("r\u00e5")[0], ch[1], "gEBTN lower case"); +is($('content').getElementsByTagName("r\u00e5").length, 1, "gEBTN lower case length"); +is($('content').getElementsByTagName("F\u00c5")[0], ch[0], "gEBTN upper case"); +is($('content').getElementsByTagName("F\u00c5").length, 1, "gEBTN upper case length"); +is($('content').getElementsByTagName("R\u00e5")[0], ch[1], "gEBTN lower case"); +is($('content').getElementsByTagName("R\u00e5").length, 1, "gEBTN lower case length"); +is($('content').getElementsByTagName("f\u00e5").length, 0, "gEBTN wrong upper case"); +is($('content').getElementsByTagName("r\u00c5").length, 0, "gEBTN wrong lower case"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug551846.html b/dom/html/test/test_bug551846.html new file mode 100644 index 000000000..e528e5a16 --- /dev/null +++ b/dom/html/test/test_bug551846.html @@ -0,0 +1,164 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=551846 +--> +<head> + <title>Test for Bug 551846</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=551846">Mozilla Bug 551846</a> +<p id="display"></p> +<div id="content" style="display: none"> + <select id='s'> + <option>Tulip</option> + <option>Lily</option> + <option>Gagea</option> + <option>Snowflake</option> + <option>Ismene</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 551846 **/ + +function checkSizeReflection(element, defaultValue) +{ + is(element.size, defaultValue, "Default size should be " + defaultValue); + + element.setAttribute('size', -15); + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), "-15", + "The content attribute should containt the previously set value"); + + element.setAttribute('size', 0); + is(element.size, 0, + "0 should be considered as a valid value"); + is(element.getAttribute('size'), "0", + "The content attribute should containt the previously set value"); + + element.setAttribute('size', 2147483647); /* PR_INT32_MAX */ + is(element.size, 2147483647, + "PR_INT32_MAX should be considered as a valid value"); + is(element.getAttribute('size'), "2147483647", + "The content attribute should containt the previously set value"); + + element.setAttribute('size', -2147483648); /* PR_INT32_MIN */ + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), "-2147483648", + "The content attribute should containt the previously set value"); + + element.setAttribute('size', 'non-numerical-value'); + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), 'non-numerical-value', + "The content attribute should containt the previously set value"); + + element.setAttribute('size', 4294967294); /* PR_INT32_MAX * 2 */ + is(element.size, defaultValue, + "Value greater than PR_INT32_MAX should be considered as invalid"); + is(element.getAttribute('size'), "4294967294", + "The content attribute should containt the previously set value"); + + element.setAttribute('size', -4294967296); /* PR_INT32_MIN * 2 */ + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), "-4294967296", + "The content attribute should containt the previously set value"); + + element.size = defaultValue + 1; + element.removeAttribute('size'); + is(element.size, defaultValue, + "When the attribute is removed, the size should be the default size"); + + element.setAttribute('size', 'foobar'); + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + element.removeAttribute('size'); + is(element.size, defaultValue, + "When the attribute is removed, the size should be the default size"); +} + +function checkSetSizeException(element) +{ + var caught = false; + + try { + element.size = 1; + } catch(e) { + caught = true; + } + ok(!caught, "Setting a positive size shouldn't throw an exception"); + + caught = false; + try { + element.size = 0; + } catch(e) { + caught = true; + } + ok(!caught, "Setting a size to 0 from the IDL shouldn't throw an exception"); + + element.size = 1; + + caught = false; + try { + element.size = -1; + } catch(e) { + caught = true; + } + ok(!caught, "Setting a negative size from the IDL shouldn't throw an exception"); + + is(element.size, 0, "The size should now be equal to the minimum non-negative value"); + + caught = false; + try { + element.setAttribute('size', -10); + } catch(e) { + caught = true; + } + ok(!caught, "Setting an invalid size in the content attribute shouldn't throw an exception"); + + // reverting to defalut + element.removeAttribute('size'); +} + +function checkSizeWhenChangeMultiple(element, aDefaultNonMultiple, aDefaultMultiple) +{ + s.setAttribute('size', -1) + is(s.size, aDefaultNonMultiple, "Size IDL attribute should be 1"); + + s.multiple = true; + is(s.size, aDefaultMultiple, "Size IDL attribute should be 4"); + + is(s.getAttribute('size'), "-1", "Size content attribute should be -1"); + + s.setAttribute('size', -2); + is(s.size, aDefaultMultiple, "Size IDL attribute should be 4"); + + s.multiple = false; + is(s.size, aDefaultNonMultiple, "Size IDL attribute should be 1"); + + is(s.getAttribute('size'), "-2", "Size content attribute should be -2"); +} + +var s = document.getElementById('s'); + +checkSizeReflection(s, 0); +checkSetSizeException(s); + +s.setAttribute('multiple', 'true'); +checkSizeReflection(s, 0); +checkSetSizeException(s); +s.removeAttribute('multiple'); + +checkSizeWhenChangeMultiple(s, 0, 0); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug555567.html b/dom/html/test/test_bug555567.html new file mode 100644 index 000000000..04c82147c --- /dev/null +++ b/dom/html/test/test_bug555567.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=555567 +--> +<head> + <title>Test for Bug 555567</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555567">Mozilla Bug 555567</a> +<div id='content' style="display: none"> + <form> + <fieldset> + <legend id="a"></legend> + </fieldset> + <legend id="b"></legend> + </form> + <legend id="c"></legend> +</div> +<pre id="test"> +<p id="display"></p> +<script type="application/javascript"> + +/** Test for Bug 555567 **/ + +var a = document.getElementById('a'); +var b = document.getElementById('b'); +var c = document.getElementById('c'); + +isnot(a.form, null, + "First legend element should have a not null form IDL attribute"); +is(b.form, null, + "Second legend element should have a null form IDL attribute"); +is(c.form, null, + "Third legend element should have a null form IDL attribute"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug556645.html b/dom/html/test/test_bug556645.html new file mode 100644 index 000000000..449f956a6 --- /dev/null +++ b/dom/html/test/test_bug556645.html @@ -0,0 +1,50 @@ +<html> +<head> + <title>Test for Bug 556645</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<script> +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTest); + +function runTest() +{ + var obj = document.getElementById("obj"); + var childDoc = obj.contentDocument; + var body = childDoc.body; + is(document.activeElement, document.body, "focus in parent before"); + is(childDoc.activeElement, body, "focus in child before"); + + var button = childDoc.getElementsByTagName("button")[0]; + button.focus(); + childDoc.defaultView.focus(); + is(document.activeElement, obj, "focus in parent after focus()"); + is(childDoc.activeElement, button, "focus in child after focus()"); + + button.blur(); + var pbutton = document.getElementById("pbutton"); + pbutton.focus(); + + synthesizeKey("VK_TAB", { }); + is(document.activeElement, obj, "focus in parent after tab"); + is(childDoc.activeElement, childDoc.documentElement, "focus in child after tab"); + + synthesizeKey("VK_TAB", { }); + is(document.activeElement, obj, "focus in parent after tab 2"); + is(childDoc.activeElement, button, "focus in child after tab 2"); + + SimpleTest.finish(); +} + +</script> + +<button id="pbutton">Parent</button> +<object id="obj" type="text/html" + data="data:text/html,%3Cbody%3E%3Cbutton%3EChild%3C/button%3E%3C/body%3E" + width="200" height="200"></object> + +</body> +</html> diff --git a/dom/html/test/test_bug557087-1.html b/dom/html/test/test_bug557087-1.html new file mode 100644 index 000000000..32e36e59d --- /dev/null +++ b/dom/html/test/test_bug557087-1.html @@ -0,0 +1,126 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=557087 +--> +<head> + <title>Test for Bug 557087</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 557087 **/ + +function checkDisabledAttribute(aFieldset) +{ + ok('disabled' in aFieldset, + "fieldset elements should have the disabled attribute"); + + ok(!aFieldset.disabled, + "fieldset elements disabled attribute should be disabled"); + is(aFieldset.getAttribute('disabled'), null, + "fieldset elements disabled attribute should be disabled"); + + aFieldset.disabled = true; + ok(aFieldset.disabled, + "fieldset elements disabled attribute should be enabled"); + isnot(aFieldset.getAttribute('disabled'), null, + "fieldset elements disabled attribute should be enabled"); + + aFieldset.removeAttribute('disabled'); + aFieldset.setAttribute('disabled', ''); + ok(aFieldset.disabled, + "fieldset elements disabled attribute should be enabled"); + isnot(aFieldset.getAttribute('disabled'), null, + "fieldset elements disabled attribute should be enabled"); + + aFieldset.removeAttribute('disabled'); + ok(!aFieldset.disabled, + "fieldset elements disabled attribute should be disabled"); + is(aFieldset.getAttribute('disabled'), null, + "fieldset elements disabled attribute should be disabled"); +} + +function checkDisabledPseudoClass(aFieldset) +{ + is(document.querySelector(":disabled"), null, + "no elements should have :disabled applied to them"); + + aFieldset.disabled = true; + is(document.querySelector(":disabled"), aFieldset, + ":disabled should apply to fieldset elements"); + + aFieldset.disabled = false; + is(document.querySelector(":disabled"), null, + "no elements should have :disabled applied to them"); +} + +function checkEnabledPseudoClass(aFieldset) +{ + is(document.querySelector(":enabled"), aFieldset, + ":enabled should apply to fieldset elements"); + + aFieldset.disabled = true; + is(document.querySelector(":enabled"), null, + "no elements should have :enabled applied to them"); + + aFieldset.disabled = false; + is(document.querySelector(":enabled"), aFieldset, + ":enabled should apply to fieldset elements"); +} + +function checkFocus(aFieldset) +{ + aFieldset.disabled = true; + aFieldset.setAttribute('tabindex', 1); + + aFieldset.focus(); + + isnot(document.activeElement, aFieldset, + "fieldset can't be focused when disabled"); + aFieldset.removeAttribute('tabindex'); + aFieldset.disabled = false; +} + +function checkClickEvent(aFieldset) +{ + var clickHandled = false; + + aFieldset.disabled = true; + + aFieldset.addEventListener("click", function(aEvent) { + aEvent.target.removeEventListener("click", arguments.callee, false); + clickHandled = true; + }, false); + + sendMouseEvent({type:'click'}, aFieldset); + SimpleTest.executeSoon(function() { + ok(!clickHandled, "When disabled, fieldset should prevent click events"); + SimpleTest.finish(); + }); +} + +SimpleTest.waitForExplicitFinish(); + +var fieldset = document.createElement("fieldset"); +var content = document.getElementById('content'); +content.appendChild(fieldset); + +checkDisabledAttribute(fieldset); +checkDisabledPseudoClass(fieldset); +checkEnabledPseudoClass(fieldset); +checkFocus(fieldset); +checkClickEvent(fieldset); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug557087-2.html b/dom/html/test/test_bug557087-2.html new file mode 100644 index 000000000..923a136c5 --- /dev/null +++ b/dom/html/test/test_bug557087-2.html @@ -0,0 +1,359 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=557087 +--> +<head> + <title>Test for Bug 557087</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a> +<p id="display"></p> +<div id="content" style="display:none;"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 557087 **/ + +SimpleTest.waitForExplicitFinish(); + +var elementsPreventingClick = [ "input", "button", "select", "textarea", "fieldset" ]; +var elementsWithClick = [ "option", "optgroup", "output", "label", "object" ]; +var gHandled = 0; + +function clickShouldNotHappenHandler(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldNotHappenHandler, false); + ok(false, "click event should be prevented! (test1)"); + if (++gHandled >= elementsWithClick.length) { + test2(); + } +} + +function clickShouldNotHappenHandler2(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldNotHappenHandler3, false); + ok(false, "click event should be prevented! (test2)"); + if (++gHandled >= elementsWithClick.length) { + test3(); + } +} + +function clickShouldNotHappenHandler5(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldNotHappenHandler5, false); + ok(false, "click event should be prevented! (test5)"); + if (++gHandled >= elementsWithClick.length) { + test6(); + } +} + +function clickShouldNotHappenHandler7(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldNotHappenHandler7, false); + ok(false, "click event should be prevented! (test7)"); + if (++gHandled >= elementsWithClick.length) { + test8(); + } +} + +function clickShouldHappenHandler(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler, false); + ok(true, "click event has been correctly received (test1)"); + if (++gHandled >= elementsWithClick.length) { + test2(); + } +} + +function clickShouldHappenHandler2(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler2, false); + ok(true, "click event has been correctly received (test2)"); + if (++gHandled >= elementsWithClick.length) { + test3(); + } +} + +function clickShouldHappenHandler3(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler3, false); + ok(true, "click event has been correctly received (test3)"); + if (++gHandled >= (elementsWithClick.length + + elementsPreventingClick.length)) { + test4(); + } +} + +function clickShouldHappenHandler4(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler4, false); + ok(true, "click event has been correctly received (test4)"); + if (++gHandled >= (elementsWithClick.length + + elementsPreventingClick.length)) { + test5(); + } +} + +function clickShouldHappenHandler5(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler5, false); + ok(true, "click event has been correctly received (test5)"); + if (++gHandled >= elementsWithClick.length) { + test6(); + } +} + +function clickShouldHappenHandler6(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler6, false); + ok(true, "click event has been correctly received (test6)"); + if (++gHandled >= (elementsWithClick.length + + elementsPreventingClick.length)) { + test7(); + } +} + +function clickShouldHappenHandler7(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler7, false); + ok(true, "click event has been correctly received (test5)"); + if (++gHandled >= elementsWithClick.length) { + test8(); + } +} + +function clickShouldHappenHandler8(aEvent) +{ + aEvent.target.removeEventListener("click", clickShouldHappenHandler8, false); + ok(true, "click event has been correctly received (test8)"); + if (++gHandled >= (elementsWithClick.length + + elementsPreventingClick.length)) { + SimpleTest.finish(); + } +} + +var fieldset1 = document.createElement("fieldset"); +var fieldset2 = document.createElement("fieldset"); +var legendA = document.createElement("legend"); +var legendB = document.createElement("legend"); +var content = document.getElementById('content'); +fieldset1.disabled = true; +content.appendChild(fieldset1); +fieldset1.appendChild(fieldset2); + +function clean() +{ + var count = fieldset2.children.length; + for (var i=0; i<count; ++i) { + if (fieldset2.children[i] != legendA && + fieldset2.children[i] != legendB) { + fieldset2.removeChild(fieldset2.children[i]); + } + } +} + +function test1() +{ + gHandled = 0; + + // Initialize children without click expected. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldNotHappenHandler, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler, false); + sendMouseEvent({type:'click'}, element); + } +} + +function test2() +{ + gHandled = 0; + fieldset1.disabled = false; + fieldset2.disabled = true; + + // Initialize children without click expected. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldNotHappenHandler2, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler2, false); + sendMouseEvent({type:'click'}, element); + } +} + +function test3() +{ + gHandled = 0; + fieldset1.disabled = false; + fieldset2.disabled = false; + + // All elements should accept the click. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler3, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler3, false); + sendMouseEvent({type:'click'}, element); + } +} + +function test4() +{ + gHandled = 0; + fieldset1.disabled = false; + fieldset2.disabled = true; + + fieldset2.appendChild(legendA); + + // All elements should accept the click. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + legendA.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler4, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + legendA.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler4, false); + sendMouseEvent({type:'click'}, element); + } +} + +function test5() +{ + gHandled = 0; + fieldset2.insertBefore(legendB, legendA); + + // Initialize children without click expected. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + legendA.appendChild(element); + element.addEventListener("click", clickShouldNotHappenHandler5, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + legendA.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler5, false); + sendMouseEvent({type:'click'}, element); + } +} + +function test6() +{ + gHandled = 0; + fieldset2.removeChild(legendB); + fieldset1.disabled = true; + fieldset2.disabled = false; + + fieldset1.appendChild(legendA); + legendA.appendChild(fieldset2); + + // All elements should accept the click. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler6, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + fieldset2.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler6, false); + sendMouseEvent({type:'click'}, element); + } +} + +function test7() +{ + gHandled = 0; + fieldset1.disabled = true; + fieldset2.disabled = false; + + fieldset1.appendChild(fieldset2); + fieldset2.appendChild(legendA); + + // All elements should accept the click. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + legendA.appendChild(element); + element.addEventListener("click", clickShouldNotHappenHandler7, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + legendA.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler7, false); + sendMouseEvent({type:'click'}, element); + } +} + +function test8() +{ + gHandled = 0; + fieldset1.disabled = true; + fieldset2.disabled = true; + + fieldset1.appendChild(legendA); + legendA.appendChild(fieldset2); + fieldset2.appendChild(legendB); + + // All elements should accept the click. + for (var name of elementsPreventingClick) { + var element = document.createElement(name); + legendB.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler8, false); + sendMouseEvent({type:'click'}, element); + } + + // Initialize children with click expected. + for (var name of elementsWithClick) { + var element = document.createElement(name); + legendB.appendChild(element); + element.addEventListener("click", clickShouldHappenHandler8, false); + sendMouseEvent({type:'click'}, element); + } +} + +test1(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug557087-3.html b/dom/html/test/test_bug557087-3.html new file mode 100644 index 000000000..166007c49 --- /dev/null +++ b/dom/html/test/test_bug557087-3.html @@ -0,0 +1,215 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=557087 +--> +<head> + <title>Test for Bug 557087</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 557087 **/ + +function checkValueMissing(aElement, aExpected) +{ + var msg = aExpected ? aElement.tagName + " should suffer from value missing" + : aElement.tagName + " should not suffer from value missing" + is(aElement.validity.valueMissing, aExpected, msg); +} + +function checkCandidateForConstraintValidation(aElement, aExpected) +{ + var msg = aExpected ? aElement.tagName + " should be candidate for constraint validation" + : aElement.tagName + " should not be candidate for constraint validation" + is(aElement.willValidate, aExpected, msg); +} + +function checkDisabledPseudoClass(aElement, aDisabled) +{ + var disabledElements = document.querySelectorAll(":disabled"); + var found = false; + + for (var e of disabledElements) { + if (aElement == e) { + found = true; + break; + } + } + + var msg = aDisabled ? aElement.tagName + " should have :disabled applying" + : aElement.tagName + " should not have :disabled applying"; + ok(aDisabled ? found : !found, msg); +} + +function checkEnabledPseudoClass(aElement, aEnabled) +{ + var enabledElements = document.querySelectorAll(":enabled"); + var found = false; + + for (var e of enabledElements) { + if (aElement == e) { + found = true; + break; + } + } + + var msg = aEnabled ? aElement.tagName + " should have :enabled applying" + : aElement.tagName + " should not have :enabled applying"; + ok(aEnabled ? found : !found, msg); +} + +function checkFocus(aElement, aExpected) +{ + aElement.setAttribute('tabindex', 1); + + // We use the focus manager so we can test <label>. + var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"] + .getService(SpecialPowers.Ci.nsIFocusManager); + fm.setFocus(aElement, 0); + + if (aExpected) { + is(document.activeElement, aElement, "element should be focused"); + } else { + isnot(document.activeElement, aElement, "element should not be focused"); + } + + aElement.blur(); + aElement.removeAttribute('tabindex'); +} + +var elements = [ "input", "button", "select", "textarea", "fieldset", "option", + "optgroup", "label", "output", "object" ]; + +var testData = { +/* tag name | affected by disabled | test focus | test pseudo-classes | test willValidate */ + "INPUT": [ true, true, true, true, true ], + "BUTTON": [ true, true, true, false, false ], + "SELECT": [ true, true, true, true, false ], + "TEXTAREA": [ true, true, true, true, true ], + "FIELDSET": [ true, true, true, false, false ], + "OPTION": [ false, true, true, false, false ], + "OPTGROUP": [ false, true, true, false, false ], + "OBJECT": [ false, true, false, false, false ], + "LABEL": [ false, true, false, false, false ], + "OUTPUT": [ false, true, false, false, false ], +}; + +/** + * For not candidate elements without disabled attribute and not submittable, + * we only have to check that focus and click works even inside a disabled + * fieldset. + */ +function checkElement(aElement, aDisabled) +{ + var data = testData[aElement.tagName]; + var expected = data[0] ? !aDisabled : true; + + if (data[1]) { + checkFocus(aElement, expected); + } + + if (data[2]) { + checkEnabledPseudoClass(aElement, data[0] ? !aDisabled : true); + checkDisabledPseudoClass(aElement, data[0] ? aDisabled : false); + } + + if (data[3]) { + checkCandidateForConstraintValidation(aElement, expected); + } + + if (data[4]) { + checkValueMissing(aElement, expected); + } +} + +var fieldset1 = document.createElement("fieldset"); +var fieldset2 = document.createElement("fieldset"); +var legendA = document.createElement("legend"); +var legendB = document.createElement("legend"); +var content = document.getElementById('content'); +content.appendChild(fieldset1); +fieldset1.appendChild(fieldset2); +fieldset2.disabled = true; + +for (var data of elements) { + var element = document.createElement(data); + + if (data[4]) { + element.required = true; + } + + fieldset1.disabled = false; + fieldset2.appendChild(element); + + checkElement(element, fieldset2.disabled); + + // Make sure changes are correctly managed. + fieldset2.disabled = false; + checkElement(element, fieldset2.disabled); + fieldset2.disabled = true; + checkElement(element, fieldset2.disabled); + + // Make sure if a fieldset which is not the first fieldset is disabled, the + // elements inside the second fielset are disabled. + fieldset2.disabled = false; + fieldset1.disabled = true; + checkElement(element, fieldset1.disabled); + + // Make sure the state change of the inner fieldset will not confuse. + fieldset2.disabled = true; + fieldset2.disabled = false; + checkElement(element, fieldset1.disabled); + + + /* legend tests */ + + // elements in the first legend of a disabled fieldset should not be disabled. + fieldset2.disabled = true; + fieldset1.disabled = false; + legendA.appendChild(element); + fieldset2.appendChild(legendA); + checkElement(element, false); + + // elements in the second legend should be disabled + fieldset2.insertBefore(legendB, legendA); + checkElement(element, fieldset2.disabled); + fieldset2.removeChild(legendB); + + // Elements in the first legend of a fieldset disabled by another fieldset + // should be disabled. + fieldset1.disabled = true; + checkElement(element, fieldset1.disabled); + + // Elements inside a fieldset inside the first legend of a disabled fieldset + // should not be diasbled. + fieldset2.disabled = false; + fieldset1.appendChild(legendA); + legendA.appendChild(fieldset2); + fieldset2.appendChild(element); + checkElement(element, false); + + // Elements inside the first legend of a disabled fieldset inside the first + // legend of a disabled fieldset should not be disabled. + fieldset2.disabled = false; + fieldset2.appendChild(legendB); + legendB.appendChild(element); + checkElement(element, false); + fieldset2.removeChild(legendB); + fieldset1.appendChild(fieldset2); + + element.parentNode.removeChild(element); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug557087-4.html b/dom/html/test/test_bug557087-4.html new file mode 100644 index 000000000..edb732dae --- /dev/null +++ b/dom/html/test/test_bug557087-4.html @@ -0,0 +1,90 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=557087 +--> +<head> + <title>Test for Bug 557087</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a> +<p id="display"></p> +<div id="content"> + <iframe name='f'></iframe> + <form target='f' action="data:text/html"> + <input type='text' id='a'> + <input type='checkbox' id='b'> + <input type='radio' id='c'> + <fieldset disabled> + <fieldset> + <input type='submit' id='s'> + </fieldset> + </fieldset> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 557087 **/ + +SimpleTest.waitForExplicitFinish(); + +var gExpectedSubmits = 6; +var gSubmitReceived = 0; +var gEnd = false; + +var fieldsets = document.getElementsByTagName("fieldset"); +var form = document.forms[0]; + +form.addEventListener("submit", function() { + ok(gEnd, gEnd ? "expected submit" : "non expected submit"); + if (++gSubmitReceived >= gExpectedSubmits) { + form.removeEventListener("submit", arguments.callee, false); + SimpleTest.finish(); + } +}, false); + +var inputs = [ + document.getElementById('a'), + document.getElementById('b'), + document.getElementById('c'), +]; + +function doSubmit() +{ + for (e of inputs) { + e.focus(); + synthesizeKey("VK_RETURN", {}); + } +} + +SimpleTest.waitForFocus(function() { + doSubmit(); + + fieldsets[1].disabled = true; + fieldsets[0].disabled = false; + doSubmit(); + + fieldsets[0].disabled = false; + fieldsets[1].disabled = false; + + gEnd = true; + doSubmit(); + + // Simple check that we can submit from inside a legend even if the fieldset + // is disabled. + var legend = document.createElement("legend"); + fieldsets[0].appendChild(legend); + fieldsets[0].disabled = true; + legend.appendChild(document.getElementById('s')); + + doSubmit(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug557087-5.html b/dom/html/test/test_bug557087-5.html new file mode 100644 index 000000000..4b8c021f8 --- /dev/null +++ b/dom/html/test/test_bug557087-5.html @@ -0,0 +1,93 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=557087 +--> +<head> + <title>Test for Bug 557087</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a> +<p id="display"></p> +<div id="content"> + <iframe name='t'></iframe> + <form target='t' action="data:text/html,"> + <fieldset disabled> + <fieldset> + <input name='i' value='i'> + <textarea name='t'>t</textarea> + <select name='s'><option>s</option></select> + </fieldset> + </fieldset> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 557087 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTest); + +var testResults = [ + "data:text/html,?", + "data:text/html,?", + "data:text/html,?i=i&t=t&s=s", + "data:text/html,?i=i&t=t&s=s", +]; +var gTestCount = 0; + +var form = document.forms[0]; +var iframe = document.getElementsByTagName('iframe')[0]; +var fieldsets = document.getElementsByTagName('fieldset'); + +function runTest() +{ + iframe.addEventListener("load", function() { + is(iframe.contentWindow.location.href, testResults[gTestCount], + testResults[gTestCount] + " should have been loaded"); + + switch (++gTestCount) { + case 1: + fieldsets[1].disabled = true; + fieldsets[0].disabled = false; + form.submit(); + SimpleTest.executeSoon(function() { + form.submit() + }); + break; + case 2: + fieldsets[0].disabled = false; + fieldsets[1].disabled = false; + SimpleTest.executeSoon(function() { + form.submit() + }); + break; + case 3: + // Elements inside the first legend of a disabled fieldset are submittable. + fieldsets[0].disabled = true; + fieldsets[1].disabled = true; + var legend = document.createElement("legend"); + fieldsets[0].appendChild(legend); + while (fieldsets[1].firstChild) { + legend.appendChild(fieldsets[1].firstChild); + } + SimpleTest.executeSoon(function() { + form.submit() + }); + break; + default: + iframe.removeEventListener("load", arguments.callee, false); + SimpleTest.executeSoon(SimpleTest.finish); + } + }, false); + + form.submit(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug557087-6.html b/dom/html/test/test_bug557087-6.html new file mode 100644 index 000000000..ea2e3efcc --- /dev/null +++ b/dom/html/test/test_bug557087-6.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=557087 +--> +<head> + <title>Test for Bug 557087</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a> +<p id="display"></p> +<div id="content" style="display: none"> + <fieldset disabled> + <input> + </fieldset> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 557087 **/ + +// Testing random stuff following review comments. + +var fieldset = document.getElementsByTagName("fieldset")[0]; + +is(fieldset.elements.length, 1, + "there should be one element inside the fieldset"); +is(fieldset.elements[0], document.getElementsByTagName("input")[0], + "input should be the element inside the fieldset"); + +document.body.removeChild(document.getElementById('content')); +is(fieldset.querySelector("input:disabled"), fieldset.elements[0], + "the input should still be disabled"); + +fieldset.disabled = false; +is(fieldset.querySelector("input:enabled"), fieldset.elements[0], + "the input should be enabled"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug557620.html b/dom/html/test/test_bug557620.html new file mode 100644 index 000000000..4fe9def3a --- /dev/null +++ b/dom/html/test/test_bug557620.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=557620 +--> +<head> + <title>Test for Bug 557620</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557620">Mozilla Bug 557620</a> +<p id="display"></p> +<div id="content" style="display: none"> + <input type="tel" id='i'> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 557620 **/ + +// More checks are done in test_bug551670.html. + +var tel = document.getElementById('i'); +is(tel.type, 'tel', "input with type='tel' should return 'tel'"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug558788-1.html b/dom/html/test/test_bug558788-1.html new file mode 100644 index 000000000..94b7a5f00 --- /dev/null +++ b/dom/html/test/test_bug558788-1.html @@ -0,0 +1,211 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=558788 +--> +<head> + <title>Test for Bug 558788</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input, textarea { background-color: rgb(0,0,0) !important; } + :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; } + :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=558788">Mozilla Bug 558788</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 558788 **/ + +/** + * This test checks the behavior of :valid and :invalid pseudo-classes + * when the user is typing/interacting with the element. + * Only <input> and <textarea> elements can have there validity changed by an + * user input. + */ + +var gContent = document.getElementById('content'); + +function checkValidApplies(elmt) +{ + is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); +} + +function checkInvalidApplies(elmt, aTodo) +{ + if (aTodo) { + todo_is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + return; + } + is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); +} + +function checkMissing(elementName) +{ + var element = document.createElement(elementName); + element.required = true; + gContent.appendChild(element); + checkInvalidApplies(element); + + element.focus(); + + synthesizeKey("a", {}); + checkValidApplies(element); + + synthesizeKey("VK_BACK_SPACE", {}); + checkInvalidApplies(element); + + gContent.removeChild(element); +} + +function checkTooLong(elementName) +{ + var element = document.createElement(elementName); + element.value = "foo"; + element.maxLength = 2; + gContent.appendChild(element); + checkInvalidApplies(element, true); + + element.focus(); + + synthesizeKey("VK_BACK_SPACE", {}); + checkValidApplies(element); + gContent.removeChild(element); +} + +function checkTextAreaMissing() +{ + checkMissing('textarea'); +} + +function checkTextAreaTooLong() +{ + checkTooLong('textarea'); +} + +function checkTextArea() +{ + checkTextAreaMissing(); + checkTextAreaTooLong(); +} + +function checkInputMissing() +{ + checkMissing('input'); +} + +function checkInputTooLong() +{ + checkTooLong('input'); +} + +function checkInputEmail() +{ + var element = document.createElement('input'); + element.type = 'email'; + gContent.appendChild(element); + checkValidApplies(element); + + element.focus(); + + synthesizeKey("a", {}); + checkInvalidApplies(element); + + sendString("@b.c"); + checkValidApplies(element); + + synthesizeKey("VK_BACK_SPACE", {}); + for (var i=0; i<4; ++i) { + if (i == 1) { + // a@b is a valid value. + checkValidApplies(element); + } else { + checkInvalidApplies(element); + } + synthesizeKey("VK_BACK_SPACE", {}); + } + checkValidApplies(element); + + gContent.removeChild(element); +} + +function checkInputURL() +{ + var element = document.createElement('input'); + element.type = 'url'; + gContent.appendChild(element); + checkValidApplies(element); + + element.focus(); + + synthesizeKey("h", {}); + checkInvalidApplies(element); + + sendString("ttp://mozilla.org"); + checkValidApplies(element); + + for (var i=0; i<13; ++i) { + synthesizeKey("VK_BACK_SPACE", {}); + checkValidApplies(element); + } + + synthesizeKey("VK_BACK_SPACE", {}); + for (var i=0; i<4; ++i) { + checkInvalidApplies(element); + synthesizeKey("VK_BACK_SPACE", {}); + } + checkValidApplies(element); + + gContent.removeChild(element); +} + +function checkInputPattern() +{ + var element = document.createElement('input'); + element.pattern = "[0-9]*" + gContent.appendChild(element); + checkValidApplies(element); + + element.focus(); + + synthesizeKey("0", {}); + checkValidApplies(element); + + synthesizeKey("a", {}); + checkInvalidApplies(element); + + synthesizeKey("VK_BACK_SPACE", {}); + checkValidApplies(element); + + synthesizeKey("VK_BACK_SPACE", {}); + checkValidApplies(element); + + gContent.removeChild(element); +} + +function checkInput() +{ + checkInputMissing(); + checkInputTooLong(); + checkInputEmail(); + checkInputURL(); + checkInputPattern(); +} + +checkTextArea(); +checkInput(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug558788-2.html b/dom/html/test/test_bug558788-2.html new file mode 100644 index 000000000..dcf5db00d --- /dev/null +++ b/dom/html/test/test_bug558788-2.html @@ -0,0 +1,174 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=558788 +--> +<head> + <title>Test for Bug 558788</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=558788">Mozilla Bug 558788</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 558788 **/ + +var validElementsDescription = [ + /* element type value required pattern maxlength minlength */ + /* <input> */ + [ "input", null, null, null, null, null, null ], + /* <input required value='foo'> */ + [ "input", null, "foo", true, null, null, null ], + /* <input type='email'> */ + [ "input", "email", null, null, null, null, null ], + /* <input type='email' value='foo@mozilla.org'> */ + [ "input", "email", "foo@mozilla.org", null, null, null, null ], + /* <input type='url'> */ + [ "input", "url", null, null, null, null, null ], + /* <input type='url' value='http://mozilla.org'> */ + [ "input", "url", "http://mozilla.org", null, null, null, null ], + /* <input pattern='\\d\\d'> */ + [ "input", null, null, null, "\\d\\d", null, null ], + /* <input pattern='\\d\\d' value='42'> */ + [ "input", null, "42", null, "\\d\\d", null, null ], + /* <input maxlength='3'> - still valid until user interaction */ + [ "input", null, null, null, null, "3", null ], + /* <input maxlength='3'> */ + [ "input", null, "fooo", null, null, "3", null ], + /* <input minlength='3'> - still valid until user interaction */ + [ "input", null, null, null, null, null, "3" ], + /* <input minlength='3'> */ + [ "input", null, "fo", null, null, null, "3" ], + /* <textarea></textarea> */ + [ "textarea", null, null, null, null, null, null ], + /* <textarea required>foo</textarea> */ + [ "textarea", null, "foo", true, null, null, null ] +]; + +var invalidElementsDescription = [ + /* element type value required pattern maxlength minlength valid-value */ + /* <input required> */ + [ "input", null, null, true, null, null, null, "foo" ], + /* <input type='email' value='foo'> */ + [ "input", "email", "foo", null, null, null, null, "foo@mozilla.org" ], + /* <input type='url' value='foo'> */ + [ "input", "url", "foo", null, null, null, null, "http://mozilla.org" ], + /* <input pattern='\\d\\d' value='foo'> */ + [ "input", null, "foo", null, "\\d\\d", null, null, "42" ], + /* <input maxlength='3'> - still valid until user interaction */ + [ "input", null, "foooo", null, null, "3", null, "foo" ], + /* <input minlength='3'> - still valid until user interaction */ + [ "input", null, "foo", null, null, null, "3", "foo" ], + /* <textarea required></textarea> */ + [ "textarea", null, null, true, null, null, null, "foo" ], +]; + +var validElements = []; +var invalidElements = []; + +function appendElements(aElementsDesc, aElements) +{ + var content = document.getElementById('content'); + var length = aElementsDesc.length; + + for (var i=0; i<length; ++i) { + var e = document.createElement(aElementsDesc[i][0]); + if (aElementsDesc[i][1]) { + e.type = aElementsDesc[i][1]; + } + if (aElementsDesc[i][2]) { + e.value = aElementsDesc[i][2]; + } + if (aElementsDesc[i][3]) { + e.required = true; + } + if (aElementsDesc[i][4]) { + e.pattern = aElementsDesc[i][4]; + } + if (aElementsDesc[i][5]) { + e.maxLength = aElementsDesc[i][5]; + } + if (aElementsDesc[i][6]) { + e.minLength = aElementsDesc[i][6]; + } + + content.appendChild(e); + + // Adding the element to the appropriate list. + aElements.push(e); + } +} + +function compareArrayWithSelector(aElements, aSelector) +{ + var aSelectorElements = document.querySelectorAll(aSelector); + + is(aSelectorElements.length, aElements.length, + aSelector + " selector should return the correct number of elements"); + + if (aSelectorElements.length != aElements.length) { + return; + } + + var length = aElements.length; + for (var i=0; i<length; ++i) { + is(aSelectorElements[i], aElements[i], + aSelector + " should return the correct elements"); + } +} + +function makeMinMaxLengthElementsActuallyInvalid(aInvalidElements, + aInvalidElementsDesc) +{ + // min/maxlength elements are not invalid until user edits them + var length = aInvalidElementsDesc.length; + + for (var i=0; i<length; ++i) { + var e = aInvalidElements[i]; + if (aInvalidElementsDesc[i][5]) { // maxlength + e.focus(); + synthesizeKey("VK_BACK_SPACE", {}); + } else if (aInvalidElementsDesc[i][6]) { // minlength + e.focus(); + synthesizeKey("VK_BACK_SPACE", {}); + } + } +} + +function makeInvalidElementsValid(aInvalidElements, + aInvalidElementsDesc, + aValidElements) +{ + var length = aInvalidElementsDesc.length; + + for (var i=0; i<length; ++i) { + var e = aInvalidElements.shift(); + e.value = aInvalidElementsDesc[i][7]; + aValidElements.push(e); + } +} + +appendElements(validElementsDescription, validElements); +appendElements(invalidElementsDescription, invalidElements); + +makeMinMaxLengthElementsActuallyInvalid(invalidElements, invalidElementsDescription); + +compareArrayWithSelector(validElements, ":valid"); +compareArrayWithSelector(invalidElements, ":invalid"); + +makeInvalidElementsValid(invalidElements, invalidElementsDescription, + validElements); + +compareArrayWithSelector(validElements, ":valid"); +compareArrayWithSelector(invalidElements, ":invalid"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug560112.html b/dom/html/test/test_bug560112.html new file mode 100644 index 000000000..1b1daadc4 --- /dev/null +++ b/dom/html/test/test_bug560112.html @@ -0,0 +1,211 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=560112 +--> +<head> + <title>Test for Bug 560112</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=560112">Mozilla Bug 560112</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 560112 **/ + +/** + * Sets dataset property. Checks data attribute "attr". + * Gets dataset property. Checks data attribute "attr". + * Overwrites dataset property Checks data attribute "attr". + * Deletes dataset property. Checks data attribute "attr". + */ +function SetGetOverwriteDel(attr, prop) +{ + var el = document.createElement('div'); + + // Set property. + is(prop in el.dataset, false, 'Property should not be in dataset before setting.'); + el.dataset[prop] = "zzzzzz"; + is(prop in el.dataset, true, 'Property should be in dataset after setting.'); + ok(el.hasAttribute(attr), 'Element should have data attribute for dataset property "' + prop + '".'); + + // Get property. + is(el.dataset[prop], "zzzzzz", 'Dataset property "' + prop + '" should have value "zzzzzz".'); + is(el.getAttribute(attr), "zzzzzz", 'Attribute "' + attr + '" should have value "zzzzzz".'); + + // Overwrite property. + el.dataset[prop] = "yyyyyy"; + is(el.dataset[prop], "yyyyyy", 'Dataset property "' + prop + '" should have value "yyyyyy".'); + is(el.getAttribute(attr), "yyyyyy", 'Attribute "' + attr + '" should have value "yyyyyy".'); + + // Delete property. + delete el.dataset[prop]; + ok(!el.hasAttribute(attr), 'Element should not have data attribute for dataset property "' + prop + '".'); + is(prop in el.dataset, false, 'Deleted property should not be in dataset.'); +} + +/** + * Sets dataset property and expects exception. + */ +function SetExpectException(prop) +{ + var el = document.createElement('div'); + + try { + el.dataset[prop] = "xxxxxx"; + ok(false, 'Exception should have been thrown.'); + } catch (ex) { + ok(true, 'Exception should have been thrown.'); + } +} + +/** + * Adds attributes in "attrList" to element. + * Deletes attributes in "delList" from element. + * Checks for "numProp" properties in dataset. + */ +function DelAttrEnumerate(attrList, delList, numProp) +{ + var el = document.createElement('div'); + + // Adds attributes in "attrList". + for (var i = 0; i < attrList.length; ++i) { + el.setAttribute(attrList[i], "aaaaaa"); + } + + // Remove attributes in "delList". + for (var i = 0; i < delList.length; ++i) { + el.removeAttribute(delList[i]); + } + + var numPropCounted = 0; + + for (var prop in el.dataset) { + if (el.dataset[prop] == "aaaaaa") { + ++numPropCounted; + } + } + + is(numPropCounted, numProp, 'Number of enumerable dataset properties is incorrent after attribute removal.'); +} + +/** + * Adds attributes in "attrList" to element. + * Checks for "numProp" properties in dataset. + */ +function Enumerate(attrList, numProp) +{ + var el = document.createElement('div'); + + // Adds attributes in "attrList" to element. + for (var i = 0; i < attrList.length; ++i) { + el.setAttribute(attrList[i], "aaaaaa"); + } + + var numPropCounted = 0; + + for (var prop in el.dataset) { + if (el.dataset[prop] == "aaaaaa") { + ++numPropCounted; + } + } + + is(numPropCounted, numProp, 'Number of enumerable dataset properties is incorrect.'); +} + +/** + * Adds dataset property then removes attribute from element and check for presence of + * properties using the "in" operator. + */ +function AddPropDelAttr(attr, prop) +{ + var el = document.createElement('div'); + + el.dataset[prop] = 'dddddd'; + is(prop in el.dataset, true, 'Operator "in" should return true after setting property.'); + el.removeAttribute(attr); + is(prop in el.dataset, false, 'Operator "in" should return false for removed attribute.'); +} + +/** + * Adds then removes attribute from element and check for presence of properties using the + * "in" operator. + */ +function AddDelAttr(attr, prop) +{ + var el = document.createElement('div'); + + el.setAttribute(attr, 'dddddd'); + is(prop in el.dataset, true, 'Operator "in" should return true after setting attribute.'); + el.removeAttribute(attr); + is(prop in el.dataset, false, 'Operator "in" should return false for removed attribute.'); +} + +// Typical use case. +SetGetOverwriteDel('data-property', 'property'); +SetGetOverwriteDel('data-a-longer-property', 'aLongerProperty'); + +AddDelAttr('data-property', 'property'); +AddDelAttr('data-a-longer-property', 'aLongerProperty'); + +AddPropDelAttr('data-property', 'property'); +AddPropDelAttr('data-a-longer-property', 'aLongerProperty'); + +// Empty property name. +SetGetOverwriteDel('data-', ''); + +// Leading dash characters. +SetGetOverwriteDel('data--', '-'); +SetGetOverwriteDel('data--d', 'D'); +SetGetOverwriteDel('data---d', '-D'); + +// Trailing dash characters. +SetGetOverwriteDel('data-d-', 'd-'); +SetGetOverwriteDel('data-d--', 'd--'); +SetGetOverwriteDel('data-d-d-', 'dD-'); + +// "data-" in attribute name. +SetGetOverwriteDel('data-data-', 'data-'); +SetGetOverwriteDel('data-data-data-', 'dataData-'); + +// Longer attribute. +SetGetOverwriteDel('data-long-long-long-long-long-long-long-long-long-long-long-long-long', 'longLongLongLongLongLongLongLongLongLongLongLongLong'); + +var longAttr = 'data-long'; +var longProp = 'long'; +for (var i = 0; i < 30000; ++i) { + // Create really long attribute and property names. + longAttr += '-long'; + longProp += 'Long'; +} + +SetGetOverwriteDel(longAttr, longProp); + +// Syntax error in setting dataset property (dash followed by lower case). +SetExpectException('-a'); +SetExpectException('a-a'); +SetExpectException('a-a-a'); + +// Invalid character. +SetExpectException('a a'); + +// Enumeration over dataset properties. +Enumerate(['data-a-big-fish'], 1); +Enumerate(['dat-a-big-fish'], 0); +Enumerate(['data-'], 1); +Enumerate(['data-', 'data-more-data'], 2); +Enumerate(['daaata-', 'data-more-data'], 1); + +// Delete data attributes and enumerate properties. +DelAttrEnumerate(['data-one', 'data-two'], ['data-one'], 1); +DelAttrEnumerate(['data-one', 'data-two'], ['data-three'], 2); +DelAttrEnumerate(['data-one', 'data-two'], ['one'], 2); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug561634.html b/dom/html/test/test_bug561634.html new file mode 100644 index 000000000..61a1486e7 --- /dev/null +++ b/dom/html/test/test_bug561634.html @@ -0,0 +1,126 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=561634 +--> +<head> + <title>Test for Bug 561634</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561634">Mozilla Bug 561634</a> +<p id="display"></p> +<div id="content" style="display: none;"> + <form> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 561634 **/ + +function checkEmptyForm() +{ + ok(document.forms[0].checkValidity(), "An empty form is valid"); +} + +function checkBarredFromConstraintValidation() +{ + var f = document.forms[0]; + var fs = document.createElement('fieldset'); + var i = document.createElement('input'); + + f.appendChild(fs); + i.type = 'hidden'; + f.appendChild(i); + + fs.setCustomValidity("foo"); + i.setCustomValidity("foo"); + + ok(f.checkValidity(), + "A form with invalid element barred from constraint validation should be valid"); + + f.removeChild(i); + f.removeChild(fs); +} + +function checkValid() +{ + var f = document.forms[0]; + var i = document.createElement('input'); + f.appendChild(i); + + ok(f.checkValidity(), "A form with valid elements is valid"); + + f.removeChild(i); +} + +function checkInvalid() +{ + var f = document.forms[0]; + var i = document.createElement('input'); + f.appendChild(i); + + i.setCustomValidity("foo"); + ok(!f.checkValidity(), "A form with invalid elements is invalid"); + + var i2 = document.createElement('input'); + f.appendChild(i2); + ok(!f.checkValidity(), + "A form with at least one invalid element is invalid"); + + f.removeChild(i2); + f.removeChild(i); +} + +function checkInvalidEvent() +{ + var f = document.forms[0]; + var i = document.createElement('input'); + f.appendChild(i); + var i2 = document.createElement('input'); + f.appendChild(i2); + + i.setCustomValidity("foo"); + + var invalidEventForInvalidElement = false; + var invalidEventForValidElement = false; + + i.addEventListener("invalid", function (e) { + invalidEventForInvalidElement = true; + ok(e.cancelable, "invalid event should be cancelable"); + ok(!e.bubbles, "invalid event should not bubble"); + }, false); + + i2.addEventListener("invalid", function (e) { + invalidEventForValidElement = true; + }, false); + + f.checkValidity(); + + setTimeout(function() { + ok(invalidEventForInvalidElement, + "invalid event should be fired on invalid elements"); + ok(!invalidEventForValidElement, + "invalid event should not be fired on valid elements"); + + f.removeChild(i2); + f.removeChild(i); + + SimpleTest.finish(); + }, 0); +} + +SimpleTest.waitForExplicitFinish(); + +checkEmptyForm(); +checkBarredFromConstraintValidation(); +checkValid(); +checkInvalid(); +checkInvalidEvent(); // will call finish(). + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug561636.html b/dom/html/test/test_bug561636.html new file mode 100644 index 000000000..d259e8c83 --- /dev/null +++ b/dom/html/test/test_bug561636.html @@ -0,0 +1,118 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=561636 +--> +<head> + <title>Test for Bug 561636</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561636">Mozilla Bug 561636</a> +<p id="display"></p> +<iframe style='width:50px; height: 50px;' name='t'></iframe> +<iframe style='width:50px; height: 50px;' name='t2' id='i'></iframe> +<div id="content"> + <form target='t' action='data:text/html,'> + <input required> + <input id='a' type='submit'> + </form> + <form target='t' action='data:text/html,'> + <input type='checkbox' required> + <button id='b' type='submit'></button> + </form> + <form target='t' action='data:text/html,'> + <input id='c' required> + </form> + <form target='t' action='data:text/html,'> + <input> + <input id='s2' type='submit'> + </form> + <form target='t2' action='data:text/html,'> + <input required> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 561636 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTest); + +function runTest() +{ + var formSubmitted = [ false, false ]; + var invalidHandled = false; + + var os = SpecialPowers.Cc['@mozilla.org/observer-service;1'] + .getService(SpecialPowers.Ci.nsIObserverService); + var observers = os.enumerateObservers("invalidformsubmit"); + + // The following test should not be done if there is no observer for + // "invalidformsubmit" because the form submission will not be canceled in that + // case. + if (!observers.hasMoreElements()) { + SimpleTest.finish(); + return; + } + + // Initialize + document.forms[0].addEventListener('submit', function(aEvent) { + aEvent.target.removeEventListener('submit', arguments.callee, false); + formSubmitted[0] = true; + }, false); + + document.forms[1].addEventListener('submit', function(aEvent) { + aEvent.target.removeEventListener('submit', arguments.callee, false); + formSubmitted[1] = true; + }, false); + + document.forms[2].addEventListener('submit', function(aEvent) { + aEvent.target.removeEventListener('submit', arguments.callee, false); + formSubmitted[2] = true; + }, false); + + document.forms[3].addEventListener('submit', function(aEvent) { + aEvent.target.removeEventListener('submit', arguments.callee, false); + formSubmitted[3] = true; + + ok(!formSubmitted[0], "Form 1 should not have been submitted because invalid"); + ok(!formSubmitted[1], "Form 2 should not have been submitted because invalid"); + ok(!formSubmitted[2], "Form 3 should not have been submitted because invalid"); + ok(formSubmitted[3], "Form 4 should have been submitted because valid"); + + // Next test. + document.forms[4].submit(); + }, false); + + document.forms[4].elements[0].addEventListener('invalid', function(aEvent) { + aEvent.target.removeEventListener('invalid', arguments.callee, false); + invalidHandled = true; + }, false); + + document.getElementById('i').addEventListener('load', function(aEvent) { + aEvent.target.removeEventListener('load', arguments.callee, false); + + SimpleTest.executeSoon(function () { + ok(true, "Form 5 should have been submitted because submit() has been used even if invalid"); + ok(!invalidHandled, "Invalid event should not have been sent"); + + SimpleTest.finish(); + }); + }, false); + + document.getElementById('a').click(); + document.getElementById('b').click(); + var c = document.getElementById('c'); + c.focus(); + synthesizeKey("KEY_Enter", { code: "Enter" }); + document.getElementById('s2').click(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug561640.html b/dom/html/test/test_bug561640.html new file mode 100644 index 000000000..670d1b3a1 --- /dev/null +++ b/dom/html/test/test_bug561640.html @@ -0,0 +1,72 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=561640 +--> +<head> + <title>Test for Bug 561640</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + input, textarea { background-color: rgb(0,0,0) !important; } + :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; } + :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561640">Mozilla Bug 561640</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 561640 **/ + +var elements = [ 'input', 'textarea' ]; +var content = document.getElementById('content'); + +function checkValid(elmt) +{ + ok(!elmt.validity.tooLong, "element should not be too long"); + is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'), + "rgb(0, 255, 0)", ":valid pseudo-class should apply"); +} + +function checkInvalid(elmt) +{ + todo(elmt.validity.tooLong, "element should be too long"); + todo_is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); +} + +for (var elmtName of elements) { + var elmt = document.createElement(elmtName); + content.appendChild(elmt); + + if (elmtName == 'textarea') { + elmt.textContent = 'foo'; + } else { + elmt.setAttribute('value', 'foo'); + } + elmt.maxLength = 2; + checkValid(elmt); + + elmt.value = 'a'; + checkValid(elmt); + + if (elmtName == 'textarea') { + elmt.textContent = 'f'; + } else { + elmt.setAttribute('value', 'f'); + } + elmt.value = 'bar'; + checkInvalid(elmt); + + content.removeChild(elmt); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug564001.html b/dom/html/test/test_bug564001.html new file mode 100644 index 000000000..3815ac8cf --- /dev/null +++ b/dom/html/test/test_bug564001.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=564001 +--> +<head> + <title>Test for Bug 564001</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=564001">Mozilla Bug 564001</a> +<p id="display"><img usemap=#map src=image.png></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script> +/** Test for Bug 564001 **/ +SimpleTest.waitForExplicitFinish(); + +var wrongArea = document.createElement("area"); +wrongArea.shape = "default"; +wrongArea.href = "#FAIL"; +var wrongMap = document.createElement("map"); +wrongMap.name = "map"; +wrongMap.appendChild(wrongArea); +document.body.appendChild(wrongMap); + +var rightArea = document.createElement("area"); +rightArea.shape = "default"; +rightArea.href = "#PASS"; +var rightMap = document.createElement("map"); +rightMap.name = "map"; +rightMap.appendChild(rightArea); +document.body.insertBefore(rightMap, wrongMap); + +var images = document.getElementsByTagName("img"); +onhashchange = function() { + is(location.hash, "#PASS", "Should get the first map in tree order."); + SimpleTest.finish(); +}; +SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {})); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug566046.html b/dom/html/test/test_bug566046.html new file mode 100644 index 000000000..f12d12536 --- /dev/null +++ b/dom/html/test/test_bug566046.html @@ -0,0 +1,207 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=566046 +--> +<head> + <title>Test for Bug 566046</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <base> + <base target='frame2'> + <base target=''> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566046">Mozilla Bug 566046</a> +<p id="display"></p> +<style> + iframe { width: 130px; height: 100px;} +</style> +<iframe name='frame1' id='frame1'></iframe> +<iframe name='frame2' id='frame2'></iframe> +<iframe name='frame3' id='frame3'></iframe> +<iframe name='frame4' id='frame4'></iframe> +<iframe name='frame5' id='frame5'></iframe> +<iframe name='frame5bis' id='frame5bis'></iframe> +<iframe name='frame6' id='frame6'></iframe> +<iframe name='frame7' id='frame7'></iframe> +<iframe name='frame8' id='frame8'></iframe> +<iframe name='frame9' id='frame9'></iframe> +<div id="content"> + <form target='frame1' action="data:text/html," method="GET"> + <input name='foo' value='foo'> + </form> + <form action="data:text/html," method="GET"> + <input name='bar' value='bar'> + </form> + <form target=""> + </form> + + <!-- submit controls with formtarget that are validated with a CLICK --> + <form target="tulip" action="data:text/html," method="GET"> + <input name='tulip' value='tulip'> + <input type='submit' id='is' formtarget='frame3'> + </form> + <form action="data:text/html," method="GET"> + <input name='foobar' value='foobar'> + <input type='image' id='ii' formtarget='frame4'> + </form> + <form action="data:text/html," method="GET"> + <input name='tulip2' value='tulip2'> + <button type='submit' id='bs' formtarget='frame5'>submit</button> + </form> + <form action="data:text/html," method="GET"> + <input name='tulip3' value='tulip3'> + <button type='submit' id='bsbis' formtarget='frame5bis'>submit</button> + </form> + + <!-- submit controls with formtarget that are validated with ENTER --> + <form target="tulip" action="data:text/html," method="GET"> + <input name='footulip' value='footulip'> + <input type='submit' id='is2' formtarget='frame6'> + </form> + <form action="data:text/html," method="GET"> + <input name='tulipfoobar' value='tulipfoobar'> + <input type='image' id='ii2' formtarget='frame7'> + </form> + <form action="data:text/html," method="GET"> + <input name='tulipbar' value='tulipbar'> + <button type='submit' id='bs2' formtarget='frame8'>submit</button> + </form> + + <!-- check that a which is not a submit control do not use @formtarget --> + <form target='frame9' action="data:text/html," method="GET"> + <input id='enter' name='input' value='enter' formtarget='frame6'> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 566046 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + setTimeout(runTests, 0); +}); + +var gTestResults = { + frame1: "data:text/html,?foo=foo", + frame2: "data:text/html,?bar=bar", + frame3: "data:text/html,?tulip=tulip", + frame4: "data:text/html,?foobar=foobar&x=0&y=0", + frame5: "data:text/html,?tulip2=tulip2", + frame5bis: "data:text/html,?tulip3=tulip3", + frame6: "data:text/html,?footulip=footulip", + frame7: "data:text/html,?tulipfoobar=tulipfoobar&x=0&y=0", + frame8: "data:text/html,?tulipbar=tulipbar", + frame9: "data:text/html,?input=enter", +}; + +var gPendingLoad = 0; // Has to be set after depending on the frames number. + +function runTests() +{ + // Check the target IDL attribute. + for (var i=0; i<document.forms.length; ++i) { + var testValue = document.forms[i].getAttribute('target'); + is(document.forms[i].target, testValue ? testValue : "", + "target IDL attribute should reflect the target content attribute"); + } + + // We add a load event for the frames which will be called when the forms + // will be submitted. + var frames = [ document.getElementById('frame1'), + document.getElementById('frame2'), + document.getElementById('frame3'), + document.getElementById('frame4'), + document.getElementById('frame5'), + document.getElementById('frame5bis'), + document.getElementById('frame6'), + document.getElementById('frame7'), + document.getElementById('frame8'), + document.getElementById('frame9'), + ]; + gPendingLoad = frames.length; + + for (var i=0; i<frames.length; i++) { + frames[i].setAttribute('onload', "frameLoaded(this);"); + } + + // Submitting only the forms with a valid target. + document.forms[0].submit(); + document.forms[1].submit(); + + /** + * We are going to focus each element before interacting with either for + * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or + * using .click(). This because it may be needed (ENTER) and because we want + * to have the element visible in the iframe. + * + * Focusing the first element (id='is') is launching the tests. + */ + document.getElementById('is').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('is'), 5, 5, {}); + document.getElementById('ii').focus(); + }, false); + + document.getElementById('ii').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('ii'), 5, 5, {}); + document.getElementById('bs').focus(); + }, false); + + document.getElementById('bs').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('bs'), 5, 5, {}); + document.getElementById('bsbis').focus(); + }, false); + + document.getElementById('bsbis').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + document.getElementById('bsbis').click(); + document.getElementById('is2').focus(); + }, false); + + document.getElementById('is2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('ii2').focus(); + }, false); + + document.getElementById('ii2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('bs2').focus(); + }, false); + + document.getElementById('bs2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('enter').focus(); + }, false); + + document.getElementById('enter').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + }, false); + + document.getElementById('is').focus(); +} + +function frameLoaded(aFrame) { + // Check if when target is unspecified, it fallback correctly to the base + // element target attribute. + is(aFrame.contentWindow.location.href, gTestResults[aFrame.name], + "the target attribute doesn't have the correct behavior"); + + if (--gPendingLoad == 0) { + SimpleTest.finish(); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug567938-1.html b/dom/html/test/test_bug567938-1.html new file mode 100644 index 000000000..b1c49bfb4 --- /dev/null +++ b/dom/html/test/test_bug567938-1.html @@ -0,0 +1,69 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=567938 +--> +<head> + <title>Test for Bug 567938</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body onload="runTests();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a> +<p id="display"></p> +<iframe id='iframe' name="submit_frame" style="visibility: hidden;"></iframe> +<div id="content" style="display: none"> + <form id='f' method='get' target='submit_frame'> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 567938 **/ + +SimpleTest.waitForExplicitFinish(); + +var gTestData = ["submit", "image"]; +var gCurrentTest = 0; + +function initializeNextTest() +{ + var form = document.forms[0]; + + // Cleaning-up. + form.textContent = ""; + + // Add the new element. + var element = document.createElement("input"); + element.id = 'i'; + element.type = gTestData[gCurrentTest]; + element.onclick = function() { form.submit(); return false; }; + form.action = gTestData[gCurrentTest]; + form.appendChild(element); + + sendMouseEvent({type: 'click'}, 'i'); +} + +function runTests() +{ + document.getElementById('iframe').addEventListener('load', function(aEvent) { + is(frames['submit_frame'].location.href, + "http://mochi.test:8888/tests/dom/html/test/" + gTestData[gCurrentTest], + "The form should have been submitted"); + gCurrentTest++; + if (gCurrentTest < gTestData.length) { + initializeNextTest(); + } else { + aEvent.target.removeEventListener('load', arguments.callee, false); + SimpleTest.finish(); + } + }, false); + + initializeNextTest(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug567938-2.html b/dom/html/test/test_bug567938-2.html new file mode 100644 index 000000000..38d4881ed --- /dev/null +++ b/dom/html/test/test_bug567938-2.html @@ -0,0 +1,70 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=567938 +--> +<head> + <title>Test for Bug 567938</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a> +<p id="display"></p> +<iframe id='iframe' name="submit_frame" style="visibility: hidden;"></iframe> +<div id="content" style="display: none"> + <form id='f' method='get' target='submit_frame'> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 567938 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTests); + +var gTestData = ["submit", "image"]; +var gCurrentTest = 0; + +function initializeNextTest() +{ + var form = document.forms[0]; + + // Cleaning-up. + form.textContent = ""; + + // Add the new element. + var element = document.createElement("input"); + element.id = 'i'; + element.type = gTestData[gCurrentTest]; + element.onclick = function() { form.submit(); element.type='text'; }; + form.action = gTestData[gCurrentTest]; + form.appendChild(element); + + sendMouseEvent({type: 'click'}, 'i'); +} + +function runTests() +{ + document.getElementById('iframe').addEventListener('load', function(aEvent) { + is(frames['submit_frame'].location.href, + "http://mochi.test:8888/tests/dom/html/test/" + gTestData[gCurrentTest], + "The form should have been submitted"); + gCurrentTest++; + if (gCurrentTest < gTestData.length) { + initializeNextTest(); + } else { + aEvent.target.removeEventListener('load', arguments.callee, false); + SimpleTest.finish(); + } + }, false); + + initializeNextTest(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug567938-3.html b/dom/html/test/test_bug567938-3.html new file mode 100644 index 000000000..ab78fb984 --- /dev/null +++ b/dom/html/test/test_bug567938-3.html @@ -0,0 +1,70 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=567938 +--> +<head> + <title>Test for Bug 567938</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a> +<p id="display"></p> +<iframe id='iframe' name="submit_frame" style="visibility: hidden;"></iframe> +<div id="content" style="display: none"> + <form id='f' method='get' target='submit_frame'> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 567938 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTests); + +var gTestData = ["submit", "image"]; +var gCurrentTest = 0; + +function initializeNextTest() +{ + var form = document.forms[0]; + + // Cleaning-up. + form.textContent = ""; + + // Add the new element. + var element = document.createElement("input"); + element.id = 'i'; + element.type = gTestData[gCurrentTest]; + element.onclick = function() { setTimeout("document.forms[0].submit();",0); return false; }; + form.appendChild(element); + form.action = gTestData[gCurrentTest]; + + sendMouseEvent({type: 'click'}, 'i'); +} + +function runTests() +{ + document.getElementById('iframe').addEventListener('load', function(aEvent) { + is(frames['submit_frame'].location.href, + "http://mochi.test:8888/tests/dom/html/test/" + gTestData[gCurrentTest], + "The form should have been submitted"); + gCurrentTest++; + if (gCurrentTest < gTestData.length) { + initializeNextTest(); + } else { + aEvent.target.removeEventListener('load', arguments.callee, false); + SimpleTest.finish(); + } + }, false); + + initializeNextTest(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug567938-4.html b/dom/html/test/test_bug567938-4.html new file mode 100644 index 000000000..749a793ef --- /dev/null +++ b/dom/html/test/test_bug567938-4.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=567938 +--> +<head> + <title>Test for Bug 567938</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a> +<p id="display"></p> +<div id="content" style="display: none"> + <input id='i' type='checkbox' onclick="return false;"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 567938 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTests); + +function runTests() +{ + document.getElementById('i').checked = false; + + document.getElementById('i').addEventListener('click', function(aEvent) { + aEvent.target.removeEventListener('click', arguments.callee, false); + SimpleTest.executeSoon(function() { + ok(!aEvent.target.checked, "the input should not be checked"); + SimpleTest.finish(); + }); + }, false); + + sendMouseEvent({type: 'click'}, 'i'); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug569955.html b/dom/html/test/test_bug569955.html new file mode 100644 index 000000000..252a4ee47 --- /dev/null +++ b/dom/html/test/test_bug569955.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=569955 +--> +<head> + <title>Test for Bug 569955</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=569955">Mozilla Bug 569955</a> +<p id="display"></p> +<div id="content" style="display: none"> + <input id='i' autofocus> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 569955 **/ + +function runTests() +{ + isnot(document.activeElement, document.getElementById('i'), + "not rendered elements can't be autofocused"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + setTimeout(runTests, 0); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug573969.html b/dom/html/test/test_bug573969.html new file mode 100644 index 000000000..308e89e51 --- /dev/null +++ b/dom/html/test/test_bug573969.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=573969 +--> +<head> + <title>Test for Bug 573969</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573969">Mozilla Bug 573969</a> +<p id="display"></p> +<div id="content" style="display: none"> + <xmp id='x'></xmp> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 573969 **/ + +var testData = [ + '<div>foo</div>', + '<div></div>', +]; + +var x = document.getElementById('x'); + +for (v of testData) { + x.innerHTML = v; + is(x.innerHTML, v, "innerHTML value should not be escaped"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug57600.html b/dom/html/test/test_bug57600.html new file mode 100644 index 000000000..a8b976e22 --- /dev/null +++ b/dom/html/test/test_bug57600.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=57600 +--> +<head> + <title>Test for Bug 57600</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=57600">Mozilla Bug 57600</a> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 57600 **/ +SimpleTest.waitForExplicitFinish(); +var count = 0; +function disp(win) { + var d = win ? win.document : self.testname.document; + var str = 'You should see this'; + d.open(); + d.write(str); + d.close(); + is(d.documentElement.textContent, str, "Unexpected text"); + if (++count == 2) { + SimpleTest.finish(); + } +} +</script> +</pre> +<p id="display"> + <iframe src="javascript:'<body onload="this.onerror = parent.onerror; parent.disp(self)"></body>'"> + </iframe> + <iframe name="testname" src="javascript:'<body onload="this.onerror = parent.onerror; parent.disp()"></body>'"> + </iframe> +</p> +</body> +</html> diff --git a/dom/html/test/test_bug579079.html b/dom/html/test/test_bug579079.html new file mode 100644 index 000000000..2f098b3cf --- /dev/null +++ b/dom/html/test/test_bug579079.html @@ -0,0 +1,43 @@ +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=579079 +--> +<head> + <title>Test for Bug 579079</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=579079">Mozilla Bug 579079</a> + +<div id="foo"> + <img name="img1"> + <form name="form1"></form> + <applet name="applet1"></applet> + <embed name="embed1"></embed> + <object name="object1"></object> +</div> + +<pre id="test"> +<script class="testbody" type="text/javascript"> +var img = document.img1; +var form = document.form1; +var applet = document.applet1; +var embed = document.embed1; +var object = document.object1; +$("foo").innerHTML = $("foo").innerHTML; +isnot(document.img1, img); +ok(document.img1 instanceof HTMLImageElement); +isnot(document.form1, form); +ok(document.form1 instanceof HTMLFormElement); +isnot(document.applet1, applet); +ok(document.applet1 instanceof HTMLAppletElement); +isnot(document.embed1, embed); +ok(document.embed1 instanceof HTMLEmbedElement); +isnot(document.object1, object); +ok(document.object1 instanceof HTMLObjectElement); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug582412-1.html b/dom/html/test/test_bug582412-1.html new file mode 100644 index 000000000..4883a3b76 --- /dev/null +++ b/dom/html/test/test_bug582412-1.html @@ -0,0 +1,209 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=566160 +--> +<head> + <title>Test for Bug 566160</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a> +<p id="display"></p> +<style> + iframe { width: 130px; height: 100px;} +</style> +<iframe name='frame1' id='frame1'></iframe> +<iframe name='frame2' id='frame2'></iframe> +<iframe name='frame3' id='frame3'></iframe> +<iframe name='frame3bis' id='frame3bis'></iframe> +<iframe name='frame4' id='frame4'></iframe> +<iframe name='frame5' id='frame5'></iframe> +<iframe name='frame6' id='frame6'></iframe> +<iframe name='frame7' id='frame7'></iframe> +<iframe name='frame8' id='frame8'></iframe> +<iframe name='frame9' id='frame9'></iframe> +<div id="content"> + <!-- submit controls with formaction that are validated with a CLICK --> + <form target="frame1" action="data:text/html," method="POST"> + <input name='foo' value='foo'> + <input type='submit' id='is' formmethod="GET"> + </form> + <form target="frame2" action="data:text/html," method="POST"> + <input name='bar' value='bar'> + <input type='image' id='ii' formmethod="GET"> + </form> + <form target="frame3" action="data:text/html," method="POST"> + <input name='tulip' value='tulip'> + <button type='submit' id='bs' formmethod="GET">submit</button> + </form> + <form target="frame3bis" action="data:text/html," method="POST"> + <input name='tulipbis' value='tulipbis'> + <button type='submit' id='bsbis' formmethod="GET">submit</button> + </form> + + <!-- submit controls with formaction that are validated with ENTER --> + <form target="frame4" action="data:text/html," method="POST"> + <input name='footulip' value='footulip'> + <input type='submit' id='is2' formmethod="GET"> + </form> + <form target="frame5" action="data:text/html," method="POST"> + <input name='foobar' value='foobar'> + <input type='image' id='ii2' formmethod="GET"> + </form> + <form target="frame6" action="data:text/html," method="POST"> + <input name='tulip2' value='tulip2'> + <button type='submit' id='bs2' formmethod="GET">submit</button> + </form> + + <!-- check that when submitting a from from an element + which is not a submit control, @formaction isn't used --> + <form target='frame7' action="data:text/html," method="GET"> + <input id='enter' name='input' value='enter' formmethod="POST"> + </form> + + <!-- If formmethod isn't set, it's default value shouldn't be used --> + <form target="frame8" action="data:text/html," method="POST"> + <input name='tulip8' value='tulip8'> + <input type='submit' id='i8'> + </form> + + <!-- If formmethod is set but has an invalid value, the default value should + be used. --> + <form target="frame9" action="data:text/html," method="POST"> + <input name='tulip9' value='tulip9'> + <input type='submit' id='i9' formmethod=""> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 566160 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + setTimeout(runTests, 0); +}); + +var gTestResults = { + frame1: "data:text/html,?foo=foo", + frame2: "data:text/html,?bar=bar&x=0&y=0", + frame3: "data:text/html,?tulip=tulip", + frame3bis: "data:text/html,?tulipbis=tulipbis", + frame4: "data:text/html,?footulip=footulip", + frame5: "data:text/html,?foobar=foobar&x=0&y=0", + frame6: "data:text/html,?tulip2=tulip2", + frame7: "data:text/html,?input=enter", + frame8: "data:text/html,", + frame9: "data:text/html,?tulip9=tulip9", +}; + +var gPendingLoad = 0; // Has to be set after depending on the frames number. + +function runTests() +{ + // We add a load event for the frames which will be called when the forms + // will be submitted. + var frames = [ document.getElementById('frame1'), + document.getElementById('frame2'), + document.getElementById('frame3'), + document.getElementById('frame3bis'), + document.getElementById('frame4'), + document.getElementById('frame5'), + document.getElementById('frame6'), + document.getElementById('frame7'), + document.getElementById('frame8'), + document.getElementById('frame9'), + ]; + gPendingLoad = frames.length; + + for (var i=0; i<frames.length; i++) { + frames[i].setAttribute('onload', "frameLoaded(this);"); + } + + /** + * We are going to focus each element before interacting with either for + * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or + * using .click(). This because it may be needed (ENTER) and because we want + * to have the element visible in the iframe. + * + * Focusing the first element (id='is') is launching the tests. + */ + document.getElementById('is').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('is'), 5, 5, {}); + document.getElementById('ii').focus(); + }, false); + + document.getElementById('ii').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('ii'), 5, 5, {}); + document.getElementById('bs').focus(); + }, false); + + document.getElementById('bs').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('bs'), 5, 5, {}); + document.getElementById('bsbis').focus(); + }, false); + + document.getElementById('bsbis').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + document.getElementById('bsbis').click(); + document.getElementById('is2').focus(); + }, false); + + document.getElementById('is2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('ii2').focus(); + }, false); + + document.getElementById('ii2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('bs2').focus(); + }, false); + + document.getElementById('bs2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('enter').focus(); + }, false); + + document.getElementById('enter').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('i8').focus(); + }, false); + + document.getElementById('i8').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('i9').focus(); + }, false); + + document.getElementById('i9').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + }, false); + + document.getElementById('is').focus(); +} + +function frameLoaded(aFrame) { + // Check if formaction/action has the correct behavior. + is(aFrame.contentWindow.location.href, gTestResults[aFrame.name], + "the method/formmethod attribute doesn't have the correct behavior"); + + if (--gPendingLoad == 0) { + SimpleTest.finish(); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug582412-2.html b/dom/html/test/test_bug582412-2.html new file mode 100644 index 000000000..59175679c --- /dev/null +++ b/dom/html/test/test_bug582412-2.html @@ -0,0 +1,209 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=566160 +--> +<head> + <title>Test for Bug 566160</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a> +<p id="display"></p> +<style> + iframe { width: 130px; height: 100px;} +</style> +<iframe name='frame1' id='frame1'></iframe> +<iframe name='frame2' id='frame2'></iframe> +<iframe name='frame3' id='frame3'></iframe> +<iframe name='frame3bis' id='frame3bis'></iframe> +<iframe name='frame4' id='frame4'></iframe> +<iframe name='frame5' id='frame5'></iframe> +<iframe name='frame6' id='frame6'></iframe> +<iframe name='frame7' id='frame7'></iframe> +<iframe name='frame8' id='frame8'></iframe> +<iframe name='frame9' id='frame9'></iframe> +<div id="content"> + <!-- submit controls with formaction that are validated with a CLICK --> + <form target="frame1" action="form_submit_server.sjs" method="POST"> + <input name='foo' value='foo'> + <input type='submit' id='is' formenctype='multipart/form-data'> + </form> + <form target="frame2" action="form_submit_server.sjs" method="POST"> + <input name='bar' value='bar'> + <input type='image' id='ii' formenctype='multipart/form-data'> + </form> + <form target="frame3" action="form_submit_server.sjs" method="POST"> + <input name='tulip' value='tulip'> + <button type='submit' id='bs' formenctype="multipart/form-data">submit</button> + </form> + <form target="frame3bis" action="form_submit_server.sjs" method="POST"> + <input name='tulipbis' value='tulipbis'> + <button type='submit' id='bsbis' formenctype="multipart/form-data">submit</button> + </form> + + <!-- submit controls with formaction that are validated with ENTER --> + <form target="frame4" action="form_submit_server.sjs" method="POST"> + <input name='footulip' value='footulip'> + <input type='submit' id='is2' formenctype="multipart/form-data"> + </form> + <form target="frame5" action="form_submit_server.sjs" method="POST"> + <input name='foobar' value='foobar'> + <input type='image' id='ii2' formenctype="multipart/form-data"> + </form> + <form target="frame6" action="form_submit_server.sjs" method="POST"> + <input name='tulip2' value='tulip2'> + <button type='submit' id='bs2' formenctype="multipart/form-data">submit</button> + </form> + + <!-- check that when submitting a from from an element + which is not a submit control, @formaction isn't used --> + <form target='frame7' action="form_submit_server.sjs" method="POST"> + <input id='enter' name='input' value='enter' formenctype="multipart/form-data"> + </form> + + <!-- If formenctype isn't set, it's default value shouldn't be used --> + <form target="frame8" action="form_submit_server.sjs" method="POST" enctype="multipart/form-data"> + <input name='tulip8' value='tulip8'> + <input type='submit' id='i8'> + </form> + + <!-- If formenctype is set but has an invalid value, the default value should + be used. --> + <form target="frame9" action="form_submit_server.sjs" method="POST" enctype="multipart/form-data"> + <input name='tulip9' value='tulip9'> + <input type='submit' id='i9' formenctype=""> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 566160 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + setTimeout(runTests, 0); +}); + +var gTestResults = { + frame1: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"foo\\\"\"},\"body\":\"foo\"}]', + frame2: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"bar\\\"\"},\"body\":\"bar\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"x\\\"\"},\"body\":\"0\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"y\\\"\"},\"body\":\"0\"}]', + frame3: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip\\\"\"},\"body\":\"tulip\"}]', + frame3bis: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulipbis\\\"\"},\"body\":\"tulipbis\"}]', + frame4: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"footulip\\\"\"},\"body\":\"footulip\"}]', + frame5: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"foobar\\\"\"},\"body\":\"foobar\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"x\\\"\"},\"body\":\"0\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"y\\\"\"},\"body\":\"0\"}]', + frame6: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip2\\\"\"},\"body\":\"tulip2\"}]', + frame7: '[]', + frame8: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip8\\\"\"},\"body\":\"tulip8\"}]', + frame9: '[]', +}; + +var gPendingLoad = 0; // Has to be set after depending on the frames number. + +function runTests() +{ + // We add a load event for the frames which will be called when the forms + // will be submitted. + var frames = [ document.getElementById('frame1'), + document.getElementById('frame2'), + document.getElementById('frame3'), + document.getElementById('frame3bis'), + document.getElementById('frame4'), + document.getElementById('frame5'), + document.getElementById('frame6'), + document.getElementById('frame7'), + document.getElementById('frame8'), + document.getElementById('frame9'), + ]; + gPendingLoad = frames.length; + + for (var i=0; i<frames.length; i++) { + frames[i].setAttribute('onload', "frameLoaded(this);"); + } + + /** + * We are going to focus each element before interacting with either for + * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or + * using .click(). This because it may be needed (ENTER) and because we want + * to have the element visible in the iframe. + * + * Focusing the first element (id='is') is launching the tests. + */ + document.getElementById('is').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('is'), 5, 5, {}); + document.getElementById('ii').focus(); + }, false); + + document.getElementById('ii').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('ii'), 5, 5, {}); + document.getElementById('bs').focus(); + }, false); + + document.getElementById('bs').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeMouse(document.getElementById('bs'), 5, 5, {}); + document.getElementById('bsbis').focus(); + }, false); + + document.getElementById('bsbis').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + document.getElementById('bsbis').click(); + document.getElementById('is2').focus(); + }, false); + + document.getElementById('is2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('ii2').focus(); + }, false); + + document.getElementById('ii2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('bs2').focus(); + }, false); + + document.getElementById('bs2').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('enter').focus(); + }, false); + + document.getElementById('enter').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('i8').focus(); + }, false); + + document.getElementById('i8').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + document.getElementById('i9').focus(); + }, false); + + document.getElementById('i9').addEventListener('focus', function(aEvent) { + aEvent.target.removeEventListener('focus', arguments.callee, false); + synthesizeKey("VK_RETURN", {}); + }, false); + + document.getElementById('is').focus(); +} + +function frameLoaded(aFrame) { + // Check if formaction/action has the correct behavior. + is(aFrame.contentDocument.documentElement.textContent, gTestResults[aFrame.name], + "the enctype/formenctype attribute doesn't have the correct behavior"); + + if (--gPendingLoad == 0) { + SimpleTest.finish(); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug583514.html b/dom/html/test/test_bug583514.html new file mode 100644 index 000000000..20e7824e6 --- /dev/null +++ b/dom/html/test/test_bug583514.html @@ -0,0 +1,71 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=583514 +--> +<head> + <title>Test for Bug 583514</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583514">Mozilla Bug 583514</a> +<p id="display"></p> +<div id="content"> + <input> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 583514 **/ + +var gExpectDivClick = false; +var gExpectInputClick = false; + +var div = document.getElementById('content'); +var input = document.getElementsByTagName('input')[0]; + +div.addEventListener('click', function() { + ok(gExpectDivClick, "click event received on div and expected status was: " + + gExpectDivClick); +}, false); + +input.addEventListener('click', function() { + ok(gExpectInputClick, "click event received on input and expected status was: " + + gExpectInputClick); +}, false); + +SimpleTest.waitForExplicitFinish(); + +SimpleTest.waitForFocus(function() { + var body = document.body; + + body.addEventListener('click', function(aEvent) { + if (aEvent.target == input) { + body.removeEventListener('click', arguments.callee, false); + } + + ok(true, "click event received on body"); + + SimpleTest.executeSoon(function() { + isnot(document.activeElement, input, "input shouldn't have been focused"); + isnot(document.activeElement, div, "div shouldn't have been focused"); + + if (aEvent.target == input) { + SimpleTest.finish(); + } else { + gExpectDivClick = true; + gExpectInputClick = true; + input.click(); + } + }); + }, false); + + gExpectDivClick = true; + div.click(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug583533.html b/dom/html/test/test_bug583533.html new file mode 100644 index 000000000..1042b6f09 --- /dev/null +++ b/dom/html/test/test_bug583533.html @@ -0,0 +1,81 @@ +<!DOCTYPE HTML> +<html> + <!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=583533 +--> + <head> + <title>Test for Bug 583514</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + </head> + <body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583533">Mozilla Bug 583533</a> + <p id="display"></p> + <div id="content"> + <div id="e" accesskey="a"> + </div> +</div> +<pre id="test"> +<script type="application/javascript"> + + /** Test for Bug 583533 **/ + + var sbs = SpecialPowers.Cc['@mozilla.org/intl/stringbundle;1']. + getService(SpecialPowers.Ci.nsIStringBundleService); + var bundle = sbs.createBundle("chrome://global-platform/locale/platformKeys.properties"); + + var shiftText = bundle.GetStringFromName("VK_SHIFT"); + var altText = bundle.GetStringFromName("VK_ALT"); + var controlText = bundle.GetStringFromName("VK_CONTROL"); + var metaText = bundle.GetStringFromName("VK_META"); + var separatorText = bundle.GetStringFromName("MODIFIER_SEPARATOR"); + + var modifier = SpecialPowers.getIntPref("ui.key.contentAccess"); + + var isShift; + var isAlt; + var isControl; + var isMeta; + + is(modifier < 16 && modifier >= 0, true, "Modifier in range"); + + // There are no consts for the mask of this prefs. + if (modifier & 8) { + isMeta = true; + } + if (modifier & 1) { + isShift = true; + } + if (modifier & 2) { + isControl = true; + } + if (modifier & 4) { + isAlt = true; + } + + var label = ""; + + if (isControl) + label += controlText + separatorText; + if (isMeta) + label += metaText + separatorText; + if (isAlt) + label += altText + separatorText; + if (isShift) + label += shiftText + separatorText; + + label += document.getElementById("e").accessKey; + + is(label, document.getElementById("e").accessKeyLabel, "JS and C++ agree on accessKeyLabel"); + + /** Test for Bug 808964 **/ + + var div = document.createElement("div"); + document.body.appendChild(div); + + is(div.accessKeyLabel, "", "accessKeyLabel should be empty string"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug586763.html b/dom/html/test/test_bug586763.html new file mode 100644 index 000000000..9ecf00ea8 --- /dev/null +++ b/dom/html/test/test_bug586763.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=586763 +--> +<title>Test for Bug 586763</title> +<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=586763">Mozilla Bug 586763</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script> +/** Test for Bug 586763 **/ +var tests = [ + ["ol", "start", 1], + ["li", "value", 0], + ["object", "hspace", 0], + ["object", "vspace", 0], + ["img", "hspace", 0], + ["img", "vspace", 0], + ["video", "height", 0], + ["video", "width", 0], + ["pre", "width", 0], + ["textarea", "cols", 20], + ["textarea", "rows", 2], + ["span", "tabIndex", -1], + ["frame", "tabIndex", 0], + ["a", "tabIndex", 0], + ["area", "tabIndex", 0], + ["button", "tabIndex", 0], + ["input", "tabIndex", 0], + ["object", "tabIndex", -1], + ["select", "tabIndex", 0], + ["textarea", "tabIndex", 0], +]; + +for (var i = 0; i < tests.length; i++) { + is(document.createElement(tests[i][0])[tests[i][1]], tests[i][2], "Reflected attribute " + tests[i][0] + "." + tests[i][1] + " should default to " + tests[i][2]); +} +</script> +</pre> diff --git a/dom/html/test/test_bug586786.html b/dom/html/test/test_bug586786.html new file mode 100644 index 000000000..17d95c2a5 --- /dev/null +++ b/dom/html/test/test_bug586786.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=586786 +--> +<head> + <title>Test for Bug 586786</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=586786">Mozilla Bug 586786</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 586786 **/ + +var elements = ["col", "colgroup", "tbody", "tfoot", "thead", "tr", "td", "th"]; + +for(var i = 0; i < elements.length; i++) +{ + reflectString({ + element: document.createElement(elements[i]), + attribute: "align", + otherValues: [ "left", "right", "center", "justify", "char" ] + }); + + reflectString({ + element: document.createElement(elements[i]), + attribute: "vAlign", + otherValues: [ "top", "middle", "bottom", "baseline" ] + }); + + reflectString({ + element: document.createElement(elements[i]), + attribute: {idl: "ch", content: "char"} + }); +} + +// table.border, table.width +reflectString({ + element: document.createElement("table"), + attribute: "border" +}); + +reflectString({ + element: document.createElement("table"), + attribute: "width" +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug587469.html b/dom/html/test/test_bug587469.html new file mode 100644 index 000000000..b0e941296 --- /dev/null +++ b/dom/html/test/test_bug587469.html @@ -0,0 +1,41 @@ +<!-- Quirks --> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=587469 +--> +<head> + <title>Test for Bug 587469</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=587469">Mozilla Bug 587469</a> +<p id="display"> +<map name=a></map> +<map name=a><area shape=rect coords=25,25,75,75 href=#fail></map> +<img usemap=#a src=image.png> +</p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for Bug 587469 **/ +SimpleTest.waitForExplicitFinish(); +function finish() { + is(location.hash, "", "Should not have changed the hash."); + SimpleTest.finish(); +} +SimpleTest.waitForFocus(function() { + synthesizeMouse(document.getElementsByTagName("img")[0], 50, 50, {}); + // Hit the event loop twice before doing the test + setTimeout(function() { + setTimeout(finish, 0); + }, 0); +}); + + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug589.html b/dom/html/test/test_bug589.html new file mode 100644 index 000000000..a5d0eabdb --- /dev/null +++ b/dom/html/test/test_bug589.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=589 +--> +<head> + <title>Test for Bug 589</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<style type="text/css"> +.letters {list-style-type: upper-alpha;} +.numbers {list-style-type: decimal;} +</style> + +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=589">Mozilla Bug 589</a> +<p id="display"></p> +<div id="content" > + +<OL id="thelist" class="letters"> +<LI id="liA">This list should feature... +<LI id="liB">...letters for each item... +<LI id="li3" class="numbers">...except this one. +</OL> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 589 **/ + +is(computedStyle($("liA"),"list-style-type"),"upper-alpha"); +is(computedStyle($("liB"),"list-style-type"),"upper-alpha"); +is(computedStyle($("li3"),"list-style-type"),"decimal"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug590353-1.html b/dom/html/test/test_bug590353-1.html new file mode 100644 index 000000000..c7aa52ab9 --- /dev/null +++ b/dom/html/test/test_bug590353-1.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=590353 +--> +<head> + <title>Test for Bug 590353</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=590353">Mozilla Bug 590353</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 590353 **/ + +var testData = ['checkbox', 'radio']; + +for (var data of testData) { + var e = document.createElement('input'); + e.type = data; + e.checked = true; + e.value = "foo"; + + is(e.value, "foo", "foo should be the new " + data + "value"); + is(e.getAttribute('value'), "foo", "foo should be the new " + data + + " value attribute value"); + ok(e.checked, data + " should still be checked"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug590353-2.html b/dom/html/test/test_bug590353-2.html new file mode 100644 index 000000000..db44efab1 --- /dev/null +++ b/dom/html/test/test_bug590353-2.html @@ -0,0 +1,79 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=590353 +--> +<head> + <title>Test for Bug 590353</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=590353">Mozilla Bug 590353</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 590353 **/ + +var testData = [ + [ "text", "foo", "" ], + [ "email", "foo@bar.com", "" ], + [ "url", "http:///foo.com", "" ], + [ "tel", "555 555 555 555", "" ], + [ "search", "foo", "" ], + [ "password", "secret", "" ], + [ "hidden", "foo", "foo" ], + [ "button", "foo", "foo" ], + [ "reset", "foo", "foo" ], + [ "submit", "foo", "foo" ], + [ "checkbox", true, false ], + [ "radio", true, false ], + [ "file", "590353_file", "" ], +]; + +function createFileWithData(fileName, fileData) { + return new File([new Blob([fileData], { type: "text/plain" })], fileName); +} + +var content = document.getElementById('content'); +var form = document.createElement('form'); +content.appendChild(form); + +for (var data of testData) { + var e = document.createElement('input'); + e.type = data[0]; + + if (data[0] == 'checkbox' || data[0] == 'radio') { + e.checked = data[1]; + } else if (data[0] == 'file') { + var file = createFileWithData(data[1], "file content"); + SpecialPowers.wrap(e).mozSetFileArray([file]); + } else { + e.value = data[1]; + } + + form.appendChild(e); +} + +form.reset(); + +var size = form.elements.length; +for (var i=0; i<size; ++i) { + var e = form.elements[i]; + + if (e.type == 'radio' || e.type == 'checkbox') { + is(e.checked, testData[i][2], + "the element checked value should be " + testData[i][2]); + } else { + is(e.value, testData[i][2], + "the element value should be " + testData[i][2]); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug590363.html b/dom/html/test/test_bug590363.html new file mode 100644 index 000000000..3e72b542c --- /dev/null +++ b/dom/html/test/test_bug590363.html @@ -0,0 +1,133 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=590363 +--> +<head> + <title>Test for Bug 590363</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=590363">Mozilla Bug 590363</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 590363 **/ + +var testData = [ + /* type to test | is the value reset when changing to file then reverting */ + [ "button", false ], + [ "checkbox", false ], + [ "hidden", false ], + [ "reset", false ], + [ "image", false ], + [ "radio", false ], + [ "submit", false ], + [ "tel", true ], + [ "text", true ], + [ "url", true ], + [ "email", true ], + [ "search", true ], + [ "password", true ], + [ "number", true ], + [ "date", true ], + [ "time", true ], + [ "range", true ], + [ "color", true ], + [ 'month', true ], + [ 'week', true ], + [ 'datetime-local', true ] + // 'file' is treated separatly. +]; + +var nonTrivialSanitizing = [ 'number', 'date', 'time', 'color', 'month', 'week', + 'datetime-local' ]; + +var length = testData.length; +for (var i=0; i<length; ++i) { + for (var j=0; j<length; ++j) { + var e = document.createElement('input'); + e.type = testData[i][0]; + + var expectedValue; + + // range will sanitize its value to 50 (the default) if it isn't a valid + // number. We need to handle that specially. + if (testData[j][0] == 'range' || testData[i][0] == 'range') { + if (testData[j][0] == 'date' || testData[j][0] == 'time' || + testData[j][0] == 'month' || testData[j][0] == 'week' || + testData[j][0] == 'datetime-local') { + expectedValue = ''; + } else if (testData[j][0] == 'color') { + expectedValue = '#000000'; + } else { + expectedValue = '50'; + } + } else if (testData[i][0] == 'color' || testData[j][0] == 'color') { + if (testData[j][0] == 'number' || testData[j][0] == 'date' || + testData[j][0] == 'time' || testData[j][0] == 'month' || + testData[j][0] == 'week' || testData[j][0] == 'datetime-local') { + expectedValue = '' + } else { + expectedValue = '#000000'; + } + } else if (nonTrivialSanitizing.indexOf(testData[i][0]) != -1 && + nonTrivialSanitizing.indexOf(testData[j][0]) != -1) { + expectedValue = ''; + } else if (testData[i][0] == 'number' || testData[j][0] == 'number') { + expectedValue = '42'; + } else if (testData[i][0] == 'date' || testData[j][0] == 'date') { + expectedValue = '2012-12-21'; + } else if (testData[i][0] == 'time' || testData[j][0] == 'time') { + expectedValue = '21:21'; + } else if (testData[i][0] == 'month' || testData[j][0] == 'month') { + expectedValue = '2013-03'; + } else if (testData[i][0] == 'week' || testData[j][0] == 'week') { + expectedValue = '2016-W35'; + } else if (testData[i][0] == 'datetime-local' || + testData[j][0] == 'datetime-local') { + expectedValue = '2016-11-07T16:40'; + } else { + expectedValue = "foo"; + } + e.value = expectedValue; + + e.type = testData[j][0]; + is(e.value, expectedValue, ".value should still return the same value after " + + "changing type from " + testData[i][0] + " to " + testData[j][0]); + } +} + +// For type='file' .value doesn't behave the same way. +// We are just going to check that we do not loose the value. +for (var data of testData) { + var e = document.createElement('input'); + e.type = data[0]; + e.value = 'foo'; + e.type = 'file'; + e.type = data[0]; + + if (data[0] == 'range') { + is(e.value, '50', ".value should still return the same value after " + + "changing type from " + data[0] + " to 'file' then reverting to " + data[0]); + } else if (data[0] == 'color') { + is(e.value, '#000000', ".value should have been reset to the default color after " + + "changing type from " + data[0] + " to 'file' then reverting to " + data[0]); + } else if (data[1]) { + is(e.value, '', ".value should have been reset to the empty string after " + + "changing type from " + data[0] + " to 'file' then reverting to " + data[0]); + } else { + is(e.value, 'foo', ".value should still return the same value after " + + "changing type from " + data[0] + " to 'file' then reverting to " + data[0]); + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug592802.html b/dom/html/test/test_bug592802.html new file mode 100644 index 000000000..c2c9df9ed --- /dev/null +++ b/dom/html/test/test_bug592802.html @@ -0,0 +1,97 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=592802 +--> +<head> + <title>Test for Bug 592802</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=592802">Mozilla Bug 592802</a> +<p id="display"></p> +<div id="content"> + <input id='a' type='file'> + <input id='a2' type='file'> +</div> +<button id='b' onclick="document.getElementById('a').click();">Show Filepicker</button> +<button id='b2' onclick="document.getElementById('a2').click();">Show Filepicker</button> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 592802 **/ + +SimpleTest.waitForExplicitFinish(); + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +var testData = [ +/* visibility | display | multiple */ + [ "", "", false ], + [ "hidden", "", false ], + [ "", "none", false ], + [ "", "", true ], + [ "hidden", "", true ], + [ "", "none", true ], +]; + +var testCounter = 0; +var testNb = testData.length; + +function finished() +{ + MockFilePicker.cleanup(); + SimpleTest.finish(); +} + +SimpleTest.waitForFocus(function() { + // mockFilePicker will simulate a cancel for the first time the file picker will be shown. + MockFilePicker.returnValue = MockFilePicker.returnCancel; + + var b2 = document.getElementById('b2'); + b2.focus(); // Be sure the element is visible. + document.getElementById('b2').addEventListener("change", function(aEvent) { + aEvent.target.removeEventListener("change", arguments.callee, false); + ok(false, "When cancel is received, change should not fire"); + }, false); + b2.click(); + + // Now, we can launch tests when file picker isn't canceled. + MockFilePicker.useBlobFile(); + MockFilePicker.returnValue = MockFilePicker.returnOK; + + var b = document.getElementById('b'); + b.focus(); // Be sure the element is visible. + + document.getElementById('a').addEventListener("change", function(aEvent) { + ok(true, "change event correctly sent"); + ok(aEvent.bubbles, "change event should bubble"); + ok(!aEvent.cancelable, "change event should not be cancelable"); + testCounter++; + + if (testCounter >= testNb) { + aEvent.target.removeEventListener("change", arguments.callee, false); + SimpleTest.executeSoon(finished); + } else { + var data = testData[testCounter]; + var a = document.getElementById('a'); + a.style.visibility = data[0]; + a.style.display = data[1]; + a.multiple = data[2]; + + SimpleTest.executeSoon(function() { + b.click(); + }); + } + }, false); + + b.click(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug593689.html b/dom/html/test/test_bug593689.html new file mode 100644 index 000000000..782601f35 --- /dev/null +++ b/dom/html/test/test_bug593689.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=593689 +--> +<head> + <title>Test for Bug 593689</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=593689">Mozilla Bug 593689</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 593689 **/ +function testWidth(w) { + var img = new Image(w); + is(img.width, w|0, "Unexpected handling of '" + w + "' width"); +} + +testWidth(1); +testWidth(0); +testWidth("xxx"); +testWidth(null); +testWidth(undefined); +testWidth({}); +testWidth({ valueOf: function() { return 10; } }); + +function testHeight(h) { + var img = new Image(100, h); + is(img.height, h|0, "Unexpected handling of '" + h + "' height"); +} + +testHeight(1); +testHeight(0); +testHeight("xxx"); +testHeight(null); +testHeight(undefined); +testHeight({}); +testHeight({ valueOf: function() { return 10; } }); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug595429.html b/dom/html/test/test_bug595429.html new file mode 100644 index 000000000..74535705e --- /dev/null +++ b/dom/html/test/test_bug595429.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=595429 +--> +<head> + <title>Test for Bug 595429</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595429">Mozilla Bug 595429</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 595429 **/ + +var fieldset = document.createElement("fieldset"); + +ok("name" in fieldset, "<fieldset> should have a name IDL attribute"); + +var testData = [ + "", + " ", + "foo", + "foo bar", +]; + +is(fieldset.getAttribute("name"), null, + "By default, name content attribute should be null"); +is(fieldset.name, "", + "By default, name IDL attribute should be the empty string"); + +for (var data of testData) { + fieldset.setAttribute("name", data); + is(fieldset.getAttribute("name"), data, + "name content attribute should be " + data); + is(fieldset.name, data, "name IDL attribute should be " + data); + + fieldset.setAttribute("name", ""); + fieldset.name = data; + is(fieldset.getAttribute("name"), data, + "name content attribute should be " + data); + is(fieldset.name, data, "name IDL attribute should be " + data); +} + +fieldset.removeAttribute("name"); +is(fieldset.getAttribute("name"), null, + "name content attribute should be null"); +is(fieldset.name, "", "name IDL attribute should be the empty string"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug595447.html b/dom/html/test/test_bug595447.html new file mode 100644 index 000000000..015af69d4 --- /dev/null +++ b/dom/html/test/test_bug595447.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=595447 +--> +<head> + <title>Test for Bug 595447</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595447">Mozilla Bug 595447</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 595447 **/ + +var fieldset = document.createElement("fieldset"); + +ok("type" in fieldset, "fieldset element should have a type IDL attribute"); +is(fieldset.type, "fieldset", "fieldset.type should return 'fieldset'"); +fieldset.type = "foo"; +is(fieldset.type, "fieldset", "fieldset.type is readonly"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug595449.html b/dom/html/test/test_bug595449.html new file mode 100644 index 000000000..14d5e5ced --- /dev/null +++ b/dom/html/test/test_bug595449.html @@ -0,0 +1,95 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=595449 +--> +<head> + <title>Test for Bug 595449</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595449">Mozilla Bug 595449</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 595449 **/ + +var fieldset = document.createElement("fieldset"); + +ok("elements" in fieldset, + "fieldset element should have an 'elements' IDL attribute"); + +ok(fieldset.elements instanceof HTMLCollection, + "fieldset.elements should be an instance of HTMLCollection"); + +// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23356 +todo(fieldset.elements instanceof HTMLFormControlsCollection, + "fieldset.elements should be an instance of HTMLFormControlsCollection"); + +is(fieldset.elements.length, 0, "Nothing should be in fieldset.elements"); + +var oldElements = fieldset.elements; + +is(fieldset.elements, oldElements, + "fieldset.elements should always return the same object"); + +var tmpElement = document.createElement("input"); + +fieldset.appendChild(tmpElement); + +is(fieldset.elements.length, 1, + "fieldset.elements should now contain one element"); + +is(fieldset.elements[0], tmpElement, + "fieldset.elements[0] should be the input element"); + +tmpElement.name = "foo"; +is(fieldset.elements.foo, tmpElement, + "we should be able to access to an element using it's name as a property on .elements"); + +is(fieldset.elements, oldElements, + "fieldset.elements should always return the same object"); + +fieldset.removeChild(tmpElement); + +var testData = [ + [ "<input>", 1 , [ HTMLInputElement ] ], + [ "<button></button>", 1, [ HTMLButtonElement ] ], + [ "<button><input></button>", 2, [ HTMLButtonElement, HTMLInputElement ] ], + [ "<object>", 1, [ HTMLObjectElement ] ], + [ "<output></output>", 1, [ HTMLOutputElement ] ], + [ "<select></select>", 1, [ HTMLSelectElement ] ], + [ "<select><option>foo</option></select>", 1, [ HTMLSelectElement ] ], + [ "<select><option>foo</option><input></select>", 2, [ HTMLSelectElement, HTMLInputElement ] ], + [ "<textarea></textarea>", 1, [ HTMLTextAreaElement ] ], + [ "<label>foo</label>", 0 ], + [ "<progress>", 0 ], + [ "<meter>", 0 ], + [ "<keygen>", 1, [ HTMLSelectElement ] ], + [ "<legend></legend>", 0 ], + [ "<legend><input></legend>", 1, [ HTMLInputElement ] ], + [ "<legend><input></legend><legend><input></legend>", 2, [ HTMLInputElement, HTMLInputElement ] ], + [ "<legend><input></legend><input>", 2, [ HTMLInputElement, HTMLInputElement ] ], + [ "<fieldset></fieldset>", 1, [ HTMLFieldSetElement ] ], + [ "<fieldset><input></fieldset>", 2, [ HTMLFieldSetElement, HTMLInputElement ] ], + [ "<fieldset><fieldset><input></fieldset></fieldset>", 3, [ HTMLFieldSetElement, HTMLFieldSetElement, HTMLInputElement ] ], + [ "<button></button><fieldset></fieldset><input><keygen><object><output></output><select></select><textarea></textarea>", 8, [ HTMLButtonElement, HTMLFieldSetElement, HTMLInputElement, HTMLSelectElement, HTMLObjectElement, HTMLOutputElement, HTMLSelectElement, HTMLTextAreaElement ] ], +]; + +for (var data of testData) { + fieldset.innerHTML = data[0]; + is(fieldset.elements.length, data[1], + "fieldset.elements should contain " + data[1] + " elements"); + + for (var i=0; i<data[1]; ++i) { + ok(fieldset.elements[i] instanceof data[2][i], + "fieldset.elements[" + i + "] should be instance of " + data[2][i]) + } +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug596350.html b/dom/html/test/test_bug596350.html new file mode 100644 index 000000000..a92484ef7 --- /dev/null +++ b/dom/html/test/test_bug596350.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=596350 +--> +<head> + <title>Test for Bug 596350</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596350">Mozilla Bug 596350</a> +<p id="display"></p> +<div id="content"> + <object></object> + <object data="iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMsALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0vr4MkhoXe0rZigAAAABJRU5ErkJggg=="></object> + <object data="data:text/html,foo"></object> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 596350 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(runTests); + +var testData = [ +// Object 0 + [ 0, null, -1 ], + [ 0, "1", 1 ], + [ 0, "-1", -1 ], + [ 0, "0", 0 ], + [ 0, "foo", -1 ], +// Object 1 + [ 1, null, -1 ], + [ 1, "1", 1 ], +// Object 2 + [ 2, null, 0 ], + [ 2, "1", 1 ], + [ 2, "-1", -1 ], +]; + +var objects = document.getElementsByTagName("object"); + +function runTests() +{ + for (var data of testData) { + var obj = objects[data[0]]; + + if (data[1]) { + obj.setAttribute("tabindex", data[1]); + } + + is(obj.tabIndex, data[2], "tabIndex value should be " + data[2]); + + obj.removeAttribute("tabindex"); + } + + SimpleTest.finish(); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug596511.html b/dom/html/test/test_bug596511.html new file mode 100644 index 000000000..e539c5b73 --- /dev/null +++ b/dom/html/test/test_bug596511.html @@ -0,0 +1,229 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=596511 +--> +<head> + <title>Test for Bug 596511</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + select:valid { background-color: green; } + select:invalid { background-color: red; } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596511">Mozilla Bug 596511</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 596511 **/ + +function checkNotSufferingFromBeingMissing(element, aTodo) +{ + if (aTodo) { + ok = todo; + is = todo_is; + } + + ok(!element.validity.valueMissing, + "Element should not suffer from value missing"); + ok(element.validity.valid, "Element should be valid"); + ok(element.checkValidity(), "Element should be valid"); + + is(element.validationMessage, "", + "Validation message should be the empty string"); + + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(0, 128, 0)", ":valid pseudo-class should apply"); + + if (aTodo) { + ok = SimpleTest.ok; + is = SimpleTest.is; + } +} + +function checkSufferingFromBeingMissing(element, aTodo) +{ + if (aTodo) { + ok = todo; + is = todo_is; + } + + ok(element.validity.valueMissing, "Element should suffer from value missing"); + ok(!element.validity.valid, "Element should not be valid"); + ok(!element.checkValidity(), "Element should not be valid"); + + is(element.validationMessage, "Please select an item in the list.", + "Validation message is wrong"); + + is(window.getComputedStyle(element, null).getPropertyValue('background-color'), + "rgb(255, 0, 0)", ":invalid pseudo-class should apply"); + + if (aTodo) { + ok = SimpleTest.ok; + is = SimpleTest.is; + } +} + +function checkRequiredAttribute(element) +{ + ok('required' in element, "select should have a required attribute"); + + ok(!element.required, "select required attribute should be disabled"); + is(element.getAttribute('required'), null, + "select required attribute should be disabled"); + + element.required = true; + ok(element.required, "select required attribute should be enabled"); + isnot(element.getAttribute('required'), null, + "select required attribute should be enabled"); + + element.removeAttribute('required'); + element.setAttribute('required', ''); + ok(element.required, "select required attribute should be enabled"); + isnot(element.getAttribute('required'), null, + "select required attribute should be enabled"); + + element.removeAttribute('required'); + ok(!element.required, "select required attribute should be disabled"); + is(element.getAttribute('required'), null, + "select required attribute should be disabled"); +} + +function checkRequiredAndOptionalSelectors(element) +{ + is(document.querySelector("select:optional"), element, + "select should be optional"); + is(document.querySelector("select:required"), null, + "select shouldn't be required"); + + element.required = true; + + is(document.querySelector("select:optional"), null, + "select shouldn't be optional"); + is(document.querySelector("select:required"), element, + "select should be required"); + + element.required = false; +} + +function checkInvalidWhenValueMissing(element) +{ + checkNotSufferingFromBeingMissing(select); + + element.required = true; + checkSufferingFromBeingMissing(select); + + /** + * Non-multiple and size=1. + */ + select.appendChild(new Option()); + checkSufferingFromBeingMissing(select); + + // When removing the required attribute, element should not be invalid. + element.required = false; + checkNotSufferingFromBeingMissing(select); + + element.required = true; + select.options[0].textContent = "foo"; + // TODO: having that working would require us to add a mutation observer on + // the select element. + checkNotSufferingFromBeingMissing(select, true); + + select.remove(0); + checkSufferingFromBeingMissing(select); + + select.add(new Option("foo", "foo"), null); + checkNotSufferingFromBeingMissing(select); + + select.add(new Option(), null); + checkNotSufferingFromBeingMissing(select); + + select.options[1].selected = true; + checkSufferingFromBeingMissing(select); + + select.selectedIndex = 0; + checkNotSufferingFromBeingMissing(select); + + select.selectedIndex = 1; + checkSufferingFromBeingMissing(select); + + select.remove(1); + checkNotSufferingFromBeingMissing(select); + + select.options[0].disabled = true; + // TODO: having that working would require us to add a mutation observer on + // the select element. + checkSufferingFromBeingMissing(select, true); + + select.options[0].disabled = false + select.remove(0); + checkSufferingFromBeingMissing(select); + + var option = new Option("foo", "foo"); + option.disabled = true; + select.add(option, null); + select.add(new Option("bar"), null); + option.selected = true; + checkSufferingFromBeingMissing(select); + + select.remove(0); + select.remove(0); + + /** + * Non-multiple and size > 1. + * Everything should be the same except moving the selection. + */ + select.multiple = false; + select.size = 4; + checkSufferingFromBeingMissing(select); + + select.add(new Option("", "", true), null); + checkSufferingFromBeingMissing(select); + + select.add(new Option("foo", "foo"), null); + select.remove(0); + checkSufferingFromBeingMissing(select); + + select.options[0].selected = true; + checkNotSufferingFromBeingMissing(select); + + select.remove(0); + + /** + * Multiple, any size. + * We can select more than one element and at least needs a value. + */ + select.multiple = true; + select.size = 4; + checkSufferingFromBeingMissing(select); + + select.add(new Option("", "", true), null); + checkSufferingFromBeingMissing(select); + + select.add(new Option("", "", true), null); + checkSufferingFromBeingMissing(select); + + select.add(new Option("foo"), null); + checkSufferingFromBeingMissing(select); + + select.options[2].selected = true; + checkNotSufferingFromBeingMissing(select); +} + +var select = document.createElement("select"); +var content = document.getElementById('content'); +content.appendChild(select); + +checkRequiredAttribute(select); +checkRequiredAndOptionalSelectors(select); +checkInvalidWhenValueMissing(select); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug598643.html b/dom/html/test/test_bug598643.html new file mode 100644 index 000000000..53c1df97c --- /dev/null +++ b/dom/html/test/test_bug598643.html @@ -0,0 +1,80 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=598643 +--> +<head> + <title>Test for Bug 598643</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=598643">Mozilla Bug 598643</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 598643 **/ + +function createFileWithData(fileName, fileData) +{ + return new File([new Blob([fileData], { type: "text/plain" })], fileName); +} + +function testFileControl(aElement) +{ + aElement.type = 'file'; + + var file = createFileWithData("file_bug598643", "file content"); + SpecialPowers.wrap(aElement).mozSetFileArray([file]); + + ok(aElement.validity.valid, "the file control should be valid"); + ok(!aElement.validity.tooLong, + "the file control shouldn't suffer from being too long"); +} + +var types = [ + // These types can be too long. + [ "text", "email", "password", "url", "search", "tel" ], + // These types can't be too long. + [ "radio", "checkbox", "submit", "button", "reset", "image", "hidden", + 'number', 'range', 'date', 'time', 'color', 'month', 'week', + 'datetime-local' ], +]; + +var input = document.createElement("input"); +input.maxLength = 1; +input.value = "foo"; + +// Too long types. +for (type of types[0]) { + input.type = type + if (type == 'email') { + input.value = "foo@bar.com"; + } else if (type == 'url') { + input.value = 'http://foo.org'; + } + + todo(!input.validity.valid, "the element should be invalid [type=" + type + "]"); + todo(input.validity.tooLong, + "the element should suffer from being too long [type=" + type + "]"); + + if (type == 'email' || type == 'url') { + input.value = 'foo'; + } +} + +// Not too long types. +for (type of types[1]) { + input.type = type + ok(input.validity.valid, "the element should be valid [type=" + type + "]"); + ok(!input.validity.tooLong, + "the element shouldn't suffer from being too long [type=" + type + "]"); +} + +testFileControl(input); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug598833-1.html b/dom/html/test/test_bug598833-1.html new file mode 100644 index 000000000..6b50b8df8 --- /dev/null +++ b/dom/html/test/test_bug598833-1.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=598833 +--> +<head> + <title>Test for Bug 598833</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=598833">Mozilla Bug 598833</a> +<p id="display"> + <fieldset disabled> + <select id="s" multiple required> + <option>one</option> + </select> + </fieldset> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 598833 **/ +var s = $("s"); +is(s.matches(":invalid"), false, "Disabled select should not be invalid"); +is(s.matches(":valid"), false, "Disabled select should not be valid"); +var p = s.parentNode; +p.removeChild(s); +is(s.matches(":invalid"), true, + "Required valueless select not in tree should be invalid"); +is(s.matches(":valid"), false, + "Required valueless select not in tree should not be valid"); +p.appendChild(s); +p.disabled = false; +is(s.matches(":invalid"), true, + "Required valueless select should be invalid"); +is(s.matches(":valid"), false, + "Required valueless select should not be valid"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug600155.html b/dom/html/test/test_bug600155.html new file mode 100644 index 000000000..bb10ddfb7 --- /dev/null +++ b/dom/html/test/test_bug600155.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=600155 +--> +<head> + <title>Test for Bug 600155</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=600155">Mozilla Bug 600155</a> +<p id="display"></p> +<div id='content' style='display:none;'> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 600155 **/ + +var subjectForConstraintValidation = [ "input", "select", "textarea" ]; +var content = document.getElementById('content'); + +for (var eName of subjectForConstraintValidation) { + var e = document.createElement(eName); + content.appendChild(e); + e.setAttribute("x-moz-errormessage", "foo"); + if ("required" in e) { + e.required = true; + } else { + e.setCustomValidity("bar"); + } + + // At this point, the element is invalid. + is(e.validationMessage, "foo", + "the validation message should be the author one"); + + content.removeChild(e); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug601030.html b/dom/html/test/test_bug601030.html new file mode 100644 index 000000000..f4fc5b986 --- /dev/null +++ b/dom/html/test/test_bug601030.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=601030 +--> +<head> + <title>Test for Bug 601030</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=601030">Mozilla Bug 601030</a> +<p id="display"></p> +<div id="content"> + <iframe src="data:text/html,<input autofocus>"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 601030 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + var f = document.createElement("iframe"); + var content = document.getElementById('content'); + + f.addEventListener("load", function() { + f.removeEventListener("load", arguments.callee, false); + SimpleTest.executeSoon(function() { + isnot(document.activeElement, f, + "autofocus should not work when another frame is inserted in the document"); + + content.removeChild(f); + content.removeChild(document.getElementsByTagName('iframe')[0]); + f = document.createElement('iframe'); + f.addEventListener("load", function() { + f.removeEventListener("load", arguments.callee, false); + isnot(document.activeElement, f, + "autofocus should not work in a frame if the top document is already loaded"); + SimpleTest.finish(); + }, false); + f.src = "data:text/html,<input autofocus>"; + content.appendChild(f); + }); + }, false); + + f.src = "data:text/html,<input autofocus>"; + content.appendChild(f); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug605124-1.html b/dom/html/test/test_bug605124-1.html new file mode 100644 index 000000000..7c3a8ee9b --- /dev/null +++ b/dom/html/test/test_bug605124-1.html @@ -0,0 +1,107 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=605124 +--> +<head> + <title>Test for Bug 605124</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605124">Mozilla Bug 605124</a> +<p id="display"></p> +<div id="content"> + <form> + <textarea required></textarea> + <input required> + <select required></select> + <button type='submit'></button> + </form> + + <table> + <form> + <tr> + <textarea required></textarea> + <input required> + <select required></select> + <button type='submit'></button> + </tr> + </form> + </table> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 605124 **/ + +function checkPseudoClass(aElement, aExpected) +{ + is(aElement.matches(":-moz-ui-invalid"), aExpected, + "matches(':-moz-ui-invalid') should return " + aExpected + " for " + aElement); +} + +var os = SpecialPowers.Cc['@mozilla.org/observer-service;1'] + .getService(SpecialPowers.Ci.nsIObserverService); +var observers = os.enumerateObservers("invalidformsubmit"); + +if (observers.hasMoreElements()) { + var content = document.getElementById('content'); + var textarea = document.getElementsByTagName('textarea')[0]; + var input = document.getElementsByTagName('input')[0]; + var select = document.getElementsByTagName('select')[0]; + var button = document.getElementsByTagName('button')[0]; + var form = document.forms[0]; + + checkPseudoClass(textarea, false); + checkPseudoClass(input, false); + checkPseudoClass(select, false); + + // Try to submit. + button.click(); + checkPseudoClass(textarea, true); + checkPseudoClass(input, true); + checkPseudoClass(select, true); + + // No longer in the form. + content.appendChild(textarea); + content.appendChild(input); + content.appendChild(select); + checkPseudoClass(textarea, false); + checkPseudoClass(input, false); + checkPseudoClass(select, false); + + // Back in the form. + form.appendChild(textarea); + form.appendChild(input); + form.appendChild(select); + checkPseudoClass(textarea, true); + checkPseudoClass(input, true); + checkPseudoClass(select, true); + + /* Case when elements get orphaned. */ + var textarea = document.getElementsByTagName('textarea')[1]; + var input = document.getElementsByTagName('input')[1]; + var select = document.getElementsByTagName('select')[1]; + var button = document.getElementsByTagName('button')[1]; + var form = document.forms[1]; + + // Try to submit. + button.click(); + checkPseudoClass(textarea, true); + checkPseudoClass(input, true); + checkPseudoClass(select, true); + + // Remove the form. + document.getElementsByTagName('table')[0].removeChild(form); + checkPseudoClass(textarea, false); + checkPseudoClass(input, false); + checkPseudoClass(select, false); +} else { + todo(false, "No 'invalidformsubmit' observers. Skip test."); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug605124-2.html b/dom/html/test/test_bug605124-2.html new file mode 100644 index 000000000..8ac9027f5 --- /dev/null +++ b/dom/html/test/test_bug605124-2.html @@ -0,0 +1,112 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=605124 +--> +<head> + <title>Test for Bug 605124</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605124">Mozilla Bug 605124</a> +<p id="display"></p> +<div id="content"> + <input required> + <textarea required></textarea> + <select required> + <option value="">foo</option> + <option>bar</option> + </select> + <select multiple required> + <option value="">foo</option> + <option>bar</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 605124 **/ + +function checkPseudoClass(aElement, aExpected) +{ + is(aElement.matches(":-moz-ui-invalid"), aExpected, + "matches(':-moz-ui-invalid') should return " + aExpected + " for " + aElement); +} + +function checkElement(aElement) +{ + checkPseudoClass(aElement, false); + + // Focusing while :-moz-ui-invalid doesn't apply, + // the pseudo-class should not apply while typing. + aElement.focus(); + checkPseudoClass(aElement, false); + // with keys + synthesizeKey('f', {}); + checkPseudoClass(aElement, false); + synthesizeKey('VK_BACK_SPACE', {}); + checkPseudoClass(aElement, false); + // with .value + aElement.value = 'f'; + checkPseudoClass(aElement, false); + aElement.value = ''; + checkPseudoClass(aElement, false); + + aElement.blur(); + checkPseudoClass(aElement, true); + + // Focusing while :-moz-ui-invalid applies, + // the pseudo-class should apply while typing if appropriate. + aElement.focus(); + checkPseudoClass(aElement, true); + // with keys + synthesizeKey('f', {}); + checkPseudoClass(aElement, false); + synthesizeKey('VK_BACK_SPACE', {}); + checkPseudoClass(aElement, true); + // with .value + aElement.value = 'f'; + checkPseudoClass(aElement, false); + aElement.value = ''; + checkPseudoClass(aElement, true); +} + +function checkSelectElement(aElement) +{ + checkPseudoClass(aElement, false); + + // Focusing while :-moz-ui-invalid doesn't apply, + // the pseudo-class should not apply while changing selection. + aElement.focus(); + checkPseudoClass(aElement, false); + + aElement.selectedIndex = 1; + checkPseudoClass(aElement, false); + aElement.selectedIndex = 0; + checkPseudoClass(aElement, false); + + aElement.blur(); + checkPseudoClass(aElement, true); + + // Focusing while :-moz-ui-invalid applies, + // the pseudo-class should apply while changing selection if appropriate. + aElement.focus(); + checkPseudoClass(aElement, true); + + aElement.selectedIndex = 1; + checkPseudoClass(aElement, false); + aElement.selectedIndex = 0; + checkPseudoClass(aElement, true); +} + +checkElement(document.getElementsByTagName('input')[0]); +checkElement(document.getElementsByTagName('textarea')[0]); +checkSelectElement(document.getElementsByTagName('select')[0]); +checkSelectElement(document.getElementsByTagName('select')[1]); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug605125-1.html b/dom/html/test/test_bug605125-1.html new file mode 100644 index 000000000..1a89af7ab --- /dev/null +++ b/dom/html/test/test_bug605125-1.html @@ -0,0 +1,113 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=605125 +--> +<head> + <title>Test for Bug 605125</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605125">Mozilla Bug 605125</a> +<p id="display"></p> +<div id="content"> + <form id='f1'> + <textarea></textarea> + <input> + <button type='submit'></button> + <select></select> + </form> + + <table> + <form id='f2'> + <tr> + <textarea></textarea> + <input> + <button type='submit'></button> + <select></select> + </tr> + </form> + </table> + <input form='f1' required> + <input form='f2' required> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 605125 **/ + +/** + * NOTE: this test is very similar to 605124-1.html. + */ + +function checkPseudoClass(aElement, aExpected) +{ + is(aElement.matches(":-moz-ui-valid"), aExpected, + "matches(':-moz-ui-valid') should return " + aExpected + " for " + aElement); +} + +var os = SpecialPowers.Cc['@mozilla.org/observer-service;1'] + .getService(SpecialPowers.Ci.nsIObserverService); +var observers = os.enumerateObservers("invalidformsubmit"); + +if (observers.hasMoreElements()) { + var content = document.getElementById('content'); + var textarea = document.getElementsByTagName('textarea')[0]; + var input = document.getElementsByTagName('input')[0]; + var button = document.getElementsByTagName('button')[0]; + var select = document.getElementsByTagName('select')[0]; + var form = document.forms[0]; + + checkPseudoClass(textarea, false); + checkPseudoClass(input, false); + checkPseudoClass(select, false); + + // Try to submit. + button.click(); + checkPseudoClass(textarea, true); + checkPseudoClass(input, true); + checkPseudoClass(select, true); + + // No longer in the form. + content.appendChild(textarea); + content.appendChild(input); + content.appendChild(select); + checkPseudoClass(textarea, false); + checkPseudoClass(input, false); + checkPseudoClass(select, false); + + // Back in the form. + form.appendChild(textarea); + form.appendChild(input); + form.appendChild(select); + checkPseudoClass(textarea, true); + checkPseudoClass(input, true); + checkPseudoClass(select, true); + + /* Case when elements get orphaned. */ + var textarea = document.getElementsByTagName('textarea')[1]; + var input = document.getElementsByTagName('input')[1]; + var button = document.getElementsByTagName('button')[1]; + var select = document.getElementsByTagName('select')[1]; + var form = document.forms[1]; + + // Try to submit. + button.click(); + checkPseudoClass(textarea, true); + checkPseudoClass(input, true); + checkPseudoClass(select, true); + + // Remove the form. + document.getElementsByTagName('table')[0].removeChild(form); + checkPseudoClass(textarea, false); + checkPseudoClass(input, false); + checkPseudoClass(select, false); +} else { + todo(false, "No 'invalidformsubmit' observers. Skip test."); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug605125-2.html b/dom/html/test/test_bug605125-2.html new file mode 100644 index 000000000..4d5c4a46a --- /dev/null +++ b/dom/html/test/test_bug605125-2.html @@ -0,0 +1,145 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=605125 +--> +<head> + <title>Test for Bug 605125</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605125">Mozilla Bug 605125</a> +<p id="display"></p> +<div id="content"> + <input> + <textarea></textarea> + <select> + <option value="">foo</option> + <option>bar</option> + </select> + <select multiple> + <option value="">foo</option> + <option>bar</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 605125 **/ + +function checkPseudoClass(aElement, aExpected) +{ + is(aElement.matches(":-moz-ui-valid"), aExpected, + "matches(':-moz-ui-valid') should return " + aExpected + " for " + aElement); +} + +function checkElement(aElement) +{ + checkPseudoClass(aElement, false); + + // Focusing while :-moz-ui-valid doesn't apply, + // the pseudo-class should not apply while typing. + aElement.focus(); + checkPseudoClass(aElement, false); + // with keys + synthesizeKey('f', {}); + checkPseudoClass(aElement, false); + synthesizeKey('VK_BACK_SPACE', {}); + checkPseudoClass(aElement, false); + // with .value + aElement.value = 'f'; + checkPseudoClass(aElement, false); + aElement.value = ''; + checkPseudoClass(aElement, false); + + aElement.blur(); + checkPseudoClass(aElement, true); + + // Focusing while :-moz-ui-valid applies, + // the pseudo-class should apply while typing if appropriate. + aElement.focus(); + checkPseudoClass(aElement, true); + // with keys + synthesizeKey('f', {}); + checkPseudoClass(aElement, true); + synthesizeKey('VK_BACK_SPACE', {}); + checkPseudoClass(aElement, true); + // with .value + aElement.value = 'f'; + checkPseudoClass(aElement, true); + aElement.value = ''; + checkPseudoClass(aElement, true); + + aElement.blur(); + aElement.required = true; + checkPseudoClass(aElement, false); + + // Focusing while :-moz-ui-invalid applies, + // the pseudo-class should apply while typing if appropriate. + aElement.focus(); + checkPseudoClass(aElement, false); + // with keys + synthesizeKey('f', {}); + checkPseudoClass(aElement, true); + synthesizeKey('VK_BACK_SPACE', {}); + checkPseudoClass(aElement, false); + // with .value + aElement.value = 'f'; + checkPseudoClass(aElement, true); + aElement.value = ''; + checkPseudoClass(aElement, false); +} + +function checkSelectElement(aElement) +{ + checkPseudoClass(aElement, false); + + // Focusing while :-moz-ui-valid doesn't apply, + // the pseudo-class should not apply while changing selection. + aElement.focus(); + checkPseudoClass(aElement, false); + + aElement.selectedIndex = 1; + checkPseudoClass(aElement, false); + aElement.selectedIndex = 0; + checkPseudoClass(aElement, false); + + aElement.blur(); + checkPseudoClass(aElement, true); + + // Focusing while :-moz-ui-valid applies, + // the pseudo-class should apply while changing selection if appropriate. + aElement.focus(); + checkPseudoClass(aElement, true); + + aElement.selectedIndex = 1; + checkPseudoClass(aElement, true); + aElement.selectedIndex = 0; + checkPseudoClass(aElement, true); + + aElement.blur(); + aElement.required = true; + checkPseudoClass(aElement, false); + + // Focusing while :-moz-ui-invalid applies, + // the pseudo-class should apply while changing selection if appropriate. + aElement.focus(); + checkPseudoClass(aElement, false); + + aElement.selectedIndex = 1; + checkPseudoClass(aElement, true); + aElement.selectedIndex = 0; + checkPseudoClass(aElement, false); +} + +checkElement(document.getElementsByTagName('input')[0]); +checkElement(document.getElementsByTagName('textarea')[0]); +checkSelectElement(document.getElementsByTagName('select')[0]); +checkSelectElement(document.getElementsByTagName('select')[1]); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug606817.html b/dom/html/test/test_bug606817.html new file mode 100644 index 000000000..3de26efc0 --- /dev/null +++ b/dom/html/test/test_bug606817.html @@ -0,0 +1,64 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=606817 +--> +<head> + <title>Test for Bug 606817</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=606817">Mozilla Bug 606817</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 606817 **/ + +var messageMaxLength = 256; + +function checkMessage(aInput, aMsg, aWithTerminalPeriod) +{ + ok(aInput.validationMessage != aMsg, + "Original content-defined message should have been truncate"); + is(aInput.validationMessage.length - aInput.validationMessage.indexOf("_42_"), + aWithTerminalPeriod ? messageMaxLength+1 : messageMaxLength, + "validation message should be 256 characters length"); +} + +var input = document.createElement("input"); + +var msg = ""; +for (var i=0; i<75; ++i) { + msg += "_42_"; +} +// msg is now 300 chars long + +// Testing with setCustomValidity(). +input.setCustomValidity(msg); +checkMessage(input, msg, false); + +// The input is still invalid but x-moz-errormessage will be used as the message. +input.setAttribute("x-moz-errormessage", msg); +checkMessage(input, msg, false); + +// Cleaning. +input.setCustomValidity(""); +input.removeAttribute("x-moz-errormessage"); + +// Testing with pattern and titl. +input.pattern = "[0-9]*"; +input.value = "foo"; +input.title = msg; +checkMessage(input, msg, true); + +// Cleaning. +input.removeAttribute("pattern"); +input.removeAttribute("title"); +input.value = ""; + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug607145.html b/dom/html/test/test_bug607145.html new file mode 100644 index 000000000..f32fff18f --- /dev/null +++ b/dom/html/test/test_bug607145.html @@ -0,0 +1,82 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=607145 +--> +<head> + <title>Test for Bug 607145</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=607145">Mozilla Bug 607145</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 607145 **/ + +/** + * This is not really reflecting an URL as the HTML5 specs want to. + * It's how .action is reflected in Gecko (might change later). + * + * If this changes, add reflectURL for "formAction" in + * dom/html/test/forms/test_input_attributes_reflection.html and + * "action" in + * dom/html/test/forms/test_form_attributes_reflection.html + */ +function reflectURL(aElement, aAttr) +{ + var idl = aAttr; + var attr = aAttr.toLowerCase(); + var elmtName = aElement.tagName.toLowerCase(); + + ok(idl in aElement, idl + " should be available in " + elmtName); + + // Default values. + is(aElement[idl], "", "." + idl + " default value should be the empty string"); + is(aElement.getAttribute(attr), null, + "@" + attr + " default value should be null"); + + var previousDir = location.href.replace(/test\/[^\/]*$/, ""); + var dir = location.href.replace(/test_bug607145.html[^\/]*$/, ""); + var doc = location.href.replace(/\.html.*/, ".html") + var values = [ + /* value to set, resolved value */ + [ "foo.html", dir + "foo.html" ], + [ "data:text/html,<html></html>", "data:text/html,<html></html>" ], + [ "http://example.org/", "http://example.org/" ], + [ "//example.org/", "http://example.org/" ], + [ "?foo=bar", doc + "?foo=bar" ], + [ "#foo", location.href + "#foo" ], + [ "", "" ], // TODO: doesn't follow the specs, should be location.href. + [ " ", location.href ], + [ "../", previousDir ], + [ "...", dir + "..." ], + // invalid URL + [ "http://a b/", "http://a b/" ], // TODO: doesn't follow the specs, should be "". + ]; + + for (var value of values) { + aElement[idl] = value[0]; + is(aElement[idl], value[1], "." + idl + " value should be " + value[1]); + is(aElement.getAttribute(attr), value[0], + "@" + attr + " value should be " + value[0]); + } + + for (var value of values) { + aElement.setAttribute(attr, value[0]); + is(aElement[idl], value[1], "." + idl + " value should be " + value[1]); + is(aElement.getAttribute(attr), value[0], + "@" + attr + " value should be " + value[0]); + } +} + +reflectURL(document.createElement("form"), "action"); +reflectURL(document.createElement("input"), "formAction"); +reflectURL(document.createElement("button"), "formAction"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug610212.html b/dom/html/test/test_bug610212.html new file mode 100644 index 000000000..56bb18dc1 --- /dev/null +++ b/dom/html/test/test_bug610212.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=610212 +--> +<head> + <title>Test for Bug 610212</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=610212">Mozilla Bug 610212</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 610212 **/ + +var canvas = document.createElement('canvas'); + +reflectUnsignedInt({ + element: canvas, + attribute: "width", + nonZero: false, + defaultValue: 300, +}); + +reflectUnsignedInt({ + element: canvas, + attribute: "height", + nonZero: false, + defaultValue: 150, +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug610687.html b/dom/html/test/test_bug610687.html new file mode 100644 index 000000000..f319685ed --- /dev/null +++ b/dom/html/test/test_bug610687.html @@ -0,0 +1,201 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=610687 +--> +<head> + <title>Test for Bug 610687</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=610687">Mozilla Bug 610687</a> +<p id="display"></p> +<div id="content" style="display: none"> + <form> + <input type='radio' name='a'> + <input type='radio' name='a'> + <input type='radio' name='b'> + </form> + <input type='radio' name='a'> + <input type='radio' name='a'> + <input type='radio' name='b'> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 610687 **/ + +function checkPseudoClasses(aElement, aValid, aValidUI, aInvalidUI) +{ + if (aValid) { + ok(aElement.matches(":valid"), ":valid should apply"); + } else { + ok(aElement.matches(":invalid"), ":invalid should apply"); + } + + is(aElement.matches(":-moz-ui-valid"), aValidUI, + aValid ? ":-moz-ui-valid should apply" : ":-moz-ui-valid should not apply"); + + is(aElement.matches(":-moz-ui-invalid"), aInvalidUI, + aInvalidUI ? ":-moz-ui-invalid should apply" : ":-moz-ui-invalid should not apply"); + + if (aInvalidUI && (aValid || aValidUI)) { + ok(false, ":invalid can't apply with :valid or :-moz-valid-ui"); + } +} + +/** + * r1 and r2 should be in the same group. + * r3 should be in another group. + * form can be null. + */ +function checkRadios(r1, r2, r3, form) +{ + // Default state. + checkPseudoClasses(r1, true, false, false); + checkPseudoClasses(r2, true, false, false); + checkPseudoClasses(r3, true, false, false); + + // Suffering from being missing (without ui-invalid). + r1.required = true; + checkPseudoClasses(r1, false, false, false); + checkPseudoClasses(r2, false, false, false); + checkPseudoClasses(r3, true, false, false); + + // Suffering from being missing (with ui-invalid). + r1.checked = false; + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, false, false, true); + checkPseudoClasses(r3, true, false, false); + + // Do not suffer from being missing (with ui-valid). + r1.checked = true; + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, true, true, false); + checkPseudoClasses(r3, true, false, false); + + // Do not suffer from being missing (with ui-valid). + r1.checked = false; + r1.required = false; + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, true, true, false); + checkPseudoClasses(r3, true, false, false); + + // Suffering from being missing (with ui-invalid) with required set on one radio + // and the checked state changed on another. + r1.required = true; + r2.checked = false; + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, false, false, true); + checkPseudoClasses(r3, true, false, false); + + // Do not suffer from being missing (with ui-valid) by checking the radio which + // hasn't the required attribute. + r2.checked = true; + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, true, true, false); + checkPseudoClasses(r3, true, false, false); + + // .setCustomValidity() should not affect the entire group. + r1.checked = r2.checked = r3.checked = false; + r1.required = false; + r1.setCustomValidity('foo'); + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, true, true, false); + checkPseudoClasses(r3, true, true, false); + + r1.setCustomValidity(''); + r2.setCustomValidity('foo'); + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, false, false, true); + checkPseudoClasses(r3, true, true, false); + + r2.setCustomValidity(''); + r3.setCustomValidity('foo'); + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, true, true, false); + checkPseudoClasses(r3, false, false, true); + + // Removing the radio with the required attribute should make the group valid. + r1.setCustomValidity(''); + r2.setCustomValidity(''); + r1.required = false; + r2.required = true; + r1.checked = r2.checked = false; + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, false, false, true); + + var p = r2.parentNode; + p.removeChild(r2); + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, false, false, true); + + p.appendChild(r2); + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, false, false, true); + + // Adding a radio element to an invalid group should make it invalid. + p.removeChild(r1); + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, false, false, true); + + p.appendChild(r1); + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, false, false, true); + + // Adding a checked radio element to an invalid group should make it valid. + p.removeChild(r1); + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, false, false, true); + + r1.checked = true; + p.appendChild(r1); + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, true, true, false); + r1.checked = false; + + // Adding an invalid radio element by changing the name attribute. + r2.name = 'c'; + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, false, false, true); + + r2.name = 'a'; + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, false, false, true); + + // Adding an element to an invalid radio group by changing the name attribute. + r1.name = 'c'; + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, false, false, true); + + r1.name = 'a'; + checkPseudoClasses(r1, false, false, true); + checkPseudoClasses(r2, false, false, true); + + // Adding a checked element to an invalid radio group with the name attribute. + r1.name = 'c'; + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, false, false, true); + + r1.checked = true; + r1.name = 'a'; + checkPseudoClasses(r1, true, true, false); + checkPseudoClasses(r2, true, true, false); + r1.checked = false; +} + +var r1 = document.getElementsByTagName('input')[0]; +var r2 = document.getElementsByTagName('input')[1]; +var r3 = document.getElementsByTagName('input')[2]; +checkRadios(r1, r2, r3); + +r1 = document.getElementsByTagName('input')[3]; +r2 = document.getElementsByTagName('input')[4]; +r3 = document.getElementsByTagName('input')[5]; +checkRadios(r1, r2, r3); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug611189.html b/dom/html/test/test_bug611189.html new file mode 100644 index 000000000..13ca618d6 --- /dev/null +++ b/dom/html/test/test_bug611189.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=611189 +--> +<head> + <title>Test for Bug 611189</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=611189">Mozilla Bug 611189</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 611189 **/ +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + var i = document.createElement("input"); + var b = document.getElementById("content"); + b.appendChild(i); + b.clientWidth; // bind to frame + i.focus(); // initialize editor + var before = snapshotWindow(window, true); + i.value = "L"; // set the value + i.style.display = "none"; + b.clientWidth; // unbind from frame + i.value = ""; // set the value without a frame + i.style.display = ""; + b.clientWidth; // rebind to frame + is(i.value, "", "Input's value should be correctly updated"); + var after = snapshotWindow(window, true); + ok(compareSnapshots(before, after, true), "The correct value should be rendered inside the control"); + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug612730.html b/dom/html/test/test_bug612730.html new file mode 100644 index 000000000..4c6d906e3 --- /dev/null +++ b/dom/html/test/test_bug612730.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=612730 +--> +<head> + <title>Test for Bug 612730</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=612730">Mozilla Bug 612730</a> +<p id="display"></p> +<div id="content"> + <select multiple required> + <option value="">foo</option> + <option value="">bar</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 612730 **/ + +SimpleTest.waitForExplicitFinish(); + +function runTest() +{ + var select = document.getElementsByTagName('select')[0]; + + select.addEventListener("focus", function() { + select.removeEventListener("focus", arguments.callee, false); + + isnot(select.selectedIndex, -1, "Something should have been selected"); + + ok(!select.matches(":-moz-ui-valid"), + ":-moz-ui-valid should not apply"); + todo(!select.matches(":-moz-ui-invalid"), + ":-moz-ui-invalid should not apply"); + + SimpleTest.finish(); + }, false); + + synthesizeMouse(select, 5, 5, {}); +} + +SimpleTest.waitForFocus(runTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug613019.html b/dom/html/test/test_bug613019.html new file mode 100644 index 000000000..bb28d108a --- /dev/null +++ b/dom/html/test/test_bug613019.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=613019 +--> +<head> + <title>Test for Bug 613019</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613019">Mozilla Bug 613019</a> +<div id="content"> + <input type="text" maxlength="2" style="width:200px" value="Test"> + <textarea maxlength="2" style="width:200px">Test</textarea> + <input type="text" minlength="6" style="width:200px" value="Test"> + <textarea minlength="6" style="width:200px">Test</textarea> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 613019 **/ + +function testInteractivityOfMaxLength(elem) { + // verify that user interactivity is necessary for validity state to apply. + is(elem.value, "Test", "Element has incorrect starting value."); + is(elem.validity.tooLong, false, "Element should not be tooLong."); + + elem.setSelectionRange(elem.value.length, elem.value.length) + elem.focus(); + + synthesizeKey("VK_BACK_SPACE", {}); + is(elem.value, "Tes", "Element value was not changed correctly."); + is(elem.validity.tooLong, true, "Element should still be tooLong."); + + synthesizeKey("VK_BACK_SPACE", {}); + is(elem.value, "Te", "Element value was not changed correctly."); + is(elem.validity.tooLong, false, "Element should no longer be tooLong."); + + elem.value = "Test"; + is(elem.validity.tooLong, false, + "Element should not be tooLong after non-interactive value change."); +} + +function testInteractivityOfMinLength(elem) { + // verify that user interactivity is necessary for validity state to apply. + is(elem.value, "Test", "Element has incorrect starting value."); + is(elem.validity.tooLong, false, "Element should not be tooShort."); + + elem.setSelectionRange(elem.value.length, elem.value.length) + elem.focus(); + + synthesizeKey("e", {}); + is(elem.value, "Teste", "Element value was not changed correctly."); + is(elem.validity.tooShort, true, "Element should still be tooShort."); + + synthesizeKey("d", {}); + is(elem.value, "Tested", "Element value was not changed correctly."); + is(elem.validity.tooShort, false, "Element should no longer be tooShort."); + + elem.value = "Test"; + is(elem.validity.tooShort, false, + "Element should not be tooShort after non-interactive value change."); +} + +function test() { + window.getSelection().removeAllRanges(); + testInteractivityOfMaxLength(document.querySelector("input[type=text][maxlength]")); + testInteractivityOfMaxLength(document.querySelector("textarea[maxlength]")); + testInteractivityOfMinLength(document.querySelector("input[type=text][minlength]")); + testInteractivityOfMinLength(document.querySelector("textarea[minlength]")); + SimpleTest.finish(); +} + +window.onload = function() { + SimpleTest.waitForExplicitFinish(); + setTimeout(test, 0); +}; + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug613113.html b/dom/html/test/test_bug613113.html new file mode 100644 index 000000000..3ffe0cf07 --- /dev/null +++ b/dom/html/test/test_bug613113.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=613113 +--> +<head> + <title>Test for Bug 613113</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613113">Mozilla Bug 613113</a> +<p id="display"></p> +<div id="content" style="display: none"> + <iframe name='f'></iframe> + <form target='f' action="data:text/html,"> + <output></output> + <button></button> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 613113 **/ + +SimpleTest.waitForExplicitFinish(); + +var invalidEvent = false; + +var form = document.forms[0]; +var button = document.getElementsByTagName('button')[0]; +var output = document.getElementsByTagName('output')[0]; + +output.addEventListener("invalid", function() { + if (invalidEvent) { + ok(false, "invalid event has already been caught"); + } else { + invalidEvent = true; + ok(true, "invalid event has been caught"); + setTimeout(function() { + SimpleTest.finish(); + }, 0); + } +}, false); + +form.addEventListener("submit", function() { + ok(false, "submit event should not have been send"); +}, false); + +output.setCustomValidity("foo"); + +button.click(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug613722.html b/dom/html/test/test_bug613722.html new file mode 100644 index 000000000..3067c6476 --- /dev/null +++ b/dom/html/test/test_bug613722.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=613722 +--> +<head> + <title>Test for Bug 613722</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613722">Mozilla Bug 613722</a> +<p id="display"></p> +<div id="content"> + <embed src="test_plugin.tst" hidden> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 613722 **/ + +var rect = document.getElementsByTagName('embed')[0].getBoundingClientRect(); + +var hasFrame = rect.left != 0 || rect.right != 0 || rect.top != 0 || + rect.bottom != 0; + +ok(hasFrame, "embed should have a frame with hidden set"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug613979.html b/dom/html/test/test_bug613979.html new file mode 100644 index 000000000..cb77b333e --- /dev/null +++ b/dom/html/test/test_bug613979.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=613979 +--> +<head> + <title>Test for Bug 613979</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613979">Mozilla Bug 613979</a> +<p id="display"></p> +<div id="content"> + <input required> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 613979 **/ + +var testNum = 0; +var input = document.getElementsByTagName('input')[0]; + +input.addEventListener("input", function() { + if (testNum == 0) { + ok(input.validity.valid, "input should be valid"); + testNum++; + SimpleTest.executeSoon(function() { + synthesizeKey("VK_BACK_SPACE", {}); + }); + } else if (testNum == 1) { + ok(!input.validity.valid, "input should not be valid"); + input.removeEventListener("input", arguments.callee, false); + SimpleTest.finish(); + } +}, false); + +SimpleTest.waitForExplicitFinish(); + +SimpleTest.waitForFocus(function() { + input.focus(); + synthesizeKey("a", {}); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug615595.html b/dom/html/test/test_bug615595.html Binary files differnew file mode 100644 index 000000000..b662103cd --- /dev/null +++ b/dom/html/test/test_bug615595.html diff --git a/dom/html/test/test_bug615833.html b/dom/html/test/test_bug615833.html new file mode 100644 index 000000000..f72245d4c --- /dev/null +++ b/dom/html/test/test_bug615833.html @@ -0,0 +1,156 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=615697 +--> +<head> + <title>Test for Bug 615697</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=615697">Mozilla Bug 615697</a> +<p id="display"></p> +<div id="content"> + <input> + <textarea></textarea> + <input type='radio'> + <input type='checkbox'> + <select> + <option>foo</option> + <option>bar</option> + </select> + <select multiple size='1'> + <option>tulip</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 615697 **/ + +/** + * This test is making all elements trigger 'change' event. + * You should read the test from bottom to top: + * events are registered from the last one to the first one. + * + * Sometimes, elements are focused before a click. This might sound useless + * but it guarantees to have the element visible before simulating the click. + */ + +var input = document.getElementsByTagName('input')[0]; +var textarea = document.getElementsByTagName('textarea')[0]; +var radio = document.getElementsByTagName('input')[1]; +var checkbox= document.getElementsByTagName('input')[2]; +var select = document.getElementsByTagName('select')[0]; +var selectMultiple = document.getElementsByTagName('select')[1]; + +function checkChangeEvent(aEvent) +{ + ok(aEvent.bubbles, "change event should bubble"); + ok(!aEvent.cancelable, "change event shouldn't be cancelable"); +} + +selectMultiple.addEventListener("change", function(aEvent) { + selectMultiple.removeEventListener("change", arguments.callee, false); + checkChangeEvent(aEvent); + SimpleTest.finish(); +}, false); + +selectMultiple.addEventListener("focus", function() { + selectMultiple.removeEventListener("focus", arguments.callee, false); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(selectMultiple, {}); + }); +}, false); + +select.addEventListener("change", function(aEvent) { + select.removeEventListener("change", arguments.callee, false); + checkChangeEvent(aEvent); + selectMultiple.focus(); +}, false); + +select.addEventListener("keyup", function() { + select.removeEventListener("keyup", arguments.callee, false); + select.blur(); +}, false); + +select.addEventListener("focus", function() { + select.removeEventListener("focus", arguments.callee, false); + SimpleTest.executeSoon(function () { + synthesizeKey("VK_DOWN", {}); + }); +}, false); + +checkbox.addEventListener("change", function(aEvent) { + checkbox.removeEventListener("change", arguments.callee, false); + checkChangeEvent(aEvent); + select.focus(); +}, false); + +checkbox.addEventListener("focus", function() { + checkbox.removeEventListener("focus", arguments.callee, false); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(checkbox, {}); + }); +}, false); + +radio.addEventListener("change", function(aEvent) { + radio.removeEventListener("change", arguments.callee, false); + checkChangeEvent(aEvent); + checkbox.focus(); +}, false); + +radio.addEventListener("focus", function() { + radio.removeEventListener("focus", arguments.callee, false); + SimpleTest.executeSoon(function () { + synthesizeMouseAtCenter(radio, {}); + }); +}, false); + +textarea.addEventListener("change", function(aEvent) { + textarea.removeEventListener("change", arguments.callee, false); + checkChangeEvent(aEvent); + radio.focus(); +}, false); + +textarea.addEventListener("input", function() { + textarea.removeEventListener("input", arguments.callee, false); + textarea.blur(); +}, false); + +textarea.addEventListener("focus", function() { + textarea.removeEventListener("focus", arguments.callee, false); + SimpleTest.executeSoon(function () { + synthesizeKey('f', {}); + }); +}, false); + +input.addEventListener("change", function(aEvent) { + input.removeEventListener("change", arguments.callee, false); + checkChangeEvent(aEvent); + textarea.focus(); +}, false); + +input.addEventListener("input", function() { + input.removeEventListener("input", arguments.callee, false); + input.blur(); +}, false); + +input.addEventListener("focus", function() { + input.removeEventListener("focus", arguments.callee, false); + SimpleTest.executeSoon(function () { + synthesizeKey('f', {}); + }); +}, false); + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + input.focus(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug617528.html b/dom/html/test/test_bug617528.html new file mode 100644 index 000000000..c8cd62568 --- /dev/null +++ b/dom/html/test/test_bug617528.html @@ -0,0 +1,73 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=617528 +--> +<head> + <title>Test for Bug 617528</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=617528">Mozilla Bug 617528</a> +<p id="display"></p> +<div id="content"> + <menu> + <menuitem id="checkbox" type="checkbox" label="Checkbox" checked></menuitem> + <menuitem id="radio1" type="radio" label="Radio1" checked></menuitem> + <menuitem id="radio2" type="radio" label="Radio2"></menuitem> + </menu> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 617528 **/ + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + function click(element, preventDefault, checked) { + function handleClick(event) { + is(this.checked, checked, + "checking .checked (" + this.id + ")"); + if (preventDefault) + event.preventDefault(); + } + element.addEventListener("click", handleClick); + element.click(); + element.removeEventListener("click", handleClick); + } + + function verify(elements, data) { + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + is(element.checked, data[i*2], + "checking .checked (" + element.id + ")"); + is(element.defaultChecked, data[i*2+1], + 'checking .defaultChecked (' + element.id + ")"); + } + } + + var checkbox = document.getElementById("checkbox"); + click(checkbox, false, false); + verify([checkbox], [false, true]); + + click(checkbox, true, true); + verify([checkbox], [false, true]); + + var radio1 = document.getElementById("radio1"); + var radio2 = document.getElementById("radio2"); + click(radio2, false, true); + verify([radio1, radio2], [false, true, + true, false]); + + click(radio1, true, true); + verify([radio1, radio2], [false, true, + true, false]); + + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug618948.html b/dom/html/test/test_bug618948.html new file mode 100644 index 000000000..258041bdb --- /dev/null +++ b/dom/html/test/test_bug618948.html @@ -0,0 +1,88 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=618948 +--> +<head> + <title>Test for Bug 618948</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=618948">Mozilla Bug 618948</a> +<p id="display"></p> +<div id="content"> + <form> + <input type='email' id='i'> + <button>submit</button> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 618948 **/ + +var events = ["focus", "input", "change", "invalid" ]; + +var handled = ({}); + +function eventHandler(event) +{ + dump("\n" + event.type + "\n"); + handled[event.type] = true; +} + +function beginTest() +{ + for (var e of events) { + handled[e] = false; + } + + i.focus(); +} + +function endTest() +{ + for (var e of events) { + ok(handled[e], "on" + e + " should have been called"); + } + + SimpleTest.finish(); +} + +var i = document.getElementsByTagName('input')[0]; +var b = document.getElementsByTagName('button')[0]; + +i.onfocus = function(event) { + eventHandler(event); + synthesizeKey('f', {}); + i.onfocus = null; +}; + +i.oninput = function(event) { + eventHandler(event); + b.focus(); + i.oninput = null; +}; + +i.onchange = function(event) { + eventHandler(event); + i.onchange = null; + synthesizeMouseAtCenter(b, {}); +}; + +i.oninvalid = function(event) { + eventHandler(event); + i.oninvalid = null; + endTest(); +}; + +SimpleTest.waitForExplicitFinish(); + +SimpleTest.waitForFocus(beginTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug619278.html b/dom/html/test/test_bug619278.html new file mode 100644 index 000000000..88e4952ec --- /dev/null +++ b/dom/html/test/test_bug619278.html @@ -0,0 +1,58 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=619278 +--> +<head> + <title>Test for Bug 619278</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=619278">Mozilla Bug 619278</a> +<p id="display"></p> +<div id="content"> + <form> + <input required><button>submit</button> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 619278 **/ + +function doElementMatchesSelector(aElement, aSelector) +{ + ok(aElement.matches(aSelector), + aSelector + " should match for " + aElement); +} + +var e = document.forms[0].elements[0]; + +e.addEventListener("invalid", function(event) { + e.addEventListener("invalid", arguments.callee, false); + + SimpleTest.executeSoon(function() { + doElementMatchesSelector(e, ":-moz-ui-invalid"); + SimpleTest.finish(); + }); +}, false); + +e.addEventListener("focus", function() { + e.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + synthesizeKey("VK_RETURN", {}); + }); +}, false); + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + e.focus(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug622558.html b/dom/html/test/test_bug622558.html new file mode 100644 index 000000000..025eeca03 --- /dev/null +++ b/dom/html/test/test_bug622558.html @@ -0,0 +1,89 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=622558 +--> +<head> + <title>Test for Bug 622558</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622558">Mozilla Bug 622558</a> +<p id="display"></p> +<div id="content"> + <form> + <input> + <textarea></textarea> + <select><option>foo</option></select> +</div> +<pre id="test"> +<script type="application/javascript"> +// Bug 940203 +if (navigator.platform.startsWith("Win")) { + SimpleTest.expectAssertions(0, 1); +} + +/** Test for Bug 622558 **/ + +function checkSelectors(aElement) +{ + ok(aElement.matches(":-moz-ui-invalid"), + ":-moz-ui-invalid should match for " + aElement); + ok(!aElement.matches(":-moz-ui-valid"), + ":-moz-ui-valid should not match for " + aElement); +} + +var input = document.getElementsByTagName('input')[0]; +var textarea = document.getElementsByTagName('textarea')[0]; +var select = document.getElementsByTagName('select')[0]; + +select.addEventListener("focus", function() { + select.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + select.setCustomValidity('foo'); + + SimpleTest.executeSoon(function() { + checkSelectors(select); + SimpleTest.finish(); + }); + }); +}, false); + +textarea.addEventListener("focus", function() { + textarea.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + textarea.setCustomValidity('foo'); + + SimpleTest.executeSoon(function() { + checkSelectors(textarea); + select.focus(); + }); + }); +}, false); + +input.addEventListener("focus", function() { + input.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + input.setCustomValidity('foo'); + + SimpleTest.executeSoon(function() { + checkSelectors(input); + textarea.focus(); + }); + }); +}, false); + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + input.focus(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug622597.html b/dom/html/test/test_bug622597.html new file mode 100644 index 000000000..c0b25ae9e --- /dev/null +++ b/dom/html/test/test_bug622597.html @@ -0,0 +1,115 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=622597 +--> +<head> + <title>Test for Bug 622597</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622597">Mozilla Bug 622597</a> +<p id="display"></p> +<div id="content"> + <form> + <input required> + <textarea required></textarea> + <select required><option>foo</option><option value="">bar</option></select> + <button>submit</button> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 622597 **/ + +var form = document.forms[0]; +var input = form.elements[0]; +var textarea = form.elements[1]; +var select = form.elements[2]; +var button = form.elements[3]; + +function checkPseudoClasses(aElement, aValid, aInvalid) +{ + is(aElement.matches(":-moz-ui-valid"), aValid, + aValid ? aElement + " should match :-moz-ui-valid" + : aElement + " should not match :-moz-ui-valid"); + is(aElement.matches(":-moz-ui-invalid"), aInvalid, + aInvalid ? aElement + " should match :-moz-ui-invalid" + : aElement + " should not match :-moz-ui-invalid"); + if (aValid && aInvalid) { + ok(false, + aElement + " should not match :-moz-ui-valid AND :-moz-ui-invalid"); + } +} + +select.addEventListener("focus", function() { + select.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + form.noValidate = false; + SimpleTest.executeSoon(function() { + checkPseudoClasses(select, false, true); + SimpleTest.finish(); + }); + }); +}, false); + +textarea.addEventListener("focus", function() { + textarea.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + form.noValidate = false; + SimpleTest.executeSoon(function() { + checkPseudoClasses(textarea, false, true); + form.noValidate = true; + select.selectedIndex = 1; + select.focus(); + }); + }); +}, false); + +input.addEventListener("invalid", function() { + input.removeEventListener("invalid", arguments.callee, false); + + input.addEventListener("focus", function() { + input.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + form.noValidate = false; + SimpleTest.executeSoon(function() { + checkPseudoClasses(input, false, true); + form.noValidate = true; + textarea.value = ''; + textarea.focus(); + }); + }); + }, false); + + SimpleTest.executeSoon(function() { + form.noValidate = true; + input.blur(); + input.value = ''; + input.focus(); + }); +}, false); + +button.addEventListener("focus", function() { + button.removeEventListener("focus", arguments.callee, false); + + SimpleTest.executeSoon(function() { + synthesizeKey("VK_RETURN", {}); + }); +}, false); + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + button.focus(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug623291.html b/dom/html/test/test_bug623291.html new file mode 100644 index 000000000..c61b9213d --- /dev/null +++ b/dom/html/test/test_bug623291.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=623291 +--> +<head> + <title>Test for Bug 623291</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=623291">Mozilla Bug 623291</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<input id="textField" onfocus="next()" onblur="done();"> +<button id="b">a button</button> + +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 623291 **/ + +function runTest() { + document.getElementById("textField").focus(); +} + +function next() { + synthesizeMouseAtCenter(document.getElementById('b'), {}, window); +} + +function done() { + isnot(document.activeElement, document.getElementById("textField"), + "TextField should not be active anymore!"); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(runTest); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug6296.html b/dom/html/test/test_bug6296.html new file mode 100644 index 000000000..9b4b2fb7c --- /dev/null +++ b/dom/html/test/test_bug6296.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=6296 +--> +<head> + <title>Test for Bug 6296</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=6296">Mozilla Bug 6296</a> +<p id="display"></p> +<div id="content" style="display: none"> + <A HREF="../testdata/test.gif" id="foo" NAME="anchor1" ALT="this is a test of the image + attribute">Hi</A> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 6296 **/ +is($("foo").name, "anchor1", "accessing an anchor name should work, and not crash either!") + + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug629801.html b/dom/html/test/test_bug629801.html new file mode 100644 index 000000000..fe3c8d9a9 --- /dev/null +++ b/dom/html/test/test_bug629801.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=629801 +--> +<head> + <title>Test for Bug 629801</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=629801">Mozilla Bug 629801</a> +<p id="display"></p> +<div id="content" style="display: none"> + +<div itemscope> + This tests itemValue on time elements, first with no datetime attribute, then with no text content, + then with both. + <time id="t1" itemprop="a">May 10th 2009</time> + <time id="t2" itemprop="b" datetime="2009-05-10"></time> + <time id="t3" itemprop="c" datetime="2009-05-10">May 10th 2009</time> +</div> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 629801 **/ + +var t1 = document.getElementById("t1"), + t2 = document.getElementById("t2"), + t3 = document.getElementById("t3"), + t4 = document.createElement("time"); + +// .dateTime IDL +is(t1.dateTime, "", "dateTime is properly set to empty string if datetime attributeis absent"); +is(t2.dateTime, "2009-05-10", "dateTime is properly set to datetime attribute with datetime and no text content"); +is(t3.dateTime, "2009-05-10", "dateTime is properly set to datetime attribute with datetime and text content"); + +// dateTime reflects datetime attribute +reflectString({ + element: t4, + attribute: "dateTime" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug633058.html b/dom/html/test/test_bug633058.html new file mode 100644 index 000000000..8ffd1fecd --- /dev/null +++ b/dom/html/test/test_bug633058.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=633058 +--> +<head> + <title>Test for Bug 633058</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633058">Mozilla Bug 633058</a> +<p id="display"></p> +<div id="content"> + <input> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 633058 **/ + +SimpleTest.waitForExplicitFinish(); + +// Turn off Spatial Navigation so that the 'keypress' event fires. +SimpleTest.waitForFocus(function() { + SpecialPowers.pushPrefEnv({"set":[['snav.enabled', false]]}, startTest); +}); +function startTest() { + var nbExpectedKeyPress = 8; + var inputGotKeyPress = 0; + var divGotKeyPress = 0; + + var input = document.getElementsByTagName('input')[0]; + var content = document.getElementById('content'); + + content.addEventListener('keypress', function() { + divGotKeyPress++; + + if (divGotKeyPress == nbExpectedKeyPress) { + is(inputGotKeyPress, nbExpectedKeyPress, "input got all keypress events"); + is(divGotKeyPress, nbExpectedKeyPress, "div got all keypress events"); + SimpleTest.finish(); + } + }, false); + + input.addEventListener('keypress', function() { + inputGotKeyPress++; + }, false); + + input.addEventListener('focus', function() { + input.removeEventListener('focus', arguments.callee, false); + + synthesizeKey('VK_UP', {}); + synthesizeKey('VK_LEFT', {}); + synthesizeKey('VK_RIGHT', {}); + synthesizeKey('VK_DOWN', {}); + synthesizeKey('VK_BACK_SPACE', {}); + synthesizeKey('VK_DELETE', {}); + synthesizeKey('VK_ESCAPE', {}); + synthesizeKey('VK_RETURN', {}); + }, false); + input.focus(); +} +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug636336.html b/dom/html/test/test_bug636336.html new file mode 100644 index 000000000..ed6812e8d --- /dev/null +++ b/dom/html/test/test_bug636336.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=636336 +--> +<head> + <title>Test for Bug 636336</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636336">Mozilla Bug 636336</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 636336 **/ +function testIt(tag) { + var elem = document.createElement(tag); + elem.setAttribute("src", " "); + is(elem.getAttribute("src"), " ", + tag + " src attribute setter should not strip whitespace"); + elem.setAttribute("src", " test "); + is(elem.getAttribute("src"), " test ", + tag + " src attribute setter should not strip whitespace around non-whitespace"); + is(elem.src, window.location.href.replace(/test_bug636336\.html$/, "test"), + tag + ".src should strip whitespace as needed"); +} + +testIt("img"); +testIt("source"); +testIt("audio"); +testIt("video"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug641219.html b/dom/html/test/test_bug641219.html new file mode 100644 index 000000000..ad25d9a57 --- /dev/null +++ b/dom/html/test/test_bug641219.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=641219 +--> +<head> + <title>Test for Bug 641219</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641219">Mozilla Bug 641219</a> +<p id="display"></p> +<div id="content" style="display: none"> +<div id="div"> +<font></font> +<svg><font/></svg> +</div> +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for Bug 641219 **/ +var HTML = "http://www.w3.org/1999/xhtml", + SVG = "http://www.w3.org/2000/svg"; +var wrapper = document.getElementById("div"); +is(wrapper.getElementsByTagName("FONT").length, 1); +is(wrapper.getElementsByTagName("FONT")[0].namespaceURI, HTML); +is(wrapper.getElementsByTagName("font").length, 2); +is(wrapper.getElementsByTagName("font")[0].namespaceURI, HTML); +is(wrapper.getElementsByTagName("font")[1].namespaceURI, SVG); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug643051.html b/dom/html/test/test_bug643051.html new file mode 100644 index 000000000..4b94e1b0e --- /dev/null +++ b/dom/html/test/test_bug643051.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=643051 +--> +<head> + <title>Test for Bug 643051</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=643051">Mozilla Bug 643051</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 643051 **/ +document.cookie = "a=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; // clear cookie +document.cookie = "a2=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; // clear cookie +document.cookie = "a3=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; // clear cookie + +// single cookie, should work +document.cookie = "a=bar"; +is(document.cookie, "a=bar", "Can't read stored cookie!"); + +document.cookie = "a2=bar\na3=bar"; +is(document.cookie, "a=bar; a2=bar", "Wrong cookie value"); + +document.cookie = "a2=baz; a3=bar"; +is(document.cookie, "a=bar; a2=baz", "Wrong cookie value"); + +// clear cookies again to avoid affecting other tests +document.cookie = "a=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; +document.cookie = "a2=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; +document.cookie = "a3=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug646157.html b/dom/html/test/test_bug646157.html new file mode 100644 index 000000000..3924c9f22 --- /dev/null +++ b/dom/html/test/test_bug646157.html @@ -0,0 +1,95 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=646157 +--> +<head> + <title>Test for Bug 646157</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=646157">Mozilla Bug 646157</a> +<p id="display"></p> +<div id="content"> + <label id="l1"/><input id="c1" type='checkbox'> + <label id="l2"/><input id="c2" type='checkbox'> + <label id="l3"/><input id="c3" type='checkbox'> + <label id="l4"/><input id="c4" type='checkbox'> + <label id="l5"/><input id="c5" type='checkbox'> + <label id="l6"/><input id="c6" type='checkbox'> + <label id="l7"/><input id="c7" type='checkbox'> + <label id="l8"/><input id="c8" type='checkbox'> + <label id="l9"/><input id="c9" type='checkbox'> + <label id="l10"/><input id="c10" type='checkbox'> +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for Bug 646157 **/ + +var expectedClicks = { + // [ Direct clicks, bubbled clicks, synthetic clicks] + l1: [0, 2, 1], + l2: [0, 2, 1], + l3: [0, 2, 1], + l4: [0, 2, 1], + l5: [0, 2, 1], + l6: [0, 2, 1], + l7: [0, 2, 1], + l8: [0, 2, 1], + l9: [0, 2, 1], + l10:[1, 2, 1], + c1: [0, 0, 0], + c2: [0, 0, 0], + c3: [0, 0, 0], + c4: [0, 0, 0], + c5: [0, 0, 0], + c6: [0, 0, 0], + c7: [0, 0, 0], + c8: [0, 0, 0], + c9: [0, 0, 0], + c10:[1, 1, 1] +}; + +function clickhandler(e) { + if (!e.currentTarget.clickCount) + e.currentTarget.clickCount = 1; + else + e.currentTarget.clickCount++; + + if (e.currentTarget === e.target) + e.currentTarget.directClickCount = 1; + + if (e.target != document.getElementById("l10")) { + if (!e.currentTarget.synthClickCount) + e.currentTarget.synthClickCount = 1; + else + e.currentTarget.synthClickCount++; + } +} + +for (var i = 1; i <= 10; i++) { + document.getElementById("l" + i).addEventListener('click', clickhandler, false); + document.getElementById("c" + i).addEventListener('click', clickhandler, false); +} + +document.getElementById("l10").click(); + +function check(thing) { + var expected = expectedClicks[thing.id]; + is(thing.directClickCount || 0, expected[0], "Wrong number of direct clicks"); + is(thing.clickCount || 0, expected[1], "Wrong number of clicks"); + is(thing.synthClickCount || 0, expected[2], "Wrong number of synthetic clicks"); +} + +// Compare them all +for (var i = 1; i <= 10; i++) { + check(document.getElementById("l" + i)); + check(document.getElementById("c" + i)); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug649134.html b/dom/html/test/test_bug649134.html new file mode 100644 index 000000000..1bedfbe3c --- /dev/null +++ b/dom/html/test/test_bug649134.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=649134 +--> +<head> + <title>Test for Bug 649134</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=649134">Mozilla Bug 649134</a> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 649134 **/ +SimpleTest.waitForExplicitFinish(); + +var calls = 0; +function finish() { + if (++calls == 4) + SimpleTest.finish(); +} +function verifyNoLoad(iframe) { + ok(iframe.contentDocument.body.offsetHeight > 0, + "HTTP Link stylesheet was ignored " + iframe.src); + finish(); +} +var verifyLoadCalls = 0; +function verifyLoad(iframe) { + if (++verifyLoadCalls == 2) { + ok(indexContent == iframe.contentDocument.body.innerHTML, + "bug649134/ loads bug649134/index.html " + iframe.src); + } + finish(); +} +function indexLoad(iframe) { + indexContent = iframe.contentDocument.body.innerHTML; + verifyLoad(iframe); +} + +</script> +</pre> +<p id="display"> +<!-- Note: the extra sub-directory is needed for the test, see bug 649134 comment 14 --> +<iframe onload="verifyNoLoad(this);" src="bug649134/file_bug649134-1.sjs"></iframe> +<iframe onload="verifyNoLoad(this);" src="bug649134/file_bug649134-2.sjs"></iframe> +<iframe onload="verifyLoad(this);" src="bug649134/"></iframe> <!-- verify that mochitest server loads index.html --> +<iframe onload="indexLoad(this);" src="bug649134/index.html"></iframe> +</p> +</body> +</html> diff --git a/dom/html/test/test_bug651956.html b/dom/html/test/test_bug651956.html new file mode 100644 index 000000000..59fbd3936 --- /dev/null +++ b/dom/html/test/test_bug651956.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=651956 +--> +<head> + <title>Test for Bug 651956</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=651956">Mozilla Bug 651956</a> +<p id="display"></p> +<div id="content"> + <input> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 651956 **/ + +var input = document.getElementsByTagName('input')[0]; + +var gotInputEvent = false; + +input.addEventListener("input", function() { + input.removeEventListener("input", arguments.callee, false); + gotInputEvent = true; +}, false); + +input.addEventListener("focus", function() { + input.removeEventListener("focus", arguments.callee, false); + synthesizeKey("VK_ESCAPE", {}); + + setTimeout(function() { + ok(!gotInputEvent, "No input event should have been sent."); + SimpleTest.finish(); + }); +}, false); + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + input.focus(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug658746.html b/dom/html/test/test_bug658746.html new file mode 100644 index 000000000..df5982547 --- /dev/null +++ b/dom/html/test/test_bug658746.html @@ -0,0 +1,97 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=658746 +--> +<head> + <title>Test for Bug 658746</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=658746">Mozilla Bug 658746</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 658746 **/ + +/** + * Sets property, gets property and deletes property. + */ +function SetGetDelete(prop) +{ + var el = document.createElement('div'); + + el.dataset[prop] = 'aaaaaa'; + is(el.dataset[prop], 'aaaaaa', 'Dataset property "' + prop + '" should have been set.'); + + delete el.dataset[prop]; + is(el.dataset[prop], undefined, 'Dataset property"' + prop + '" should have been deleted.'); +} + +/** + * Gets, deletes and sets property. Expects exception while trying to set property. + */ +function SetExpectException(prop) +{ + var el = document.createElement('div'); + + is(el.dataset[prop], undefined, 'Dataset property "' + prop + '" should be undefined.'); + delete el.dataset[prop]; + + try { + el.dataset[prop] = "xxxxxx"; + ok(false, 'Exception should have been thrown when setting "' + prop + '".'); + } catch (ex) { + ok(true, 'Exception should have been thrown.'); + } +} + +// Numbers as properties. +SetGetDelete(-12345678901234567980); +SetGetDelete(-1); +SetGetDelete(0); +SetGetDelete(1); +SetGetDelete(12345678901234567980); + +// Floating point numbers as properties. +SetGetDelete(-1.1); +SetGetDelete(0.0); +SetGetDelete(1.1); + +// Hexadecimal numbers as properties. +SetGetDelete(0x3); +SetGetDelete(0xa); + +// Octal numbers as properties. +SetGetDelete(03); +SetGetDelete(07); + +// String numbers as properties. +SetGetDelete('0'); +SetGetDelete('01'); +SetGetDelete('0x1'); + +// Undefined as property. +SetGetDelete(undefined); + +// Empty arrays as properties. +SetGetDelete(new Array()); +SetGetDelete([]); + +// Non-empty array and object as properties. +SetExpectException(['a', 'b']); +SetExpectException({'a':'b'}); + +// Objects as properties. +SetExpectException(new Object()); +SetExpectException(document); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug659596.html b/dom/html/test/test_bug659596.html new file mode 100644 index 000000000..a8828cf0a --- /dev/null +++ b/dom/html/test/test_bug659596.html @@ -0,0 +1,96 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=659596 +--> +<head> + <title>Test for Bug 659596</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=659596">Mozilla Bug 659596</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 659596 **/ + +function checkReflection(option, attribute) { + /** + * Getting. + */ + + // When attribute isn't present. + var tests = [ "", "foo" ]; + for (var test of tests) { + option.removeAttribute(attribute); + option.textContent = test; + is(option.getAttribute(attribute), null, + "option " + attribute + "'s value should be null"); + is(option[attribute], option.textContent, + "option." + attribute + " should reflect the text content when the attribute isn't set"); + } + + // When attribute is present. + tests = [ + [ "", "" ], + [ "", "foo" ], + [ "foo", "bar" ], + [ "foo", "" ], + ]; + for (var test of tests) { + option.setAttribute(attribute, test[0]); + option.textContent = test[1]; + is(option[attribute], option.getAttribute(attribute), + "option." + attribute + " should reflect the content attribute when it is set"); + } + + /** + * Setting. + */ + + // When attribute isn't present. + tests = [ + [ "", "new" ], + [ "foo", "new" ], + ]; + for (var test of tests) { + option.removeAttribute(attribute); + option.textContent = test[0]; + option[attribute] = test[1] + + is(option.getAttribute(attribute), test[1], + "when setting, the content attribute should change"); + is(option.textContent, test[0], + "when setting, the text content should not change"); + } + + // When attribute is present. + tests = [ + [ "", "", "new" ], + [ "", "foo", "new" ], + [ "foo", "bar", "new" ], + [ "foo", "", "new" ], + ]; + for (var test of tests) { + option.setAttribute(attribute, test[0]); + option.textContent = test[1]; + option[attribute] = test[2]; + + is(option.getAttribute(attribute), test[2], + "when setting, the content attribute should change"); + is(option.textContent, test[1], + "when setting, the text content should not change"); + } +} + +var option = document.createElement("option"); + +checkReflection(option, "value"); +checkReflection(option, "label"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug659743.xml b/dom/html/test/test_bug659743.xml new file mode 100644 index 000000000..12236bdc0 --- /dev/null +++ b/dom/html/test/test_bug659743.xml @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=659743 +--> +<head> + <title>Test for Bug 659743</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=659743">Mozilla Bug 659743</a> +<p id="display"> +<map name="a"> +<area shape="rect" coords="25,25,75,75" href="#x"/> +</map> +<map id="b"> +<area shape="rect" coords="25,25,75,75" href="#y"/> +</map> +<map name="a"> +<area shape="rect" coords="25,25,75,75" href="#FAIL"/> +</map> +<map id="b"> +<area shape="rect" coords="25,25,75,75" href="#FAIL"/> +</map> + +<img usemap="#a" src="image.png"/> +<img usemap="#b" src="image.png"/> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 659743 **/ +SimpleTest.waitForExplicitFinish(); +var images = document.getElementsByTagName("img"); +var second = false; +onhashchange = function() { + if (!second) { + second = true; + is(location.hash, "#x", "First map"); + SimpleTest.waitForFocus(() => synthesizeMouse(images[1], 50, 50, {})); + } else { + is(location.hash, "#y", "Second map"); + SimpleTest.finish(); + } +}; +SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {})); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug660663.html b/dom/html/test/test_bug660663.html new file mode 100644 index 000000000..2ce3f9ac6 --- /dev/null +++ b/dom/html/test/test_bug660663.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=660663 +--> +<head> + <title>Test for Bug 660663</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660663">Mozilla Bug 660663</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for Bug 660663 **/ +reflectLimitedEnumerated({ + element: document.createElement("div"), + attribute: "dir", + validValues: ["ltr", "rtl", "auto"], + invalidValues: ["cheesecake", ""] +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug660959-1.html b/dom/html/test/test_bug660959-1.html new file mode 100644 index 000000000..0bffa0e05 --- /dev/null +++ b/dom/html/test/test_bug660959-1.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=660959 +--> +<head> + <title>Test for Bug 660959</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660959">Mozilla Bug 660959</a> +<p id="display"></p> +<div id="content" style="display: none"> + <a href="#" id="testa"></a> +</div> +<pre id="test"> +<script> + is($("content").querySelector(":link, :visited"), $("testa"), + "Should find a link even in a display:none subtree"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug660959-2.html b/dom/html/test/test_bug660959-2.html new file mode 100644 index 000000000..a4d74b6e3 --- /dev/null +++ b/dom/html/test/test_bug660959-2.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=660959 +--> +<head> + <title>Test for Bug 660959</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <style> + :link, :visited { + color: red; + } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660959">Mozilla Bug 660959</a> +<p id="display"></p> +<div id="content" style="display: none"> + <a href="#" id="a"></a> +</div> +<pre id="test"> +<script type="application/javascript"> + var a = document.getElementById("a"); + is(window.getComputedStyle(a).color, "rgb(255, 0, 0)", "Link is not right color?"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug660959-3.html b/dom/html/test/test_bug660959-3.html new file mode 100644 index 000000000..4539a0449 --- /dev/null +++ b/dom/html/test/test_bug660959-3.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=660959 +--> +<head> + <title>Test for Bug 660959</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660959">Mozilla Bug 660959</a> +<p id="display"></p> +<div id="content" style="display: none"> + <a href="http://www.example.com"></a> + <div id="foo"> + <span id="test"></span> + </div> +</div> +<pre id="test"> +<script> + is($("foo").querySelector(":link + * span, :visited + * span"), $("test"), + "Should be able to find link siblings even in a display:none subtree"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug666200.html b/dom/html/test/test_bug666200.html new file mode 100644 index 000000000..d2a748697 --- /dev/null +++ b/dom/html/test/test_bug666200.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=666200 +--> +<head> + <title>Test for Bug 666200</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666200">Mozilla Bug 666200</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +/** Test for Bug 666200 **/ +var sel = document.createElement("select"); +var opt1 = new Option(); +var opt2 = new Option(); +var opt3 = new Option(); +var opt4 = new Option(); +var opt5 = new Option(); +opt1.value = 1; +opt2.value = 2; +opt3.value = 3; +opt4.value = 4; +opt5.value = 5; +sel.add(opt1); +sel.add(opt2, 0); +sel.add(opt3, 1000); +sel.options.add(opt4, opt3); +sel.add(opt5, undefined); +is(sel[0], opt2, "1st item should be 2"); +is(sel[1], opt1, "2nd item should be 1"); +is(sel[2], opt4, "3rd item should be 4"); +is(sel[3], opt3, "4th item should be 3"); +is(sel[4], opt5, "5th item should be 5"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug666666.html b/dom/html/test/test_bug666666.html new file mode 100644 index 000000000..3bd1d5832 --- /dev/null +++ b/dom/html/test/test_bug666666.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=666666 +--> +<head> + <title>Test for Bug 666666</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666666">Mozilla Bug 666666</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for Bug 666666 **/ +["audio", "video"].forEach(function(element) { + reflectLimitedEnumerated({ + element: document.createElement(element), + attribute: "preload", + validValues: ["none", "metadata", "auto"], + invalidValues: ["cheesecake", ""] + }); +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug669012.html b/dom/html/test/test_bug669012.html new file mode 100644 index 000000000..e6be933fa --- /dev/null +++ b/dom/html/test/test_bug669012.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=669012 +--> +<head> + <title>Test for Bug 669012</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=669012">Mozilla Bug 669012</a> +<p id="display"></p> +<div id="content" style="display: none"> +<script> +var run = 0; +</script> +<svg> +<script> +run++; +ok(true, "Should run SVG script without attributes") +</script> +<script for=window event=onload> +run++; +ok(true, "Should run SVG script with for=window event=onload") +</script> +<script for=window event=foo> +run++; +ok(true, "Should run SVG script with for=window event=foo") +</script> +<script for=foo event=onload> +run++; +ok(true, "Should run SVG script with for=foo event=onload") +</script> +</svg> +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for Bug 669012 **/ +is(run, 4, "Should have run all tests") +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug674558.html b/dom/html/test/test_bug674558.html new file mode 100644 index 000000000..c728bc14e --- /dev/null +++ b/dom/html/test/test_bug674558.html @@ -0,0 +1,290 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=674558 +--> +<head> + <title>Test for Bug 674558</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=674558">Mozilla Bug 674558</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 674558 **/ +SimpleTest.waitForExplicitFinish(); + +// Turn off spatial navigation because it hijacks VK_RIGHT and VK_LEFT keydown +// events. +SimpleTest.waitForFocus(function() { + SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, startTest); +}); +function startTest() { + function textAreaCtor() { + return document.createElement("textarea"); + } + var ctors = [textAreaCtor]; + ["text", "password", "search"].forEach(function(type) { + ctors.push(function inputCtor() { + var input = document.createElement("input"); + input.type = type; + return input; + }); + }); + + for (var ctor in ctors) { + test(ctors[ctor]); + } + + SimpleTest.finish(); +} + +function test(ctor) { + var elem = ctor(); + ok(true, "Testing " + name(elem)); + + ok("selectionDirection" in elem, "elem should have the selectionDirection property"); + + is(elem.selectionStart, elem.value.length, "Default value"); + is(elem.selectionEnd, elem.value.length, "Default value"); + is(elem.selectionDirection, "forward", "Default value"); + + var content = document.getElementById("content"); + content.appendChild(elem); + + function flush() { document.body.clientWidth; } + function hide() { + content.style.display = "none"; + flush(); + } + function show() { + content.style.display = ""; + flush(); + } + + elem.value = "foobar"; + + is(elem.selectionStart, elem.value.length, "Default value"); + is(elem.selectionEnd, elem.value.length, "Default value"); + is(elem.selectionDirection, "forward", "Default value"); + + elem.setSelectionRange(1, 3); + is(elem.selectionStart, 1, "Correct value"); + is(elem.selectionEnd, 3, "Correct value"); + is(elem.selectionDirection, "forward", "If not set, should default to forward"); + + hide(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 3, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + show(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 3, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + // extend to right + elem.focus(); + synthesizeKey("VK_RIGHT", {shiftKey: true}); + + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Correct value"); + is(elem.selectionDirection, "forward", "Still forward"); + + hide(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + show(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + // change the direction + elem.selectionDirection = "backward"; + + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "backward", "Correct value"); + + hide(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + show(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + // extend to right again + synthesizeKey("VK_RIGHT", {shiftKey: true}); + + is(elem.selectionStart, 2, "Correct value"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "backward", "Still backward"); + + hide(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + show(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + elem.selectionEnd = 5; + + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Correct value"); + is(elem.selectionDirection, "backward", "Still backward"); + + hide(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + show(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + elem.selectionDirection = "none"; + + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "forward", "none not supported"); + + hide(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + show(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + elem.selectionDirection = "backward"; + + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Correct Value"); + + hide(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + show(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + elem.selectionDirection = "invalid"; + + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "forward", "Treated as none"); + + hide(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + show(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + elem.selectionDirection = "backward"; + + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Correct Value"); + + hide(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + show(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + elem.setSelectionRange(1, 4); + + is(elem.selectionStart, 1, "Correct value"); + is(elem.selectionEnd, 4, "Correct value"); + is(elem.selectionDirection, "forward", "Correct value"); + + hide(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + show(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + elem.setSelectionRange(1, 1); + synthesizeKey("VK_RIGHT", {shiftKey: true}); + synthesizeKey("VK_RIGHT", {shiftKey: true}); + synthesizeKey("VK_RIGHT", {shiftKey: true}); + + is(elem.selectionStart, 1, "Correct value"); + is(elem.selectionEnd, 4, "Correct value"); + is(elem.selectionDirection, "forward", "Correct value"); + + hide(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + show(); + is(elem.selectionStart, 1, "Value unchanged"); + is(elem.selectionEnd, 4, "Value unchanged"); + is(elem.selectionDirection, "forward", "Value unchanged"); + + elem.setSelectionRange(5, 5); + synthesizeKey("VK_LEFT", {shiftKey: true}); + synthesizeKey("VK_LEFT", {shiftKey: true}); + synthesizeKey("VK_LEFT", {shiftKey: true}); + + is(elem.selectionStart, 2, "Correct value"); + is(elem.selectionEnd, 5, "Correct value"); + is(elem.selectionDirection, "backward", "Correct value"); + + hide(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); + + show(); + is(elem.selectionStart, 2, "Value unchanged"); + is(elem.selectionEnd, 5, "Value unchanged"); + is(elem.selectionDirection, "backward", "Value unchanged"); +} + +function name(elem) { + var tag = elem.localName; + if (tag == "input") { + tag += "[type=" + elem.type + "]"; + } + return tag; +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug674927.html b/dom/html/test/test_bug674927.html new file mode 100644 index 000000000..92af59453 --- /dev/null +++ b/dom/html/test/test_bug674927.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=674927 +--> +<title>Test for Bug 674927</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +<p><span>Hello</span></p> +<div contenteditable>Contenteditable <i>is</i> splelchecked by default</div> +<textarea>Textareas are spellchekced by default</textarea> +<input value="Inputs are not spellcheckde by default"> +<script> +// Test the effect of setting spellcheck on various elements +[ + "html", + "body", + "p", + "span", + "div", + "i", + "textarea", + "input", +].forEach(function(query) { + var element = document.querySelector(query); + + // First check what happens if no attributes are set + var defaultSpellcheck; + if (element.isContentEditable || element.tagName == "TEXTAREA") { + defaultSpellcheck = true; + } else { + defaultSpellcheck = false; + } + is(element.spellcheck, defaultSpellcheck, + "Default spellcheck for <" + element.tagName.toLowerCase() + ">"); + + // Now try setting spellcheck on ancestors + var ancestor = element; + do { + testSpellcheck(ancestor, element); + ancestor = ancestor.parentNode; + } while (ancestor.nodeType == Node.ELEMENT_NODE); +}); + +function testSpellcheck(ancestor, element) { + ancestor.spellcheck = true; + is(element.spellcheck, true, + ".spellcheck on <" + element.tagName.toLowerCase() + "> with " + + "spellcheck=true on <" + ancestor.tagName.toLowerCase() + ">"); + ancestor.spellcheck = false; + is(element.spellcheck, false, + ".spellcheck on <" + element.tagName.toLowerCase() + "> with " + + "spellcheck=false on <" + ancestor.tagName.toLowerCase() + ">"); + ancestor.removeAttribute("spellcheck"); +} +</script> diff --git a/dom/html/test/test_bug677463.html b/dom/html/test/test_bug677463.html new file mode 100644 index 000000000..2d895d8d2 --- /dev/null +++ b/dom/html/test/test_bug677463.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=677463 +--> +<head> + <title>Test for Bug 677463</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677463">Mozilla Bug 677463</a> +<p id="display"></p> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 677463 **/ + +var o = document.createElement("option"); +var m = document.createElement("menuitem"); +is(o.label, m.label, "Should have same labels"); +o.textContent = " "; +is(o.label, m.label, "Should have same labels"); +m.textContent = " "; +is(o.label, m.label, "Should have same labels"); +o.textContent = " foo"; +isnot(o.label, m.label, "Shouldn't have same labels"); +m.textContent = "foo "; +is(o.label, m.label, "Should have same labels"); +m.label = "bar"; +isnot(o.label, m.label, "Shouldn't have same labels"); +o.label = "bar"; +is(o.label, m.label, "Should have same labels"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug677495-1.html b/dom/html/test/test_bug677495-1.html new file mode 100644 index 000000000..916997f00 --- /dev/null +++ b/dom/html/test/test_bug677495-1.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=677495 + +As mandated by the spec, the body of a media document must only contain one child. +--> +<head> + <title>Test for Bug 571981</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +<script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + + function frameLoaded() { + var testframe = document.getElementById('testframe'); + var testframeChildren = testframe.contentDocument.body.childNodes; + is(testframeChildren.length, 1, "Body of video document has 1 child"); + is(testframeChildren[0].nodeName, "VIDEO", "Only child of body must be a <video> element"); + + SimpleTest.finish(); + } +</script> + +</head> +<body> + <p id="display"></p> + + <iframe id="testframe" name="testframe" onload="frameLoaded()" + src="data:video/webm,"></iframe> + +</body> +</html> diff --git a/dom/html/test/test_bug677495.html b/dom/html/test/test_bug677495.html new file mode 100644 index 000000000..fec1912b4 --- /dev/null +++ b/dom/html/test/test_bug677495.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=677495 + +As mandated by the spec, the body of a media document must only contain one child. +--> +<head> + <title>Test for Bug 571981</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +<script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + + function frameLoaded() { + var testframe = document.getElementById('testframe'); + var testframeChildren = testframe.contentDocument.body.childNodes; + is(testframeChildren.length, 1, "Body of image document has 1 child"); + is(testframeChildren[0].nodeName, "IMG", "Only child of body must be an <img> element"); + + SimpleTest.finish(); + } +</script> + +</head> +<body> + <p id="display"></p> + + <iframe id="testframe" name="testframe" onload="frameLoaded()" + src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMFgQGMyFwHucAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC"></iframe> + +</body> +</html> diff --git a/dom/html/test/test_bug677658.html b/dom/html/test/test_bug677658.html new file mode 100644 index 000000000..3aab5dba8 --- /dev/null +++ b/dom/html/test/test_bug677658.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=677658 +--> +<head> + <title>Test for Bug 677658</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body onload="test()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677658">Mozilla Bug 677658</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"><!-- + +/** Test for Bug 677658 **/ + +SimpleTest.waitForExplicitFinish(); + +function testDone() { + ok(window.testPassed, "Script shouldn't have run!"); + SimpleTest.finish(); +} + +function test() { + window.testPassed = true; + document.getElementById("testtarget").innerHTML = + "<script async src='data:text/plain, window.testPassed = false;'></script>"; + SimpleTest.executeSoon(testDone); +} + +// --> +</script> +</pre> +<div id="testtarget"></div> +</body> +</html> diff --git a/dom/html/test/test_bug682886.html b/dom/html/test/test_bug682886.html new file mode 100644 index 000000000..b321d017f --- /dev/null +++ b/dom/html/test/test_bug682886.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=682886 +--> +<head> + <title>Test for Bug 682886</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=682886">Mozilla Bug 682886</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 682886 **/ + + + var m = document.createElement("menu"); + var s = "<menuitem>foo</menuitem>"; + m.innerHTML = s; + is(m.innerHTML, s, "Wrong menuitem serialization!"); + + + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug691.html b/dom/html/test/test_bug691.html new file mode 100644 index 000000000..cfdb53985 --- /dev/null +++ b/dom/html/test/test_bug691.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=691 +--> +<head> + <title>Test for Bug 691</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +<script type="text/javascript"> + +function show(what) { + var stage = document.getElementById("stage"); + if (what == "modularity") { + var spaghetti = document.createElement("IMG",null); + spaghetti.setAttribute("SRC","nnc_lockup.gif"); + spaghetti.setAttribute("id","foo"); + stage.insertBefore(spaghetti,stage.firstChild); + } +} + +function remove() { + var stage = document.getElementById("stage"); + var body = document.getElementsByTagName("BODY")[0]; + while (stage.firstChild) { + stage.removeChild(stage.firstChild); + } +} + +</script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=691">Mozilla Bug 691</a> +<p id="display"></p> +<div id="content" > +<ul> +<li >foo</li> +</ul> +<div id="stage"> +</div> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 691 **/ + +show("modularity"); +remove(); +show("modularity"); +remove(); +show("modularity"); +remove(); +show("modularity"); + +ok($("foo"), "basic DOM manipulation doesn't crash"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug694.html b/dom/html/test/test_bug694.html new file mode 100644 index 000000000..8e88dd1cf --- /dev/null +++ b/dom/html/test/test_bug694.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=694 +--> +<head> + <title>Test for Bug 694</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=694">Mozilla Bug 694</a> +<p id="display"></p> +<div id="content" > +<img src="/missing_on_purpose" width=123 height=25 alt="Hello, "Quotes" how are you?" id="testimg"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 694 **/ + +is($("testimg").getAttribute("alt"), "Hello, \"Quotes\" how are you?", "entities in alt attribute works"); + + + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug694503.html b/dom/html/test/test_bug694503.html new file mode 100644 index 000000000..6ffd18d64 --- /dev/null +++ b/dom/html/test/test_bug694503.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=694503 +--> +<head> + <title>Test for Bug 694503</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=694503">Mozilla Bug 694503</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> + +<div> +<map name="map1"> + <area onclick="++mapClickCount; event.preventDefault();" + coords="0,0,50,50" shape="rect"> +</map> +</div> + +<img id="img" + usemap="#map1" alt="Foo bar" src="about:logo"> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 694503 **/ + +var mapClickCount = 0; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + var m = document.getElementsByTagName("map")[0]; + var img = document.getElementById('img'); + var origName = m.name; + + synthesizeMouse(img, 25, 25, {}); + is(mapClickCount, 1, "Wrong click count (1)"); + + m.name = "foo" + synthesizeMouse(img, 25, 25, {}); + is(mapClickCount, 1, "Wrong click count (2)"); + + m.removeAttribute("name"); + m.id = origName; + synthesizeMouse(img, 25, 25, {}); + is(mapClickCount, 2, "Wrong click count (3)"); + + // Back to original state + m.removeAttribute("id"); + m.name = origName; + synthesizeMouse(img, 25, 25, {}); + is(mapClickCount, 3, "Wrong click count (4)"); + + var p = m.parentNode; + p.removeChild(m); + synthesizeMouse(img, 25, 25, {}); + is(mapClickCount, 3, "Wrong click count (5)"); + + // Back to original state + p.appendChild(m); + synthesizeMouse(img, 25, 25, {}); + is(mapClickCount, 4, "Wrong click count (6)"); + + SimpleTest.finish(); +}); + + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug696.html b/dom/html/test/test_bug696.html new file mode 100644 index 000000000..35669f565 --- /dev/null +++ b/dom/html/test/test_bug696.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=696 +--> +<head> + <title>Test for Bug 696</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696">Mozilla Bug 696</a> +<p id="display"></p> +<div id="content" style="display: none"> + <table><tr id="mytr"><td>Foo</td><td>Bar</td></tr></table> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 696 **/ +var mytr = $("content").getElementsByTagName("TR")[0]; +is(mytr.getAttribute("ID"),"mytr","TR tags expose their ID attribute"); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug717819.html b/dom/html/test/test_bug717819.html new file mode 100644 index 000000000..9c574dd68 --- /dev/null +++ b/dom/html/test/test_bug717819.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=717819 +--> +<head> + <title>Test for Bug 717819</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717819">Mozilla Bug 717819</a> +<p id="display"></p> +<div id="content"> + <table style="position: relative; top: 100px;"> + <tr> + <td> + <div id="test" style="position: absolute; top: 50px;"></div> + </td> + </tr> + </table> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 717819 **/ +var div = document.getElementById("test"); +is(div.offsetTop, 50, "The offsetTop must be calculated correctly"); +is(div.offsetParent, document.querySelector("table"), + "The offset should be calculated off of the correct parent"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug741266.html b/dom/html/test/test_bug741266.html new file mode 100644 index 000000000..72db28079 --- /dev/null +++ b/dom/html/test/test_bug741266.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741266 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 741266</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741266">Mozilla Bug 741266</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 741266 **/ +SimpleTest.waitForExplicitFinish(); + +var url = URL.createObjectURL(new Blob([""], { type: "text/html" })); +var w = window.open(url, "", "width=100,height=100"); +w.onload = function() { + is(w.innerHeight, 100, "Popup height should be 100 when opened with window.open"); + // XXXbz On at least some platforms, the innerWidth is off by the scrollbar + // width for some reason. So just make sure it's the same for both popups. + var width = w.innerWidth; + w.close(); + + w = document.open(url, "", "width=100,height=100"); + w.onload = function() { + is(w.innerHeight, 100, "Popup height should be 100 when opened with document.open"); + is(w.innerWidth, width, "Popup width should be the same when opened with document.open"); + w.close(); + SimpleTest.finish(); + }; +}; +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug742030.html b/dom/html/test/test_bug742030.html new file mode 100644 index 000000000..c88f38879 --- /dev/null +++ b/dom/html/test/test_bug742030.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=742030 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 742030</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742030">Mozilla Bug 742030</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 742030 **/ +const str = " color: #ff0000 "; +var span = document.createElement("span"); +span.setAttribute("style", str); +is(span.getAttribute("style"), str, "Should have set properly"); +var span2 = span.cloneNode(false); +is(span2.getAttribute("style"), str, "Should have cloned properly"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug742549.html b/dom/html/test/test_bug742549.html new file mode 100644 index 000000000..5ab88f36e --- /dev/null +++ b/dom/html/test/test_bug742549.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=742549 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 742549</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742549">Mozilla Bug 742549</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 742549 **/ +var els = [ document.createElement("script"), + document.createElementNS("http://www.w3.org/2000/svg", "script") ] + +for (var i = 0; i < els.length; ++i) { + reflectLimitedEnumerated({ + element: els[i], + attribute: { content: "crossorigin", idl: "crossOrigin" }, + // "" is a valid value per spec, but gets mapped to the "anonymous" state, + // just like invalid values, so just list it under invalidValues + validValues: [ "anonymous", "use-credentials" ], + invalidValues: [ + "", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR " + ], + defaultValue: { invalid: "anonymous", missing: null }, + nullable: true, + }) +} + + + + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug745685.html b/dom/html/test/test_bug745685.html new file mode 100644 index 000000000..c4544441e --- /dev/null +++ b/dom/html/test/test_bug745685.html @@ -0,0 +1,105 @@ +<!doctype html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=745685 +--> +<title>Test for Bug 745685</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=745685">Mozilla Bug 745685</a> +<font>Test text</font> +<font size=1>1</font> +<font size=2>2</font> +<font size=3>3</font> +<font size=4>4</font> +<font size=5>5</font> +<font size=6>6</font> +<font size=7>7</font> +<script> +/** Test for Bug 745685 **/ + +var referenceSizes = {}; +for (var i = 1; i <= 7; i++) { + referenceSizes[i] = + getComputedStyle(document.querySelector('[size="' + i + '"]')) + .fontSize; + if (i > 1) { + isnot(referenceSizes[i], referenceSizes[i - 1], + "Sanity check: different <font size>s give different .fontSize"); + } +} + +function testFontSize(input, expected) { + var font = document.querySelector("font"); + font.setAttribute("size", input); + is(font.getAttribute("size"), input, + "Setting doesn't round-trip (.getAttribute)"); + is(font.size, input, + "Setting doesn't round-trip (.size)"); + is(getComputedStyle(font).fontSize, referenceSizes[expected], + 'Incorrect size for "' + input + '" : expected the same as ' + expected); +} + +function testFontSizes(input, expected) { + testFontSize(input, expected); + // Leading whitespace + testFontSize(" " + input, expected); + testFontSize("\t" + input, expected); + testFontSize("\n" + input, expected); + testFontSize("\f" + input, expected); + testFontSize("\r" + input, expected); + // Trailing garbage + testFontSize(input + "abcd", expected); + testFontSize(input + ".5", expected); + testFontSize(input + "e2", expected); +} + +// Parse error +testFontSizes("", 3); + +// No sign +testFontSizes("0", 1); +testFontSizes("1", 1); +testFontSizes("2", 2); +testFontSizes("3", 3); +testFontSizes("4", 4); +testFontSizes("5", 5); +testFontSizes("6", 6); +testFontSizes("7", 7); +testFontSizes("8", 7); +testFontSizes("9", 7); +testFontSizes("10", 7); +testFontSizes("10000000000000000000000", 7); + +// Minus sign +testFontSizes("-0", 3); +testFontSizes("-1", 2); +testFontSizes("-2", 1); +testFontSizes("-3", 1); +testFontSizes("-4", 1); +testFontSizes("-5", 1); +testFontSizes("-6", 1); +testFontSizes("-7", 1); +testFontSizes("-8", 1); +testFontSizes("-9", 1); +testFontSizes("-10", 1); +testFontSizes("-10000000000000000000000", 1); + +// Plus sign +testFontSizes("+0", 3); +testFontSizes("+1", 4); +testFontSizes("+2", 5); +testFontSizes("+3", 6); +testFontSizes("+4", 7); +testFontSizes("+5", 7); +testFontSizes("+6", 7); +testFontSizes("+7", 7); +testFontSizes("+8", 7); +testFontSizes("+9", 7); +testFontSizes("+10", 7); +testFontSizes("+10000000000000000000000", 7); + +// Non-HTML5 whitespace +testFontSize("\b1", 3); +testFontSize("\v1", 3); +testFontSize("\0u00a01", 3); +</script> diff --git a/dom/html/test/test_bug763626.html b/dom/html/test/test_bug763626.html new file mode 100644 index 000000000..960712c39 --- /dev/null +++ b/dom/html/test/test_bug763626.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=763626 +--> +<head> +<title>Test for Bug 763626</title> + +<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); + +function boom() +{ + var r = document.createElement("iframe").sandbox; + SpecialPowers.DOMWindowUtils.garbageCollect(); + is("" + r, "", "ToString should return empty string when element is gone"); + SimpleTest.finish(); +} + +</script> +</head> + +<body onload="boom();"></body> +</html> + diff --git a/dom/html/test/test_bug765780.html b/dom/html/test/test_bug765780.html new file mode 100644 index 000000000..975353e2e --- /dev/null +++ b/dom/html/test/test_bug765780.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=765780 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 765780</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /** Test for Bug 765780 **/ + SimpleTest.waitForExplicitFinish(); + window.onload = function() { + var f = $("f"); + var doc = f.contentDocument; + doc.designMode = "on"; + var s = doc.createElement("script"); + s.textContent = "parent.called = true;"; + + window.called = false; + doc.body.appendChild(s); + ok(called, "Script in designMode iframe should have run"); + + doc = doc.querySelector("iframe").contentDocument; + var s = doc.createElement("script"); + s.textContent = "parent.parent.called = true;"; + + window.called = false; + doc.body.appendChild(s); + ok(called, "Script in designMode iframe's child should have run"); + + SimpleTest.finish(); + } + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=765780">Mozilla Bug 765780</a> +<!-- Important: iframe needs to not be display: none --> +<p id="display"><iframe id="f" src="data:text/html,<iframe></iframe>"></iframe> </p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug780993.html b/dom/html/test/test_bug780993.html new file mode 100644 index 000000000..14324e8e4 --- /dev/null +++ b/dom/html/test/test_bug780993.html @@ -0,0 +1,39 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test for bug 780993</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +test(function() { + var select = document.createElement("select"); + var option = document.createElement("option"); + select.appendChild(option); + assert_equals(select[0], option); + select[0] = null; + assert_equals(option.parentNode, null); + assert_equals(select[0], undefined); +}, "Should be able to set select[n] to null."); +test(function() { + var select = document.createElement("select"); + var option = document.createElement("option"); + var option2 = document.createElement("option"); + select.appendChild(option); + assert_equals(select[0], option); + select[0] = option2; + assert_equals(option.parentNode, null); + assert_equals(option2.parentNode, select); + assert_equals(select[0], option2); +}, "Should be able to set select[n] to an option element"); +test(function() { + var select = document.createElement("select"); + var option = document.createElement("option"); + select.appendChild(option); + assert_equals(select[0], option); + assert_throws(null, function() { + select[0] = 42; + }); + assert_equals(option.parentNode, select); + assert_equals(select[0], option); +}, "Should not be able to set select[n] to a primitive."); +</script> diff --git a/dom/html/test/test_bug787134.html b/dom/html/test/test_bug787134.html new file mode 100644 index 000000000..37daa8e33 --- /dev/null +++ b/dom/html/test/test_bug787134.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=787134 +--> +<head> + <title>Test for Bug 787134</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787134">Mozilla Bug 787134</a> +<p id="display"></p> +<p><a id="link-test1" href="example link">example link</a></p> +<pre id="test"> +<script> + var div = document.createElement('div'); + div.innerHTML = '<a href=#></a>'; + var a = div.firstChild; + ok(a.matches(':link'), "Should match a link not in a document"); + is(div.querySelector(':link'), a, "Should find a link not in a document"); + a = document.querySelector('#link-test1'); + ok(a.matches(':link'), "Should match a link in a document with an invalid URL"); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug797113.html b/dom/html/test/test_bug797113.html new file mode 100644 index 000000000..6c246eb3c --- /dev/null +++ b/dom/html/test/test_bug797113.html @@ -0,0 +1,39 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test for bug 780993</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +test(function() { + var select = document.createElement("select"); + var option = document.createElement("option"); + select.appendChild(option); + assert_equals(select.options[0], option); + select.options[0] = null; + assert_equals(option.parentNode, null); + assert_equals(select.options[0], undefined); +}, "Should be able to set select.options[n] to null."); +test(function() { + var select = document.createElement("select"); + var option = document.createElement("option"); + var option2 = document.createElement("option"); + select.appendChild(option); + assert_equals(select.options[0], option); + select.options[0] = option2; + assert_equals(option.parentNode, null); + assert_equals(option2.parentNode, select); + assert_equals(select.options[0], option2); +}, "Should be able to set select.options[n] to an option element"); +test(function() { + var select = document.createElement("select"); + var option = document.createElement("option"); + select.appendChild(option); + assert_equals(select.options[0], option); + assert_throws(null, function() { + select.options[0] = 42; + }); + assert_equals(option.parentNode, select); + assert_equals(select.options[0], option); +}, "Should not be able to set select.options[n] to a primitive."); +</script> diff --git a/dom/html/test/test_bug803677.html b/dom/html/test/test_bug803677.html new file mode 100644 index 000000000..fd754ba00 --- /dev/null +++ b/dom/html/test/test_bug803677.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=803677 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 803677</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +<style> + .base { border:1px solid gray; } + .bad-table { display:table-cell; border:1px solid red; } +</style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=803677">Mozilla Bug 803677</a> +<p id="display"></p> +<div id="content"> + <p class="base">1</p> + <p class="base">2</p> + <p class="base">3</p> + <p class="base bad-table">4</p> + <p class="base">7</p> + <p class="base">8</p> + <p class="base">9</p> +</div> +<pre id="test"> +<script type="application/javascript"> + var p = document.querySelectorAll(".base"); + var parent = document.querySelector("body"); + var prevOffset = 0; + for (var i = 0; i < p.length; i++) { + var t = 0, e = p[i]; + is(e.offsetParent, parent, "Offset parent of all paragraphs should be the body."); + while (e) { + t += e.offsetTop; + e = e.offsetParent; + } + p[i].innerHTML = t; + + ok(t > prevOffset, "Offset should increase down the page"); + prevOffset = t; + } +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug821307.html b/dom/html/test/test_bug821307.html new file mode 100644 index 000000000..46721fcca --- /dev/null +++ b/dom/html/test/test_bug821307.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=821307 +--> +<head> + <title>Test for Bug 821307</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821307">Mozilla Bug 821307</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> + +<input id='dummy'></input> +<input type="password" id='input' value='11111111111111111' style="width:40em; font-size:40px;"></input> + +<pre id="test"> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + var dummy = document.getElementById('dummy'); + dummy.focus(); + is(document.activeElement, dummy, "Check dummy element is now focused"); + + var input = document.getElementById('input'); + var rect = input.getBoundingClientRect(); + synthesizeMouse(input, 100, rect.height/2, {}); + is(document.activeElement, input, "Check input element is now focused"); + + SimpleTest.finish(); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug827126.html b/dom/html/test/test_bug827126.html new file mode 100644 index 000000000..3d8b1a597 --- /dev/null +++ b/dom/html/test/test_bug827126.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=827126 +--> +<head> + <title>Test for Bug 827126</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=827126">Mozilla Bug 827126</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test to ensure we reflect <img align> correctly **/ +reflectString({ + element: new Image(), + attribute: "align", + otherValues: [ "left", "right", "middle", "justify" ] +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug838582.html b/dom/html/test/test_bug838582.html new file mode 100644 index 000000000..5c227c2bd --- /dev/null +++ b/dom/html/test/test_bug838582.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=838582 +--> +<head> + <title>Test for Bug 838582</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=838582">Mozilla Bug 838582</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<textarea id="t">abc</textarea> +<script type="application/javascript"> + +/** Test for Bug 838582 **/ + +var textarea = document.getElementById("t"); + +is(t.textLength, 3, "Correct textLength for defaultValue"); +t.value = "abcdef"; +is(t.textLength, 6, "Correct textLength for value"); +ok(!("controllers" in t), "Don't have web-visible controllers property"); +ok("controllers" in SpecialPowers.wrap(t), "Have chrome-visible controllers property"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug839371.html b/dom/html/test/test_bug839371.html new file mode 100644 index 000000000..293c0c452 --- /dev/null +++ b/dom/html/test/test_bug839371.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=839371 +--> +<head> + <title>Test for Bug 839371</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=839371">Mozilla Bug 839371</a> +<p id="display"></p> +<div id="content" style="display: none"> + +<div itemscope> + <data id="d1" itemprop="product-id" value="9678AOU879">The Instigator 2000</data> +</div> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 839371 **/ + +var d1 = document.getElementById("d1"), + d2 = document.createElement("data"); + +// .value IDL +is(d1.value, "9678AOU879", "value property reflects content attribute"); +d1.value = "123"; +is(d1.value, "123", "value property can be set via setter"); + +// .value reflects value attribute +reflectString({ + element: d2, + attribute: "value" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug839913.html b/dom/html/test/test_bug839913.html new file mode 100644 index 000000000..7397fa3b6 --- /dev/null +++ b/dom/html/test/test_bug839913.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for HTMLAreaElement's stringifier</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var area = document.createElement("area"); + area.href = "http://example.org/"; + assert_equals(area.href, "http://example.org/"); + assert_equals(String(area), "http://example.org/"); +}, "Area elements should stringify to the href attribute"); +</script> diff --git a/dom/html/test/test_bug841466.html b/dom/html/test/test_bug841466.html new file mode 100644 index 000000000..260ecfcca --- /dev/null +++ b/dom/html/test/test_bug841466.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=841466 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 841466</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"> + <script> + /** Test for Bug 841466 **/ +var els = ['button', 'fieldset', 'input', 'keygen', 'object', 'output', 'select', 'textarea']; +var code = "try { is(foo, 'bar', 'expected value bar from expando on element ' + localName); } catch (e) { ok(false, String(e)); }"; +els.forEach(function(el) { + var f = document.createElement("form"); + f.foo = "bar"; + f.innerHTML = '<' + el + ' onclick="' + code + '">'; + var e = f.firstChild + if (el === "keygen") { + todo_is(e.localName, "keygen", "Bug 101019"); + return; + } + e.dispatchEvent(new Event("click")); +}) + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841466">Mozilla Bug 841466</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug845057.html b/dom/html/test/test_bug845057.html new file mode 100644 index 000000000..631cd2b5c --- /dev/null +++ b/dom/html/test/test_bug845057.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=845057 +--> +<head> + <title>Test for Bug 845057</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=845057">Mozilla Bug 845057</a> +<p id="display"></p> +<div id="content"> + <iframe id="iframe" sandbox="allow-scripts"></iframe> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + var iframe = document.getElementById("iframe"), + attr = iframe.sandbox; + // Security enforcement tests for iframe sandbox are in test_iframe_* + + function eq(a, b) { + // check if two attributes are qual modulo permutation + return ((a+'').split(" ").sort()+'') == ((b+'').split(" ").sort()+''); + } + + ok(attr instanceof DOMTokenList, + "Iframe sandbox attribute is instace of DOMTokenList"); + ok(eq(attr, "allow-scripts") && + eq(iframe.getAttribute("sandbox"), "allow-scripts"), + "Stringyfied sandbox attribute is same as that of the DOM element"); + + ok(attr.contains("allow-scripts") && !attr.contains("allow-same-origin"), + "Set membership of attribute elements is ok"); + + attr.add("allow-same-origin"); + + ok(attr.contains("allow-scripts") && attr.contains("allow-same-origin"), + "Attribute contains added atom"); + ok(eq(attr, "allow-scripts allow-same-origin") && + eq(iframe.getAttribute("sandbox"), "allow-scripts allow-same-origin"), + "Stringyfied attribute with new atom is correct"); + + attr.add("allow-forms"); + attr.remove("allow-scripts"); + + ok(!attr.contains("allow-scripts") && attr.contains("allow-forms") && + attr.contains("allow-same-origin"), + "Attribute does not contain removed atom"); + ok(eq(attr, "allow-forms allow-same-origin") && + eq(iframe.getAttribute("sandbox"), "allow-forms allow-same-origin"), + "Stringyfied attribute with removed atom is correct"); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_bug869040.html b/dom/html/test/test_bug869040.html new file mode 100644 index 000000000..bfd75c7b7 --- /dev/null +++ b/dom/html/test/test_bug869040.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=869040 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 869040</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=869040">Mozilla Bug 869040</a> +<p id="display"></p> +<div id="content" style="display: none" data-foo="present1" data-bar="present2"> + +</div> +<pre id="test"> +</pre> + <script type="application/javascript"> + + /** Test for Bug 869040 **/ + var foo = "default1"; + var dataset = $("content").dataset; + for (var i = 0; i < 100000; ++i) + foo = dataset.foo; + + var bar = "default2"; + for (var j = 0; j < 100; ++j) + bar = dataset.bar; + + is(foo, "present1", "Our IC should work"); + is(bar, "present2", "Our non-IC case should work"); + </script> +</body> +</html> diff --git a/dom/html/test/test_bug870787.html b/dom/html/test/test_bug870787.html new file mode 100644 index 000000000..92a871284 --- /dev/null +++ b/dom/html/test/test_bug870787.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=870787 +--> +<head> + <title>Test for Bug 870787</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=870787">Mozilla Bug 870787</a> + +<p id="msg"></p> + +<form id="form0"></form> +<img name="img0" id="img0id"> + +<img name="img1" id="img1id" /> +<form id="form1"> + <img name="img2" id="img2id" /> +</form> +<img name="img3" id="img3id" /> + +<table> + <form id="form2"> + <tr><td> + <button name="input1" id="input1id" /> + <input name="input2" id="input2id" /> + </form> +</table> + +<table> + <form id="form3"> + <tr><td> + <img name="img4" id="img4id" /> + <img name="img5" id="img5id" /> + </form> +</table> + +<form id="form4"><img id="img6"></form> + +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 870787 **/ + +var form0 = document.getElementById("form0"); +ok(form0, "Form0 exists"); +ok(!form0.img0, "Form0.img0 doesn't exist"); +ok(!form0.img0id, "Form0.img0id doesn't exist"); + +var form1 = document.getElementById("form1"); +ok(form1, "Form1 exists"); +ok(!form1.img1, "Form1.img1 doesn't exist"); +ok(!form1.img1id, "Form1.img1id doesn't exist"); +is(form1.img2, document.getElementById("img2id"), "Form1.img2 exists"); +is(form1.img2id, document.getElementById("img2id"), "Form1.img2id exists"); +ok(!form1.img3, "Form1.img3 doesn't exist"); +ok(!form1.img3id, "Form1.img3id doesn't exist"); + +var form2 = document.getElementById("form2"); +ok(form2, "Form2 exists"); +is(form2.input1, document.getElementById("input1id"), "Form2.input1 exists"); +is(form2.input1id, document.getElementById("input1id"), "Form2.input1id exists"); +is(form2.input2, document.getElementById("input2id"), "Form2.input2 exists"); +is(form2.input2id, document.getElementById("input2id"), "Form2.input2id exists"); + +var form3 = document.getElementById("form3"); +ok(form3, "Form3 exists"); +is(form3.img4, document.getElementById("img4id"), "Form3.img4 doesn't exists"); +is(form3.img4id, document.getElementById("img4id"), "Form3.img4id doesn't exists"); +is(form3.img5, document.getElementById("img5id"), "Form3.img5 doesn't exists"); +is(form3.img5id, document.getElementById("img5id"), "Form3.img5id doesn't exists"); + +var form4 = document.getElementById("form4"); +ok(form4, "Form4 exists"); +is(Object.getOwnPropertyNames(form4.elements).indexOf("img6"), -1, "Form4.elements should not contain img6"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug871161.html b/dom/html/test/test_bug871161.html new file mode 100644 index 000000000..c2049b25b --- /dev/null +++ b/dom/html/test/test_bug871161.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=871161 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 871161</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 871161 **/ + SimpleTest.waitForExplicitFinish(); + + window.onmessage = function(e) { + is(e.data, "windows-1252", "Wrong charset"); + e.source.close(); + SimpleTest.finish(); + } + + function run() { + window.open("file_bug871161-1.html"); + } + + </script> +</head> +<body onload="run();"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=871161">Mozilla Bug 871161</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug874758.html b/dom/html/test/test_bug874758.html new file mode 100644 index 000000000..b8bfe40f3 --- /dev/null +++ b/dom/html/test/test_bug874758.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html data-expando-prop="xyz"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=874758 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 874758</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 874758 **/ + Object.prototype.expandoProp = 5; + is({}.expandoProp, 5, "Should see this on random objects"); + + is(document.head.dataset.expandoProp, 5, "Should see this on dataset too"); + is(document.documentElement.dataset.expandoProp, "xyz", + "But if the dataset has it, we should get it from there"); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=874758">Mozilla Bug 874758</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug879319.html b/dom/html/test/test_bug879319.html new file mode 100644 index 000000000..a232461ba --- /dev/null +++ b/dom/html/test/test_bug879319.html @@ -0,0 +1,92 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=879319 +--> +<head> + <title>Test for Bug 879319</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=879319">Mozilla Bug 879319</a> + +<p id="msg"></p> + +<form id="form"> + <img id="img0" name="bar0" /> +</form> +<input id="input0" name="foo0" form="form" /> +<input id="input1" name="foo1" form="form" /> +<input id="input2" name="foo2" form="form" /> + +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 879319 **/ + +var input0 = document.getElementById("input0"); +ok(input0, "input0 exists"); + +var form = document.getElementById("form"); +ok(form, "form exists"); +is(form.foo0, input0, "Form.foo0 should exist"); + +ok("foo0" in form.elements, "foo0 in form.elements"); +is(input0.form, form, "input0.form is form"); + +input0.setAttribute("name", "tmp0"); +ok("tmp0" in form.elements, "tmp0 is in form.elements"); +ok(!("foo0" in form.elements), "foo0 is not in form.elements"); +is(form.tmp0, input0, "Form.tmp0 == input0"); +is(form.foo0, input0, "Form.foo0 is still here"); + +input0.setAttribute("name", "tmp1"); +ok("tmp1" in form.elements, "tmp1 is in form.elements"); +ok(!("tmp0" in form.elements), "tmp0 is not in form.elements"); +ok(!("foo0" in form.elements), "foo0 is not in form.elements"); +is(form.tmp0, input0, "Form.tmp0 == input0"); +is(form.tmp1, input0, "Form.tmp1 == input0"); +is(form.foo0, input0, "Form.foo0 is still here"); + +input0.setAttribute("form", ""); +ok(!("foo0" in form.elements), "foo0 is not in form.elements"); +is(form.foo0, undefined, "Form.foo0 should not still be here"); +is(form.tmp0, undefined, "Form.tmp0 should not still be here"); +is(form.tmp1, undefined, "Form.tmp1 should not still be here"); + +var input1 = document.getElementById("input1"); +ok(input1, "input1 exists"); +is(form.foo1, input1, "Form.foo1 should exist"); + +ok("foo1" in form.elements, "foo1 in form.elements"); +is(input1.form, form, "input1.form is form"); + +input1.setAttribute("name", "foo0"); +ok("foo0" in form.elements, "foo0 is in form.elements"); +is(form.foo0, input1, "Form.foo0 should be input1"); +is(form.foo1, input1, "Form.foo1 should be input1"); + +var input2 = document.getElementById("input2"); +ok(input2, "input2 exists"); +is(form.foo2, input2, "Form.foo2 should exist"); +input2.parentNode.removeChild(input2); +ok(!("foo2" in form.elements), "foo2 is not in form.elements"); +is(form.foo2, undefined, "Form.foo2 should not longer be there"); + +var img0 = document.getElementById("img0"); +ok(img0, "img0 exists"); +is(form.bar0, img0, "Form.bar0 should exist"); + +img0.setAttribute("name", "old_bar0"); +is(form.old_bar0, img0, "Form.bar0 is still here"); +is(form.bar0, img0, "Form.bar0 is still here"); + +img0.parentNode.removeChild(img0); +is(form.bar0, undefined, "Form.bar0 should not be here"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug885024.html b/dom/html/test/test_bug885024.html new file mode 100644 index 000000000..118c140bd --- /dev/null +++ b/dom/html/test/test_bug885024.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html data-expando-prop="xyz"> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=885024 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 885024</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885024">Mozilla Bug 885024</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> + +<img form="t"> + +<form id="form"> + <div id="div"></div> +</form> + +<pre id="test"> + <script type="application/javascript"> + var img = document.createElement('img'); + img.setAttribute('id', 'img'); + + var div = document.getElementById('div'); + div.appendChild(img); + + var form = document.getElementById('form'); + ok(form, "form exists"); + ok(form.img, "form.img exists"); + + var img2 = document.createElement('img'); + img2.setAttribute('id', 'img2'); + img2.setAttribute('form', 'blabla'); + ok(form, "form exists2"); + div.appendChild(img2); + ok(form.img2, "form.img2 exists"); + + </script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug893537.html b/dom/html/test/test_bug893537.html new file mode 100644 index 000000000..5935529d8 --- /dev/null +++ b/dom/html/test/test_bug893537.html @@ -0,0 +1,45 @@ +<!doctype html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=893537 +--> + <head> +<title>Test for crash caused by unloading and reloading srcdoc iframes</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=893537">Mozilla Bug 893537</a> + +<iframe id="pframe" src="file_bug893537.html"></iframe> + +<pre id="test"> +<script> + <!-- Bug 895303 --> + SimpleTest.expectAssertions(0, 1); + + SimpleTest.waitForExplicitFinish(); + var pframe = $("pframe"); + + var loadState = 1; + pframe.contentWindow.addEventListener("load", function () { + + if (loadState == 1) { + var iframe = pframe.contentDocument.getElementById("iframe"); + iframe.removeAttribute("srcdoc"); + loadState = 2; + } + if (loadState == 2) { + SimpleTest.executeSoon(function () { pframe.contentWindow.location.reload() }); + loadState = 3; + } + if (loadState == 3) { + ok(true, "This is a mochitest implementation of a crashtest. To finish is to pass"); + SimpleTest.finish(); + } + }); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug95530.html b/dom/html/test/test_bug95530.html new file mode 100644 index 000000000..05cbd709b --- /dev/null +++ b/dom/html/test/test_bug95530.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=95530 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 95530</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 95530 **/ + function run() { + is(document.compatMode, "CSS1Compat", "Ensure we are in standards mode, not quirks mode."); + + var body = document.getElementsByTagName("body"); + + is(computedStyle(body[0],"margin-top"), "100px", "Ensure margin-top matches topmargin"); + is(computedStyle(body[0],"margin-bottom"), "150px", "Ensure margin-bottom matches bottommargin"); + is(computedStyle(body[0],"margin-left"), "23px", "Ensure margin-left matches leftmargin"); + is(computedStyle(body[0],"margin-right"), "64px", "Ensure margin-right matches rightmargin"); + SimpleTest.finish(); + } + SimpleTest.waitForExplicitFinish(); + window.addEventListener("load", run, false); + </script> +</head> +<body topmargin="100" bottommargin="150" leftmargin="23" rightmargin="64"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=95530">Mozilla Bug 95530</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug969346.html b/dom/html/test/test_bug969346.html new file mode 100644 index 000000000..5be76c46e --- /dev/null +++ b/dom/html/test/test_bug969346.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=969346 +--> +<head> +<title>Nesting of srcdoc iframes is permitted</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=969349">Mozilla Bug 969346</a> + +<iframe id="pframe" srcdoc="<iframe id='iframe' srcdoc='I am nested'></iframe"></iframe> + +<pre id="test"> +<script> + + SimpleTest.waitForExplicitFinish(); + addLoadEvent(function () { + var pframe = $("pframe"); + var pframeDoc = pframe.contentDocument; + var iframe = pframeDoc.getElementById("iframe"); + var innerDoc = iframe.contentDocument; + + is(innerDoc.body.innerHTML, "I am nested", "Nesting not working?"); + SimpleTest.finish(); + }); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_bug982039.html b/dom/html/test/test_bug982039.html new file mode 100644 index 000000000..22833440f --- /dev/null +++ b/dom/html/test/test_bug982039.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=982039 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 982039</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 982039 **/ + SimpleTest.waitForExplicitFinish(); + function test() { + var f = document.getElementById("testform"); + f.elements[0].disabled = true; + is(f.checkValidity(), false, + "Setting a radiobutton to disabled shouldn't make form valid."); + + f.elements[1].checked = true; + ok(f.checkValidity(), "Form should be now valid."); + + f.elements[0].required = false; + f.elements[1].required = false; + f.elements[2].required = false; + SimpleTest.finish(); + } + + </script> +</head> +<body onload="test()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982039">Mozilla Bug 982039</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +<form action="#" id="testform"> + <input type="radio" name="radio" value="1" required> + <input type="radio" name="radio" value="2" required> + <input type="radio" name="radio" value="3" required> +</form> +</body> +</html> diff --git a/dom/html/test/test_change_crossorigin.html b/dom/html/test/test_change_crossorigin.html new file mode 100644 index 000000000..01f31bc09 --- /dev/null +++ b/dom/html/test/test_change_crossorigin.html @@ -0,0 +1,89 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=696451 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 696451</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 696451 **/ + + SimpleTest.waitForExplicitFinish(); + + var img = new Image, + canvas = document.createElement("canvas"), + ctx = canvas.getContext("2d"), + src = "http://example.com/tests/dom/html/test/image-allow-credentials.png", + imgDone = false, + imgNotAllowedToLoadDone = false; + + img.src = src; + img.crossOrigin = "Anonymous"; + + img.addEventListener("load", function() { + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage( img, 0, 0 ); + try { + canvas.toDataURL("image/png"); + ok(true, "Image was refetched with setting crossOrigin."); + } catch (e) { + ok(false, "Image was not refetched after setting crossOrigin."); + } + + imgDone = true; + if (imgDone && imgNotAllowedToLoadDone) { + SimpleTest.finish(); + } + }); + + img.addEventListener("error", function (event) { + ok(false, "Should be able to load cross origin image with proper headers."); + + imgDone = true; + if (imgDone && imgNotAllowedToLoadDone) { + SimpleTest.finish(); + } + }); + + var imgNotAllowedToLoad = new Image; + + imgNotAllowedToLoad.src = "http://example.com/tests/dom/html/test/image.png"; + + imgNotAllowedToLoad.crossOrigin = "Anonymous"; + + imgNotAllowedToLoad.addEventListener("load", function() { + ok(false, "Image should not be allowed to load without " + + "allow-cross-origin-access headers."); + + imgNotAllowedToLoadDone = true; + if (imgDone && imgNotAllowedToLoadDone) { + SimpleTest.finish(); + } + }); + + imgNotAllowedToLoad.addEventListener("error", function() { + ok(true, "Image should not be allowed to load without " + + "allow-cross-origin-access headers."); + imgNotAllowedToLoadDone = true; + if (imgDone && imgNotAllowedToLoadDone) { + SimpleTest.finish(); + } + }); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696451">Mozilla Bug 696451</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_checked.html b/dom/html/test/test_checked.html new file mode 100644 index 000000000..9d40a6ded --- /dev/null +++ b/dom/html/test/test_checked.html @@ -0,0 +1,358 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=418756 +https://bugzilla.mozilla.org/show_bug.cgi?id=617528 +--> +<head> + <title>Test for Bug 418756 and 617528</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +Mozilla bug +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418756">418756</a> +and +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=617528">617528</a> +<p id="display"></p> +<div id="content"> + <form id="f1"> + </form> + <form id="f2"> + </form> + <menu id="m1"> + </menu> + <menu id="m2"> + </menu> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript; version=1.7"> + +/** Test for Bug 418756 and 617528 **/ +var group1; +var group2; +var group3; + +var tags = ["input", "menuitem"]; +for (let tag of tags) { + +function bounce(node) { + let n = node.nextSibling; + let p = node.parentNode; + p.removeChild(node); + p.insertBefore(node, n); +} + +var createdNodes = []; + +function cleanup() { + for (let node of createdNodes) { + if (node.parentNode) { + node.parentNode.removeChild(node); + } + } + + createdNodes = []; +} + +var typeMapper = { + 'c': 'checkbox', + 'r': 'radio' +}; + +var id = 0; + +// type can be 'c' for 'checkbox' and 'r' for 'radio' +function createNode(type, name, checked) { + let node = document.createElement(tag); + node.setAttribute("type", typeMapper[type]); + if (checked) { + node.setAttribute("checked", "checked"); + } + node.setAttribute("id", type + (++id)); + node.setAttribute(tag == "input" ? "name" : "radiogroup", name); + createdNodes.push(node); + return node; +} + +var types = ['c', 'r']; + +// First make sure that setting .checked makes .defaultChecked changes no +// longer affect .checked. +for (let type of types) { + let n = createNode(type, '', false); + is(n.defaultChecked, false, "Bogus defaultChecked on " + typeMapper[type]); + is(n.checked, false, "Bogus checked on " + typeMapper[type]); + n.defaultChecked = true; + is(n.defaultChecked, true, "Bogus defaultChecked on " + typeMapper[type] + + "after mutation"); + is(n.checked, true, "Bogus checked on " + typeMapper[type] + + "after mutation"); + n.checked = false; + is(n.defaultChecked, true, "Bogus defaultChecked on " + typeMapper[type] + + "after second mutation"); + is(n.checked, false, "Bogus checked on " + typeMapper[type] + + "after second mutation"); + n.defaultChecked = false; + is(n.defaultChecked, false, "Bogus defaultChecked on " + typeMapper[type] + + "after third mutation"); + is(n.checked, false, "Bogus checked on " + typeMapper[type] + + "after third mutation"); + n.defaultChecked = true; + is(n.defaultChecked, true, "Bogus defaultChecked on " + typeMapper[type] + + "after fourth mutation"); + is(n.checked, false, "Bogus checked on " + typeMapper[type] + + "after fourth mutation"); +} + +cleanup(); + +// Now check that bouncing a control that's the only one of its kind has no +// effect +for (let type of types) { + let n = createNode(type, 'test1', true); + $(tag == "input" ? "f1" : "m1").appendChild(n); + n.checked = false; + n.defaultChecked = false; + bounce(n); + n.defaultChecked = true; + is(n.checked, false, "We set .checked on this " + typeMapper[type]); +} + +cleanup(); + +// Now check that playing with a single radio in a group affects all +// other radios in the group (but not radios not in that group) +group1 = [ createNode('r', 'g1', false), + createNode('r', 'g1', false), + createNode('r', 'g1', false) ]; +group2 = [ createNode('r', 'g2', false), + createNode('r', 'g2', false), + createNode('r', 'g2', false) ]; +group3 = [ createNode('r', 'g1', false), + createNode('r', 'g1', false), + createNode('r', 'g1', false) ]; +for (let g of group1) { + $(tag == "input" ? "f1" : "m1").appendChild(g); +} +for (let g of group2) { + $(tag == "input" ? "f1" : "m1").appendChild(g); +} +for (let g of group3) { + $(tag == "input" ? "f2" : "m2").appendChild(g); +} + +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, false, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 1"); + is(g.checked, false, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checkedhecked wrong pass 1"); + } +} + +group1[1].defaultChecked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && group1.indexOf(g) == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 2"); + is(g.checked, n == 1 && group1.indexOf(g) == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 2"); + } +} + +group1[0].defaultChecked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 1 || + group1.indexOf(g) == 0), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 3"); + is(g.checked, n == 1 && group1.indexOf(g) == 0, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 3"); + } +} + +group1[2].defaultChecked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 4"); + is(g.checked, n == 1 && group1.indexOf(g) == 2, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 4"); + } +} + +var next = group1[1].nextSibling; +var p = group1[1].parentNode; +p.removeChild(group1[1]); +group1[1].defaultChecked = false; +group1[1].defaultChecked = true; +p.insertBefore(group1[1], next); +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 5"); + is(g.checked, n == 1 && group1.indexOf(g) == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 5"); + } +} + +for (let g of group1) { + g.defaultChecked = false; +} +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, false, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 6"); + is(g.checked, false, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checkedhecked wrong pass 6"); + } +} + +group1[1].checked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, false, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 7"); + is(g.checked, n == 1 && group1.indexOf(g) == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 7"); + } +} + +group1[0].defaultChecked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && group1.indexOf(g) == 0, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 8"); + is(g.checked, n == 1 && group1.indexOf(g) == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 8"); + } +} + +group1[2].defaultChecked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 || + group1.indexOf(g) == 2), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 9"); + is(g.checked, n == 1 && group1.indexOf(g) == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 9"); + } +} +group1[1].parentNode.removeChild(group1[1]); +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 || + group1.indexOf(g) == 2), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 10"); + is(g.checked, n == 1 && group1.indexOf(g) == 1, + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 10"); + } +} + +group1[2].checked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 || + group1.indexOf(g) == 2), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 11"); + is(g.checked, n == 1 && (group1.indexOf(g) == 1 || + group1.indexOf(g) == 2), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 11"); + } +} + +group1[0].checked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 || + group1.indexOf(g) == 2), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 12"); + is(g.checked, n == 1 && (group1.indexOf(g) == 1 || + group1.indexOf(g) == 0), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 12"); + } +} + +next = group2[1].nextSibling; +p = group2[1].parentNode; +p.removeChild(group2[1]); +p.insertBefore(group2[1], next); +group2[0].checked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 || + group1.indexOf(g) == 2), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 13"); + is(g.checked, (n == 1 && (group1.indexOf(g) == 1 || + group1.indexOf(g) == 0)) || + (n == 2 && group2.indexOf(g) == 0), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 13"); + } +} + +p.insertBefore(group2[1], next); +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 || + group1.indexOf(g) == 2), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 14"); + is(g.checked, (n == 1 && (group1.indexOf(g) == 1 || + group1.indexOf(g) == 0)) || + (n == 2 && group2.indexOf(g) == 0), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 14"); + } +} + +group2[1].defaultChecked = true; +for (let n of [1, 2, 3]) { + for (let g of window["group"+n]) { + is(g.defaultChecked, (n == 1 && (group1.indexOf(g) == 0 || + group1.indexOf(g) == 2)) || + (n == 2 && group2.indexOf(g) == 1), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] defaultChecked wrong pass 15"); + is(g.checked, (n == 1 && (group1.indexOf(g) == 1 || + group1.indexOf(g) == 0)) || + (n == 2 && group2.indexOf(g) == 0), + "group" + n + "[" + window["group"+n].indexOf(g) + + "] checked wrong pass 15"); + } +} + +cleanup(); + +} +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_dir_attributes_reflection.html b/dom/html/test/test_dir_attributes_reflection.html new file mode 100644 index 000000000..c9c4022a3 --- /dev/null +++ b/dom/html/test/test_dir_attributes_reflection.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLDirectoryElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLDirectoryElement attributes reflection **/ + +// .name +reflectBoolean({ + element: document.createElement("dir"), + attribute: "compact", +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_dl_attributes_reflection.html b/dom/html/test/test_dl_attributes_reflection.html new file mode 100644 index 000000000..1fbab51ab --- /dev/null +++ b/dom/html/test/test_dl_attributes_reflection.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLDListElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLDListElement attributes reflection **/ + +// .compact +reflectBoolean({ + element: document.createElement("dl"), + attribute: "compact" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_document-element-inserted.html b/dom/html/test/test_document-element-inserted.html new file mode 100644 index 000000000..483d0cb0a --- /dev/null +++ b/dom/html/test/test_document-element-inserted.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Media test: document-element-inserted</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<iframe id = 'media'> +</iframe> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +if (navigator.platform.startsWith("Win")) { + SimpleTest.expectAssertions(0, 4); +} + +SimpleTest.waitForExplicitFinish(); +var loc; + +var observe = function(doc){ + if (doc == media.contentDocument) { + ok(media.contentDocument.location.toString().indexOf(loc) != -1, + "The loaded media should be " + loc); + next(); + } +} + +var media = document.getElementById('media'); +var tests = [ + "../../../media/test/short-video.ogv", + "../../../media/test/sound.ogg", + "../../content/test/image.png" +] + +function next() { + if (tests.length > 0) { + var t = tests.shift(); + loc = t.substring(t.indexOf("test")); + media.setAttribute("src",t); + } + else { + SpecialPowers.removeObserver(observe, "document-element-inserted"); + SimpleTest.finish(); + } +} + +SpecialPowers.addObserver(observe, "document-element-inserted", false) +next(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_document.watch.html b/dom/html/test/test_document.watch.html new file mode 100644 index 000000000..54509823b --- /dev/null +++ b/dom/html/test/test_document.watch.html @@ -0,0 +1,129 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=903332 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 903332</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 903332 **/ + + var watch1Called; + function watch1(prop, oldValue, newValue) + { + is(watch1Called, false, "watch1Called not reset properly?"); + watch1Called = true; + + is(prop, "cookie", "wrong property name passed to watch1"); + return newValue; + } + + var watch2Called; + function watch2(prop, oldValue, newValue) + { + is(watch2Called, false, "watch2Called not reset properly?"); + watch2Called = true; + + is(prop, "cookie", "wrong property name passed to watch2"); + return newValue; + } + + // Just in case subsequent tests depend on a particular value... + var originalValue = document.cookie; + ok(true, "originalValue: " + originalValue); + + var originalPrefix = originalValue.length > 0 ? originalValue + "; " : ""; + + try + { + // trial set (no watch) to verify things work + document.cookie = "first=set"; + is(document.cookie, originalPrefix + "first=set", + "first value correct"); + + // add a watch + document.watch("cookie", watch1); + + // set, check for watch invoked + watch1Called = false; + document.cookie = "second=set"; + is(watch1Called, true, "watch1 function should be called"); + is(document.cookie, originalPrefix + "first=set; second=set", + "second value correct"); + + // and a second time, just in case + watch1Called = false; + document.cookie = "third=set"; + is(watch1Called, true, "watch1 function should be called"); + is(document.cookie, originalPrefix + "first=set; second=set; third=set", + "third value correct"); + + // overwrite the current watch with a new one + document.watch("cookie", watch2); + + // set, check for watch invoked + watch1Called = false; + watch2Called = false; + document.cookie = "fourth=set"; + is(watch1Called, false, "watch1 invoked erroneously"); + is(watch2Called, true, "watch2 function should be called"); + is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set", + "fourth value correct"); + + // and a second time, just in case + watch1Called = false; + watch2Called = false; + document.cookie = "fifth=set"; + is(watch1Called, false, "watch1 invoked erroneously"); + is(watch2Called, true, "watch2 function should be called"); + is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set; fifth=set", + "fifth value correct"); + + // remove the watch + document.unwatch("cookie"); + + // check for non-invocation now + watch1Called = false; + watch2Called = false; + document.cookie = "sixth=set"; + is(watch1Called, false, "watch1 shouldn't be called"); + is(watch2Called, false, "watch2 shouldn't be called"); + is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set; fifth=set; sixth=set", + "sixth value correct"); + } + finally + { + // reset + document.unwatch("cookie"); // harmless, should be no-op except if bugs + + var d = new Date(); + d.setTime(0); + var suffix = "=; expires=" + d.toGMTString(); + + document.cookie = "first" + suffix; + document.cookie = "second" + suffix; + document.cookie = "third" + suffix; + document.cookie = "fourth" + suffix; + document.cookie = "fifth" + suffix; + document.cookie = "sixth" + suffix; + } + + is(document.cookie, originalValue, + "document.cookie isn't what it was initially! expect bustage further " + + "down the line"); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=903332">Mozilla Bug 903332</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_documentAll.html b/dom/html/test/test_documentAll.html new file mode 100644 index 000000000..ec877acec --- /dev/null +++ b/dom/html/test/test_documentAll.html @@ -0,0 +1,167 @@ +<html> +<!-- +Tests for document.all +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>Tests for document.all</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=259332">Mozilla Bug 259332</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=393629">Mozilla Bug 393629</a> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448904">Mozilla Bug 448904</a> +<p id="display"> +</p> +<div id="content" style="display: none"> + <a id="id1">A</a> + <a id="id2">B</a> + <a id="id2">C</a> + <a id="id3">D</a> + <a id="id3">E</a> + <a id="id3">F</a> +</div> +<iframe id="subframe" src="data:text/html,<span id='x'></span>" + style="display: none"></iframe> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +p = document.getElementById("content"); + +// Test that several elements with the same id or name behave correctly +function testNumSame() { + is(document.all.id0, undefined, "no ids"); + is(document.all.namedItem("id0"), null, "no ids"); + is(document.all.id1, p.children[0], "one id"); + is(document.all.id2[0], p.children[1], "two ids"); + is(document.all.id2[1], p.children[2], "two ids"); + is(document.all.id2.length, 2, "two length"); + is(document.all.id3[0], p.children[3], "three ids"); + is(document.all.id3[1], p.children[4], "three ids"); + is(document.all.id3[2], p.children[5], "three ids"); + is(document.all.id3.length, 3, "three length"); +} +testNumSame(); +p.innerHTML = p.innerHTML.replace(/id=/g, "name="); +testNumSame(); + + +// Test that dynamic changes behave properly + +// Add two elements and check that they are added to the correct lists +child = Array.prototype.slice.call(p.children); +child[6] = document.createElement("a"); +child[6].id = "id0"; +p.appendChild(child[6]); +child[7] = document.createElement("a"); +child[7].id = "id1"; +p.appendChild(child[7]); +is(document.all.id0, child[6], "now one id"); +is(document.all.id1[0], child[0], "now two ids"); +is(document.all.id1[1], child[7], "now two ids"); +is(document.all.id1.length, 2, "now two length"); + +// Remove and element and check that the list shrinks +rC(child[1]); +is(document.all.id2, child[2], "now just one id"); + +// Change an id and check that its removed and added to the correct lists +child[4].name = "id1"; +is(document.all.id1[0], child[0], "now three ids"); +is(document.all.id1[1], child[4], "now three ids"); +is(document.all.id1[2], child[7], "now three ids"); +is(document.all.id1.length, 3, "now three length"); +is(document.all.id3[1], child[5], "now just two ids"); +is(document.all.id3.length, 2, "now two length"); + +// Remove all elements from a list and check that it goes empty +id3list = document.all.id3; +rC(child[3]); +is(id3list.length, 1, "now one length"); +rC(child[5]); +is(document.all.id3, undefined, "now none"); +is(document.all.namedItem("id3"), null, "now none (namedItem)"); +is(id3list.length, 0, "now none length"); + +// Give an element both a name and id and check that it appears in two lists +p.insertBefore(child[1], child[2]); // restore previously removed +id1list = document.all.id1; +id2list = document.all.id2; +child[1].id = "id1"; +is(id1list[0], child[0], "now four ids"); +is(id1list[1], child[1], "now four ids"); +is(id1list[2], child[4], "now four ids"); +is(id1list[3], child[7], "now four ids"); +is(id1list.length, 4, "now four length"); +is(id2list[0], child[1], "still two ids"); +is(id2list[1], child[2], "still two ids"); +is(id2list.length, 2, "still two length"); + + +// Check that document.all behaves list a list of all elements +allElems = document.getElementsByTagName("*"); +ok(testArraysSame(document.all, allElems), "arrays same"); +length = document.all.length; +expectedLength = length + p.getElementsByTagName("*").length + 1; +p.appendChild(p.cloneNode(true)); +ok(testArraysSame(document.all, allElems), "arrays still same"); +is(document.all.length, expectedLength, "grew correctly"); + +// Check which elements the 'name' attribute works on +var elementNames = + ['applet','abbr','acronym','address','area','a','b','base', + 'bgsound','big','blockquote','br','canvas','center','cite','code', + 'col','colgroup','dd','del','dfn','dir','div','dir','dl','dt','em','embed', + 'fieldset','font','form','frame','frameset','head','i','iframe','img', + 'input','ins','isindex','kbd','keygen','label','li','legend','link','menu', + 'multicol','noscript','noframes','object','spacer','table','td','td','th', + 'thead','tfoot','tr','textarea','select','option','spacer','param', + 'marquee','hr','title','hx','tt','u','ul','var','wbr','sub','sup','cite', + 'code','q','nobr','ol','p','pre','s','samp','small','body','html','map', + 'bdo','legend','listing','style','script','tbody','caption','meta', + 'optgroup','button','span','strike','strong','td'].sort(); +var hasName = + ['applet','a','embed','form','iframe','img','input','object','textarea', + 'select','map','meta','button','frame','frameset'].sort(); + +elementNames.forEach(function (name) { + nameval = 'namefor' + name; + + e = document.createElement(name); + p.appendChild(e); + e.setAttribute('name', nameval); + + if (name == hasName[0]) { + is(document.all[nameval], e, "should have name"); + hasName.shift(); + } + else { + is(document.all[nameval], undefined, "shouldn't have name"); + is(document.all.namedItem(nameval), null, "shouldn't have name (namedItem)"); + } +}); +is(hasName.length, 0, "found all names"); + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + var subdoc = $("subframe").contentDocument; + is(subdoc.all.x, subdoc.body.firstChild, + "document.all should work in a subdocument"); + SimpleTest.finish(); +}); + +// Utility functions +function rC(node) { + node.parentNode.removeChild(node); +} +function testArraysSame(a1, a2) { + return Array.prototype.every.call(a1, function(e, index) { + return a2[index] === e; + }) && a1.length == a2.length; +} +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_element_prototype.html b/dom/html/test/test_element_prototype.html new file mode 100644 index 000000000..44ef4edd6 --- /dev/null +++ b/dom/html/test/test_element_prototype.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=844127 +--> +<head> + <title>Test for Bug 844127</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=844127">Mozilla Bug 844127</a> + +<script type="text/javascript"> + +/** Test for Bug 844127 **/ + +var a1 = document.createElement('bgsound'); +var a2 = document.createElement('image'); +var a3 = document.createElement('multicol'); +var a4 = document.createElement('spacer'); +var a5 = document.createElement('isindex'); + +is(Object.getPrototypeOf(a1), HTMLUnknownElement.prototype, "Prototype for bgsound should be correct"); +is(Object.getPrototypeOf(a2), HTMLElement.prototype, "Prototype for image should be correct"); +is(Object.getPrototypeOf(a3), HTMLUnknownElement.prototype, "Prototype for multicol should be correct"); +is(Object.getPrototypeOf(a4), HTMLUnknownElement.prototype, "Prototype for spacer should be correct"); +is(Object.getPrototypeOf(a5), HTMLUnknownElement.prototype, "Prototype for isindex should be correct"); + +</script> +</body> +</html> diff --git a/dom/html/test/test_embed_attributes_reflection.html b/dom/html/test/test_embed_attributes_reflection.html new file mode 100644 index 000000000..85001598a --- /dev/null +++ b/dom/html/test/test_embed_attributes_reflection.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLEmbedElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLEmbedElement attributes reflection **/ + +// .src (URL) +reflectURL({ + element: document.createElement("embed"), + attribute: "src", +}); + +// .type (String) +reflectString({ + element: document.createElement("embed"), + attribute: "type", +}); + +// .width (String) +reflectString({ + element: document.createElement("embed"), + attribute: "width", +}); + +// .height (String) +reflectString({ + element: document.createElement("embed"), + attribute: "height", +}); + +// .align (String) +reflectString({ + element: document.createElement("embed"), + attribute: "align", +}); + +// .name (String) +reflectString({ + element: document.createElement("embed"), + attribute: "name", +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_filepicker_default_directory.html b/dom/html/test/test_filepicker_default_directory.html new file mode 100644 index 000000000..c2212baa0 --- /dev/null +++ b/dom/html/test/test_filepicker_default_directory.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1194893 +--> +<head> + <title>Test for filepicker default directory</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1194893">Mozilla Bug 1194893</a> +<div id="content"> + <input type="file" id="f"> +</div> +<pre id="text"> +<script class="testbody" type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); +const { Cc: Cc, Ci: Ci } = SpecialPowers; + +// Platform-independent directory names are #define'd in xpcom/io/nsDirectoryServiceDefs.h +var defaultUploadDirectory = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIDirectoryService) + .QueryInterface(Ci.nsIProperties) + .get("Desk", Ci.nsIFile); + +// When we want to test an upload directory other than the default, we need to +// get a valid directory in a platform-independent way. Since NS_OS_DESKTOP_DIR +// may fallback to NS_OS_HOME_DIR, let's use NS_OS_TMP_DIR. +var customUploadDirectory = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIDirectoryService) + .QueryInterface(Ci.nsIProperties) + .get("TmpD", Ci.nsIFile); + +// Useful for debugging +//info("defaultUploadDirectory" + defaultUploadDirectory.path); +//info("customUploadDirectory" + customUploadDirectory.path); + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +// need to show the MockFilePicker so .displayDirectory gets set +var f = document.getElementById("f"); +f.focus(); + +var testIndex = 0; +var tests = [ + ["", defaultUploadDirectory.path], + [customUploadDirectory.path, customUploadDirectory.path] +] + +MockFilePicker.showCallback = function(filepicker) { + info(SpecialPowers.wrap(MockFilePicker).displayDirectory.path); + + is(SpecialPowers.wrap(MockFilePicker).displayDirectory.path, + tests[testIndex][1]); + + if (++testIndex == tests.length) { + MockFilePicker.cleanup(); + SimpleTest.finish(); + } else { + launchNextTest(); + } +} + +function launchNextTest() { + SpecialPowers.pushPrefEnv( + { 'set': [ + ['dom.input.fallbackUploadDir', tests[testIndex][0]], + ]}, + function () { + f.click(); + }); +} + +launchNextTest(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_focusshift_button.html b/dom/html/test/test_focusshift_button.html new file mode 100644 index 000000000..2ae4743be --- /dev/null +++ b/dom/html/test/test_focusshift_button.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for shifting focus while mouse clicking on button</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> + +<script class="testbody" type="application/javascript;version=1.7"> + +var result = ""; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.waitForFocus(function() { + synthesizeMouseAtCenter(document.getElementById("button"), { }); + if (/Mac/.test(navigator.platform)) { + // Buttons don't focus when clicked on Mac. + is(result, "", "Focus button then input"); + } + else { + is(result, "(focus button)(blur button)(focus input)", "Focus button then input"); + } + SimpleTest.finish(); +}); +</script> + + +<button id="button" onfocus="result += '(focus button)'; document.getElementById('input').focus()" + onblur="result += '(blur button)'">Focus</button> +<input id="input" value="Test" onfocus="result += '(focus input)'" + onblur="result += '(blur input)'"> + +</body> +</html> diff --git a/dom/html/test/test_form-parsing.html b/dom/html/test/test_form-parsing.html new file mode 100644 index 000000000..6a4a4c54e --- /dev/null +++ b/dom/html/test/test_form-parsing.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Form parsing</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<div id="content" style="display: none"> + <div> + <form name="test" action="test" id="test"> + <input type="text" name="text1" id="text1" /> + <input type="text" name="text2" id="text2" /> + </div> + <input type="text" name="text3" id="text3" /> + <input type="text" name="text4" id="text4" /> + <input type="text" name="text5" id="text5" /> + <input type="text" name="text6" id="text6" /> + </form> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + + var form1 = document.getElementById("test"); + var elem1 = form1.getElementsByTagName("*"); + var elem1Length = elem1.length; + var form1ElementsLength = form1.elements.length; + + is(form1ElementsLength, 6, "form.elements must include mis-nested elements"); + is(elem1Length, 2, "form must not include mis-nested elements"); +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_formData.html b/dom/html/test/test_formData.html new file mode 100644 index 000000000..a8b1bc0f7 --- /dev/null +++ b/dom/html/test/test_formData.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=690659 +--> +<head> + <title>Test for Bug 690659 and 739173</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=690659">Mozilla Bug 690659 & 739173</a> +<script type="text/javascript" src="./formData_test.js"></script> +<script type="text/javascript"> +SimpleTest.waitForExplicitFinish(); + +function runMainThreadAndWorker() { + var mt = new Promise(function(resolve) { + runTest(resolve); + }); + + var worker; + var w = new Promise(function(resolve) { + worker = new Worker("formData_worker.js"); + worker.onmessage = function(event) { + if (event.data.type == 'finish') { + resolve(); + } else if (event.data.type == 'status') { + ok(event.data.status, event.data.msg); + } else if (event.data.type == 'todo') { + todo(event.data.status, event.data.msg); + } + } + + worker.onerror = function(event) { + ok(false, "Worker had an error: " + event.message + " at " + event.lineno); + resolve(); + }; + + worker.postMessage(true); + }); + + return Promise.all([mt, w]); +} + +runMainThreadAndWorker().then(SimpleTest.finish); +</script> +</body> +</html> diff --git a/dom/html/test/test_formSubmission.html b/dom/html/test/test_formSubmission.html new file mode 100644 index 000000000..0edfeaeb8 --- /dev/null +++ b/dom/html/test/test_formSubmission.html @@ -0,0 +1,825 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=523771 +--> +<head> + <title>Test for Bug 523771</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=523771">Mozilla Bug 523771</a> +<p id="display"></p> +<iframe name="target_iframe" id="target_iframe"></iframe> +<form action="form_submit_server.sjs" target="target_iframe" id="form" + method="POST" enctype="multipart/form-data"> + <table> + <tr> + <td>Control type</td> + <td>Name and value</td> + <td>Name, empty value</td> + <td>Name, no value</td> + <td>Empty name, with value</td> + <td>No name, with value</td> + <td>No name or value</td> + <td>Strange name/value</td> + </tr> + <tr> + <td>Default input</td> + <td><input name="n1_1" value="v1_1"></td> + <td><input name="n1_2" value=""></td> + <td><input name="n1_3"></td> + <td><input name="" value="v1_4"></td> + <td><input value="v1_5"></td> + <td><input></td> + <td><input name="n1_7_ _ _ _ _"" + value="v1_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Text input</td> + <td><input type=text name="n2_1" value="v2_1"></td> + <td><input type=text name="n2_2" value=""></td> + <td><input type=text name="n2_3"></td> + <td><input type=text name="" value="v2_4"></td> + <td><input type=text value="v2_5"></td> + <td><input type=text></td> + <td><input type=text name="n2_7_ _ _ _ _"" + value="v2_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Checkbox unchecked</td> + <td><input type=checkbox name="n3_1" value="v3_1"></td> + <td><input type=checkbox name="n3_2" value=""></td> + <td><input type=checkbox name="n3_3"></td> + <td><input type=checkbox name="" value="v3_4"></td> + <td><input type=checkbox value="v3_5"></td> + <td><input type=checkbox></td> + <td><input type=checkbox name="n3_7_ _ _ _ _"" + value="v3_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Checkbox checked</td> + <td><input checked type=checkbox name="n4_1" value="v4_1"></td> + <td><input checked type=checkbox name="n4_2" value=""></td> + <td><input checked type=checkbox name="n4_3"></td> + <td><input checked type=checkbox name="" value="v4_4"></td> + <td><input checked type=checkbox value="v4_5"></td> + <td><input checked type=checkbox></td> + <td><input checked type=checkbox + name="n4_7_ _ _ _ _"" + value="v4_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Radio unchecked</td> + <td><input type=radio name="n5_1" value="v5_1"></td> + <td><input type=radio name="n5_2" value=""></td> + <td><input type=radio name="n5_3"></td> + <td><input type=radio name="" value="v5_4"></td> + <td><input type=radio value="v5_5"></td> + <td><input type=radio></td> + <td><input type=radio name="n5_7_ _ _ _ _"" + value="v5_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Radio checked</td> + <td><input checked type=radio name="n6_1" value="v6_1"></td> + <td><input checked type=radio name="n6_2" value=""></td> + <td><input checked type=radio name="n6_3"></td> + <td><input checked type=radio name="" value="v6_4"></td> + <td><input checked type=radio value="v6_5"></td> + <td><input checked type=radio></td> + <td><input checked type=radio + name="n6_7_ _ _ _ _"" + value="v6_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Hidden input</td> + <td><input type=hidden name="n7_1" value="v7_1"></td> + <td><input type=hidden name="n7_2" value=""></td> + <td><input type=hidden name="n7_3"></td> + <td><input type=hidden nane="" value="v7_4"></td> + <td><input type=hidden value="v7_5"></td> + <td><input type=hidden></td> + <td><input type=hidden name="n7_7_ _ _ _ _"" + value="v7_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Password input</td> + <td><input type=password name="n8_1" value="v8_1"></td> + <td><input type=password name="n8_2" value=""></td> + <td><input type=password name="n8_3"></td> + <td><input type=password name="" value="v8_4"></td> + <td><input type=password value="v8_5"></td> + <td><input type=password></td> + <td><input type=password name="n8_7_ _ _ _ _"" + value="v8_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Submit input</td> + <td><input type=submit name="n9_1" value="v9_1"></td> + <td><input type=submit name="n9_2" value=""></td> + <td><input type=submit name="n9_3"></td> + <td><input type=submit name="" value="v9_4"></td> + <td><input type=submit value="v9_5"></td> + <td><input type=submit></td> + <td><input type=submit name="n9_7_ _ _ _ _"" + value="v9_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Button input</td> + <td><input type=button name="n10_1" value="v10_1"></td> + <td><input type=button name="n10_2" value=""></td> + <td><input type=button name="n10_3"></td> + <td><input type=button name="" value="v10_4"></td> + <td><input type=button value="v10_5"></td> + <td><input type=button></td> + <td><input type=button name="n10_7_ _ _ _ _"" + value="v10_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Image input</td> + <td><input type=image src="file_formSubmission_img.jpg" name="n11_1" value="v11_1"></td> + <td><input type=image src="file_formSubmission_img.jpg" name="n11_2" value=""></td> + <td><input type=image src="file_formSubmission_img.jpg" name="n11_3"></td> + <td><input type=image src="file_formSubmission_img.jpg" name="" value="v11_4"></td> + <td><input type=image src="file_formSubmission_img.jpg" value="v11_5"></td> + <td><input type=image src="file_formSubmission_img.jpg"></td> + <td><input type=image src="file_formSubmission_img.jpg" + name="n11_7_ _ _ _ _"" + value="v11_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Reset input</td> + <td><input type=reset name="n12_1" value="v12_1"></td> + <td><input type=reset name="n12_2" value=""></td> + <td><input type=reset name="n12_3"></td> + <td><input type=reset name="" value="v12_4"></td> + <td><input type=reset value="v12_5"></td> + <td><input type=reset></td> + <td><input type=reset name="n12_7_ _ _ _ _"" + value="v12_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Unknown input</td> + <td><input type=foobar name="n13_1" value="v13_1"></td> + <td><input type=foobar name="n13_2" value=""></td> + <td><input type=foobar name="n13_3"></td> + <td><input type=foobar name="" value="v13_4"></td> + <td><input type=foobar value="v13_5"></td> + <td><input type=foobar></td> + <td><input type=foobar name="n13_7_ _ _ _ _"" + value="v13_7_ _ _ _ _""></td> + </tr> + <tr> + <td>Default button</td> + <td><button name="n14_1" value="v14_1"></button></td> + <td><button name="n14_2" value=""></button></td> + <td><button name="n14_3"></button></td> + <td><button name="" value="v14_4"></button></td> + <td><button value="v14_5"></button></td> + <td><button></button></td> + <td><button name="n14_7_ _ _ _ _"" + value="v14_7_ _ _ _ _""></button></td> + </tr> + <tr> + <td>Submit button</td> + <td><button type=submit name="n15_1" value="v15_1"></button></td> + <td><button type=submit name="n15_2" value=""></button></td> + <td><button type=submit name="n15_3"></button></td> + <td><button type=submit name="" value="v15_4"></button></td> + <td><button type=submit value="v15_5"></button></td> + <td><button type=submit></button></td> + <td><button type=submit name="n15_7_ _ _ _ _"" + value="v15_7_ _ _ _ _""></button></td> + </tr> + <tr> + <td>Button button</td> + <td><button type=button name="n16_1" value="v16_1"></button></td> + <td><button type=button name="n16_2" value=""></button></td> + <td><button type=button name="n16_3"></button></td> + <td><button type=button name="" value="v16_4"></button></td> + <td><button type=button value="v16_5"></button></td> + <td><button type=button></button></td> + <td><button type=button name="n16_7_ _ _ _ _"" + value="v16_7_ _ _ _ _""></button></td> + </tr> + <tr> + <td>Reset button</td> + <td><button type=reset name="n17_1" value="v17_1"></button></td> + <td><button type=reset name="n17_2" value=""></button></td> + <td><button type=reset name="n17_3"></button></td> + <td><button type=reset name="" value="v17_4"></button></td> + <td><button type=reset value="v17_5"></button></td> + <td><button type=reset></button></td> + <td><button type=reset name="n17_7_ _ _ _ _"" + value="v17_7_ _ _ _ _""></button></td> + </tr> + <tr> + <td>Unknown button</td> + <td><button type=foobar name="n18_1" value="v18_1"></button></td> + <td><button type=foobar name="n18_2" value=""></button></td> + <td><button type=foobar name="n18_3"></button></td> + <td><button type=foobar name="" value="v18_4"></button></td> + <td><button type=foobar value="v18_5"></button></td> + <td><button type=foobar ></button></td> + <td><button type=foobar name="n18_7_ _ _ _ _"" + value="v18_7_ _ _ _ _""></button></td> + </tr> + <tr> + <td><input type='url'></td> + <td><input type=url name="n19_1" value="http://v19_1.org"></td> + <td><input type=url name="n19_2" value=""></td> + <td><input type=url name="n19_3"></td> + <td><input type=url name="" value="http://v19_4.org"></td> + <td><input type=url value="http://v19_5.org"></td> + <td><input type=url ></td> + <td><input type=url name="n19_7_ _ _ __"" + value="http://v19_7_ _ _ __""> + <!-- Put UTF-8 value in the "strange" column. --> + <input type=url name="n19_8" value="http://mózillä.órg"></td> + </tr> + <tr> + <td><input type='email'></td> + <td><input type=email name="n20_1" value="v20_1@bar"></td> + <td><input type=email name="n20_2" value=""></td> + <td><input type=email name="n20_3"></td> + <td><input type=email name="" value="v20_4@bar"></td> + <td><input type=email value="v20_5@bar"></td> + <td><input type=email ></td> + <td><input type=email name="n20_7_ _ _ __"" + value="v20_7_ _ _ __"@bar"> + <!-- Put UTF-8 value is the "strange" column. --> + <input type=email name="n20_8" value="foo@mózillä.órg"></td> + </tr> + </table> + + <p> + File input: + <input type=file name="file_1" class="setfile"> + <input type=file name="file_2"> + <input type=file name="" class="setfile"> + <input type=file name=""> + <input type=file class="setfile"> + <input type=file> + </p> + <p> + Multifile input: + <input multiple type=file name="file_3" class="setfile"> + <input multiple type=file name="file_4" class="setfile multi"> + <input multiple type=file name="file_5"> + <input multiple type=file name="" class="setfile"> + <input multiple type=file name="" class="setfile multi"> + <input multiple type=file name=""> + <input multiple type=file class="setfile"> + <input multiple type=file class="setfile multi"> + <input multiple type=file> + </p> + + <p> + Textarea: + <textarea name="t1">t_1_v</textarea> + <textarea name="t2"></textarea> + <textarea name="">t_3_v</textarea> + <textarea>t_4_v</textarea> + <textarea></textarea> + <textarea name="t6"> +t_6_v</textarea> + <textarea name="t7">t_7_v +</textarea> + <textarea name="t8"> + + t_8_v +</textarea> + <textarea name="t9_ _ _ _ _"">t_9_ _ _ _ _"_v</textarea> + <textarea name="t10" value="t_10_bogus">t_10_v</textarea> + </p> + + <p> + Select one: + + <select name="sel_1"></select> + <select name="sel_1b"><option></option></select> + <select name="sel_1c"><option selected></option></select> + + <select name="sel_2"><option value="sel_2_v"></option></select> + <select name="sel_3"><option selected value="sel_3_v"></option></select> + + <select name="sel_4"><option value="sel_4_v1"></option><option value="sel_4_v2"></option></select> + <select name="sel_5"><option selected value="sel_5_v1"></option><option value="sel_5_v2"></option></select> + <select name="sel_6"><option value="sel_6_v1"></option><option selected value="sel_6_v2"></option></select> + + <select name="sel_7"><option>sel_7_v1</option><option>sel_7_v2</option></select> + <select name="sel_8"><option selected>sel_8_v1</option><option>sel_8_v2</option></select> + <select name="sel_9"><option>sel_9_v1</option><option selected>sel_9_v2</option></select> + + <select name="sel_10"><option value="sel_10_v1">sel_10_v1_text</option><option value="sel_10_v2">sel_10_v2_text</option></select> + <select name="sel_11"><option selected value="sel_11_v1">sel_11_v1_text</option><option value="sel_11_v2">sel_11_v2_text</option></select> + <select name="sel_12"><option value="sel_12_v1">sel_12_v1_text</option><option selected value="sel_12_v2">sel_12_v2_text</option></select> + + <select name="sel_13"><option disabled>sel_13_v1</option><option>sel_13_v2</option></select> + <select name="sel_14"><option disabled selected>sel_14_v1</option><option>sel_14_v2</option></select> + <select name="sel_15"><option disabled>sel_15_v1</option><option selected>sel_15_v2</option></select> + + <select name="sel_16"><option>sel_16_v1</option><option disabled>sel_16_v2</option></select> + <select name="sel_17"><option selected>sel_17_v1</option><option disabled>sel_17_v2</option></select> + <select name="sel_18"><option>sel_18_v1</option><option disabled selected>sel_18_v2</option></select> + + <select name=""><option selected value="sel_13_v1"></option><option value="sel_13_v2"></option></select> + <select name=""><option value="sel_14_v1"></option><option selected value="sel_14_v2"></option></select> + <select name=""><option selected>sel_15_v1</option><option>sel_15_v2</option></select> + <select name=""><option>sel_16_v1</option><option selected>sel_16_v2</option></select> + + <select><option selected value="sel_17_v1"></option><option value="sel_17_v2"></option></select> + <select><option value="sel_18_v1"></option><option selected value="sel_18_v2"></option></select> + <select><option selected>sel_19_v1</option><option>sel_19_v2</option></select> + <select><option>sel_20_v1</option><option selected>sel_20_v2</option></select> + </p> + + <p> + Select multiple: + + <select multiple name="msel_1"></select> + <select multiple name="msel_1b"><option></option></select> + <select multiple name="msel_1c"><option selected></option></select> + + <select multiple name="msel_2"><option value="msel_2_v"></option></select> + <select multiple name="msel_3"><option selected value="msel_3_v"></option></select> + + <select multiple name="msel_4"><option value="msel_4_v1"></option><option value="msel_4_v2"></option></select> + <select multiple name="msel_5"><option selected value="msel_5_v1"></option><option value="msel_5_v2"></option></select> + <select multiple name="msel_6"><option value="msel_6_v1"></option><option selected value="msel_6_v2"></option></select> + <select multiple name="msel_7"><option selected value="msel_7_v1"></option><option selected value="msel_7_v2"></option></select> + + <select multiple name="msel_8"><option>msel_8_v1</option><option>msel_8_v2</option></select> + <select multiple name="msel_9"><option selected>msel_9_v1</option><option>msel_9_v2</option></select> + <select multiple name="msel_10"><option>msel_10_v1</option><option selected>msel_10_v2</option></select> + <select multiple name="msel_11"><option selected>msel_11_v1</option><option selected>msel_11_v2</option></select> + + <select multiple name="msel_12"><option value="msel_12_v1">msel_12_v1_text</option><option value="msel_12_v2">msel_12_v2_text</option></select> + <select multiple name="msel_13"><option selected value="msel_13_v1">msel_13_v1_text</option><option value="msel_13_v2">msel_13_v2_text</option></select> + <select multiple name="msel_14"><option value="msel_14_v1">msel_14_v1_text</option><option selected value="msel_14_v2">msel_14_v2_text</option></select> + <select multiple name="msel_15"><option selected value="msel_15_v1">msel_15_v1_text</option><option selected value="msel_15_v2">msel_15_v2_text</option></select> + + <select multiple name="msel_16"><option>msel_16_v1</option><option>msel_16_v2</option><option>msel_16_v3</option></select> + <select multiple name="msel_17"><option selected>msel_17_v1</option><option>msel_17_v2</option><option>msel_17_v3</option></select> + <select multiple name="msel_18"><option>msel_18_v1</option><option selected>msel_18_v2</option><option>msel_18_v3</option></select> + <select multiple name="msel_19"><option selected>msel_19_v1</option><option selected>msel_19_v2</option><option>msel_19_v3</option></select> + <select multiple name="msel_20"><option>msel_20_v1</option><option>msel_20_v2</option><option selected>msel_20_v3</option></select> + <select multiple name="msel_21"><option selected>msel_21_v1</option><option>msel_21_v2</option><option selected>msel_21_v3</option></select> + <select multiple name="msel_22"><option>msel_22_v1</option><option selected>msel_22_v2</option><option selected>msel_22_v3</option></select> + <select multiple name="msel_23"><option selected>msel_23_v1</option><option selected>msel_23_v2</option><option selected>msel_23_v3</option></select> + + <select multiple name="msel_24"><option disabled>msel_24_v1</option><option>msel_24_v2</option></select> + <select multiple name="msel_25"><option disabled selected>msel_25_v1</option><option>msel_25_v2</option></select> + <select multiple name="msel_26"><option disabled>msel_26_v1</option><option selected>msel_26_v2</option></select> + <select multiple name="msel_27"><option disabled selected>msel_27_v1</option><option selected>msel_27_v2</option></select> + + <select multiple name="msel_28"><option>msel_28_v1</option><option disabled>msel_28_v2</option></select> + <select multiple name="msel_29"><option selected>msel_29_v1</option><option disabled>msel_29_v2</option></select> + <select multiple name="msel_30"><option>msel_30_v1</option><option disabled selected>msel_30_v2</option></select> + <select multiple name="msel_31"><option selected>msel_31_v1</option><option disabled selected>msel_31_v2</option></select> + + <select multiple name="msel_32"><option disabled selected>msel_32_v1</option><option disabled selected>msel_32_v2</option></select> + + <select multiple name=""><option>msel_33_v1</option><option>msel_33_v2</option></select> + <select multiple name=""><option selected>msel_34_v1</option><option>msel_34_v2</option></select> + <select multiple name=""><option>msel_35_v1</option><option selected>msel_35_v2</option></select> + <select multiple name=""><option selected>msel_36_v1</option><option selected>msel_36_v2</option></select> + + <select multiple><option>msel_37_v1</option><option>msel_37_v2</option></select> + <select multiple><option selected>msel_38_v1</option><option>msel_38_v2</option></select> + <select multiple><option>msel_39_v1</option><option selected>msel_39_v2</option></select> + <select multiple><option selected>msel_40_v1</option><option selected>msel_40_v2</option></select> + </p> +</form> +<pre id="test"> +<script class="testbody" type="text/javascript;version=1.8"> + +SimpleTest.waitForExplicitFinish(); + +const placeholder_myFile1 = {}; +const placeholder_myFile2 = {}; +const placeholder_emptyFile = {}; + +var myFile1, myFile2, emptyFile; +let openerURL = SimpleTest.getTestFileURL("formSubmission_chrome.js"); +let opener = SpecialPowers.loadChromeScript(openerURL); + +{ + let xhr = new XMLHttpRequest; + xhr.open("GET", "/dynamic/getMyDirectory.sjs", false); + xhr.send(); + let basePath = xhr.responseText; + + opener.addMessageListener("files.opened", onFilesOpened); + opener.sendAsyncMessage("files.open", [ + basePath + "file_formSubmission_text.txt", + basePath + "file_formSubmission_img.jpg", + ]); +} + +function onFilesOpened(files) { + let [textFile, imageFile] = files; + opener.destroy(); + + let singleFile = textFile; + let multiFile = [textFile, imageFile]; + + var addList = document.getElementsByClassName("setfile"); + let i = 0; + var input; + while (input = addList[i++]) { + if (input.classList.contains("multi")) { + SpecialPowers.wrap(input).mozSetFileArray(multiFile); + } else { + SpecialPowers.wrap(input).mozSetFileArray([singleFile]); + } + } + + input = document.createElement("input"); + input.type = "file"; + input.multiple = true; + SpecialPowers.wrap(input).mozSetFileArray(multiFile); + myFile1 = input.files[0]; + myFile2 = input.files[1]; + is(myFile1.size, 20, "File1 size"); + is(myFile2.size, 2711, "File2 size"); + emptyFile = { name: "", type: "application/octet-stream" }; + + // Now, actually run the tests; see below. + onFilesSet(); +}; + +var expectedSub = [ + // Default input + { name: "n1_1", value: "v1_1" }, + { name: "n1_2", value: "" }, + { name: "n1_3", value: "" }, + { name: "n1_7_\r\n_\r\n_\r\n_ _\"", value: "v1_7____ _\"" }, + // Text input + { name: "n2_1", value: "v2_1" }, + { name: "n2_2", value: "" }, + { name: "n2_3", value: "" }, + { name: "n2_7_\r\n_\r\n_\r\n_ _\"", value: "v2_7____ _\"" }, + // Checkbox unchecked + // Checkbox checked + { name: "n4_1", value: "v4_1" }, + { name: "n4_2", value: "" }, + { name: "n4_3", value: "on" }, + { name: "n4_7_\r\n_\r\n_\r\n_ _\"", value: "v4_7_\r\n_\r\n_\r\n_ _\"" }, + // Radio unchecked + // Radio checked + { name: "n6_1", value: "v6_1" }, + { name: "n6_2", value: "" }, + { name: "n6_3", value: "on" }, + { name: "n6_7_\r\n_\r\n_\r\n_ _\"", value: "v6_7_\r\n_\r\n_\r\n_ _\"" }, + // Hidden input + { name: "n7_1", value: "v7_1" }, + { name: "n7_2", value: "" }, + { name: "n7_3", value: "" }, + { name: "n7_7_\r\n_\r\n_\r\n_ _\"", value: "v7_7_\r\n_\r\n_\r\n_ _\"" }, + // Password input + { name: "n8_1", value: "v8_1" }, + { name: "n8_2", value: "" }, + { name: "n8_3", value: "" }, + { name: "n8_7_\r\n_\r\n_\r\n_ _\"", value: "v8_7____ _\"" }, + // Submit input + // Button input + // Image input + // Reset input + // Unknown input + { name: "n13_1", value: "v13_1" }, + { name: "n13_2", value: "" }, + { name: "n13_3", value: "" }, + { name: "n13_7_\r\n_\r\n_\r\n_ _\"", value: "v13_7____ _\"" }, + // <input type='url'> + { name: "n19_1", value: "http://v19_1.org" }, + { name: "n19_2", value: "" }, + { name: "n19_3", value: "" }, + { name: "n19_7_\r\n_\r\n_\r\n__\"", value: "http://v19_7_____\"" }, + { name: "n19_8", value: "http://m\xf3zill\xe4.\xf3rg" }, + // <input type='email'> + { name: "n20_1", value: "v20_1@bar" }, + { name: "n20_2", value: "" }, + { name: "n20_3", value: "" }, + { name: "n20_7_\r\n_\r\n_\r\n__\"", value: "v20_7_____\"@bar" }, + { name: "n20_8", value: "foo@mózillä.órg" }, + // Default button + // Submit button + // Button button + // Reset button + // Unknown button + // File + { name: "file_1", value: placeholder_myFile1 }, + { name: "file_2", value: placeholder_emptyFile }, + // Multiple file + { name: "file_3", value: placeholder_myFile1 }, + { name: "file_4", value: placeholder_myFile1 }, + { name: "file_4", value: placeholder_myFile2 }, + { name: "file_5", value: placeholder_emptyFile }, + // Textarea + { name: "t1", value: "t_1_v" }, + { name: "t2", value: "" }, + { name: "t6", value: "t_6_v" }, + { name: "t7", value: "t_7_v\r\n" }, + { name: "t8", value: "\r\n t_8_v \r\n" }, + { name: "t9_\r\n_\r\n_\r\n_ _\"", value: "t_9_\r\n_\r\n_\r\n_ _\"_v" }, + { name: "t10", value: "t_10_v" }, + + // Select one + { name: "sel_1b", value: "" }, + { name: "sel_1c", value: "" }, + { name: "sel_2", value: "sel_2_v" }, + { name: "sel_3", value: "sel_3_v" }, + { name: "sel_4", value: "sel_4_v1" }, + { name: "sel_5", value: "sel_5_v1" }, + { name: "sel_6", value: "sel_6_v2" }, + { name: "sel_7", value: "sel_7_v1" }, + { name: "sel_8", value: "sel_8_v1" }, + { name: "sel_9", value: "sel_9_v2" }, + { name: "sel_10", value: "sel_10_v1" }, + { name: "sel_11", value: "sel_11_v1" }, + { name: "sel_12", value: "sel_12_v2" }, + { name: "sel_13", value: "sel_13_v2" }, + { name: "sel_15", value: "sel_15_v2" }, + { name: "sel_16", value: "sel_16_v1" }, + { name: "sel_17", value: "sel_17_v1" }, + // Select three + { name: "msel_1c", value: "" }, + { name: "msel_3", value: "msel_3_v" }, + { name: "msel_5", value: "msel_5_v1" }, + { name: "msel_6", value: "msel_6_v2" }, + { name: "msel_7", value: "msel_7_v1" }, + { name: "msel_7", value: "msel_7_v2" }, + { name: "msel_9", value: "msel_9_v1" }, + { name: "msel_10", value: "msel_10_v2" }, + { name: "msel_11", value: "msel_11_v1" }, + { name: "msel_11", value: "msel_11_v2" }, + { name: "msel_13", value: "msel_13_v1" }, + { name: "msel_14", value: "msel_14_v2" }, + { name: "msel_15", value: "msel_15_v1" }, + { name: "msel_15", value: "msel_15_v2" }, + { name: "msel_17", value: "msel_17_v1" }, + { name: "msel_18", value: "msel_18_v2" }, + { name: "msel_19", value: "msel_19_v1" }, + { name: "msel_19", value: "msel_19_v2" }, + { name: "msel_20", value: "msel_20_v3" }, + { name: "msel_21", value: "msel_21_v1" }, + { name: "msel_21", value: "msel_21_v3" }, + { name: "msel_22", value: "msel_22_v2" }, + { name: "msel_22", value: "msel_22_v3" }, + { name: "msel_23", value: "msel_23_v1" }, + { name: "msel_23", value: "msel_23_v2" }, + { name: "msel_23", value: "msel_23_v3" }, + { name: "msel_26", value: "msel_26_v2" }, + { name: "msel_27", value: "msel_27_v2" }, + { name: "msel_29", value: "msel_29_v1" }, + { name: "msel_31", value: "msel_31_v1" }, +]; + +var expectedAugment = [ + { name: "aName", value: "aValue" }, + //{ name: "aNameBool", value: "false" }, + { name: "aNameNum", value: "9.2" }, + { name: "aNameFile1", value: placeholder_myFile1 }, + { name: "aNameFile2", value: placeholder_myFile2 }, + //{ name: "aNameObj", value: "[object XMLHttpRequest]" }, + //{ name: "aNameNull", value: "null" }, + //{ name: "aNameUndef", value: "undefined" }, +]; + +function checkMPSubmission(sub, expected, test) { + function getPropCount(o) { + var x, l = 0; + for (x in o) ++l; + return l; + } + function mpquote(s) { + return s.replace(/\r\n/g, " ") + .replace(/\r/g, " ") + .replace(/\n/g, " ") + .replace(/\"/g, "\\\""); + } + + is(sub.length, expected.length, + "Correct number of multipart items in " + test); + + if (sub.length != expected.length) { + alert(JSON.stringify(sub)); + } + + var i; + for (i = 0; i < expected.length; ++i) { + if (!("fileName" in expected[i])) { + is(sub[i].headers["Content-Disposition"], + "form-data; name=\"" + mpquote(expected[i].name) + "\"", + "Correct name in " + test); + is (getPropCount(sub[i].headers), 1, + "Wrong number of headers in " + test); + is(sub[i].body, + expected[i].value.replace(/\r\n|\r|\n/, "\r\n"), + "Correct value in " + test); + } + else { + is(sub[i].headers["Content-Disposition"], + "form-data; name=\"" + mpquote(expected[i].name) + "\"; filename=\"" + + mpquote(expected[i].fileName) + "\"", + "Correct name in " + test); + is(sub[i].headers["Content-Type"], + expected[i].contentType, + "Correct content type in " + test); + is (getPropCount(sub[i].headers), 2, + "Wrong number of headers in " + test); + is(sub[i].body, + expected[i].value, + "Correct value in " + test); + } + } +} + +function utf8encode(s) { + return unescape(encodeURIComponent(s)); +} + +function checkURLSubmission(sub, expected) { + function urlEscape(s) { + return escape(utf8encode(s)).replace(/%20/g, "+") + .replace(/\//g, "%2F") + .replace(/@/g, "%40"); + } + + subItems = sub.split("&"); + is(subItems.length, expected.length, + "Correct number of url items"); + var i; + for (i = 0; i < expected.length; ++i) { + let expect = urlEscape(expected[i].name) + "=" + + urlEscape(("fileName" in expected[i]) ? expected[i].fileName : expected[i].value); + is (subItems[i], expect, "expected URL part"); + } +} + +function checkPlainSubmission(sub, expected) { + + is(sub, + expected.map(function(v) { + return v.name + "=" + + (("fileName" in v) ? v.fileName : v.value) + + "\r\n"; + }).join(""), + "Correct submission"); +} + +function setDisabled(list, state) { + Array.prototype.forEach.call(list, function(e) { + e.disabled = state; + }); +} + +var gen; +function onFilesSet() { + gen = runTest(); + addLoadEvent(function() { + gen.next(); + }); +} + +function runTest() { + // Set up the expectedSub array + fileReader1 = new FileReader; + fileReader1.readAsBinaryString(myFile1); + fileReader2 = new FileReader; + fileReader2.readAsBinaryString(myFile2); + fileReader1.onload = fileReader2.onload = function() { gen.next(); }; + yield undefined; // Wait for both FileReaders. We don't care which order they finish. + yield undefined; + function fileFixup(o) { + if (o.value === placeholder_myFile1) { + o.value = fileReader1.result; + o.fileName = myFile1.name; + o.contentType = myFile1.type; + } + else if (o.value === placeholder_myFile2) { + o.value = fileReader2.result; + o.fileName = myFile2.name; + o.contentType = myFile2.type; + } + else if (o.value === placeholder_emptyFile) { + o.value = ""; + o.fileName = emptyFile.name; + o.contentType = emptyFile.type; + } + }; + expectedSub.forEach(fileFixup); + expectedAugment.forEach(fileFixup); + + var form = $("form"); + + // multipart/form-data + + var iframe = $("target_iframe"); + iframe.onload = function() { gen.next(); }; + + // Make normal submission + form.submit(); + yield undefined; // Wait for iframe to load as a result of the submission + var submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkMPSubmission(submission, expectedSub, "normal submission"); + + // Disabled controls + setDisabled(document.querySelectorAll("input, select, textarea"), true); + form.submit(); + yield undefined; + submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkMPSubmission(submission, [], "disabled controls"); + + // Reenabled controls + setDisabled(document.querySelectorAll("input, select, textarea"), false); + form.submit(); + yield undefined; + submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkMPSubmission(submission, expectedSub, "reenabled controls"); + + // text/plain + form.action = "form_submit_server.sjs?plain"; + form.enctype = "text/plain"; + form.submit(); + yield undefined; + submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkPlainSubmission(submission, expectedSub); + + // application/x-www-form-urlencoded + form.action = "form_submit_server.sjs?url"; + form.enctype = "application/x-www-form-urlencoded"; + form.submit(); + yield undefined; + submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkURLSubmission(submission, expectedSub); + + // application/x-www-form-urlencoded + form.action = "form_submit_server.sjs?xxyy"; + form.method = "GET"; + form.enctype = ""; + form.submit(); + yield undefined; + submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkURLSubmission(submission, expectedSub); + + // application/x-www-form-urlencoded + form.action = "form_submit_server.sjs"; + form.method = ""; + form.enctype = ""; + form.submit(); + yield undefined; + submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkURLSubmission(submission, expectedSub); + + // Send form using XHR and FormData + xhr = new XMLHttpRequest(); + xhr.onload = function() { gen.next(); }; + xhr.open("POST", "form_submit_server.sjs"); + xhr.send(new FormData(form)); + yield undefined; // Wait for XHR load + checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData"); + + // Send disabled form using XHR and FormData + setDisabled(document.querySelectorAll("input, select, textarea"), true); + xhr.open("POST", "form_submit_server.sjs"); + xhr.send(new FormData(form)); + yield undefined; + checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData"); + setDisabled(document.querySelectorAll("input, select, textarea"), false); + + // Send FormData + function addToFormData(fd) { + fd.append("aName", "aValue"); + fd.append("aNameNum", 9.2); + fd.append("aNameFile1", myFile1); + fd.append("aNameFile2", myFile2); + } + var fd = new FormData(); + addToFormData(fd); + xhr.open("POST", "form_submit_server.sjs"); + xhr.send(fd); + yield undefined; + checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData"); + + // Augment <form> using FormData + fd = new FormData(form); + addToFormData(fd); + xhr.open("POST", "form_submit_server.sjs"); + xhr.send(fd); + yield undefined; + checkMPSubmission(JSON.parse(xhr.responseText), + expectedSub.concat(expectedAugment), "send augmented FormData"); + + SimpleTest.finish(); + yield undefined; +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_formSubmission2.html b/dom/html/test/test_formSubmission2.html new file mode 100644 index 000000000..2d0eb42f9 --- /dev/null +++ b/dom/html/test/test_formSubmission2.html @@ -0,0 +1,221 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=523771 +--> +<head> + <title>Test for Bug 523771</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=523771">Mozilla Bug 523771</a> +<p id="display"></p> +<iframe name="target_iframe" id="target_iframe"></iframe> +<form action="form_submit_server.sjs" target="target_iframe" id="form" + method="POST" enctype="multipart/form-data"> + <table> + <tr> + <td>Control type</td> + <td>Name and value</td> + <td>Name, empty value</td> + <td>Name, no value</td> + <td>Empty name, with value</td> + <td>No name, with value</td> + <td>No name or value</td> + </tr> + <tr> + <td>Submit input</td> + <td><input type=submit name="n1_1" value="v1_1"></td> + <td><input type=submit name="n1_2" value=""></td> + <td><input type=submit name="n1_3"></td> + <td><input type=submit name="" value="v1_4"></td> + <td><input type=submit value="v1_5"></td> + <td><input type=submit></td> + </tr> + <tr> + <td>Image input</td> + <td><input type=image src="file_formSubmission_img.jpg" name="n2_1" value="v2_1"></td> + <td><input type=image src="file_formSubmission_img.jpg" name="n2_2" value=""></td> + <td><input type=image src="file_formSubmission_img.jpg" name="n2_3"></td> + <td><input type=image src="file_formSubmission_img.jpg" name="" value="v2_4"></td> + <td><input type=image src="file_formSubmission_img.jpg" value="v2_5"></td> + <td><input type=image src="file_formSubmission_img.jpg"></td> + </tr> + <tr> + <td>Submit button</td> + <td><button type=submit name="n3_1" value="v3_1"></button></td> + <td><button type=submit name="n3_2" value=""></button></td> + <td><button type=submit name="n3_3"></button></td> + <td><button type=submit name="" value="v3_4"></button></td> + <td><button type=submit value="v3_5"></button></td> + <td><button type=submit ></button></td> + </tr> + <tr> + <td>Submit button with text</td> + <td><button type=submit name="n4_1" value="v4_1">text here</button></td> + <td><button type=submit name="n4_2" value="">text here</button></td> + <td><button type=submit name="n4_3">text here</button></td> + <td><button type=submit name="" value="v4_4">text here</button></td> + <td><button type=submit value="v4_5">text here</button></td> + <td><button type=submit>text here</button></td> + </tr> + </table> +</form> +<pre id="test"> +<script class="testbody" type="text/javascript;version=1.8"> + +var gen = runTest(); + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(function() { + gen.next(); +}); + +var expectedSub = [ + // Submit input + [{ name: "n1_1", value: "v1_1" }], + [{ name: "n1_2", value: "" }], + [{ name: "n1_3", value: "Submit Query" }], + [], + [], + [], + // Image input + [{ name: "n2_1.x", value: "10" }, + { name: "n2_1.y", value: "7" }], + [{ name: "n2_2.x", value: "10" }, + { name: "n2_2.y", value: "7" }], + [{ name: "n2_3.x", value: "10" }, + { name: "n2_3.y", value: "7" }], + [{ name: "x", value: "10" }, + { name: "y", value: "7" }], + [{ name: "x", value: "10" }, + { name: "y", value: "7" }], + [{ name: "x", value: "10" }, + { name: "y", value: "7" }], + // Submit button + [{ name: "n3_1", value: "v3_1" }], + [{ name: "n3_2", value: "" }], + [{ name: "n3_3", value: "" }], + [], + [], + [], + // Submit button with text + [{ name: "n4_1", value: "v4_1" }], + [{ name: "n4_2", value: "" }], + [{ name: "n4_3", value: "" }], + [], + [], + [], +]; + +function checkSubmission(sub, expected) { + function getPropCount(o) { + var x, l = 0; + for (x in o) ++l; + return l; + } + + is(sub.length, expected.length, + "Correct number of items"); + var i; + for (i = 0; i < expected.length; ++i) { + if (!("fileName" in expected[i])) { + is(sub[i].headers["Content-Disposition"], + "form-data; name=\"" + expected[i].name + "\"", + "Correct name"); + is (getPropCount(sub[i].headers), 1, + "Wrong number of headers"); + } + else { + is(sub[i].headers["Content-Disposition"], + "form-data; name=\"" + expected[i].name + "\"; filename=\"" + + expected[i].fileName + "\"", + "Correct name"); + is(sub[i].headers["Content-Type"], + expected[i].contentType, + "Correct content type"); + is (getPropCount(sub[i].headers), 2, + "Wrong number of headers"); + } + is(sub[i].body, + expected[i].value, + "Correct value"); + } +} + +function clickImage(aTarget, aX, aY) +{ + aTarget.style.position = "absolute"; + aTarget.style.top = "0"; + aTarget.style.left = "0"; + aTarget.offsetTop; + + var wu = SpecialPowers.getDOMWindowUtils(aTarget.ownerDocument.defaultView); + + wu.sendMouseEvent('mousedown', aX, aY, 0, 1, 0); + wu.sendMouseEvent('mouseup', aX, aY, 0, 0, 0); + + aTarget.style.position = ""; + aTarget.style.top = ""; + aTarget.style.left = ""; +} + +function runTest() { + // Make normal submission + var form = $("form"); + var iframe = $("target_iframe"); + iframe.onload = function() { gen.next(); }; + + var elements = form.querySelectorAll("input, button"); + + is(elements.length, expectedSub.length, + "tests vs. expected out of sync"); + + var i; + for (i = 0; i < elements.length && i < expectedSub.length; ++i) { + elem = elements[i]; + if (elem.localName != "input" || elem.type != "image") { + elem.click(); + } + else { + clickImage(elem, 10, 7); + } + yield undefined; + + var submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkSubmission(submission, expectedSub[i]); + } + + // Disabled controls + var i; + for (i = 0; i < elements.length && i < expectedSub.length; ++i) { + elem = elements[i]; + form.onsubmit = function() { + elem.disabled = true; + } + if (elem.localName != "input" || elem.type != "image") { + elem.click(); + } + else { + clickImage(elem, 10, 7); + } + yield undefined; + + is(elem.disabled, true, "didn't disable"); + elem.disabled = false; + form.onsubmit = undefined; + + var submission = JSON.parse(iframe.contentDocument.documentElement.textContent); + checkSubmission(submission, []); + } + + SimpleTest.finish(); + yield undefined; +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_formelements.html b/dom/html/test/test_formelements.html new file mode 100644 index 000000000..c4714aa6b --- /dev/null +++ b/dom/html/test/test_formelements.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=772869 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 772869</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a> +<p id="display"></p> +<div id="content" style="display: none"> + <form id="f"> + <input name="x"> + <input type="image" name="a"> + <input type="file" name="y"> + <input type="submit" name="z"> + <input id="w"> + <input name="w"> + </form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 772869 **/ +var x = $("f").elements; +x.something = "another"; +names = []; +for (var name in x) { + names.push(name); +} +is(names.length, 9, "Should have 9 enumerated names"); +is(names[0], "0", "Enum entry 1"); +is(names[1], "1", "Enum entry 2"); +is(names[2], "2", "Enum entry 3"); +is(names[3], "3", "Enum entry 4"); +is(names[4], "4", "Enum entry 5"); +is(names[5], "something", "Enum entry 6"); +is(names[6], "namedItem", "Enum entry 7"); +is(names[7], "item", "Enum entry 8"); +is(names[8], "length", "Enum entry 9"); + +names = Object.getOwnPropertyNames(x); +is(names.length, 10, "Should have 10 items"); +// Now sort entries 5 through 8, for comparison purposes. We don't sort the +// whole array, because we want to make sure the ordering between the parts +// is correct +temp = names.slice(5, 9); +temp.sort(); +names.splice.bind(names, 5, 4).apply(null, temp); +is(names.length, 10, "Should still have 10 items"); +is(names[0], "0", "Entry 1") +is(names[1], "1", "Entry 2") +is(names[2], "2", "Entry 3") +is(names[3], "3", "Entry 4") +is(names[4], "4", "Entry 5") +is(names[5], "w", "Entry 6") +is(names[6], "x", "Entry 7") +is(names[7], "y", "Entry 8") +is(names[8], "z", "Entry 9") +is(names[9], "something", "Entry 10") +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_fragment_form_pointer.html b/dom/html/test/test_fragment_form_pointer.html new file mode 100644 index 000000000..c9ed9dbc5 --- /dev/null +++ b/dom/html/test/test_fragment_form_pointer.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=946585 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 946585</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=946585">Mozilla Bug 946585</a> +<p id="display"></p> +<div id="content" style="display: none"> +<form><div id="formdiv"></div></form> +</div> +<pre id="test"> +</pre> +<script type="application/javascript"> +/** Test for Bug 946585 **/ +var formDiv = document.getElementById("formdiv"); +formDiv.innerHTML = '<form>'; +is(formDiv.firstChild, null, "InnerHTML should not produce form element because the div has a form pointer."); +</script> +</body> +</html> diff --git a/dom/html/test/test_fullscreen-api-race.html b/dom/html/test/test_fullscreen-api-race.html new file mode 100644 index 000000000..03c6c6da3 --- /dev/null +++ b/dom/html/test/test_fullscreen-api-race.html @@ -0,0 +1,166 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test for race conditions of Fullscreen API</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<script> + +function Deferred() { + this.promise = new Promise(resolve => { + this.resolve = resolve; + }); +} + +function checkIsChromeFullscreen(win, inFullscreen) { + return SimpleTest.promiseWaitForCondition( + () => win.fullScreen == inFullscreen, + "The window should exit fullscreen state"); +} + +SimpleTest.waitForExplicitFinish(); +// XXX This actually exposes a true race condition, but it could rarely +// happen in real world, because it only happens when requestFullscreen +// is called immediately after exiting fullscreen in certain condition, +// and in real life, requestFullscreen can only be called inside a user +// event handler. But we want to fix this race condition at some point, +// via queuing all exiting request as well as entering request together +// which we may eventually need to do for bug 1188256. +SimpleTest.requestFlakyTimeout( + "Need to wait for potential fullscreen transition"); +addLoadEvent(function () { + SpecialPowers.pushPrefEnv({ + "set": [ + ["full-screen-api.unprefix.enabled", true], + ["full-screen-api.allow-trusted-requests-only", false] + ] + }, next); +}); + +const OPEN_WINDOW_FUNCS = [ + function openNewTab() { + return window.open("about:blank"); + }, + function openNewWindow() { + return window.open("about:blank", "", "width=300,height=200"); + } +]; + +const ACTION_FUNCS = [ + function navigate(win) { + info("About to navigate to another page"); + var deferred = new Deferred(); + win.location = "data:text/html,<html>"; + setTimeout(() => { + SimpleTest.waitForFocus(() => { + checkIsChromeFullscreen(win, false).then(() => { + win.close(); + deferred.resolve(); + }); + }, win); + }, 0); + return deferred.promise; + }, + function closeWindow(win) { + info("About to close the window"); + win.close(); + return Promise.resolve(); + }, + function exitFullscreen(win) { + info("About to cancel fullscreen"); + var deferred = new Deferred(); + function listener() { + win.removeEventListener("fullscreenchange", listener); + ok(!win.document.fullscreenElement, "Should exit fullscreen"); + checkIsChromeFullscreen(win, false).then(() => { + win.close(); + deferred.resolve(); + }); + } + win.addEventListener("fullscreenchange", listener); + win.document.exitFullscreen(); + return deferred.promise; + }, + function exitAndClose(win) { + info("About to cancel fullscreen and close the window"); + win.document.exitFullscreen(); + win.close(); + return Promise.resolve(); + } +]; + +function* testGenerator() { + for (var openWinFunc of OPEN_WINDOW_FUNCS) { + for (var actionFunc of ACTION_FUNCS) { + info(`Testing ${openWinFunc.name}, ${actionFunc.name}`); + yield { openWinFunc: openWinFunc, actionFunc: actionFunc }; + } + } +} + +function runTest(test) { + var win = test.openWinFunc(); + return new Promise(resolve => { + SimpleTest.waitForFocus(resolve, win, true); + }).then(() => { + return new Promise((resolve, reject) => { + var retried = false; + function listener(evt) { + if (!retried && evt.type == "fullscreenerror") { + todo(false, "Failed to enter fullscreen, but try again"); + retried = true; + SimpleTest.waitForFocus(() => { + win.document.documentElement.requestFullscreen(); + }, win, true); + return; + } + win.removeEventListener("fullscreenchange", listener); + win.removeEventListener("fullscreenerror", listener); + is(evt.type, "fullscreenchange", "Should get fullscreenchange"); + ok(win.document.fullscreenElement, "Should have entered fullscreen"); + ok(win.fullScreen, "The window should be in fullscreen"); + test.actionFunc(win).then(resolve); + } + if (win.fullScreen) { + todo(false, "Should not open in fullscreen mode"); + win.close(); + reject(); + return; + } + info("About to enter fullscreen"); + win.addEventListener("fullscreenchange", listener); + win.addEventListener("fullscreenerror", listener); + win.document.documentElement.requestFullscreen(); + }); + }).then(() => { + ok(win.closed, "The window should have been closed"); + }); +} + +var tests = testGenerator(); + +function next() { + var test = tests.next().value; + if (test) { + runTest(test).catch(() => { + return new Promise(resolve => { + SimpleTest.waitForFocus(resolve); + }).then(() => runTest(test)); + }).catch(() => { + ok(false, "Fail to run test " + + `${test.openWinFunc.name}, ${test.actionFunc.name}`); + }).then(() => { + setTimeout(() => SimpleTest.waitForFocus(next), 1000); + }); + } else { + SimpleTest.finish(); + return; + } +} + +</script> +</body> +</html> diff --git a/dom/html/test/test_fullscreen-api.html b/dom/html/test/test_fullscreen-api.html new file mode 100644 index 000000000..1ac5b3b51 --- /dev/null +++ b/dom/html/test/test_fullscreen-api.html @@ -0,0 +1,106 @@ + <!DOCTYPE HTML> +<html> +<head> + <title>Test for Bug 545812</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <style> + body { + background-color: black; + } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=545812">Mozilla Bug 545812</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Tests for Bug 545812 **/ +SimpleTest.requestFlakyTimeout("untriaged"); + +// Run the tests which go full-screen in new windows, as mochitests normally +// run in an iframe, which by default will not have the allowfullscreen +// attribute set, so full-screen won't work. +var gTestWindows = [ + "file_fullscreen-multiple.html", + "file_fullscreen-rollback.html", + "file_fullscreen-esc-exit.html", + "file_fullscreen-denied.html", + "file_fullscreen-api.html", + "file_fullscreen-plugins.html", + "file_fullscreen-hidden.html", + "file_fullscreen-svg-element.html", + "file_fullscreen-navigation.html", + "file_fullscreen-scrollbar.html", + "file_fullscreen-selector.html", + "file_fullscreen-top-layer.html", + "file_fullscreen-backdrop.html", + "file_fullscreen-nested.html", + "file_fullscreen-prefixed.html", + "file_fullscreen-unprefix-disabled.html", + "file_fullscreen-lenient-setters.html", +]; + +var testWindow = null; +var gTestIndex = 0; + +function finish() { + SimpleTest.finish(); +} + +function nextTest() { + if (testWindow) { + testWindow.close(); + } + SimpleTest.executeSoon(runNextTest); +} + +function runNextTest() { + if (gTestIndex < gTestWindows.length) { + info("Run test " + gTestWindows[gTestIndex]); + testWindow = window.open(gTestWindows[gTestIndex], "", "width=500,height=500,scrollbars=yes"); + // We'll wait for the window to load, then make sure our window is refocused + // before starting the test, which will get kicked off on "focus". + // This ensures that we're essentially back on the primary "desktop" on + // OS X Lion before we run the test. + testWindow.addEventListener("load", function onload() { + testWindow.removeEventListener("load", onload, false); + SimpleTest.waitForFocus(function() { + SimpleTest.waitForFocus(testWindow.begin, testWindow); + }); + }, false); + gTestIndex++; + } else { + SimpleTest.finish(); + } +} + +try { + window.fullScreen = true; +} catch (e) { +} +is(window.fullScreen, false, "Shouldn't be able to set window fullscreen from content"); +// Ensure the full-screen api is enabled, and will be disabled on test exit. +// Disable the requirement for trusted contexts only, so the tests are easier +// to write +addLoadEvent(function() { + SpecialPowers.pushPrefEnv({ + "set": [ + ["full-screen-api.enabled", true], + ["full-screen-api.unprefix.enabled", true], + ["full-screen-api.allow-trusted-requests-only", false], + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"] + ]}, nextTest); +}); +SimpleTest.waitForExplicitFinish(); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_hash_encoded.html b/dom/html/test/test_hash_encoded.html new file mode 100644 index 000000000..f814c8ae9 --- /dev/null +++ b/dom/html/test/test_hash_encoded.html @@ -0,0 +1,118 @@ +<!doctype html> +<html> +<head> +<title>Test link.hash attribute</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<pre id="test"> + +<script> + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set": [['dom.url.encode_decode_hash', false]]}, runTest); + +function runTest() { + setupTest(); + doTestEncoded(); + SimpleTest.finish(); +} + +function setupTest() { + var target1 = document.createElement("a"); + target1.id = "target1"; + target1.href = "http://www.example.com/#q=♥â¥#hello"; + document.body.appendChild(target1); + + var target2 = document.createElement("a"); + target2.id = "target2"; + target2.href = "http://www.example.com/#q=%E2%99%A5%C3%A2%C2%A5"; + document.body.appendChild(target2); + + var target3 = document.createElement("a"); + target3.id = "target3"; + target3.href = "http://www.example.com/#/search/%23important"; + document.body.appendChild(target3); + + var target4 = document.createElement("a"); + target4.id = "target4"; + target4.href = 'http://www.example.com/#{"a":[13, 42], "b":{"key":"value"}}'; + document.body.appendChild(target4); +} + +function doTestEncoded() { + // Tests Link::GetHash + + // Check that characters aren't being encoded + var target = document.getElementById("target1"); + is(target.hash, '#q=♥â¥#hello', 'Unexpected link hash'); + + // Check that encoded characters aren't being decoded + target = document.getElementById("target2"); + is(target.hash, '#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected link hash'); + + // A more regular use case + target = document.getElementById("target3"); + is(target.hash, '#/search/%23important', 'Unexpected link hash'); + + // Some JSON + target = document.getElementById("target4"); + is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected link hash'); + + // Tests URL::GetHash + + var url = new URL("http://www.example.com/#q=♥â¥#hello") + is(url.hash, '#q=♥â¥#hello', 'Unexpected url hash'); + + url = new URL("http://www.example.com/#q=%E2%99%A5%C3%A2%C2%A5") + is(url.hash, '#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected url hash'); + + url = new URL("http://www.example.com/#/search/%23important") + is(url.hash, '#/search/%23important', 'Unexpected url hash'); + + // Test getters and setters + + url = new URL("http://www.example.com/"); + url.hash = "#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important" + is(url.hash, '#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important', 'Unexpected url hash'); + + // codepath in nsStandardUrl::SetRef is different if the path is non-empty + url = new URL("http://www.example.com/test/"); + url.hash = "#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important" + is(url.hash, '#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important', 'Unexpected url hash'); + + url = new URL("http://www.example.com/"); + url.hash = '#{"a":[13, 42], "b":{"key":"value"}}'; + is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected url hash'); + var parsed = JSON.parse(target.hash.substring(1)); + is(parsed.b.key, 'value', 'JSON not parsed correctly'); + + url = new URL("http://www.example.com/test/"); + url.hash = '#{"a":[13, 42], "b":{"key":"value"}}'; + is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected url hash'); + parsed = JSON.parse(target.hash.substring(1)); + is(parsed.b.key, 'value', 'JSON not parsed correctly'); + + // Tests Location::GetHash + + window.history.pushState(1, document.title, '#q=♥â¥#hello'); + is(location.hash,'#q=♥â¥#hello', 'Unexpected location hash'); + + window.history.pushState(1, document.title, '#q=%E2%99%A5%C3%A2%C2%A5'); + is(location.hash,'#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected location hash'); + + window.history.pushState(1, document.title, '#/search/%23important'); + is(location.hash,'#/search/%23important', 'Unexpected location hash'); + + window.history.pushState(1, document.title, '#{"a":[13, 42], "b":{"key":"value"}}'); + is(location.hash,'#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected location hash'); + +} + +</script> + +</pre> +</body> +</html> diff --git a/dom/html/test/test_hidden.html b/dom/html/test/test_hidden.html new file mode 100644 index 000000000..7b9d488c0 --- /dev/null +++ b/dom/html/test/test_hidden.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=567663 +--> +<head> + <title>Test for Bug 567663</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567663">Mozilla Bug 567663</a> +<p id="display"></p> +<div id="content" style="display: none"> + <p></p> + <p hidden></p> +</div> +<pre id="test"> +<script> +/** Test for Bug 567663 **/ +var ps = document.getElementById("content").getElementsByTagName("p"); +is(ps[0].hidden, false, "First p's IDL attribute was wrong."); +is(ps[0].hasAttribute("hidden"), false, "First p had a content attribute."); +is(ps[1].hidden, true, "Second p's IDL attribute was wrong."); +is(ps[1].hasAttribute("hidden"), true, + "Second p didn't have a content attribute."); +is(ps[1].getAttribute("hidden"), "", + "Second p's content attribute was wrong."); + +ps[0].hidden = true; +is(ps[0].getAttribute("hidden"), "", + "Content attribute was set to an incorrect value."); +ps[1].hidden = false; +is(ps[1].hasAttribute("hidden"), false, + "Second p still had a content attribute."); + +ps[0].setAttribute("hidden", "banana"); +is(ps[0].hidden, true, "p's IDL attribute was wrong after setting."); +is(ps[0].getAttribute("hidden"), "banana", "Content attribute changed."); + +ps[0].setAttribute("hidden", "false"); +is(ps[0].hidden, true, "p's IDL attribute was wrong after setting."); +is(ps[0].getAttribute("hidden"), "false", "Content attribute changed."); + +ps[0].removeAttribute("hidden"); +is(ps[0].hidden, false, + "p's IDL attribute was wrong after removing the content attribute."); +is(ps[0].hasAttribute("hidden"), false); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_html_attributes_reflection.html b/dom/html/test/test_html_attributes_reflection.html new file mode 100644 index 000000000..372c2503a --- /dev/null +++ b/dom/html/test/test_html_attributes_reflection.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLHtmlElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLHtmlElement attributes reflection **/ + +// .version +reflectString({ + element: document.createElement("html"), + attribute: "version", +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_htmlcollection.html b/dom/html/test/test_htmlcollection.html new file mode 100644 index 000000000..1452f0c3c --- /dev/null +++ b/dom/html/test/test_htmlcollection.html @@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=772869 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 772869</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a> +<p id="display"></p> +<div id="content" style="display: none"> + <a class="foo" name="x"></a> + <span class="foo" id="y"></span> + <span class="foo" name="x"></span> + <form class="foo" name="z" id="w"></form> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 772869 **/ +var x = document.getElementsByClassName("foo"); +x.something = "another"; +var names = []; +for (var name in x) { + names.push(name); +} +is(names.length, 8, "Should have 8 enumerated names"); +is(names[0], "0", "Enum entry 1") +is(names[1], "1", "Enum entry 2") +is(names[2], "2", "Enum entry 3") +is(names[3], "3", "Enum entry 4") +is(names[4], "something", "Enum entry 5") +is(names[5], "item", "Enum entry 6") +is(names[6], "namedItem", "Enum entry 7") +is(names[7], "length", "Enum entry 8"); + +names = Object.getOwnPropertyNames(x); +is(names.length, 9, "Should have 9 items"); +is(names[0], "0", "Entry 1") +is(names[1], "1", "Entry 2") +is(names[2], "2", "Entry 3") +is(names[3], "3", "Entry 4") +is(names[4], "x", "Entry 5") +is(names[5], "y", "Entry 6") +is(names[6], "w", "Entry 7") +is(names[7], "z", "Entry 8") +is(names[8], "something", "Entry 9") +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_general.html b/dom/html/test/test_iframe_sandbox_general.html new file mode 100644 index 000000000..6d3a190ee --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_general.html @@ -0,0 +1,283 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=341604 +Implement HTML5 sandbox attribute for IFRAMEs - general tests +--> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 341604 and Bug 766282</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> +/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs - general tests **/ + +SimpleTest.expectAssertions(0, 1); +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestCompleteLog(); + +// a postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin' to communicate pass/fail back to this main page. +// it expects to be called with an object like {ok: true/false, desc: +// <description of the test> which it then forwards to ok() +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) +{ + ok_wrapper(event.data.ok, event.data.desc); +} + +var completedTests = 0; +var passedTests = 0; + +function ok_wrapper(result, desc) { + ok(result, desc); + + completedTests++; + + if (result) { + passedTests++; + } + + if (completedTests == 33) { + is(passedTests, completedTests, "There are " + completedTests + " general tests that should pass"); + SimpleTest.finish(); + } +} + +function doTest() { + // passes twice if good + // 1) test that inline scripts (<script>) can run in an iframe sandboxed with "allow-scripts" + // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts') + + // passes twice if good + // 2) test that <script src=...> can run in an iframe sandboxed with "allow-scripts" + // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts') + + // passes twice if good + // 3) test that script in an event listener (body onload) can run in an iframe sandboxed with "allow-scripts" + // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts') + + // passes twice if good + // 4) test that script in an javascript:url can run in an iframe sandboxed with "allow-scripts" + // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts') + + // fails if bad + // 5) test that inline scripts cannot run in an iframe sandboxed without "allow-scripts" + // (done in file_iframe_sandbox_c_if2.html which has sandbox='') + + // fails if bad + // 6) test that <script src=...> cannot run in an iframe sandboxed without "allow-scripts" + // (done in file_iframe_sandbox_c_if2.html which has sandbox='') + + // fails if bad + // 7) test that script in an event listener (body onload) cannot run in an iframe sandboxed without "allow-scripts" + // (done in file_iframe_sandbox_c_if2.html which has sandbox='') + + // fails if bad + // 8) test that script in an event listener (img onerror) cannot run in an iframe sandboxed without "allow-scripts" + // (done in file_iframe_sandbox_c_if2.html which has sandbox='') + + // fails if bad + // 9) test that script in an javascript:url cannot run in an iframe sandboxed without "allow-scripts" + // (done in file_iframe_sandbox_c_if_5.html which has sandbox='allow-same-origin') + var if_w = document.getElementById('if_5').contentWindow; + sendMouseEvent({type:'click'}, 'a_link', if_w); + + // passes if good + // 10) test that a new iframe has sandbox attribute + var ifr = document.createElement("iframe"); + ok_wrapper("sandbox" in ifr, "a new iframe should have a sandbox attribute"); + + // passes if good + // 11) test that the sandbox attribute's default stringyfied value is an empty string + ok_wrapper(ifr.sandbox.length === 0 && ifr.sandbox == "", "default sandbox attribute should be an empty string"); + + // passes if good + // 12) test that a sandboxed iframe with 'allow-forms' can submit forms + // (done in file_iframe_sandbox_c_if3.html which has 'allow-forms' and 'allow-scripts') + + // fails if bad + // 13) test that a sandboxed iframe without 'allow-forms' can NOT submit forms + // (done in file_iframe_sandbox_c_if1.html which only has 'allow-scripts') + + // fails if bad + // 14) test that a sandboxed iframe can't open a new window using the target.attribute + // this is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin" + // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok() + // function that calls window.parent.ok_wrapper + + // passes if good + // 15) test that a sandboxed iframe can't open a new window using window.open + // this is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin" + // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok() + // function that calls window.parent.ok_wrapper + + // passes if good + // 16) test that a sandboxed iframe can't open a new window using window.ShowModalDialog + // this is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin" + // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok() + // function that calls window.parent.ok_wrapper + + // passes twice if good + // 17) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute + // is separated with two spaces + // done via file_iframe_sandbox_c_if6.html which is sandboxed with " allow-scripts allow-same-origin " + + // passes twice if good + // 18) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute + // is separated with tabs + // done via file_iframe_sandbox_c_if6.html which is sandboxed with "	allow-scripts	allow-same-origin	" + + // passes twice if good + // 19) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute + // is separated with line feeds + // done via file_iframe_sandbox_c_if6.html which is sandboxed with "
allow-scripts
allow-same-origin
" + + // passes twice if good + // 20) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute + // is separated with form feeds + // done via file_iframe_sandbox_c_if6.html which is sandboxed with "allow-scriptsallow-same-origin" + + // passes twice if good + // 21) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute + // is separated with carriage returns + // done via file_iframe_sandbox_c_if6.html which is sandboxed with "
allow-scripts
allow-same-origin
" + + // fails if bad + // 22) test that an iframe with sandbox="" does NOT have script in a src attribute created by a javascript: + // URL executed + // done by this page, see if_7 + + // passes if good + // 23) test that an iframe with sandbox="allow-scripts" DOES have script in a src attribute created by a javascript: + // URL executed + // done by this page, see if_8 + + // fails if bad + // 24) test that an iframe with sandbox="", starting out with a document already loaded, does NOT have script in a newly + // set src attribute created by a javascript: URL executed + // done by this page, see if_9 + + // passes if good + // 25) test that an iframe with sandbox="allow-scripts", starting out with a document already loaded, DOES have script + // in a newly set src attribute created by a javascript: URL executed + // done by this page, see if_10 + + // passes if good or fails if bad + // 26) test that an sandboxed document without 'allow-same-origin' can NOT access indexedDB + // done via file_iframe_sandbox_c_if7.html, which has sandbox='allow-scripts' + + // passes if good or fails if bad + // 27) test that an sandboxed document with 'allow-same-origin' can access indexedDB + // done via file_iframe_sandbox_c_if8.html, which has sandbox='allow-scripts allow-same-origin' + + // fails if bad + // 28) Test that a sandboxed iframe can't open a new window using the target.attribute for a + // non-existing browsing context (BC341604). + // This is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin" + // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok() + // function that calls window.parent.ok_wrapper. + + // passes twice if good + // 29-32) Test that sandboxFlagsAsString returns the set flags. + // see if_14 and if_15 + + // passes once if good + // 33) Test that sandboxFlagsAsString returns null if iframe does not have sandbox flag set. + // see if_16 +} + +addLoadEvent(doTest); + +var started_if_9 = false; +var started_if_10 = false; + +function start_if_9() { + if (started_if_9) + return; + + started_if_9 = true; + sendMouseEvent({type:'click'}, 'a_button'); +} + +function start_if_10() { + if (started_if_10) + return; + + started_if_10 = true; + sendMouseEvent({type:'click'}, 'a_button2'); +} + +function do_if_9() { + var if_9 = document.getElementById('if_9'); + if_9.src = 'javascript:"<html><script>window.parent.ok_wrapper(false, \'an iframe sandboxed without allow-scripts should not execute script in a javascript URL in a newly set src attribute\');<\/script><\/html>"'; +} + +function do_if_10() { + var if_10 = document.getElementById('if_10'); + if_10.src = 'javascript:"<html><script>window.parent.ok_wrapper(true, \'an iframe sandboxed with allow-scripts should execute script in a javascript URL in a newly set src attribute\');<\/script><\/html>"'; +} + +function eqFlags(a, b) { + // both a and b should be either null or have the array same flags + if (a === null && b === null) { return true; } + if (a === null || b === null) { return false; } + if (a.length !== b.length) { return false; } + var a_sorted = a.sort(); + var b_sorted = b.sort(); + for (var i in a_sorted) { + if (a_sorted[i] !== b_sorted[i]) { return false; } + } + return true; +} + +function getSandboxFlags(doc) { + var flags = doc.sandboxFlagsAsString; + if (flags === null) { return null; } + return flags? flags.split(" "):[]; +} + +function test_sandboxFlagsAsString(name, expected) { + var ifr = document.getElementById(name); + try { + var flags = getSandboxFlags(SpecialPowers.wrap(ifr).contentDocument); + ok_wrapper(eqFlags(flags, expected), name + ' expected: "' + expected + '", got: "' + flags + '"'); + } catch (e) { + ok_wrapper(false, name + ' expected "' + expected + ', but failed with ' + e); + } +} + +</script> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs +<p id="display"></p> +<div id="content"> +<iframe sandbox="allow-same-origin allow-scripts" id="if_1" src="file_iframe_sandbox_c_if1.html" height="10" width="10"></iframe> +<iframe sandbox="aLlOw-SAME-oRiGin ALLOW-sCrIpTs" id="if_1_case_insensitive" src="file_iframe_sandbox_c_if1.html" height="10" width="10"></iframe> +<iframe sandbox="" id="if_2" src="file_iframe_sandbox_c_if2.html" height="10" width="10"></iframe> +<iframe sandbox="allow-forms allow-scripts" id="if_3" src="file_iframe_sandbox_c_if3.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin allow-scripts" id="if_4" src="file_iframe_sandbox_c_if4.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin" id="if_5" src="file_iframe_sandbox_c_if5.html" height="10" width="10"></iframe> +<iframe sandbox=" allow-same-origin allow-scripts " id="if_6_a" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe> +<iframe sandbox="	allow-same-origin	allow-scripts	" id="if_6_b" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe> +<iframe sandbox="
allow-same-origin
allow-scripts
" id="if_6_c" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-originallow-scripts" id="if_6_d" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe> +<iframe sandbox="
allow-same-origin
allow-scripts
" id="if_6_e" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin" id='if_7' src="javascript:'<html><script>window.parent.ok_wrapper(false, \'an iframe sandboxed without allow-scripts should not execute script in a javascript URL in its src attribute\');<\/script><\/html>';" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin allow-scripts" id='if_8' src="javascript:'<html><script>window.parent.ok_wrapper(true, \'an iframe sandboxed without allow-scripts should execute script in a javascript URL in its src attribute\');<\/script><\/html>';" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin" onload='start_if_9()' id='if_9' src="about:blank" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin allow-scripts" onload='start_if_10()' id='if_10' src="about:blank" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id='if_11' src="file_iframe_sandbox_c_if7.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin allow-scripts" id='if_12' src="file_iframe_sandbox_c_if8.html" height="10" width="10"></iframe> +<iframe sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation " id='if_13' src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_13",["allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", "allow-top-navigation"])'></iframe> +<iframe sandbox="	allow-same-origin	allow-scripts	" id="if_14" src="file_iframe_sandbox_c_if6.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_14",["allow-same-origin","allow-scripts"])'></iframe> +<iframe sandbox="" id="if_15" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_15",[])'></iframe> +<iframe id="if_16" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_16",null)'></iframe> +<input type='button' id="a_button" onclick='do_if_9()'> +<input type='button' id="a_button2" onclick='do_if_10()'> +</div> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_inheritance.html b/dom/html/test/test_iframe_sandbox_inheritance.html new file mode 100644 index 000000000..ddf45f70b --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_inheritance.html @@ -0,0 +1,203 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=341604 +Implement HTML5 sandbox attribute for IFRAMEs - inheritance tests +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> +/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/ +/** Inheritance Tests **/ + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); + +// A postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin' to communicate pass/fail back to this main page. +// It expects to be called with an object like {ok: true/false, desc: +// <description of the test> which it then forwards to ok(). +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) { + switch (event.data.type) { + case "attempted": + testAttempted(); + break; + case "ok": + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + break; + default: + // allow for old style message + if (event.data.ok != undefined) { + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + } + } +} + +var attemptedTests = 0; +var passedTests = 0; +var totalTestsToPass = 15; +var totalTestsToAttempt = 19; + +function ok_wrapper(result, desc, addToAttempted = true) { + ok(result, desc); + + if (result) { + passedTests++; + } + + if (addToAttempted) { + testAttempted(); + } +} + +// Added so that tests that don't register unless they fail, +// can at least notify that they've attempted to run. +function testAttempted() { + attemptedTests++; + if (attemptedTests == totalTestsToAttempt) { + // Make sure all tests have had a chance to complete. + setTimeout(function() {finish();}, 1000); + } +} + +var finishCalled = false; + +function finish() { + if (!finishCalled) { + finishCalled = true; + is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " inheritance tests that should pass"); + + SimpleTest.finish(); + } +} + +function doTest() { + // fails if bad + // 1) an iframe with no sandbox attribute inside an iframe that has sandbox = "" + // should not be able to execute scripts (cannot ever loosen permissions) + // (done by file_iframe_sandbox_a_if2.html contained within file_iframe_sandbox_a_if1.html) + testAttempted(); + + // fails if bad + // 2) an iframe with sandbox = "allow-scripts" inside an iframe that has sandbox = "" + // should not be able to execute scripts (cannot ever loosen permissions) + // (done by file_iframe_sandbox_a_if2.html contained within file_iframe_sandbox_a_if1.html) + testAttempted(); + + // passes if good and fails if bad + // 3) an iframe with no sandbox attribute inside an iframe that has sandbox = "allow-scripts" + // should not be same origin with the top window + // (done by file_iframe_sandbox_a_if4.html contained within file_iframe_sandbox_a_if3.html) + + // passes if good and fails if bad + // 4) an iframe with no sandbox attribute inside an iframe that has sandbox = "allow-scripts" + // should not be same origin with its parent + // (done by file_iframe_sandbox_a_if4.html contained within file_iframe_sandbox_a_if3.html) + + // passes if good + // 5) an iframe with 'allow-same-origin' and 'allow-scripts' inside an iframe with 'allow-same-origin' + // and 'allow-scripts' should be same origin with the top window + // (done by file_iframe_sandbox_a_if6.html contained within file_iframe_sandbox_a_if5.html) + + // passes if good + // 6) an iframe with 'allow-same-origin' and 'allow-scripts' inside an iframe with 'allow-same-origin' + // and 'allow-scripts' should be same origin with its parent + // (done by file_iframe_sandbox_a_if6.html contained within file_iframe_sandbox_a_if5.html) + + // passes if good + // 7) an iframe with no sandbox attribute inside an iframe that has sandbox = "allow-scripts" + // should be able to execute scripts + // (done by file_iframe_sandbox_a_if7.html contained within file_iframe_sandbox_a_if3.html) + + // fails if bad + // 8) an iframe with sandbox="" inside an iframe that has allow-scripts should not be able + // to execute scripts + // (done by file_iframe_sandbox_a_if2.html contained within file_iframe_sandbox_a_if3.html) + testAttempted(); + + // passes if good + // 9) make sure that changing the sandbox flags on an iframe (if_8) doesn't affect + // the sandboxing of subloads of content within that iframe + var if_8 = document.getElementById('if_8'); + if_8.sandbox = 'allow-scripts'; + if_8.contentWindow.doSubload(); + + // passes if good + // 10) a <frame> inside an <iframe> sandboxed with 'allow-scripts' should not be same + // origin with this document + // done by file_iframe_sandbox_a_if11.html which is contained with file_iframe_sandbox_a_if10.html + + // passes if good + // 11) a <frame> inside a <frame> inside an <iframe> sandboxed with 'allow-scripts' should not be same + // origin with its parent frame or this document + // done by file_iframe_sandbox_a_if12.html which is contained with file_iframe_sandbox_a_if11.html + + // passes if good, fails if bad + // 12) An <object> inside an <iframe> sandboxed with 'allow-scripts' should not be same + // origin with this document + // Done by file_iframe_sandbox_a_if14.html which is contained within file_iframe_sandbox_a_if13.html + + // passes if good, fails if bad + // 13) An <object> inside an <object> inside an <iframe> sandboxed with 'allow-scripts' should not be same + // origin with its parent frame or this document + // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if14.html + + // passes if good, fails if bad + // 14) An <object> inside a <frame> inside an <iframe> sandboxed with 'allow-scripts' should not be same + // origin with its parent frame or this document + // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if16.html + // which is contained within file_iframe_sandbox_a_if10.html + + // passes if good + // 15) An <object> inside an <object> inside an <iframe> sandboxed with 'allow-scripts allow-forms' + // should be able to submit forms. + // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if14.html + + // passes if good + // 16) An <object> inside a <frame> inside an <iframe> sandboxed with 'allow-scripts allow-forms' + // should be able to submit forms. + // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if16.html + // which is contained within file_iframe_sandbox_a_if10.html + + // fails if bad + // 17) An <object> inside an <iframe> sandboxed with 'allow-same-origin' + // should not be able to run scripts. + // Done by iframe "if_no_scripts" using a data: load. + testAttempted(); + + // passes if good + // 18) An <object> inside an <iframe> sandboxed with 'allow-scripts allow-same-origin' + // should be able to run scripts and be same origin with this document. + // Done by iframe "if_scripts" using a data: load. + + // passes if good, fails if bad + // 19) Make sure that the parent's document's sandboxing flags are copied when + // changing the sandbox flags on an iframe inside an iframe. + // Done in file_iframe_sandbox_a_if17.html and file_iframe_sandbox_a_if18.html +} + +addLoadEvent(doTest); +</script> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs +<p id="display"></p> +<div id="content"> +<iframe sandbox="" id="if_1" src="file_iframe_sandbox_a_if1.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_3" src="file_iframe_sandbox_a_if3.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-same-origin" id="if_5" src="file_iframe_sandbox_a_if5.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-same-origin" id="if_8" src="file_iframe_sandbox_a_if8.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-forms" id="if_10" src="file_iframe_sandbox_a_if10.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-forms" id="if_13" src="file_iframe_sandbox_a_if13.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin" id="if_no_scripts" src="data:text/html,<object%20data='data:text/html,<script>parent.parent.ok_wrapper(false, "an object inside an iframe sandboxed with only allow-same-origin should not be able to run scripts")</script>'></object>" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-same-origin" id="if_scripts" src="data:text/html,<object%20data='data:text/html,<script>parent.parent.ok_wrapper(true, "an object inside an iframe sandboxed with allow-scripts allow-same-origin should be able to run scripts and call functions in the parent of the iframe")</script>'></object>" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin" id="if_19" src="data:text/html,<iframe%20data='data:text/html,<script>parent.parent.ok_wrapper(true, "an object inside an iframe sandboxed with allow-scripts allow-same-origin should be able to run scripts and call functions in the parent of the iframe")</script>'></object>" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_17" src="file_iframe_sandbox_a_if17.html" height="10" width="10"></iframe> +</div> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_modal.html b/dom/html/test/test_iframe_sandbox_modal.html new file mode 100644 index 000000000..1307ea9a5 --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_modal.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=766282 +implement allow-popups directive for iframe sandbox +--> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 766282</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script> + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); + +// A postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin' to communicate pass/fail back to this main page. +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) { + switch (event.data.type) { + case "attempted": + testAttempted(); + break; + case "ok": + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + break; + default: + // allow for old style message + if (event.data.ok != undefined) { + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + } + } +} + +var attemptedTests = 0; +var passedTests = 0; +var totalTestsToPass = 5; +var totalTestsToAttempt = 5; + +function ok_wrapper(result, desc, addToAttempted = true) { + ok(result, desc); + + if (result) { + passedTests++; + } + + if (addToAttempted) { + testAttempted(); + } +} + +// Added so that tests that don't register unless they fail, +// can at least notify that they've attempted to run. +function testAttempted() { + attemptedTests++; + if (attemptedTests == totalTestsToAttempt) { + // Make sure all tests have had a chance to complete. + setTimeout(function() {finish();}, 1000); + } +} + +var finishCalled = false; + +function finish() { + if (!finishCalled) { + finishCalled = true; + is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " modal tests that should pass"); + + SimpleTest.finish(); + } +} + +function doTest() { + // passes if good and fails if bad + // 1) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups + // allow-same-origin" should not have its origin sandbox flag set and be able to access + // document.cookie. (Done by file_iframe_sandbox_k_if5.html opened from + // file_iframe_sandbox_j_if1.html) using showModalDialog.) + + // passes if good + // 2) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups + // allow-top-navigation" should not have its top-level navigation sandbox flag set and be able to + // navigate top. (Done by file_iframe_sandbox_k_if5.html (and if6) opened from + // file_iframe_sandbox_j_if1.html) using showModalDialog.) + + // passes if good + // 3) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups + // all-forms" should not have its forms sandbox flag set and be able to submit forms. + // (Done by file_iframe_sandbox_k_if7.html opened from + // file_iframe_sandbox_j_if1.html) using showModalDialog.) + + // passes if good + // 4) Make sure that the sandbox flags copied to a new browsing context are taken from the + // current active document not the browsing context (iframe / docShell). + // This is done by removing allow-same-origin and calling doSubOpens from file_iframe_sandbox_j_if2.html, + // which opens file_iframe_sandbox_k_if9.html using showModalDialog. + var if_2 = document.getElementById('if_2'); + if_2.sandbox = 'allow-scripts allow-popups'; + if_2.contentWindow.doSubOpens(); + + // passes if good + // 5) Test that a sandboxed iframe with "allow-popups" can open a new window using window.ShowModalDialog. + // This is done via file_iframe_sandbox_j_if3.html which is sandboxed with "allow-popups allow-scripts + // allow-same-origin". The window it attempts to open calls window.opener.ok(true, ...) and + // file_iframe_j_if3.html has an ok() function that calls window.parent.ok_wrapper. +} + +addLoadEvent(doTest); +</script> + +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=766282">Mozilla Bug 766282</a> - implement allow-popups directive for iframe sandbox +<p id="display"></p> +<div id="content"> +<iframe sandbox="allow-scripts allow-popups allow-modals allow-same-origin allow-forms allow-top-navigation" id="if_1" src="file_iframe_sandbox_j_if1.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-popups allow-modals allow-same-origin" id="if_2" src="file_iframe_sandbox_j_if2.html" height="10" width="10"></iframe> +<iframe sandbox="allow-popups allow-modals allow-same-origin allow-scripts" id="if_3" src="file_iframe_sandbox_j_if3.html" height="10" width="10"></iframe> +</div> diff --git a/dom/html/test/test_iframe_sandbox_navigation.html b/dom/html/test/test_iframe_sandbox_navigation.html new file mode 100644 index 000000000..b60f715f3 --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_navigation.html @@ -0,0 +1,281 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=341604 +Implement HTML5 sandbox attribute for IFRAMEs +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604 - navigation</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> +/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/ +/** Navigation tests Part 1**/ + +SimpleTest.requestLongerTimeout(2); // slow on Android +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +// a postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin'/other windows to communicate pass/fail back to this main page. +// it expects to be called with an object like {ok: true/false, desc: +// <description of the test> which it then forwards to ok() +window.addEventListener("message", receiveMessage, false); + +var testPassesReceived = 0; + +function receiveMessage(event) { + switch (event.data.type) { + case "attempted": + testAttempted(); + break; + case "ok": + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + break; + case "if_10": + doIf10TestPart2(); + break; + default: + // allow for old style message + if (event.data.ok != undefined) { + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + } + } +} + +// Open windows for tests to attempt to navigate later. +var windowsToClose = new Array(); + +var attemptedTests = 0; +var passedTests = 0; +var totalTestsToPass = 7; +var totalTestsToAttempt = 13; + +function ok_wrapper(result, desc, addToAttempted = true) { + ok(result, desc); + + if (result) { + passedTests++; + } + + if (addToAttempted) { + testAttempted(); + } +} + +// Added so that tests that don't register unless they fail, +// can at least notify that they've attempted to run. +function testAttempted() { + attemptedTests++; + if (attemptedTests == totalTestsToAttempt) { + // Make sure all tests have had a chance to complete. + setTimeout(function() {finish();}, 1000); + } +} + +var finishCalled = false; + +function finish() { + if (!finishCalled) { + finishCalled = true; + is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " navigation tests that should pass"); + + closeWindows(); + + SimpleTest.finish(); + } +} + +function checkTestsFinished() { + // If our own finish() has not been called, probably failed due to a timeout, so close remaining windows. + if (!finishCalled) { + closeWindows(); + } +} + +function closeWindows() { + for (var i = 0; i < windowsToClose.length; i++) { + windowsToClose[i].close(); + } +} + +function doTest() { + // passes if good + // 1) A sandboxed iframe is allowed to navigate itself + // (done by file_iframe_sandbox_d_if1.html which has 'allow-scripts' and navigates to + // file_iframe_sandbox_navigation_pass.html). + + // passes if good + // 2) A sandboxed iframe is allowed to navigate its children, even if they are sandboxed + // (done by file_iframe_sandbox_d_if2.html which has 'allow-scripts', it navigates a child + // iframe containing file_iframe_sandbox_navigation_start.html to file_iframe_sandbox_navigation_pass.html). + + // fails if bad + // 3) A sandboxed iframe is not allowed to navigate its ancestor + // (done by file_iframe_sandbox_d_if4.html contained within file_iframe_sandbox_d_if3.html, + // it attempts to navigate file_iframe_sandbox_d_if3.html to file_iframe_sandbox_navigation_fail.html). + + // fails if bad + // 4) A sandboxed iframe is not allowed to navigate its sibling + // (done by file_iframe_sandbox_d_if5.html which has 'allow scripts allow-same-origin' + // and attempts to navigate file_iframe_navigation_start.html contained in if_sibling on this + // page to file_iframe_sandbox_navigation_fail.html). + + // passes if good, fails if bad + // 5) When a link is clicked in a sandboxed iframe, the document navigated to is sandboxed + // the same as the original document and is not same origin with parent document + // (done by file_iframe_sandbox_d_if6.html which simulates a link click and navigates + // to file_iframe_sandbox_d_if7.html which attempts to call back into its parent). + + // fails if bad + // 6) An iframe (if_8) has sandbox="allow-same-origin allow-scripts", the sandboxed document + // (file_iframe_sandbox_d_if_8.html) that it contains accesses its parent (this file) and removes + // 'allow-same-origin' and then triggers a reload. + // The document should not be able to access its parent (this file). + + // fails if bad + // 7) An iframe (if_9) has sandbox="allow-same-origin allow-scripts", the sandboxed document + // (file_iframe_sandbox_d_if_9.html) that it contains accesses its parent (this file) and removes + // 'allow-scripts' and then triggers a reload. + // The document should not be able to run a script and access its parent (this file). + + // passes if good + // 8) a document in an iframe with sandbox='allow-scripts' should have a different null + // principal in its original document than a document to which it navigates itself + // file_iframe_sandbox_d_if_10.html does this, co-ordinating with this page via postMessage + + // passes if good + // 9) a document (file_iframe_sandbox_d_if11.html in an iframe (if_11) with sandbox='allow-scripts' + // is navigated to file_iframe_sandbox_d_if12.html - when that document loads + // a message is sent back to this document, which adds 'allow-same-origin' to if_11 and then + // calls .back on it - file_iframe_sandbox_if12.html should be able to call back into this + // document - this is all contained in file_iframe_sandbox_d_if13.html which is opened in another + // tab so it has its own isolated session history + window.open("file_iframe_sandbox_d_if13.html"); + + // open up the top navigation tests + + // fails if bad + // 10) iframe with sandbox='allow-scripts' can NOT navigate top + // file_iframe_sandbox_e_if1.html contains file_iframe_sandbox_e_if6.html which + // attempts to navigate top + windowsToClose.push(window.open("file_iframe_sandbox_e_if1.html")); + + // fails if bad + // 11) iframe with sandbox='allow-scripts' nested inside iframe with + // 'allow-top-navigation allow-scripts' can NOT navigate top + // file_iframe_sandbox_e_if2.html contains file_iframe_sandbox_e_if1.html which + // contains file_iframe_sandbox_e_if6.html which attempts to navigate top + windowsToClose.push(window.open("file_iframe_sandbox_e_if2.html")); + + // passes if good + // 12) iframe with sandbox='allow-top-navigation allow-scripts' can navigate top + // file_iframe_sandbox_e_if3.html contains file_iframe_sandbox_e_if5.html which navigates top + window.open("file_iframe_sandbox_e_if3.html"); + + // passes if good + // 13) iframe with sandbox='allow-top-navigation allow-scripts' nested inside an iframe with + // 'allow-top-navigation allow-scripts' can navigate top + // file_iframe_sandbox_e_if4.html contains file_iframe_sandbox_e_if3.html which contains + // file_iframe_sandbox_e_if5.html which navigates top + window.open("file_iframe_sandbox_e_if4.html"); +} + +addLoadEvent(doTest); + +window.modified_if_8 = false; + +function reload_if_8() { + var if_8 = document.getElementById('if_8'); + if_8.src = 'file_iframe_sandbox_d_if8.html'; +} + +function modify_if_8() { + // If this is the second time this has been called + // that's a failed test (allow-same-origin was removed + // the first time). + if (window.modified_if_8) { + ok_wrapper(false, "a sandboxed iframe from which 'allow-same-origin' was removed should not be able to access its parent"); + + // need to return here since we end up in an infinite loop otherwise + return; + } + + var if_8 = document.getElementById('if_8'); + window.modified_if_8 = true; + + if_8.sandbox = 'allow-scripts'; + testAttempted(); + sendMouseEvent({type:'click'}, 'a_button'); +} + +window.modified_if_9 = false; + +function reload_if_9() { + var if_9 = document.getElementById('if_9'); + if_9.src = 'file_iframe_sandbox_d_if9.html'; +} + +function modify_if_9() { + // If this is the second time this has been called + // that's a failed test (allow-scripts was removed + // the first time). + if (window.modified_if_9) { + ok_wrapper(false, "an sandboxed iframe from which 'allow-scripts' should be removed should not be able to access its parent via a script", false); + + // need to return here since we end up in an infinite loop otherwise + return; + } + + var if_9 = document.getElementById('if_9'); + window.modified_if_9 = true; + + if_9.sandbox = 'allow-same-origin'; + + testAttempted(); + sendMouseEvent({type:'click'}, 'a_button2'); +} + +var firstPrincipal = ""; +var secondPrincipal; + +function doIf10TestPart1() { + if (firstPrincipal != "") + return; + + // use SpecialPowers to get the principal of if_10. + // NB: We stringify here and below because special-powers wrapping doesn't + // preserve identity. + var if_10 = document.getElementById('if_10'); + firstPrincipal = SpecialPowers.wrap(if_10).contentDocument.nodePrincipal.origin; + if_10.src = 'file_iframe_sandbox_d_if10.html'; +} + +function doIf10TestPart2() { + var if_10 = document.getElementById('if_10'); + // use SpecialPowers to get the principal of if_10 + secondPrincipal = SpecialPowers.wrap(if_10).contentDocument.nodePrincipal.origin; + ok_wrapper(firstPrincipal != secondPrincipal, "documents should NOT have the same principal if they are sandboxed without" + + " allow-same-origin and the first document is navigated to the second"); +} +</script> +<body onunload="checkTestsFinished()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs +<p id="display"></p> +<div id="content"> +<iframe sandbox="allow-scripts" id="if_1" src="file_iframe_sandbox_d_if1.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_2" src="file_iframe_sandbox_d_if2.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_3" src="file_iframe_sandbox_d_if3.html" height="10" width="10"></iframe> +<iframe id="if_sibling" name="if_sibling" src="about:blank" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-same-origin" id="if_5" src="file_iframe_sandbox_d_if5.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_6" src="file_iframe_sandbox_d_if6.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin allow-scripts" id="if_8" src="file_iframe_sandbox_d_if8.html" height="10" width="10"></iframe> +<iframe sandbox="allow-same-origin allow-scripts" id="if_9" src="file_iframe_sandbox_d_if9.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_10" src="file_iframe_sandbox_navigation_start.html" onload='doIf10TestPart1()' height="10" width="10"></iframe> +</div> +<input type='button' id="a_button" onclick='reload_if_8()'> +<input type='button' id="a_button2" onclick='reload_if_9()'> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_navigation2.html b/dom/html/test/test_iframe_sandbox_navigation2.html new file mode 100644 index 000000000..7982d913f --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_navigation2.html @@ -0,0 +1,212 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=341604 +Implement HTML5 sandbox attribute for IFRAMEs +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604 - navigation</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> +/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/ +/** Navigation tests Part 2**/ + +SimpleTest.expectAssertions(0); +SimpleTest.requestLongerTimeout(2); // slow on Android +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +// a postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin'/other windows to communicate pass/fail back to this main page. +// it expects to be called with an object like {ok: true/false, desc: +// <description of the test> which it then forwards to ok() +window.addEventListener("message", receiveMessage, false); + +var testPassesReceived = 0; + +function receiveMessage(event) { + switch (event.data.type) { + case "attempted": + testAttempted(); + break; + case "ok": + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + break; + default: + // allow for old style message + if (event.data.ok != undefined) { + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + } + } +} + +// Open windows for tests to attempt to navigate later. +var windowsToClose = new Array(); +windowsToClose.push(window.open("about:blank", "window_to_navigate")); +windowsToClose.push(window.open("about:blank", "window_to_navigate2")); +var iframesWithWindowsToClose = new Array(); + +var attemptedTests = 0; +var passedTests = 0; +var totalTestsToPass = 12; +var totalTestsToAttempt = 15; + +function ok_wrapper(result, desc, addToAttempted = true) { + ok(result, desc); + + if (result) { + passedTests++; + } + + if (addToAttempted) { + testAttempted(); + } +} + +// Added so that tests that don't register unless they fail, +// can at least notify that they've attempted to run. +function testAttempted() { + attemptedTests++; + if (attemptedTests == totalTestsToAttempt) { + // Make sure all tests have had a chance to complete. + setTimeout(function() {finish();}, 1000); + } +} + +var finishCalled = false; + +function finish() { + if (!finishCalled) { + finishCalled = true; + is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " navigation tests that should pass"); + + for (var i = 0; i < windowsToClose.length; i++) { + windowsToClose[i].close(); + } + + SimpleTest.finish(); + } +} + +function checkTestsFinished() { + // If our own finish() has not been called, probably failed due to a timeout, so close remaining windows. + if (!finishCalled) { + for (var i = 0; i < windowsToClose.length; i++) { + windowsToClose[i].close(); + } + } +} + +function doTest() { + // fails if bad + // 14) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not + // be able to navigate another window (opened by another browsing context) using its name. + // file_iframe_sandbox_d_if14.html in if_14 attempts to navigate "window_to_navigate", + // which has been opened in preparation. + + // fails if bad + // 15) iframe with sandbox='allow-scripts' should not be able to navigate top using its + // real name (instead of _top) as allow-top-navigation is not specified. + // file_iframe_sandbox_e_if7.html contains file_iframe_sandbox_e_if8.html, which + // attempts to navigate top by name. + windowsToClose.push(window.open("file_iframe_sandbox_e_if7.html")); + + // fails if bad + // 16) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not + // be able to use its parent's name (instead of _parent) to navigate it, when it is not top. + // (Note: this would apply to other ancestors that are not top as well.) + // file_iframe_sandbox_d_if15.html in if_15 contains file_iframe_sandbox_d_if16.html, which + // tries to navigate if_15 by its name (if_parent). + + // passes if good, fails if bad + // 17) A sandboxed iframe is allowed to navigate itself using window.open(). + // (Done by file_iframe_sandbox_d_if17.html which has 'allow-scripts' and navigates to + // file_iframe_sandbox_navigation_pass.html). + + // passes if good, fails if bad + // 18) A sandboxed iframe is allowed to navigate its children with window.open(), even if + // they are sandboxed. (Done by file_iframe_sandbox_d_if18.html which has 'allow-scripts', + // it navigates a child iframe to file_iframe_sandbox_navigation_pass.html). + + // passes if good, fails if bad + // 19) A sandboxed iframe is not allowed to navigate its ancestor with window.open(). + // (Done by file_iframe_sandbox_d_if20.html contained within file_iframe_sandbox_d_if19.html, + // it attempts to navigate file_iframe_sandbox_d_if19.html to file_iframe_sandbox_navigation_fail.html). + + // passes if good, fails if bad + // 20) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not + // be able to navigate another window (opened by another browsing context) using window.open(..., "<name>"). + // file_iframe_sandbox_d_if14.html in if_14 attempts to navigate "window_to_navigate2", + // which has been opened in preparation, using window.open(..., "window_to_navigate2"). + + // passes if good, fails if bad + // 21) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not + // be able to use its parent's name (not _parent) to navigate it using window.open(), when it is not top. + // (Note: this would apply to other ancestors that are not top as well.) + // file_iframe_sandbox_d_if21.html in if_21 contains file_iframe_sandbox_d_if22.html, which + // tries to navigate if_21 by its name (if_parent2). + + // passes if good, fails if bad + // 22) iframe with sandbox='allow-top-navigation allow-scripts' can navigate top with window.open(). + // file_iframe_sandbox_e_if9.html contains file_iframe_sandbox_e_if11.html which navigates top. + window.open("file_iframe_sandbox_e_if9.html"); + + // passes if good, fails if bad + // 23) iframe with sandbox='allow-top-navigation allow-scripts' nested inside an iframe with + // 'allow-top-navigation allow-scripts' can navigate top, with window.open(). + // file_iframe_sandbox_e_if10.html contains file_iframe_sandbox_e_if9.html which contains + // file_iframe_sandbox_e_if11.html which navigates top. + window.open("file_iframe_sandbox_e_if10.html"); + + // passes if good, fails if bad + // 24) iframe with sandbox='allow-scripts' can NOT navigate top with window.open(). + // file_iframe_sandbox_e_if12.html contains file_iframe_sandbox_e_if14.html which navigates top. + window.open("file_iframe_sandbox_e_if12.html"); + + // passes if good, fails if bad + // 25) iframe with sandbox='allow-scripts' nested inside an iframe with + // 'allow-top-navigation allow-scripts' can NOT navigate top, with window.open(..., "_top"). + // file_iframe_sandbox_e_if13.html contains file_iframe_sandbox_e_if12.html which contains + // file_iframe_sandbox_e_if14.html which navigates top. + window.open("file_iframe_sandbox_e_if13.html"); + + // passes if good, fails if bad + // 26) iframe with sandbox='allow-scripts' should not be able to navigate top using its real name + // (not with _top e.g. window.open(..., "topname")) as allow-top-navigation is not specified. + // file_iframe_sandbox_e_if15.html contains file_iframe_sandbox_e_if16.html, which + // attempts to navigate top by name using window.open(). + window.open("file_iframe_sandbox_e_if15.html"); + + // passes if good + // 27) iframe with sandbox='allow-scripts allow-popups' should be able to + // navigate a window, that it has opened, using it's name. + // file_iframe_sandbox_d_if23.html in if_23 opens a window and then attempts + // to navigate it using it's name in the target of an anchor. + iframesWithWindowsToClose.push("if_23"); + + // passes if good, fails if bad + // 28) iframe with sandbox='allow-scripts allow-popups' should be able to + // navigate a window, that it has opened, using window.open(..., "<name>"). + // file_iframe_sandbox_d_if23.html in if_23 opens a window and then attempts + // to navigate it using it's name in the target of window.open(). +} + +addLoadEvent(doTest); +</script> +<body onunload="checkTestsFinished()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs +<p id="display"></p> +<div id="content"> +<iframe sandbox="allow-same-origin allow-scripts allow-top-navigation" id="if_14" src="file_iframe_sandbox_d_if14.html" height="10" width="10"></iframe> +<iframe id="if_15" name="if_parent" src="file_iframe_sandbox_d_if15.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_17" src="file_iframe_sandbox_d_if17.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_18" src="file_iframe_sandbox_d_if18.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts" id="if_19" src="file_iframe_sandbox_d_if19.html" height="10" width="10"></iframe> +<iframe id="if_21" name="if_parent2" src="file_iframe_sandbox_d_if21.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-popups" id="if_23" src="file_iframe_sandbox_d_if23.html" height="10" width="10"></iframe> +</div> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_plugins.html b/dom/html/test/test_iframe_sandbox_plugins.html new file mode 100644 index 000000000..a8c2bd21b --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_plugins.html @@ -0,0 +1,141 @@ +<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604 - plugins</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <script type="application/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
+/** Plugin tests **/
+SimpleTest.waitForExplicitFinish();
+
+function doTest() {
+ // 1) test that a plugin can't be loaded with <embed> inside a sandboxed <iframe>
+ // (done by file_iframe_sandbox_f_if1.html loaded in if1 below)
+ // 2) test that a plugin can't be loaded with <object> inside a sandboxed <iframe>
+ // (done by file_iframe_sandbox_f_if1.html loaded in if1 below)
+ // 3) test that plugin can't be loaded by a sandboxed <iframe> with src pointing to
+ // a document that is handled by a plugin (done by if_2 below)
+ // 4) test that when a plugin is loaded in an unsandboxed iframe, a sandbox attribute
+ // is then added to the iframe and the document containing the plugin is reloaded,
+ // the plugin does not load in the sandboxed iframe (done with if_3 below)
+ // 5) test that when when a sandboxed iframe's sandbox attribute is removed,
+ // and a new document is loaded into the iframe, the plugin loads
+ // (done with if_4 below)
+
+ // these are all handled by checking how many instances of the test plugin are loaded
+ // when this script runs as the onload handler - there should be two instances,
+ // initially the one loaded directly by this page itself, and the one loaded during
+ // test #4 above.
+ var p = document.getElementById('plugin1');
+ var if_1 = document.getElementById('if_1');
+ p.startWatchingInstanceCount();
+
+ if_1.src = 'file_iframe_sandbox_f_if1.html';
+}
+
+function if_1_load() {
+ var if_1 = document.getElementById('if_1');
+
+ if (if_1.src == "about:blank")
+ return;
+
+ // need to wait for plugin to load, if the test fails...
+ SimpleTest.executeSoon(if_1_continue);
+}
+
+function if_1_continue() {
+ // instance count should be 0 (tests #1 and #2 above)
+ var p = document.getElementById('plugin1');
+ is(p.getInstanceCount(), 0, "plugins should not be loaded via <object> or <embed> by a sandboxed iframe");
+
+ var if_2 = document.getElementById('if_2');
+ if_2.src = 'file_iframe_sandbox_f_if2.html';
+
+ SimpleTest.executeSoon(if_2_continue);
+}
+
+function if_2_continue() {
+ // instance count should be 0 (test #3 above)
+ var p = document.getElementById('plugin1');
+
+ is(p.getInstanceCount(), 0, "plugins should not be loaded via a document of a type that requires a plugin embedded in a sandboxed iframe");
+
+ SimpleTest.executeSoon(if_3_test);
+}
+
+function if_3_test() {
+ var if_3 = document.getElementById('if_3');
+ // add sandbox attribute
+ if_3.sandbox = '';
+ if_3.src = 'file_iframe_sandbox_f_if1.html';
+}
+
+function if_3_load() {
+ if (if_3.src == "about:blank")
+ return;
+
+ SimpleTest.executeSoon(if_3_continue);
+}
+
+function if_3_continue() {
+ var p = document.getElementById('plugin1');
+ is(p.getInstanceCount(), 0, "plugins should not be loaded when a sandbox attribute is added" +
+ "to an iframe and a document containing a plugin is then loaded into the iframe");
+
+ SimpleTest.executeSoon(if_4_test);
+}
+
+function if_4_test() {
+ var if_4 = document.getElementById('if_4');
+ // remove sandbox attribute
+ if_4.removeAttribute('sandbox');
+ if_4.src = 'file_iframe_sandbox_f_if1.html';
+}
+
+function if_4_load() {
+ if (if_4.src == "about:blank")
+ return;
+
+ SimpleTest.executeSoon(if_4_continue);
+}
+
+function if_4_continue() {
+ var p = document.getElementById('plugin1');
+ // there are 2 plugin instances in file_iframe_sandbox_if1.html loaded by
+ // if_1, they should successfully load.
+ is(p.getInstanceCount(), 2, "plugins should be loaded when a sandbox attribute is removed " +
+ "from an iframe and a document containing a plugin is then loaded into the iframe");
+
+ p.stopWatchingInstanceCount();
+ SimpleTest.executeSoon(finish_test);
+}
+
+function finish_test() {
+ SimpleTest.finish();
+}
+
+addLoadEvent(doTest);
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+<iframe id="if_1" sandbox='allow-same-origin' onLoad='if_1_load()' src="about:blank" height="400" width="400"></iframe>
+<iframe id="if_2" sandbox='allow-same-origin' src="about:blank" height="400" width="400"></iframe>
+<iframe id="if_3" src="about:blank" onload='if_3_load()' height="400" width="400"></iframe>
+<iframe id="if_4" sandbox='allow-same-origin' onload='if_4_load()' src="about:blank" height="400" width="400"></iframe>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_popups.html b/dom/html/test/test_iframe_sandbox_popups.html new file mode 100644 index 000000000..28094f2e6 --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_popups.html @@ -0,0 +1,78 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=766282 +implement allow-popups directive for iframe sandbox +--> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 766282</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); + +// a postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin' to communicate pass/fail back to this main page. +// it expects to be called with an object like {ok: true/false, desc: +// <description of the test> which it then forwards to ok() +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) +{ + ok_wrapper(event.data.ok, event.data.desc); +} + +var completedTests = 0; +var passedTests = 0; + +function ok_wrapper(result, desc) { + ok(result, desc); + + completedTests++; + + if (result) { + passedTests++; + } + + if (completedTests == 3) { + is(passedTests, completedTests, "There are " + completedTests + " popups tests that should pass"); + SimpleTest.finish(); + } +} + +function doTest() { + // passes if good + // 1) Test that a sandboxed iframe with "allow-popups" can open a new window using the target.attribute. + // This is done via file_iframe_sandbox_h_if1.html which is sandboxed with "allow-popups allow-scripts allow-same-origin". + // The window it attempts to open calls window.opener.ok(true, ...) and file_iframe_h_if1.html has an ok() + // function that calls window.parent.ok_wrapper. + + // passes if good + // 2) Test that a sandboxed iframe with "allow-popups" can open a new window using window.open. + // This is done via file_iframe_sandbox_h_if1.html which is sandboxed with "allow-popups allow-scripts allow-same-origin". + // The window it attempts to open calls window.opener.ok(true, ...) and file_iframe_h_if1.html has an ok() + // function that calls window.parent.ok_wrapper. + + // passes if good, fails if bad + // 3) Test that a sandboxed iframe with "allow-popups" can open a new window using the target.attribute + // for a non-existing browsing context (BC766282). + // This is done via file_iframe_sandbox_h_if1.html which is sandboxed with "allow-popups allow-scripts allow-same-origin". + // The window it attempts to open calls window.opener.ok(true, ...) and file_iframe_h_if1.html has an ok() + // function that calls window.parent.ok_wrapper. +} + +addLoadEvent(doTest); + +</script> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=766282">Mozilla Bug 766282</a> - implement allow-popups directive for iframe sandbox +<p id="display"></p> +<div id="content"> +<iframe sandbox="allow-popups allow-same-origin allow-scripts" id="if1" src="file_iframe_sandbox_h_if1.html" height="10" width="10"></iframe> +</div> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_popups_inheritance.html b/dom/html/test/test_iframe_sandbox_popups_inheritance.html new file mode 100644 index 000000000..54afb56b2 --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_popups_inheritance.html @@ -0,0 +1,157 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=766282 +Implement HTML5 sandbox allow-popuos directive for IFRAMEs - inheritance tests +--> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 766282</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> + +<script type="application/javascript"> + +SimpleTest.expectAssertions(0, 5); +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); + +// A postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin' to communicate pass/fail back to this main page. +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) { + switch (event.data.type) { + case "attempted": + testAttempted(); + break; + case "ok": + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + break; + default: + // allow for old style message + if (event.data.ok != undefined) { + ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted); + } + } +} + +var iframesWithWindowsToClose = new Array(); + +var attemptedTests = 0; +var passedTests = 0; +var totalTestsToPass = 15; +var totalTestsToAttempt = 21; + +function ok_wrapper(result, desc, addToAttempted = true) { + ok(result, desc); + + if (result) { + passedTests++; + } + + if (addToAttempted) { + testAttempted(); + } +} + +// Added so that tests that don't register unless they fail, +// can at least notify that they've attempted to run. +function testAttempted() { + attemptedTests++; + if (attemptedTests == totalTestsToAttempt) { + // Make sure all tests have had a chance to complete. + setTimeout(function() {finish();}, 1000); + } +} + +var finishCalled = false; + +function finish() { + if (!finishCalled) { + finishCalled = true; + is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " inheritance tests that should pass"); + + closeWindows(); + + SimpleTest.finish(); + } +} + +function checkTestsFinished() { + // If our own finish() has not been called, probably failed due to a timeout, so close remaining windows. + if (!finishCalled) { + closeWindows(); + } +} + +function closeWindows() { + for (var i = 0; i < iframesWithWindowsToClose.length; i++) { + document.getElementById(iframesWithWindowsToClose[i]).contentWindow.postMessage({type: "closeWindows"}, "*"); + } +} + +function doTest() { + // passes if good and fails if bad + // 1,2,3) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups + // allow-same-origin" should not have its origin sandbox flag set and be able to access document.cookie. + // (Done by file_iframe_sandbox_k_if5.html opened from file_iframe_sandbox_k_if4.html) + // This is repeated for 3 different ways of opening the window, + // see file_iframe_sandbox_k_if4.html for details. + + // passes if good + // 4,5,6) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups + // allow-top-navigation" should not have its top-level navigation sandbox flag set and be able to + // navigate top. (Done by file_iframe_sandbox_k_if5.html (and if6) opened from + // file_iframe_sandbox_k_if4.html). This is repeated for 3 different ways of opening the window, + // see file_iframe_sandbox_k_if4.html for details. + + // passes if good + // 7,8,9) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups + // all-forms" should not have its forms sandbox flag set and be able to submit forms. + // (Done by file_iframe_sandbox_k_if7.html opened from file_iframe_sandbox_k_if4.html) + // This is repeated for 3 different ways of opening the window, + // see file_iframe_sandbox_k_if4.html for details. + + // passes if good + // 10,11,12) Make sure that the sandbox flags copied to a new browsing context are taken from the + // current active document not the browsing context (iframe / docShell). + // This is done by removing allow-same-origin and calling doSubOpens from file_iframe_sandbox_k_if8.html, + // which opens file_iframe_sandbox_k_if9.html in 3 different ways. + // It then navigates to file_iframe_sandbox_k_if1.html to run tests 13 - 21 below. + var if_8_1 = document.getElementById('if_8_1'); + if_8_1.sandbox = 'allow-scripts allow-popups'; + if_8_1.contentWindow.doSubOpens(); + + // passes if good and fails if bad + // 13,14,15) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups" + // should have its origin sandbox flag set and not be able to access document.cookie. + // This is done by file_iframe_sandbox_k_if8.html navigating to file_iframe_sandbox_k_if1.html + // after allow-same-origin has been removed from iframe if_8_1. file_iframe_sandbox_k_if1.html + // opens file_iframe_sandbox_k_if2.html in 3 different ways to perform the tests. + iframesWithWindowsToClose.push("if_8_1"); + + // fails if bad + // 16,17,18) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups" + // should have its forms sandbox flag set and not be able to submit forms. + // This is done by file_iframe_sandbox_k_if2.html, see test 10 for details of how this is opened. + + // fails if bad + // 19,20,21) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups" + // should have its top-level navigation sandbox flag set and not be able to navigate top. + // This is done by file_iframe_sandbox_k_if2.html, see test 10 for details of how this is opened. +} + +addLoadEvent(doTest); +</script> + +<body onunload="checkTestsFinished()"> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=766282">Mozilla Bug 766282</a> - Implement HTML5 sandbox allow-popups directive for IFRAMEs +<p id="display"></p> +<div id="content"> +<iframe sandbox="allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation" id="if_4" src="file_iframe_sandbox_k_if4.html" height="10" width="10"></iframe> +<iframe sandbox="allow-scripts allow-popups allow-same-origin" id="if_8_1" src="file_iframe_sandbox_k_if8.html" height="10" width="10"></iframe> +</div> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_redirect.html b/dom/html/test/test_iframe_sandbox_redirect.html new file mode 100644 index 000000000..5476a6d44 --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_redirect.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=985135 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 985135</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 985135 **/ + SimpleTest.waitForExplicitFinish(); + addLoadEvent(function() { + try { + var doc = frames[0].document; + ok(false, "Should not be able to get the document"); + isnot(doc.body.textContent.slice(0, -1), "I have been redirected", + "Should not happen"); + SimpleTest.finish(); + } catch (e) { + // Check that we got the right document + window.onmessage = function(event) { + is(event.data, "who are you? redirect target", + "Should get the message we expect"); + SimpleTest.finish(); + } + + frames[0].postMessage("who are you?", "*"); + } + }); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=985135">Mozilla Bug 985135</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe src="file_iframe_sandbox_redirect.html" sandbox="allow-scripts"></iframe> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_refresh.html b/dom/html/test/test_iframe_sandbox_refresh.html new file mode 100644 index 000000000..770a4ba8f --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_refresh.html @@ -0,0 +1,101 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1156059 +--> +<head> + <meta charset="utf-8"> + <title>Tests for Bug 1156059</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + // Tests for Bug 1156059 + // See ok messages in iframes for test cases. + + SimpleTest.waitForExplicitFinish(); + SimpleTest.requestFlakyTimeout("We cannot detect when the sandbox blocks the META REFRESH, so we need to allow a reasonable amount of time for them to fail."); + + var testCases = [ + { + desc: "Meta refresh without allow-scripts should be ignored.", + numberOfLoads: 0, + numberOfLoadsExpected: 1 + }, + { + desc: "Meta refresh check should be case insensitive.", + numberOfLoads: 0, + numberOfLoadsExpected: 1 + }, + { + desc: "Meta refresh with allow-scripts should work.", + numberOfLoads: 0, + numberOfLoadsExpected: 2 + }, + { + desc: "Refresh HTTP headers should not be affected by sandbox.", + numberOfLoads: 0, + numberOfLoadsExpected: 2 + } + ]; + + var totalLoads = 0; + var totalLoadsExpected = testCases.reduce(function(partialSum, testCase) { + return partialSum + testCase.numberOfLoadsExpected; + }, 0); + + function processLoad(testCaseIndex) { + testCases[testCaseIndex].numberOfLoads++; + + if (++totalLoads == totalLoadsExpected) { + // Give the tests that should block the refresh a bit of extra time to + // fail. The worst that could happen here is that we get a false pass. + window.setTimeout(processResults, 500); + } + } + + function processResults() { + testCases.forEach(function(testCase, index) { + var msg = "Test Case " + index + ": " + testCase.desc; + is(testCase.numberOfLoads, testCase.numberOfLoadsExpected, msg); + }); + + SimpleTest.finish(); + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1156059">Mozilla Bug 1156059</a> +<p id="display"></p> +<div id="content" style="display: none"> + +<iframe + onload="processLoad(0)" + srcdoc="<meta http-equiv='refresh' content='0; url=data:text/html,Refreshed'>" + sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-top-navigation" +></iframe> + +<iframe + onload="processLoad(1)" + srcdoc="<meta http-equiv='rEfReSh' content='0; url=data:text/html,Refreshed'>" + sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-top-navigation" +></iframe> + +<iframe + onload="processLoad(2)" + srcdoc="<meta http-equiv='refresh' content='0; url=data:text/html,Refreshed'>" + sandbox="allow-scripts" +></iframe> + +<iframe + onload="processLoad(3)" + src="file_iframe_sandbox_refresh.html" + sandbox +></iframe> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_iframe_sandbox_same_origin.html b/dom/html/test/test_iframe_sandbox_same_origin.html new file mode 100644 index 000000000..b924b9f20 --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_same_origin.html @@ -0,0 +1,108 @@ +\<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs - same origin tests
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
+/** Same Origin Tests **/
+
+SimpleTest.waitForExplicitFinish();
+
+var completedTests = 0;
+var passedTests = 0;
+
+function ok_wrapper(result, desc) {
+ ok(result, desc);
+
+ completedTests++;
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (completedTests == 14) {
+ is(passedTests, completedTests, "There are " + completedTests + " same-origin tests that should pass");
+
+ SimpleTest.finish();
+ }
+}
+
+function receiveMessage(event)
+{
+ ok_wrapper(event.data.ok, event.data.desc);
+}
+
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+// it expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok()
+window.addEventListener("message", receiveMessage, false);
+
+function doTest() {
+ // 1) test that we can't access an iframe sandboxed without "allow-same-origin"
+ var if_1 = document.getElementById("if_1");
+ try {
+ var b = if_1.contentDocument.body;
+ ok_wrapper(false, "accessing body of a sandboxed document should not be allowed");
+ } catch (err){
+ ok_wrapper(true, "accessing body of a sandboxed document should not be allowed");
+ }
+
+ // 2) test that we can access an iframe sandboxed with "allow-same-origin"
+ var if_2 = document.getElementById("if_2");
+
+ try {
+ var b = if_2.contentDocument.body;
+ ok_wrapper(true, "accessing body of a sandboxed document with allow-same-origin should be allowed");
+ } catch (err) {
+ ok_wrapper(false, "accessing body of a sandboxed document with allow-same-origin should be allowed");
+ }
+
+ // 3) test that a sandboxed iframe without 'allow-same-origin' cannot access its parent
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 4) test that a sandboxed iframe with 'allow-same-origin' can access its parent
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 5) check that a sandboxed iframe with "allow-same-origin" can access document.cookie
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 6) check that a sandboxed iframe with "allow-same-origin" can access window.localStorage
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 7) check that a sandboxed iframe with "allow-same-origin" can access window.sessionStorage
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 8) check that a sandboxed iframe WITHOUT "allow-same-origin" can NOT access document.cookie
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 9) check that a sandboxed iframe WITHOUT "allow-same-origin" can NOT access window.localStorage
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 10) check that a sandboxed iframe WITHOUT "allow-same-origin" can NOT access window.sessionStorage
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 11) check that XHR works normally in a sandboxed iframe with "allow-same-origin" and "allow-scripts"
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 12) check that XHR is blocked in a sandboxed iframe with "allow-scripts" but WITHOUT "allow-same-origin"
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+}
+addLoadEvent(doTest);
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="" id="if_1" src="file_iframe_sandbox_b_if1.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" id="if_2" src="file_iframe_sandbox_b_if2.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_3" src="file_iframe_sandbox_b_if3.html" height="10" width="10"></iframe>
+</div>
diff --git a/dom/html/test/test_iframe_sandbox_workers.html b/dom/html/test/test_iframe_sandbox_workers.html new file mode 100644 index 000000000..0737729da --- /dev/null +++ b/dom/html/test/test_iframe_sandbox_workers.html @@ -0,0 +1,74 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=341604 +Implement HTML5 sandbox attribute for IFRAMEs - tests for workers +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 341604</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> +/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs - test for workers **/ + +SimpleTest.waitForExplicitFinish(); + +// a postMessage handler that is used by sandboxed iframes without +// 'allow-same-origin' to communicate pass/fail back to this main page. +// it expects to be called with an object like {ok: true/false, desc: +// <description of the test> which it then forwards to ok() +window.addEventListener("message", receiveMessage, false); + +function receiveMessage(event) +{ + ok_wrapper(event.data.ok, event.data.desc); +} + +var completedTests = 0; +var passedTests = 0; + +function ok_wrapper(result, desc) { + ok(result, desc); + + completedTests++; + + if (result) { + passedTests++; + } + + if (completedTests == 3) { + is(passedTests, 3, "There are 3 worker tests that should pass"); + SimpleTest.finish(); + } +} + +function doTest() { + // passes if good + // 1) test that a worker in a sandboxed iframe with 'allow-scripts' can be loaded + // from a data: URI + // (done by file_iframe_sandbox_g_if1.html) + + // passes if good + // 2) test that a worker in a sandboxed iframe with 'allow-scripts' can be loaded + // from a blob URI created by the sandboxed document itself + // (done by file_iframe_sandbox_g_if1.html) + + // passes if good + // 3) test that a worker in a sandboxed iframe with 'allow-scripts' without + // 'allow-same-origin' cannot load a script via a relative URI + // (done by file_iframe_sandbox_g_if1.html) +} + +addLoadEvent(doTest); +</script> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs +<p id="display"></p> +<div id="content"> +<iframe sandbox="allow-scripts" id="if_1" src="file_iframe_sandbox_g_if1.html" height="10" width="10"></iframe> +</div> +</body> +</html> diff --git a/dom/html/test/test_ignoreuserfocus.html b/dom/html/test/test_ignoreuserfocus.html new file mode 100644 index 000000000..629790182 --- /dev/null +++ b/dom/html/test/test_ignoreuserfocus.html @@ -0,0 +1,158 @@ +<!DOCTYPE HTML> +<html> + <head> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + </head> + <body> + <script type="application/javascript;version=1.7"> + "use strict"; + + SimpleTest.requestCompleteLog(); + SimpleTest.waitForExplicitFinish(); + + // Copied from EventUtils.js, but we want *ToWindow methods. + function synthesizeMouseAtPoint(left, top, aEvent, aWindow) { + var utils = _getDOMWindowUtils(aWindow); + var defaultPrevented = false; + if (utils) { + var button = aEvent.button || 0; + var clickCount = aEvent.clickCount || 1; + var modifiers = _parseModifiers(aEvent); + var pressure = ("pressure" in aEvent) ? aEvent.pressure : 0; + var inputSource = ("inputSource" in aEvent) ? aEvent.inputSource : 0; + + if (("type" in aEvent) && aEvent.type) { + defaultPrevented = utils.sendMouseEventToWindow(aEvent.type, left, top, button, clickCount, modifiers, false, pressure, inputSource); + } + else { + utils.sendMouseEventToWindow("mousedown", left, top, button, clickCount, modifiers, false, pressure, inputSource); + utils.sendMouseEventToWindow("mouseup", left, top, button, clickCount, modifiers, false, pressure, inputSource); + } + } + } + + function runTest() { + var witness = document.createElement("input"); + witness.setAttribute("type", "text"); + var witness2 = document.createElement("input"); + witness2.setAttribute("type", "text"); + + var iframe = document.createElement("iframe"); + iframe.setAttribute("mozbrowser", "true"); + iframe.setAttribute("ignoreuserfocus", "true"); + iframe.setAttribute("height", "300px"); + + iframe.addEventListener('load', function (e) { + // Get privileged iframe because mozbrowser iframe is not same origin + // with the parent. We need to access its content through the wrapper. + var privilegedIframe = SpecialPowers.wrap(iframe); + privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaint(e) { + privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaint); + + privilegedIframe.contentWindow.addEventListener("focus", + function(e) { + ok(!iframe.hasAttribute("ignoreuserfocus"), "Shouldn't get a focus event in ignoreuserfocus iframe!"); + }, + true); + privilegedIframe.contentWindow.addEventListener("blur", + function(e) { + ok(!iframe.hasAttribute("ignoreuserfocus"), "Shouldn't get a blur event in ignoreuserfocus iframe!"); + }, + true); + + // Sanity check + witness.focus(); + is(document.activeElement, witness, "witness should have the focus"); + + iframe.focus(); + isnot(document.activeElement, iframe, "[explicit iframe.focus()] iframe should not get the focus"); + + iframe.removeAttribute("ignoreuserfocus"); + iframe.focus(); + is(document.activeElement, iframe, "[explicit iframe.focus()] iframe should get the focus"); + + iframe.setAttribute("ignoreuserfocus", "true"); + + // Test the case when iframe contains <input> and .focus() + // is called and explicit focus using mouse + witness.focus(); + + var innerInput = privilegedIframe.contentDocument.getElementsByTagName("input")[0]; + innerInput.focus(); + isnot(document.activeElement, iframe, "[explicit innerInput.focus()] iframe should not have the focus"); + + var iframeWindow = SpecialPowers.unwrap(privilegedIframe.contentWindow); + witness.focus(); + synthesizeMouseAtCenter(innerInput, {}, iframeWindow); + is(document.activeElement, witness, "[synthesize mouse click] witness should have the focus"); + + // Test the case when iframe contains <iframe> and .focus() + // is called and explicit focus using mouse + witness.focus(); + + var innerIframe = privilegedIframe.contentDocument.getElementsByTagName("iframe")[0]; + innerIframe.focus(); + isnot(document.activeElement, iframe, "[explicit innerIframe.focus()] iframe should not have the focus"); + + witness.focus(); + synthesizeMouseAtCenter(innerIframe, {}, iframeWindow); + is(document.activeElement, witness, "[synthesize mouse click inner iframe] witness should have the focus"); + + // Test the case when iframe contains <area> and .focus() + // is called and explicit focus using mouse + + // Wait for paint to setup frame for area. Currently the area frame + // map is reset for each paint. If we are in the middle of a paint + // then the area will not be focusable. + privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaintArea(e) { + privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaintArea); + var innerArea = privilegedIframe.contentDocument.getElementsByTagName("area")[0]; + innerArea.focus(); + isnot(document.activeElement, iframe, "[explicit innerArea.focus()] iframe should not have the focus"); + + witness.focus(); + synthesizeMouseAtCenter(innerArea, {}, iframeWindow); + is(document.activeElement, witness, "[synthesize mouse click] witness should have the focus"); + + // Test tabindex + witness.focus(); + is(document.activeElement, witness, "witness should have the focus"); + synthesizeKey("VK_TAB", {}); + isnot(document.activeElement, iframe, "[synthesize tab key] iframe should not have the focus"); + is(document.activeElement, witness2, "witness2 should have the focus"); + + SimpleTest.finish(); + }); + witness.focus(); + // force reflow + iframe.setAttribute("height", "298px"); + }); + // force reflow + iframe.setAttribute("height", "299px"); + }); + + document.body.appendChild(witness); + document.body.appendChild(iframe); + document.body.appendChild(witness2); + + iframe.setAttribute("src", "file_ignoreuserfocus.html"); + } + addEventListener("load", function() { + SpecialPowers.pushPermissions( + [{'type': 'browser', 'allow': true, 'context': document}], + function() { + SpecialPowers.pushPrefEnv({ + "set": [ + ["dom.mozBrowserFramesEnabled", true], + ["network.disable.ipc.security", true], + ] + }, function() { + SimpleTest.waitForFocus(runTest); + }); + }); + }); + </script> + </body> +</html> diff --git a/dom/html/test/test_imageSrcSet.html b/dom/html/test/test_imageSrcSet.html new file mode 100644 index 000000000..adbea1676 --- /dev/null +++ b/dom/html/test/test_imageSrcSet.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=980243 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 980243</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 980243 **/ + SimpleTest.waitForExplicitFinish(); + + addLoadEvent(function() { + var img = document.querySelector("img"); + img.onload = function() { + ok(true, "Reached here"); + SimpleTest.finish(); + } + // If ths spec ever changes to treat .src sets differently from + // setAttribute("src"), we'll need some sort of canonicalization step + // earlier to make the attr value an absolute URI. + img.setAttribute("src", img.getAttribute("src")); + }); + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=980243">Mozilla Bug 980243</a> +<p id="display"></p> +<div id="content" style="display: none"> + <img src="file_formSubmission_img.jpg"> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_image_clone_load.html b/dom/html/test/test_image_clone_load.html new file mode 100644 index 000000000..e808c80a5 --- /dev/null +++ b/dom/html/test/test_image_clone_load.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for image clones doing their load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var t = async_test("The clone of an image should do the load of the same image, and do it synchronously"); +t.step(function() { + var img = new Image(); + img.onload = t.step_func(function() { + var clone = img.cloneNode(); + assert_not_equals(img.naturalWidth, 0, "Should have a width"); + assert_equals(clone.naturalWidth, img.naturalWidth, + "Clone should have a width too"); + // And make sure the clone fires onload too, which happens async. + clone.onload = function() { t.done() } + }); + img.src = "image.png"; +}); +</script> diff --git a/dom/html/test/test_img_attributes_reflection.html b/dom/html/test/test_img_attributes_reflection.html new file mode 100644 index 000000000..c40865a86 --- /dev/null +++ b/dom/html/test/test_img_attributes_reflection.html @@ -0,0 +1,103 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLImageElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> +/** Test for HTMLImageElement attributes reflection **/ + +reflectString({ + element: document.createElement("img"), + attribute: "alt", +}) + +reflectURL({ + element: document.createElement("img"), + attribute: "src", +}) + +reflectString({ + element: document.createElement("img"), + attribute: "srcset", +}) + +reflectLimitedEnumerated({ + element: document.createElement("img"), + attribute: "crossOrigin", + // "" is a valid value per spec, but gets mapped to the "anonymous" state, + // just like invalid values, so just list it under invalidValues + validValues: [ "anonymous", "use-credentials" ], + invalidValues: [ + "", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR " + ], + defaultValue: { invalid: "anonymous", missing: null }, + nullable: true, +}) + +reflectString({ + element: document.createElement("img"), + attribute: "useMap", +}) + +reflectBoolean({ + element: document.createElement("img"), + attribute: "isMap", +}) + +ok("width" in document.createElement("img"), "img.width is present") +ok("height" in document.createElement("img"), "img.height is present") +ok("naturalWidth" in document.createElement("img"), "img.naturalWidth is present") +ok("naturalHeight" in document.createElement("img"), "img.naturalHeight is present") +ok("complete" in document.createElement("img"), "img.complete is present") + +reflectString({ + element: document.createElement("img"), + attribute: "name", +}) + +reflectString({ + element: document.createElement("img"), + attribute: "align", +}) + +reflectUnsignedInt({ + element: document.createElement("img"), + attribute: "hspace", +}) + +reflectUnsignedInt({ + element: document.createElement("img"), + attribute: "vspace", +}) + +reflectURL({ + element: document.createElement("img"), + attribute: "longDesc", +}) + +reflectString({ + element: document.createElement("img"), + attribute: "border", + extendedAttributes: { TreatNullAs: "EmptyString" }, +}) + +reflectURL({ + element: document.createElement("img"), + attribute: "lowsrc", +}) + +ok("x" in document.createElement("img"), "img.x is present") +ok("y" in document.createElement("img"), "img.y is present") + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_imports_basics.html b/dom/html/test/test_imports_basics.html new file mode 100644 index 000000000..3bdd96152 --- /dev/null +++ b/dom/html/test/test_imports_basics.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=877072 +--> +<head> + <title>Test for Bug 877072</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=877072">Mozilla Bug 877072</a> + + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var loadEventFired = false; + var errorEventFired = false; + var counter = 0; + function loaded() { + loadEventFired = true; + } + function failed() { + errorEventFired = true; + } + </script> + + <link rel="import" href="file_imports_basics.html" id="import1" onload="loaded()" onerror="failed()"></link> + + <script type="text/javascript"> + ok(importDone, "Script of the imported document runned before this script"); + ok(loadEventFired, "Load eventhandler works"); + ok(!errorEventFired, "There were no error event fired"); + + var import1 = document.getElementById("import1").import; + is(import1.getElementById("foo").textContent, "bar", + "import property of link import works"); + + try{ + import1.open(); + import1.write("<h1>This should not show up!</h1>"); + import1.close(); + } catch (e) { + ok(true, "import.open/write should throw"); + } + + // Let's add dynamically a new link import with the same URI + var link = document.createElement("link"); + link.setAttribute("id", "inserted"); + link.setAttribute("rel", "import"); + link.setAttribute("href", "file_imports_basics.html"); + function loaded2() { + ok(true, "Load event is fired for link import that refers to an already loaded import"); + is(counter, 1, "Adding another link referring to the same import, does not load it twice"); + is(document.getElementById("inserted").import.getElementById("foo").textContent, "bar", + "import property of dynamic link import works"); + SimpleTest.finish(); + }; + link.setAttribute("onload", "loaded2()"); + function failed2() { + ok(false, "You should not reach this code"); + SimpleTest.finish(); + }; + link.setAttribute("onerror", "failed2()"); + document.body.appendChild(link); + </script> +</body> +</html>
\ No newline at end of file diff --git a/dom/html/test/test_imports_nested.html b/dom/html/test/test_imports_nested.html new file mode 100644 index 000000000..518e5b741 --- /dev/null +++ b/dom/html/test/test_imports_nested.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=877072 +--> +<head> + <title>Test for Bug 877072</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=877072">Mozilla Bug 877072</a> + + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var order = []; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + + <link rel="import" href="imports/file_importA1.html" id="A1" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="imports/file_importB1.html" id="B1" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="imports/file_importB2.html" id="B2_2" onload="loaded()" onerror="failed()"></link> + + <script type="text/javascript"> + is(counter, 5, "Imports are loaded"); + is(fcounter, 0, "No error in imports"); + var expected = ["A2", "A1", "B2", "B1"]; + for (i in expected) + is(order[i], expected[i], "import " + i + " should be " + expected[i]); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/test_imports_nested_2.html b/dom/html/test/test_imports_nested_2.html new file mode 100644 index 000000000..8e8e57d68 --- /dev/null +++ b/dom/html/test/test_imports_nested_2.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=877072 +--> +<head> + <title>Test for Bug 877072</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=877072">Mozilla Bug 877072</a> + + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var counter = 0; + var fcounter = 0; + var order = []; + function loaded() { + counter++; + } + function failed() { + fcounter++; + } + </script> + +<!-- + +Master -> c1 -> ... -> C10 +| | | +| - - -> D | +| ^ | +| | | + - - - -> E < - - - - - - + +This test is for testing ImportLoader::UpdateDependants.Because of the long +chain to C10, it's very likely that C10->E will be the last edge the ImportLoaders +find. At that point it won't only have to update E but also its subimport D. + +--> + + <link rel="import" href="imports/file_importC1.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="imports/file_importD.html" onload="loaded()" onerror="failed()"></link> + <link rel="import" href="imports/file_importE.html" onload="loaded()" onerror="failed()"></link> + + <script type="text/javascript"> + is(counter, 14, "Imports are loaded"); // 12 imports but 14 link imports... + is(fcounter, 0, "No error in imports"); + var expected = ["D", "E", "C10", "C9", "C8", "C7", "C6", "C5", "C4", "C3", "C2", "C1"]; + for (i in expected) + is(order[i], expected[i], "import " + i + " should be " + expected[i]); + SimpleTest.finish(); + </script> +</body> +</html> diff --git a/dom/html/test/test_imports_nonhttp.html b/dom/html/test/test_imports_nonhttp.html new file mode 100644 index 000000000..7a5620599 --- /dev/null +++ b/dom/html/test/test_imports_nonhttp.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1016875 +--> +<head> + <title>Test for Bug 1016875</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1016875">Mozilla Bug 1016875</a> + + <script type="text/javascript"> + //<![CDATA[ + SimpleTest.waitForExplicitFinish(); + var counter = 0; + function loaded() { + if ( counter++ == 1 ) { + ok(document.getElementById("import1").import.getElementById("div1"), + "import document was loaded"); + ok(document.getElementById("import2").import.getElementById("div1"), + "import document was loaded"); + SimpleTest.finish(); + } + } + function failed() { + ok(false, "Import should not have failed") + SimpleTest.finish(); + } + var link = document.createElement("link"); + link.setAttribute("id", "import1"); + link.setAttribute("rel", "import"); + var stringDoc = "<!DOCTYPE html><html><body><div id='div1'></div></body></html>"; + var encoded = btoa(stringDoc); + var dataurl = "data:text/html;base64," + encoded; + link.setAttribute("href", dataurl); + link.onload = loaded; + link.onerror = failed; + document.body.appendChild(link); + + var link = document.createElement("link"); + link.setAttribute("id", "import2"); + link.setAttribute("rel", "import"); + var blob = new Blob([stringDoc], {type : 'text/html'}); + var objectURL = URL.createObjectURL(blob); + link.setAttribute("href", objectURL); + link.onload = loaded; + link.onerror = failed; + document.body.appendChild(link); + //]]> + </script> + +</body> +</html> diff --git a/dom/html/test/test_imports_redirect.html b/dom/html/test/test_imports_redirect.html new file mode 100644 index 000000000..d780476cf --- /dev/null +++ b/dom/html/test/test_imports_redirect.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1016875 +--> +<head> + <title>Test for Bug 1016875</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> +</head> +<body> + <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1016875">Mozilla Bug 1016875</a> + + <script type="text/javascript"> + SimpleTest.waitForExplicitFinish(); + var loadEventFired = false; + var errorEventFired = false; + var counter = 0; + function loaded() { + loadEventFired = true; + } + function failed() { + errorEventFired = true; + } + </script> + + <link rel="import" href="http://mochi.test:8888/tests/dom/html/test/file_imports_redirect.html" id="import" onload="loaded()" onerror="failed()"></link> + + <script type="text/javascript"> + ok(loadEventFired, "Load event was fired"); + ok(!errorEventFired, "Error event was not fired, redirection worked"); + ok(redirected, "Script of the target of redirection was executed"); + + SimpleTest.finish(); + </script> + +</body> +</html> diff --git a/dom/html/test/test_input_files_not_nsIFile.html b/dom/html/test/test_input_files_not_nsIFile.html new file mode 100644 index 000000000..a52afac7c --- /dev/null +++ b/dom/html/test/test_input_files_not_nsIFile.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for <input type='file'> handling when its "files" do not implement nsIFile</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<div id="content"> + <input id='a' type='file'> +</div> +<button id='b' onclick="document.getElementById('a').click();">Show Filepicker</button> + +<input type="file" id="file" /> +<pre id="test"> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); + +var MockFilePicker = SpecialPowers.MockFilePicker; +MockFilePicker.init(window); + +SimpleTest.waitForFocus(function() { + MockFilePicker.useBlobFile(); + MockFilePicker.returnValue = MockFilePicker.returnOK; + + var b = document.getElementById('b'); + b.focus(); // Be sure the element is visible. + + document.getElementById('a').addEventListener("change", function(aEvent) { + ok(true, "change event correctly sent"); + + SimpleTest.executeSoon(function() { + MockFilePicker.cleanup(); + SimpleTest.finish(); + }); + }, false); + + b.click(); +}); + +</script> +</pre> +</body> +</html> + diff --git a/dom/html/test/test_li_attributes_reflection.html b/dom/html/test/test_li_attributes_reflection.html new file mode 100644 index 000000000..b6fcd7581 --- /dev/null +++ b/dom/html/test/test_li_attributes_reflection.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLLIElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLLIElement attributes reflection **/ + +// .value +reflectInt({ + element: document.createElement("li"), + attribute: "value", + nonNegative: false, +}); + +// .type +reflectString({ + element: document.createElement("li"), + attribute: "type" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_link_attributes_reflection.html b/dom/html/test/test_link_attributes_reflection.html new file mode 100644 index 000000000..db092f0ef --- /dev/null +++ b/dom/html/test/test_link_attributes_reflection.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLLinkElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLLinkElement attributes reflection **/ + +// .href (URL) +reflectURL({ + element: document.createElement("link"), + attribute: "href", +}); + +// .crossOrigin (String or null) +reflectLimitedEnumerated({ + element: document.createElement("link"), + attribute: "crossOrigin", + // "" is a valid value per spec, but gets mapped to the "anonymous" state, + // just like invalid values, so just list it under invalidValues + validValues: [ "anonymous", "use-credentials" ], + invalidValues: [ + "", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR " + ], + defaultValue: { invalid: "anonymous", missing: null }, + nullable: true, +}) + +// .rel (String) +reflectString({ + element: document.createElement("link"), + attribute: "rel", +}); + +// .media (String) +reflectString({ + element: document.createElement("link"), + attribute: "media", +}); + +// .hreflang (String) +reflectString({ + element: document.createElement("link"), + attribute: "hreflang", +}); + +// .type (String) +reflectString({ + element: document.createElement("link"), + attribute: "type", +}); + + +// .charset (String) +reflectString({ + element: document.createElement("link"), + attribute: "charset", +}); + +// .rev (String) +reflectString({ + element: document.createElement("link"), + attribute: "rev", +}); + +// .target (String) +reflectString({ + element: document.createElement("link"), + attribute: "target", +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_link_sizes.html b/dom/html/test/test_link_sizes.html new file mode 100644 index 000000000..b24274888 --- /dev/null +++ b/dom/html/test/test_link_sizes.html @@ -0,0 +1,35 @@ +<!doctype html> +<html> +<head> +<title>Test link.sizes attribute</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" sizes="16x16 24x24 32x32 48x48"> +</head> +<body> + +<pre id="test"> +<script> + + var links = document.getElementsByTagName('link'); + for (var i = 0; i < links.length; ++i) { + var link = links[i]; + ok("sizes" in link, "link.sizes exists"); + + if (link.rel == 'shortcut icon') { + is(link.sizes.value, "16x16 24x24 32x32 48x48", 'link.sizes.value correct value'); + is(link.sizes.length, 4, 'link.sizes.length correct value'); + ok(link.sizes.contains('32x32'), 'link.sizes.contains() works'); + link.sizes.add('64x64'); + is(link.sizes.length, 5, 'link.sizes.length correct value'); + link.sizes.remove('64x64'); + is(link.sizes.length, 4, 'link.sizes.length correct value'); + is(link.sizes + "", "16x16 24x24 32x32 48x48", 'link.sizes stringify correct value'); + } else { + is(link.sizes.value, "", 'link.sizes correct value'); + } + } +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_map_attributes_reflection.html b/dom/html/test/test_map_attributes_reflection.html new file mode 100644 index 000000000..710dce669 --- /dev/null +++ b/dom/html/test/test_map_attributes_reflection.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLMapElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLMapElement attributes reflection **/ + +// .name (String) +reflectString({ + element: document.createElement("map"), + attribute: "name", +}) + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_meta_attributes_reflection.html b/dom/html/test/test_meta_attributes_reflection.html new file mode 100644 index 000000000..c21d53587 --- /dev/null +++ b/dom/html/test/test_meta_attributes_reflection.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLMetaElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLMetaElement attributes reflection **/ + +// .name (String) +reflectString({ + element: document.createElement("meta"), + attribute: "name", +}) + +// .httpEquiv (String) +reflectString({ + element: document.createElement("meta"), + attribute: { content: "http-equiv", idl: "httpEquiv" }, +}) + +// .content (String) +reflectString({ + element: document.createElement("meta"), + attribute: "content", +}) + +// .scheme (String) +reflectString({ + element: document.createElement("meta"), + attribute: "scheme", +}) + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_mod_attributes_reflection.html b/dom/html/test/test_mod_attributes_reflection.html new file mode 100644 index 000000000..94313bc63 --- /dev/null +++ b/dom/html/test/test_mod_attributes_reflection.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLModElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLModElement attributes reflection **/ + +// .cite (URL) +reflectURL({ + element: document.createElement("ins"), + attribute: "cite", +}) +reflectURL({ + element: document.createElement("del"), + attribute: "cite", +}) + +// .dateTime (String) +reflectString({ + element: document.createElement("ins"), + attribute: "dateTime", +}) +reflectString({ + element: document.createElement("del"), + attribute: "dateTime", +}) + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_mozaudiochannel.html b/dom/html/test/test_mozaudiochannel.html new file mode 100644 index 000000000..722e181bf --- /dev/null +++ b/dom/html/test/test_mozaudiochannel.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for mozaudiochannel</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<pre id="test"> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true]]}, function() { + var ifr = document.createElement('iframe'); + ifr.src = 'file_mozaudiochannel.html'; + onmessage = function(e) { + if ("finish" in e.data) { + SimpleTest.finish(); + } else { + ok(e.data.status, e.data.msg); + } + } + + document.body.appendChild(ifr); +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_named_options.html b/dom/html/test/test_named_options.html new file mode 100644 index 000000000..b6e84a9f2 --- /dev/null +++ b/dom/html/test/test_named_options.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=772869 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 772869</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a> +<p id="display"></p> +<div id="content" style="display: none"> + <select id="s"> + <option name="x"></option> + <option name="y" id="z"></option> + <option name="z" id="x"></option> + <option id="w"></option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 772869 **/ +var opt = $("s").options; +opt.loopy = "something" +var names = Object.getOwnPropertyNames(opt); +is(names.length, 9, "Should have nine entries"); +is(names[0], "0", "Entry 1") +is(names[1], "1", "Entry 2") +is(names[2], "2", "Entry 3") +is(names[3], "3", "Entry 4") +is(names[4], "x", "Entry 5") +is(names[5], "y", "Entry 6") +is(names[6], "z", "Entry 7") +is(names[7], "w", "Entry 8") +is(names[8], "loopy", "Entry 9") + +var names2 = []; +for (var name in opt) { + names2.push(name); +} +is(names2.length, 11, "Should have eleven enumerated names"); +is(names2[0], "0", "Enum entry 1") +is(names2[1], "1", "Enum entry 2") +is(names2[2], "2", "Enum entry 3") +is(names2[3], "3", "Enum entry 4") +is(names2[4], "loopy", "Enum entry 5") +is(names2[5], "add", "Enum entrry 6") +is(names2[6], "remove", "Enum entry 7") +is(names2[7], "length", "Enum entry 8") +is(names2[8], "selectedIndex", "Enum entry 9") +is(names2[9], "item", "Enum entry 10") +is(names2[10], "namedItem", "Enum entry 11") + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_nested_invalid_fieldsets.html b/dom/html/test/test_nested_invalid_fieldsets.html new file mode 100644 index 000000000..42413baa9 --- /dev/null +++ b/dom/html/test/test_nested_invalid_fieldsets.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=914029 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 914029</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 914029 **/ + + var innerFieldset = document.createElement("fieldset"); + var outerFieldset = document.createElement("fieldset"); + var textarea = document.createElement("textarea"); + textarea.setAttribute("required", ""); + innerFieldset.appendChild(textarea); + outerFieldset.appendChild(innerFieldset); + SpecialPowers.forceGC(); + ok(true, "This page did not crash - dynamically added nested invalid fieldsets" + + " work correctly."); + var innerFieldset = document.createElement("fieldset"); + var outerFieldset = document.createElement("fieldset"); + var textarea = document.createElement("textarea"); + var textarea2 = document.createElement("textarea"); + textarea.setAttribute("required", ""); + innerFieldset.appendChild(textarea); + innerFieldset.appendChild(textarea2); + outerFieldset.appendChild(innerFieldset); + SpecialPowers.forceGC(); + ok(true, "This page did not crash - dynamically added nested invalid fieldsets" + + " work correctly."); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=914029">Mozilla Bug 914029</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/dom/html/test/test_non-ascii-cookie.html b/dom/html/test/test_non-ascii-cookie.html new file mode 100644 index 000000000..ab96ac07c --- /dev/null +++ b/dom/html/test/test_non-ascii-cookie.html @@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=784367 +--> +<head> + <meta charset="utf-8"> + <title>Test for non-ASCII cookie values</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=784367">Mozilla Bug 784367</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for non-ASCII cookie values **/ + +SimpleTest.waitForExplicitFinish(); + +var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL("file_cookiemanager.js")); + +function getCookieFromManager() { + return new Promise(resolve => { + gScript.addMessageListener("getCookieFromManager:return", function gcfm({ cookie }) { + gScript.removeMessageListener("getCookieFromManager:return", gcfm); + resolve(cookie); + }); + gScript.sendAsyncMessage("getCookieFromManager", { host: location.hostname, path: location.pathname }); + }); +} + +var c = document.cookie; +is(document.cookie, 'abc=012©ABC\ufffdDEF', "document.cookie should be decoded as UTF-8"); + +var newCookie; + +getCookieFromManager().then((cookie) => { + is(cookie, document.cookie, "nsICookieManager should be consistent with document.cookie"); + newCookie = 'def=∼≩â‰â‰§âˆ¯â‰³â‰²â‰£âˆ½â‰¸â‰¸âˆºâ‰¸âˆ ≯≮≥≲≲≯≲∽≡≬≥≲≴∨∱∩∾'; + document.cookie = newCookie; + is(document.cookie, c + '; ' + newCookie, "document.cookie should be encoded as UTF-8"); + + return getCookieFromManager(); +}).then((cookie) => { + is(cookie, document.cookie, "nsICookieManager should be consistent with document.cookie"); + var date1 = new Date(); + date1.setTime(0); + document.cookie = newCookie + 'def=;expires=' + date1.toGMTString(); + gScript.destroy(); + SimpleTest.finish(); +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_non-ascii-cookie.html^headers^ b/dom/html/test/test_non-ascii-cookie.html^headers^ new file mode 100644 index 000000000..54aa6c3e7 --- /dev/null +++ b/dom/html/test/test_non-ascii-cookie.html^headers^ @@ -0,0 +1 @@ +Set-Cookie: abc=012©ABC©DEF diff --git a/dom/html/test/test_object_attributes_reflection.html b/dom/html/test/test_object_attributes_reflection.html new file mode 100644 index 000000000..40978e582 --- /dev/null +++ b/dom/html/test/test_object_attributes_reflection.html @@ -0,0 +1,117 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLObjectElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLObjectElement attributes reflection **/ + +// .data (URL) +reflectURL({ + element: document.createElement("object"), + attribute: "data", +}); + +// .type (String) +reflectString({ + element: document.createElement("object"), + attribute: "type", +}); + +// .name (String) +reflectString({ + element: document.createElement("object"), + attribute: "name", +}); + +// .useMap (String) +reflectString({ + element: document.createElement("object"), + attribute: "useMap", +}); + +// .width (String) +reflectString({ + element: document.createElement("object"), + attribute: "width", +}); + +// .height (String) +reflectString({ + element: document.createElement("object"), + attribute: "height", +}); + +// .align (String) +reflectString({ + element: document.createElement("object"), + attribute: "align", +}); + +// .archive (String) +reflectString({ + element: document.createElement("object"), + attribute: "archive", +}); + +// .code (String) +reflectString({ + element: document.createElement("object"), + attribute: "code", +}); + +// .declare (String) +reflectBoolean({ + element: document.createElement("object"), + attribute: "declare", +}); + +// .hspace (unsigned int) +reflectUnsignedInt({ + element: document.createElement("object"), + attribute: "hspace", +}); + +// .standby (String) +reflectString({ + element: document.createElement("object"), + attribute: "standby", +}); + +// .vspace (unsigned int) +reflectUnsignedInt({ + element: document.createElement("object"), + attribute: "vspace", +}); + +// .codeBase (URL) +reflectURL({ + element: document.createElement("object"), + attribute: "codeBase", +}); + +// .codeType (String) +reflectString({ + element: document.createElement("object"), + attribute: "codeType", +}); + +// .border (String) +reflectString({ + element: document.createElement("object"), + attribute: "border", + extendedAttributes: { TreatNullAs: "EmptyString" }, +}); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_object_plugin_nav.html b/dom/html/test/test_object_plugin_nav.html new file mode 100644 index 000000000..91590e51a --- /dev/null +++ b/dom/html/test/test_object_plugin_nav.html @@ -0,0 +1,99 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=720130 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 720130</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="plugin-utils.js"></script> + <script type="application/javascript"> + setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED); + </script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720130">Mozilla Bug 720130</a> +<p id="display"></p> +<div id="content"> + <input> + <object type="application/x-test"></object> + <button>foo</button> + <object tabindex='0' type="application/x-test"></object> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 720130 **/ + +var gFocusCount = 0; +var gFocusNb = 4; + +/** + * Check the focus navigation. + */ +function checkFocus() { + switch (gFocusCount) { + case 0: + is(document.activeElement, document.getElementsByTagName('a')[0], + "first focused element should be the link"); + break; + case 1: + is(document.activeElement, document.getElementsByTagName('input')[0], + "second focused element should be the text field"); + break; + case 2: + is(document.activeElement, document.getElementsByTagName('button')[0], + "third focused element should be the button"); + break; + case 3: + is(document.activeElement, document.getElementsByTagName('object')[1], + "fourth focused element should be the object"); + break; + } + + gFocusCount++; +} + +SimpleTest.waitForExplicitFinish(); + +function doTest() { + is(document.activeElement, document.body); + + // Preliminary check: tabindex should be -1 on the object. + is(document.getElementsByTagName('object')[0].tabIndex, -1, + "the plugin shouldn't get focus while navigating in the document"); + + document.addEventListener("focus", function() { + checkFocus(); + + if (gFocusCount != gFocusNb) { + synthesizeKey("VK_TAB", {}); + return; + } + + document.removeEventListener("focus", arguments.callee, true); + + // Just make sure that .focus() still works. + var o = document.getElementsByTagName('object')[0]; + o.onfocus = function() { + SimpleTest.finish(); + o.onfocus = null; + }; + o.focus(); + }, true); + + synthesizeKey("VK_TAB", {}); +} + +SimpleTest.waitForFocus(function () { + // Set the focus model so that links are focusable by the tab key even on Mac + SpecialPowers.pushPrefEnv({'set': [['accessibility.tabfocus', 7]]}, doTest); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_ol_attributes_reflection.html b/dom/html/test/test_ol_attributes_reflection.html new file mode 100644 index 000000000..819ef60e4 --- /dev/null +++ b/dom/html/test/test_ol_attributes_reflection.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLOLElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLOLElement attributes reflection **/ + +// .reversed (boolean) +reflectBoolean({ + element: document.createElement("ol"), + attribute: "reversed", +}) + +// .start +reflectInt({ + element: document.createElement("ol"), + attribute: "start", + nonNegative: false, + defaultValue: 1, +}); + +// .type +reflectString({ + element: document.createElement("ol"), + attribute: "type" +}); + +// .compact +reflectBoolean({ + element: document.createElement("ol"), + attribute: "compact", +}) + +// Additional tests for ol.start behavior when li elements are added +var ol = document.createElement("ol"); +var li = document.createElement("li"); +li.value = 42; +ol.appendChild(li); +is(ol.start, 1, "ol.start with one li child, li.value = 42:"); +li.value = -42; +is(ol.start, 1, "ol.start with one li child, li.value = 42:"); +ol.removeAttribute("start"); +li.removeAttribute("value"); +ol.appendChild(document.createElement("li")); +ol.reversed = true; +todo_is(ol.start, 2, "ol.start with two li children, ol.reversed == true:"); +li.value = 42; +todo_is(ol.start, 2, "ol.start with two li childern, ol.reversed == true:"); +ol.start = 42; +is(ol.start, 42, "ol.start = 42:"); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_option_defaultSelected.html b/dom/html/test/test_option_defaultSelected.html new file mode 100644 index 000000000..f3994e784 --- /dev/null +++ b/dom/html/test/test_option_defaultSelected.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=927796 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 927796</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=927796">Mozilla Bug 927796</a> +<p id="display"> +<select id="s1"> + <option selected>one</option> + <option>two</option> +</select> +<select id="s2" size="5"> + <option selected>one</option> + <option>two</option> +</select> +</p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> + <script type="application/javascript"> + + /** Test for Bug 927796 **/ + var s1 = $("s1"); + s1.options[0].defaultSelected = false; + is(s1.options[0].selected, true, + "First option in combobox should still be selected"); + is(s1.options[1].selected, false, + "Second option in combobox should not be selected"); + + var s2 = $("s2"); + s2.options[0].defaultSelected = false; + is(s2.options[0].selected, false, + "First option in listbox should not be selected"); + is(s2.options[1].selected, false, + "Second option in listbox should not be selected"); + </script> +</body> +</html> diff --git a/dom/html/test/test_option_selected_state.html b/dom/html/test/test_option_selected_state.html new file mode 100644 index 000000000..ba4a1a330 --- /dev/null +++ b/dom/html/test/test_option_selected_state.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=942648 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 942648</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=942648">Mozilla Bug 942648</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> + <select> + <option value="1">1</option> + <option id="e1" value="2">2</option> + </select> + <select> + <option value="1">1</option> + <option id="e2" selected value="2">2</option> + </select> + <select> + <option value="1">1</option> + <option id="e3" selected="" value="2">2</option> + </select> + <select> + <option value="1">1</option> + <option id="e4" selected="selected" value="2">2</option> + </select> +</pre> + <script type="application/javascript"> + + /** Test for Bug 942648 **/ +SimpleTest.waitForExplicitFinish(); + window.onload = function() { + var e1 = document.getElementById('e1'); + var e2 = document.getElementById('e2'); + var e3 = document.getElementById('e3'); + var e4 = document.getElementById('e4'); + ok(!e1.selected, "e1 should not be selected"); + ok(e2.selected, "e2 should be selected"); + ok(e3.selected, "e3 should be selected"); + ok(e4.selected, "e4 should be selected"); + e1.setAttribute('selected', 'selected'); + e2.setAttribute('selected', 'selected'); + e3.setAttribute('selected', 'selected'); + e4.setAttribute('selected', 'selected'); + ok(e1.selected, "e1 should now be selected"); + ok(e2.selected, "e2 should still be selected"); + ok(e3.selected, "e3 should still be selected"); + ok(e4.selected, "e4 should still be selected"); + SimpleTest.finish(); + }; + </script> +</body> +</html> diff --git a/dom/html/test/test_param_attributes_reflection.html b/dom/html/test/test_param_attributes_reflection.html new file mode 100644 index 000000000..05d7949d5 --- /dev/null +++ b/dom/html/test/test_param_attributes_reflection.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLParamElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLParamElement attributes reflection **/ + +// .name +reflectString({ + element: document.createElement("param"), + attribute: "name", +}); + +// .value +reflectString({ + element: document.createElement("param"), + attribute: "value" +}); + +// .type +reflectString({ + element: document.createElement("param"), + attribute: "type" +}); + +// .valueType +reflectString({ + element: document.createElement("param"), + attribute: "valueType" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_plugin.tst b/dom/html/test/test_plugin.tst new file mode 100644 index 000000000..323fae03f --- /dev/null +++ b/dom/html/test/test_plugin.tst @@ -0,0 +1 @@ +foobar diff --git a/dom/html/test/test_q_attributes_reflection.html b/dom/html/test/test_q_attributes_reflection.html new file mode 100644 index 000000000..ddb6c77d9 --- /dev/null +++ b/dom/html/test/test_q_attributes_reflection.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLQuoteElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLQuoteElement attributes reflection **/ + +// .cite +reflectURL({ + element: document.createElement("q"), + attribute: "cite", +}); + +reflectURL({ + element: document.createElement("blockquote"), + attribute: "cite", +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_restore_from_parser_fragment.html b/dom/html/test/test_restore_from_parser_fragment.html new file mode 100644 index 000000000..119ee2102 --- /dev/null +++ b/dom/html/test/test_restore_from_parser_fragment.html @@ -0,0 +1,59 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=644959 +--> +<head> + <title>Test for Bug 644959</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=644959">Mozilla Bug 644959</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 644959 **/ + +var content = document.getElementById('content'); + +function appendHTML(aParent, aElementString) +{ + aParent.innerHTML = "<form>" + aElementString + "</form>"; +} + +function clearHTML(aParent) +{ + aParent.innerHTML = ""; +} + +var tests = [ + [ "button", "<button></button>" ], + [ "input", "<input>" ], + [ "textarea", "<textarea></textarea>" ], + [ "select", "<select></select>" ], +]; + +var element = null; + +for (var test of tests) { + appendHTML(content, test[1]); + element = content.getElementsByTagName(test[0])[0]; + is(element.disabled, false, "element shouldn't be disabled"); + element.disabled = true; + is(element.disabled, true, "element should be disabled"); + + clearHTML(content); + + appendHTML(content, test[1]); + element = content.getElementsByTagName(test[0])[0]; + is(element.disabled, false, "element shouldn't be disabled"); +} + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_rowscollection.html b/dom/html/test/test_rowscollection.html new file mode 100644 index 000000000..7a726b8a8 --- /dev/null +++ b/dom/html/test/test_rowscollection.html @@ -0,0 +1,69 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=772869 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 772869</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a> +<p id="display"></p> +<div id="content" style="display: none"> + <table id="f"> + <thead> + <tr id="x"></tr> + </thead> + <tfoot> + <tr id="z"></tr> + <tr id="w"></tr> + </tfoot> + <tr id="x"></tr> + <tr id="y"></tr> + <tbody> + <tr id="z"></tr> + </tbody> + </table> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 772869 **/ +var x = $("f").rows; +x.something = "another"; +var names = []; +for (var name in x) { + names.push(name); +} +is(names.length, 10, "Should have 10 enumerated names"); +is(names[0], "0", "Enum entry 1") +is(names[1], "1", "Enum entry 2") +is(names[2], "2", "Enum entry 3") +is(names[3], "3", "Enum entry 4") +is(names[4], "4", "Enum entry 5") +is(names[5], "5", "Enum entry 6") +is(names[6], "something", "Enum entry 7") +is(names[7], "item", "Enum entry 8") +is(names[8], "namedItem", "Enum entry 9") +is(names[9], "length", "Enum entry 10"); + +names = Object.getOwnPropertyNames(x); +is(names.length, 11, "Should have 11 items"); +is(names[0], "0", "Entry 1") +is(names[1], "1", "Entry 2") +is(names[2], "2", "Entry 3") +is(names[3], "3", "Entry 4") +is(names[4], "4", "Entry 5") +is(names[5], "5", "Entry 6") +is(names[6], "x", "Entry 7") +is(names[7], "y", "Entry 8") +is(names[8], "z", "Entry 9") +is(names[9], "w", "Entry 10") +is(names[10], "something", "Entry 11") +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_srcdoc-2.html b/dom/html/test/test_srcdoc-2.html new file mode 100644 index 000000000..4e273473b --- /dev/null +++ b/dom/html/test/test_srcdoc-2.html @@ -0,0 +1,57 @@ +<!doctype html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=802895 +--> + <head> +<title>Test session history for srcdoc iframes introduced in bug 802895</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> + +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=802895">Mozilla Bug 802895</a> + +<iframe id="pframe" name="pframe" src="file_srcdoc-2.html"></iframe> +<pre id="test"> +<script> + + SimpleTest.waitForExplicitFinish(); + var pframe = $("pframe"); + + //disable bfcache + pframe.contentWindow.addEventListener("unload", function () { }, false); + + var loadState = 0; + pframe.onload = function () { + SimpleTest.executeSoon(function () { + + var pDoc = pframe.contentDocument; + + if (loadState == 0) { + var div = pDoc.createElement("div"); + div.id = "modifyCheck"; + div.innerHTML = "hello again"; + pDoc.body.appendChild(div); + ok(pDoc.getElementById("modifyCheck"), "Child element not created"); + pframe.src = "about:blank"; + loadState = 1; + } + else if (loadState == 1) { + loadState = 2; + window.history.back(); + } + else if (loadState == 2) { + ok(!pDoc.getElementById("modifyCheck"), "modifyCheck element shouldn't be present"); + is(pDoc.getElementById("iframe").contentDocument.body.innerHTML, + "Hello World", "srcdoc iframe not present"); + SimpleTest.finish(); + } + + }) + }; + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_srcdoc.html b/dom/html/test/test_srcdoc.html new file mode 100644 index 000000000..f7e48fde9 --- /dev/null +++ b/dom/html/test/test_srcdoc.html @@ -0,0 +1,118 @@ +<!doctype html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=802895 +--> + <head> +<title>Tests for srcdoc iframes introduced in bug 802895</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=802895">Mozilla Bug 802895</a> + +<iframe id="pframe" src="file_srcdoc.html"></iframe> + +<pre id="test"> +<script> + + SimpleTest.waitForExplicitFinish(); + SimpleTest.requestFlakyTimeout("untriaged"); + var pframe = $("pframe"); + + var loadState = 0; + pframe.contentWindow.addEventListener("load", function () { + + var pframeDoc = pframe.contentDocument; + + var iframe = pframeDoc.getElementById("iframe"); + var innerDoc = iframe.contentDocument; + var iframe1 = pframeDoc.getElementById("iframe1"); + var innerDoc1 = iframe1.contentDocument; + + var finish = false; + var finish1 = false; + var finish3 = false; + + + + is(iframe.srcdoc, "Hello World", "Bad srcdoc attribute contents") + + is(innerDoc.domain, document.domain, "Wrong domain"); + is(innerDoc.referrer, pframeDoc.referrer, "Wrong referrer"); + is(innerDoc.body.innerHTML, "Hello World", "Wrong body"); + is(innerDoc.compatMode, "CSS1Compat", "Not standards compliant"); + + is(innerDoc1.domain, document.domain, "Wrong domain with src attribute"); + is(innerDoc1.referrer, pframeDoc.referrer, "Wrong referrer with src attribute"); + is(innerDoc1.body.innerHTML, "Goodbye World", "Wrong body with src attribute") + is(innerDoc1.compatMode, "CSS1Compat", "Not standards compliant with src attribute"); + + var iframe2 = pframeDoc.getElementById("iframe2"); + var innerDoc2 = iframe2.contentDocument; + try { + innerDoc2.domain; + foundError = false; + } + catch (error) { + foundError = true; + } + ok(foundError, "srcdoc iframe not sandboxed"); + + //Test changed srcdoc attribute + iframe.onload = function () { + + iframe = pframeDoc.getElementById("iframe"); + innerDoc = iframe.contentDocument; + + is(iframe.srcdoc, "Hello again", "Bad srcdoc attribute contents with srcdoc attribute changed"); + is(innerDoc.domain, document.domain, "Wrong domain with srcdoc attribute changed"); + is(innerDoc.referrer, pframeDoc.referrer, "Wrong referrer with srcdoc attribute changed"); + is(innerDoc.body.innerHTML, "Hello again", "Wrong body with srcdoc attribute changed"); + is(innerDoc.compatMode, "CSS1Compat", "Not standards compliant with srcdoc attribute changed"); + + finish = true; + if (finish && finish1 && finish3) { + SimpleTest.finish(); + } + }; + + iframe.srcdoc = "Hello again"; + + var iframe3 = pframeDoc.getElementById("iframe3"); + + // Test srcdoc attribute removal + iframe3.onload = function () { + var innerDoc3 = iframe3.contentDocument; + is(innerDoc3.body.innerHTML, "Gone", "Bad srcdoc attribute removal"); + finish3 = true; + if (finish && finish1 && finish3) { + SimpleTest.finish(); + } + } + + iframe3.removeAttribute("srcdoc"); + + + var iframe1load = false; + iframe1.onload = function () { + iframe1load = true; + } + + iframe1.src = "data:text/plain;charset=US-ASCII,Goodbyeeee"; + + // Need to test that changing the src doesn't change the iframe. + setTimeout(function () { + ok(!iframe1load, "Changing src attribute shouldn't cause a load when srcdoc is set"); + finish1 = true; + if (finish && finish1 && finish3) { + SimpleTest.finish(); + } + }, 2000); + + }, false); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_style_attributes_reflection.html b/dom/html/test/test_style_attributes_reflection.html new file mode 100644 index 000000000..c97bc8767 --- /dev/null +++ b/dom/html/test/test_style_attributes_reflection.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> + <title>Test for HTMLStyleElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLStyleElement attributes reflection **/ + +var e = document.createElement("style"); + +// .media +reflectString({ + element: e, + attribute: "media" +}); + +// .type +reflectString({ + element: e, + attribute: "type" +}); + +// .scoped +reflectBoolean({ + element: e, + attribute: "scoped" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_track.html b/dom/html/test/test_track.html new file mode 100644 index 000000000..bc23e4dae --- /dev/null +++ b/dom/html/test/test_track.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=833386 +--> +<head> + <meta charset='utf-8'> + <title>Test for Bug 833386 - HTMLTrackElement</title> + <script type="text/javascript" src="/MochiKit/MochiKit.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/dom/html/test/reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +reflectLimitedEnumerated({ + element: document.createElement("track"), + attribute: "kind", + validValues: ["subtitles", "captions", "descriptions", "chapters", + "metadata"], + invalidValues: ["foo", "bar", "\u0000", "null", "", "subtitle", "caption", + "description", "chapter", "meta"], + defaultValue: { missing: "subtitles", invalid: "metadata" }, +}); + +// Default attribute +reflectBoolean({ + element: document.createElement("track"), + attribute: "default" +}); + +// Label attribute +reflectString({ + element: document.createElement("track"), + attribute: "label", + otherValues: [ "foo", "BAR", "_FoO", "\u0000", "null", "white space" ] +}); + +// Source attribute +reflectURL({ + element: document.createElement("track"), + attribute: "src", + otherValues: ["foo", "bar", "\u0000", "null", ""] +}); + +// Source Language attribute +reflectString({ + element: document.createElement("track"), + attribute: "srclang", + otherValues: ["foo", "bar", "\u0000", "null", ""] +}); + +var track = document.createElement("track"); +is(track.readyState, 0, "Default ready state should be 0 (NONE)."); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_ul_attributes_reflection.html b/dom/html/test/test_ul_attributes_reflection.html new file mode 100644 index 000000000..7696a4f9f --- /dev/null +++ b/dom/html/test/test_ul_attributes_reflection.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for HTMLUListElement attributes reflection</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for HTMLUListElement attributes reflection **/ + +// .compact +reflectBoolean({ + element: document.createElement("ul"), + attribute: "compact" +}); + +// .type +reflectString({ + element: document.createElement("ul"), + attribute: "type" +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_video_wakelock.html b/dom/html/test/test_video_wakelock.html new file mode 100644 index 000000000..52b05cda4 --- /dev/null +++ b/dom/html/test/test_video_wakelock.html @@ -0,0 +1,198 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=868943 +--> +<head> + <title>Test for Bug 868943</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=868943">Mozilla Bug 868943</a> +<p id="display"></p> +<div id="content"> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 868943 **/ + +function testVideoPlayPause() { + info("#1 testVideoPlayPause"); + + var lockState_cpu = true; + var lockState_screen = true; + var count_cpu = 0; + var count_screen = 0; + + var content = document.getElementById('content'); + + var video = document.createElement('video'); + ok(video.mozUseScreenWakeLock, "#1 Video element uses screen wake lock by default"); + video.src = "wakelock.ogv"; + content.appendChild(video); + + var startDate; + function testVideoPlayPauseListener(topic, state) { + info("#1 topic=" + topic + ", state=" + state); + + var locked = state == "locked-foreground" || + state == "locked-background"; + + if (topic == "cpu") { + is(locked, lockState_cpu, "#1 Video element locked the cpu"); + count_cpu++; + } else if (topic == "screen") { + is(locked, lockState_screen, "#1 Video element locked the screen"); + count_screen++; + } + + if (count_cpu == 1 && count_screen == 1) { + info("#1 Both cpu and screen are locked"); + // The next step is to unlock the resource. + lockState_cpu = false; + lockState_screen = false; + video.pause(); + startDate = new Date(); + } + + if (count_cpu == 2 && count_screen == 2) { + var diffDate = (new Date() - startDate); + ok(diffDate > 200, "#1 There was at least 200 milliseconds between the stop and the wakelock release"); + + content.removeChild(video); + navigator.mozPower.removeWakeLockListener(testVideoPlayPauseListener); + runTests(); + } + } + + navigator.mozPower.addWakeLockListener(testVideoPlayPauseListener); + video.play(); +} + +function testVideoPlay() { + info("#2 testVideoPlay"); + + var lockState_cpu = true; + var lockState_screen = true; + var count_cpu = 0; + var count_screen = 0; + + var content = document.getElementById('content'); + + var video = document.createElement('video'); + ok(video.mozUseScreenWakeLock, "#2 Video element uses screen wake lock by default"); + video.src = "wakelock.ogv"; + content.appendChild(video); + + var startDate; + video.addEventListener('progress', function() { + startDate = new Date(); + }); + + function testVideoPlayListener(topic, state) { + info("#2 topic=" + topic + ", state=" + state); + + var locked = state == "locked-foreground" || + state == "locked-background"; + + if (topic == "cpu") { + is(locked, lockState_cpu, "#2 Video element locked the cpu"); + count_cpu++; + } else if (topic == "screen") { + is(locked, lockState_screen, "#2 Video element locked the screen"); + count_screen++; + } + + if (count_cpu == 1 && count_screen == 1) { + info("#2 Both cpu and screen are locked"); + // The next step is to unlock the resource. + lockState_cpu = false; + lockState_screen = false; + } else if (count_cpu == 2 && count_screen == 2) { + var diffDate = (new Date() - startDate); + ok(diffDate > 200, "#2 There was at least milliseconds between the stop and the wakelock release"); + + content.removeChild(video); + navigator.mozPower.removeWakeLockListener(testVideoPlayListener); + runTests(); + } + } + + navigator.mozPower.addWakeLockListener(testVideoPlayListener); + video.play(); +} + +function testVideoNoScreenWakeLock() { + info("#3 testVideoNoScreenWakeLock"); + + var lockState_cpu = true; + var lockState_screen = false; + var count_cpu = 0; + + var content = document.getElementById('content'); + + var video = document.createElement('video'); + video.mozUseScreenWakeLock = false; + video.src = "wakelock.ogv"; + content.appendChild(video); + + var startDate; + function testVideoNoScreenWakeLockListener(topic, state) { + info("#3 topic=" + topic + ", state=" + state); + + var locked = state == "locked-foreground" || + state == "locked-background"; + + if (topic == "cpu") { + is(locked, lockState_cpu, "#3 Video element locked the cpu"); + count_cpu++; + } else if (topic == "screen") { + is(locked, lockState_screen, "#3 Video element locked the screen"); + } + + if (count_cpu == 1) { + info("#3 Cpu is locked"); + // The next step is to unlock the resource. + lockState_cpu = false; + video.pause(); + startDate = new Date(); + } + + if (count_cpu == 2) { + var diffDate = (new Date() - startDate); + ok(diffDate > 200, "#3 There was at least 200 milliseconds between the stop and the wakelock release"); + + content.removeChild(video); + navigator.mozPower.removeWakeLockListener(testVideoNoScreenWakeLockListener); + runTests(); + } + } + + navigator.mozPower.addWakeLockListener(testVideoNoScreenWakeLockListener); + video.play(); +} + +var tests = [ testVideoPlayPause, testVideoPlay, testVideoNoScreenWakeLock ]; +function runTests() { + if (!tests.length) { + SimpleTest.finish(); + return; + } + + var test = tests.pop(); + test(); +}; + +SpecialPowers.pushPrefEnv({"set": [["media.wakelock_timeout", 500], + ["dom.wakelock.enabled", true]]}, runTests); + +SimpleTest.waitForExplicitFinish(); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_viewport.html b/dom/html/test/test_viewport.html new file mode 100644 index 000000000..2299bef3d --- /dev/null +++ b/dom/html/test/test_viewport.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=436083 +--> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="height=398, width=4224, minimum-scale=0.1, + initial-scale=2.3, maximum-scale=45.2, user-scalable=no"> + <title>Test for Viewport META Tag Parsing</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" +href="https://bugzilla.mozilla.org/show_bug.cgi?id=436083">Mozilla Bug 436083</a> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Viewport META Tag **/ + +SimpleTest.waitForExplicitFinish(); + +function testViewport() { + + /* We need to access the document headers, which are chrome-only. */ + + /* Grab Viewport Metadata from the document header. */ + var windowUtils = SpecialPowers.getDOMWindowUtils(window); + var vpWidth = + parseInt(windowUtils.getDocumentMetadata("viewport-width")); + var vpHeight = + parseInt(windowUtils.getDocumentMetadata("viewport-height")); + var vpInitialScale = + parseFloat(windowUtils.getDocumentMetadata("viewport-initial-scale")); + var vpMaxScale = + parseFloat(windowUtils.getDocumentMetadata("viewport-maximum-scale")); + var vpMinScale = + parseFloat(windowUtils.getDocumentMetadata("viewport-minimum-scale")); + var vpUserScalable = + windowUtils.getDocumentMetadata("viewport-user-scalable"); + + is(vpWidth, 4224, "Should get proper width"); + is(vpHeight, 398, "Should get proper height"); + is(vpInitialScale, 2.3, "Should get proper initial scale"); + is(vpMaxScale, 45.2, "Should get proper max scale"); + is(vpMinScale, 0.1, "Should get proper min scale"); + is(vpUserScalable, "no", "Should get proper user scalable parameter"); +} + +addLoadEvent(testViewport); +addLoadEvent(SimpleTest.finish); + +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_viewport_resize.html b/dom/html/test/test_viewport_resize.html new file mode 100644 index 000000000..711d2afa0 --- /dev/null +++ b/dom/html/test/test_viewport_resize.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1135812 +--> +<head> + <title>Test for Bug 1135812</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1135812">Mozilla Bug 1135812</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> + +<iframe style="width: 50px;" + srcdoc='<picture><source srcset="data:,a" media="(min-width: 150px)" /><source srcset="data:,b" media="(min-width: 100px)" /><img src="data:,c" /></picture>'></iframe> +<script> + SimpleTest.waitForExplicitFinish(); + addEventListener('load', function() { + var iframe = document.querySelector('iframe'); + var img = iframe.contentDocument.querySelector('img'); + is(img.currentSrc, 'data:,c'); + + img.onload = function() { + is(img.currentSrc, 'data:,a'); + img.onload = function() { + is(img.currentSrc, 'data:,b'); + SimpleTest.finish(); + } + img.onerror = img.onload; + iframe.style.width = '120px'; + }; + img.onerror = img.onload; + + iframe.style.width = '200px'; + }, true); +</script> +</pre> +</body> +</html> diff --git a/dom/html/test/test_window_open_close.html b/dom/html/test/test_window_open_close.html new file mode 100644 index 000000000..c7e3b96f5 --- /dev/null +++ b/dom/html/test/test_window_open_close.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); + +// Opens a popup. Link should load in main browser window. Popup should be closed when link clicked. +function openWindow1() { + return window.open('file_window_open_close_outer.html','','width=300,height=200'); +} + +// Opens a new tab T1. Link opens in another new tab T2. T1 should close when link clicked. +function openWindow2() { + return window.open('file_window_open_close_outer.html'); +} + +// Opens a new window. Link should open in a new tab of that window, but then both windows should close. +function openWindow3() { + return window.open('file_window_open_close_outer.html', '', 'toolbar=1'); +} + +var TESTS = [openWindow1, openWindow2, openWindow3]; + +function popupLoad(win) +{ + info("Sending click"); + sendMouseEvent({type: "click"}, "link", win); + ok(true, "Didn't crash"); + + next(); +} + +function next() +{ + if (TESTS.length == 0) { + SimpleTest.finish(); + } else { + var test = TESTS.shift(); + var w = test(); + w.addEventListener("load", (e) => popupLoad(w)); + } +} +</script> + +<body onload="next()"> +</body> +</html> diff --git a/dom/html/test/wakelock.ogg b/dom/html/test/wakelock.ogg Binary files differnew file mode 100644 index 000000000..d7f6a0ccf --- /dev/null +++ b/dom/html/test/wakelock.ogg diff --git a/dom/html/test/wakelock.ogv b/dom/html/test/wakelock.ogv Binary files differnew file mode 100644 index 000000000..093158432 --- /dev/null +++ b/dom/html/test/wakelock.ogv |