Coverage for tests/test_lp.py: 28.37%

Shortcuts 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

370 statements  

1""" 

2# Tests for the literate programming (LP) feature. 

3 

4We turn code tags with lp as argument after the language into evaluated result blocks incl Ansi Escape sequences, which are processed by xterm on the client, possibly remote fetched. 

5 

6""" 

7import json pytest

8import os pytest

9import shutil pytest

10import sys pytest

11import time pytest

12import unittest pytest

13 

14import pytest pytest

15 

16from lcdoc.mkdocs.lp import LP, LPPlugin, split_off_fenced_blocks pytest

17from lcdoc.mkdocs.markdown import deindent pytest

18 

19from lcdoc.tools import dirname, exists, project, read_file, write_file pytest

20 

21# initializing it, otherwise init_page fails: 

22LP.fn_lp = '/tmp/not_set/not_set.md' pytest

23# import lcdoc.call_flow_logging as cfl 

24 

25# just for reference, the unwrapped original: 

26# orig_gen_markdown = make_badges.gen_markdown 

27# first_test_was_run = [] 

28 

29now = time.time pytest

30 

31# set (and cache) hard, we are in <root>/tests: 

32r = dirname(dirname(__file__)) pytest

33project.root(root=r) pytest

34LP.config = {'docs_dir': r + '/docs'} pytest

35 

36 

37def d_test(): pytest

38 return project.root() + '/tmp/lp_tests' 

39 

40 

41fn_test = lambda: d_test() + '/test.md' 41 ↛ exitline 41 didn't run the lambda on line 41pytest

42test_content = '\n'.join(['line0', ' \x1b[38;5;124mline1\x1b[0m', 'line2']) pytest

43 

44 

45plugin = LPPlugin() pytest

46 

47 

48def run_md_page(md, fn, raise_on_errs): pytest

49 rmd = plugin.on_page_markdown(md, page=mock_page(fn), config={}, files=[]) 

50 return rmd 

51 

52 

53def run_lp(md, raise_on_errs=None): pytest

54 old = LP.on_err_keep_running 

55 LP.on_err_keep_running = not (raise_on_errs) 

56 try: 

57 dw, fn = d_test(), fn_test() 

58 LP.fn_lp = fn 

59 assert '/tmp/' in dw # safety measure 

60 shutil.rmtree(dw, ignore_errors=True) 

61 os.makedirs(dw, exist_ok=True) 

62 write_file(dw + '/test_content', test_content) 

63 return run_md_page(md, fn, raise_on_errs=raise_on_errs) 

64 finally: 

65 LP.on_err_keep_running = old 

66 

67 

68def err_msg(l, res): pytest

69 # just to not have too much lines in breakpoint below 

70 msg = 'Expected line in produced markdown not in result!\nline: %s\nres: %s' 

71 msg = os.environ['PYTEST_CURRENT_TEST'] + '\n' + msg 

72 msg = msg % (l, res) 

73 print(msg) 

74 return msg 

75 

76 

77def check_lines_in(res, *blocks): pytest

78 """Are all non empty lines of the blocks in the result? 

79 More strict we don't go, for changes in newlines would kill all tests 

80 Plus "the dot, which we'll remove some day ..." 

81 """ 

82 res = [l.rstrip() for l in res.splitlines()] 

83 # print('check_lines') 

84 # print(res) 

85 # print('????????') 

86 for b in blocks: 

87 for l in b.splitlines(): 

88 

89 if l.strip(): 

90 kk = l.rstrip() 

91 # print('kk') 

92 # print(kk) 

93 assert kk in res 

94 # try: 

95 # # res is a LIST - whole line must match 

96 # assert l.rstrip() in res 

97 # except Exception as ex: 

98 # if not sys.stdin.isatty(): 

99 # raise 

100 # err_msg(l, res) 

101 # breakpoint() 

102 # sys.exit(1) 

103 

104 

105class Page: pytest

