1# test_files.py 2 3import locale 4 5import pytest 6 7from graphviz.files import Source 8 9SOURCE = { 10 'source': 'digraph { hello -> world }', 11 'filename': 'hello.gv', 'directory': 'test-output', 12 'format': 'PNG', 'engine': 'NEATO', 'encoding': 'utf-8', 13} 14 15 16@pytest.fixture(scope='module') 17def source(): 18 return Source(**SOURCE) 19 20 21def test_format(source): 22 assert not SOURCE['format'].islower() 23 24 assert source.format == SOURCE['format'].lower() 25 with pytest.raises(ValueError, match=r'format'): 26 source.format = '' 27 28 29def test_engine(source): 30 assert not SOURCE['engine'].islower() 31 32 assert source.engine == SOURCE['engine'].lower() 33 with pytest.raises(ValueError, match=r'engine'): 34 source.engine = '' 35 36 37def test_encoding(source): 38 assert source.encoding == SOURCE['encoding'] 39 40 with pytest.raises(LookupError, match=r'encoding'): 41 source.encoding = '' 42 43 44def test_encoding_none(source): 45 source_copy = source.copy() 46 source_copy.encoding = None 47 assert source_copy.encoding == locale.getpreferredencoding() 48 49 50def test_init(source): 51 assert source.source == SOURCE['source'] 52 assert source.filename == SOURCE['filename'] 53 assert source.directory == SOURCE['directory'] 54 55 56def test_init_filename(): 57 assert Source('').filename == 'Source.gv' 58 assert type('Named', (Source,), {'name': 'name'})('').filename == 'name.gv' 59 60 61def test__repr_svg_(mocker, source): 62 kwargs = {'return_value.decode.return_value': mocker.sentinel.decoded} 63 pipe = mocker.patch.object(source, 'pipe', new_callable=mocker.Mock, **kwargs) 64 65 assert source._repr_svg_() is mocker.sentinel.decoded 66 67 pipe.assert_called_once_with(format='svg') 68 pipe.return_value.decode.assert_called_once_with(source.encoding) 69 70 71def test_pipe_format(pipe, source, format_='svg'): 72 assert source.format != format_ 73 74 assert source.pipe(format=format_) is pipe.return_value 75 76 data = source.source.encode(source.encoding) 77 pipe.assert_called_once_with(source.engine, format_, data, None, None) 78 79 80def test_pipe(pipe, source): 81 assert source.pipe() is pipe.return_value 82 83 data = source.source.encode(source.encoding) 84 pipe.assert_called_once_with(source.engine, source.format, data, None, None) 85 86 87def test_filepath(test_platform, source): 88 if test_platform == 'windows': 89 assert source.filepath == 'test-output\\hello.gv' 90 else: 91 assert source.filepath == 'test-output/hello.gv' 92 93 94def test_save(mocker, py2, filename='filename', directory='directory'): 95 source = Source(**SOURCE) 96 makedirs = mocker.patch('os.makedirs', new_callable=mocker.Mock) 97 open_ = mocker.patch('io.open', mocker.mock_open()) 98 99 assert source.save(filename, directory) == source.filepath 100 101 assert source.filename == filename and source.directory == directory 102 if py2: 103 makedirs.assert_called_once_with(source.directory, 0o777) 104 else: 105 makedirs.assert_called_once_with(source.directory, 0o777, exist_ok=True) 106 open_.assert_called_once_with(source.filepath, 'w', encoding=source.encoding) 107 assert open_.return_value.write.call_args_list == [((source.source,),), ((u'\n',),)] 108 109 110def test_render(mocker, render, source): 111 save = mocker.patch.object(source, 'save', new_callable=mocker.Mock) 112 _view = mocker.patch.object(source, '_view', new_callable=mocker.Mock) 113 remove = mocker.patch('os.remove', new_callable=mocker.Mock) 114 115 assert source.render(cleanup=True, view=True) is render.return_value 116 117 save.assert_called_once_with(None, None) 118 render.assert_called_once_with(source.engine, source.format, save.return_value, None, None) 119 remove.assert_called_once_with(save.return_value) 120 _view.assert_called_once_with(render.return_value, source.format) 121 122 123def test_view(mocker, source): 124 render = mocker.patch.object(source, 'render', new_callable=mocker.Mock) 125 kwargs = {'filename': 'filename', 'directory': 'directory', 'cleanup': True} 126 127 assert source.view(**kwargs) is render.return_value 128 129 render.assert_called_once_with(view=True, **kwargs) 130 131 132def test__view(mocker, platform, source): 133 if platform == 'nonplatform': 134 with pytest.raises(RuntimeError, match=r'support'): 135 source._view('name', 'png') 136 else: 137 _view_platform = mocker.patch.object(source, '_view_%s' % platform, 138 new_callable=mocker.Mock) 139 140 assert source._view(mocker.sentinel.name, 'png') is None 141 142 _view_platform.assert_called_once_with(mocker.sentinel.name) 143 144 145def test_copy(source): 146 assert source.copy() is not source 147 assert source.copy() is not source.copy() 148 assert source.copy().__class__ is source.__class__ 149 assert source.copy().__dict__ == source.__dict__ 150 151 152def test_from_file(tmpdir, filename='hello.gv', directory='source_hello', 153 data=u'digraph { hello -> world }', encoding='utf-8'): 154 lpath = tmpdir.mkdir(directory) 155 (lpath / filename).write_text(data, encoding=encoding) 156 157 source = Source.from_file(filename, str(lpath)) 158 assert source.encoding == 'utf-8' 159 160 source = Source.from_file(filename, str(lpath), encoding=None) 161 assert source.encoding == locale.getpreferredencoding() 162 163 source = Source.from_file(filename, str(lpath), encoding=encoding) 164 assert source.source == data 165 assert source.filename == filename 166 assert source.directory == str(lpath) 167 assert source.encoding == encoding 168