Exemplo n.º 1
0
class TestExport(tests.TestCase):

	options = {'format': 'html', 'template': 'Default'}

	def setUp(self):
		self.dir = Dir(self.create_tmp_dir('exported_files'))

	def export(self):
		notebook = tests.new_notebook(fakedir='/foo/bar')

		exporter = Exporter(notebook, **self.options)
		exporter.export_all(self.dir)

	def runTest(self):
		'''Test export notebook to html'''
		self.export()

		file = self.dir.file('Test/foo.html')
		self.assertTrue(file.exists())
		text = file.read()
		self.assertTrue('<!-- Wiki content -->' in text, 'template used')
		self.assertTrue('<h1>Foo</h1>' in text)

		for icon in ('checked-box',): #'unchecked-box', 'xchecked-box'):
			# Default template doesn't have its own checkboxes
			self.assertTrue(self.dir.file('_resources/%s.png' % icon).exists())
			self.assertEqual(
				md5(self.dir.file('_resources/%s.png' % icon)),
				md5(data_file('pixmaps/%s.png' % icon))
			)
Exemplo n.º 2
0
	def runTest(self):
		for creator in self.creators:
			thumbdir = Dir(self.create_tmp_dir(creator.__name__))

			dir = Dir('./data/pixmaps')
			for i, basename in enumerate(dir.list()):
				file = dir.file(basename)
				thumbfile = thumbdir.file('thumb--' + basename)

				self.assertFalse(thumbfile.exists())
				pixbuf = creator(file, thumbfile, THUMB_SIZE_NORMAL)
				self.assertIsInstance(pixbuf, gtk.gdk.Pixbuf)
				self.assertTrue(thumbfile.exists())

				pixbuf = gtk.gdk.pixbuf_new_from_file(thumbfile.encodedpath)
				self.assertEqual(pixbuf.get_option('tEXt::Thumb::URI'), file.uri)
				self.assertTrue(pixbuf.get_option('tEXt::Thumb::URI').startswith('file:///'))
					# Specific requirement of spec to use file:/// and not file://localhost/
				self.assertEqual(int(pixbuf.get_option('tEXt::Thumb::MTime')), int(file.mtime()))

			self.assertTrue(i > 3)

			thumbfile = thumbdir.file('thumb-test.txt')
			self.assertRaises(
				ThumbnailCreatorFailure,
				creator, File('./README.txt'), thumbfile, THUMB_SIZE_NORMAL
			)
Exemplo n.º 3
0
	def runTest(self):
		'''Test FileEntry widget'''
		path = Path('Foo:Bar')
		entry = self.entry
		entry.set_use_relative_paths(self.notebook, path)

		home = Dir('~')
		dir = self.notebook.dir
		for file, text in (
			(home.file('zim-test.txt'), '~/zim-test.txt'),
			(dir.file('Foo/Bar/test.txt'), './test.txt'),
			(File('/test.txt'), File('/test.txt').path), # win32 save
		):
			entry.set_file(file)
			self.assertEqual(entry.get_text(), text)
			self.assertEqual(entry.get_file(), file)

		self.notebook.config['Notebook']['document_root'] = './notebook_document_root'
		self.notebook.do_properties_changed() # parse config
		doc_root = self.notebook.document_root
		self.assertEqual(doc_root, dir.subdir('notebook_document_root'))

		for file, text in (
			(home.file('zim-test.txt'), '~/zim-test.txt'),
			(dir.file('Foo/Bar/test.txt'), './test.txt'),
			(File('/test.txt'), File('/test.txt').uri), # win32 save
			(doc_root.file('test.txt'), '/test.txt'),
		):
			entry.set_file(file)
			self.assertEqual(entry.get_text(), text)
			self.assertEqual(entry.get_file(), file)

		entry.set_use_relative_paths(self.notebook, None)

		for file, text in (
			(home.file('zim-test.txt'), '~/zim-test.txt'),
			(dir.file('Foo/Bar/test.txt'), './Foo/Bar/test.txt'),
			(File('/test.txt'), File('/test.txt').uri), # win32 save
			(doc_root.file('test.txt'), '/test.txt'),
		):
			entry.set_file(file)
			self.assertEqual(entry.get_text(), text)
			self.assertEqual(entry.get_file(), file)

		entry.set_use_relative_paths(notebook=None)

		for file, text in (
			(home.file('zim-test.txt'), '~/zim-test.txt'),
			#~ (dir.file('Foo/Bar/test.txt'), './test.txt'),
			(File('/test.txt'), File('/test.txt').path), # win32 save
		):
			entry.set_file(file)
			self.assertEqual(entry.get_text(), text)
			self.assertEqual(entry.get_file(), file)
