prole/tests/test_service_layer_navigation.py
chrisfu 5e0a1bda85 feat: Add GitOps (Gitea) and Supabase integration, plus database options
- Makefile: Added 'init' and 'deploy' targets for k3s parity and Gitea staging.

- OpenTofu: Fixed namespace handling in k3s main.tf to prevent metadata overwrites.

- UI: Added 'GitOps' and 'Database Options' configuration screens.

- Core: Enhanced monitoring, milestones, and environment handling for new services.

- Supabase: Integrated full Helm chart and manifest rendering logic.

- Gitea: Added deployment scripts and GitOps sync support.

- Database: Added Percona/Postgres Dockerfile templates and improved TDE scripts.

- Tests: Added coverage for new UI screens and navigation flows.
2026-02-26 18:32:15 -08:00

125 lines
4.2 KiB
Python

import sys
from unittest.mock import patch, MagicMock
import pytest
from pathlib import Path
# Mock tkinter and other GUI/macOS specific imports
sys.modules["tkinter"] = MagicMock()
sys.modules["tkinter.ttk"] = MagicMock()
sys.modules["tkinter.scrolledtext"] = MagicMock()
sys.modules["tkinter.messagebox"] = MagicMock()
sys.modules["Foundation"] = MagicMock()
sys.modules["AppKit"] = MagicMock()
sys.modules["PIL"] = MagicMock()
sys.modules["PIL.Image"] = MagicMock()
sys.modules["PIL.ImageTk"] = MagicMock()
import install
from install import ProleInstaller
@pytest.fixture
def mock_installer(tmp_path):
test_cfg_src = Path(__file__).parent / "fixtures" / "test-prole.cfg"
cfg_path = tmp_path / "prole.cfg"
cfg_path.write_text(test_cfg_src.read_text())
with patch("install.tk.Tk"), patch("install.tk.Frame"), patch(
"install.tk.Canvas"
), patch("install.tk.Label"), patch("install.tk.Button"), patch(
"install.tk.Entry"
) as mock_entry, patch(
"install.tk.StringVar"
), patch(
"install.tk.BooleanVar"
), patch(
"install.tk.IntVar"
), patch(
"install.ttk.Style"
), patch(
"install.Path.exists", return_value=True
), patch(
"install.Path.mkdir"
), patch.object(
ProleInstaller, "_save_env_to_file"
), patch.object(
ProleInstaller, "_save_prole_cfg"
), patch.object(
ProleInstaller, "_save_ansible_prole_vault"
), patch.object(
ProleInstaller, "_after_env_saved"
), patch(
"threading.Thread"
):
mock_entry.return_value.get.return_value.strip.return_value = "mock_val"
root = MagicMock()
root.winfo_screenwidth.return_value = 1920
root.winfo_screenheight.return_value = 1080
app = ProleInstaller(root, config_path=str(cfg_path))
app.bg_canvas.winfo_width.return_value = 1000
return app
def test_service_layer_navigation_pause(mock_installer):
# Go to init_cluster
mock_installer.show_page("init_cluster")
# Mock cluster ready
with patch.object(
mock_installer, "_cluster_ready_for_navigation", return_value=True
):
# Click Next - should NOT go to init_password yet, but show overlay
with patch.object(mock_installer, "_run_service_layer_overlay") as mock_overlay:
mock_installer.on_next()
mock_overlay.assert_called_once()
assert mock_installer.pages[mock_installer.page_index][0] == "init_cluster"
def test_service_layer_overlay_behavior(mock_installer):
mock_installer.show_page("init_cluster")
# Trigger overlay
with patch.object(
mock_installer, "_cluster_ready_for_navigation", return_value=True
), patch.object(mock_installer, "_create_console_output"):
mock_installer.on_next()
assert mock_installer._showing_service_overlay is True
assert mock_installer._common_services_success is False
# Next button should be disabled via update_footer
mock_installer.next_button = MagicMock()
mock_installer.prev_button = MagicMock()
mock_installer.update_footer()
mock_installer.next_button.configure.assert_any_call(state="disabled")
# Simulate success
mock_installer._common_services_success = True
mock_installer.next_button.reset_mock()
mock_installer.update_footer()
mock_installer.next_button.configure.assert_any_call(state="normal")
# Now Next should proceed
with patch.object(
mock_installer, "_cluster_ready_for_navigation", return_value=True
):
mock_installer.on_next()
assert mock_installer.pages[mock_installer.page_index][0] == "database_options"
def test_service_layer_prev_behavior(mock_installer):
mock_installer.show_page("init_cluster")
with patch.object(
mock_installer, "_cluster_ready_for_navigation", return_value=True
), patch.object(mock_installer, "_create_console_output"):
mock_installer.on_next()
assert mock_installer._showing_service_overlay is True
# Prev from overlay should go back to init_cluster and reset overlay flag
mock_installer.on_prev()
assert mock_installer._showing_service_overlay is False
assert mock_installer.pages[mock_installer.page_index][0] == "init_cluster"