106 url = 'tests/' pytest

107 title = 'test_lp' pytest

108 

109 class file: pytest

110 abs_src_path = None pytest

111 

112 

113def mock_page(fn): pytest

114 """mock for the mkdocs page object. We need only this in prod code:""" 

115 p = Page 

116 # being set by the lcd hook decorator: 

117 p.stats = {} 

118 p.file.abs_src_path = fn 

119 p.file.src_path = r + '/' + fn 

120 LP.page = p 

121 LP.init_page() 

122 return p 

123 

124 

125class extract(unittest.TestCase): pytest

126 'Detecting LP blocks in Markdown' 

127 

128 def extract(md): pytest

129 mock_page(__file__) 

130 r = split_off_fenced_blocks( 

131 deindent(md), fc_crit=LP.is_lp_block, fc_process=LP.parse_lp_block 

132 ) 

133 return r 

134 

135 # the test md, where we play with the header of the first LP block: 

136 md = ''' 

137 hi 

138 ```js lp %s 

139 foo = bar 

140 ``` 

141 there 

142 

143 no lp code: 

144 ```py k lp 

145 

146 # also not since in other one: 

147 ```py lp 

148 outer non lp closes here: 

149 ``` 

150 second lp one, indented, ok: 

151 

152 ```foo lp  

153 second lp code 

154 ``` 

155 ''' 

156 

157 gen_md = lambda header: extract.md % header 157 ↛ exitline 157 didn't run the lambda on line 157pytest

158 

159 @classmethod pytest

160 def check_norm(cls, header): 

161 

162 h = cls.gen_md(header) 

163 mds, specs = cls.extract(h) 

164 assert mds == [ 

165 ['hi'], 

166 [ 

167 'there', 

168 '', 

169 'no lp code:', 

170 '```py k lp', 

171 '', 

172 '# also not since in other one:', 

173 '```py lp', 

174 'outer non lp closes here:', 

175 '```', 

176 'second lp one, indented, ok:', 

177 '', 

178 ], 

179 [], 

180 ] 

181 

182 # all blocks 

183 assert isinstance(specs, list) 

184 # would indent the result like the original lp block: 

185 assert specs[1]['indent'] == ' ' 

186 assert specs[1]['code'] == [' second lp code'] 

187 assert specs[1]['lang'] == 'foo' 

188 assert specs[1]['nr'] == 1 

189 

190 spec = specs[0] 

191 assert spec['code'] == ['foo = bar'] 

192 assert spec['indent'] == '' 

193 assert spec['lang'] == 'js' 

194 assert spec['nr'] == 0 

195 return spec 

196 

197 def test_find_block_without_attrs(self): pytest

198 spec = extract.check_norm('') 

199 assert spec['args'] == () 

200 assert spec['kwargs'] == {} 

201 

202 def test_find_block_with_easy_attrs(self): pytest

203 spec = extract.check_norm('foo=bar i=42 b=true f=1.2') 

204 assert spec['args'] == () 

205 assert spec['kwargs'] == {'b': True, 'f': 1.2, 'foo': 'bar', 'i': 42} 

206 

207 def test_find_block_with_py_sig_attrs(self): pytest

208 spec = extract.check_norm("'foo', 'bar', a='b', c='23', d={'foo': 'bar'}") 

209 assert spec['args'] == ('foo', 'bar') 

210 assert spec['kwargs'] == {'a': 'b', 'c': '23', 'd': {'foo': 'bar'}} 

211 

212 def test_header_parse_error(self): pytest

213 spec = extract.check_norm("'foo 'bar', a='b', c='23', d={'foo': 'bar'}") 

214 assert spec['args'] == LP.header_parse_err 

215 assert 'SyntaxError' in repr(spec['kwargs'][LP.py_err]) 

216 assert spec['kwargs'][LP.easy_args_err] 

217 

218 

219class embedded_no_sessions(unittest.TestCase): pytest