Exemplo n.º 4
0
Arquivo: __init__.py Projeto: gdw2/zim
class StubLinker(BaseLinker):
	'''Linker used for testing - just gives back the link as it was
	parsed. DO NOT USE outside of testing.
	'''

	def __init__(self):
		BaseLinker.__init__(self)
		self.path = '<PATH>'
		self.base = Dir('<NOBASE>')

	def resolve_file(self, link):
		return self.base.file(link)
			# Very simple stub, allows finding files be rel path for testing

	def icon(self, name):
		return 'icon:' + name

	def resource(self, path):
		return path

	def link_page(self, link):
		return link

	def link_file(self, path):
		return path
Exemplo n.º 5
0
	def runTest(self):
		from pprint import pprint

		from zim.fs import File
		file = File('./tests/data/TestTemplate.html')

		templ = Template(file)
		#~ pprint(templ.parts) # parser output

		output = []
		templ.process(output, {
			'title': 'THIS IS THE TITLE',
			'generator': {
				'name': 'ZIM VERSION',
			},
			'navigation': {
				'prev': None,
				'next': None,
			},
			'links': {},
			'pages': [
				{ # page
					'name': 'page',
					'heading': 'HEAD',
					'body': 'BODY',
					'properties': {
						'type': 'PAGE',
					},
					'backlinks': [
						{'name': 'LINK1'},
						{'name': 'LINK2'},
						{'name': 'LINK3'},
					],
					'attachments': [
						{'name': 'FILE1', 'basename': 'FILE1', 'size': '1k'},
						{'name': 'FILE2', 'basename': 'FILE2', 'size': '1k'},
					],
				},
			],
			'uri': ExpressionFunction(lambda l: "URL:%s" % l['name']),
			'anchor': ExpressionFunction(lambda l: "ANCHOR:%s" % l['name']),
		})
		#~ print ''.join(output)

		# TODO assert something

		### Test empty template OK as well
		dir = Dir(self.create_tmp_dir())
		file = dir.file('empty.html')

		self.assertRaises(FileNotFoundError, Template, file)

		file.touch()
		templ = Template(file)
		output = []
		templ.process(output, {})
		self.assertEqual(output, [])
Exemplo n.º 6
0
class TestBuildNotebook(tests.TestCase):
	# Test including automount !

	def setUp(self):
		self.tmpdir = Dir(self.get_tmp_name())
		self.notebookdir = self.tmpdir.subdir('notebook')

		script = self.tmpdir.file('mount.py')
		script.write('''\
import os
import sys
notebook = sys.argv[1]
os.mkdir(notebook)
os.mkdir(notebook + '/foo')
for path in (
	notebook + "/notebook.zim",
	notebook + "/foo/bar.txt"
):
	fh = open(path, 'w')
	fh.write("")
	fh.close()
''')

		automount = XDG_CONFIG_HOME.file('zim/automount.conf')
		assert not automount.exists()
		automount.write('''\
[Path %s]
mount=%s %s
''' % (self.notebookdir.path, script.path, self.notebookdir.path))

	#~ def tearDown(self):
		#~ automount = XDG_CONFIG_HOME.file('zim/automount.conf')
		#~ automount.remove()

	def runTest(self):
		def mockconstructor(dir):
			return dir

		for uri, path in (
			(self.notebookdir.uri, None),
			(self.notebookdir.file('notebook.zim').uri, None),
			(self.notebookdir.file('foo/bar.txt').uri, Path('foo:bar')),
			#~ ('zim+' + tmpdir.uri + '?aaa:bbb:ccc', Path('aaa:bbb:ccc')),
		):
			#~ print ">>", uri
			info = NotebookInfo(uri)
			nb, p = build_notebook(info, notebookclass=mockconstructor)
			self.assertEqual(nb, self.notebookdir)
			self.assertEqual(p, path)

		info = NotebookInfo(self.notebookdir.file('nonexistingfile.txt'))
		self.assertRaises(FileNotFoundError, build_notebook, info)
