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.20210903162431.1: * @file ../unittests/core/test_leoCommands.py 

4#@@first 

5"""Tests of leoCommands.py""" 

6# pylint: disable=no-member 

7import inspect 

8import textwrap 

9from leo.core import leoGlobals as g 

10from leo.core.leoTest2 import LeoUnitTest 

11 

12#@+others 

13#@+node:ekr.20210903162431.2: ** class TestCommands(LeoUnitTest) 

14class TestCommands(LeoUnitTest): 

15 """Test cases for leoCommands.py""" 

16 #@+others 

17 #@+node:ekr.20210906075242.28: *3* TestCommands.test_add_comments_with_multiple_language_directives 

18 def test_add_comments_with_multiple_language_directives(self): 

19 c, p, w = self.c, self.c.p, self.c.frame.body.wrapper 

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

21 @language rest 

22 rest text. 

23 @language python 

24 def spam(): 

25 pass 

26 # after 

27 """) 

28 expected = textwrap.dedent("""\ 

29 @language rest 

30 rest text. 

31 @language python 

32 def spam(): 

33 # pass 

34 # after 

35 """) 

36 i = p.b.find('pass') 

37 assert i > -1, 'fail1: %s' % (repr(p.b)) 

38 w.setSelectionRange(i, i + 4) 

39 c.addComments() 

40 self.assertEqual(p.b, expected) 

41 #@+node:ekr.20210906075242.30: *3* TestCommands.test_add_html_comments 

42 def test_add_html_comments(self): 

43 c, p, w = self.c, self.c.p, self.c.frame.body.wrapper 

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

45 @language html 

46 <html> 

47 text 

48 </html> 

49 """) 

50 expected = textwrap.dedent("""\ 

51 @language html 

52 <html> 

53 <!-- text --> 

54 </html> 

55 """) 

56 i = p.b.find('text') 

57 w.setSelectionRange(i, i + 4) 

58 c.addComments() 

59 self.assertEqual(p.b, expected) 

60 #@+node:ekr.20210906075242.32: *3* TestCommands.test_add_python_comments 

61 def test_add_python_comments(self): 

62 c, p, w = self.c, self.c.p, self.c.frame.body.wrapper 

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

64 @language python 

65 def spam(): 

66 pass 

67 # after 

68 """) 

69 expected = textwrap.dedent("""\ 

70 @language python 

71 def spam(): 

72 # pass 

73 # after 

74 """) 

75 i = p.b.find('pass') 

76 w.setSelectionRange(i, i + 4) 

77 c.addComments() 

78 self.assertEqual(p.b, expected) 

79 #@+node:ekr.20210901140645.2: *3* TestCommands.test_all_commands_have_an_event_arg 

80 def test_all_commands_have_an_event_arg(self): 

81 c = self.c 

82 d = c.commandsDict 

83 keys = sorted(d.keys()) 

84 table = ('bookmark', 'quickmove_', 'screen-capture', 'stickynote') 

85 for key in keys: 

86 continue_flag = False 

87 for prefix in table: 

88 if key.startswith(prefix): 

89 continue_flag = True 

90 break # These plugins have their own signatures. 

91 if continue_flag: 

92 continue 

93 f = d.get(key) 

94 # print(key, f.__name__ if f else repr(f)) 

95 # Test true __call__ methods if they exist. 

96 name = getattr(f, '__name__', None) or repr(f) 

97 if hasattr(f, '__call__') and inspect.ismethod(f.__call__): 

98 f = getattr(f, '__call__') 

99 t = inspect.getfullargspec(f) # t is a named tuple. 

100 args = t.args 

101 arg0 = len(args) > 0 and args[0] 

102 arg1 = len(args) > 1 and args[1] 

103 expected = ('event',) 

104 message = f"no event arg for command {key}, func: {name}, args: {args}" 

105 assert arg0 in expected or arg1 in expected, message 

106 #@+node:ekr.20210906075242.2: *3* TestCommands.test_c_alert 

107 def test_c_alert(self): 

108 c = self.c 

109 c.alert('test of c.alert') 

110 #@+node:ekr.20210906075242.3: *3* TestCommands.test_c_checkOutline 

111 def test_c_checkOutline(self): 

112 c = self.c 

113 errors = c.checkOutline() 

114 self.assertEqual(errors, 0) 

115 #@+node:ekr.20210901140645.15: *3* TestCommands.test_c_checkPythonCode 

116 def test_c_checkPythonCode(self): 

117 c = self.c 

118 c.checkPythonCode(event=None, ignoreAtIgnore=False, checkOnSave=False) 

119 #@+node:ekr.20210901140645.16: *3* TestCommands.test_c_checkPythonNode 

120 def test_c_checkPythonNode(self): 

121 c, p = self.c, self.c.p 

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

123 @language python 

124 

125 def abc: # missing parens. 

126 pass 

127 """) 