220 'Embedded Blocks, not remote fetched' 

221 

222 def test_no_session_cmd_out(self): pytest

223 """First a test w/o sessions""" 

224 run = 'head %s/test_content |grep --color=never line' % d_test() 

225 md = ''' 

226 ```bash lp 

227 %s 

228 ``` 

229 ''' 

230 cmd = ''' 

231 === "Cmd" 

232 ```console 

233 $ %s 

234 ``` 

235 ''' 

236 out = ''' 

237 === "Output" 

238 <xterm /> 

239 line0 

240 \x1b[38;5;124mline1\x1b[0m 

241 line2 

242 ''' 

243 res = run_lp(md % run) 

244 check_lines_in(res, cmd % run, out) 

245 

246 def test_asserts_work(self): pytest

247 run = 'head %s/test_content |grep --color=never line' % d_test() 

248 md = ''' 

249 ```bash lp asserts=line1 

250 %s # lp: expect=line 

251 ``` 

252 ''' 

253 cmd = ''' 

254 === "Cmd" 

255 ```console 

256 $ %s 

257 ``` 

258 ''' 

259 out = ''' 

260 === "Output" 

261 <xterm /> 

262 line0 

263 \x1b[38;5;124mline1\x1b[0m 

264 line2 

265 ''' 

266 res = run_lp(md % run) 

267 check_lines_in(res, cmd % run, out) 

268 

269 def test_asserts_fail(self): pytest

270 run = 'head %s/test_content |grep --color=never line' % d_test() 

271 md = ''' 

272 ```bash lp asserts=XXXX 

273 %s 

274 ``` 

275 ''' 

276 cmd = ''' 

277 === "Cmd" 

278 ```console 

279 $ %s 

280 ``` 

281 ''' 

282 out = ''' 

283 === "Output" 

284 <xterm /> 

285 line0 

286 \x1b[38;5;124mline1\x1b[0m 

287 line2 

288 ''' 

289 with pytest.raises(Exception, match='XXX'): 

290 res = run_lp(md % run, raise_on_errs=True) 

291 

292 def test_escape(self): pytest

293 """Single Escapes Working?""" 

294 md = ''' 

295 ```bash lp  

296 echo -e "With \x1b[1;38;5;124mAnsi\x1b[0m" 

297 ``` 

298 ''' 

299 cmd = ''' 

300 === "Cmd" 

301 ```console 

302 $ echo -e "With \x1b[1;38;5;124mAnsi\x1b[0m"\n 

303 ``` 

304 ''' 

305 out = ''' 

306 === "Output" 

307 <xterm /> 

308 With \x1b[1;38;5;124mAnsi\x1b[0m\n 

309 ''' 

310 res = run_lp(md) 

311 # print('have res') 

312 # print(res) 

313 check_lines_in(res, cmd, out) 

314 

315 

316class embedded_sessions(unittest.TestCase): pytest

317 """Format mk_cmd_out (cmd and output tabs) 

318 

319 This is the default format. 

320 """ 

321 

322 def test_with_paths(self): pytest

323 for k in 'PATH', 'PYTHONPATH': 

324 os.environ[k] = os.environ.get(k, '') + ':/bin/baz/foobar' + k 

325 md = ''' 

326 ```bash lp new_session=test with_paths 

327 echo $PATH 

328 echo $PYTHONPATH 

329 ``` 

330 ''' 

331 res = run_lp(md) 

332 assert '/bin/baz/foobarPATH' in res 

333 assert '/bin/baz/foobarPYTHONPATH' in res 

334 

335 def test_session_escape(self): pytest

336 """Single Escapes Working? 

337 Note: Tmux breaks appart the escape sequences, e.g. bold and color, 

338 so we only send one esc - a color: 

339 

340 """ 

341 md = ''' 

342 ```bash lp new_session=test 

343 echo -e "With \x1b[38;5;124mAnsi" 

344 ``` 

345 ''' 

