from bouquin.key_prompt import KeyPrompt from PySide6.QtCore import QTimer from PySide6.QtWidgets import QFileDialog, QLineEdit def test_key_prompt_roundtrip(qtbot): kp = KeyPrompt() qtbot.addWidget(kp) kp.show() kp.key_entry.setText("swordfish") assert kp.key() == "swordfish" def test_key_prompt_with_db_path_browse(qtbot, app, tmp_path, monkeypatch): """Test KeyPrompt with DB path selection - covers lines 57-67""" test_db = tmp_path / "test.db" test_db.touch() # Create prompt with show_db_change=True prompt = KeyPrompt(show_db_change=True) qtbot.addWidget(prompt) # Mock the file dialog to return a file def mock_get_open_filename(*args, **kwargs): return str(test_db), "SQLCipher DB (*.db)" monkeypatch.setattr(QFileDialog, "getOpenFileName", mock_get_open_filename) # Simulate clicking the browse button # Find the browse button by looking through the widget's children browse_btn = None for child in prompt.findChildren(object): if hasattr(child, "clicked") and hasattr(child, "text"): if ( "select" in str(child.text()).lower() or "browse" in str(child.text()).lower() ): browse_btn = child break if browse_btn: browse_btn.click() qtbot.wait(50) # Verify the path was set assert prompt.path_edit is not None assert str(test_db) in prompt.path_edit.text() def test_key_prompt_with_db_path_no_file_selected(qtbot, app, tmp_path, monkeypatch): """Test KeyPrompt when cancel is clicked in file dialog - covers line 64 condition""" # Create prompt with show_db_change=True prompt = KeyPrompt(show_db_change=True) qtbot.addWidget(prompt) # Mock the file dialog to return empty string (user cancelled) def mock_get_open_filename(*args, **kwargs): return "", "" monkeypatch.setattr(QFileDialog, "getOpenFileName", mock_get_open_filename) # Store original path text original_text = prompt.path_edit.text() if prompt.path_edit else "" # Simulate clicking the browse button browse_btn = None for child in prompt.findChildren(object): if hasattr(child, "clicked") and hasattr(child, "text"): if ( "select" in str(child.text()).lower() or "browse" in str(child.text()).lower() ): browse_btn = child break if browse_btn: browse_btn.click() qtbot.wait(50) # Path should not have changed since no file was selected if prompt.path_edit: assert prompt.path_edit.text() == original_text def test_key_prompt_with_existing_db_path(qtbot, app, tmp_path): """Test KeyPrompt with existing DB path provided""" test_db = tmp_path / "existing.db" test_db.touch() prompt = KeyPrompt(show_db_change=True, initial_db_path=test_db) qtbot.addWidget(prompt) # Verify the path is pre-filled assert prompt.path_edit is not None assert str(test_db) in prompt.path_edit.text() def test_key_prompt_with_db_path_none_and_show_db_change(qtbot, app): """Test KeyPrompt with show_db_change but no initial_db_path - covers line 57""" prompt = KeyPrompt(show_db_change=True, initial_db_path=None) qtbot.addWidget(prompt) # Path edit should exist but be empty assert prompt.path_edit is not None assert prompt.path_edit.text() == "" def test_key_prompt_accept_with_valid_key(qtbot, app): """Test accepting prompt with valid key""" prompt = KeyPrompt() qtbot.addWidget(prompt) # Enter a key prompt.key_entry.setText("test-key-123") # Accept QTimer.singleShot(0, prompt.accept) qtbot.wait(50) assert prompt.key_entry.text() == "test-key-123" def test_key_prompt_without_db_change(qtbot, app): """Test KeyPrompt without show_db_change""" prompt = KeyPrompt(show_db_change=False) qtbot.addWidget(prompt) # Path edit should not exist assert prompt.path_edit is None def test_key_prompt_password_visibility(qtbot, app): """Test password entry mode""" prompt = KeyPrompt() qtbot.addWidget(prompt) # Initially should be password mode assert prompt.key_entry.echoMode() == QLineEdit.EchoMode.Password # Enter some text prompt.key_entry.setText("secret") # The text should be obscured assert prompt.key_entry.echoMode() == QLineEdit.EchoMode.Password def test_key_prompt_key_method(qtbot, app): """Test the key() method returns entered text""" prompt = KeyPrompt() qtbot.addWidget(prompt) prompt.key_entry.setText("my-secret-key") assert prompt.key() == "my-secret-key" def test_key_prompt_db_path_method(qtbot, app, tmp_path): """Test the db_path() method returns selected path""" test_db = tmp_path / "test.db" test_db.touch() prompt = KeyPrompt(show_db_change=True, initial_db_path=test_db) qtbot.addWidget(prompt) # Should return the db_path assert prompt.db_path() == test_db def test_key_prompt_browse_with_initial_path(qtbot, app, tmp_path, monkeypatch): """Test browsing when initial_db_path is set - covers line 57 with non-None path""" initial_db = tmp_path / "initial.db" initial_db.touch() new_db = tmp_path / "new.db" new_db.touch() prompt = KeyPrompt(show_db_change=True, initial_db_path=initial_db) qtbot.addWidget(prompt) # Mock the file dialog to return a different file def mock_get_open_filename(*args, **kwargs): # Verify that start_dir was passed correctly (line 57) return str(new_db), "SQLCipher DB (*.db)" monkeypatch.setattr(QFileDialog, "getOpenFileName", mock_get_open_filename) # Find and click browse button browse_btn = None for child in prompt.findChildren(object): if hasattr(child, "clicked") and hasattr(child, "text"): if ( "select" in str(child.text()).lower() or "browse" in str(child.text()).lower() ): browse_btn = child break if browse_btn: browse_btn.click() qtbot.wait(50) # Verify new path was set assert str(new_db) in prompt.path_edit.text() assert prompt.db_path() == new_db