Skip to content

Commit 72f928e

Browse files
solzipclaude
andcommitted
fix: CI 테스트 14건 실패 수정 — surrogate/mock/assertion 오류 해결
- Notion exporter: requests 미설치 환경에서 sys.modules mock 방식으로 변경 - indexer/stats: UTF-16 surrogate pair를 정상 Unicode(\U0001f4c1)로 교체 - git_info: _get_branch 직접 patch로 예외 전파 테스트 수정 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 50d5e06 commit 72f928e

File tree

4 files changed

+69
-69
lines changed

4 files changed

+69
-69
lines changed

tests/test_exporters.py

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -295,72 +295,76 @@ def test_validate_config_empty(self):
295295
from claude_diary.exporters.notion import NotionExporter
296296
assert not NotionExporter({}).validate_config()
297297

298-
@patch("requests.post")
299-
def test_export_success(self, mock_post):
298+
def test_export_success(self):
300299
from claude_diary.exporters.notion import NotionExporter
300+
mock_requests = MagicMock()
301301
mock_resp = MagicMock()
302302
mock_resp.status_code = 200
303-
mock_post.return_value = mock_resp
304-
305-
exp = NotionExporter({"api_token": "secret_abc", "database_id": "db123"})
306-
result = exp.export(SAMPLE_ENTRY)
307-
assert result is True
308-
mock_post.assert_called_once()
309-
310-
# Verify the API call — requests.post(url, headers=..., json=..., timeout=...)
311-
call_kwargs = mock_post.call_args
312-
assert call_kwargs[0][0] == "https://api.notion.com/v1/pages"
313-
headers = call_kwargs[1]["headers"]
314-
assert headers["Authorization"] == "Bearer secret_abc"
315-
assert headers["Notion-Version"] == "2022-06-28"
316-
317-
@patch("requests.post")
318-
def test_export_failure_status(self, mock_post):
303+
mock_requests.post.return_value = mock_resp
304+
305+
with patch.dict("sys.modules", {"requests": mock_requests}):
306+
exp = NotionExporter({"api_token": "secret_abc", "database_id": "db123"})
307+
result = exp.export(SAMPLE_ENTRY)
308+
assert result is True
309+
mock_requests.post.assert_called_once()
310+
311+
# Verify the API call — requests.post(url, headers=..., json=..., timeout=...)
312+
call_kwargs = mock_requests.post.call_args
313+
assert call_kwargs[0][0] == "https://api.notion.com/v1/pages"
314+
headers = call_kwargs[1]["headers"]
315+
assert headers["Authorization"] == "Bearer secret_abc"
316+
assert headers["Notion-Version"] == "2022-06-28"
317+
318+
def test_export_failure_status(self):
319319
from claude_diary.exporters.notion import NotionExporter
320+
mock_requests = MagicMock()
320321
mock_resp = MagicMock()
321322
mock_resp.status_code = 400
322-
mock_post.return_value = mock_resp
323+
mock_requests.post.return_value = mock_resp
323324

324-
exp = NotionExporter({"api_token": "secret_abc", "database_id": "db123"})
325-
result = exp.export(SAMPLE_ENTRY)
326-
assert result is False
325+
with patch.dict("sys.modules", {"requests": mock_requests}):
326+
exp = NotionExporter({"api_token": "secret_abc", "database_id": "db123"})
327+
result = exp.export(SAMPLE_ENTRY)
328+
assert result is False
327329

328-
@patch("requests.post")
329-
def test_export_with_team_member(self, mock_post):
330+
def test_export_with_team_member(self):
330331
"""Team mode: Author field should be included in properties."""
331332
from claude_diary.exporters.notion import NotionExporter
333+
mock_requests = MagicMock()
332334
mock_resp = MagicMock()
333335
mock_resp.status_code = 200
334-
mock_post.return_value = mock_resp
335-
336-
exp = NotionExporter({
337-
"api_token": "secret_abc",
338-
"database_id": "db123",
339-
"member_name": "alice",
340-
})
341-
exp.export(SAMPLE_ENTRY)
342-
343-
call_kwargs = mock_post.call_args
344-
properties = call_kwargs[1]["json"]["properties"]
345-
assert "Author" in properties
346-
assert properties["Author"]["select"]["name"] == "alice"
347-
348-
@patch("requests.post")
349-
def test_export_properties_structure(self, mock_post):
336+
mock_requests.post.return_value = mock_resp
337+
338+
with patch.dict("sys.modules", {"requests": mock_requests}):
339+
exp = NotionExporter({
340+
"api_token": "secret_abc",
341+
"database_id": "db123",
342+
"member_name": "alice",
343+
})
344+
exp.export(SAMPLE_ENTRY)
345+
346+
call_kwargs = mock_requests.post.call_args
347+
properties = call_kwargs[1]["json"]["properties"]
348+
assert "Author" in properties
349+
assert properties["Author"]["select"]["name"] == "alice"
350+
351+
def test_export_properties_structure(self):
350352
"""Verify properties include git commits and code stats when present."""
351353
from claude_diary.exporters.notion import NotionExporter
354+
mock_requests = MagicMock()
352355
mock_resp = MagicMock()
353356
mock_resp.status_code = 200
354-
mock_post.return_value = mock_resp
357+
mock_requests.post.return_value = mock_resp
355358