346 cmd = ''' 

347 === "Cmd" 

348 ```console 

349 $ echo -e "With \x1b[38;5;124mAnsi" 

350 ``` 

351 ''' 

352 out = ''' 

353 === "Output" 

354 <xterm /> 

355 With \x1b[38;5;124mAnsi" 

356 ''' 

357 res = run_lp(md) 

358 check_lines_in(res, cmd) 

359 

360 def test_multiline(self): pytest

361 """ With the '> ' at the beginning, we send those blocks as one command 

362 the other lines are run one by one, for results per command. 

363 """ 

364 md = ''' 

365 ```bash lp new_session=test asserts=foobarbaz and line2 

366 

367 ip () { echo bar; } 

368 cat << FOO > test.pyc 

369 > foo$(ip)baz 

370 > line2  

371 > FOO 

372 cat test.pyc 

373 ``` 

374 ''' 

375 res = run_lp(md, raise_on_errs=True) 

376 with open('test.pyc') as fd: 

377 assert fd.read().strip() == 'foobarbaz\nline2' 

378 os.unlink('test.pyc') 

379 

380 def test_multiline_struct(self): pytest

381 """ No '> ' required here""" 

382 md = ''' 

383 ```bash lp new_session=test expect= asserts=foobarbaz and line2 

384 [{'cmd': 'ip () { echo bar; }'}, 

385 {'cmd': """cat << FOO > test.pyc 

386 foo$(ip)baz 

387 line2  

388 FOO"""}, 

389 {'cmd': 'cat test.pyc'}] 

390 

391 ``` 

392 ''' 

393 res = run_lp(md, raise_on_errs=True) 

394 with open('test.pyc') as fd: 

395 assert fd.read().strip() == 'foobarbaz\nline2' 

396 os.unlink('test.pyc') 

397 

398 def test_cmd_out(self): pytest

399 md = ''' 

400 ```bash lp new_session=test 

401 %s 

402 ``` 

403 ''' 

404 cmd = ''' 

405 === "Cmd" 

406 ```console 

407 $ %s 

408 ``` 

409 ''' 

410 out = ''' 

411 === "Output" 

412 <xterm /> 

413 line0 

414 line2 

415 ''' 

416 run = 'head %s/test_content |grep --color=never line' % d_test() 

417 res = run_lp(md % run) 

418 check_lines_in(res, cmd % run, out) 

419 # tmux changes the ansi codes slightly and the cmd is 

420 # repeated in the output, with prompt: 

421 assert '[38;5;124mline1' in res 

422 assert run in res.split('Output', 1)[1] 

423 

424 def test_session_reuse(self): pytest

425 md1 = ''' 

426 ```bash lp new_session=test1 

427 i=23 

428 ``` 

429 ''' 

430 res = run_lp(md1) 

431 md2 = ''' 

432 ```bash lp session=test1 

433 echo $i 

434 ``` 

435 ''' 

436 res = run_lp(md2) 

437 o = res.split('Output', 1)[1] 

438 ind = o.split('<xterm', 1)[0].rsplit('\n', 1)[1] 

439 assert '\n' + ind + ' $ echo $i' in o 

440 assert '\n' + ind + ' 23' in o 

441 

442 def test_custom_expect_and_kill(self): pytest

443 """expect=... will include the expected string in the output. 

444 kill terminates the session after last command 

445 """ 

446 md1 = ''' 

447 ```bash lp new_session=test_foo kill_session=true 

448 ['echo bar', {'cmd': 'echo foo', 'expect': 'foo'}] 

449 ``` 

450 ''' 

451 res = run_lp(md1) 

452 out = ''' 

453 

454 === "Output" 

455 <xterm /> 

456 $ echo bar 

457 bar 

458 $ echo foo 

459 foo 

460 ''' 

461 check_lines_in(res, out) 

462 assert 'test_foo' not in os.popen('tmux ls').read() 

463 

464 def test_empty_expect_and_ctrl_c(self): pytest

465 """This way you start e.g. a service in foreground, then kill it""" 

466 md1 = ''' 

467 

468 ```bash lp session=test1 fmt=mk_console expect=false 

469 [{'cmd': 'sleep 5', 'timeout': 0.5}, 'send-keys: C-c'] 

470 ``` 

471 

472 ''' 

473 t0 = now() 

474 res = run_lp(md1) 

475 assert now() - t0 > 0.5 

476 out = ''' 

477 $ sleep 5 

478 ''' 

479 print('res--------------') 

480 print(res) 

481 print('res--------------') 

482 check_lines_in(res, out) 

483 # cmd output was skipped since result had it anyway: 

484 assert len(res.split('$ sleep 5')) == 2 

485 

486 def test_asserts_pycond(self): pytest

487 

488 md1 = ''' 

489 

490 ```bash lp session='test1', asserts='[bar and not foo]' 

491 ['echo foo', {'cmd': 'echo bar'}] 

492 ``` 

493 ''' 

494 

495 with pytest.raises(Exception, match='foo'): 

496 res = run_lp(md1, raise_on_errs=True) 

497 

498 md1 = ''' 

499 

500 ```bash lp session='test1', asserts='bar and foo' 

501 ['echo foo', {'cmd': 'echo bar'}] 

502 ``` 

503 ''' 

504 

505 res = run_lp(md1) 

506 out = ''' 

507 === "Output" 

508 <xterm /> 

509 $ echo foo 

510 foo 

511 $ echo bar 

512 bar 

513 ''' 

514 check_lines_in(res, out) 

515 md1 = ''' 

516 

517 ```bash lp session='test1', asserts='[bar and not foo] or echo' 

518 ['echo foo', {'cmd': 'echo bar'}] 

519 ``` 

520 ''' 

521 res = run_lp(md1) 

522 check_lines_in(res, out) 

523 

524 def test_asserts_inline(self): pytest

525 """Use the documentation tool as a little test framework""" 

526 md1 = ''' 

527 

528 ```bash lp session=test1 asserts=foo 

529 ['echo foo', {'cmd': 'echo bar', 'asserts': 'bar'}] 

530 ``` 

531 ''' 

532 res = run_lp(md1) 

533 out = ''' 

534 === "Output" 

535 <xterm /> 

536 $ echo foo 

537 foo 

538 $ echo bar 

539 bar 

540 ''' 

541 check_lines_in(res, out) 

542 

543 md1 = ''' 

544 ```bash lp session=test1 asserts=foo 

545 ['echo foo', {'cmd': 'echo bar', 'asserts': 'XXX'}] 

546 ``` 

547 ''' 

548 res = run_lp(md1) 

549 assert ( 

550 '!!! error "LP error: Assertion failed: Expected "[\'XXX\']" not found in result' 

551 in res 

552 ) 

553 

554 md1 = ''' 

555 ```bash lp session=test1 asserts=foo 

556 ['echo foo', {'cmd': 'echo bar', 'asserts': ['XXX', 'bar']}] 

557 ``` 

558 ''' 

559 

560 with pytest.raises(Exception, match='XXX'): 

561 res = run_lp(md1, raise_on_errs=True) 

562 

563 md1 = ''' 

564 ```bash lp session=test1 asserts=foo 

565 ['echo foo', {'cmd': 'echo bar', 'asserts': ['b', 'bar']}] 

566 ``` 

567 ''' 

568 res = run_lp(md1, raise_on_errs=False) 

569 

570 

571class embedded_multiline(unittest.TestCase): pytest

572 def test_simple_multiline_cmd(self): pytest

573 """w/o and w/ tmux""" 

574 for k in '', ' session=test': 

575 md = ''' 

576 ```bash lp %s 

577 echo foo 

578 echo bar 

579 ``` 

580 ''' 

581 md = md % k 

582 cmd = ''' 

583 === "Cmd" 

584 

585 ```console 

586 $ echo foo 

587 $ echo bar 

588 ``` 

589 ''' 

590 out = ''' 

591 === "Output" 

592 <xterm /> 

593 $ echo foo 

594 foo 

595 $ echo bar 

596 bar 

597 ''' 

598 res = run_lp(md) 

599 check_lines_in(res, cmd, out) 

600 

601 def test_simple_ansi_multiline_cmd(self): pytest

602 """w/o and w/ tmux""" 

603 for k in ('',): 

604 md = ''' 

605 ```bash lp %s 

606 echo -e '\x1b[32mfoo' 

607 echo bar 

608 ``` 

609 ''' 

610 md = md % k 

611 cmd = ''' 

612 === "Cmd" 

613 

614 ```console 

615 $ echo -e '\x1b[32mfoo'\n 

616 $ echo bar 

617 ``` 

618 ''' 

619 out = ''' 

620 === "Output" 

621 <xterm /> 

622 $ echo -e '\x1b[32mfoo' 

623 \x1b[32mfoo 

624 $ echo bar 

625 bar 

626 ''' 

627 res = run_lp(md) 

628 check_lines_in(res, cmd, out) 

629 

630 def test_simple_multiline_cmd_flat(self): pytest

631 for k in '', ' session=test': 

632 md = ''' 

633 ```bash lp fmt=xt_flat %s 

634 echo foo 

635 echo bar 

636 ``` 

637 ''' 

638 md = md % k 

639 cmd = ''' 

640 <xterm /> 

641 $ echo foo 

642 foo 

643 $ echo bar 

644 bar 

645 ''' 

646 res = run_lp(md) 

647 check_lines_in(res, cmd) 

648 

649 

650class multi(unittest.TestCase): pytest

651 def test_multicmd_with_one_silent(self): pytest

652 md = ''' 

653 ```bash lp new_session=test 

654 ['n=foo', {"cmd": "echo fubar", "silent": True}, 'echo $n'] 

655 ``` 

656 ''' 

657 cmd = ''' 

658 

659 === "Cmd" 

660 ```console 

661 $ n=foo 

662 $ echo $n 

663 ``` 

664 ''' 

665 out = ''' 

666 === "Output" 

667 <xterm /> 

668 $ n=foo 

669 $ echo $n 

670 foo 

671 ''' 

672 

673 res = run_lp(md) 

674 assert not 'fubar' in res 

675 check_lines_in(res, cmd, out) 

676 

677 

678def strip_id(s): pytest

679 r, l = [], s.splitlines() 

680 while l: 

681 line = l.pop(0) 

682 if not '<!-- id: ' in line: 

683 r.append(line) 

684 return '\n'.join(line) 

685 

686 

687class python_mode(unittest.TestCase): pytest

688 def test_mode_python_1(self): pytest

689 md = ''' 

690 ```python lp:python fmt=mk_console 

691 assert ctx.get('hide_cmd') == None 

692 print('foo') 

693 print('bar') 

694 ``` 

695 ''' 

696 out = ''' 

697 ```python 

698 print('foo') 

699 foo 

700 ''' 

701 res = run_lp(md) 

702 check_lines_in(res, out) 

703 

704 def test_mode_python_cmd_hidden_and_ctx_availability(self): pytest

705 md = ''' 

706 ```python lp mode=python hide_cmd=True fmt=mk_console 

707 assert ctx['hide_cmd'] 

708 assert ctx['fmt'] == 'mk_console' 

709 print('foo') 

710 ``` 

711 ''' 

712 out = ''' 

713 ```python 

714 foo 

715 ''' 

716 res = run_lp(md) 

717 check_lines_in(res, out) 

718 assert not 'print' in res 

719 

720 def test_mode_python_header_arg_silent(self): pytest

721 md = ''' 

722 ```python lp mode=python silent=True 

723 assert ctx.get('hide_cmd') == None 

724 print('foo') 

725 ``` 

726 ''' 

