Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2#@+leo-ver=5-thin 

3#@+node:ekr.20201203042030.1: * @file ../unittests/core/test_leoNodes.py 

4#@@first 

5"""Tests for leo.core.leoNodes""" 

6 

7# pylint has troubles finding Commands methods. 

8# pylint: disable=no-member 

9import textwrap 

10from leo.core import leoGlobals as g 

11from leo.core.leoTest2 import LeoUnitTest 

12 

13#@+others 

14#@+node:ekr.20210828112210.1: ** class TestNodes(LeoUnitTest) 

15class TestNodes(LeoUnitTest): 

16 """Unit tests for leo/core/leoNodes.py.""" 

17 

18 test_outline = None # Set by create_test_outline. 

19 

20 #@+others 

21 #@+node:ekr.20201203042409.3: *3* TestNodes.setUp 

22 def setUp(self): 

23 """Create the nodes in the commander.""" 

24 super().setUp() 

25 c = self.c 

26 self.create_test_outline() 

27 c.selectPosition(c.rootPosition()) 

28 #@+node:ekr.20210902022909.1: *3* TestNodes.tests... 

29 #@+node:ekr.20210830095545.3: *4* TestNodes.test_all_generators_return_unique_positions 

30 def test_all_generators_return_unique_positions(self): 

31 # This tests a major bug in *all* generators returning positions. 

32 c, p = self.c, self.c.p 

33 root = p.next() 

34 table = ( 

35 ('all_positions', c.all_positions), 

36 ('all_unique_positions', c.all_unique_positions), 

37 ('children', root.children), 

38 ('self_and_siblings', root.self_and_siblings), 

39 ('self_and_parents', root.firstChild().self_and_parents), 

40 ('self_and_subtree', root.self_and_subtree), 

41 ('following_siblings', root.following_siblings), 

42 ('parents', root.firstChild().firstChild().parents), 

43 ('unique_subtree', root.unique_subtree), 

44 ) 

45 for kind, generator in table: 

46 aList = [] 

47 for p in generator(): 

48 self.assertFalse(p in aList, msg=f"{kind} {p.gnx} {p.h}") 

49 aList.append(p) 

50 #@+node:ekr.20210828075915.1: *4* TestNodes.test_all_nodes_coverage 

51 def test_all_nodes_coverage(self): 

52 # @test c iters: <coverage tests> 

53 c = self.c 

54 v1 = [p.v for p in c.all_positions()] 

55 v2 = [v for v in c.all_nodes()] 

56 for v in v2: 

57 self.assertTrue(v in v1) 

58 for v in v1: 

59 self.assertTrue(v in v2) 

60 #@+node:ekr.20210830095545.41: *4* TestNodes.test_at_most_one_VNode_has_str_leo_pos_attribute 

61 def test_at_most_one_VNode_has_str_leo_pos_attribute(self): 

62 c = self.c 

63 n = 0 

64 for v in c.all_unique_vnodes_iter(): 

65 if hasattr(v, 'unknownAttributes'): 

66 d = v.unknownAttributes 

67 if d.get('str_leo_pos'): 

68 n += 1 

69 self.assertTrue(n == 0) 

70 #@+node:ekr.20210830095545.58: *4* TestNodes.test_at_others_directive 

71 def test_at_others_directive(self): 

72 p = self.c.p 

73 p1 = p.insertAsLastChild() 

74 p1.setHeadString('@file zzz') 

75 body = ''' %s 

76 ''' % (chr(64) + 'others') # ugly hack 

77 p1.setBodyString(body) 

78 p2 = p1.insertAsLastChild() 

79 self.assertEqual(p1.textOffset(), 0) 

80 self.assertEqual(p2.textOffset(), 5) 

81 #@+node:ekr.20210830095545.6: *4* TestNodes.test_c_positionExists 

82 def test_c_positionExists(self): 

83 c, p = self.c, self.c.p 

84 child = p.insertAsLastChild() 

85 self.assertTrue(c.positionExists(child)) 

86 child.doDelete() 

87 self.assertFalse(c.positionExists(child)) 

88 # also check the same on root level 

89 child = c.rootPosition().insertAfter() 

90 self.assertTrue(c.positionExists(child)) 

91 child.doDelete() 

92 self.assertFalse(c.positionExists(child)) 

93 #@+node:ekr.20210830095545.7: *4* TestNodes.test_c_positionExists_for_all_nodes 

94 def test_c_positionExists_for_all_nodes(self): 

95 c, p = self.c, self.c.p 

96 for p in c.all_positions(): 

97 self.assertTrue(c.positionExists(p)) 

98 # 2012/03/08: If a root is given, the search is confined to that root only. 

99 #@+node:ekr.20210830095545.8: *4* TestNodes.test_c_safe_all_positions 

100 def test_c_safe_all_positions(self): 

101 c = self.c 

102 aList1 = list(c.all_positions()) 

103 aList2 = list(c.safe_all_positions()) 

104 self.assertEqual(len(aList1), len(aList2)) 

105 #@+node:ekr.20210830095545.9: *4* TestNodes.test_check_all_gnx_s_exist_and_are_unique 