356-
exp = NotionExporter({"api_token": "secret_abc", "database_id": "db123"})
357-
exp.export(RICH_ENTRY)
359+
with patch.dict("sys.modules", {"requests": mock_requests}):
360+
exp = NotionExporter({"api_token": "secret_abc", "database_id": "db123"})
361+
exp.export(RICH_ENTRY)
358362

359-
call_kwargs = mock_post.call_args
360-
properties = call_kwargs[1]["json"]["properties"]
361-
assert "Git Commits" in properties
362-
assert "Lines Changed" in properties
363-
assert properties["Lines Changed"]["number"] == 60 # 50 added + 10 deleted
363+
call_kwargs = mock_requests.post.call_args
364+
properties = call_kwargs[1]["json"]["properties"]
365+
assert "Git Commits" in properties
366+
assert "Lines Changed" in properties
367+
assert properties["Lines Changed"]["number"] == 60 # 50 added + 10 deleted
364368

365369
def test_export_requests_not_installed(self):
366370
"""When requests is not installed, export should return False."""

tests/test_git_info.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,8 @@ def fake_run(cmd, **kwargs):
196196
assert result["diff_stat"]["added"] == 3
197197

198198
def test_returns_none_on_exception(self):
199-
def fake_run(cmd, **kwargs):
200-
if "rev-parse" in cmd:
201-
return MagicMock(returncode=0)
202-
raise RuntimeError("unexpected error")
203-
204-
with patch("claude_diary.lib.git_info.subprocess.run", side_effect=fake_run):
199+
with patch("claude_diary.lib.git_info._is_git_repo", return_value=True), \
200+
patch("claude_diary.lib.git_info._get_branch", side_effect=RuntimeError("unexpected error")):
205201
result = collect_git_info("/repo")
206202
assert result is None
207203

tests/test_indexer.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,14 @@ def test_reindex_with_sessions(self, tmp_path):
208208
content = (
209209
"# 2026-03-17\n\n"
210210
"### \u23f0 10:00:00\n"
211-
"\ud83d\udcc1 `my-project`\n\n"
211+
"\U0001f4c1 `my-project`\n\n"
212212
"\uce74\ud14c\uace0\ub9ac: `feature`\n\n"
213213
"\uc791\uc5c5 \uc694\uccad:\n"
214214
" 1. Build authentication module\n"
215215
" 2. Write tests for login\n\n"
216216
" - `src/auth.py`\n\n"
217217
"### \u23f0 14:00:00\n"
218-
"\ud83d\udcc1 `other-project`\n"
218+
"\U0001f4c1 `other-project`\n"
219219
)
220220
(tmp_path / "2026-03-17.md").write_text(content, encoding="utf-8")
221221

@@ -236,11 +236,11 @@ def test_reindex_skips_zero_session_files(self, tmp_path):
236236
def test_reindex_multiple_files(self, tmp_path):
237237
day1 = (
238238
"### \u23f0 10:00:00\n"
239-
"\ud83d\udcc1 `proj-a`\n"
239+
"\U0001f4c1 `proj-a`\n"
240240
)
241241
day2 = (
242242
"### \u23f0 09:00:00\n"
243-
"\ud83d\udcc1 `proj-b`\n"
243+
"\U0001f4c1 `proj-b`\n"
244244
)
245245
(tmp_path / "2026-03-16.md").write_text(day1, encoding="utf-8")
246246
(tmp_path / "2026-03-17.md").write_text(day2, encoding="utf-8")
@@ -255,7 +255,7 @@ def test_reindex_multiple_files(self, tmp_path):
255255
def test_reindex_extracts_keywords_from_task_requests(self, tmp_path):
256256
content = (
257257
"### \u23f0 10:00:00\n"
258-
"\ud83d\udcc1 `proj`\n\n"
258+
"\U0001f4c1 `proj`\n\n"
259259
"\uc791\uc5c5 \uc694\uccad:\n"
260260
" 1. Implement authentication flow\n"
261261
)
@@ -267,7 +267,7 @@ def test_reindex_extracts_keywords_from_task_requests(self, tmp_path):
267267