128 result = c.checkPythonCode(event=None, checkOnSave=False, ignoreAtIgnore=True) 

129 self.assertEqual(result, 'error') 

130 #@+node:ekr.20210901140645.7: *3* TestCommands.test_c_config_initIvar_sets_commander_ivars 

131 def test_c_config_initIvar_sets_commander_ivars(self): 

132 c = self.c 

133 for ivar, setting_type, default in g.app.config.ivarsData: 

134 assert hasattr(c, ivar), ivar 

135 assert hasattr(c.config, ivar), ivar 

136 val = getattr(c.config, ivar) 

137 val2 = c.config.get(ivar, setting_type) 

138 self.assertEqual(val, val2) 

139 #@+node:ekr.20210906075242.4: *3* TestCommands.test_c_contractAllHeadlines 

140 def test_c_contractAllHeadlines(self): 

141 c = self.c 

142 c.contractAllHeadlines() 

143 p = c.rootPosition() 

144 while p.hasNext(): 

145 p.moveToNext() 

146 c.redraw(p) 

147 #@+node:ekr.20210906075242.6: *3* TestCommands.test_c_demote_illegal_clone_demote 

148 def test_c_demote_illegal_clone_demote(self): 

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

150 # Create two cloned children. 

151 c.selectPosition(p) 

152 c.insertHeadline() 

153 p2 = c.p 

154 p2.moveToFirstChildOf(p) 

155 p2.setHeadString('aClone') 

156 c.selectPosition(p2) 

157 c.clone() 

158 self.assertEqual(2, p.numberOfChildren()) 

159 # Select the first clone and demote (it should be illegal) 

160 c.selectPosition(p2) 

161 c.demote() # This should do nothing. 

162 self.assertEqual(0, c.checkOutline()) 

163 self.assertEqual(2, p.numberOfChildren()) 

164 #@+node:ekr.20210906075242.7: *3* TestCommands.test_c_expand_path_expression 

165 def test_c_expand_path_expression(self): 

166 c = self.c 

167 import os 

168 sep = os.sep 

169 table = ( 

170 ('~{{sep}}tmp{{sep}}x.py', '~%stmp%sx.py' % (sep, sep)), 

171 ) 

172 for s, expected in table: 

173 if g.isWindows: 

174 expected = expected.replace('\\', '/') 

175 got = c.expand_path_expression(s) 

176 self.assertEqual(got, expected, msg=repr(s)) 

177 #@+node:ekr.20210906075242.8: *3* TestCommands.test_c_findMatchingBracket 

178 def test_c_findMatchingBracket(self): 

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

180 s = '(abc)' 

181 c.p.b = s 

182 table = ( 

183 (-1, -1), 

184 (len(s), len(s)), 

185 (0, 0), 

186 (1, 1), 

187 ) 

188 for i, j in table: 

189 w.setSelectionRange(-1, len(s)) 

190 c.findMatchingBracket(event=None) 

191 i2, j2 = w.getSelectionRange() 

192 self.assertTrue(i2 < j2, msg=f"i: {i}, j: {j}") 

193 

194 #@+node:ekr.20210906075242.9: *3* TestCommands.test_c_hiddenRootNode_fileIndex 

195 def test_c_hiddenRootNode_fileIndex(self): 

196 c = self.c 

197 assert c.hiddenRootNode.fileIndex.startswith('hidden-root-vnode-gnx'), c.hiddenRootNode.fileIndex 

