mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add tests for CFI round-tripping
This commit is contained in:
parent
8648e3ff2f
commit
7c9cafc63f
@ -136,7 +136,9 @@ def encode(doc, node, offset, tail): # {{{
|
|||||||
# Handle the offset, if any
|
# Handle the offset, if any
|
||||||
if node.nodeType is Node.ELEMENT_NODE:
|
if node.nodeType is Node.ELEMENT_NODE:
|
||||||
if jstype(offset) is 'number':
|
if jstype(offset) is 'number':
|
||||||
node = node.childNodes.item(offset)
|
q = node.childNodes.item(offset)
|
||||||
|
if q and q.nodeType is Node.ELEMENT_NODE:
|
||||||
|
node = q
|
||||||
elif Node.TEXT_NODE <= node.nodeType <= Node.ENTITY_NODE:
|
elif Node.TEXT_NODE <= node.nodeType <= Node.ENTITY_NODE:
|
||||||
offset = offset or 0
|
offset = offset or 0
|
||||||
while True:
|
while True:
|
||||||
@ -212,7 +214,7 @@ def decode(cfi, doc): # {{{
|
|||||||
cfi = cfi.substr(r[0].length)
|
cfi = cfi.substr(r[0].length)
|
||||||
break
|
break
|
||||||
index |= 1 # Increment index by 1 if it is even
|
index |= 1 # Increment index by 1 if it is even
|
||||||
if child.nodeType is 1:
|
if child.nodeType is Node.ELEMENT_NODE:
|
||||||
index += 1
|
index += 1
|
||||||
if index is target:
|
if index is target:
|
||||||
cfi = cfi.substr(r[0].length)
|
cfi = cfi.substr(r[0].length)
|
||||||
@ -276,8 +278,6 @@ def decode(cfi, doc): # {{{
|
|||||||
# TODO: Handle text assertion
|
# TODO: Handle text assertion
|
||||||
|
|
||||||
# Find the text node that contains the offset
|
# Find the text node that contains the offset
|
||||||
if node and node.parentNode:
|
|
||||||
node.parentNode.normalize()
|
|
||||||
if offset is not None:
|
if offset is not None:
|
||||||
while True:
|
while True:
|
||||||
l = node.nodeValue.length
|
l = node.nodeValue.length
|
||||||
|
@ -2,11 +2,46 @@
|
|||||||
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
from __python__ import bound_methods, hash_literals
|
from __python__ import bound_methods, hash_literals
|
||||||
|
|
||||||
from read_book.cfi import escape_for_cfi, unescape_from_cfi
|
from elementmaker import E
|
||||||
from testing import test, assert_equal
|
|
||||||
|
from read_book.cfi import encode, decode, escape_for_cfi, unescape_from_cfi
|
||||||
|
from testing import assert_equal, test
|
||||||
|
|
||||||
|
|
||||||
@test
|
@test
|
||||||
def cfi_escaping():
|
def cfi_escaping():
|
||||||
t = 'a^!,1'
|
t = 'a^!,1'
|
||||||
assert_equal(t, unescape_from_cfi(escape_for_cfi(t)))
|
assert_equal(t, unescape_from_cfi(escape_for_cfi(t)))
|
||||||
|
|
||||||
|
|
||||||
|
@test
|
||||||
|
def cfi_roundtripping():
|
||||||
|
idc = 0
|
||||||
|
def nid():
|
||||||
|
nonlocal idc
|
||||||
|
idc += 1
|
||||||
|
return idc + ''
|
||||||
|
|
||||||
|
document.body.appendChild(E.p('abc'))
|
||||||
|
p = document.body.firstChild
|
||||||
|
path_to_p = '/2/4/2'
|
||||||
|
assert_equal(encode(document, p), path_to_p)
|
||||||
|
assert_equal(decode(path_to_p), {'node': p})
|
||||||
|
|
||||||
|
assert_equal(encode(document, p.firstChild), f'{path_to_p}/1:0')
|
||||||
|
assert_equal(decode(f'{path_to_p}/1:0'), {'node': p.firstChild, 'offset': 0})
|
||||||
|
|
||||||
|
assert_equal(encode(document, p.firstChild, 1), f'{path_to_p}/1:1')
|
||||||
|
assert_equal(decode(f'{path_to_p}/1:1'), {'node': p.firstChild, 'offset': 1})
|
||||||
|
|
||||||
|
p.appendChild(document.createTextNode('def'))
|
||||||
|
assert_equal(encode(document, p.firstChild, 5), f'{path_to_p}/1:5')
|
||||||
|
assert_equal(p.childNodes.length, 2)
|
||||||
|
assert_equal(encode(document, p.lastChild, 1), f'{path_to_p}/1:4')
|
||||||
|
assert_equal(decode(f'{path_to_p}/1:5'), {'node': p.lastChild, 'offset': 2})
|
||||||
|
assert_equal(decode(f'{path_to_p}/1:1'), {'node': p.firstChild, 'offset': 1})
|
||||||
|
|
||||||
|
p.appendChild(E.span('123', id=nid()))
|
||||||
|
p.appendChild(document.createTextNode('456'))
|
||||||
|
assert_equal(encode(document, p.lastChild, 1), f'{path_to_p}/1:7')
|
||||||
|
assert_equal(decode(f'{path_to_p}/1:7'), {'node': p.lastChild, 'offset': 1})
|
||||||
|
@ -25,8 +25,8 @@ def get_traceback(lines):
|
|||||||
lines = traceback.format_exception()
|
lines = traceback.format_exception()
|
||||||
last_line = lines[-1]
|
last_line = lines[-1]
|
||||||
final_lines = v'[]'
|
final_lines = v'[]'
|
||||||
pat = /at assert_\w+ \(/
|
pat = /at assert_[0-9a-zA-Z_]+ \(/
|
||||||
for line in lines:
|
for line in lines[:-1]:
|
||||||
if pat.test(line):
|
if pat.test(line):
|
||||||
break
|
break
|
||||||
final_lines.push(line)
|
final_lines.push(line)
|
||||||
|
@ -14,10 +14,21 @@ def raise_fail(preamble, msg, call_site):
|
|||||||
raise AssertionError(preamble + msg)
|
raise AssertionError(preamble + msg)
|
||||||
|
|
||||||
|
|
||||||
|
def repr_of(a):
|
||||||
|
if not a:
|
||||||
|
return a
|
||||||
|
q = a.outerHTML
|
||||||
|
if q:
|
||||||
|
return q.split('>')[0] + '>'
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
def assert_equal(a, b, msg, call_site=None):
|
def assert_equal(a, b, msg, call_site=None):
|
||||||
|
|
||||||
def fail():
|
def fail():
|
||||||
p = f'{a} != {b}'
|
ra = repr_of(a)
|
||||||
|
rb = repr_of(b)
|
||||||
|
p = f'{ra} != {rb}'
|
||||||
raise_fail(p, msg, call_site)
|
raise_fail(p, msg, call_site)
|
||||||
|
|
||||||
atype = jstype(a)
|
atype = jstype(a)
|
||||||
@ -31,10 +42,18 @@ def assert_equal(a, b, msg, call_site=None):
|
|||||||
if not a.__eq__(b):
|
if not a.__eq__(b):
|
||||||
fail()
|
fail()
|
||||||
return
|
return
|
||||||
|
if a.isSameNode:
|
||||||
|
if not a.isSameNode(b):
|
||||||
|
fail()
|
||||||
|
return
|
||||||
if b.__eq__:
|
if b.__eq__:
|
||||||
if not b.__eq__(a):
|
if not b.__eq__(a):
|
||||||
fail()
|
fail()
|
||||||
return
|
return
|
||||||
|
if b.isSameNode:
|
||||||
|
if not b.isSameNode(a):
|
||||||
|
fail()
|
||||||
|
return
|
||||||
if a.length? or b.length?:
|
if a.length? or b.length?:
|
||||||
if a.length is not b.length:
|
if a.length is not b.length:
|
||||||
fail()
|
fail()
|
||||||
@ -48,7 +67,7 @@ def assert_equal(a, b, msg, call_site=None):
|
|||||||
for key in Object.keys(b):
|
for key in Object.keys(b):
|
||||||
assert_equal(a[key], b[key])
|
assert_equal(a[key], b[key])
|
||||||
|
|
||||||
if a is not b:
|
if atype is not 'object' and btype is not 'object':
|
||||||
fail()
|
fail()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user