mirror of
https://github.com/SuperClaude-Org/SuperClaude_Framework.git
synced 2025-12-17 17:56:46 +00:00
96 lines
3.6 KiB
Python
96 lines
3.6 KiB
Python
|
|
import pytest
|
||
|
|
from pathlib import Path
|
||
|
|
import shutil
|
||
|
|
import tarfile
|
||
|
|
import tempfile
|
||
|
|
from unittest.mock import MagicMock
|
||
|
|
from setup.core.installer import Installer
|
||
|
|
|
||
|
|
class TestInstaller:
|
||
|
|
def test_create_backup_empty_dir(self):
|
||
|
|
with tempfile.TemporaryDirectory() as temp_dir_str:
|
||
|
|
temp_dir = Path(temp_dir_str)
|
||
|
|
installer = Installer(install_dir=temp_dir)
|
||
|
|
|
||
|
|
backup_path = installer.create_backup()
|
||
|
|
|
||
|
|
assert backup_path is not None
|
||
|
|
assert backup_path.exists()
|
||
|
|
|
||
|
|
# This is the crucial part: check if it's a valid tar file.
|
||
|
|
# An empty file created with .touch() is not a valid tar file.
|
||
|
|
try:
|
||
|
|
with tarfile.open(backup_path, "r:gz") as tar:
|
||
|
|
members = tar.getmembers()
|
||
|
|
# An empty archive can have 0 members, or 1 member (the root dir)
|
||
|
|
if len(members) == 1:
|
||
|
|
assert members[0].name == "."
|
||
|
|
else:
|
||
|
|
assert len(members) == 0
|
||
|
|
except tarfile.ReadError as e:
|
||
|
|
pytest.fail(f"Backup file is not a valid tar.gz file: {e}")
|
||
|
|
|
||
|
|
def test_skips_already_installed_component(self):
|
||
|
|
# Create a mock component that is NOT reinstallable
|
||
|
|
mock_component = MagicMock()
|
||
|
|
mock_component.get_metadata.return_value = {'name': 'test_component'}
|
||
|
|
mock_component.is_reinstallable.return_value = False
|
||
|
|
mock_component.install.return_value = True
|
||
|
|
mock_component.validate_prerequisites.return_value = (True, [])
|
||
|
|
|
||
|
|
installer = Installer()
|
||
|
|
installer.register_component(mock_component)
|
||
|
|
|
||
|
|
# Simulate component is already installed
|
||
|
|
installer.installed_components = {'test_component'}
|
||
|
|
|
||
|
|
installer.install_component('test_component', {})
|
||
|
|
|
||
|
|
# Assert that the install method was NOT called
|
||
|
|
mock_component.install.assert_not_called()
|
||
|
|
assert 'test_component' in installer.skipped_components
|
||
|
|
|
||
|
|
def test_installs_reinstallable_component(self):
|
||
|
|
# Create a mock component that IS reinstallable
|
||
|
|
mock_component = MagicMock()
|
||
|
|
mock_component.get_metadata.return_value = {'name': 'reinstallable_component'}
|
||
|
|
mock_component.is_reinstallable.return_value = True
|
||
|
|
mock_component.install.return_value = True
|
||
|
|
mock_component.validate_prerequisites.return_value = (True, [])
|
||
|
|
|
||
|
|
installer = Installer()
|
||
|
|
installer.register_component(mock_component)
|
||
|
|
|
||
|
|
# Simulate component is already installed
|
||
|
|
installer.installed_components = {'reinstallable_component'}
|
||
|
|
|
||
|
|
installer.install_component('reinstallable_component', {})
|
||
|
|
|
||
|
|
# Assert that the install method WAS called
|
||
|
|
mock_component.install.assert_called_once()
|
||
|
|
assert 'reinstallable_component' not in installer.skipped_components
|
||
|
|
|
||
|
|
def test_post_install_validation_only_validates_updated_components(self):
|
||
|
|
# Arrange
|
||
|
|
installer = Installer()
|
||
|
|
|
||
|
|
mock_comp1 = MagicMock()
|
||
|
|
mock_comp1.get_metadata.return_value = {'name': 'comp1'}
|
||
|
|
mock_comp1.validate_installation.return_value = (True, [])
|
||
|
|
|
||
|
|
mock_comp2 = MagicMock()
|
||
|
|
mock_comp2.get_metadata.return_value = {'name': 'comp2'}
|
||
|
|
mock_comp2.validate_installation.return_value = (True, [])
|
||
|
|
|
||
|
|
installer.register_component(mock_comp1)
|
||
|
|
installer.register_component(mock_comp2)
|
||
|
|
|
||
|
|
installer.updated_components = {'comp1'}
|
||
|
|
|
||
|
|
# Act
|
||
|
|
installer._run_post_install_validation()
|
||
|
|
|
||
|
|
# Assert
|
||
|
|
mock_comp1.validate_installation.assert_called_once()
|
||
|
|
mock_comp2.validate_installation.assert_not_called()
|