test: add unit tests for DuplicateService and AutoCloseService#509
Conversation
- Replace raw user_id with SHA256 hash (8-char prefix) in all log statements - Maintains audit trail capability while protecting user identifiers (PII) - Complies with GDPR/CCPA privacy requirements - Hash is deterministic for correlation without exposing PII Resolves CodeRabbit PII logging concern
…backfill Fix tenant ticket orphaning by persisting company_id on save
…ashboard feat: Real-time Support Dashboard Updates Using Supabase Realtime Channels
…y bugs on Ticket Detail page
…bles across UI and config
… with premium header
…link them in landing footer
…and style premium elements
- Add test_duplicate_service.py with 5 test cases: - test_check_duplicate_returns_no_match_when_store_empty - test_check_duplicate_uses_custom_threshold - test_check_duplicate_handles_degraded_mode - test_check_duplicate_returns_best_match - test_check_duplicate_below_threshold - Add test_auto_close.py with 6 test cases: - test_get_system_settings_returns_defaults_on_error - test_get_system_settings_returns_db_values - test_close_ticket_success - test_close_ticket_failure - test_service_initialization Closes ritesh-1918#297, Closes ritesh-1918#279
|
Someone is attempting to deploy a commit to the ritesh Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughTwo test modules add comprehensive unit test coverage for backend services. ChangesAutoCloseService Test Coverage
DuplicateService Test Coverage
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
backend/tests/test_auto_close.py (2)
16-21: ⚡ Quick winAvoid process-wide env mutation at import time.
Setting
os.environat module import can leak state into other tests. Use per-test env patching so state is isolated and automatically restored.Proposed refactor
-# Set environment variables before importing -os.environ["SUPABASE_URL"] = "https://test.supabase.co" -os.environ["SUPABASE_SERVICE_ROLE_KEY"] = "test-key" -os.environ["AUTO_CLOSE_ENABLED"] = "true" -os.environ["AUTO_CLOSE_DAYS"] = "7" - from backend.services.auto_close_service import AutoCloseService class TestAutoCloseService: @@ def setup_method(self): """Reset service before each test.""" + self._env = patch.dict(os.environ, { + "SUPABASE_URL": "https://test.supabase.co", + "SUPABASE_SERVICE_ROLE_KEY": "test-key", + "AUTO_CLOSE_ENABLED": "true", + "AUTO_CLOSE_DAYS": "7", + }) + self._env.start() with patch("backend.services.auto_close_service.create_client") as mock_client: self.mock_supabase = MagicMock() mock_client.return_value = self.mock_supabase self.service = AutoCloseService() + + def teardown_method(self): + self._env.stop()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/tests/test_auto_close.py` around lines 16 - 21, Remove the module-level os.environ mutations (the lines setting "SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY", "AUTO_CLOSE_ENABLED", "AUTO_CLOSE_DAYS") and instead set these variables inside the test using per-test env patching (e.g., pytest's monkeypatch.setenv or a fixture) so state is isolated and restored; update the test(s) in test_auto_close.py to call monkeypatch.setenv("AUTO_CLOSE_DAYS", "7") etc. before exercising the code that reads the env and ensure no import-time side effects remain.
64-76: ⚡ Quick winAssert the update contract in the success-path close test.
This test currently proves only “no exception + counter increment.” It should also assert the
tickets.update(...)payload and filters (id,company_id) to lock the behavior promised by_close_ticket.Proposed assertions
def test_close_ticket_success(self): """Should successfully close a ticket and update stats.""" # Mock successful update mock_table = MagicMock() mock_table.update.return_value.eq.return_value.eq.return_value.execute.return_value = MagicMock() self.mock_supabase.table.return_value = mock_table @@ assert result is True assert stats["closed_count"] == 1 assert stats["error_count"] == 0 + self.mock_supabase.table.assert_called_once_with("tickets") + update_arg = mock_table.update.call_args.args[0] + assert update_arg["status"] == "closed" + assert update_arg["auto_closed"] is True + assert "closed_at" in update_arg + mock_table.update.return_value.eq.assert_any_call("id", "ticket-123") + mock_table.update.return_value.eq.return_value.eq.assert_any_call("company_id", "company-123")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/tests/test_auto_close.py` around lines 64 - 76, Update test_close_ticket_success to assert the supabase update contract: after calling self.service._close_ticket("ticket-123", "company-123", stats) assert that self.mock_supabase.table(...) was used (mock_table), that mock_table.update was called with the expected payload (the dict your _close_ticket constructs to mark a ticket closed, e.g. status/closed_at keys), and that the chained filter calls were invoked with the correct identifiers by asserting mock_table.update.return_value.eq was called with ("id", "ticket-123") and ("company_id", "company-123") (and that execute was called); keep the existing assertions for returned True and counters.backend/tests/test_duplicate_service.py (1)
59-65: ⚡ Quick winMake threshold assertions resilient to default-threshold changes.
The test intent is override behavior, not a specific global default value; deriving values from
SIMILARITY_THRESHOLDkeeps this stable if defaults are tuned.Proposed refactor
- mock_util.cos_sim.return_value.item.return_value = 0.75 + score = SIMILARITY_THRESHOLD + 0.05 + mock_util.cos_sim.return_value.item.return_value = score @@ - # With default threshold (0.70), 0.75 should be a duplicate + # With default threshold, score should be a duplicate result_default = self.service.check_duplicate("new ticket text") assert result_default["is_duplicate"] is True - # With custom threshold (0.80), 0.75 should NOT be a duplicate - result_custom = self.service.check_duplicate("new ticket text", threshold=0.80) + # With stricter custom threshold, score should NOT be a duplicate + result_custom = self.service.check_duplicate( + "new ticket text", + threshold=score + 0.05, + ) assert result_custom["is_duplicate"] is False🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/tests/test_duplicate_service.py` around lines 59 - 65, The test should not hardcode numeric thresholds; import and use the module constant SIMILARITY_THRESHOLD (or settings.SIMILARITY_THRESHOLD) to derive expectations and the override value. Update the assertions around self.service.check_duplicate to compute the expected duplicate result using SIMILARITY_THRESHOLD (e.g., assert that a score just above SIMILARITY_THRESHOLD is duplicate) and call check_duplicate with threshold=SIMILARITY_THRESHOLD + delta (e.g., +0.05) to verify override behavior; reference the check_duplicate method and the SIMILARITY_THRESHOLD constant when making these replacements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/tests/test_duplicate_service.py`:
- Around line 14-17: The test mutates process env at import-time by setting
ALLOW_DEGRADED_STARTUP globally; instead remove that top-level os.environ change
and set the variable only for the test scope (so it is auto-restored) — e.g., in
the test use pytest's monkeypatch.setenv("ALLOW_DEGRADED_STARTUP","1") before
importing or instantiating DuplicateService (or move the import of
DuplicateService and SIMILARITY_THRESHOLD into the test after setting the env)
so the env change does not leak across the test session.
---
Nitpick comments:
In `@backend/tests/test_auto_close.py`:
- Around line 16-21: Remove the module-level os.environ mutations (the lines
setting "SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY", "AUTO_CLOSE_ENABLED",
"AUTO_CLOSE_DAYS") and instead set these variables inside the test using
per-test env patching (e.g., pytest's monkeypatch.setenv or a fixture) so state
is isolated and restored; update the test(s) in test_auto_close.py to call
monkeypatch.setenv("AUTO_CLOSE_DAYS", "7") etc. before exercising the code that
reads the env and ensure no import-time side effects remain.
- Around line 64-76: Update test_close_ticket_success to assert the supabase
update contract: after calling self.service._close_ticket("ticket-123",
"company-123", stats) assert that self.mock_supabase.table(...) was used
(mock_table), that mock_table.update was called with the expected payload (the
dict your _close_ticket constructs to mark a ticket closed, e.g.
status/closed_at keys), and that the chained filter calls were invoked with the
correct identifiers by asserting mock_table.update.return_value.eq was called
with ("id", "ticket-123") and ("company_id", "company-123") (and that execute
was called); keep the existing assertions for returned True and counters.
In `@backend/tests/test_duplicate_service.py`:
- Around line 59-65: The test should not hardcode numeric thresholds; import and
use the module constant SIMILARITY_THRESHOLD (or settings.SIMILARITY_THRESHOLD)
to derive expectations and the override value. Update the assertions around
self.service.check_duplicate to compute the expected duplicate result using
SIMILARITY_THRESHOLD (e.g., assert that a score just above SIMILARITY_THRESHOLD
is duplicate) and call check_duplicate with threshold=SIMILARITY_THRESHOLD +
delta (e.g., +0.05) to verify override behavior; reference the check_duplicate
method and the SIMILARITY_THRESHOLD constant when making these replacements.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 961fa440-f453-4719-859d-a080ae2dd9a6
📒 Files selected for processing (2)
backend/tests/test_auto_close.pybackend/tests/test_duplicate_service.py
| # Set environment variables before importing | ||
| os.environ["ALLOW_DEGRADED_STARTUP"] = "1" | ||
|
|
||
| from backend.services.duplicate_service import DuplicateService, SIMILARITY_THRESHOLD |
There was a problem hiding this comment.
Avoid leaking ALLOW_DEGRADED_STARTUP across the test session.
This mutates process env at import time and never restores it, which can change behavior of later tests that rely on default startup mode.
Proposed fix
import os
import pytest
from unittest.mock import patch, MagicMock
# Set environment variables before importing
+_PREV_ALLOW_DEGRADED = os.environ.get("ALLOW_DEGRADED_STARTUP")
os.environ["ALLOW_DEGRADED_STARTUP"] = "1"
from backend.services.duplicate_service import DuplicateService, SIMILARITY_THRESHOLD
+
+
+def teardown_module():
+ if _PREV_ALLOW_DEGRADED is None:
+ os.environ.pop("ALLOW_DEGRADED_STARTUP", None)
+ else:
+ os.environ["ALLOW_DEGRADED_STARTUP"] = _PREV_ALLOW_DEGRADED🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@backend/tests/test_duplicate_service.py` around lines 14 - 17, The test
mutates process env at import-time by setting ALLOW_DEGRADED_STARTUP globally;
instead remove that top-level os.environ change and set the variable only for
the test scope (so it is auto-restored) — e.g., in the test use pytest's
monkeypatch.setenv("ALLOW_DEGRADED_STARTUP","1") before importing or
instantiating DuplicateService (or move the import of DuplicateService and
SIMILARITY_THRESHOLD into the test after setting the env) so the env change does
not leak across the test session.
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 29368972 | Triggered | Supabase Service Role JWT | b460068 | scratch/test_companies.js | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
|
Hi @unsiqasik! Thanks for the contribution. I have successfully converted your PR's target branch to PR approved and merged! Welcome to the family! 🚀💻 🌟 Developer Action NetworkBefore starting or submitting updates, please complete these quick onboarding steps:
Note: All PR branches must target the |
Summary
Adds comprehensive unit tests for two backend services:
DuplicateService (Issue #297)
AutoCloseService (Issue #279)
Testing
Closes #297, Closes #279
Summary by CodeRabbit