106 def test_check_all_gnx_s_exist_and_are_unique(self): 

107 c, p = self.c, self.c.p 

108 d = {} # Keys are gnx's, values are lists of vnodes with that gnx. 

109 for p in c.all_positions(): 

110 gnx = p.v.fileIndex 

111 self.assertTrue(gnx) 

112 aSet = d.get(gnx, set()) 

113 aSet.add(p.v) 

114 d[gnx] = aSet 

115 for gnx in sorted(d.keys()): 

116 aList = sorted(d.get(gnx)) 

117 self.assertTrue(len(aList) == 1) 

118 #@+node:ekr.20210830095545.42: *4* TestNodes.test_clone_and_move_the_clone_to_the_root 

119 def test_clone_and_move_the_clone_to_the_root(self): 

120 c, p = self.c, self.c.p 

121 child = p.insertAsNthChild(0) 

122 c.setHeadString(child, 'child') # Force the headline to update. 

123 self.assertTrue(child) 

124 c.selectPosition(child) 

125 clone = c.clone() 

126 self.assertEqual(clone, c.p) 

127 self.assertEqual(clone.h, 'child') 

128 assert child.isCloned(), 'fail 1' 

129 assert clone.isCloned(), 'fail 2' 

130 assert child.isCloned(), 'fail 3' 

131 assert clone.isCloned(), 'fail 4' 

132 c.undoer.undo() 

133 assert not child.isCloned(), 'fail 1-a' 

134 c.undoer.redo() 

135 assert child.isCloned(), 'fail 1-b' 

136 c.undoer.undo() 

137 assert not child.isCloned(), 'fail 1-c' 

138 c.undoer.redo() 

139 assert child.isCloned(), 'fail 1-d' 

140 clone.moveToRoot() # Does not change child position. 

141 assert child.isCloned(), 'fail 3-2' 

142 assert clone.isCloned(), 'fail 4-2' 

143 assert not clone.parent(), 'fail 5' 

144 assert not clone.back(), 'fail 6' 

145 clone.doDelete() 

146 assert not child.isCloned(), 'fail 7' 

147 #@+node:ekr.20210830095545.2: *4* TestNodes.test_consistency_between_parents_iter_and_v_parents 

148 def test_consistency_between_parents_iter_and_v_parents(self): 

149 c, p = self.c, self.c.p 

150 for p in c.all_positions(): 

151 parents1 = p.v.parents 

152 parents2 = p.v.directParents() 

153 self.assertEqual(len(parents1), len(parents2), msg=p.h) 

154 for parent in parents1: 

155 self.assertTrue(parent in parents2) 

156 for parent in parents2: 

157 self.assertTrue(parent in parents1) 

158 #@+node:ekr.20210830095545.10: *4* TestNodes.test_consistency_of_back_next_links 

159 def test_consistency_of_back_next_links(self): 

160 c, p = self.c, self.c.p 

161 for p in c.all_positions(): 

162 back = p.back() 

163 next = p.next() 

164 if back: 

165 self.assertEqual(back.getNext(), p) 

166 if next: 

167 self.assertEqual(next.getBack(), p) 

168 #@+node:ekr.20210830095545.11: *4* TestNodes.test_consistency_of_c_all_positions__and_p_ThreadNext_ 

169 def test_consistency_of_c_all_positions__and_p_ThreadNext_(self): 

170 c, p = self.c, self.c.p 

171 p2 = c.rootPosition() 

172 for p in c.all_positions(): 

173 self.assertEqual(p, p2) 

174 p2.moveToThreadNext() 

175 self.assertFalse(p2) 

176 #@+node:ekr.20210830095545.12: *4* TestNodes.test_consistency_of_firstChild__children_iter_ 

177 def test_consistency_of_firstChild__children_iter_(self): 

178 c, p = self.c, self.c.p 

179 for p in c.all_positions(): 

180 p2 = p.firstChild() 

181 for p3 in p.children_iter(): 

182 self.assertEqual(p3, p2) 

183 p2.moveToNext() 

184 self.assertFalse(p2) 

185 #@+node:ekr.20210830095545.13: *4* TestNodes.test_consistency_of_level 

186 def test_consistency_of_level(self): 

187 c, p = self.c, self.c.p 

188 for p in c.all_positions(): 

189 if p.hasParent(): 

190 self.assertEqual(p.parent().level(), p.level() - 1) 

191 if p.hasChildren(): 

192 self.assertEqual(p.firstChild().level(), p.level() + 1) 

193 if p.hasNext(): 

194 self.assertEqual(p.next().level(), p.level()) 

195 if p.hasBack(): 

196 self.assertEqual(p.back().level(), p.level()) 

197 #@+node:ekr.20210830095545.14: *4* TestNodes.test_consistency_of_parent__parents_iter_ 

198 def test_consistency_of_parent__parents_iter_(self): 

199 c, p = self.c, self.c.p 

200 for p in c.all_positions(): 

201 p2 = p.parent() 

202 for p3 in p.parents_iter(): 

203 self.assertEqual(p3, p2) 

204 p2.moveToParent() 

205 self.assertFalse(p2) 