198 #@+node:ekr.20210906075242.10: *3* TestCommands.test_c_hoist_chapter_node 

199 def test_c_hoist_chapter_node(self): 

200 c = self.c 

201 # Create the @settings and @chapter nodes. 

202 settings = c.rootPosition().insertAfter() 

203 settings.h = '@settings' 

204 chapter = settings.insertAsLastChild() 

205 chapter.h = '@chapter aaa' 

206 aaa = chapter.insertAsLastChild() 

207 aaa.h = 'aaa node 1' 

208 assert not c.hoistStack 

209 c.selectPosition(aaa) 

210 # Test. 

211 c.hoist() # New in Leo 5.3: should do nothing 

212 self.assertEqual(c.p, aaa) 

213 c.dehoist() # New in Leo 5.3: should do nothing: 

214 self.assertEqual(c.p, aaa) 

215 self.assertEqual(c.hoistStack, []) 

216 #@+node:ekr.20210906075242.11: *3* TestCommands.test_c_hoist_followed_by_goto_first_node 

217 def test_c_hoist_followed_by_goto_first_node(self): 

218 c = self.c 

219 # Create the @settings and @chapter nodes. 

220 settings = c.rootPosition().insertAfter() 

221 settings.h = '@settings' 

222 chapter = settings.insertAsLastChild() 

223 chapter.h = '@chapter aaa' 

224 aaa = chapter.insertAsLastChild() 

225 aaa.h = 'aaa node 1' 

226 # Test. 

227 assert not c.hoistStack 

228 c.selectPosition(aaa) 

229 assert not c.hoistStack 

230 

231 # The de-hoist happens in c.expandOnlyAncestorsOfNode, the call to c.selectPosition. 

232 if 1: 

233 c.hoist() 

234 c.goToFirstVisibleNode() 

235 self.assertEqual(c.p, aaa) 

236 else: 

237 c.hoist() 

238 c.goToFirstNode() 

239 assert not c.hoistStack # The hoist stack must be cleared to show the first node. 

240 self.assertEqual(c.p, c.rootPosition()) 

241 assert c.p.isVisible(c) 

242 #@+node:ekr.20210906075242.12: *3* TestCommands.test_c_hoist_with_no_children 

243 def test_c_hoist_with_no_children(self): 

244 c = self.c 

245 c.hoist() 

246 c.dehoist() 

247 #@+node:ekr.20210906075242.13: *3* TestCommands.test_c_insertBodyTime 

248 def test_c_insertBodyTime(self): 

249 c = self.c 

250 # p = c.p 

251 # w = c.frame.body.wrapper 

252 # s = w.getAllText() 

253 # w.setInsertPoint(len(s)) 

254 c.insertBodyTime() 

255 #@+node:ekr.20210906075242.14: *3* TestCommands.test_c_markAllAtFileNodesDirty 

256 def test_c_markAllAtFileNodesDirty(self): 

257 c = self.c 

258 marks = [p.v for p in c.all_positions() if p.isMarked()] 

259 try: 

260 ok = True 

261 try: 

262 c.markAllAtFileNodesDirty() 

263 except Exception: 

264 g.es_exception() 

265 ok = False 

266 finally: 

267 for p in c.all_positions(): 

268 if p.v in marks: 

269 if not p.isMarked(): 

270 c.setMarked(p) 

271 else: 

272 if p.isMarked(): 

273 c.clearMarked(p) 

274 

275 assert ok 

276 #@+node:ekr.20210906075242.15: *3* TestCommands.test_c_markSubheads 

277 def test_c_markSubheads(self): 

278 c = self.c 

279 child1 = c.rootPosition().insertAsLastChild() 

280 child2 = c.rootPosition().insertAsLastChild() 

281 assert child1 and child2 

282 c.markSubheads() 

283 #@+node:ekr.20210906075242.16: *3* TestCommands.test_c_pasteOutline_does_not_clone_top_node 

284 def test_c_pasteOutline_does_not_clone_top_node(self): 

285 c = self.c 

286 p = c.p 

287 p.b = '# text.' 

288 # child1 = c.rootPosition().insertAsLastChild() 

289 # c.selectPosition(child) 

