1
2# Copyright 2009-2014 Jaap Karssenberg <jaap.karssenberg@gmail.com>
3
4
5
6import tests
7
8import os
9
10from gi.repository import Gtk
11
12from functools import partial
13
14from zim.config import data_file, SectionedConfigDict
15from zim.notebook import Path, Page, Notebook, init_notebook, \
16	interwiki_link, get_notebook_list, NotebookInfo
17from zim.templates import list_templates
18
19from zim.main import ExportCommand, UsageError
20
21from zim.export import *
22from zim.export.layouts import *
23from zim.export.linker import *
24from zim.export.selections import *
25from zim.export.template import *
26from zim.export.exporters.files import *
27from zim.export.exporters.mhtml import MHTMLExporter
28
29from zim.templates import Template
30from zim.templates.expression import ExpressionParameter, \
31	ExpressionFunctionCall, ExpressionList
32
33from zim.notebook import Path
34
35from zim.fs import adapt_from_oldfs
36from zim.newfs import File, Folder, FilePath
37
38
39def md5(f):
40	return _md5(f.raw())
41
42
43
44class TestMultiFileLayout(tests.TestCase):
45
46	#  dir/
47	#   `--> _resources/
48	#   `--> page.html
49	#   `--> page/
50	#         `--> attachment.png
51
52	def runTest(self):
53		dir = self.setUpFolder()
54		rdir = dir.folder('_resources')
55
56
57		layout = MultiFileLayout(dir, 'html')
58		self.assertEqual(layout.relative_root, dir)
59		self.assertEqual(layout.resources_dir(), rdir)
60
61		for path, file, adir in (
62			(Path('Foo'), dir.file('Foo.html'), dir.folder('Foo')),
63			(Path('Foo:Bar'), dir.file('Foo/Bar.html'), dir.folder('Foo/Bar')),
64		):
65			self.assertEqual(layout.page_file(path), file)
66			self.assertEqual(layout.attachments_dir(path), adir)
67
68		self.assertRaises(PathLookupError, layout.page_file, Path(':'))
69
70
71		layout = MultiFileLayout(dir, 'html', namespace=Path('Test'))
72		self.assertEqual(layout.relative_root, dir)
73		self.assertEqual(layout.resources_dir(), rdir)
74
75		for path, file, adir in (
76			(Path('Test:Foo'), dir.file('Foo.html'), dir.folder('Foo')),
77			(Path('Test:Foo:Bar'), dir.file('Foo/Bar.html'), dir.folder('Foo/Bar')),
78		):
79			self.assertEqual(layout.page_file(path), file)
80			self.assertEqual(layout.attachments_dir(path), adir)
81
82		self.assertRaises(PathLookupError, layout.page_file, Path(':'))
83		self.assertRaises(PathLookupError, layout.page_file, Path('Foo'))
84
85
86class TestFileLayout(tests.TestCase):
87
88	#  page.html
89	#  page_files/
90	#   `--> attachment.png
91	#   `--> subpage.html
92	#   `--> subpage/attachment.pdf
93	#   `--> _resources/
94
95	def runTest(self):
96		tdir = self.setUpFolder()
97		topfile = tdir.file('page.html')
98		dir = tdir.folder('page_files')
99		rdir = dir.folder('_resources')
100
101		layout = FileLayout(topfile, Path('Test'), 'html')
102		self.assertEqual(layout.relative_root, dir.parent())
103		self.assertEqual(layout.resources_dir(), rdir)
104
105		for path, file, adir in (
106			(Path('Test'), topfile, dir),
107			(Path('Test:Foo'), dir.file('Foo.html'), dir.folder('Foo')),
108			(Path('Test:Foo:Bar'), dir.file('Foo/Bar.html'), dir.folder('Foo/Bar')),
109		):
110			self.assertEqual(layout.page_file(path), file)
111			self.assertEqual(layout.attachments_dir(path), adir)
112
113		self.assertRaises(PathLookupError, layout.page_file, Path(':'))
114		self.assertRaises(PathLookupError, layout.page_file, Path('Foo'))
115
116
117class TestSingleFileLayout(tests.TestCase):
118
119	# page.html
120	#  page_files/
121	#   `--> attachment.png
122	#   `--> subpage/attachment.pdf
123	#   `--> _resources/
124
125	def runTest(self):
126		tdir = self.setUpFolder()
127		topfile = tdir.file('page.html')
128		dir = tdir.folder('page_files')
129		rdir = dir.folder('_resources')
130
131		layout = SingleFileLayout(topfile, page=Path('Test'))
132		self.assertEqual(layout.relative_root, dir.parent())
133		self.assertEqual(layout.resources_dir(), rdir)
134
135		for path, file, adir in (
136			(Path('Test'), topfile, dir),
137			(Path('Test:Foo'), topfile, dir.folder('Foo')),
138			(Path('Test:Foo:Bar'), topfile, dir.folder('Foo/Bar')),
139		):
140			self.assertEqual(layout.page_file(path), file)
141			self.assertEqual(layout.attachments_dir(path), adir)
142
143		self.assertRaises(PathLookupError, layout.page_file, Path(':'))
144		self.assertRaises(PathLookupError, layout.page_file, Path('Foo'))
145
146
147
148class TestLinker(tests.TestCase):
149
150	def runTest(self):
151		notebook = self.setUpNotebook(content=('foo', 'bar', 'foo:bar',))
152		dir = Dir(notebook.folder.parent().folder('layout').path)
153
154		layout = MultiFileLayout(dir.subdir('layout'), 'html')
155		source = Path('foo:bar')
156		output = layout.page_file(source)
157
158		linker = ExportLinker(notebook, layout,
159			source=source, output=output, usebase=True
160		)
161
162		self.assertEqual(linker.link('+dus'), './bar/dus.html')
163		self.assertEqual(linker.link('dus'), './dus.html')
164		self.assertEqual(linker.link('./dus.pdf'), './bar/dus.pdf')
165		self.assertEqual(linker.link('../dus.pdf'), './dus.pdf')
166		self.assertEqual(linker.link('../../dus.pdf'), '../dus.pdf')
167
168		extpath = 'C:\\dus.pdf' if os.name == 'nt' else '/duf.pdf'
169		self.assertEqual(linker.link(extpath), FilePath(extpath).uri)
170
171		# TODO:
172		# 	img
173		# 	icon
174		# 	resource
175		# 	resolve_source_file
176		# 	page_object
177		# 	file_object
178		#
179		#	document_root_url
180
181		## setup environment for interwiki link
182		if os.name == 'nt':
183			uri = 'file:///C:/foo'
184		else:
185			uri = 'file:///foo'
186
187		list = get_notebook_list()
188		list.append(NotebookInfo(uri, interwiki='foo'))
189		list.write()
190		##
191
192		href = interwiki_link('foo?Ideas:Task List')
193		self.assertIsNotNone(href)
194		self.assertEqual(linker.link('foo?Ideas:Task List'), uri + '/Ideas/Task_List.txt')
195
196
197
198
199
200class TestExportTemplateContext(tests.TestCase):
201
202	def setUp(self):
203		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
204		output_folder = self.setUpFolder()
205		layout = MultiFileLayout(output_folder, 'html')
206		linker_factory = partial(ExportLinker,
207			notebook=notebook,
208			layout=layout,
209			output=layout.page_file(Path('test')),
210			usebase=True
211		)
212		dumper_factory = get_format('html').Dumper
213
214		title = 'Test Export'
215		self.content = [notebook.get_page(Path('Test:foo'))]
216		self.context = ExportTemplateContext(
217			notebook, linker_factory, dumper_factory,
218			title, self.content, special=None,
219			home=None, up=None, prevpage=None, nextpage=None,
220			links=None,
221		)
222
223	def runTest(self):
224		def get(name):
225			param = ExpressionParameter(name)
226			return param(self.context)
227
228		# Test context setup
229		self.assertIsInstance(get('generator.name'), str)
230		self.assertTrue(get('generator.name').startswith('Zim'))
231		self.assertIsInstance(get('generator.user'), str)
232
233		self.assertEqual(get('title'), 'Test Export')
234
235		pages = list(get('pages'))
236		self.assertEqual(len(pages), 1)
237		self.assertTrue(all(isinstance(o, PageProxy) for o in pages))
238		self.assertEqual(pages[0]._page, self.content[0])
239		## TODO
240		# pages
241		#   content
242		#   special
243		#
244		# navigation	- links to other export pages (if not included here)
245		#	home
246		#	up
247		# 	prev			-- prev export file or None
248		# 	next			-- next export file or None
249		#
250		# links			-- links to other export pages (index & plugins / ...) - sorted dict to have Index, Home first followed by plugins
251		#
252		#	link
253		#		.name
254		#		.basename
255
256
257		# Test PageProxy
258		self.context['mypage'] = pages[0]
259		self.assertEqual(get('mypage.title'), 'Foo')
260		self.assertEqual(get('mypage.name'), 'Test:foo')
261		self.assertEqual(get('mypage.namespace'), 'Test')
262		self.assertEqual(get('mypage.basename'), 'foo')
263
264		self.assertEqual(get('mypage.heading'), 'Foo')
265		self.assertIsInstance(get('mypage.content'), str)
266		self.assertIsInstance(get('mypage.body'), str)
267		#TODO self.assertIsInstance(get('mypage.meta'), dict)
268
269
270		#			.links
271		#			.backlinks
272		#			.attachments
273		#
274
275
276		# Test HeadingsProxy
277		mycall = ExpressionFunctionCall(
278			ExpressionParameter('mypage.headings'),
279			ExpressionList(),
280		)
281		headings = list(mycall(self.context))
282		self.assertEqual(len(headings), 2)
283
284		self.context['h1'] = headings[0]
285		self.context['h2'] = headings[1]
286		self.assertEqual(get('h1.level'), 1)
287		self.assertEqual(get('h2.level'), 2)
288		self.assertIsInstance(get('h1.heading'), str)
289		self.assertIsInstance(get('h1.body'), str)
290		self.assertIsInstance(get('h1.content'), str)
291
292		# Test FileProxy
293		#				file
294		#					.basename
295		#					.mtime
296		#					.size
297		#
298
299		## TODO
300		# options		-- dict with template options (for format)
301		#
302		# toc([page])			-- iter of headings in this page or all of pages
303		# index([namespace])	-- index of full export job, not just in this page
304		# uri(link|file)
305		# resource(file)
306		# anchor(page|section)
307		#
308		# From template:
309		# range() / len() / sorted() / reversed()
310		# strftime()
311		# strfcal()
312		#
313		# test single page by "IF loop.first and loop.last"
314
315
316		## TODO test all of the attributes / items accesible through the
317		##      context dict are string, expressionfunction, or proxy defined in this module
318
319		## TODO test modification of options by template ends up in context
320		##      test setting other local paramters in template does NOT affect context object
321		##      test setting page meta is NOT allowed
322
323		## TODO list simple template with processor to test looping through pages
324
325
326
327
328class TestPageSelections(tests.TestCase):
329
330	def _test_iface(self, selection):
331		self.assertIsNotNone(selection.name)
332		self.assertIsNotNone(selection.title)
333		self.assertIsNotNone(selection.notebook)
334		for p in selection:
335			self.assertIsInstance(p, Page)
336
337	# TODO add alternative method to walk names for ToC
338	# TODO add __len__ that gives total pages for progress
339	# TODO Use collections subclass to make interface complete ?
340
341	def testAllPages(self):
342		selection = AllPages(self.setUpNotebook(content=tests.FULL_NOTEBOOK))
343		self._test_iface(selection)
344
345	def testSinglePage(self):
346		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
347		page = notebook.get_page(Path('Test'))
348		selection = SinglePage(notebook, page)
349		self._test_iface(selection)
350		self.assertIsNotNone(selection.prefix)
351
352	def testSubPages(self):
353		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
354		page = notebook.get_page(Path('Test'))
355		selection = SinglePage(notebook, page)
356		self._test_iface(selection)
357		self.assertIsNotNone(selection.prefix)
358
359
360class TestMultiFileExporter(tests.TestCase):
361
362	def runTest(self):
363		folder = self.setUpFolder()
364		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
365		pages = AllPages(notebook)
366
367		exporter = build_notebook_exporter(folder, 'html', 'Default', index_page='Index')
368		self.assertIsInstance(exporter, MultiFileExporter)
369		exporter.export(pages)
370
371		file = exporter.layout.page_file(Path('roundtrip'))
372		text = file.read()
373		self.assertIn('Lorem ipsum dolor sit amet', text)
374
375		file = exporter.layout.page_file(Path('Index'))
376		text = file.read()
377		self.assertIn('<li><a href="./roundtrip.html" title="roundtrip" class="page">roundtrip</a></li>', text)
378
379
380class TestSingleFileExporter(tests.TestCase):
381
382	def runTest(self):
383		folder = self.setUpFolder()
384		file = folder.file('export.html')
385		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
386		pages = AllPages(notebook)
387
388		exporter = build_single_file_exporter(file, 'html', 'Default')
389		self.assertIsInstance(exporter, SingleFileExporter)
390		exporter.export(pages)
391
392		text = file.read()
393		self.assertIn('Lorem ipsum dolor sit amet', text)
394
395
396class TestMHTMLExporter(tests.TestCase):
397
398	def runTest(self):
399		dir = self.setUpFolder()
400		file = dir.file('export.mht')
401		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
402		pages = AllPages(notebook)
403
404		exporter = build_mhtml_file_exporter(file, 'Default')
405		self.assertIsInstance(exporter, MHTMLExporter)
406		exporter.export(pages)
407
408		text = file.read()
409		self.assertIn('Lorem ipsum dolor sit amet', text)
410
411
412class TestTemplateOptions(tests.TestCase):
413
414	def runTest(self):
415		dir = self.setUpFolder()
416		file = dir.file('test.tex')
417		page = Path('roundtrip')
418		exporter = build_page_exporter(file, 'latex', 'Article', page)
419
420		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
421		selection = SinglePage(notebook, page)
422
423		with tests.LoggingFilter('zim.formats.latex', 'Could not find latex equation'):
424			exporter.export(selection)
425		result = file.read()
426		#~ print result
427		self.assertIn('\section{Head1}', result) # this implies that document_type "article" was indeed used
428
429
430class TestExportFormat(object):
431
432	def runTest(self):
433		output_folder = self.setUpFolder()
434		notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK)
435
436		i = 0
437		print('')
438		for template, file in list_templates(self.format):
439			#print 'Testing template: %s' % template
440			pages = AllPages(notebook) # TODO - sub-section ?
441			exporter = build_notebook_exporter(output_folder.folder(template), self.format, template)
442			self.assertIsInstance(exporter, MultiFileExporter)
443
444			with tests.LoggingFilter('zim.formats.latex', 'Could not find latex equation'):
445				exporter.export(pages)
446
447			file = exporter.layout.page_file(Path('roundtrip'))
448			text = file.read()
449			self.assertIn('Lorem ipsum dolor sit amet', text)
450
451			i += 1
452
453		if self.format in ('html', 'latex'):
454			self.assertTrue(i >= 3) # Ensure we actually tested something ..
455
456
457class TestExportFormatHtml(TestExportFormat, tests.TestCase):
458	format = 'html'
459
460
461class TestExportFormatLatex(TestExportFormat, tests.TestCase):
462	format = 'latex'
463
464
465class TestExportFormatMarkDown(TestExportFormat, tests.TestCase):
466	format = 'markdown'
467
468
469class TestExportFormatRst(TestExportFormat, tests.TestCase):
470	format = 'rst'
471
472
473class TestExportCommand(tests.TestCase):
474
475	def setUp(self):
476		self.tmpfolder = self.setUpFolder(mock=tests.MOCK_ALWAYS_REAL)
477		self.notebookfolder = self.tmpfolder.folder('notebook')
478		init_notebook(self.notebookfolder)
479
480	def testOptions(self):
481		# Only testing we get a valid exporter, not the full command,
482		# because the command is very slow
483
484		## Full notebook, minimal options
485		cmd = ExportCommand('export')
486		cmd.parse_options(self.notebookfolder.path)
487		self.assertRaises(UsageError, cmd.get_exporter, None)
488
489		cmd = ExportCommand('export')
490		cmd.parse_options(self.notebookfolder.path,
491			'--output', self.tmpfolder.folder('output').path,
492		)
493		exp = cmd.get_exporter(None)
494		self.assertIsInstance(exp, MultiFileExporter)
495		self.assertIsInstance(exp.layout, MultiFileLayout)
496		self.assertIsInstance(exp.layout.dir, Folder)
497		self.assertIsInstance(exp.template, Template)
498		self.assertIsNone(exp.document_root_url)
499		self.assertIsNotNone(exp.format)
500		self.assertIsNone(exp.index_page)
501
502		## Full notebook, full options
503		cmd = ExportCommand('export')
504		cmd.parse_options(self.notebookfolder.path,
505			'--format', 'markdown',
506			'--template', './tests/data/TestTemplate.html',
507			'--output', self.tmpfolder.folder('output').path,
508			'--root-url', '/foo/',
509			'--index-page', 'myindex',
510			'--overwrite',
511		)
512		exp = cmd.get_exporter(None)
513		self.assertIsInstance(exp, MultiFileExporter)
514		self.assertIsInstance(exp.layout, MultiFileLayout)
515		self.assertIsInstance(exp.layout.dir, Folder)
516		self.assertIsInstance(exp.template, Template)
517		self.assertIsNotNone(exp.document_root_url)
518		self.assertIsNotNone(exp.format)
519		self.assertIsNotNone(exp.index_page)
520
521
522		## Full notebook, single page
523		cmd = ExportCommand('export')
524		cmd.parse_options(self.notebookfolder.path,
525			'--format', 'markdown',
526			'--template', './tests/data/TestTemplate.html',
527			'--output', self.tmpfolder.file('output.md').path,
528			'-s'
529		)
530		exp = cmd.get_exporter(None)
531		self.assertIsInstance(exp, SingleFileExporter)
532		self.assertIsInstance(exp.layout, SingleFileLayout)
533		self.assertIsInstance(exp.layout.file, File)
534
535		## Single page
536		cmd = ExportCommand('export')
537		cmd.parse_options(self.notebookfolder.path, 'Foo:Bar',
538			'--output', self.tmpfolder.folder('output').path,
539		)
540		exp = cmd.get_exporter(Path('Foo:Bar'))
541		self.assertIsInstance(exp, MultiFileExporter)
542		self.assertIsInstance(exp.layout, FileLayout)
543		self.assertIsInstance(exp.layout.file, File)
544		self.assertIsInstance(exp.template, Template)
545		self.assertIsNone(exp.document_root_url)
546		self.assertIsNotNone(exp.format)
547		self.assertIsNone(exp.index_page)
548
549		cmd = ExportCommand('export')
550		cmd.parse_options(self.notebookfolder.path, 'Foo:Bar',
551			'--recursive',
552			'--output', self.tmpfolder.folder('output').path,
553		)
554		exp = cmd.get_exporter(Path('Foo:Bar'))
555		self.assertIsInstance(exp, MultiFileExporter)
556		self.assertIsInstance(exp.layout, FileLayout)
557		self.assertIsInstance(exp.layout.file, File)
558		self.assertIsInstance(exp.template, Template)
559		self.assertIsNone(exp.document_root_url)
560		self.assertIsNotNone(exp.format)
561		self.assertIsNone(exp.index_page)
562
563		cmd = ExportCommand('export')
564		cmd.parse_options(self.notebookfolder.path, 'Foo:Bar',
565			'-rs',
566			'--output', self.tmpfolder.folder('output').path,
567		)
568		exp = cmd.get_exporter(Path('Foo:Bar'))
569		self.assertIsInstance(exp, SingleFileExporter)
570		self.assertIsInstance(exp.layout, SingleFileLayout)
571		self.assertIsInstance(exp.layout.file, File)
572		self.assertIsInstance(exp.template, Template)
573		self.assertIsNone(exp.document_root_url)
574		self.assertIsNotNone(exp.format)
575
576		## MHTML exporter
577		cmd = ExportCommand('export')
578		cmd.parse_options(self.notebookfolder.path, 'Foo:Bar',
579			'-rs', '--format', 'mhtml',
580			'--output', self.tmpfolder.folder('output').path,
581		)
582		exp = cmd.get_exporter(Path('Foo:Bar'))
583		self.assertIsInstance(exp, MHTMLExporter)
584		self.assertIsInstance(exp.file, File)
585		self.assertIsInstance(exp.template, Template)
586		self.assertIsNone(exp.document_root_url)
587
588	def testExport(self):
589		# Only test single page, just to show "run()" works
590		file = self.notebookfolder.file('Foo/Bar.txt')
591		file.write(
592			'Content-Type: text/x-zim-wiki\n\n'
593			'=== Foo\ntest 123\n'
594		)
595
596		output = self.tmpfolder.file('output.html')
597
598		cmd = ExportCommand('export')
599		cmd.parse_options(self.notebookfolder.path, 'Foo:Bar',
600			'--output', output.path,
601			'--template', 'tests/data/TestTemplate.html'
602		)
603		cmd.run()
604
605		self.assertTrue(output.exists())
606		html = output.read()
607		self.assertTrue('<h1>Foo' in html)
608		self.assertTrue('test 123' in html)
609
610
611class TestExportDialog(tests.TestCase):
612
613	def testDialog(self):
614		'''Test ExportDialog'''
615		from zim.gui.exportdialog import ExportDialog, ExportDoneDialog
616
617		dir = self.setUpFolder(mock=tests.MOCK_ALWAYS_REAL)
618		notebook = self.setUpNotebook(content={'foo': 'test 123\n', 'bar': 'test 123\n'})
619
620		window = Gtk.Window()
621		window.notebook = notebook
622
623		## Test export all pages
624		dialog = ExportDialog(window, notebook, Path('foo'))
625		dialog.set_page(0)
626
627		page = dialog.get_page()
628		page.form['selection'] = 'all'
629		dialog.next_page()
630
631		page = dialog.get_page()
632		page.form['format'] = 'HTML'
633		page.form['template'] = 'Print'
634		dialog.next_page()
635
636		page = dialog.get_page()
637		page.form['folder'] = dir
638		page.form['index'] = 'INDEX_PAGE'
639		with tests.DialogContext(ExportDoneDialog):
640			dialog.assert_response_ok()
641
642		file = dir.file('foo.html')
643		self.assertTrue(file.exists())
644		text = file.read()
645		self.assertTrue('<!-- Wiki content -->' in text, 'template used')
646
647		#~ print dialog.uistate
648		self.assertEqual(dialog.uistate, window.notebook.state['ExportDialog'])
649		self.assertIsInstance(dialog.uistate['output_folder'], Dir)
650
651		## Test export single page
652		dialog = ExportDialog(window, notebook, Path('foo'))
653		dialog.set_page(0)
654
655		page = dialog.get_page()
656		page.form['selection'] = 'page'
657		page.form['page'] = 'foo'
658		dialog.next_page()
659
660		page = dialog.get_page()
661		page.form['format'] = 'HTML'
662		page.form['template'] = 'Print'
663		dialog.next_page()
664
665		page = dialog.get_page()
666		page.form['file'] = dir.file('SINGLE_FILE_EXPORT.html').path
667		with tests.DialogContext(ExportDoneDialog):
668			dialog.assert_response_ok()
669
670		file = dir.file('SINGLE_FILE_EXPORT.html')
671		self.assertTrue(file.exists())
672		text = file.read()
673		self.assertTrue('<!-- Wiki content -->' in text, 'template used')
674
675		#~ print dialog.uistate
676		self.assertEqual(dialog.uistate, window.notebook.state['ExportDialog'])
677		self.assertIsInstance(adapt_from_oldfs(dialog.uistate['output_file']), File)
678		self.assertIsInstance(adapt_from_oldfs(dialog.uistate['output_folder']), Folder) # Keep this in state as well
679
680	def testLogging(self):
681		from zim.gui.exportdialog import LogContext
682
683		mylogger = logging.getLogger('zim.export')
684		foologger = logging.getLogger('zim.foo')
685		log_context = LogContext()
686
687		with tests.LoggingFilter(logger='zim', message='Test'):
688			with log_context:
689				mylogger.warn('Test export warning')
690				mylogger.debug('Test export debug')
691				foologger.warn('Test foo')
692
693		file = log_context.file
694		self.assertTrue(file.exists())
695		#~ print(">>>\n", file.read(), "\n<<<")
696		self.assertTrue('Test export warning' in file.read())
697		self.assertFalse('Test export debug' in file.read())
698		self.assertFalse('Test foo' in file.read())
699
700
701class TestOverwrite(tests.TestCase):
702
703	def testSingleFile(self):
704		# TODO: run this with mock file
705		# TODO: ensure template has resources
706		# TODO: add attachements to test notebook
707
708		folder = self.setUpFolder(mock=tests.MOCK_ALWAYS_REAL)
709		file = folder.file('test.html')
710		exporter = build_single_file_exporter(file, 'html', 'Default.html')
711
712		notebook = self.setUpNotebook(content={'foo': 'test 123\n', 'bar': 'test 123\n'})
713		pages = AllPages(notebook)
714
715		# Now do it twice - should not raise for file exists
716		exporter.export(pages)
717		exporter.export(pages)
718
719	def testMultiFile(self):
720		# TODO: ensure template has resources
721		# TODO: add attachements to test notebook
722
723		folder = self.setUpFolder(mock=tests.MOCK_ALWAYS_REAL)
724		exporter = build_notebook_exporter(folder, 'html', 'Default.html')
725
726		notebook = self.setUpNotebook(content={'foo': 'test 123\n', 'bar': 'test 123\n'})
727		pages = AllPages(notebook)
728
729		# Now do it twice - should not raise for file exists
730		exporter.export(pages)
731		exporter.export(pages)
732