Commit 7979f575 authored by Ian Briggs's avatar Ian Briggs
Browse files

ch9

parent 361a5ec9
......@@ -8,6 +8,7 @@ interaction.
>>> import test
>>> _ = test.socket.patch().start()
>>> _ = test.ssl.patch().start()
>>> test.NORMALIZE_FONT = True
>>> import browser
Note that we aren't mocking `dukpy`. It should just run JavaScript normally!
......@@ -17,25 +18,28 @@ Testing basic <script> support
The browser should download JavaScript code mentioned in a `<script>` tag:
>>> url = 'http://test.test/html'
>>> url2 = 'http://test.test/js'
>>> url = 'http://test.test/chapter9-base/html'
>>> url2 = 'http://test.test/chapter9-base/js'
>>> html_page = "<script src=" + url2 + "></script>"
>>> test.socket.respond(url, b"HTTP/1.0 200 OK\r\n\r\n" + html_page.encode("utf8"))
>>> test.socket.respond(url2, b"HTTP/1.0 200 OK\r\n\r\n")
>>> test.socket.respond_200(url, body=html_page)
>>> test.socket.respond_200(url2, body="")
>>> browser.Browser().load(url)
>>> test.socket.last_request(url2)
b'GET /js HTTP/1.0\r\nHost: test.test\r\n\r\n'
>>> req = test.socket.last_request(url2).decode("utf-8").lower()
>>> req.startswith("get")
True
>>> req.split()[1]
'/chapter9-base/js'
If the script succeeds, the browser prints nothing:
>>> test.socket.respond(url2, b"HTTP/1.0 200 OK\r\n\r\nvar x = 2; x + x")
>>> test.socket.respond_200(url2, body="var x = 2; x + x")
>>> browser.Browser().load(url)
If instead the script crashes, the browser prints an error message:
>>> test.socket.respond(url2, b"HTTP/1.0 200 OK\r\n\r\nthrow Error('Oops');")
>>> test.socket.respond_200(url2, body="throw Error('Oops');")
>>> browser.Browser().load(url) #doctest: +ELLIPSIS
Script http://test.test/js crashed Error: Oops
Script http://test.test/chapter9-base/js crashed Error: Oops
...
Note that in the last test I set the `ELLIPSIS` flag to elide the duktape stack
......@@ -46,33 +50,30 @@ Testing JSContext
For the rest of these tests we're going to use `console.log` for most testing:
>>> script = "console.log('Hello, world!')"
>>> test.socket.respond(url2, b"HTTP/1.0 200 OK\r\n\r\n" + script.encode("utf8"))
>>> test.socket.respond_200(url2, body="console.log('Hello, world!')")
>>> browser.Browser().load(url)
Hello, world!
Note that you can print other data structures as well:
>>> script = "console.log([2, 3, 4])"
>>> test.socket.respond(url2, b"HTTP/1.0 200 OK\r\n\r\n" + script.encode("utf8"))
>>> test.socket.respond_200(url2, body="console.log([2, 3, 4])")
>>> browser.Browser().load(url)
[2, 3, 4]
Let's test that variables work:
>>> script = "var x = 'Hello!'; console.log(x)"
>>> test.socket.respond(url2, b"HTTP/1.0 200 OK\r\n\r\n" + script.encode("utf8"))
>>> test.socket.respond_200(url2, body="var x = 'Hello!'; console.log(x)")
>>> browser.Browser().load(url)
Hello!
Next let's try to do two scripts:
>>> url2 = 'http://test.test/js1'
>>> url3 = 'http://test.test/js2'
>>> url2 = 'http://test.test/chapter9-base/js1'
>>> url3 = 'http://test.test/chapter9-base/js2'
>>> html_page = "<script src=" + url2 + "></script>" + "<script src=" + url3 + "></script>"
>>> test.socket.respond(url, b"HTTP/1.0 200 OK\r\n\r\n" + html_page.encode("utf8"))
>>> test.socket.respond(url2, b"HTTP/1.0 200 OK\r\n\r\nvar x = 'Testing, testing';")
>>> test.socket.respond(url3, b"HTTP/1.0 200 OK\r\n\r\nconsole.log(x);")
>>> test.socket.respond_200(url, body=html_page)
>>> test.socket.respond_200(url2, body="var x = 'Testing, testing';")
>>> test.socket.respond_200(url3, body="console.log(x);")
>>> browser.Browser().load(url)
Testing, testing
......@@ -87,7 +88,7 @@ matching nodes:
... <p id=lorem>Lorem</p>
... <p class=ipsum>Ipsum</p>
... </div>"""
>>> test.socket.respond(url, b"HTTP/1.0 200 OK\r\n\r\n" + page.encode("utf8"))
>>> test.socket.respond_200(url, body=page)
>>> b = browser.Browser()
>>> b.load(url)
>>> js = b.tabs[0].js
......@@ -137,7 +138,7 @@ One annoying thing about `innerHTML` is that, since it is an assignment, it
returns its right hand side. I use `void()` to avoid testing that.
>>> js.run("void(document.querySelectorAll('p')[0].innerHTML" +
... " = 'This is a <b id=new>new</b> element!')")
... " = 'This is a <b id=wen>new</b> element!')")
Once we've changed the page, the browser should rerender:
......@@ -148,14 +149,14 @@ Once we've changed the page, the browser should rerender:
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=73, y=20.25, width=24, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=109, y=20.25, width=12, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=133, y=20.25, width=36, height=12, font=Font size=12 weight=bold slant=roman style=None
TextLayout(x=181, y=20.25, width=96, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=13, y=20.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=20.25, width=24, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=109, y=20.25, width=12, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=133, y=20.25, width=36, height=12, font=Font size=12 weight=bold slant=roman style=None)
TextLayout(x=181, y=20.25, width=96, height=12, font=Font size=12 weight=normal slant=roman style=None)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
TextLayout(x=13, y=35.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=13, y=35.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None)
Note that there's now many `TextLayout`s inside the first `LineLayout`, one per
new word.
......@@ -181,15 +182,15 @@ The page is rerendered again:
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=13, y=20.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
TextLayout(x=13, y=35.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=13, y=35.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None)
Despite this, the old nodes should stick around:
>>> js.run("old_b.getAttribute('id')")
'new'
'wen'
Testing events
==============
......@@ -216,7 +217,7 @@ link, a button, and an input area:
... <input name=input value=hi>
... <button>Submit</button>
... </form>"""
>>> test.socket.respond(url, b"HTTP/1.0 200 OK\r\n\r\n" + page.encode("utf8"))
>>> test.socket.respond_200(url, body=page)
>>> b.load(url)
>>> js = b.tabs[1].js
......@@ -265,8 +266,8 @@ events. The display list gives us coordinates for clicking.
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=85, y=20.25, width=36, height=12, font=Font size=12 weight=normal slant=roman style=None
TextLayout(x=13, y=20.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=85, y=20.25, width=36, height=12, font=Font size=12 weight=normal slant=roman style=None)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
InputLayout(x=13, y=35.25, width=200, height=12)
......@@ -285,7 +286,7 @@ However, we should not have navigated away from the original URL, because we
prevented submission:
>>> b.tabs[1].history[-1]
'http://test.test/html'
'http://test.test/chapter9-base/html'
Similarly, when we clicked on the `input` element its `value` should be cleared,
but when we then typed `t` into it that was cancelled so the value should still
......
......@@ -12,8 +12,8 @@ Implement all three methods.
Extra Requirements
------------------
*
* We will only call `appendChild` and `insertBefore` to add newly created
elements using valid arguments.
Test code
---------
......@@ -23,4 +23,154 @@ Boilerplate.
>>> import test
>>> _ = test.socket.patch().start()
>>> _ = test.ssl.patch().start()
>>> test.NORMALIZE_FONT = True
>>> import browser
Show the page with no content changes by scripts.
>>> web_url = 'http://test.test/chapter9-create-1/html'
>>> html = "<div>Some content</div> <p>More content</p>"
>>> test.socket.respond_200(web_url, body=html)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=30.0)
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=20.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
TextLayout(x=13, y=35.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=35.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
Set up the webpage and script links.
Create a button and add it as a child to the `<body>` at the end.
>>> web_url = 'http://test.test/chapter9-create-2/html'
>>> script_url = 'http://test.test/chapter9-create-2/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div>Some content</div> <p>More content</p>")
>>> test.socket.respond_200(web_url, body=html)
>>> script = """
... new_elt = document.createElement("button");
... my_body = document.querySelectorAll('body')[0];
... my_body.appendChild(new_elt);
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=0)
LineLayout(x=13, y=18, width=774, height=0)
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=20.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
TextLayout(x=13, y=35.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=35.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
BlockLayout(x=13, y=48.0, width=774, height=0)
Create a button and add it inside the `<body>` before the `<div>`
>>> web_url = 'http://test.test/chapter9-create-3/html'
>>> script_url = 'http://test.test/chapter9-create-3/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div>Some content</div> <p>More content</p>")
>>> test.socket.respond_200(web_url, body=html)
>>> script = """
... new_elt = document.createElement("button");
... my_body = document.querySelectorAll('body')[0];
... my_div = document.querySelectorAll('div')[0];
... my_body.insertBefore(new_elt, my_div);
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=0)
LineLayout(x=13, y=18, width=774, height=0)
BlockLayout(x=13, y=18, width=774, height=30.0)
BlockLayout(x=13, y=18, width=774, height=0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=20.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
TextLayout(x=13, y=35.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=35.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
Create a button and add it inside the `<body>` before the `<p>`
>>> web_url = 'http://test.test/chapter9-create-4/html'
>>> script_url = 'http://test.test/chapter9-create-4/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div>Some content</div> <p>More content</p>")
>>> test.socket.respond_200(web_url, body=html)
>>> script = """
... new_elt = document.createElement("button");
... my_body = document.querySelectorAll('body')[0];
... my_p = document.querySelectorAll('p')[0];
... my_body.insertBefore(new_elt, my_p);
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=0)
LineLayout(x=13, y=18, width=774, height=0)
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=20.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
BlockLayout(x=13, y=33.0, width=774, height=0)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
TextLayout(x=13, y=35.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=35.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
Create a button and add it inside the `<body>` at then end of its children
by using `insertBefore` with a reference node of null.
>>> web_url = 'http://test.test/chapter9-create-5/html'
>>> script_url = 'http://test.test/chapter9-create-5/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div>Some content</div> <p>More content</p>")
>>> test.socket.respond_200(web_url, body=html)
>>> script = """
... new_elt = document.createElement("button");
... my_body = document.querySelectorAll('body')[0];
... my_body.insertBefore(new_elt, null);
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=0)
LineLayout(x=13, y=18, width=774, height=0)
BlockLayout(x=13, y=18, width=774, height=30.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=20.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
InlineLayout(x=13, y=33.0, width=774, height=15.0)
LineLayout(x=13, y=33.0, width=774, height=15.0)
TextLayout(x=13, y=35.25, width=48, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=73, y=35.25, width=84, height=12, font=Font size=12 weight=normal slant=roman style=None)
BlockLayout(x=13, y=48.0, width=774, height=0)
......@@ -19,11 +19,6 @@ Double-check that clicking on links still works, and make sure preventDefault
link.
Extra Requirements
------------------
*
Test code
---------
......@@ -32,4 +27,135 @@ Boilerplate.
>>> import test
>>> _ = test.socket.patch().start()
>>> _ = test.ssl.patch().start()
>>> test.NORMALIZE_FONT = True
>>> import browser
Set up the webpage and script links.
>>> web_url = 'http://test.test/chapter9-create-1/html'
>>> script_url = 'http://test.test/chapter9-create-1/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div><form><input name=bubbles value=sugar></form></div>")
>>> test.socket.respond_200(web_url, body=html)
Attach an event listener to each nested element.
Click an show that all event listeners are called in the correct order.
>>> script = """
... document.querySelectorAll('div')[0].addEventListener('click',
... function(e) {
... console.log('div saw a click');
... });
... document.querySelectorAll('form')[0].addEventListener('click',
... function(e) {
... console.log('form saw a click');
... });
... document.querySelectorAll('input')[0].addEventListener('click',
... function(e) {
... console.log('input saw a click');
... });
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> this_browser.handle_click(test.Event(20, 100 + 24))
input saw a click
form saw a click
div saw a click
>>> this_browser.tabs[0].js.run("document.querySelectorAll('input')[0].getAttribute('value')")
''
Setup a new webpage with the same content but a different script.
This time prevent the default in the input.
>>> web_url = 'http://test.test/chapter9-create-2/html'
>>> script_url = 'http://test.test/chapter9-create-2/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div><form><input name=bubbles value=sugar></form></div>")
>>> test.socket.respond_200(web_url, body=html)
>>> script = """
... document.querySelectorAll('div')[0].addEventListener('click',
... function(e) {
... console.log('div saw a click');
... });
... document.querySelectorAll('form')[0].addEventListener('click',
... function(e) {
... console.log('form saw a click');
... });
... document.querySelectorAll('input')[0].addEventListener('click',
... function(e) {
... console.log('input saw a click');
... e.preventDefault();
... });
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> this_browser.handle_click(test.Event(20, 100 + 24))
input saw a click
form saw a click
div saw a click
>>> this_browser.tabs[0].js.run("document.querySelectorAll('input')[0].getAttribute('value')")
'sugar'
Stopping propagation should also work.
>>> web_url = 'http://test.test/chapter9-create-3/html'
>>> script_url = 'http://test.test/chapter9-create-3/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div><form><input name=bubbles value=sugar></form></div>")
>>> test.socket.respond_200(web_url, body=html)
>>> script = """
... document.querySelectorAll('div')[0].addEventListener('click',
... function(e) {
... console.log('div saw a click');
... });
... document.querySelectorAll('form')[0].addEventListener('click',
... function(e) {
... console.log('form saw a click');
... e.stopPropagation();
... });
... document.querySelectorAll('input')[0].addEventListener('click',
... function(e) {
... console.log('input saw a click');
... });
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> this_browser.handle_click(test.Event(20, 100 + 24))
input saw a click
form saw a click
>>> this_browser.tabs[0].js.run("document.querySelectorAll('input')[0].getAttribute('value')")
''
Both should be able to work on the same click.
>>> web_url = 'http://test.test/chapter9-create-3/html'
>>> script_url = 'http://test.test/chapter9-create-3/js'
>>> html = ("<script src=" + script_url + "></script>"
... + "<div><form><input name=bubbles value=sugar></form></div>")
>>> test.socket.respond_200(web_url, body=html)
>>> script = """
... document.querySelectorAll('div')[0].addEventListener('click',
... function(e) {
... console.log('div saw a click');
... });
... document.querySelectorAll('form')[0].addEventListener('click',
... function(e) {
... console.log('form saw a click');
... });
... document.querySelectorAll('input')[0].addEventListener('click',
... function(e) {
... console.log('input saw a click');
... e.preventDefault();
... e.stopPropagation();
... });
... """
>>> test.socket.respond_200(script_url, body=script)
>>> this_browser = browser.Browser()
>>> this_browser.load(web_url)
>>> this_browser.handle_click(test.Event(20, 100 + 24))
input saw a click
>>> this_browser.tabs[0].js.run("document.querySelectorAll('input')[0].getAttribute('value')")
'sugar'
......@@ -27,3 +27,113 @@ Boilerplate.
>>> _ = test.socket.patch().start()
>>> _ = test.ssl.patch().start()
>>> import browser
After parse html, start js context, run runtime, before scripts
for elt in ....
self.js.run('{elt.id} = new Node({handle});')
Dealing with add/remove node
before remove check all elts and delete
have func that is find ids
promise no id collisions
>>> url = 'http://test.test/chapter9-ids-1/html'
>>> html = "<div id=alice><div>"
>>> test.socket.respond_200(url, html)
>>> this_browser = browser.Browser()
>>> this_browser.load(url)
>>> js = this_browser.tabs[0].js
Check that the id from the page was added to the js environment.
>>> js.run("alice;")
{'handle': 0}
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=0)
BlockLayout(x=13, y=18, width=774, height=0)
BlockLayout(x=13, y=18, width=774, height=0)
BlockLayout(x=13, y=18, width=774, height=0)
Modify the page but do not add an id.
>>> js.run("void(alice.innerHTML" +
... " = '<b>No</b> new ids added')")
>>> js.run("alice;")
{'handle': 0}
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=15.0)
BlockLayout(x=13, y=18, width=774, height=15.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=24, height=12, font=Font size=12 weight=bold slant=roman style=None)
TextLayout(x=49, y=20.25, width=36, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=97, y=20.25, width=36, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=145, y=20.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None)
Replace that content with something that has an id.
>>> js.run("void(alice.innerHTML" +
... " = '<b id=one>One</b> new id added')")
>>> js.run("alice;")
{'handle': 0}
>>> js.run("one;")
{'handle': 1}
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=15.0)
BlockLayout(x=13, y=18, width=774, height=15.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=36, height=12, font=Font size=12 weight=bold slant=roman style=None)
TextLayout(x=61, y=20.25, width=36, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=109, y=20.25, width=24, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=145, y=20.25, width=60, height=12, font=Font size=12 weight=normal slant=roman style=None)
Replace the id with something that has a different id.
>>> js.run("void(alice.innerHTML" +
... " = '<p id=replacement>Id was replaced</p>')")
>>> js.run("alice;")
{'handle': 0}
>>> test.errors(js.run, "one;")
True
>>> js.run("replacement;")
{'handle': 2}
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=15.0)
BlockLayout(x=13, y=18, width=774, height=15.0)
BlockLayout(x=13, y=18, width=774, height=15.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=24, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=49, y=20.25, width=36, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=97, y=20.25, width=96, height=12, font=Font size=12 weight=normal slant=roman style=None)
Empty the document of ids.
>>> js.run("void(document.querySelectorAll('body')[0].innerHTML" +
... " = 'No ids')")
>>> test.errors(js.run, "alice;")
True
>>> test.errors(js.run, "one;")
True
>>> test.errors(js.run, "replacement;")
True
>>> browser.print_tree(this_browser.tabs[0].document)
DocumentLayout()
BlockLayout(x=13, y=18, width=774, height=15.0)
InlineLayout(x=13, y=18, width=774, height=15.0)
LineLayout(x=13, y=18, width=774, height=15.0)
TextLayout(x=13, y=20.25, width=24, height=12, font=Font size=12 weight=normal slant=roman style=None)
TextLayout(x=49, y=20.25, width=36, height=12, font=Font size=12 weight=normal slant=roman style=None)
......@@ -9,11 +9,6 @@ Node.children returns the immediate Element children of a node, as an array.
Text children are not included.
Extra Requirements
------------------
*
Test code
---------
......@@ -23,3 +18,33 @@ Boilerplate.
>>> _ = test.socket.patch().start()
>>> _ = test.ssl.patch().start()
>>> import browser
Setup page and grab the javascript runtime.
>>> url = 'http://test.test/chapter9-children/html'
>>> page = """<!doctype html>
... <p id=lorem>Lorem</p>
... <p class=ipsum>Ipsum</p>"""
>>> test.socket.respond_200(url, body=page)
>>> b = browser.Browser()
>>> b.load(url)
>>> js = b.tabs[0].js
Look at the contents of the body.
>>> js.run("void(bdy_chld = document.querySelectorAll('body')[0].children)")
>>> js.run("bdy_chld.length")