290 c.copyOutline() 

291 p2 = c.pasteOutline() 

292 assert p2 

293 assert not p2.isCloned() 

294 #@+node:ekr.20210906075242.17: *3* TestCommands.test_c_scanAllDirectives 

295 def test_c_scanAllDirectives(self): 

296 c = self.c 

297 d = c.scanAllDirectives(c.p) 

298 # These are the commander defaults, without any settings. 

299 self.assertEqual(d.get('language'), 'python') 

300 self.assertEqual(d.get('tabwidth'), -4) 

301 self.assertEqual(d.get('pagewidth'), 132) 

302 #@+node:ekr.20210906075242.18: *3* TestCommands.test_c_scanAtPathDirectives 

303 def test_c_scanAtPathDirectives(self): 

304 c, p = self.c, self.c.p 

305 child = p.insertAfter() 

306 child.h = '@path one' 

307 grand = child.insertAsLastChild() 

308 grand.h = '@path two' 

309 great = grand.insertAsLastChild() 

310 great.h = 'xyz' 

311 aList = g.get_directives_dict_list(great) 

312 path = c.scanAtPathDirectives(aList) 

313 endpath = g.os_path_normpath('one/two') 

314 assert path.endswith(endpath), f"expected '{endpath}' got '{path}'" 

315 #@+node:ekr.20210906075242.19: *3* TestCommands.test_c_scanAtPathDirectives_same_name_subdirs 

316 def test_c_scanAtPathDirectives_same_name_subdirs(self): 

317 c = self.c 

318 # p2 = p.firstChild().firstChild().firstChild() 

319 p = c.p 

320 child = p.insertAfter() 

321 child.h = '@path again' 

322 grand = child.insertAsLastChild() 

323 grand.h = '@path again' 

324 great = grand.insertAsLastChild() 

325 great.h = 'xyz' 

326 aList = g.get_directives_dict_list(great) 

327 path = c.scanAtPathDirectives(aList) 

328 endpath = g.os_path_normpath('again/again') 

329 self.assertTrue(path and path.endswith(endpath)) 

330 #@+node:ekr.20210901140645.17: *3* TestCommands.test_c_tabNannyNode 

331 def test_c_tabNannyNode(self): 

332 c, p = self.c, self.c.p 

333 # Test 1. 

334 s = textwrap.dedent("""\ 

335 # no error 

336 def spam(): 

337 pass 

338 """) 

339 c.tabNannyNode(p, headline=p.h, body=s) 

340 # Test 2. 

341 s2 = textwrap.dedent("""\ 

342 # syntax error 

343 def spam: 

344 pass 

345 a = 2 

346 """) 

347 try: 

348 c.tabNannyNode(p, headline=p.h, body=s2) 

349 except IndentationError: 

350 pass 

351 #@+node:ekr.20210906075242.20: *3* TestCommands.test_c_unmarkAll 

352 def test_c_unmarkAll(self): 

353 c = self.c 

354 c.unmarkAll() 

355 for p in c.all_positions(): 

356 assert not p.isMarked(), p.h 

357 #@+node:ekr.20210906075242.21: *3* TestCommands.test_class_StubConfig 

358 def test_class_StubConfig(self): 

359 c = self.c 

360 class StubConfig(g.NullObject): 

361 pass 

362 

363 x = StubConfig() 

364 assert not x.getBool(c, 'mySetting') 

365 assert not x.enabledPluginsFileName 

366 #@+node:ekr.20210906075242.29: *3* TestCommands.test_delete_comments_with_multiple_at_language_directives 

367 def test_delete_comments_with_multiple_at_language_directives(self): 

368 c, p, w = self.c, self.c.p, self.c.frame.body.wrapper 

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

370 @language rest 

371 rest text. 

372 @language python 

373 def spam(): 

374 pass 

375 # after 

376 """) 

377 expected = textwrap.dedent("""\ 

378 @language rest 

379 rest text. 

380 @language python 

381 def spam(): 

382 pass 

383 # after 

