Skip to content

Commit 6e42da6

Browse files
committed
adding tests
1 parent 5deaa04 commit 6e42da6

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-0
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ path = "src/edit_python_pe/__about__.py"
3030
dev = [
3131
"black>=25.1.0",
3232
"isort>=6.0.1",
33+
"pytest>=8.4.1",
3334
]
3435

3536
[tool.black]

tests/test_member_app.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
import os
2+
import sys
3+
import unittest
4+
from unittest.mock import MagicMock, patch
5+
6+
import pytest
7+
8+
sys.path.insert(
9+
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../src"))
10+
)
11+
from edit_python_pe.main import MemberApp
12+
13+
14+
class TestMemberApp(unittest.TestCase):
15+
def setUp(self):
16+
# Patch Github and Repository for testing
17+
self.token = "fake-token"
18+
self.repo = MagicMock()
19+
self.app = MemberApp(token=self.token, original_repo=self.repo)
20+
self.app.social_container = MagicMock()
21+
self.app.alias_container = MagicMock()
22+
# Manually initialize attributes normally set in on_mount
23+
self.app.social_entries = []
24+
self.app.alias_entries = []
25+
self.app.social_index = 0
26+
self.app.alias_index = 0
27+
28+
# Mock UI elements and REPO_PATH
29+
# Use simple stub classes for input widgets and text areas
30+
class StubInput:
31+
def __init__(self):
32+
self.value = ""
33+
34+
class StubTextArea:
35+
def __init__(self):
36+
self.text = ""
37+
38+
self.app.name_input = StubInput()
39+
self.app.email_input = StubInput()
40+
self.app.city_input = StubInput()
41+
self.app.homepage_input = StubInput()
42+
self.app.about_me_area = StubTextArea()
43+
self.app.who_area = StubTextArea()
44+
self.app.python_area = StubTextArea()
45+
self.app.contributions_area = StubTextArea()
46+
self.app.availability_area = StubTextArea()
47+
self.app.REPO_PATH = "test_repo"
48+
49+
# Patch remove method for entries to avoid Textual lifecycle errors
50+
# Use stub classes for entries with .remove() method
51+
class StubSocialEntry:
52+
def __init__(self):
53+
self.index = 0
54+
self.select = StubInput()
55+
self.url_input = StubInput()
56+
57+
def remove(self):
58+
pass
59+
60+
class StubAliasEntry:
61+
def __init__(self):
62+
self.index = 0
63+
self.alias_input = StubInput()
64+
65+
def remove(self):
66+
pass
67+
68+
self.StubSocialEntry = StubSocialEntry
69+
self.StubAliasEntry = StubAliasEntry
70+
71+
def test_add_social_entry(self):
72+
# Patch add_social_entry to use stub
73+
self.app.social_entries = []
74+
self.app.social_container.mount = MagicMock()
75+
# Patch mount to accept any object
76+
self.app.social_container.mount = lambda x: None # type: ignore
77+
78+
def stub_add_social_entry():
79+
entry = self.StubSocialEntry()
80+
entry.index = self.app.social_index
81+
self.app.social_index += 1
82+
self.app.social_entries.append(entry)
83+
self.app.social_container.mount(entry)
84+
85+
self.app.add_social_entry = stub_add_social_entry
86+
initial_count = len(self.app.social_entries)
87+
self.app.add_social_entry()
88+
self.assertEqual(len(self.app.social_entries), initial_count + 1)
89+
90+
def test_add_alias_entry(self):
91+
# Patch add_alias_entry to use stub
92+
self.app.alias_entries = []
93+
self.app.alias_container.mount = MagicMock()
94+
# Patch mount to accept any object
95+
self.app.alias_container.mount = lambda x: None # type: ignore
96+
97+
def stub_add_alias_entry():
98+
entry = self.StubAliasEntry()
99+
entry.index = self.app.alias_index
100+
self.app.alias_index += 1
101+
self.app.alias_entries.append(entry)
102+
self.app.alias_container.mount(entry)
103+
104+
self.app.add_alias_entry = stub_add_alias_entry
105+
initial_count = len(self.app.alias_entries)
106+
self.app.add_alias_entry()
107+
self.assertEqual(len(self.app.alias_entries), initial_count + 1)
108+
109+
def test_clear_form(self):
110+
# Patch add_social_entry and add_alias_entry to use stub
111+
self.app.social_entries = []
112+
self.app.alias_entries = []
113+
self.app.social_container.remove_children = lambda: None # type: ignore
114+
self.app.alias_container.remove_children = lambda: None # type: ignore
115+
116+
def stub_add_social_entry():
117+
entry = self.StubSocialEntry()
118+
entry.index = self.app.social_index
119+
self.app.social_index += 1
120+
self.app.social_entries.append(entry)
121+
self.app.social_container.mount(entry)
122+
123+
def stub_add_alias_entry():
124+
entry = self.StubAliasEntry()
125+
entry.index = self.app.alias_index
126+
self.app.alias_index += 1
127+
self.app.alias_entries.append(entry)
128+
self.app.alias_container.mount(entry)
129+
130+
self.app.add_social_entry = stub_add_social_entry
131+
self.app.add_alias_entry = stub_add_alias_entry
132+
self.app.add_social_entry()
133+
self.app.add_alias_entry()
134+
self.app.clear_form()
135+
self.assertEqual(len(self.app.social_entries), 0)
136+
self.assertEqual(len(self.app.alias_entries), 0)
137+
138+
@patch("edit_python_pe.main.open", create=True)
139+
@patch("edit_python_pe.main.os.path.exists", return_value=True)
140+
def test_load_file_into_form(self, mock_exists, mock_open):
141+
# Simulate a markdown file with social and alias data
142+
mock_open.return_value.__enter__.return_value.read.return_value = """
143+
---
144+
@author: joe
145+
@location: Lima
146+
---
147+
# Joe Doe
148+
```{gravatar} joe@example.com
149+
---
150+
width: 200
151+
class: "member-gravatar"
152+
---
153+
```
154+
```{raw} html
155+
<ul class="social-media profile">
156+
<li>
157+
<a class="external reference" href="https://github.com/joe.doe">
158+
<iconify-icon icon="simple-icons:github" style="font-size:2em"></iconify-icon>
159+
</a>
160+
</li>
161+
</ul>
162+
```
163+
:Aliases: joe
164+
:Ciudad: Lima
165+
:Homepage: https://joe-doe.org
166+
"""
167+
# Patch add_social_entry and add_alias_entry to use stub
168+
self.app.social_entries = []
169+
self.app.alias_entries = []
170+
171+
def stub_add_social_entry():
172+
entry = self.StubSocialEntry()
173+
entry.index = self.app.social_index
174+
self.app.social_index += 1
175+
self.app.social_entries.append(entry)
176+
self.app.social_container.mount(entry)
177+
178+
def stub_add_alias_entry():
179+
entry = self.StubAliasEntry()
180+
entry.index = self.app.alias_index
181+
self.app.alias_index += 1
182+
self.app.alias_entries.append(entry)
183+
self.app.alias_container.mount(entry)
184+
185+
self.app.add_social_entry = stub_add_social_entry
186+
self.app.add_alias_entry = stub_add_alias_entry
187+
# Patch clear_form to avoid resetting stubs
188+
self.app.clear_form = lambda: None # type: ignore
189+
self.app.load_file_into_form("fake.md")
190+
# Assert YAML author assignment first
191+
# The stub allows assignment, so check after YAML parsing
192+
yaml_author = "joe"
193+
self.assertIn(
194+
self.app.name_input.value,
195+
[yaml_author, "Joe Doe"],
196+
f"Expected YAML author or markdown header, got '{self.app.name_input.value}'",
197+
)
198+
# Now check if markdown header overwrites it
199+
# The regex should match '# Joe Doe' and overwrite the value
200+
# If not, print debug info
201+
if self.app.name_input.value != "Joe Doe":
202+
print(
203+
"DEBUG: Markdown header regex did not match, value is:",
204+
self.app.name_input.value,
205+
)
206+
self.assertEqual(
207+
self.app.name_input.value,
208+
"Joe Doe",
209+
f"Expected 'Joe Doe', got '{self.app.name_input.value}'",
210+
)
211+
self.assertEqual(self.app.email_input.value, "joe@example.com")
212+
self.assertEqual(self.app.city_input.value, "Lima")
213+
self.assertEqual(self.app.homepage_input.value, "https://joe-doe.org")
214+
self.assertGreaterEqual(len(self.app.social_entries), 1)
215+
self.assertGreaterEqual(len(self.app.alias_entries), 1)
216+
217+
218+
if __name__ == "__main__":
219+
unittest.main()

uv.lock

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)