206 #@+node:ekr.20210830095545.15: *4* TestNodes.test_consistency_of_parent_child_links 

207 def test_consistency_of_parent_child_links(self): 

208 # Test consistency of p.parent, p.next, p.back and p.firstChild. 

209 c, p = self.c, self.c.p 

210 for p in c.all_positions(): 

211 if p.hasParent(): 

212 n = p.childIndex() 

213 self.assertEqual(p, p.parent().moveToNthChild(n)) 

214 for child in p.children_iter(): 

215 self.assertEqual(p, child.parent()) 

216 if p.hasNext(): 

217 self.assertEqual(p.next().parent(), p.parent()) 

218 if p.hasBack(): 

219 self.assertEqual(p.back().parent(), p.parent()) 

220 #@+node:ekr.20210830095545.16: *4* TestNodes.test_consistency_of_threadBack_Next_links 

221 def test_consistency_of_threadBack_Next_links(self): 

222 c, p = self.c, self.c.p 

223 for p in c.all_positions(): 

224 threadBack = p.threadBack() 

225 threadNext = p.threadNext() 

226 if threadBack: 

227 self.assertEqual(p, threadBack.getThreadNext()) 

228 if threadNext: 

229 self.assertEqual(p, threadNext.getThreadBack()) 

230 #@+node:ekr.20210830095545.17: *4* TestNodes.test_convertTreeToString_and_allies 

231 def test_convertTreeToString_and_allies(self): 

232 p = self.c.p 

233 sib = p.next() 

234 self.assertTrue(sib) 

235 s = sib.convertTreeToString() 

236 for p2 in sib.self_and_subtree(): 

237 self.assertTrue(p2.h in s) 

238 #@+node:ekr.20210830095545.43: *4* TestNodes.test_delete_node 

239 def test_delete_node(self): 

240 # This test requires @bool select-next-after-delete = False 

241 c, p = self.c, self.c.p 

242 p2 = p.insertAsNthChild(0) 

243 p2.setHeadString('A') 

244 p3 = p.insertAsNthChild(1) 

245 p3.setHeadString('B') 

246 p4 = p.insertAsNthChild(2) 

247 p4.setHeadString('C') 

248 p.expand() 

249 c.selectPosition(p3) 

250 c.deleteOutline() 

251 c.redraw_now() 

252 p = c.p 

253 self.assertEqual(p.h, 'A') 

254 self.assertEqual(p.next().h, 'C') 

255 c.undoer.undo() 

256 c.outerUpdate() 

257 p = c.p 

258 self.assertEqual(p.back(), p2) 

259 self.assertEqual(p.next(), p4) 

260 c.undoer.redo() 

261 c.outerUpdate() 

262 p = c.p 

263 self.assertEqual(p.h, 'A') 

264 self.assertEqual(p.next().h, 'C') 

265 c.undoer.undo() 

266 c.outerUpdate() 

267 p = c.p 

268 self.assertEqual(p.back(), p2) 

269 self.assertEqual(p.next(), p4) 

270 c.undoer.redo() 

271 c.outerUpdate() 

272 p = c.p 

273 self.assertEqual(p.h, 'A') 

274 self.assertEqual(p.next().h, 'C') 

275 #@+node:ekr.20210830095545.44: *4* TestNodes.test_deleting_the_root_should_select_another_node 

276 def test_deleting_the_root_should_select_another_node(self): 

277 c, p = self.c, self.c.p 

278 root_h = p.h 

279 child = p.next() 

280 child.moveToRoot() # Does not change child position. 

281 c.setRootPosition(child) 

282 self.assertTrue(c.positionExists(child)) 

283 self.assertEqual(c.rootPosition().h, child.h) 

284 next = c.rootPosition().next() 

285 self.assertEqual(next.h, root_h) 

286 c.rootPosition().doDelete(newNode=next) 

287 c.setRootPosition(next) 

288 #@+node:ekr.20210830095545.45: *4* TestNodes.test_demote 

289 def test_demote(self): 

290 c, p = self.c, self.c.p 

291 p2 = p.insertAsNthChild(0) 

292 p2.setHeadString('A') 

293 p3 = p.insertAsNthChild(1) 

294 p3.setHeadString('B') 

295 p4 = p.insertAsNthChild(2) 

296 p4.setHeadString('C') 

297 p5 = p.insertAsNthChild(3) 

298 p5.setHeadString('D') 

299 p.expand() 

300 c.setCurrentPosition(p3) 

301 c.demote() 

302 p = c.p 

303 self.assertEqual(p, p3) 

304 self.assertEqual(p.h, 'B') 

305 assert not p.next() 

306 self.assertEqual(p.firstChild().h, 'C') 

307 self.assertEqual(p.firstChild().next().h, 'D') 

308 c.undoer.undo() 

309 p = c.p 

310 self.assertEqual(p, p3) 

311 self.assertEqual(p.back(), p2) 

312 self.assertEqual(p.next(), p4) 

313 c.undoer.redo() 

314 self.assertEqual(p, p3) 

315 self.assertEqual(p.h, 'B') 

316 assert not p.next() 