Exemplo n.º 7
0
	def export(self):
		dir = Dir(self.create_tmp_dir('source_files'))
		init_notebook(dir)
		notebook = Notebook(dir=dir)
		for name, text in tests.WikiTestData:
			page = notebook.get_page(Path(name))
			page.parse('wiki', text)
			notebook.store_page(page)
		file = dir.file('Test/foo.txt')
		self.assertTrue(file.exists())

		zim = Application(('./zim.py', '--export', '--template=Default', dir.path, '--output', self.dir.path, '--index-page', 'index'))
		zim.run()
Exemplo n.º 8
0
	def testCreateThumbnail(self):
		manager = ThumbnailManager()

		dir = Dir(self.create_tmp_dir())
		file = dir.file('zim.png')
		File('./data/zim.png').copyto(file)
		self.assertTrue(file.exists())
		self.assertTrue(file.isimage())
		self.removeThumbnail(manager, file)

		# Thumbfile does not exist
		thumbfile, pixbuf = manager.get_thumbnail(file, 64, create=False)
		self.assertEqual((thumbfile, pixbuf), (None, None))

		thumbfile, pixbuf = manager.get_thumbnail(file, 64)
		self.assertTrue(thumbfile.exists())
		self.assertIsInstance(pixbuf, gtk.gdk.Pixbuf)

		thumbfile, pixbuf = manager.get_thumbnail(file, 64)
		self.assertTrue(thumbfile.exists())
		self.assertIsInstance(pixbuf, gtk.gdk.Pixbuf)

		import stat
		mode = os.stat(thumbfile.encodedpath).st_mode
		self.assertEqual(stat.S_IMODE(mode), 0600)
		mode = os.stat(thumbfile.dir.dir.encodedpath).st_mode # thumnails dir
		self.assertEqual(stat.S_IMODE(mode), 0700)

		# Change mtime to make thumbfile invalid
		oldmtime = file.mtime()
		os.utime(file.encodedpath, None)
		self.assertNotEqual(file.mtime(), oldmtime)

		thumbfile, pixbuf = manager.get_thumbnail(file, 64, create=False)
		self.assertEqual((thumbfile, pixbuf), (None, None))

		thumbfile, pixbuf = manager.get_thumbnail(file, 64)
		self.assertTrue(thumbfile.exists())
		self.assertIsInstance(pixbuf, gtk.gdk.Pixbuf)

		# ensure next call to get_thumbnail cannot call create_thumbnail
		manager.create_thumbnail = None

		thumbfile, pixbuf = manager.get_thumbnail(file, 64)
		self.assertTrue(thumbfile.exists())
		self.assertIsInstance(pixbuf, gtk.gdk.Pixbuf)

		# Test remove
		self.removeThumbnail(manager, file)
