""" 配置文件管理测试 """ from pathlib import Path import pytest from pl_japanese.cleaner.config import ( JCleanConfig, load_config, find_config_file, generate_sample_config ) def test_default_config(): """没有配置文件时使用默认值""" config = JCleanConfig() assert config.tasks_root == 'tasks' assert config.vocabulary == 'data/db/vocabulary.txt' assert config.skipped == 'data/db/skipped.txt' def test_resolve_path_absolute(tmp_path): """绝对路径直接返回""" config = JCleanConfig(_config_file=tmp_path / 'jclean.toml') # 使用 Windows 兼容的绝对路径 abs_path = str((tmp_path / 'absolute_file.txt').resolve()) assert config.resolve_path(abs_path) == abs_path def test_resolve_path_relative_with_config(tmp_path): """相对路径相对配置文件所在目录""" config_file = tmp_path / 'jclean.toml' config_file.write_text('[paths]', encoding='utf-8') config = JCleanConfig(_config_file=config_file) resolved = config.resolve_path('tasks') expected = str((tmp_path / 'tasks').resolve()) assert resolved == expected def test_resolve_path_relative_no_config(tmp_path): """没有配置文件时,相对当前工作目录""" config = JCleanConfig() # 没有 _config_file resolved = config.resolve_path('tasks') expected = str((Path.cwd() / 'tasks').resolve()) assert resolved == expected def test_find_config_file_current_dir(tmp_path): """在当前目录查找配置文件""" config_file = tmp_path / 'jclean.toml' config_file.write_text('[paths]', encoding='utf-8') found = find_config_file(start_dir=tmp_path) assert found == config_file.resolve() def test_find_config_file_dotfile(tmp_path): """查找 .jclean.toml""" config_file = tmp_path / '.jclean.toml' config_file.write_text('[paths]', encoding='utf-8') found = find_config_file(start_dir=tmp_path) assert found == config_file.resolve() def test_find_config_file_custom_path(tmp_path): """命令行指定配置文件路径""" config_file = tmp_path / 'custom.toml' config_file.write_text('[paths]', encoding='utf-8') found = find_config_file(custom_path=str(config_file)) assert found == config_file.resolve() def test_find_config_file_not_found(tmp_path): """找不到配置文件返回 None""" found = find_config_file(start_dir=tmp_path) assert found is None def test_load_config_no_file(tmp_path): """没有配置文件时返回默认配置""" config = load_config() assert isinstance(config, JCleanConfig) assert config.tasks_root == 'tasks' def test_load_config_from_file(tmp_path): """从配置文件加载""" config_file = tmp_path / 'jclean.toml' config_file.write_text(''' [paths] tasks_root = "my_tasks" vocabulary = "my_vocab.txt" [defaults] backup_before_merge = false ''', encoding='utf-8') config = load_config(custom_path=str(config_file)) assert config.tasks_root == 'my_tasks' assert config.vocabulary == 'my_vocab.txt' assert config.backup_before_merge == False assert config._config_file == config_file.resolve() def test_generate_sample_config(tmp_path): """生成示例配置文件""" output = tmp_path / 'test.toml' generate_sample_config(str(output)) assert output.exists() content = output.read_text(encoding='utf-8') assert '[paths]' in content assert 'tasks_root' in content assert '[defaults]' in content assert '[logging]' in content def test_config_priority_command_line_over_file(tmp_path): """命令行参数优先级高于配置文件""" # 这个测试在 CLI 层面验证,这里只测试配置加载 config_file = tmp_path / 'jclean.toml' config_file.write_text(''' [paths] tasks_root = "config_tasks" vocabulary = "custom_vocab.txt" ''', encoding='utf-8') config = load_config(custom_path=str(config_file)) # CLI 层面会覆盖这些值 assert config.tasks_root == 'config_tasks' # 从配置文件读取 assert config.vocabulary == 'custom_vocab.txt' def test_config_resolve_path_with_parent_dir(tmp_path): """解析包含 .. 的相对路径""" config_dir = tmp_path / 'subdir' config_dir.mkdir() config_file = config_dir / 'jclean.toml' config_file.write_text('[paths]', encoding='utf-8') config = JCleanConfig(_config_file=config_file) resolved = config.resolve_path('../data') expected = str((tmp_path / 'data').resolve()) assert resolved == expected def test_load_config_tolerates_bom(tmp_path): """带 UTF-8 BOM 的配置文件应能正常解析(记事本等编辑器会写入 BOM)""" config_file = tmp_path / 'jclean.toml' # utf-8-sig 会在文件头写入 BOM (EF BB BF) config_file.write_text('''[paths] tasks_root = "bom_tasks" vocabulary = "bom_vocab.txt" ''', encoding='utf-8-sig') # 确认文件确实带 BOM assert config_file.read_bytes()[:3] == b'\xef\xbb\xbf' config = load_config(custom_path=str(config_file)) assert config.tasks_root == 'bom_tasks' assert config.vocabulary == 'bom_vocab.txt'