317 self.assertEqual(p.firstChild().h, 'C') 

318 self.assertEqual(p.firstChild().next().h, 'D') 

319 c.undoer.undo() 

320 p = c.p 

321 self.assertEqual(p.back(), p2) 

322 self.assertEqual(p.next(), p4) 

323 c.undoer.redo() 

324 self.assertEqual(p, p3) 

325 self.assertEqual(p.h, 'B') 

326 assert not p.next() 

327 self.assertEqual(p.firstChild().h, 'C') 

328 self.assertEqual(p.firstChild().next().h, 'D') 

329 #@+node:ekr.20210830095545.46: *4* TestNodes.test_insert_node 

330 def test_insert_node(self): 

331 c, p = self.c, self.c.p 

332 self.assertEqual(p.h, 'root') 

333 p2 = p.insertAsNthChild(0) 

334 p2.setHeadString('A') 

335 p3 = p.insertAsNthChild(1) 

336 p3.setHeadString('B') 

337 p.expand() 

338 c.setCurrentPosition(p2) 

339 p4 = c.insertHeadline() 

340 self.assertEqual(p4, c.p) 

341 p = c.p 

342 self.assertTrue(p) 

343 p.setHeadString('inserted') 

344 self.assertTrue(p.back()) 

345 self.assertEqual(p.back().h, 'A') 

346 self.assertEqual(p.next().h, 'B') 

347 # With the new undo logic, it takes 2 undoes. 

348 # The first undo undoes the headline changes, 

349 # the second undo undoes the insert node. 

350 c.undoer.undo() 

351 c.undoer.undo() 

352 p = c.p 

353 self.assertEqual(p, p2) 

354 self.assertEqual(p.next(), p3) 

355 c.undoer.redo() 

356 p = c.p 

357 self.assertTrue(p.back()) 

358 self.assertEqual(p.back().h, 'A') 

359 self.assertEqual(p.next().h, 'B') 

360 c.undoer.undo() 

361 p = c.p 

362 self.assertEqual(p, p2) 

363 self.assertEqual(p.next(), p3) 

364 c.undoer.redo() 

365 p = c.p 

366 self.assertEqual(p.back().h, 'A') 

367 self.assertEqual(p.next().h, 'B') 

368 #@+node:ekr.20210830095545.18: *4* TestNodes.test_leoNodes_properties 

369 def test_leoNodes_properties(self): 

370 c, p = self.c, self.c.p 

371 v = p.v 

372 b = p.b 

373 p.b = b 

374 self.assertEqual(p.b, b) 

375 v.b = b 

376 self.assertEqual(v.b, b) 

377 h = p.h 

378 p.h = h 

379 self.assertEqual(p.h, h) 

380 v.h = h 

381 self.assertEqual(v.h, h) 

382 for p in c.all_positions(): 

383 self.assertEqual(p.b, p.bodyString()) 

384 self.assertEqual(p.v.b, p.v.bodyString()) 

385 self.assertEqual(p.h, p.headString()) 

386 self.assertEqual(p.v.h, p.v.headString()) 

387 #@+node:ekr.20210830095545.47: *4* TestNodes.test_move_outline_down__undo_redo 

388 def test_move_outline_down__undo_redo(self): 

389 c, p = self.c, self.c.p 

390 p2 = p.insertAsNthChild(0) 

391 p2.setHeadString('A') 

392 p3 = p.insertAsNthChild(1) 

393 p3.setHeadString('B') 

394 p4 = p.insertAsNthChild(2) 

395 p4.setHeadString('C') 

396 p5 = p.insertAsNthChild(3) 

397 p5.setHeadString('D') 

398 p.expand() 

399 c.setCurrentPosition(p3) 

400 c.moveOutlineDown() 

401 moved = c.p 

402 self.assertEqual(moved.h, 'B') 

403 self.assertEqual(moved.back().h, 'C') 

404 self.assertEqual(moved.next().h, 'D') 

405 self.assertEqual(moved.next(), p5) 

406 c.undoer.undo() 

407 moved = c.p 

408 self.assertEqual(moved.back(), p2) 

409 self.assertEqual(moved.next(), p4) 

410 c.undoer.redo() 

411 moved = c.p 

412 self.assertEqual(moved.h, 'B') 

413 self.assertEqual(moved.back().h, 'C') 

414 self.assertEqual(moved.next().h, 'D') 

415 c.undoer.undo() 

416 moved = c.p 

417 self.assertEqual(moved.back(), p2) 

418 self.assertEqual(moved.next(), p4) 

419 c.undoer.redo() 

420 moved = c.p 

421 self.assertEqual(moved.h, 'B') 

422 self.assertEqual(moved.back().h, 'C') 

423 self.assertEqual(moved.next().h, 'D') 

424 #@+node:ekr.20210830095545.48: *4* TestNodes.test_move_outline_left 

425 def test_move_outline_left(self): 

426 c, p = self.c, self.c.p 

427 p2 = p.insertAsNthChild(0) 

428 p2.setHeadString('A') 

429 p.expand() 

430 c.setCurrentPosition(p2) 

431 c.moveOutlineLeft() 

432 moved = c.p 