Exemplo n.º 9
0
	def testQueue(self):
		queue = ThumbnailQueue()
		self.assertTrue(queue.queue_empty())

		# Test input / output
		queue.queue_thumbnail_request(File('./README.txt'), 64)
			# put an error in the queue

		dir = Dir('./data/pixmaps')
		pixmaps = set()
		for basename in dir.list():
			file = dir.file(basename)
			pixmaps.add(file)
			queue.queue_thumbnail_request(file, 64)

		self.assertFalse(queue.queue_empty())

		with tests.LoggingFilter('zim.plugins.attachmentbrowser', 'Exception'):
			queue.start()

			seen = set()
			i = len(pixmaps)
			while i > 0:
				i -= 1
				file, size, thumbfile, pixbuf, mtime = queue.get_ready_thumbnail(block=True)
				seen.add(file)
				self.assertEqual(size, 64)
				self.assertTrue(thumbfile.exists())
				self.assertIsInstance(pixbuf, gtk.gdk.Pixbuf)
				self.assertEqual(mtime, file.mtime())

		self.assertEqual(seen, pixmaps)

		# Test clear
		self.assertTrue(queue.queue_empty())
		for file in pixmaps:
			queue.queue_thumbnail_request(file, 64)
		self.assertFalse(queue.queue_empty())
		queue.start()
		time.sleep(0.1)
		queue.clear_queue()
		self.assertTrue(queue.queue_empty())
Exemplo n.º 10
0
	def runTest(self):
		'''Test ExportDialog'''
		from zim.gui.exportdialog import ExportDialog

		dir = Dir(self.create_tmp_dir())

		notebook = tests.new_notebook(fakedir='/foo/bar')

		ui = tests.MockObject()
		ui.notebook = notebook
		ui.page = Path('foo')
		ui.mainwindow = None
		ui.uistate = ConfigDict()

		## Test export all pages
		dialog = ExportDialog(ui)
		dialog.set_page(0)

		page = dialog.get_page()
		page.form['selection'] = 'all'
		dialog.next_page()

		page = dialog.get_page()
		page.form['format'] = 'HTML'
		page.form['template'] = 'Print'
		dialog.next_page()

		page = dialog.get_page()
		page.form['folder'] = dir
		page.form['index'] = 'INDEX_PAGE'
		dialog.assert_response_ok()

		file = dir.file('Test/foo.html')
		self.assertTrue(file.exists())
		text = file.read()
		self.assertTrue('<!-- Wiki content -->' in text, 'template used')
		self.assertTrue('<h1>Foo</h1>' in text)

		#~ print dialog.uistate
		self.assertEqual(dialog.uistate, ui.uistate['ExportDialog'])
		self.assertIsInstance(dialog.uistate['output_folder'], Dir)

		## Test export single page
		dialog = ExportDialog(ui)
		dialog.set_page(0)

		page = dialog.get_page()
		page.form['selection'] = 'page'
		page.form['page'] = 'Test:foo'
		dialog.next_page()

		page = dialog.get_page()
		page.form['format'] = 'HTML'
		page.form['template'] = 'Print'
		dialog.next_page()

		page = dialog.get_page()
		page.form['file'] = dir.file('SINGLE_FILE_EXPORT.html').path
		dialog.assert_response_ok()

		file = dir.file('SINGLE_FILE_EXPORT.html')
		self.assertTrue(file.exists())
		text = file.read()
		self.assertTrue('<!-- Wiki content -->' in text, 'template used')
		self.assertTrue('<h1>Foo</h1>' in text)

		#~ print dialog.uistate
		self.assertEqual(dialog.uistate, ui.uistate['ExportDialog'])
		self.assertIsInstance(dialog.uistate['output_file'], File)
		self.assertIsInstance(dialog.uistate['output_folder'], Dir) # Keep this in state as well
