| <!doctype html> | |
| <title>Range.compareBoundaryPoints() tests</title> | |
| <link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name> | |
| <meta name=timeout content=long> | |
| <div id=log></div> | |
| <script src=/resources/testharness.js></script> | |
| <script src=/resources/testharnessreport.js></script> | |
| <script src=../common.js></script> | |
| <script> | |
| "use strict"; | |
| var testRangesCached = []; | |
| testRangesCached.push(document.createRange()); | |
| testRangesCached[0].detach(); | |
| for (var i = 0; i < testRangesShort.length; i++) { | |
| try { | |
| testRangesCached.push(rangeFromEndpoints(eval(testRangesShort[i]))); | |
| } catch(e) { | |
| testRangesCached.push(null); | |
| } | |
| } | |
| var testRangesCachedClones = []; | |
| testRangesCachedClones.push(document.createRange()); | |
| testRangesCachedClones[0].detach(); | |
| for (var i = 1; i < testRangesCached.length; i++) { | |
| if (testRangesCached[i]) { | |
| testRangesCachedClones.push(testRangesCached[i].cloneRange()); | |
| } else { | |
| testRangesCachedClones.push(null); | |
| } | |
| } | |
| // We want to run a whole bunch of extra tests with invalid "how" values (not | |
| // 0-3), but it's excessive to run them for every single pair of ranges -- | |
| // there are too many of them. So just run them for a handful of the tests. | |
| var extraTests = [0, // detached | |
| 1 + testRanges.indexOf("[paras[0].firstChild, 2, paras[0].firstChild, 8]"), | |
| 1 + testRanges.indexOf("[paras[0].firstChild, 3, paras[3], 1]"), | |
| 1 + testRanges.indexOf("[testDiv, 0, comment, 5]"), | |
| 1 + testRanges.indexOf("[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]")]; | |
| for (var i = 0; i < testRangesCached.length; i++) { | |
| var range1 = testRangesCached[i]; | |
| var range1Desc = i + " " + (i == 0 ? "[detached]" : testRanges[i - 1]); | |
| for (var j = 0; j <= testRangesCachedClones.length; j++) { | |
| var range2; | |
| var range2Desc; | |
| if (j == testRangesCachedClones.length) { | |
| range2 = range1; | |
| range2Desc = "same as first range"; | |
| } else { | |
| range2 = testRangesCachedClones[j]; | |
| range2Desc = j + " " + (j == 0 ? "[detached]" : testRanges[j - 1]); | |
| } | |
| var hows = [Range.START_TO_START, Range.START_TO_END, Range.END_TO_END, | |
| Range.END_TO_START]; | |
| if (extraTests.indexOf(i) != -1 && extraTests.indexOf(j) != -1) { | |
| // TODO: Make some type of reusable utility function to do this | |
| // work. | |
| hows.push(-1, 4, 5, NaN, -0, +Infinity, -Infinity); | |
| [65536, -65536, 65536*65536, 0.5, -0.5, -72.5].forEach(function(addend) { | |
| hows.push(-1 + addend, 0 + addend, 1 + addend, | |
| 2 + addend, 3 + addend, 4 + addend); | |
| }); | |
| hows.forEach(function(how) { hows.push(String(how)) }); | |
| hows.push("6.5536e4", null, undefined, true, false, "", "quasit"); | |
| } | |
| for (var k = 0; k < hows.length; k++) { | |
| var how = hows[k]; | |
| test(function() { | |
| assert_not_equals(range1, null, | |
| "Creating context range threw an exception"); | |
| assert_not_equals(range2, null, | |
| "Creating argument range threw an exception"); | |
| // Convert how per WebIDL. TODO: Make some type of reusable | |
| // utility function to do this work. | |
| // "Let number be the result of calling ToNumber on the input | |
| // argument." | |
| var convertedHow = Number(how); | |
| // "If number is NaN, +0, −0, +∞, or −∞, return +0." | |
| if (isNaN(convertedHow) | |
| || convertedHow == 0 | |
| || convertedHow == Infinity | |
| || convertedHow == -Infinity) { | |
| convertedHow = 0; | |
| } else { | |
| // "Let posInt be sign(number) * floor(abs(number))." | |
| var posInt = (convertedHow < 0 ? -1 : 1) * Math.floor(Math.abs(convertedHow)); | |
| // "Let int16bit be posInt modulo 2^16; that is, a finite | |
| // integer value k of Number type with positive sign and | |
| // less than 2^16 in magnitude such that the mathematical | |
| // difference of posInt and k is mathematically an integer | |
| // multiple of 2^16." | |
| // | |
| // "Return int16bit." | |
| convertedHow = posInt % 65536; | |
| if (convertedHow < 0) { | |
| convertedHow += 65536; | |
| } | |
| } | |
| // Now to the actual algorithm. | |
| // "If how is not one of | |
| // START_TO_START, | |
| // START_TO_END, | |
| // END_TO_END, and | |
| // END_TO_START, | |
| // throw a "NotSupportedError" exception and terminate these | |
| // steps." | |
| if (convertedHow != Range.START_TO_START | |
| && convertedHow != Range.START_TO_END | |
| && convertedHow != Range.END_TO_END | |
| && convertedHow != Range.END_TO_START) { | |
| assert_throws("NOT_SUPPORTED_ERR", function() { | |
| range1.compareBoundaryPoints(how, range2); | |
| }, "NotSupportedError required if first parameter doesn't convert to 0-3 per WebIDL"); | |
| return; | |
| } | |
| // "If context object's root is not the same as sourceRange's | |
| // root, throw a "WrongDocumentError" exception and terminate | |
| // these steps." | |
| if (furthestAncestor(range1.startContainer) != furthestAncestor(range2.startContainer)) { | |
| assert_throws("WRONG_DOCUMENT_ERR", function() { | |
| range1.compareBoundaryPoints(how, range2); | |
| }, "WrongDocumentError required if the ranges don't share a root"); | |
| return; | |
| } | |
| // "If how is: | |
| // START_TO_START: | |
| // Let this point be the context object's start. | |
| // Let other point be sourceRange's start. | |
| // START_TO_END: | |
| // Let this point be the context object's end. | |
| // Let other point be sourceRange's start. | |
| // END_TO_END: | |
| // Let this point be the context object's end. | |
| // Let other point be sourceRange's end. | |
| // END_TO_START: | |
| // Let this point be the context object's start. | |
| // Let other point be sourceRange's end." | |
| var thisPoint = convertedHow == Range.START_TO_START || convertedHow == Range.END_TO_START | |
| ? [range1.startContainer, range1.startOffset] | |
| : [range1.endContainer, range1.endOffset]; | |
| var otherPoint = convertedHow == Range.START_TO_START || convertedHow == Range.START_TO_END | |
| ? [range2.startContainer, range2.startOffset] | |
| : [range2.endContainer, range2.endOffset]; | |
| // "If the position of this point relative to other point is | |
| // before | |
| // Return −1. | |
| // equal | |
| // Return 0. | |
| // after | |
| // Return 1." | |
| var position = getPosition(thisPoint[0], thisPoint[1], otherPoint[0], otherPoint[1]); | |
| var expected; | |
| if (position == "before") { | |
| expected = -1; | |
| } else if (position == "equal") { | |
| expected = 0; | |
| } else if (position == "after") { | |
| expected = 1; | |
| } | |
| assert_equals(range1.compareBoundaryPoints(how, range2), expected, | |
| "Wrong return value"); | |
| }, i + "," + j + "," + k + ": context range " + range1Desc + ", argument range " + range2Desc + ", how " + format_value(how)); | |
| } | |
| } | |
| } | |
| testDiv.style.display = "none"; | |
| </script> |