433 self.assertEqual(moved.h, 'A') 

434 self.assertEqual(moved.back(), p) 

435 c.undoer.undo() 

436 c.undoer.redo() 

437 c.undoer.undo() 

438 c.undoer.redo() 

439 moved.doDelete(newNode=p) 

440 #@+node:ekr.20210830095545.49: *4* TestNodes.test_move_outline_right 

441 def test_move_outline_right(self): 

442 c, p = self.c, self.c.p 

443 p2 = p.insertAsNthChild(0) 

444 p2.setHeadString('A') 

445 p3 = p.insertAsNthChild(1) 

446 p3.setHeadString('B') 

447 p4 = p.insertAsNthChild(2) 

448 p4.setHeadString('C') 

449 p.expand() 

450 c.setCurrentPosition(p3) 

451 c.moveOutlineRight() 

452 moved = c.p 

453 self.assertEqual(moved.h, 'B') 

454 self.assertEqual(moved.parent(), p2) 

455 c.undoer.undo() 

456 c.undoer.redo() 

457 c.undoer.undo() 

458 c.undoer.redo() 

459 #@+node:ekr.20210830095545.50: *4* TestNodes.test_move_outline_up 

460 def test_move_outline_up(self): 

461 c, p = self.c, self.c.p 

462 p2 = p.insertAsNthChild(0) 

463 p2.setHeadString('A') 

464 p3 = p.insertAsNthChild(1) 

465 p3.setHeadString('B') 

466 p4 = p.insertAsNthChild(2) 

467 p4.setHeadString('C') 

468 p5 = p.insertAsNthChild(3) 

469 p5.setHeadString('D') 

470 p.expand() 

471 c.setCurrentPosition(p4) 

472 c.moveOutlineUp() 

473 moved = c.p 

474 self.assertEqual(moved.h, 'C') 

475 self.assertEqual(moved.back().h, 'A') 

476 self.assertEqual(moved.next().h, 'B') 

477 self.assertEqual(moved.back(), p2) 

478 c.undoer.undo() 

479 c.undoer.redo() 

480 c.undoer.undo() 

481 c.undoer.redo() 

482 #@+node:ekr.20210830095545.19: *4* TestNodes.test_new_vnodes_methods 

483 def test_new_vnodes_methods(self): 

484 c, p = self.c, self.c.p 

485 parent_v = p.parent().v or c.hiddenRootNode 

486 p.v.cloneAsNthChild(parent_v, p.childIndex()) 

487 v2 = p.v.insertAsFirstChild() 

488 v2.h = 'insertAsFirstChild' 

489 v2 = p.v.insertAsLastChild() 

490 v2.h = 'insertAsLastChild' 

491 v2 = p.v.insertAsNthChild(1) 

492 v2.h = 'insertAsNthChild(1)' 

493 #@+node:ekr.20210830095545.20: *4* TestNodes.test_newlines_in_headlines 

494 def test_newlines_in_headlines(self): 

495 # Bug https://bugs.launchpad.net/leo-editor/+bug/1245535 

496 p = self.c.p 

497 p.h = '\nab\nxy\n' 

498 self.assertEqual(p.h, 'abxy') 

499 

500 #@+node:ekr.20210830095545.54: *4* TestNodes.test_node_that_does_nott_belong_to_a_derived_file 

501 def test_node_that_does_not_belong_to_a_derived_file(self): 

502 # Change @file activeUnitTests.txt to @@file activeUnitTests.txt 

503 p = self.c.p 

504 p1 = p.insertAsLastChild() 

505 self.assertFalse(p1.textOffset()) 

506 

507 #@+node:ekr.20210830095545.56: *4* TestNodes.test_organizer_node 

508 def test_organizer_node(self): 

509 p = self.c.p 

510 p1 = p.insertAsLastChild() 

511 p1.setHeadString('@file zzz') 

512 p2 = p1.insertAsLastChild() 

513 self.assertEqual(p1.textOffset(), 0) 

514 self.assertEqual(p2.textOffset(), 0) 

515 

516 #@+node:ekr.20210830095545.21: *4* TestNodes.test_p__eq_ 

517 def test_p__eq_(self): 

518 c, p = self.c, self.c.p 

519 # These must not return NotImplemented! 

520 root = c.rootPosition() 

521 self.assertFalse(p.__eq__(None)) 

522 self.assertTrue(p.__ne__(None)) 

523 self.assertTrue(p.__eq__(root)) 

524 self.assertFalse(p.__ne__(root)) 

525 #@+node:ekr.20210830095545.24: *4* TestNodes.test_p_comparisons 

526 def test_p_comparisons(self): 

527 c, p = self.c, self.c.p 

528 copy = p.copy() 

529 self.assertEqual(p, copy) 

530 self.assertNotEqual(p, p.threadNext()) 

531 root = c.rootPosition() 

532 self.assertTrue(p.__eq__(copy)) 

533 self.assertFalse(p.__ne__(copy)) 

534 self.assertTrue(p.__eq__(root)) 

535 self.assertFalse(p.__ne__(root)) 