268268
def test_reindex_handles_unreadable_file(self, tmp_path):
269269
"""A file that parse_daily_file can read but read_text fails for."""
270-
content = "### \u23f0 10:00:00\n\ud83d\udcc1 `proj`\n"
270+
content = "### \u23f0 10:00:00\n\U0001f4c1 `proj`\n"
271271
f = tmp_path / "2026-03-17.md"
272272
f.write_text(content, encoding="utf-8")
273273

@@ -288,7 +288,7 @@ def mock_read_text(self, *args, **kwargs):
288288
def test_reindex_session_without_time(self, tmp_path):
289289
content = (
290290
"### \u23f0\n"
291-
"\ud83d\udcc1 `proj`\n"
291+
"\U0001f4c1 `proj`\n"
292292
)
293293
(tmp_path / "2026-03-17.md").write_text(content, encoding="utf-8")
294294
count = reindex_all(str(tmp_path))
@@ -305,7 +305,7 @@ def test_reindex_session_without_project(self, tmp_path):
305305
assert index["entries"][0]["project"] == ""
306306

307307
def test_reindex_sets_last_indexed(self, tmp_path):
308-
content = "### \u23f0 10:00:00\n\ud83d\udcc1 `proj`\n"
308+
content = "### \u23f0 10:00:00\n\U0001f4c1 `proj`\n"
309309
(tmp_path / "2026-03-17.md").write_text(content, encoding="utf-8")
310310
reindex_all(str(tmp_path))
311311
index = load_index(str(tmp_path))

tests/test_stats.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ class TestParseDailyFileProjects:
5252
def test_extracts_projects(self, tmp_path):
5353
content = (
5454
"### \u23f0 10:00:00\n"
55-
"\ud83d\udcc1 `my-project`\n"
55+
"\U0001f4c1 `my-project`\n"
5656
"### \u23f0 14:00:00\n"
57-
"\ud83d\udcc1 `other-project`\n"
57+
"\U0001f4c1 `other-project`\n"
5858
)
5959
f = tmp_path / "2026-03-17.md"
6060
f.write_text(content, encoding="utf-8")
@@ -64,9 +64,9 @@ def test_extracts_projects(self, tmp_path):
6464
def test_duplicate_projects(self, tmp_path):
6565
content = (
6666
"### \u23f0 10:00:00\n"
67-
"\ud83d\udcc1 `my-project`\n"
67+
"\U0001f4c1 `my-project`\n"
6868
"### \u23f0 14:00:00\n"
69-
"\ud83d\udcc1 `my-project`\n"
69+
"\U0001f4c1 `my-project`\n"
7070
)
7171
f = tmp_path / "2026-03-17.md"
7272
f.write_text(content, encoding="utf-8")
@@ -225,9 +225,9 @@ def test_extracts_task_requests_english(self, tmp_path):
225225
class TestParseDailyFileFullDocument:
226226
def test_full_diary_entry(self, tmp_path):
227227
content = (
228-
"# \ud83d\udcdd 2026-03-17\n\n"
228+
"# \U0001f4dd 2026-03-17\n\n"
229229
"### \u23f0 10:00:00\n"
230-
"\ud83d\udcc1 `my-app`\n\n"
230+
"\U0001f4c1 `my-app`\n\n"
231231
"\uce74\ud14c\uace0\ub9ac: `feature`\n\n"
232232
"\uc0dd\uc131\ub41c \ud30c\uc77c:\n"
233233
" - `src/new.py`\n\n"
@@ -240,7 +240,7 @@ def test_full_diary_entry(self, tmp_path):
240240
"\uc791\uc5c5 \uc694\uccad:\n"
241241
" 1. Build the feature\n\n"
242242
"### \u23f0 14:00:00\n"
243-
"\ud83d\udcc1 `other-app`\n"
243+
"\U0001f4c1 `other-app`\n"
244244
)
245245
f = tmp_path / "2026-03-17.md"
246246
f.write_text(content, encoding="utf-8")

0 commit comments

Comments
 (0)