1import html
2import json
3import re
4from pathlib import Path
5import runpy
6import shutil
7from tempfile import TemporaryDirectory
8import unittest
9import xml.etree.ElementTree as ET
10
11from native_xml import ns
12
13ROOT = Path(__file__).resolve().parent.parent
14FIXTURE = ROOT / 'corpus/link-edit'
15compare = runpy.run_path(str(ROOT / 'tools/verify-document.py'))['compare']
16
17
18class LinkEditTest(unittest.TestCase):
19 def test_a_rust_hyperlink_renders_natively(self):
20 with TemporaryDirectory() as temporary:
21 read = Path(temporary) / 'read'
22 shutil.copytree(FIXTURE / 'cold/read', read)
23 compare(FIXTURE / 'candidate', read)
24 page, = (ET.parse(path).getroot() for path in sorted((FIXTURE / 'cold/read').glob('page-*.xml')))
25 texts = [oe.find('one:T', ns).text for oe in page.iter('{%s}OE' % ns['one']) if oe.find('one:T', ns) is not None]
26 self.assertEqual([' '.join(text.split()) for text in texts],
27 ['Read about Rust <a href="https://example.invalid/rust">the Rust site</a>'])
28
29 def test_onenote_links_between_pages_use_stored_identities(self):
30 with TemporaryDirectory() as temporary:
31 read = Path(temporary) / 'read'
32 shutil.copytree(FIXTURE / 'native-links/read', read)
33 compare(FIXTURE / 'native-links/notebook', read)
34 links = json.loads((FIXTURE / 'native-links/links.json').read_text(encoding='utf-8-sig'))
35 page, = (ET.parse(path).getroot() for path in sorted((FIXTURE / 'native-links/read').glob('page-*.xml'))
36 if ET.parse(path).getroot().get('name') == 'Read about Rust the Rust site')
37 hrefs = re.findall(r'href="([^"]*)"', ''.join(oe.find('one:T', ns).text for oe in page.iter('{%s}OE' % ns['one']) if oe.find('one:T', ns) is not None))
38 section = re.search(r'section-id=(\{[^}]*\})', links['page']).group(1)
39 page_id = re.search(r'page-id=(\{[^}]*\})', links['page']).group(1)
40 self.assertEqual(hrefs[1], 'onenote:#Link%%20target&amp;section-id=%s&amp;page-id=%s&amp;end&amp;base-path=C:\\one-tests\\runs\\capture\\notebook\\links.one' % (section, page_id))
41 self.assertEqual(hrefs[3], 'onenote:#section-id=%s&amp;end&amp;base-path=C:\\one-tests\\runs\\capture\\notebook\\links.one' % section)
42
43 def test_rust_internal_links_render_natively(self):
44 with TemporaryDirectory() as temporary:
45 read = Path(temporary) / 'read'
46 shutil.copytree(FIXTURE / 'internal/cold/read', read)
47 compare(FIXTURE / 'internal/candidate', read)
48 pages = {ET.parse(path).getroot().get('name'): ET.parse(path).getroot() for path in sorted((FIXTURE / 'internal/cold/read').glob('page-*.xml'))}
49 page = next(page for name, page in pages.items() if name.startswith('Linking page'))
50 text = ' '.join(' '.join(oe.find('one:T', ns).text.split()) for oe in page.iter('{%s}OE' % ns['one']) if oe.find('one:T', ns) is not None)
51 self.assertRegex(text, r'^Linking page <a href="onenote:#Link%20target&amp;section-id=\{[0-9A-F-]{36}\}&amp;page-id=\{[0-9A-F-]{36}\}&amp;end&amp;base-path=C:\\one-tests\\runs\\capture\\notebook\\links.one">Link target</a>$')
52
53 def test_onenote_links_typed_urls_and_dialog_addresses(self):
54 """OneNote 2010's read of `native-typed`: a typed `www.` address opens over http,
55 and a Link dialog address typed without a scheme does too."""
56 text = (FIXTURE / 'native-typed/read/page-000.xml').read_text(encoding='utf-8-sig')
57 hrefs = [html.unescape(href) for href in re.findall(r'href="([^"]*)"', text)]
58 self.assertEqual(hrefs[1], 'http://www.example.com')
59 self.assertEqual(hrefs[11], 'http://www.d.example')
60 self.assertEqual(hrefs[15], 'http://example.net/x')
61 self.assertNotIn('me@example.com', hrefs)
62
63 def test_editor_links_and_equations_render_natively(self):
64 """What the canvas editor saved for typed URLs, the Link dialog, Remove Link and
65 equations typed after Alt+= reads back in a cold OneNote 2010 with the links and
66 MathML it meant (`crates/canvas/tests/links_equations.rs`)."""
67 row = FIXTURE / 'editor'
68 with TemporaryDirectory() as temporary:
69 read = Path(temporary) / 'read'
70 shutil.copytree(row / 'cold/read', read)
71 compare(row / 'candidate', read)
72 expected = json.loads((row / 'expected.json').read_text())
73 path = next(path for path in sorted((row / 'cold/read').glob('page-*.xml'))
74 if ET.parse(path).getroot().get('name').startswith('Linking page'))
75 page = ET.parse(path).getroot()
76 text = ''.join(oe.find('one:T', ns).text for oe in page.iter('{%s}OE' % ns['one']) if oe.find('one:T', ns) is not None)
77 hrefs = [html.unescape(href) for href in re.findall(r'href="([^"]*)"', text)]
78 self.assertEqual(hrefs, expected['hrefs'])
79 raw = path.read_text(encoding='utf-8-sig')
80 mathml = [re.sub(r'&#(\d+);', lambda m: chr(int(m.group(1))), body)
81 for body in re.findall(r'<mml:math[^>]*>(.*?)</mml:math>', raw, re.S)]
82 self.assertEqual(mathml, expected['mathml'])
83
84
85if __name__ == '__main__':
86 unittest.main()