536 #@+node:ekr.20210830095545.25: *4* TestNodes.test_p_deletePositionsInList 

537 def test_p_deletePositionsInList(self): 

538 c, p = self.c, self.c.p 

539 root = p.insertAsLastChild() 

540 root.h = 'root' 

541 # Top level 

542 a1 = root.insertAsLastChild() 

543 a1.h = 'a' 

544 a1.clone() 

545 d1 = a1.insertAfter() 

546 d1.h = 'd' 

547 b1 = root.insertAsLastChild() 

548 b1.h = 'b' 

549 # Children of a. 

550 b11 = b1.clone() 

551 b11.moveToLastChildOf(a1) 

552 b11.clone() 

553 c2 = b11.insertAfter() 

554 c2.h = 'c' 

555 # Children of d 

556 b11 = b1.clone() 

557 b11.moveToLastChildOf(d1) 

558 # Count number of 'b' nodes. 

559 aList = [] 

560 nodes = 0 

561 for p in root.subtree(): 

562 nodes += 1 

563 if p.h == 'b': 

564 aList.append(p.copy()) 

565 self.assertEqual(len(aList), 6) 

566 c.deletePositionsInList(aList) 

567 c.redraw() 

568 

569 #@+node:ekr.20210830095545.26: *4* TestNodes.test_p_hasNextBack 

570 def test_p_hasNextBack(self): 

571 c, p = self.c, self.c.p 

572 for p in c.all_positions(): 

573 back = p.back() 

574 next = p.next() 

575 assert( 

576 (back and p.hasBack()) or 

577 (not back and not p.hasBack())) 

578 assert( 

579 (next and p.hasNext()) or 

580 (not next and not p.hasNext())) 

581 #@+node:ekr.20210830095545.27: *4* TestNodes.test_p_hasParentChild 

582 def test_p_hasParentChild(self): 

583 c, p = self.c, self.c.p 

584 for p in c.all_positions(): 

585 child = p.firstChild() 

586 parent = p.parent() 

587 assert( 

588 (child and p.hasFirstChild()) or 

589 (not child and not p.hasFirstChild())) 

590 assert( 

591 (parent and p.hasParent()) or 

592 (not parent and not p.hasParent())) 

593 #@+node:ekr.20210830095545.28: *4* TestNodes.test_p_hasThreadNextBack 

594 def test_p_hasThreadNextBack(self): 

595 c, p = self.c, self.c.p 

596 for p in c.all_positions(): 

597 threadBack = p.getThreadBack() 

598 threadNext = p.getThreadNext() 

599 assert( 

600 (threadBack and p.hasThreadBack()) or 

601 (not threadBack and not p.hasThreadBack())) 

602 assert( 

603 (threadNext and p.hasThreadNext()) or 

604 (not threadNext and not p.hasThreadNext())) 

605 #@+node:ekr.20210830095545.29: *4* TestNodes.test_p_isAncestorOf 

606 def test_p_isAncestorOf(self): 

607 c, p = self.c, self.c.p 

608 for p in c.all_positions(): 

609 child = p.firstChild() 

610 while child: 

611 for parent in p.self_and_parents_iter(): 

612 assert parent.isAncestorOf(child) 

613 child.moveToNext() 

614 next = p.next() 

615 self.assertFalse(p.isAncestorOf(next)) 

616 #@+node:ekr.20210830095545.30: *4* TestNodes.test_p_isCurrentPosition 

617 def test_p_isCurrentPosition(self): 

618 c, p = self.c, self.c.p 

619 self.assertFalse(c.isCurrentPosition(None)) 

620 self.assertTrue(c.isCurrentPosition(p)) 

621 #@+node:ekr.20210830095545.31: *4* TestNodes.test_p_isRootPosition 

622 def test_p_isRootPosition(self): 

623 c, p = self.c, self.c.p 

624 self.assertFalse(c.isRootPosition(None)) 

625 self.assertTrue(c.isRootPosition(p)) 

626 #@+node:ekr.20210830095545.33: *4* TestNodes.test_p_moveToFirst_LastChild 

627 def test_p_moveToFirst_LastChild(self): 

628 c, p = self.c, self.c.p 

629 root2 = p.next() 

630 self.assertTrue(root2) 

631 p2 = root2.insertAfter() 

632 p2.h = "test" 

633 self.assertTrue(c.positionExists(p2)) 

634 p2.moveToFirstChildOf(root2) 

635 self.assertTrue(c.positionExists(p2)) 

636 p2.moveToLastChildOf(root2) 

637 self.assertTrue(c.positionExists(p2)) 

638 #@+node:ekr.20210830095545.34: *4* TestNodes.test_p_moveToVisBack_in_a_chapter 

639 def test_p_moveToVisBack_in_a_chapter(self): 

640 # Verify a fix for bug https://bugs.launchpad.net/leo-editor/+bug/1264350 

641 import leo.core.leoChapters as leoChapters 

642 c, p = self.c, self.c.p 

643 cc = c.chapterController 

644 settings_p = p.insertAsNthChild(0) 

645 settings_p.h = '@settings' 

646 chapter_p = settings_p.insertAsLastChild() 

