blob: 09fbc0ae81b328ba5bb3fd2399335ba0ef9434c4 [file] [log] [blame]
<!DOCTYPE html>
<html>
<!--
Copyright 2009 Google Inc. All Rights Reserved.
Use of this source code is governed by an Apache 2.0 License.
See the COPYING file for details.
-->
<!--
Unit tests for domwalker.js.
-->
<head>
<title>bidichecker - Javascript Unit Tests</title>
<script type="text/javascript" src="../third_party/closure-library/closure/goog/base.js">
</script>
<!-- Include the generated deps.js which enables goog.require of
the modules under test.
-->
<script type="text/javascript" src="deps.js"></script>
<script type="text/javascript" src="testutils.js"></script>
<script type="text/javascript">
// This in turn pulls in the rest of the files.
goog.require('bidichecker.DomWalker');
goog.require('bidichecker.DomWalker.EventTypes');
goog.require('goog.events.EventHandler');
goog.require('goog.testing.jsunit');
</script>
</head>
<body>
<script type="text/javascript">
// Aliases for convenience in unit testing.
var START_TAG = bidichecker.DomWalker.EventTypes.START_TAG;
var END_TAG = bidichecker.DomWalker.EventTypes.END_TAG;
var TEXT_NODE = bidichecker.DomWalker.EventTypes.TEXT_NODE;
var END_OF_DOM = bidichecker.DomWalker.EventTypes.END_OF_DOM;
/**
* Walks the DOM using a {@code bidichecker.DomWalker}, collecting all DOM
* events dispatched along the way.
* @param {!bidichecker.DomWalker} domWalker The DOM walker.
* @return {Array.<!Object>} The sequence of states encountered while walking
* the DOM, each of which is represented by an object with fields indicating
* the state variables: 'type' is the event type string, 'inRtl' is the
* directionality (boolean), 'block' is the current lowest-level enclosing
* block, 'text' (if applicable) is the string contents of a text node,
* 'element' (if applicable) is the DOM element for a start or end tag,
* and 'inDeclaredDir' (if applicable) is the declared-directionality status
* (boolean).
*/
function walkTheDom(domWalker) {
var states = [];
// Listen to all types of DOM events and collect the state of the traversal in
// {@code states}.
var handler = function(event) {
var state = {
type: event.type,
inRtl: domWalker.inRtl(),
block: domWalker.getCurrentBlock()
};
if (event.type == TEXT_NODE) {
state.text = domWalker.getNode().data;
} else if (event.type == START_TAG || event.type == END_TAG) {
state.element = domWalker.getNode();
}
if (domWalker.inDeclaredDir() != undefined) {
state.inDeclaredDir = domWalker.inDeclaredDir();
}
states.push(state);
};
var eventHandler = new goog.events.EventHandler();
eventHandler.listen(domWalker,
[START_TAG, END_TAG, TEXT_NODE, END_OF_DOM],
handler);
domWalker.go();
eventHandler.removeAll();
return states;
}
/**
* Asserts the equality of two sequences of DOM states, as returned by
* {@code walkTheDom()}.
* @param {Array.<!Object>} expected The expected sequence of DOM states.
* @param {Array.<!Object>} actual The actual sequence of DOM states.
*/
function assertStatesEqual(expected, actual) {
// Check the lengths of the arguments.
assertEquals('Expected ' + expected.length + ' elements: [' + expected +
'], ' + 'got ' + actual.length + ' elements: [' + actual + ']',
expected.length, actual.length);
// Compare individual entries by hash equality, which is a shallow equality
// check on the keys and values.
for (var i = 0; i < expected.length; ++i) {
// Warning: borrowing private _displayStringForValue() function from
// closure/testing/asserts.js.
assertHashEquals('Failed assertion in DOM state #' + i + ': Expected ' +
_displayStringForValue(expected[i]) + ', got ' +
_displayStringForValue(actual[i]),
expected[i], actual[i]);
}
}
function testDomWalker_EmptyDiv() {
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
var domWalker = new bidichecker.DomWalker(testDiv);
assertEquals(testDiv, domWalker.getRootBlock());
assertArrayEquals([], domWalker.getFrames());
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_TextNode() {
var testDiv = goog.dom.createDom('div', {'id': 'test'}, 'test');
goog.dom.appendChild(document.body, testDiv);
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: TEXT_NODE, text: 'test',
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_TwoOppositeDirParagraphs() {
// Two paragraphs with opposite directionality tags.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<p dir=\'rtl\'>Shalom!</p><p>Okay?</p>';
var rtlPara = testDiv.firstChild; // <p dir='rtl'>...
var ltrPara = testDiv.childNodes[1]; // <p>Okay?</p>
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: rtlPara,
inRtl: true, inDeclaredDir: true, block: rtlPara},
{type: TEXT_NODE, text: 'Shalom!',
inRtl: true, inDeclaredDir: true, block: rtlPara},
{type: END_TAG, element: rtlPara,
inRtl: true, inDeclaredDir: true, block: rtlPara},
{type: START_TAG, element: ltrPara,
inRtl: false, inDeclaredDir: false, block: ltrPara},
{type: TEXT_NODE, text: 'Okay?',
inRtl: false, inDeclaredDir: false, block: ltrPara},
{type: END_TAG, element: ltrPara,
inRtl: false, inDeclaredDir: false, block: ltrPara},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_DeclaredSameDirParagraphs() {
// Paragraphs have explicit directionality declaration, though they're the
// same as the root element's.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<p dir=\'ltr\'>Shalom!</p><p dir=\'ltr\'>Okay?</p>';
var para1 = testDiv.firstChild; // <p dir='ltr'>Shalom!</p>
var para2 = testDiv.childNodes[1]; // <p dir='ltr'>Okay?</p>
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: para1,
inRtl: false, inDeclaredDir: true, block: para1},
{type: TEXT_NODE, text: 'Shalom!',
inRtl: false, inDeclaredDir: true, block: para1},
{type: END_TAG, element: para1,
inRtl: false, inDeclaredDir: true, block: para1},
{type: START_TAG, element: para2,
inRtl: false, inDeclaredDir: true, block: para2},
{type: TEXT_NODE, text: 'Okay?',
inRtl: false, inDeclaredDir: true, block: para2},
{type: END_TAG, element: para2,
inRtl: false, inDeclaredDir: true, block: para2},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_DeclaredSameDirInBlock() {
// Text elements with the same directionality within the same block,
// but the second has declared directionality.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<p>Shalom! <span dir=\'ltr\'>BACK</span> Okay? </p>';
var para = testDiv.firstChild; // <p>Shalom!...
var span = para.childNodes[1]; // <p dir='ltr'>BACK</p>
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: para,
inRtl: false, inDeclaredDir: false, block: para},
{type: TEXT_NODE, text: 'Shalom! ',
inRtl: false, inDeclaredDir: false, block: para},
{type: START_TAG, element: span,
inRtl: false, inDeclaredDir: true, block: para},
{type: TEXT_NODE, text: 'BACK',
inRtl: false, inDeclaredDir: true, block: para},
{type: END_TAG, element: span,
inRtl: false, inDeclaredDir: true, block: para},
{type: TEXT_NODE, text: ' Okay? ',
inRtl: false, inDeclaredDir: false, block: para},
{type: END_TAG, element: para,
inRtl: false, inDeclaredDir: false, block: para},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_EmbeddedBlockCancelsDeclaredStatus() {
// If a block with declared directionality contains another block inside it,
// we don't consider the outer block's contents to be "declared".
// Note: This DOM must be built with createDom(), since the HTML parser
// inserts unwanted paragraph breaks due to the nested paragraphs.
// The HTML would look like:
// <div id='test'><p dir='ltr'>Shalom<p dir='ltr'>BACK</p>Okay</p></div>
var para1 = goog.dom.createDom('p', {'dir': 'ltr'}, 'BACK');
var para2 = goog.dom.createDom('p', {'dir': 'ltr'}, 'Shalom', para1, 'Okay');
var testDiv = goog.dom.createDom('div', {'id': 'test'}, para2);
goog.dom.appendChild(document.body, testDiv);
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: para2,
inRtl: false, inDeclaredDir: false, block: para2},
{type: TEXT_NODE, text: 'Shalom',
inRtl: false, inDeclaredDir: false, block: para2},
// "inDeclaredDir" is set only for the innermost paragraph.
{type: START_TAG, element: para1,
inRtl: false, inDeclaredDir: true, block: para1},
{type: TEXT_NODE, text: 'BACK',
inRtl: false, inDeclaredDir: true, block: para1},
{type: END_TAG, element: para1,
inRtl: false, inDeclaredDir: true, block: para1},
{type: TEXT_NODE, text: 'Okay',
inRtl: false, inDeclaredDir: false, block: para2},
{type: END_TAG, element: para2,
inRtl: false, inDeclaredDir: false, block: para2},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_EmbeddedBlockCancelsDeclaredStatusViaCss() {
// As above, but with the paragraph directionality declared via CSS, which
// causes a change in the computed directionality.
goog.style.installStyles('.domwalker-test-ltr { direction: ltr }');
// Note: This DOM must be built with createDom(), since the HTML parser
// inserts unwanted paragraph breaks due to the nested paragraphs.
// The HTML would look like:
// <div dir='rtl' id='test'><p class='domwalker-test-ltr'>Shalom
// <p dir='ltr'>BACK</p>Okay</p></div>
var para1 = goog.dom.createDom('p', {'dir': 'ltr'}, 'BACK');
var para2 = goog.dom.createDom('p', {'class': 'domwalker-test-ltr'},
'Shalom', para1, 'Okay');
var testDiv = goog.dom.createDom('div', {'dir': 'rtl', 'id': 'test'}, para2);
goog.dom.appendChild(document.body, testDiv);
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: true, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: para2,
inRtl: false, inDeclaredDir: false, block: para2},
{type: TEXT_NODE, text: 'Shalom',
inRtl: false, inDeclaredDir: false, block: para2},
// "inDeclaredDir" is set only for the innermost paragraph.
{type: START_TAG, element: para1,
inRtl: false, inDeclaredDir: true, block: para1},
{type: TEXT_NODE, text: 'BACK',
inRtl: false, inDeclaredDir: true, block: para1},
{type: END_TAG, element: para1,
inRtl: false, inDeclaredDir: true, block: para1},
{type: TEXT_NODE, text: 'Okay',
inRtl: false, inDeclaredDir: false, block: para2},
{type: END_TAG, element: para2,
inRtl: false, inDeclaredDir: false, block: para2},
{type: END_TAG, element: testDiv,
inRtl: true, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: true, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_BlockChangesAfterExitingEmbeddedBlock() {
var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<div><div dir=\'ltr\'>Shalom</div>Okay</div>';
var parentDiv = testDiv.firstChild; // <div>...
var ltrDiv = parentDiv.firstChild; // <div dir='ltr'>...
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: true, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: parentDiv,
inRtl: true, inDeclaredDir: false, block: parentDiv},
{type: START_TAG, element: ltrDiv,
inRtl: false, inDeclaredDir: true, block: ltrDiv},
{type: TEXT_NODE, text: 'Shalom',
inRtl: false, inDeclaredDir: true, block: ltrDiv},
{type: END_TAG, element: ltrDiv,
inRtl: false, inDeclaredDir: true, block: ltrDiv},
{type: TEXT_NODE, text: 'Okay',
inRtl: true, inDeclaredDir: false, block: parentDiv},
{type: END_TAG, element: parentDiv,
inRtl: true, inDeclaredDir: false, block: parentDiv},
{type: END_TAG, element: testDiv,
inRtl: true, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: true, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_DisplayNoneIsIgnored() {
// All the contents have display:none set.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<p dir=\'rtl\' style=\'display: none\'>Shalom!</p>' +
'<p style=\'display: none\'>Okay?</p>';
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_VisibilityHiddenIsIgnored() {
// All the contents have visibility:hidden set; they should be ignored.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML =
'<p dir=\'rtl\' style=\'visibility: hidden\'>Shalom!<\/p>';
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_VisibilityCollapseIsIgnored() {
// All the contents have visibility:collapse set; they should be ignored.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML =
'<p dir=\'rtl\' style=\'visibility: collapse\'>Shalom!<\/p>';
var para = testDiv.firstChild;
// Some browsers (in particular, IE7) do not support visiblity:collapse; skip
// the test in that case.
if (!para.style.visibility) {
return;
}
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_ScriptAndStyleAreIgnored() {
// <style> shouldn't really appear in the body, but sometimes it does.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<\script dir=\'rtl\'>if (true) x=7;</\script>' +
'<style>A b c d e f g</style>';
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_TextareaContentsAreIgnored() {
// Text nodes inside a <textarea> are not inline with the surrounding text.
// We ignore them completely, instead processing the textarea value property
// (which contains the up-to-date text) in the undeclared field detector.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<textarea>A b c d e f g<\/textarea>';
var textarea = testDiv.firstChild;
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: textarea,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: textarea,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_NoscriptIsIgnored() {
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<noscript><p>In a noscript tag.</p></noscript>';
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
}
function testDomWalker_CanWalkAnIframe() {
// Create an iframe in the document.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<iframe id=\'iframe\'></iframe>';
// For iframes to work, the div must belong to a document.
goog.dom.appendChild(document.body, testDiv);
// Fill the iframe with two "hello world" div's.
var iframe = testDiv.firstChild;
var iframeDoc =
goog.dom.getFrameContentDocument(/** @type {Element} */ (iframe));
iframeDoc.open();
iframeDoc.write('<div id=line1>hello world<\/div>' +
'<div id=line2>hello world<\/div>');
iframeDoc.close();
var iframeRoot = iframeDoc.body;
// Walk the DOM; this should also collect the iframes.
var domWalker = new bidichecker.DomWalker(testDiv);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: START_TAG, element: iframe,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: iframe,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_TAG, element: testDiv,
inRtl: false, inDeclaredDir: false, block: testDiv},
{type: END_OF_DOM, inRtl: false, block: testDiv}
];
assertStatesEqual(expected, states);
assertArrayEquals([iframe], domWalker.getFrames());
// Access the elements for the div's inside the iframe.
var iframeHelper = new goog.dom.DomHelper(iframeDoc);
var line1 = iframeHelper.getElement('line1');
var line2 = iframeHelper.getElement('line2');
// Now walk the DOM for the iframe, with a new DomWalker.
var iframeDomWalker = new bidichecker.DomWalker(iframeRoot);
states = walkTheDom(iframeDomWalker);
expected = [{type: START_TAG, element: iframeRoot,
inRtl: false, inDeclaredDir: false, block: iframeRoot},
{type: START_TAG, element: line1,
inRtl: false, inDeclaredDir: false, block: line1},
{type: TEXT_NODE, text: 'hello world',
inRtl: false, inDeclaredDir: false, block: line1},
{type: END_TAG, element: line1,
inRtl: false, inDeclaredDir: false, block: line1},
{type: START_TAG, element: line2,
inRtl: false, inDeclaredDir: false, block: line2},
{type: TEXT_NODE, text: 'hello world',
inRtl: false, inDeclaredDir: false, block: line2},
{type: END_TAG, element: line2,
inRtl: false, inDeclaredDir: false, block: line2},
{type: END_TAG, element: iframeRoot,
inRtl: false, inDeclaredDir: false, block: iframeRoot},
{type: END_OF_DOM, inRtl: false, block: iframeRoot}
];
assertStatesEqual(expected, states);
assertArrayEquals([], iframeDomWalker.getFrames()); // No nested iframes.
}
function testDomWalker_CanWalkMultipleIframes() {
// This time, there's more than iframe on the page, and there are nested
// iframes too.
// Create two iframes in the document.
var testDiv = goog.dom.createDom('div', {'id': 'test'});
goog.dom.appendChild(document.body, testDiv);
testDiv.innerHTML = '<iframe id=\'iframe1\'><\/iframe>' +
'<iframe id=\'iframe2\'><\/iframe>';
goog.dom.appendChild(document.body, testDiv);
// Fill the first iframe with content.
var iframe1 = testDiv.firstChild;
var iframe1Doc =
goog.dom.getFrameContentDocument(/** @type {Element} */ (iframe1));
iframe1Doc.open();
iframe1Doc.write('<p>hello world<\/p>');
iframe1Doc.close();
var iframe1Root = iframe1Doc.body;
// Fill the second iframe with a nested iframe.
var iframe2 = testDiv.childNodes[1];
var iframe2Doc = goog.dom.getFrameContentDocument(iframe2);
iframe2Doc.open();
iframe2Doc.write('<iframe id=\'iframe_nested\'><\/iframe>');
iframe2Doc.close();
var iframe2Root = iframe2Doc.body;
// Fill the nested iframe with content.
var iframe3 = iframe2Root.firstChild;
var iframe3Doc =
goog.dom.getFrameContentDocument(/** @type {Element} */ (iframe3));
iframe3Doc.open();
iframe3Doc.write('<p id=\'para\'>In a nested iframe!<\/p>');
iframe3Doc.close();
var iframe3Root = iframe3Doc.body;
// Walk the DOM; this should also collect the iframes.
var domWalker = new bidichecker.DomWalker(testDiv);
walkTheDom(domWalker);
// No need to bother testing the state machine here. Just make sure we've
// seen both top-level iframes.
var expectedFrames = [iframe1, iframe2];
assertArrayEquals(expectedFrames, domWalker.getFrames());
// Now walk the DOM for the first iframe, with a new DomWalker. No new iframes
// there.
var iframe1DomWalker = new bidichecker.DomWalker(iframe1Root);
walkTheDom(iframe1DomWalker);
assertArrayEquals([], iframe1DomWalker.getFrames());
// Now walk the DOM for the second iframe, revealing a third, nested, iframe.
// there.
var iframe2DomWalker = new bidichecker.DomWalker(iframe2Root);
walkTheDom(iframe2DomWalker);
assertArrayEquals([iframe3], iframe2DomWalker.getFrames());
// Finally, walk the DOM for the third iframe, with a new DomWalker. No new
// iframes there.
var iframe3DomWalker = new bidichecker.DomWalker(iframe3Root);
var states = walkTheDom(iframe3DomWalker);
assertArrayEquals([], iframe3DomWalker.getFrames());
// This time, we'll also check the DOM in the nested iframe.
var iframeHelper = new goog.dom.DomHelper(iframe3Doc);
var para = iframeHelper.getElement('para');
var expected = [{type: START_TAG, element: iframe3Root,
inRtl: false, inDeclaredDir: false, block: iframe3Root},
{type: START_TAG, element: para,
inRtl: false, inDeclaredDir: false, block: para},
{type: TEXT_NODE, text: 'In a nested iframe!',
inRtl: false, inDeclaredDir: false, block: para},
{type: END_TAG, element: para,
inRtl: false, inDeclaredDir: false, block: para},
{type: END_TAG, element: iframe3Root,
inRtl: false, inDeclaredDir: false, block: iframe3Root},
{type: END_OF_DOM, inRtl: false, block: iframe3Root}
];
assertStatesEqual(expected, states);
}
function testDomWalker_CanWalkAFrameSet() {
// There doesn't seem to be a way to create a frameset using Javascript under
// IE; disable this test.
if (goog.userAgent.IE) {
return;
}
var frameset = goog.dom.createDom('frameset', {'rows': '*,*', 'id': 'test' },
goog.dom.createDom('frame'), goog.dom.createDom('frame'));
document.documentElement.appendChild(frameset);
// Add a paragraph of text to the first frame.
var frame1 = frameset.firstChild;
var frame2 = frameset.childNodes[1];
var frame1Doc =
goog.dom.getFrameContentDocument(/** @type {Element} */ (frame1));
var frame1Root = frame1Doc.body;
frame1Root.appendChild(goog.dom.createDom('p', null, 'testing'));
// Walk the top-level DOM for the frameset.
var domWalker = new bidichecker.DomWalker(frameset);
var states = walkTheDom(domWalker);
var expected = [{type: START_TAG, element: frameset,
inRtl: false, inDeclaredDir: false, block: frameset},
{type: START_TAG, element: frame1,
inRtl: false, inDeclaredDir: false, block: frameset},
{type: END_TAG, element: frame1,
inRtl: false, inDeclaredDir: false, block: frameset},
{type: START_TAG, element: frame2,
inRtl: false, inDeclaredDir: false, block: frameset},
{type: END_TAG, element: frame2,
inRtl: false, inDeclaredDir: false, block: frameset},
{type: END_TAG, element: frameset,
inRtl: false, inDeclaredDir: false, block: frameset},
{type: END_OF_DOM, inRtl: false, block: frameset}
];
assertStatesEqual(expected, states);
assertArrayEquals([frame1, frame2], domWalker.getFrames());
// Now walk the DOM for the first frame, with a new DomWalker.
var frame1DomWalker = new bidichecker.DomWalker(frame1Root);
states = walkTheDom(frame1DomWalker);
var para = frame1Root.firstChild;
expected = [{type: START_TAG, element: frame1Root,
inRtl: false, inDeclaredDir: false, block: frame1Root},
{type: START_TAG, element: para,
inRtl: false, inDeclaredDir: false, block: para},
{type: TEXT_NODE, text: 'testing',
inRtl: false, inDeclaredDir: false, block: para},
{type: END_TAG, element: para,
inRtl: false, inDeclaredDir: false, block: para},
{type: END_TAG, element: frame1Root,
inRtl: false, inDeclaredDir: false, block: frame1Root},
{type: END_OF_DOM, inRtl: false, block: frame1Root}
];
assertStatesEqual(expected, states);
assertArrayEquals([], frame1DomWalker.getFrames());
}
</script>
</body>
</html>