384 """) 

385 i = p.b.find('pass') 

386 w.setSelectionRange(i, i + 4) 

387 c.deleteComments() 

388 self.assertEqual(p.b, expected) 

389 

390 #@+node:ekr.20210906075242.31: *3* TestCommands.test_delete_html_comments 

391 def test_delete_html_comments(self): 

392 c, p, w = self.c, self.c.p, self.c.frame.body.wrapper 

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

394 @language html 

395 <html> 

396 <!-- text --> 

397 </html> 

398 """) 

399 expected = textwrap.dedent("""\ 

400 @language html 

401 <html> 

402 text 

403 </html> 

404 """) 

405 i = p.b.find('text') 

406 w.setSelectionRange(i, i + 4) 

407 c.deleteComments() 

408 self.assertEqual(p.b, expected) 

409 #@+node:ekr.20210906075242.33: *3* TestCommands.test_delete_python_comments 

410 def test_delete_python_comments(self): 

411 c, p, w = self.c, self.c.p, self.c.frame.body.wrapper 

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

413 @language python 

414 def spam(): 

415 # pass 

416 # after 

417 """) 

418 expected = textwrap.dedent("""\ 

419 @language python 

420 def spam(): 

421 pass 

422 # after 

423 """) 

424 i = p.b.find('pass') 

425 w.setSelectionRange(i, i + 4) 

426 c.deleteComments() 

427 self.assertEqual(p.b, expected) 

428 #@+node:ekr.20210906075242.22: *3* TestCommands.test_efc_ask 

429 def test_efc_ask(self): 

430 c = self.c 

431 p = c.p 

432 # Not a perfect test, but stil significant. 

433 efc = g.app.externalFilesController 

434 if not efc: 

435 self.skipTest('No externalFilesController') 

436 result = efc.ask(c, p.h) 

437 assert result in (True, False), result 

438 #@+node:ekr.20210906075242.23: *3* TestCommands.test_efc_compute_ext 

439 def test_efc_compute_ext(self): 

440 c, p = self.c, self.c.p 

441 efc = g.app.externalFilesController 

442 if not efc: 

443 self.skipTest('No externalFilesController') 

444 table = ( 

445 # (None,'.py'), 

446 # ('','.py'), 

447 ('txt', '.txt'), 

448 ('.txt', '.txt'), 

449 ) 

450 for ext, result in table: 

451 result2 = efc.compute_ext(c, p, ext) 

452 self.assertEqual(result, result2, msg=repr(ext)) 

453 #@+node:ekr.20210906075242.24: *3* TestCommands.test_efc_compute_temp_file_path 

454 def test_efc_compute_temp_file_path(self): 

455 c = self.c 

456 p = c.p 

457 efc = g.app.externalFilesController 

458 if not efc: 

459 self.skipTest('no externalFilesController') 

460 s = efc.compute_temp_file_path(c, p, '.py') 

461 assert s.endswith('.py') 

462 #@+node:ekr.20210901140645.27: *3* TestCommands.test_koi8_r_encoding 

463 def test_koi8_r_encoding(self): 

464 c, p = self.c, self.c.p 

465 p1 = p.insertAsLastChild() 

466 s = '\xd4\xc5\xd3\xd4' # the word 'test' in Russian, koi8-r 

467 assert isinstance(s, str), repr(s) 

468 p1.setBodyString(s) 

469 c.selectPosition(p1) 

470 c.copyOutline() 

471 c.pasteOutline() 

472 p2 = p1.next() 

473 self.assertEqual(p1.b, p2.b) 

474 

475 #@+node:ekr.20210901140645.9: *3* TestCommands.test_official_commander_ivars 

476 def test_official_commander_ivars(self): 

477 c = self.c 

478 f = c.frame 

479 self.assertEqual(c, f.c) 

480 self.assertEqual(f, c.frame) 

481 ivars = ( 

482 '_currentPosition', 

483 'hoistStack', 

484 'mFileName', 

485 # Subcommanders... 

486 'atFileCommands', 'fileCommands', 'importCommands', 'undoer', 

487 # Args... 

488 'page_width', 'tab_width', 'target_language', 

489 ) 

490 for ivar in ivars: 

491 self.assertTrue(hasattr(c, ivar), msg=ivar) 

492 #@-others 

493#@-others 

494#@-leo