727 res = run_lp(md) 

728 assert len(res.split('<!-- id: ')) == 3 

729 assert not strip_id(res).strip() 

730 

731 def test_python_new_session(self): pytest

732 """new(!) session same name 2 times:""" 

733 md = ''' 

734 ```python lp:python new_session=pytest1 

735 pytest1var='foo' 

736 ``` 

737 ''' 

738 res = run_lp(md) 

739 md = ''' 

740 ```python lp:python new_session=pytest1 

741 print(pytest1var) 

742 ``` 

743 ''' 

744 res = run_lp(md) 

745 assert 'is not defined' in str(res) 

746 

747 def test_python_session_reuse(self): pytest

748 md = ''' 

749 ```python lp:python new_session=pytest1 

750 pytest1var='foo' 

751 ``` 

752 ''' 

753 res = run_lp(md) 

754 # other session: 

755 md = ''' 

756 ```python lp:python session=pytest2 

757 print(pytest1var) 

758 ``` 

759 ''' 

760 res = run_lp(md) 

761 assert 'is not defined' in str(res) 

762 

763 # firstsession: 

764 md = ''' 

765 ```python lp:python session=pytest1 

766 print(pytest1var) 

767 ``` 

768 ''' 

769 res = run_lp(md) 

770 assert 'foo' in str(res) and not 'is not defined' in str(res) 

771 

772 

773class test_other_modes(unittest.TestCase): pytest

774 def test_mode_make_file(self): pytest

775 fn = '/tmp/test_lp_file_%s' % os.environ['USER'] 

776 md = ''' 

777 ```python lp fn=%s mode=make_file 

778 foo = bar 

779 ``` 

780 ''' 

781 md = md % fn 

782 res = run_lp(md) 

783 out = ''' 

784 ```python 

785 $ cat %s 

786 foo = bar 

787 ``` 

788 ''' 

789 check_lines_in(res, out % fn) 

790 

791 def test_mode_show_file(self): pytest

792 fn = '/tmp/test_lp_file_%s' % os.environ['USER'] 

793 with open(fn, 'w') as fd: 

794 fd.write('foo = bar') 

795 md = ''' 

796 ```console lp fn=%s mode=show_file 

797 ``` 

798 ''' 

799 md = md % fn 

800 res = run_lp(md) 

801 out = ''' 

802 ```console 

803 $ cat %s 

804 foo = bar 

805 ``` 

806 ''' 

807 check_lines_in(res, out % fn) 

808 

809 

810class header_args(unittest.TestCase): pytest

811 def test_presets(self): pytest

812 md = ''' 

813 ```bash lp foo=dir_repo bar=dir_project 

814 stuff 

815 ``` 

816 ''' 

817 d = project.root() 

818 fn = d + '/docs/foo.md' 

819 mds, lps = extract.extract(md) 

820 mock_page(fn) 

821 assert lps[0]['kwargs'] == {'bar': d, 'foo': d} 

822 

823 

824class state(unittest.TestCase): pytest

825 def test_assign(self): pytest

826 md = ''' 

827 ```bash lp 

828 name=joe; echo $name 

829 ``` 

830 ''' 

831 res = run_lp(md) 

832 assert ' joe' in res.split('Output', 1)[1] 

833 

834 def test__assign_with_session_state(self): pytest

835 """Tmux keeps the state. No NEW session in the second call""" 

836 md = ''' 

837 ```bash lp new_session=test 

838 name=joe; echo $name 

839 ``` 

840 ''' 

841 res = run_lp(md) 

842 assert ' joe' in res.split('Output', 1)[1] 

843 

844 md = ''' 

845 ```bash lp session=test 

846 echo "hi $name" 

847 ``` 

848 ''' 

849 res = run_lp(md) 

850 assert ' hi joe' in res.split('Output', 1)[1] 

851 

852 