647 chapter_p.h = '@chapter aaa' 

648 node_p = chapter_p.insertAsNthChild(0) 

649 node_p.h = 'aaa node 1' 

650 # Hack the chaptersDict. 

651 cc.chaptersDict['aaa'] = leoChapters.Chapter(c, cc, 'aaa') 

652 # Select the chapter. 

653 cc.selectChapterByName('aaa') 

654 self.assertEqual(c.p.h, 'aaa node 1') 

655 p2 = c.p.moveToVisBack(c) 

656 self.assertEqual(p2, None) 

657 #@+node:ekr.20210830095545.35: *4* TestNodes.test_p_nosentinels 

658 def test_p_nosentinels(self): 

659 

660 p = self.c.p 

661 p.b = textwrap.dedent("""\ 

662 

663 def not_a_sentinel(x): 

664 pass 

665 

666 @not_a_sentinel 

667 def spam(): 

668 pass 

669  

670 """) 

671 self.assertEqual(p.b, p.nosentinels) 

672 #@+node:ekr.20210830095545.22: *4* TestNodes.test_p_relinkAsCloneOf 

673 def test_p_relinkAsCloneOf(self): 

674 

675 # test-outline: root 

676 # child clone a 

677 # node clone 1 

678 # child b 

679 # child clone a 

680 # node clone 1 

681 # child c 

682 # node clone 1 

683 # child clone a 

684 # node clone 1 

685 # child b 

686 # child clone a 

687 # node clone 1 

688 c, u = self.c, self.c.undoer 

689 p = c.p.next() 

690 child_b = g.findNodeAnywhere(c, 'child b') 

691 self.assertTrue(child_b) 

692 self.assertTrue(child_b.isCloned()) 

693 # 

694 # child_c must *not* be a clone at first. 

695 child_c = g.findNodeAnywhere(c, 'child c') 

696 self.assertTrue(child_c) 

697 self.assertFalse(child_c.isCloned()) 

698 # 

699 # Change the tree. 

700 bunch = u.beforeChangeTree(p) 

701 child_c._relinkAsCloneOf(child_b) 

702 u.afterChangeTree(p, 'relink-clone', bunch) 

703 # self.dump_tree('Before...') 

704 u.undo() 

705 # self.dump_tree('After...') 

706 self.assertTrue(child_b.isCloned()) 

707 self.assertFalse(child_c.isCloned()) 

708 

709 #@+node:ekr.20210830095545.36: *4* TestNodes.test_p_setBodyString 

710 def test_p_setBodyString(self): 

711 # Test that c.setBodyString works immediately. 

712 c, w = self.c, self.c.frame.body.wrapper 

713 next = self.root_p.next() 

714 c.setBodyString(next, "after") 

715 c.selectPosition(next) 

716 s = w.get("1.0", "end") 

717 self.assertEqual(s.rstrip(), "after") 

718 #@+node:ekr.20210830095545.37: *4* TestNodes.test_p_u 

719 def test_p_u(self): 

720 p = self.c.p 

721 self.assertEqual(p.u, p.v.u) 

722 p.v.u = None 

723 self.assertEqual(p.u, {}) 

724 self.assertEqual(p.v.u, {}) 

725 d = {'my_plugin': 'val'} 

726 p.u = d 

727 self.assertEqual(p.u, d) 

728 self.assertEqual(p.v.u, d) 

729 #@+node:ekr.20210830095545.38: *4* TestNodes.test_p_unique_nodes 

730 def test_p_unique_nodes(self): 

731 

732 self.assertEqual(len(list(self.root_p.unique_nodes())), 5) 

733 #@+node:ekr.20210830095545.51: *4* TestNodes.test_paste_node 

734 def test_paste_node(self): 

735 c, p = self.c, self.c.p 

736 child = p.insertAsNthChild(0) 

737 child.setHeadString('child') 

738 child2 = p.insertAsNthChild(1) 

739 child2.setHeadString('child2') 

740 grandChild = child.insertAsNthChild(0) 

741 grandChild.setHeadString('grand child') 

742 c.selectPosition(grandChild) 

743 c.clone() 

744 c.selectPosition(child) 

745 p.expand() 

746 c.selectPosition(child) 

747 self.assertEqual(c.p.h, 'child') 

748 c.copyOutline() 

749 oldVnodes = [p2.v for p2 in child.self_and_subtree()] 

750 c.selectPosition(child) 

751 c.p.contract() # Essential 

752 c.pasteOutline() 

753 assert c.p != child 

754 self.assertEqual(c.p.h, 'child') 

755 newVnodes = [p2.v for p2 in c.p.self_and_subtree()] 

756 for v in newVnodes: 

757 assert v not in oldVnodes 

758 c.undoer.undo() 

759 c.undoer.redo() 

760 c.undoer.undo() 

761 c.undoer.redo() 

762 #@+node:ekr.20210830095545.52: *4* TestNodes.test_paste_retaining_clones 

763 def test_paste_retaining_clones(self): 

764 c, p = self.c, self.c.p 

765 child = p.insertAsNthChild(0) 

766 child.setHeadString('child') 

767 self.assertTrue(child) 