Exemplo n.º 11
0
	def runTest(self):
		'''Test synchronization'''
		# Test if zim detects pages, that where created with another
		# zim instance and transfered to this instance with
		# dropbox or another file synchronization tool.
		#
		# The scenario is as follow:
		# 1) Page.txt is created in this instance
		# 2) Page/Subpage.txt is created in another instance
		#    and copied into the notebook by the synchronization tool
		# 3) Zim runs a standard index update
		# Outcome should be that Page:Subpage shows up in the index

		# create notebook
		dir = Dir(self.create_tmp_dir())

		init_notebook(dir, name='foo')
		notebook = get_notebook(dir)
		index = notebook.index
		index.update()

		# add page in this instance
		path = Path('Page')
		page =  notebook.get_page(path)
		page.parse('wiki', 'nothing important')
		notebook.store_page(page)

		# check file exists
		self.assertTrue(dir.file('Page.txt').exists())

		# check file is indexed
		self.assertTrue(page in list(index.list_all_pages()))

		# check attachment dir does not exist
		subdir = dir.subdir('Page')
		self.assertEqual(notebook.get_attachments_dir(page), subdir)
		self.assertFalse(subdir.exists())

		for newfile, newpath in (
			(subdir.file('NewSubpage.txt').path, Path('Page:NewSubpage')),
			(dir.file('Newtoplevel.txt').path, Path('Newtoplevel')),
			(dir.file('SomeDir/Dir/Newpage.txt').path, Path('SomeDir:Dir:Newpage')),
		):
			# make sure ctime changed since last index
			import time
			time.sleep(2)

			# create new page without using zim classes
			self.assertFalse(os.path.isfile(newfile))

			mydir = os.path.dirname(newfile)
			if not os.path.isdir(mydir):
				os.makedirs(mydir)

			fh = open(newfile, 'w')
			fh.write('Test 123\n')
			fh.close()

			self.assertTrue(os.path.isfile(newfile))

			# simple index reload
			index.update()

			# check if the new page is found in the index
			self.assertTrue(newpath in list(index.list_all_pages()))
Exemplo n.º 12
0
	def get_exporter(self, page):
		from zim.fs import File, Dir
		from zim.export import \
			build_mhtml_file_exporter, \
			build_single_file_exporter, \
			build_page_exporter, \
			build_notebook_exporter

		format = self.opts.get('format', 'html')
		if not 'output' in self.opts:
			raise UsageError, _('Output location needed for export') # T: error in export command
		output = Dir(self.opts['output'])
		if not output.isdir():
			output = File(self.opts.get('output'))
		template = self.opts.get('template', 'Default')

		if output.exists() and not self.opts.get('overwrite'):
			if output.isdir():
				if len(output.list()) > 0:
					raise Error, _('Output folder exists and not empty, specify "--overwrite" to force export')  # T: error message for export
				else:
					pass
			else:
				raise Error, _('Output file exists, specify "--overwrite" to force export')  # T: error message for export

		if format == 'mhtml':
			self.ignore_options('index-page')
			if output.isdir():
				raise UsageError, _('Need output file to export MHTML') # T: error message for export

			exporter = build_mhtml_file_exporter(
				output, template,
				document_root_url=self.opts.get('root-url'),
			)
		elif page:
			self.ignore_options('index-page')
			if output.exists() and output.isdir():
				ext = 'html'
				output = output.file(page.basename) + '.' + ext

			if self.opts.get('singlefile'):
				exporter = build_single_file_exporter(
					output, format, template, namespace=page,
					document_root_url=self.opts.get('root-url'),
				)
			else:
				exporter = build_page_exporter(
					output, format, template, page,
					document_root_url=self.opts.get('root-url'),
				)
		else:
			if not output.exists():
				output = Dir(output.path)
			elif not output.isdir():
				raise UsageError, _('Need output folder to export full notebook') # T: error message for export

			exporter = build_notebook_exporter(
				output, format, template,
				index_page=self.opts.get('index-page'),
				document_root_url=self.opts.get('root-url'),
			)

		return exporter
