jimaku-dl/tests/test_end_to_end_windows.py
2025-03-12 20:37:17 -07:00

193 lines
7.1 KiB
Python

"""End-to-end tests simulating Windows environment."""
import builtins
import os
import platform
import socket
from unittest.mock import patch, MagicMock, mock_open
import pytest
from jimaku_dl.downloader import JimakuDownloader
from jimaku_dl.cli import main
# Patch to simulate Windows environment
@pytest.fixture
def windows_environment():
"""Create a simulated Windows environment."""
# Save original items we'll modify
original_platform = platform.system
original_path_exists = os.path.exists
original_open = builtins.open
original_socket_socket = socket.socket
# Create mock objects
mock_socket = MagicMock()
# Mock Windows behavior
platform.system = lambda: "Windows"
os.sep = "\\"
# Restore all after test
try:
yield
finally:
platform.system = original_platform
os.path.exists = original_path_exists
builtins.open = original_open
socket.socket = original_socket_socket
os.sep = "/"
class TestEndToEndWindows:
"""Test the complete application flow in a Windows environment."""
def test_path_handling_windows(self, windows_environment, temp_dir):
"""Test path handling in Windows environment."""
# Create a test file that will pass the existence check
test_file = os.path.join(temp_dir, "test_video.mkv")
with open(test_file, "w") as f:
f.write("dummy content")
# Use Windows-style path
win_path = test_file.replace("/", "\\")
# Create a downloader with mock token and network calls
with patch("requests.post") as mock_post, patch(
"requests.get"
) as mock_get, patch(
"jimaku_dl.downloader.requests_get"
) as mock_requests_get, patch(
"builtins.open", mock_open()
), patch(
"subprocess.run"
) as mock_run, patch(
"builtins.input", return_value="Show Name"
):
# Setup mocks with proper return values
mock_post.return_value.json.return_value = {"data": {"Media": {"id": 1234}}}
mock_post.return_value.status_code = 200
# Mock for the Jimaku API calls
mock_get_response = MagicMock()
mock_get_response.json.return_value = [
{"id": 1, "english_name": "Test Anime", "japanese_name": "テスト"}
]
mock_get_response.status_code = 200
mock_get_response.raise_for_status = MagicMock()
mock_get.return_value = mock_get_response
mock_requests_get.return_value = mock_get_response
# Create downloader
downloader = JimakuDownloader("test_token")
# Test that Windows paths are handled correctly with mocked _prompt_for_title_info
with patch.object(
downloader, "_prompt_for_title_info", return_value=("Show Name", 1, 1)
):
result = downloader.parse_filename(win_path)
assert result[0] == "Show Name" # Should extract show name correctly
# A more extensive mock to properly handle the fzf menu selection
test_entry = {
"id": 1,
"english_name": "Test Anime",
"japanese_name": "テスト",
}
test_file_info = {
"id": 101,
"name": "test_file.srt",
"url": "http://test/file",
}
def mock_fzf_menu_side_effect(options, multi=False):
"""Handle both cases of fzf menu calls properly."""
if any("Test Anime - テスト" in opt for opt in options):
# This is the first call to select the entry
return "1. Test Anime - テスト"
else:
# This is the second call to select the file
return "1. test_file.srt" if not multi else ["1. test_file.srt"]
# Test if download function handles Windows paths by mocking all the API calls
with patch.object(
downloader, "fzf_menu", side_effect=mock_fzf_menu_side_effect
), patch.object(
downloader, "query_anilist", return_value=1234
), patch.object(
downloader, "parse_filename", return_value=("Show Name", 1, 1)
), patch.object(
downloader,
"download_file",
return_value=os.path.join(temp_dir, "test_file.srt"),
), patch.object(
downloader, "query_jimaku_entries", return_value=[test_entry]
), patch.object(
downloader, "get_entry_files", return_value=[test_file_info]
), patch(
"os.path.exists", return_value=True
), patch(
"jimaku_dl.downloader.exists", return_value=True
):
# This should handle Windows paths correctly
result = downloader.download_subtitles(win_path)
# Print for debugging
print(f"Returned paths: {result}")
# Verify the results
assert isinstance(result, list)
assert len(result) > 0
# Just verify we get a path back that contains the expected filename
# Don't check for backslashes since the test environment may convert them
assert any("test_file.srt" in str(path) for path in result)
# OPTIONAL: Check that the path has proper structure for the platform
if os.name == "nt": # Only on actual Windows
assert any("\\" in str(path) for path in result)
def test_cli_windows_paths(self, windows_environment):
"""Test CLI handling of Windows paths."""
with patch("jimaku_dl.cli.parse_args") as mock_parse_args, patch(
"jimaku_dl.cli.JimakuDownloader"
) as mock_downloader_class, patch("os.path.exists", return_value=True), patch(
"subprocess.run"
), patch(
"builtins.print"
):
# Setup mock return values
mock_downloader = MagicMock()
mock_downloader.download_subtitles.return_value = [
"C:\\path\\to\\subtitle.srt"
]
mock_downloader_class.return_value = mock_downloader
# Create mock args with Windows paths
mock_args = MagicMock(
media_path="C:\\path\\to\\video.mkv",
dest_dir="C:\\output\\dir",
play=False,
token="test_token",
log_level="INFO",
anilist_id=None,
sync=False,
)
mock_parse_args.return_value = mock_args
# Run the CLI function
result = main()
# Verify paths were handled correctly
mock_downloader.download_subtitles.assert_called_once()
args, kwargs = mock_downloader.download_subtitles.call_args
assert (
args[0] == "C:\\path\\to\\video.mkv"
) # First arg should be media_path
assert kwargs.get("dest_dir") == "C:\\output\\dir"