| 1 | from pathlib import Path |
| 2 | import runpy |
| 3 | import shutil |
| 4 | from tempfile import TemporaryDirectory |
| 5 | import unittest |
| 6 | import uuid |
| 7 | import xml.etree.ElementTree as ET |
| 8 | |
| 9 | from native_xml import ns |
| 10 | |
| 11 | ROOT = Path(__file__).resolve().parent.parent |
| 12 | FIXTURE = ROOT / 'corpus/notebook-edit' |
| 13 | compare = runpy.run_path(str(ROOT / 'tools/verify-document.py'))['compare'] |
| 14 | |
| 15 | |
| 16 | def file_identity(path): |
| 17 | return uuid.UUID(bytes_le=path.read_bytes()[16:32]) |
| 18 | |
| 19 | |
| 20 | def entries(node): |
| 21 | return [(child.tag.rsplit('}', 1)[-1], child.get('name'), child.get('color'), entries(child)) |
| 22 | for child in node if child.tag.rsplit('}', 1)[-1] in ('Section', 'SectionGroup')] |
| 23 | |
| 24 | |
| 25 | class NotebookEditTest(unittest.TestCase): |
| 26 | def check(self, row, expected): |
| 27 | with TemporaryDirectory() as temporary: |
| 28 | read = Path(temporary) / 'read' |
| 29 | shutil.copytree(FIXTURE / row / 'cold/read', read) |
| 30 | compare(FIXTURE / row / 'candidate', read) |
| 31 | hierarchy = ET.parse(FIXTURE / row / 'cold/read/hierarchy.xml').getroot() |
| 32 | self.assertEqual(entries(hierarchy), expected) |
| 33 | for candidate in sorted((FIXTURE / row / 'candidate').rglob('*.one*')): |
| 34 | relative = candidate.relative_to(FIXTURE / row / 'candidate') |
| 35 | self.assertEqual(file_identity(FIXTURE / row / 'cold/notebook' / relative), file_identity(candidate), str(relative)) |
| 36 | |
| 37 | def test_rust_sections_and_groups_open_natively_in_the_written_order(self): |
| 38 | self.check('structured', [ |
| 39 | ('Section', 'Renamed', '#FFD75E', []), |
| 40 | ('Section', 'First', '#8AA8E4', []), |
| 41 | ('SectionGroup', 'Kept', None, [('Section', 'Inner', '#8AA8E4', [])]), |
| 42 | ]) |
| 43 | |
| 44 | def test_a_rust_deleted_section_sits_in_the_native_recycle_bin(self): |
| 45 | self.check('deleted', [ |
| 46 | ('Section', 'Renamed', '#FFD75E', []), |
| 47 | ('SectionGroup', 'Kept', None, [('Section', 'First', '#8AA8E4', [])]), |
| 48 | ('SectionGroup', 'OneNote_RecycleBin', None, [('Section', 'First', '#8AA8E4', [])]), |
| 49 | ]) |
| 50 | hierarchy = ET.parse(FIXTURE / 'deleted/cold/read/hierarchy.xml').getroot() |
| 51 | bin = hierarchy.find("one:SectionGroup[@name='OneNote_RecycleBin']", ns) |
| 52 | self.assertEqual(bin.get('isRecycleBin'), 'true') |
| 53 | self.assertEqual(bin.find('one:Section', ns).get('isInRecycleBin'), 'true') |
| 54 | |
| 55 | def test_onenote_re_identifies_files_whose_header_disagrees_with_their_place(self): |
| 56 | # The native session lists a Rust section created with a zero ancestor twice: once |
| 57 | # under the identity Rust wrote and once under the identity OneNote assigned. |
| 58 | toc = (FIXTURE / 'native-structure/notebook/Open Notebook.onetoc2').read_bytes() |
| 59 | links = FIXTURE / 'native-structure/notebook/links.one' |
| 60 | self.assertEqual(uuid.UUID(bytes_le=links.read_bytes()[128:144]), file_identity(FIXTURE / 'native-structure/notebook/Open Notebook.onetoc2')) |
| 61 | self.assertIn(file_identity(links).bytes_le, toc) |
| 62 | |
| 63 | |
| 64 | if __name__ == '__main__': |
| 65 | unittest.main() |