Exemplo n.º 13
0
    def testDialog(self):
        '''Test ExportDialog'''
        from zim.gui.exportdialog import ExportDialog, ExportDoneDialog

        dir = Dir(self.create_tmp_dir())

        notebook = tests.new_notebook(fakedir='/foo/bar')

        ui = tests.MockObject()
        ui.notebook = notebook
        ui.page = Path('foo')
        ui.uistate = SectionedConfigDict()

        ## Test export all pages
        dialog = ExportDialog(ui)
        dialog.set_page(0)

        page = dialog.get_page()
        page.form['selection'] = 'all'
        dialog.next_page()

        page = dialog.get_page()
        page.form['format'] = 'HTML'
        page.form['template'] = 'Print'
        dialog.next_page()

        page = dialog.get_page()
        page.form['folder'] = dir
        page.form['index'] = 'INDEX_PAGE'
        with tests.DialogContext(ExportDoneDialog):
            dialog.assert_response_ok()

        file = dir.file('Test/foo.html')
        self.assertTrue(file.exists())
        text = file.read()
        self.assertTrue('<!-- Wiki content -->' in text, 'template used')
        self.assertTrue('<h1>Foo</h1>' in text)

        #~ print dialog.uistate
        self.assertEqual(dialog.uistate, ui.uistate['ExportDialog'])
        self.assertIsInstance(dialog.uistate['output_folder'], Dir)

        ## Test export single page
        dialog = ExportDialog(ui)
        dialog.set_page(0)

        page = dialog.get_page()
        page.form['selection'] = 'page'
        page.form['page'] = 'Test:foo'
        dialog.next_page()

        page = dialog.get_page()
        page.form['format'] = 'HTML'
        page.form['template'] = 'Print'
        dialog.next_page()

        page = dialog.get_page()
        page.form['file'] = dir.file('SINGLE_FILE_EXPORT.html').path
        with tests.DialogContext(ExportDoneDialog):
            dialog.assert_response_ok()

        file = dir.file('SINGLE_FILE_EXPORT.html')
        self.assertTrue(file.exists())
        text = file.read()
        self.assertTrue('<!-- Wiki content -->' in text, 'template used')
        self.assertTrue('<h1>Foo</h1>' in text)

        #~ print dialog.uistate
        self.assertEqual(dialog.uistate, ui.uistate['ExportDialog'])
        self.assertIsInstance(dialog.uistate['output_file'], File)
        self.assertIsInstance(dialog.uistate['output_folder'],
                              Dir)  # Keep this in state as well
