forked from ImGajeed76/tfUtils
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3179860
commit 252720d
Showing
2 changed files
with
367 additions
and
0 deletions.
There are no files selected for viewing
225 changes: 225 additions & 0 deletions
225
src/tests/interfaces/HW_Entwicklung/Altium/test_altium.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
import json | ||
from unittest.mock import AsyncMock, MagicMock, patch | ||
|
||
import pytest | ||
import pytest_asyncio | ||
from textual.containers import Container | ||
|
||
# Import the functions to test | ||
from src.interfaces.HW_Entwicklung.Altium.altium import ( | ||
_edit_project_files, | ||
_load_file_mappings, | ||
_rename_files, | ||
_update_project_vc, | ||
is_altium_project, | ||
new_altium_project, | ||
rename_project, | ||
update_project_version, | ||
) | ||
|
||
|
||
@pytest_asyncio.fixture | ||
async def mock_container(): | ||
"""Create a mock container with async mount method""" | ||
container = MagicMock(spec=Container) | ||
container.mount = AsyncMock() | ||
return container | ||
|
||
|
||
@pytest.fixture | ||
def temp_project_dir(tmp_path): | ||
"""Create a temporary project directory with mock Altium project files""" | ||
project_dir = tmp_path / "test_project" | ||
project_dir.mkdir() | ||
|
||
# Create mock project files | ||
project_name = "TestProject" | ||
version = "V1.0" | ||
|
||
# Create PRJPCB file | ||
prjpcb_file = project_dir / f"{project_name}_{version}.PRJPCB" | ||
prjpcb_file.write_text("Mock project content") | ||
|
||
# Create OutJob file | ||
outjob_file = project_dir / f"{project_name}_{version}.OutJob" | ||
outjob_file.write_text("Mock outjob content") | ||
|
||
# Create history file | ||
history_file = project_dir / "_history.txt" | ||
history_file.write_text("1.0\t\tTEST\t01/01/2024\tInitial Project Creation\n") | ||
|
||
# Create template directory | ||
template_dir = project_dir / "template1" | ||
template_dir.mkdir() | ||
template_prjpcb = template_dir / "Template_V1.0.PRJPCB" | ||
template_prjpcb.write_text("Template content") | ||
|
||
# Create test_input directory | ||
test_input_dir = project_dir / "test-input" | ||
test_input_dir.mkdir() | ||
test_input_prjpcb = test_input_dir / "test-input_V1.0.PRJPCB" | ||
test_input_prjpcb.write_text("Test input content") | ||
|
||
# Create .vc.json file | ||
vc_data = { | ||
"project_name": project_name, | ||
"replacements": { | ||
f"{project_name}_{version}.PRJPCB": "{project_name}_{project_version}.PRJPCB", # noqa: E501 | ||
f"{project_name}_{version}.OutJob": "{project_name}_{project_version}.OutJob", # noqa: E501 | ||
}, | ||
} | ||
|
||
with open(project_dir / ".vc.json", "w") as f: | ||
json.dump(vc_data, f) | ||
|
||
return project_dir | ||
|
||
|
||
@pytest_asyncio.fixture | ||
async def mock_fs_ops(): | ||
"""Mock filesystem operations""" | ||
fs_ops = MagicMock() | ||
fs_ops.safe_copy_directory = AsyncMock() | ||
return fs_ops | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_new_altium_project(mock_container, temp_project_dir, mock_fs_ops): | ||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_input", | ||
return_value="test-input", | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_select", | ||
return_value="template1", | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_yes_no", return_value=True | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ALTIUM_TEMPLATES_PATH", | ||
temp_project_dir, | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.Path.cwd", | ||
return_value=temp_project_dir, | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.safe_copy_directory", | ||
mock_fs_ops.safe_copy_directory, | ||
): | ||
await new_altium_project(mock_container) | ||
|
||
mock_fs_ops.safe_copy_directory.assert_called_once() | ||
assert (temp_project_dir / "test-input").exists() | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_update_project_version(mock_container, temp_project_dir): | ||
await _update_project_vc(temp_project_dir) # Ensure .vc.json exists | ||
|
||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_input", return_value="TEST" | ||
), patch("pathlib.Path.cwd", return_value=temp_project_dir): | ||
await update_project_version(mock_container, temp_project_dir, "V2.0") | ||
|
||
# Verify version update | ||
prjpcb_files = list(temp_project_dir.glob("*.PRJPCB")) | ||
assert len(prjpcb_files) == 1 | ||
assert "TestProject_V2.0.PRJPCB" == prjpcb_files[0].name | ||
|
||
# Verify history update | ||
history_file = temp_project_dir / "_history.txt" | ||
assert history_file.exists() | ||
content = history_file.read_text() | ||
assert "2.0" in content | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_rename_project(mock_container, temp_project_dir): | ||
await _update_project_vc(temp_project_dir) # Ensure .vc.json exists | ||
new_name = "NewProjectName" | ||
|
||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_input", return_value=new_name | ||
), patch("pathlib.Path.cwd", return_value=temp_project_dir): | ||
await rename_project(mock_container, temp_project_dir, new_name) | ||
|
||
# Verify renamed files | ||
prjpcb_files = list(temp_project_dir.glob("*.PRJPCB")) | ||
assert len(prjpcb_files) == 1 | ||
assert f"{new_name}_V1.0.PRJPCB" == prjpcb_files[0].name | ||
|
||
|
||
def test_is_altium_project(temp_project_dir): | ||
with patch("pathlib.Path.cwd", return_value=temp_project_dir): | ||
assert is_altium_project() | ||
|
||
empty_dir = temp_project_dir / "empty" | ||
empty_dir.mkdir() | ||
with patch("pathlib.Path.cwd", return_value=empty_dir): | ||
assert not is_altium_project() | ||
|
||
|
||
def test_load_file_mappings(temp_project_dir): | ||
mappings = _load_file_mappings(temp_project_dir, "NewProject", "V2.0") | ||
assert mappings | ||
assert any("NewProject_V2.0.PRJPCB" in mapping[1] for mapping in mappings) | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_rename_files(temp_project_dir): | ||
await _update_project_vc(temp_project_dir) # Ensure .vc.json exists | ||
original_file = temp_project_dir / "TestProject_V1.0.PRJPCB" | ||
new_name = "NewProject" | ||
new_version = "V2.0" | ||
|
||
_rename_files(temp_project_dir, new_version, new_name) | ||
|
||
assert not original_file.exists() | ||
assert (temp_project_dir / f"{new_name}_{new_version}.PRJPCB").exists() | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_edit_project_files(temp_project_dir): | ||
await _update_project_vc(temp_project_dir) # Ensure .vc.json exists | ||
|
||
new_name = "NewProject" | ||
new_version = "V2.0" | ||
|
||
file_content = "TestProject_V1.0.PRJPCB content" | ||
test_file = temp_project_dir / f"{new_name}_{new_version}.PRJPCB" | ||
test_file.write_text(file_content) | ||
|
||
_edit_project_files(temp_project_dir, new_version, new_name) | ||
|
||
with open(test_file) as f: | ||
new_content = f.read() | ||
assert "TestProject_V1.0.PRJPCB" not in new_content | ||
assert f"{new_name}_{new_version}.PRJPCB" in new_content | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_new_altium_project_invalid_name(mock_container, temp_project_dir): | ||
invalid_name = "Invalid/Name" | ||
mock_ask_input = AsyncMock( | ||
side_effect=ValueError("Invalid project name"), return_value=invalid_name | ||
) | ||
mock_ask_select = AsyncMock(return_value="template1") | ||
|
||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_input", mock_ask_input | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ALTIUM_TEMPLATES_PATH", | ||
temp_project_dir, | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_select", mock_ask_select | ||
): | ||
with pytest.raises(ValueError): | ||
await new_altium_project(mock_container) | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_update_project_version_invalid_version(mock_container, temp_project_dir): | ||
await _update_project_vc(temp_project_dir) # Ensure .vc.json exists | ||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.altium.ask_input", | ||
side_effect=ValueError("Invalid version format"), | ||
): | ||
with pytest.raises(ValueError): | ||
await update_project_version(mock_container, temp_project_dir) |
142 changes: 142 additions & 0 deletions
142
src/tests/interfaces/HW_Entwicklung/Altium/test_install.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import subprocess | ||
from unittest.mock import AsyncMock, MagicMock, patch | ||
|
||
import pytest | ||
import pytest_asyncio | ||
from textual.containers import Container | ||
|
||
from src.interfaces.HW_Entwicklung.Altium.install import ( | ||
get_installer_path, | ||
install_altium, | ||
) | ||
|
||
|
||
@pytest_asyncio.fixture | ||
async def mock_container(): | ||
"""Create a mock container with async mount method""" | ||
container = MagicMock(spec=Container) | ||
container.mount = AsyncMock() | ||
container.refresh = MagicMock() | ||
return container | ||
|
||
|
||
@pytest.fixture | ||
def mock_installer_dir(tmp_path): | ||
"""Create a temporary directory with mock installer files""" | ||
installer_dir = tmp_path / "AD24" | ||
installer_dir.mkdir(parents=True) | ||
|
||
# Create mock installer files with different versions | ||
installers = [ | ||
"AltiumDesignerSetup_21.0.exe", | ||
"AltiumDesignerSetup_22.0.exe", | ||
"AltiumDesignerSetup_24.0.exe", | ||
] | ||
|
||
for installer in installers: | ||
(installer_dir / installer).write_bytes(b"mock installer content") | ||
|
||
return installer_dir | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_install_altium_success(mock_container, mock_installer_dir): | ||
"""Test successful Altium installation""" | ||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.ALTIUM_INSTALLER_PATH", | ||
mock_installer_dir, | ||
), patch("subprocess.run") as mock_run, patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.safe_copy_file", AsyncMock() | ||
) as mock_copy: | ||
await install_altium(mock_container) | ||
|
||
# Verify file copy was called | ||
mock_copy.assert_called_once() | ||
|
||
# Verify installer was executed | ||
mock_run.assert_called_once() | ||
cmd_args = mock_run.call_args[0][0] | ||
assert cmd_args[0:2] == ["cmd", "/c"] | ||
assert "AltiumDesignerSetup_24.0.exe" in cmd_args[2] | ||
|
||
|
||
def test_get_installer_path(mock_installer_dir): | ||
"""Test installer path resolution""" | ||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.ALTIUM_INSTALLER_PATH", | ||
mock_installer_dir, | ||
): | ||
installer_path = get_installer_path() | ||
|
||
assert installer_path is not None | ||
assert installer_path.name == "AltiumDesignerSetup_24.0.exe" | ||
|
||
|
||
def test_get_installer_path_empty_dir(tmp_path): | ||
"""Test installer path resolution with empty directory""" | ||
empty_dir = tmp_path / "empty" | ||
empty_dir.mkdir() | ||
|
||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.ALTIUM_INSTALLER_PATH", empty_dir | ||
): | ||
installer_path = get_installer_path() | ||
assert installer_path is None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_install_altium_copy_error(mock_container, mock_installer_dir): | ||
"""Test handling of file copy errors""" | ||
|
||
async def mock_copy_error(*args, **kwargs): | ||
raise OSError("Copy failed") | ||
|
||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.ALTIUM_INSTALLER_PATH", | ||
mock_installer_dir, | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.safe_copy_file", mock_copy_error | ||
), pytest.raises( | ||
IOError | ||
): | ||
await install_altium(mock_container) | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_install_altium_subprocess_error(mock_container, mock_installer_dir): | ||
"""Test handling of subprocess execution errors""" | ||
|
||
def mock_run_error(*args, **kwargs): | ||
raise subprocess.SubprocessError("Installation failed") | ||
|
||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.ALTIUM_INSTALLER_PATH", | ||
mock_installer_dir, | ||
), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.safe_copy_file", AsyncMock() | ||
), patch( | ||
"subprocess.run", mock_run_error | ||
), pytest.raises( | ||
subprocess.SubprocessError | ||
): | ||
await install_altium(mock_container) | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_install_altium_refresh_and_sleep(mock_container, mock_installer_dir): | ||
"""Test that container refresh and sleep are called""" | ||
with patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.ALTIUM_INSTALLER_PATH", | ||
mock_installer_dir, | ||
), patch("subprocess.run"), patch( | ||
"src.interfaces.HW_Entwicklung.Altium.install.safe_copy_file", AsyncMock() | ||
), patch( | ||
"asyncio.sleep", AsyncMock() | ||
) as mock_sleep: | ||
await install_altium(mock_container) | ||
|
||
# Verify refresh was called | ||
mock_container.refresh.assert_called_once() | ||
|
||
# Verify sleep was called with correct duration | ||
mock_sleep.assert_called_once_with(1) |