853# class lang: 

854# def xxtest_lang(): 

855# md = ''' 

856# ```js lp session=test timeout=10000 

857# echo '{\"json\": true}' 

858# ``` 

859# ''' 

860# res = run_lp(md) 

861# breakpoint() # FIXME BREAKPOINT 

862# assert ' joe' in res.split('Output', 1)[1] 

863 

864 

865class fetched_mk_cmd_out(unittest.TestCase): pytest

866 """Format mk_cmd_out (cmd and output tabs) 

867 'Blocks now fetched from the server' 

868 

869 This is the default format. 

870 """ 

871 

872 def test_with_and_without_session_cmd_fetched_out(self): pytest

873 run = 'head %s/test_content |grep --color=never line' % d_test() 

874 for k in '', 'new_session=test': 

875 md = ''' 

876 ```bash lp fetch=usecase _k_ 

877 %s 

878 ``` 

879 ''' 

880 md = md.replace('_k_', k) 

881 cmd = ''' 

882 === "Cmd" 

883 ```console 

884 $ %s 

885 ``` 

886 ''' 

887 out = ''' 

888 === "Output" 

889 <xterm /> 

890 remote_content 

891 ![](./media/test.md_usecase.ansi) 

892 ''' 

893 res = run_lp(md % run) 

894 check_lines_in(res, cmd % run, out) 

895 # done by the js when live: 

896 s = read_file(d_test() + '/media/test.md_usecase.ansi') 

897 if k: 

898 # tmux we have prompt and it changes the ansi slightly: 

899 s = s.split(run, 1)[1] 

900 assert '124mline1' in s 

901 else: 

902 # prompt is in s but rest is ident: 

903 s.endswith(test_content) 

904 

905 

906extr_head = lambda h: mock_page('x') and LP.extract_header_args(h)[1] 906 ↛ exitline 906 didn't run the lambda on line 906pytest

907 

908 

909class headers_easy(unittest.TestCase): pytest

910 def test_headers_easy_1(self): pytest

911 res = extr_head('```bash lp foo=bar') 

912 assert res == {'foo': 'bar'} 

913 

914 def test_headers_easy_2(self): pytest

915 res = extr_head('```bash lp foo=bar bar') 

916 assert res == {'foo': 'bar', 'bar': True} 

917 

918 def test_headers_easy_3(self): pytest

919 res = extr_head('```bash lp foo=bar, bar') 

920 assert LP.easy_args_err in str(res) 

921 

922 def test_headers_easy_4(self): pytest

923 res = extr_head('```bash lp foo="bar, " bar') 

924 assert res == {'bar': True, 'foo': 'bar, '} 

925 

926 def test_headers_easy_5(self): pytest

927 res = extr_head("```bash lp foo='=,bar, ' bar") 

928 assert res == {'bar': True, 'foo': '=,bar, '} 

929 

930 

931class headers_py(unittest.TestCase): pytest

932 def test_headers_py_1(self): pytest

933 res = extr_head('```bash lp foo="bar", bar') 

934 assert LP.easy_args_err in str(res) 

935 assert 'positional argument follows keyword argument' in str(res) 

936 

937 def test_headers_py_2(self): pytest

938 res = extr_head('```bash lp bar, foo="bar"') 

939 assert LP.easy_args_err in str(res) 

940 assert "name 'bar' is not defined" 

941 

942 

943class features(unittest.TestCase): pytest

944 def test_wait(self): pytest

945 

946 md1 = ''' 

947 ```bash lp new_session=test1 

948 ['echo foo', 'wait 0.1', 'echo bar' ] 

949 ``` 

950 ''' 

951 t = now() 

952 res = run_lp(md1) 

953 assert now() - t > 0.1 

954 out = ''' 

955 === "Output" 

956 <xterm /> 

957 $ echo foo 

958 foo 

959 $ echo bar 

960 bar 

961 ''' 

962 check_lines_in(res, out)