Exemplo n.º 14
0
class TestExportCommand(tests.TestCase):
    def setUp(self):
        self.tmpdir = Dir(self.create_tmp_dir())
        self.notebook = self.tmpdir.subdir('notebook')
        init_notebook(self.notebook)

    def testOptions(self):
        # Only testing we get a valid exporter, not the full command,
        # because the command is very slow

        ## Full notebook, minimal options
        cmd = ExportCommand('export')
        cmd.parse_options(self.notebook.path)
        self.assertRaises(UsageError, cmd.get_exporter, None)

        cmd = ExportCommand('export')
        cmd.parse_options(
            self.notebook.path,
            '--output',
            self.tmpdir.subdir('output').path,
        )
        exp = cmd.get_exporter(None)
        self.assertIsInstance(exp, MultiFileExporter)
        self.assertIsInstance(exp.layout, MultiFileLayout)
        self.assertIsInstance(exp.layout.dir, Dir)
        self.assertIsInstance(exp.template, Template)
        self.assertIsNone(exp.document_root_url)
        self.assertIsNotNone(exp.format)
        self.assertIsNone(exp.index_page)

        ## Full notebook, full options
        cmd = ExportCommand('export')
        cmd.parse_options(
            self.notebook.path,
            '--format',
            'markdown',
            '--template',
            './tests/data/TestTemplate.html',
            '--output',
            self.tmpdir.subdir('output').path,
            '--root-url',
            '/foo/',
            '--index-page',
            'myindex',
            '--overwrite',
        )
        exp = cmd.get_exporter(None)
        self.assertIsInstance(exp, MultiFileExporter)
        self.assertIsInstance(exp.layout, MultiFileLayout)
        self.assertIsInstance(exp.layout.dir, Dir)
        self.assertIsInstance(exp.template, Template)
        self.assertIsNotNone(exp.document_root_url)
        self.assertIsNotNone(exp.format)
        self.assertIsNotNone(exp.index_page)

        ## Full notebook, single page
        cmd = ExportCommand('export')
        cmd.parse_options(self.notebook.path, '--format', 'markdown',
                          '--template', './tests/data/TestTemplate.html',
                          '--output',
                          self.tmpdir.file('output.md').path, '-s')
        exp = cmd.get_exporter(None)
        self.assertIsInstance(exp, SingleFileExporter)
        self.assertIsInstance(exp.layout, SingleFileLayout)
        self.assertIsInstance(exp.layout.file, File)

        ## Single page
        cmd = ExportCommand('export')
        cmd.parse_options(
            self.notebook.path,
            'Foo:Bar',
            '--output',
            self.tmpdir.subdir('output').path,
        )
        exp = cmd.get_exporter(Path('Foo:Bar'))
        self.assertIsInstance(exp, MultiFileExporter)
        self.assertIsInstance(exp.layout, FileLayout)
        self.assertIsInstance(exp.layout.file, File)
        self.assertIsInstance(exp.template, Template)
        self.assertIsNone(exp.document_root_url)
        self.assertIsNotNone(exp.format)
        self.assertIsNone(exp.index_page)

        cmd = ExportCommand('export')
        cmd.parse_options(
            self.notebook.path,
            'Foo:Bar',
            '--recursive',
            '--output',
            self.tmpdir.subdir('output').path,
        )
        exp = cmd.get_exporter(Path('Foo:Bar'))
        self.assertIsInstance(exp, MultiFileExporter)
        self.assertIsInstance(exp.layout, FileLayout)
        self.assertIsInstance(exp.layout.file, File)
        self.assertIsInstance(exp.template, Template)
        self.assertIsNone(exp.document_root_url)
        self.assertIsNotNone(exp.format)
        self.assertIsNone(exp.index_page)

        cmd = ExportCommand('export')
        cmd.parse_options(
            self.notebook.path,
            'Foo:Bar',
            '-rs',
            '--output',
            self.tmpdir.subdir('output').path,
        )
        exp = cmd.get_exporter(Path('Foo:Bar'))
        self.assertIsInstance(exp, SingleFileExporter)
        self.assertIsInstance(exp.layout, SingleFileLayout)
        self.assertIsInstance(exp.layout.file, File)
        self.assertIsInstance(exp.template, Template)
        self.assertIsNone(exp.document_root_url)
        self.assertIsNotNone(exp.format)

        ## MHTML exporter
        cmd = ExportCommand('export')
        cmd.parse_options(
            self.notebook.path,
            'Foo:Bar',
            '-rs',
            '--format',
            'mhtml',
            '--output',
            self.tmpdir.subdir('output').path,
        )
        exp = cmd.get_exporter(Path('Foo:Bar'))
        self.assertIsInstance(exp, MHTMLExporter)
        self.assertIsInstance(exp.file, File)
        self.assertIsInstance(exp.template, Template)
        self.assertIsNone(exp.document_root_url)

    @tests.slowTest
    def testExport(self):
        # Only test single page, just to show "run()" works
        file = self.notebook.file('Foo/Bar.txt')
        file.write('=== Foo\ntest 123\n')

        output = self.tmpdir.file('output.html')

        cmd = ExportCommand('export')
        cmd.parse_options(self.notebook.path, 'Foo:Bar', '--output',
                          output.path, '--template',
                          'tests/data/TestTemplate.html')
        cmd.run()

        self.assertTrue(output.exists())
        html = output.read()
        self.assertTrue('<h1>Foo' in html)
        self.assertTrue('test 123' in html)