def test_convert_notes_nsx_file_type(tmp_path, capsys, caplog): test_source_path = tmp_path input_file = 'file1.nsx' args = {'silent': True, 'ini': False, 'source': test_source_path} touch(Path(tmp_path, input_file)) cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() nc.conversion_settings._source = Path(tmp_path) nc.conversion_settings._source_absolute_root = Path(tmp_path) nc.conversion_settings.conversion_input = 'nsx' with patch('notes_converter.NotesConvertor.process_nsx_files', spec=True) as mock_process_nsx_files: with patch( 'notes_converter.NotesConvertor.evaluate_command_line_arguments', spec=True): caplog.clear() nc.convert_notes() mock_process_nsx_files.assert_called_once() assert len(nc._nsx_backups) == 1 captured = capsys.readouterr() assert 'Processing Completed' in caplog.records[-1].message assert 'Found pandoc' in captured.out
def test_ask_user_to_choose_new_default_config_file_user_choose_exit( good_config_ini, tmp_path, monkeypatch): print('hello') def patched_cli(_): return 'exit' good_config_ini = good_config_ini.replace('source = my_source', 'source = ') Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") monkeypatch.setattr(interactive_cli.InvalidConfigFileCommandLineInterface, 'run_cli', patched_cli) cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) with pytest.raises(SystemExit) as exc: cd.ask_user_to_choose_new_default_config_file() assert isinstance(exc.type, type(SystemExit)) assert str(exc.value) == '0'
def test_convert_html_rename_existing_file(tmp_path): test_source_path = tmp_path args = {'source': test_source_path} cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() nc.conversion_settings.orphans = 'orphan' nc.conversion_settings._working_directory = Path(tmp_path) nc.conversion_settings.export_folder = Path(tmp_path, 'notes') nc.conversion_settings.orphans = 'orphan' touch(Path(tmp_path, 'file1.html')) # add link to existing file so it does not get moved to orphans content_for_source = f'<a href="file1.md">existing file</a><a href="{Path(tmp_path, "notes", "file1.md")}">existing file</a>' Path(tmp_path, 'file1.html').write_text(content_for_source) # create the notes export folder and create the existing file Path(tmp_path, 'notes').mkdir() touch(Path(tmp_path, 'notes', 'file1.md')) nc.conversion_settings._source = Path(tmp_path) nc.conversion_settings._source_absolute_root = Path(tmp_path) nc.convert_html() assert Path(tmp_path, 'file1.html').exists() assert Path(tmp_path, 'notes', 'file1.md').exists() assert Path(tmp_path, 'notes', 'file1-old-1.md').exists() assert Path(tmp_path, 'notes', 'file1-old-1.md').stat().st_size == 0 assert Path(tmp_path, 'notes', 'file1.md').stat().st_size > 0
def test_process_files_copy_attachments_source_and_export_same_folder( tmp_path, silent): config.yanom_globals.is_silent = silent args = {'source': tmp_path} cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() nc.conversion_settings.export_folder = Path(tmp_path) touch(Path(tmp_path, 'file1.html')) file1_content = '<a href="attachments/a-file.pdf">an attachment</a>' Path(tmp_path, 'file1.html').write_text(file1_content) Path(tmp_path, 'attachments').mkdir() Path(tmp_path, 'attachments', 'a-file.pdf').touch() nc.conversion_settings._source = Path(tmp_path, 'file1.html') nc.conversion_settings._source_absolute_root = Path(tmp_path) files_to_convert = [Path(tmp_path, 'file1.html')] file_converter = file_converter_HTML_to_MD.HTMLToMDConverter( nc.conversion_settings, files_to_convert) nc.process_files(files_to_convert, file_converter) assert nc._note_page_count == 1 assert Path(tmp_path, 'file1.md').exists()
def test_exit_if_no_files_found_with_no_file(tmp_path, caplog, silent_mode, expected_out): config.yanom_globals.is_silent = silent_mode test_source_path = tmp_path args = {'source': test_source_path} touch(Path(tmp_path, 'file1.html')) cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() nc.conversion_settings._source = Path(tmp_path) files_to_convert = None extension = 'html' with pytest.raises(SystemExit) as pytest_wrapped_e: caplog.clear() nc.exit_if_no_files_found(files_to_convert, extension) assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code == 0 assert len(caplog.records) == 1 assert expected_out in caplog.records[0].message
def test_evaluate_command_line_arguments_when_will_be_interactive_command_line_used( caplog): test_source_path = str(Path(__file__).parent.absolute()) config.yanom_globals.logger_level = logging.DEBUG args = { 'silent': False, 'ini': False, 'source': test_source_path, 'export': 'hello' } cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() with patch( 'notes_converter.NotesConvertor.configure_for_ini_settings', spec=True, ) as mock_configure_for_ini_settings: with patch( 'notes_converter.NotesConvertor.run_interactive_command_line_interface', spec=True, ) as mock_run_interactive_command_line_interface: caplog.clear() nc.evaluate_command_line_arguments() mock_configure_for_ini_settings.assert_called_once() mock_run_interactive_command_line_interface.assert_called_once() assert nc.conversion_settings.export_folder == Path('hello') assert nc.conversion_settings.source == Path(test_source_path) assert 'Starting interactive command line tool' in caplog.messages
def test_generate_conversion_settings_from_parsed_config_file_data_test_source_setting( good_config_ini, tmp_path): # by inducing a system exit we know the new path was passed into config_settings correctly # the error is raised when the source setter sees an invalid path Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.read_config_file() # set the source location cd['file_options']['source'] = 'new_source' # confirm conversion_settings source is empty assert cd.conversion_settings.source == '' # convert config parser object to conversion settings with pytest.raises(SystemExit) as exc: cd.generate_conversion_settings_from_parsed_config_file_data() assert isinstance(exc.type, type(SystemExit)) assert str(exc.value) == '1'
def test_evaluate_command_line_arguments_when_going_to_use_ini_file( caplog, silent, ini): test_source_path = str(Path(__file__).parent.absolute()) config.yanom_globals.logger_level = logging.DEBUG args = { 'silent': silent, 'ini': ini, 'source': test_source_path, 'export': 'hello' } cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() with patch( 'notes_converter.NotesConvertor.configure_for_ini_settings', spec=True, ) as mock_configure_for_ini_settings: with patch( 'notes_converter.NotesConvertor.run_interactive_command_line_interface', spec=True, ) as mock_run_interactive_command_line_interface: caplog.clear() nc.evaluate_command_line_arguments() mock_configure_for_ini_settings.assert_called_once() mock_run_interactive_command_line_interface.assert_not_called()
def test_evaluate_command_line_arguments_when_blank_source_export_in_args( caplog): config.yanom_globals.logger_level = logging.DEBUG args = {'silent': False, 'ini': False, 'source': '', 'export': ''} cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() with patch( 'notes_converter.NotesConvertor.configure_for_ini_settings', spec=True, ) as mock_configure_for_ini_settings: with patch( 'notes_converter.NotesConvertor.run_interactive_command_line_interface', spec=True, ) as mock_run_interactive_command_line_interface: caplog.clear() nc.evaluate_command_line_arguments() mock_configure_for_ini_settings.assert_called_once() mock_run_interactive_command_line_interface.assert_called_once() assert nc.conversion_settings.export_folder == 'notes' assert nc.conversion_settings.source == '' assert 'Starting interactive command line tool' in caplog.messages
def test_generate_conversion_settings_using_quick_settings_string_to_forced_bad_directory( good_config_ini, tmp_path, caplog, capsys, monkeypatch, silent, expected): """Force a bad directory into the config.ini save method to check it is handled and logged""" config.yanom_globals.is_silent = silent Path(tmp_path, 'data').mkdir() Path(tmp_path, 'data', 'config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(str(Path(tmp_path, 'data', 'config.ini')), 'obsidian', allow_no_value=True) # remove the config.ini so we can check a new one is saved Path(tmp_path, 'data', 'config.ini').unlink() assert not Path(tmp_path, 'config.ini').exists() cd._config_file = 'config.ini' monkeypatch.setattr(ConversionSettings, 'working_directory', Path(tmp_path, "abc")) cd.generate_conversion_settings_using_quick_settings_string('gfm') assert not Path(tmp_path, 'abc', 'config.ini').exists() assert not Path(tmp_path, 'config.ini').exists() assert caplog.records assert f"Unable to save config.ini file '{Path(tmp_path, 'abc/data')}' is not a directory. No such file or directory" in caplog.messages captured = capsys.readouterr() assert expected in captured.out
def test_print_result_if_any_no_message_expected(capsys, tmp_path): args = {'silent': True, 'ini': False, 'source': tmp_path} cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.print_result_if_any(0, 'message') captured = capsys.readouterr() assert 'message' not in captured.out
def test_validate_config_file_good_file(tmp_path, good_config_ini): Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.read_config_file() valid_config = cd.validate_config_file() assert valid_config
def test_repr(good_config_ini, tmp_path): good_config_ini = good_config_ini.replace('source = my_source', 'source = ') Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.parse_config_file() result = repr(cd) assert result == "ConfigData{'conversion_inputs': {'conversion_input': 'nsx'}, 'markdown_conversion_inputs': {'markdown_conversion_input': 'gfm'}, 'quick_settings': {'quick_setting': 'obsidian'}, 'export_formats': {'export_format': 'obsidian'}, 'meta_data_options': {'front_matter_format': 'yaml', 'metadata_schema': 'title,ctime,mtime,tag', 'tag_prefix': '#', 'spaces_in_tags': 'False', 'split_tags': 'False', 'metadata_time_format': '%Y-%m-%d %H:%M:%S%Z', 'file_created_text': 'created', 'file_modified_text': 'updated'}, 'table_options': {'first_row_as_header': 'True', 'first_column_as_header': 'True'}, 'chart_options': {'chart_image': 'True', 'chart_csv': 'True', 'chart_data_table': 'True'}, 'file_options': {'source': '', 'export_folder': 'notes-15', 'attachment_folder_name': 'attachments', 'allow_spaces_in_filenames': 'True', 'filename_spaces_replaced_by': '-', 'allow_unicode_in_filenames': 'True', 'allow_uppercase_in_filenames': 'True', 'allow_non_alphanumeric_in_filenames': 'True', 'creation_time_in_exported_file_name': 'True', 'max_file_or_directory_name_length': '255', 'orphans': 'copy', 'make_absolute': 'False'}, 'nimbus_options': {'embed_these_document_types': 'md,pdf', 'embed_these_image_types': 'png,jpg,jpeg,gif,bmp,svg', 'embed_these_audio_types': 'mp3,webm,wav,m4a,ogg,3gp,flac', 'embed_these_video_types': 'mp4,webm,ogv', 'keep_nimbus_row_and_column_headers': 'False', 'unrecognised_tag_format': 'html'}}"
def test_validate_config_file_bad_values(tmp_path, good_config_ini, key1, key2, bad_value): Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.read_config_file() cd[key1][key2] = bad_value valid_config = cd.validate_config_file() assert valid_config is False
def test_update_processing_stats(): test_source_path = str(Path(__file__).parent.absolute()) args = {'source': test_source_path} cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.update_processing_stats(FakeNSXFile()) assert nc._note_page_count == 1 assert nc._note_book_count == 2 assert nc._image_count == 3 assert nc._attachment_count == 4
def test_conversion_settings_proprty_obj_confirm_string_setting( tmp_path, good_config_ini): Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.conversion_settings = 'multimarkdown' assert cd.conversion_settings.export_format == 'multimarkdown' assert cd['export_formats']['export_format'] == 'multimarkdown'
def test_validate_good_config_ini_no_notes_or_attachment_folder( tmp_path, good_config_ini_no_notes_or_attachment_folder): Path(f'{str(tmp_path)}/data').mkdir() Path(f'{str(tmp_path)}/data/config.ini').write_text( good_config_ini_no_notes_or_attachment_folder, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/data/config.ini", 'gfm', allow_no_value=True) cd.conversion_settings.working_directory = Path(tmp_path) cd.parse_config_file() assert cd.conversion_settings.export_folder == Path('notes') assert cd.conversion_settings.attachment_folder_name == Path('attachments')
def test_set_file_modified_text(good_config_ini, tmp_path): good_config_ini = good_config_ini.replace( 'file_modified_text = updated', 'file_modified_text = hello_world') Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.parse_config_file() assert cd['meta_data_options']['file_modified_text'] == 'hello_world' assert cd.conversion_settings.file_modified_text == 'hello_world'
def test_generate_conversion_settings_using_quick_settings_object( good_config_ini, tmp_path): Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cs = ConversionSettings() cs.quick_set_commonmark_settings() cd.generate_conversion_settings_using_quick_settings_object(cs) assert cd['quick_settings']['quick_setting'] == 'commonmark'
def test_parse_config_file(good_config_ini, tmp_path): good_config_ini = good_config_ini.replace('source = my_source', 'source = ') Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.parse_config_file() assert cd.conversion_settings.export_format == 'obsidian'
def test_set_time_format(good_config_ini, tmp_path): good_config_ini = good_config_ini.replace( 'metadata_time_format = %%Y-%%m-%%d %%H:%%M:%%S%%Z', 'metadata_time_format = %%Y') Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.parse_config_file() assert cd['meta_data_options']['metadata_time_format'] == '%Y' assert cd.conversion_settings.metadata_time_format == '%Y'
def test_validate_config_file_missing_keys_and_sections( tmp_path, good_config_ini, replace_this, with_this): good_config_ini = good_config_ini.replace(replace_this, with_this) Path(tmp_path, 'data').mkdir() Path(f'{str(tmp_path)}/data/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/data/config.ini", 'gfm', allow_no_value=True) cd.read_config_file() valid_config = cd.validate_config_file() assert valid_config is False
def test_read_config_file_file_missing(tmp_path, caplog): cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) caplog.clear() cd.read_config_file() assert cd.conversion_settings.export_format == 'gfm' assert len(caplog.records) > 0 for record in caplog.records: if record.levelname == "WARNING": assert 'config.ini missing at' in record.message
def test_generate_conversion_settings_using_quick_settings_string( good_config_ini, tmp_path): Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'obsidian', allow_no_value=True) # remove the config.ini so we can check it is saved Path(f'{str(tmp_path)}/config.ini').unlink() assert not Path(f'{str(tmp_path)}/config.ini').exists() cd.generate_conversion_settings_using_quick_settings_string('gfm') assert Path(f'{str(tmp_path)}/config.ini').exists() assert cd['quick_settings']['quick_setting'] == 'gfm'
def test_run_interactive_command_line_interface(caplog, tmp_path): args = {'source': tmp_path} cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() with patch('interactive_cli.StartUpCommandLineInterface.run_cli', spec=True, return_value=nc.conversion_settings) as mock_run_cli: caplog.clear() nc.run_interactive_command_line_interface() mock_run_cli.assert_called_once() assert 'Using conversion settings from interactive command line tool' in caplog.messages
def test_read_config_missing_file(tmp_path, caplog, capsys, silent, expected): config.yanom_globals.is_silent = silent cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) cd.read_config_file() assert len(caplog.records) > 0 assert caplog.records[0].levelname == "WARNING" captured = capsys.readouterr() assert captured.out == expected
def test_generate_file_list_single_file_source(tmp_path): test_source_path = tmp_path args = {'source': test_source_path} touch(Path(tmp_path, 'file1.nsx')) cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() nc.conversion_settings.source = Path(tmp_path, 'file1.nsx') result = nc.generate_file_list('nsx', nc.conversion_settings.source_absolute_root) assert len(result) == 1 assert Path(tmp_path, f'file1.nsx') in result
def test_generate_conversion_settings_using_quick_settings_string_bad_value( good_config_ini, tmp_path, caplog): good_config_ini = good_config_ini.replace('source = my_source', 'source = ') Path(f'{str(tmp_path)}/config.ini').write_text(good_config_ini, encoding="utf-8") cd = config_data.ConfigData(f"{str(tmp_path)}/config.ini", 'gfm', allow_no_value=True) with pytest.raises(ValueError): cd.generate_conversion_settings_using_quick_settings_string('invalid') assert 'is not a recognised quick setting string' in caplog.records[ -1].message
def test_process_files(tmp_path): args = {'source': tmp_path} touch(Path(tmp_path, 'file1.html')) cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc.conversion_settings = conversion_settings.ConversionSettings() nc.conversion_settings._source = Path(tmp_path, 'file1.html') nc.conversion_settings._source_absolute_root = Path(tmp_path) files_to_convert = [Path(tmp_path, 'file1.html')] file_converter = file_converter_HTML_to_MD.HTMLToMDConverter( nc.conversion_settings, files_to_convert) nc.process_files(files_to_convert, file_converter) assert nc._note_page_count == 1
def test_process_nsx_files(capsys): test_source_path = str(Path(__file__).parent.absolute()) args = {'source': test_source_path} cd = config_data.ConfigData(f"{config.yanom_globals.data_dir}/config.ini", 'gfm', allow_no_value=True) nc = notes_converter.NotesConvertor(args, cd) nc._nsx_backups = [FakeNSXFile()] nc.process_nsx_files() captured = capsys.readouterr() assert 'nsx_file process_nsx_file called' in captured.out assert nc._note_page_count == 1 assert nc._note_book_count == 2 assert nc._image_count == 3 assert nc._attachment_count == 4