768 grandChild = child.insertAsNthChild(0) 

769 grandChild.setHeadString('grand child') 

770 c.selectPosition(child) 

771 c.copyOutline() 

772 oldVnodes = [p2.v for p2 in child.self_and_subtree()] 

773 c.p.contract() # Essential 

774 c.pasteOutlineRetainingClones() 

775 self.assertNotEqual(c.p, child) 

776 newVnodes = [p2.v for p2 in c.p.self_and_subtree()] 

777 for v in newVnodes: 

778 self.assertTrue(v in oldVnodes) 

779 #@+node:ekr.20210830095545.4: *4* TestNodes.test_position_not_hashable 

780 def test_position_not_hashable(self): 

781 p = self.c.p 

782 try: 

783 a = set() 

784 a.add(p) 

785 assert False, 'Adding position to set should throw exception' 

786 except TypeError: 

787 pass 

788 #@+node:ekr.20210830095545.53: *4* TestNodes.test_promote 

789 def test_promote(self): 

790 c, p = self.c, self.c.p 

791 p2 = p.insertAsNthChild(0) 

792 p2.setHeadString('A') 

793 p3 = p.insertAsNthChild(1) 

794 p3.setHeadString('B') 

795 p4 = p3.insertAsNthChild(0) 

796 p4.setHeadString('child 1') 

797 p5 = p3.insertAsNthChild(1) 

798 p5.setHeadString('child 2') 

799 p.expand() 

800 p6 = p.insertAsNthChild(2) 

801 p6.setHeadString('C') 

802 c.setCurrentPosition(p3) 

803 c.promote() 

804 p = c.p 

805 self.assertEqual(p, p3) 

806 self.assertEqual(p.h, 'B') 

807 self.assertEqual(p.next().h, 'child 1') 

808 self.assertEqual(p.next().next().h, 'child 2') 

809 self.assertEqual(p.next().next().next().h, 'C') 

810 c.undoer.undo() 

811 p = c.p 

812 self.assertEqual(p, p3) 

813 self.assertEqual(p.back(), p2) 

814 self.assertEqual(p.next(), p6) 

815 self.assertEqual(p.firstChild().h, 'child 1') 

816 self.assertEqual(p.firstChild().next().h, 'child 2') 

817 c.undoer.redo() 

818 p = c.p 

819 self.assertEqual(p, p3) 

820 self.assertEqual(p.h, 'B') 

821 self.assertEqual(p.next().h, 'child 1') 

822 self.assertEqual(p.next().next().h, 'child 2') 

823 self.assertEqual(p.next().next().next().h, 'C') 

824 c.undoer.undo() 

825 p = c.p 

826 self.assertEqual(p, p3) 

827 self.assertEqual(p.back(), p2) 

828 self.assertEqual(p.next(), p6) 

829 self.assertEqual(p.firstChild().h, 'child 1') 

830 self.assertEqual(p.firstChild().next().h, 'child 2') 

831 c.undoer.redo() 

832 p = c.p 

833 self.assertEqual(p, p3) 

834 self.assertEqual(p.h, 'B') 

835 self.assertEqual(p.next().h, 'child 1') 

836 self.assertEqual(p.next().next().h, 'child 2') 

837 self.assertEqual(p.next().next().next().h, 'C') 

838 #@+node:ekr.20210830095545.55: *4* TestNodes.test_root_of_a_derived_file 

839 def test_root_of_a_derived_file(self): 

840 p = self.c.p 

841 p1 = p.insertAsLastChild() 

842 p1.setHeadString('@file zzz') 

843 self.assertEqual(p1.textOffset(), 0) 

844 #@+node:ekr.20210830095545.57: *4* TestNodes.test_section_node 

845 def test_section_node(self): 

846 p = self.c.p 

847 p1 = p.insertAsLastChild() 

848 p1.setHeadString('@file zzz') 

849 body = ''' %s 

850 ''' % (g.angleBrackets(' section ')) 

851 p1.setBodyString(body) 

852 p2 = p1.insertAsLastChild() 

853 head = g.angleBrackets(' section ') 

854 p2.setHeadString(head) 

855 self.assertEqual(p1.textOffset(), 0) 

856 self.assertEqual(p2.textOffset(), 3) 

857 # Section nodes can appear in with @others nodes, 

858 # so they don't get special treatment. 

859 #@+node:ekr.20210830095545.39: *4* TestNodes.test_v_atAutoNodeName_and_v_atAutoRstNodeName 

860 def test_v_atAutoNodeName_and_v_atAutoRstNodeName(self): 

861 p = self.c.p 

862 table = ( 

863 ('@auto-rst rst-file', 'rst-file', 'rst-file'), 

864 ('@auto x', 'x', ''), 

865 ('xyz', '', ''), 

866 ) 

867 for s, expected1, expected2 in table: 

868 result1 = p.v.atAutoNodeName(h=s) 

869 result2 = p.v.atAutoRstNodeName(h=s) 

870 self.assertEqual(result1, expected1, msg=s) 

871 self.assertEqual(result2, expected2, msg=s) 

872 #@-others 

873#@-others 

874 

875#@-leo