More tests
This commit is contained in:
parent
e8db5bcf7d
commit
ca3c839c7d
5 changed files with 1184 additions and 3 deletions
|
|
@ -1,5 +1,8 @@
|
|||
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()
|
||||
|
|
@ -7,3 +10,196 @@ def test_key_prompt_roundtrip(qtbot):
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1812,3 +1812,279 @@ def test_main_window_update_tag_views_no_tags_widget(
|
|||
window._update_tag_views_for_date("2024-01-15")
|
||||
|
||||
assert True
|
||||
|
||||
|
||||
def test_main_window_with_tags_disabled(qtbot, app, tmp_path):
|
||||
"""Test MainWindow with tags disabled in config - covers line 319"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
s.setValue("ui/tags", False) # Disable tags
|
||||
s.setValue("ui/time_log", True)
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Tags widget should be hidden
|
||||
assert w.tags.isHidden()
|
||||
|
||||
|
||||
def test_main_window_with_time_log_disabled(qtbot, app, tmp_path):
|
||||
"""Test MainWindow with time_log disabled in config - covers line 321"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
s.setValue("ui/tags", True)
|
||||
s.setValue("ui/time_log", False) # Disable time log
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Time log widget should be hidden
|
||||
assert w.time_log.isHidden()
|
||||
|
||||
|
||||
def test_export_csv_format(qtbot, app, tmp_path, monkeypatch):
|
||||
"""Test exporting to CSV format - covers export path lines"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Add some data
|
||||
w.db.save_new_version("2024-01-01", "Test content", "test")
|
||||
|
||||
# Mock file dialog to return CSV
|
||||
dest = tmp_path / "export_test.csv"
|
||||
monkeypatch.setattr(
|
||||
mwmod.QFileDialog,
|
||||
"getSaveFileName",
|
||||
staticmethod(lambda *a, **k: (str(dest), "CSV (*.csv)")),
|
||||
)
|
||||
|
||||
# Mock QMessageBox to auto-accept
|
||||
monkeypatch.setattr(
|
||||
mwmod.QMessageBox, "exec", lambda self: mwmod.QMessageBox.Yes, raising=False
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
mwmod.QMessageBox, "information", staticmethod(lambda *a, **k: 0), raising=False
|
||||
)
|
||||
|
||||
w._export()
|
||||
assert dest.exists()
|
||||
|
||||
|
||||
def test_settings_dialog_with_locale_change(qtbot, app, tmp_path, monkeypatch):
|
||||
"""Test opening settings dialog and changing locale - covers settings dialog paths"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Mock the settings dialog to auto-accept
|
||||
from bouquin.settings_dialog import SettingsDialog
|
||||
|
||||
SettingsDialog.exec
|
||||
|
||||
def fake_exec(self):
|
||||
# Change locale before accepting
|
||||
idx = self.locale_combobox.findData("fr")
|
||||
if idx >= 0:
|
||||
self.locale_combobox.setCurrentIndex(idx)
|
||||
return mwmod.QDialog.Accepted
|
||||
|
||||
monkeypatch.setattr(SettingsDialog, "exec", fake_exec)
|
||||
|
||||
w._open_settings()
|
||||
qtbot.wait(50)
|
||||
|
||||
|
||||
def test_statistics_dialog_open(qtbot, app, tmp_path, monkeypatch):
|
||||
"""Test opening statistics dialog - covers statistics dialog paths"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Add some data
|
||||
w.db.save_new_version("2024-01-01", "Test content", "test")
|
||||
|
||||
from bouquin.statistics_dialog import StatisticsDialog
|
||||
|
||||
StatisticsDialog.exec
|
||||
|
||||
def fake_exec(self):
|
||||
# Just accept immediately
|
||||
return mwmod.QDialog.Accepted
|
||||
|
||||
monkeypatch.setattr(StatisticsDialog, "exec", fake_exec)
|
||||
|
||||
w._open_statistics()
|
||||
qtbot.wait(50)
|
||||
|
||||
|
||||
def test_bug_report_dialog_open(qtbot, app, tmp_path, monkeypatch):
|
||||
"""Test opening bug report dialog"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
from bouquin.bug_report_dialog import BugReportDialog
|
||||
|
||||
BugReportDialog.exec
|
||||
|
||||
def fake_exec(self):
|
||||
return mwmod.QDialog.Rejected
|
||||
|
||||
monkeypatch.setattr(BugReportDialog, "exec", fake_exec)
|
||||
|
||||
w._open_bugs()
|
||||
qtbot.wait(50)
|
||||
|
||||
|
||||
def test_history_dialog_open_and_restore(qtbot, app, tmp_path, monkeypatch):
|
||||
"""Test opening history dialog and restoring a version"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Add some data
|
||||
date_str = QDate.currentDate().toString("yyyy-MM-dd")
|
||||
w.db.save_new_version(date_str, "Version 1", "v1")
|
||||
w.db.save_new_version(date_str, "Version 2", "v2")
|
||||
|
||||
from bouquin.history_dialog import HistoryDialog
|
||||
|
||||
def fake_exec(self):
|
||||
# Simulate selecting first version and accepting
|
||||
if self.list.count() > 0:
|
||||
self.list.setCurrentRow(0)
|
||||
self._revert()
|
||||
return mwmod.QDialog.Accepted
|
||||
|
||||
monkeypatch.setattr(HistoryDialog, "exec", fake_exec)
|
||||
|
||||
w._open_history()
|
||||
qtbot.wait(50)
|
||||
|
||||
|
||||
def test_goto_today_button(qtbot, app, tmp_path):
|
||||
"""Test going to today's date"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Move to a different date
|
||||
past_date = QDate.currentDate().addDays(-30)
|
||||
w.calendar.setSelectedDate(past_date)
|
||||
|
||||
# Go back to today
|
||||
w._adjust_today()
|
||||
qtbot.wait(50)
|
||||
|
||||
assert w.calendar.selectedDate() == QDate.currentDate()
|
||||
|
||||
|
||||
def test_adjust_font_size(qtbot, app, tmp_path):
|
||||
"""Test adjusting font size"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
s.setValue("ui/font_size", 12)
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
initial_size = w.editor.font().pointSize()
|
||||
|
||||
# Increase font size
|
||||
w._on_font_larger_requested()
|
||||
qtbot.wait(50)
|
||||
assert w.editor.font().pointSize() > initial_size
|
||||
|
||||
# Decrease font size
|
||||
w._on_font_smaller_requested()
|
||||
qtbot.wait(50)
|
||||
|
||||
|
||||
def test_calendar_date_selection(qtbot, app, tmp_path):
|
||||
"""Test selecting a date from calendar"""
|
||||
db_path = tmp_path / "notebook.db"
|
||||
s = get_settings()
|
||||
s.setValue("db/default_db", str(db_path))
|
||||
s.setValue("db/key", "test-key")
|
||||
s.setValue("ui/idle_minutes", 0)
|
||||
s.setValue("ui/theme", "light")
|
||||
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
w = MainWindow(themes=themes)
|
||||
qtbot.addWidget(w)
|
||||
w.show()
|
||||
|
||||
# Select a specific date
|
||||
test_date = QDate(2024, 6, 15)
|
||||
w.calendar.setSelectedDate(test_date)
|
||||
qtbot.wait(50)
|
||||
|
||||
# The window should load that date
|
||||
assert test_date.toString("yyyy-MM-dd") in str(w._current_date_iso())
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import base64
|
||||
import pytest
|
||||
|
||||
from PySide6.QtCore import Qt, QPoint
|
||||
|
|
@ -1808,3 +1809,453 @@ def test_insert_alarm_marker_on_checkbox_line_does_not_merge_lines(editor, qtbot
|
|||
# Second line has the alarm marker
|
||||
assert "Foobar" in lines[1]
|
||||
assert "⏰ 16:54" in lines[1]
|
||||
|
||||
|
||||
def test_render_images_with_corrupted_data(qtbot, app):
|
||||
"""Test rendering images with corrupted data that creates null QImage"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
# Create some binary data that will decode but not form a valid image
|
||||
corrupted_data = base64.b64encode(b"not an image file").decode("utf-8")
|
||||
markdown = f""
|
||||
|
||||
editor.from_markdown(markdown)
|
||||
qtbot.wait(50)
|
||||
|
||||
# Should still work without crashing
|
||||
text = editor.to_markdown()
|
||||
assert len(text) >= 0
|
||||
|
||||
|
||||
def test_insert_alarm_marker(qtbot, app):
|
||||
"""Test inserting alarm markers"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
# Insert alarm marker
|
||||
editor.insert_alarm_marker("14:30")
|
||||
qtbot.wait(50)
|
||||
|
||||
content = editor.to_markdown()
|
||||
assert "14:30" in content or "⏰" in content
|
||||
|
||||
|
||||
def test_editor_with_tables(qtbot, app):
|
||||
"""Test editor with markdown tables"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
table_markdown = """
|
||||
| Header 1 | Header 2 |
|
||||
|----------|----------|
|
||||
| Cell 1 | Cell 2 |
|
||||
| Cell 3 | Cell 4 |
|
||||
"""
|
||||
editor.from_markdown(table_markdown)
|
||||
qtbot.wait(50)
|
||||
|
||||
result = editor.to_markdown()
|
||||
assert "Header 1" in result or "|" in result
|
||||
|
||||
|
||||
def test_editor_with_code_blocks(qtbot, app):
|
||||
"""Test editor with code blocks"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
code_markdown = """
|
||||
Some text
|
||||
|
||||
```python
|
||||
def hello():
|
||||
print("world")
|
||||
```
|
||||
|
||||
More text
|
||||
"""
|
||||
editor.from_markdown(code_markdown)
|
||||
qtbot.wait(50)
|
||||
|
||||
result = editor.to_markdown()
|
||||
assert "def hello" in result or "python" in result
|
||||
|
||||
|
||||
def test_editor_undo_redo(qtbot, app):
|
||||
"""Test undo/redo functionality"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
# Type some text
|
||||
editor.from_markdown("Initial text")
|
||||
qtbot.wait(50)
|
||||
|
||||
# Add more text
|
||||
editor.insertPlainText(" additional")
|
||||
qtbot.wait(50)
|
||||
|
||||
# Undo
|
||||
editor.undo()
|
||||
qtbot.wait(50)
|
||||
|
||||
# Redo
|
||||
editor.redo()
|
||||
qtbot.wait(50)
|
||||
|
||||
assert len(editor.to_markdown()) > 0
|
||||
|
||||
|
||||
def test_editor_cut_copy_paste(qtbot, app):
|
||||
"""Test cut/copy/paste operations"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
editor.from_markdown("Test content for copy")
|
||||
qtbot.wait(50)
|
||||
|
||||
# Select all
|
||||
editor.selectAll()
|
||||
|
||||
# Copy
|
||||
editor.copy()
|
||||
qtbot.wait(50)
|
||||
|
||||
# Move to end and paste
|
||||
cursor = editor.textCursor()
|
||||
cursor.movePosition(QTextCursor.End)
|
||||
editor.setTextCursor(cursor)
|
||||
|
||||
editor.paste()
|
||||
qtbot.wait(50)
|
||||
|
||||
# Should have content twice (or clipboard might be empty in test env)
|
||||
assert len(editor.to_markdown()) > 0
|
||||
|
||||
|
||||
def test_editor_with_blockquotes(qtbot, app):
|
||||
"""Test editor with blockquotes"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
quote_markdown = """
|
||||
Normal text
|
||||
|
||||
> This is a quote
|
||||
> With multiple lines
|
||||
|
||||
More normal text
|
||||
"""
|
||||
editor.from_markdown(quote_markdown)
|
||||
qtbot.wait(50)
|
||||
|
||||
result = editor.to_markdown()
|
||||
assert ">" in result or "quote" in result
|
||||
|
||||
|
||||
def test_editor_with_horizontal_rules(qtbot, app):
|
||||
"""Test editor with horizontal rules"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
hr_markdown = """
|
||||
Section 1
|
||||
|
||||
---
|
||||
|
||||
Section 2
|
||||
"""
|
||||
editor.from_markdown(hr_markdown)
|
||||
qtbot.wait(50)
|
||||
|
||||
result = editor.to_markdown()
|
||||
assert "Section" in result
|
||||
|
||||
|
||||
def test_editor_with_mixed_content(qtbot, app):
|
||||
"""Test editor with mixed markdown content"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
mixed_markdown = """
|
||||
# Heading
|
||||
|
||||
This is **bold** and *italic* text.
|
||||
|
||||
- [ ] Todo item
|
||||
- [x] Completed item
|
||||
|
||||
```python
|
||||
code()
|
||||
```
|
||||
|
||||
[Link](https://example.com)
|
||||
|
||||
> Quote
|
||||
|
||||
| Table | Header |
|
||||
|-------|--------|
|
||||
| A | B |
|
||||
"""
|
||||
editor.from_markdown(mixed_markdown)
|
||||
qtbot.wait(50)
|
||||
|
||||
result = editor.to_markdown()
|
||||
# Should contain various markdown elements
|
||||
assert len(result) > 50
|
||||
|
||||
|
||||
def test_editor_insert_text_at_cursor(qtbot, app):
|
||||
"""Test inserting text at cursor position"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
editor.from_markdown("Start Middle End")
|
||||
qtbot.wait(50)
|
||||
|
||||
# Move cursor to middle
|
||||
cursor = editor.textCursor()
|
||||
cursor.setPosition(6)
|
||||
editor.setTextCursor(cursor)
|
||||
|
||||
# Insert text
|
||||
editor.insertPlainText("INSERTED ")
|
||||
qtbot.wait(50)
|
||||
|
||||
result = editor.to_markdown()
|
||||
assert "INSERTED" in result
|
||||
|
||||
|
||||
def test_editor_delete_operations(qtbot, app):
|
||||
"""Test delete operations"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
editor = MarkdownEditor(theme_manager=themes)
|
||||
qtbot.addWidget(editor)
|
||||
editor.show()
|
||||
|
||||
editor.from_markdown("Text to delete")
|
||||
qtbot.wait(50)
|
||||
|
||||
# Select some text and delete
|
||||
cursor = editor.textCursor()
|
||||
cursor.setPosition(0)
|
||||
cursor.setPosition(4, QTextCursor.KeepAnchor)
|
||||
editor.setTextCursor(cursor)
|
||||
|
||||
cursor.removeSelectedText()
|
||||
qtbot.wait(50)
|
||||
|
||||
result = editor.to_markdown()
|
||||
assert "Text" not in result or len(result) < 15
|
||||
|
||||
|
||||
def test_markdown_highlighter_dark_theme(qtbot, app):
|
||||
"""Test markdown highlighter with dark theme - covers lines 74-75"""
|
||||
# Create theme manager with dark theme
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.DARK))
|
||||
|
||||
# Create a text document
|
||||
doc = QTextDocument()
|
||||
|
||||
# Create highlighter with dark theme
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
# Set some markdown text
|
||||
doc.setPlainText("# Heading\n\nSome **bold** text\n\n```python\ncode\n```")
|
||||
|
||||
# The highlighter should work with dark theme
|
||||
assert highlighter is not None
|
||||
assert highlighter.code_block_format is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_light_theme(qtbot, app):
|
||||
"""Test markdown highlighter with light theme"""
|
||||
# Create theme manager with light theme
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
|
||||
# Create a text document
|
||||
doc = QTextDocument()
|
||||
|
||||
# Create highlighter with light theme
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
# Set some markdown text
|
||||
doc.setPlainText("# Heading\n\nSome **bold** text")
|
||||
|
||||
# The highlighter should work with light theme
|
||||
assert highlighter is not None
|
||||
assert highlighter.code_block_format is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_system_dark_theme(qtbot, app, monkeypatch):
|
||||
"""Test markdown highlighter with system dark theme"""
|
||||
# Create theme manager with system theme
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.SYSTEM))
|
||||
|
||||
# Mock the system to be dark
|
||||
monkeypatch.setattr(themes, "_is_system_dark", True)
|
||||
|
||||
# Create a text document
|
||||
doc = QTextDocument()
|
||||
|
||||
# Create highlighter
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
# Set some markdown text
|
||||
doc.setPlainText("# Dark Theme Heading\n\n**Bold text**")
|
||||
|
||||
# The highlighter should use dark theme colors
|
||||
assert highlighter is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_with_headings(qtbot, app):
|
||||
"""Test highlighting various heading levels"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
doc = QTextDocument()
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
markdown = """
|
||||
# H1 Heading
|
||||
## H2 Heading
|
||||
### H3 Heading
|
||||
#### H4 Heading
|
||||
##### H5 Heading
|
||||
###### H6 Heading
|
||||
"""
|
||||
doc.setPlainText(markdown)
|
||||
|
||||
# Should highlight all headings
|
||||
assert highlighter.h1_format is not None
|
||||
assert highlighter.h2_format is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_with_emphasis(qtbot, app):
|
||||
"""Test highlighting bold and italic"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
doc = QTextDocument()
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
markdown = """
|
||||
**Bold text**
|
||||
*Italic text*
|
||||
***Bold and italic***
|
||||
__Also bold__
|
||||
_Also italic_
|
||||
"""
|
||||
doc.setPlainText(markdown)
|
||||
|
||||
# Should have emphasis formats
|
||||
assert highlighter is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_with_code(qtbot, app):
|
||||
"""Test highlighting inline code and code blocks"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
doc = QTextDocument()
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
markdown = """
|
||||
Inline `code` here.
|
||||
|
||||
```python
|
||||
def hello():
|
||||
print("world")
|
||||
```
|
||||
|
||||
More text.
|
||||
"""
|
||||
doc.setPlainText(markdown)
|
||||
|
||||
# Should highlight code
|
||||
assert highlighter.code_block_format is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_with_links(qtbot, app):
|
||||
"""Test highlighting links"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
doc = QTextDocument()
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
markdown = """
|
||||
[Link text](https://example.com)
|
||||
<https://auto-link.com>
|
||||
"""
|
||||
doc.setPlainText(markdown)
|
||||
|
||||
# Should have link format
|
||||
assert highlighter is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_with_lists(qtbot, app):
|
||||
"""Test highlighting lists"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
doc = QTextDocument()
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
markdown = """
|
||||
- Unordered item 1
|
||||
- Unordered item 2
|
||||
|
||||
1. Ordered item 1
|
||||
2. Ordered item 2
|
||||
|
||||
- [ ] Unchecked task
|
||||
- [x] Checked task
|
||||
"""
|
||||
doc.setPlainText(markdown)
|
||||
|
||||
# Should highlight lists
|
||||
assert highlighter is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_with_blockquotes(qtbot, app):
|
||||
"""Test highlighting blockquotes"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
doc = QTextDocument()
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
markdown = """
|
||||
> This is a quote
|
||||
> With multiple lines
|
||||
"""
|
||||
doc.setPlainText(markdown)
|
||||
|
||||
# Should highlight quotes
|
||||
assert highlighter is not None
|
||||
|
||||
|
||||
def test_markdown_highlighter_theme_change(qtbot, app):
|
||||
"""Test changing theme after creation"""
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
doc = QTextDocument()
|
||||
highlighter = MarkdownHighlighter(doc, themes)
|
||||
|
||||
markdown = "# Heading\n\n**Bold**"
|
||||
doc.setPlainText(markdown)
|
||||
|
||||
# Change to dark theme
|
||||
themes.apply(Theme.DARK)
|
||||
qtbot.wait(50)
|
||||
|
||||
# Highlighter should update
|
||||
# We can't directly test the visual change, but verify it doesn't crash
|
||||
assert highlighter is not None
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import datetime as _dt
|
||||
from datetime import datetime, timedelta, date
|
||||
|
||||
from bouquin import strings
|
||||
|
||||
from datetime import date
|
||||
from PySide6.QtCore import Qt, QPoint
|
||||
from PySide6.QtWidgets import QLabel
|
||||
from PySide6.QtTest import QTest
|
||||
from PySide6.QtCore import QDate
|
||||
|
||||
from bouquin.statistics_dialog import DateHeatmap, StatisticsDialog
|
||||
|
||||
|
|
@ -417,3 +418,100 @@ def test_statistics_dialog_gather_stats_exception_handling(
|
|||
|
||||
# Should handle error gracefully
|
||||
assert dialog.isVisible()
|
||||
|
||||
|
||||
def test_statistics_dialog_with_sparse_data(qtbot, tmp_db_cfg, fresh_db):
|
||||
"""Test statistics dialog with sparse data"""
|
||||
# Add some entries on non-consecutive days
|
||||
dates = ["2024-01-01", "2024-01-05", "2024-01-10", "2024-01-20"]
|
||||
for _date in dates:
|
||||
content = "Word " * 100 # 100 words
|
||||
fresh_db.save_new_version(_date, content, "note")
|
||||
|
||||
dialog = StatisticsDialog(fresh_db)
|
||||
qtbot.addWidget(dialog)
|
||||
|
||||
# Should create without crashing
|
||||
assert dialog is not None
|
||||
|
||||
|
||||
def test_statistics_dialog_with_empty_data(qtbot, tmp_db_cfg, fresh_db):
|
||||
"""Test statistics dialog with no data"""
|
||||
dialog = StatisticsDialog(fresh_db)
|
||||
qtbot.addWidget(dialog)
|
||||
|
||||
# Should handle empty data gracefully
|
||||
assert dialog is not None
|
||||
|
||||
|
||||
def test_statistics_dialog_date_range_selection(qtbot, tmp_db_cfg, fresh_db):
|
||||
"""Test changing metric in statistics dialog"""
|
||||
# Add some test data
|
||||
for i in range(10):
|
||||
date = QDate.currentDate().addDays(-i).toString("yyyy-MM-dd")
|
||||
fresh_db.save_new_version(date, f"Content for day {i}", "note")
|
||||
|
||||
dialog = StatisticsDialog(fresh_db)
|
||||
qtbot.addWidget(dialog)
|
||||
|
||||
# Change metric to revisions
|
||||
idx = dialog.metric_combo.findData("revisions")
|
||||
if idx >= 0:
|
||||
dialog.metric_combo.setCurrentIndex(idx)
|
||||
qtbot.wait(50)
|
||||
|
||||
# Change back to words
|
||||
idx = dialog.metric_combo.findData("words")
|
||||
if idx >= 0:
|
||||
dialog.metric_combo.setCurrentIndex(idx)
|
||||
qtbot.wait(50)
|
||||
|
||||
|
||||
def test_heatmap_with_varying_word_counts(qtbot):
|
||||
"""Test heatmap color scaling with varying word counts"""
|
||||
today = datetime.now().date()
|
||||
start = today - timedelta(days=30)
|
||||
|
||||
entries = {}
|
||||
# Create entries with varying word counts
|
||||
for i in range(31):
|
||||
date = start + timedelta(days=i)
|
||||
entries[date] = i * 50 # Increasing word counts
|
||||
|
||||
heatmap = DateHeatmap()
|
||||
heatmap.set_data(entries)
|
||||
qtbot.addWidget(heatmap)
|
||||
heatmap.show()
|
||||
|
||||
# Should paint without errors
|
||||
assert heatmap.isVisible()
|
||||
|
||||
|
||||
def test_heatmap_single_day(qtbot):
|
||||
"""Test heatmap with single day of data"""
|
||||
today = datetime.now().date()
|
||||
entries = {today: 500}
|
||||
|
||||
heatmap = DateHeatmap()
|
||||
heatmap.set_data(entries)
|
||||
qtbot.addWidget(heatmap)
|
||||
heatmap.show()
|
||||
|
||||
assert heatmap.isVisible()
|
||||
|
||||
|
||||
def test_statistics_dialog_metric_changes(qtbot, tmp_db_cfg, fresh_db):
|
||||
"""Test various metric selections"""
|
||||
# Add data spanning multiple months
|
||||
base_date = QDate.currentDate().addDays(-90)
|
||||
for i in range(90):
|
||||
date = base_date.addDays(i).toString("yyyy-MM-dd")
|
||||
fresh_db.save_new_version(date, f"Day {i} content with many words", "note")
|
||||
|
||||
dialog = StatisticsDialog(fresh_db)
|
||||
qtbot.addWidget(dialog)
|
||||
|
||||
# Test each metric option
|
||||
for i in range(dialog.metric_combo.count()):
|
||||
dialog.metric_combo.setCurrentIndex(i)
|
||||
qtbot.wait(50)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import pytest
|
||||
from PySide6.QtCore import Qt, QPoint, QEvent
|
||||
|
||||
from PySide6.QtCore import Qt, QPoint, QEvent, QDate
|
||||
from PySide6.QtGui import QMouseEvent, QColor
|
||||
from PySide6.QtWidgets import QApplication, QMessageBox, QInputDialog, QColorDialog
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QMessageBox,
|
||||
QInputDialog,
|
||||
QColorDialog,
|
||||
QDialog,
|
||||
)
|
||||
from bouquin.db import DBManager
|
||||
from bouquin.strings import load_strings
|
||||
from bouquin.tags_widget import PageTagsWidget, TagChip
|
||||
|
|
@ -2157,3 +2164,156 @@ def test_page_tags_widget_updates_on_tag_change(qtbot, fresh_db):
|
|||
qtbot.wait(100)
|
||||
|
||||
assert widget.chip_layout.count() == 2
|
||||
|
||||
|
||||
def test_tags_widget_open_manager_and_accept(qtbot, tmp_db_cfg, fresh_db, monkeypatch):
|
||||
"""Test opening tag manager dialog and accepting - covers lines 248-256"""
|
||||
tags_widget = PageTagsWidget(fresh_db)
|
||||
qtbot.addWidget(tags_widget)
|
||||
|
||||
# Set a current date
|
||||
date = QDate.currentDate().toString("yyyy-MM-dd")
|
||||
tags_widget.set_current_date(date)
|
||||
|
||||
# Add some tags first
|
||||
fresh_db.add_tag("Test Tag", date)
|
||||
tags_widget._reload_tags()
|
||||
|
||||
# Mock the tag browser dialog
|
||||
from bouquin.tag_browser import TagBrowserDialog
|
||||
|
||||
dialog_executed = []
|
||||
|
||||
def fake_exec(self):
|
||||
dialog_executed.append(True)
|
||||
# Simulate the dialog being accepted
|
||||
return QDialog.Accepted
|
||||
|
||||
monkeypatch.setattr(TagBrowserDialog, "exec", fake_exec)
|
||||
|
||||
# Open the manager
|
||||
tags_widget._open_manager()
|
||||
qtbot.wait(50)
|
||||
|
||||
# Dialog should have been executed
|
||||
assert len(dialog_executed) > 0
|
||||
|
||||
|
||||
def test_tags_widget_open_manager_and_reject(qtbot, tmp_db_cfg, fresh_db, monkeypatch):
|
||||
"""Test opening tag manager dialog and rejecting"""
|
||||
tags_widget = PageTagsWidget(fresh_db)
|
||||
qtbot.addWidget(tags_widget)
|
||||
|
||||
# Set a current date
|
||||
date = QDate.currentDate().toString("yyyy-MM-dd")
|
||||
tags_widget.set_current_date(date)
|
||||
|
||||
# Mock the tag browser dialog
|
||||
from bouquin.tag_browser import TagBrowserDialog
|
||||
|
||||
dialog_executed = []
|
||||
|
||||
def fake_exec(self):
|
||||
dialog_executed.append(True)
|
||||
# Simulate the dialog being rejected
|
||||
return QDialog.Rejected
|
||||
|
||||
monkeypatch.setattr(TagBrowserDialog, "exec", fake_exec)
|
||||
|
||||
# Open the manager
|
||||
tags_widget._open_manager()
|
||||
qtbot.wait(50)
|
||||
|
||||
# Dialog should have been executed
|
||||
assert len(dialog_executed) > 0
|
||||
|
||||
|
||||
def test_tags_widget_open_manager_without_current_date(
|
||||
qtbot, tmp_db_cfg, fresh_db, monkeypatch
|
||||
):
|
||||
"""Test opening tag manager when no current date is set"""
|
||||
tags_widget = PageTagsWidget(fresh_db)
|
||||
qtbot.addWidget(tags_widget)
|
||||
|
||||
# Don't set a current date
|
||||
tags_widget._current_date = None
|
||||
|
||||
# Mock the tag browser dialog
|
||||
from bouquin.tag_browser import TagBrowserDialog
|
||||
|
||||
dialog_executed = []
|
||||
|
||||
def fake_exec(self):
|
||||
dialog_executed.append(True)
|
||||
return QDialog.Accepted
|
||||
|
||||
monkeypatch.setattr(TagBrowserDialog, "exec", fake_exec)
|
||||
|
||||
# Open the manager
|
||||
tags_widget._open_manager()
|
||||
qtbot.wait(50)
|
||||
|
||||
# Dialog should still execute
|
||||
assert len(dialog_executed) > 0
|
||||
|
||||
|
||||
def test_tags_widget_manager_with_date_click_signal(
|
||||
qtbot, tmp_db_cfg, fresh_db, monkeypatch
|
||||
):
|
||||
"""Test tag manager emitting openDateRequested signal"""
|
||||
tags_widget = PageTagsWidget(fresh_db)
|
||||
qtbot.addWidget(tags_widget)
|
||||
|
||||
date = QDate.currentDate().toString("yyyy-MM-dd")
|
||||
tags_widget.set_current_date(date)
|
||||
|
||||
activated_tags = []
|
||||
|
||||
def capture_tag(tag):
|
||||
activated_tags.append(tag)
|
||||
|
||||
tags_widget.tagActivated.connect(capture_tag)
|
||||
|
||||
# Mock the tag browser dialog
|
||||
from bouquin.tag_browser import TagBrowserDialog
|
||||
|
||||
def fake_exec(self):
|
||||
# Simulate clicking a date in the browser
|
||||
self.openDateRequested.emit("2024-01-01")
|
||||
return QDialog.Accepted
|
||||
|
||||
monkeypatch.setattr(TagBrowserDialog, "exec", fake_exec)
|
||||
|
||||
# Open the manager
|
||||
tags_widget._open_manager()
|
||||
qtbot.wait(50)
|
||||
|
||||
# Should have captured the activated tag/date
|
||||
assert len(activated_tags) > 0
|
||||
assert "2024-01-01" in activated_tags
|
||||
|
||||
|
||||
def test_tags_widget_chip_click(qtbot, tmp_db_cfg, fresh_db):
|
||||
"""Test clicking on a tag chip"""
|
||||
tags_widget = PageTagsWidget(fresh_db)
|
||||
qtbot.addWidget(tags_widget)
|
||||
|
||||
date = QDate.currentDate().toString("yyyy-MM-dd")
|
||||
tags_widget.set_current_date(date)
|
||||
|
||||
# Add a tag
|
||||
fresh_db.add_tag("ClickMe", date)
|
||||
tags_widget._reload_tags()
|
||||
|
||||
activated_tags = []
|
||||
|
||||
def capture_tag(tag):
|
||||
activated_tags.append(tag)
|
||||
|
||||
tags_widget.tagActivated.connect(capture_tag)
|
||||
|
||||
# Simulate chip click
|
||||
tags_widget._on_chip_clicked("ClickMe")
|
||||
qtbot.wait(50)
|
||||
|
||||
assert "ClickMe" in activated_tags
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue