-
-
Notifications
You must be signed in to change notification settings - Fork 81
fix(research): classify by longest matching pattern, not map order #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4f0a835
4906753
adb5936
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,11 +76,16 @@ def test_no_match_returns_excluded(self): | |
| "excluded", | ||
| ) | ||
|
|
||
| def test_first_match_wins(self): | ||
| # Both "facebook" and "twitter" present — first pattern in iteration wins | ||
| def test_longest_pattern_wins(self): | ||
| # Both "facebook" (8) and "twitter" (7) present — the longer pattern wins | ||
| result = classify_title("Facebook Twitter integration - Chrome", self.CATEGORY_MAP) | ||
| self.assertEqual(result, "Facebook") | ||
|
|
||
| def test_equal_length_patterns_resolve_to_map_order(self): | ||
| # "gmail" and "inbox" are both 5 chars — the earlier map entry wins | ||
| category_map = {"gmail": "Email", "inbox": "Other"} | ||
| self.assertEqual(classify_title("gmail inbox", category_map), "Email") | ||
|
|
||
| def test_empty_title(self): | ||
| self.assertEqual(classify_title("", self.CATEGORY_MAP), "excluded") | ||
|
|
||
|
|
@@ -341,6 +346,54 @@ def test_input_not_mutated_with_app_map(self): | |
| transform(window, self.CATEGORY_MAP, self.APP_CATEGORY_MAP) | ||
| self.assertEqual(window, original) | ||
|
|
||
| class TestSpecificHostBeatsGenericHost(unittest.TestCase): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new longest-match regression tests are not run by Knowledge Base Used: Quality automation
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 4906753. Added |
||
| """Regression: a generic host must not shadow a more specific one. | ||
|
|
||
| Study maps list ``google.com`` well before ``docs.google.com``. Under | ||
| first-match-wins every Google Workspace URL was filed as *Search & | ||
| Navigation* instead of *Work & Productivity* — reported from the | ||
| Research Edition b4 field test. | ||
| """ | ||
|
|
||
| CATEGORY_MAP = { | ||
| "google.com": "Search & Navigation", | ||
| "docs.google.com": "Work & Productivity", | ||
| "drive.google.com": "Work & Productivity", | ||
| "calendar.google.com": "Work & Productivity", | ||
| "meet.google.com": "Work & Productivity", | ||
| } | ||
|
|
||
| def test_workspace_urls_are_work_not_search(self): | ||
| for url in ( | ||
| "https://docs.google.com/document/d/abc/edit", | ||
| "https://drive.google.com/drive/my-drive", | ||
| "https://calendar.google.com/calendar/u/0/r", | ||
| "https://meet.google.com/xyz-abcd-efg", | ||
| ): | ||
| with self.subTest(url=url): | ||
| self.assertEqual( | ||
| classify_title("", self.CATEGORY_MAP, url=url), | ||
| "Work & Productivity", | ||
| ) | ||
|
|
||
| def test_plain_google_search_still_matches_generic(self): | ||
| self.assertEqual( | ||
| classify_title("", self.CATEGORY_MAP, url="https://www.google.com/search?q=aw"), | ||
| "Search & Navigation", | ||
| ) | ||
|
|
||
| def test_specific_host_also_wins_on_title_fallback(self): | ||
| self.assertEqual( | ||
| classify_title("docs.google.com - Untitled", self.CATEGORY_MAP), | ||
| "Work & Productivity", | ||
| ) | ||
|
|
||
| def test_empty_pattern_is_ignored(self): | ||
| # An empty map key matches everything under `in`; it must not swallow input. | ||
| category_map = {"": "Bogus", "youtube": "Youtube"} | ||
| self.assertEqual(classify_title("youtube - Chrome", category_map), "Youtube") | ||
| self.assertEqual(classify_title("unrelated", category_map), "excluded") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a category map contains overlapping non-ASCII patterns, Python ranks lowercased code points while Swift ranks original extended grapheme clusters and uses different case-folding semantics, producing different research categories for the same activity across platforms.
Knowledge Base Used:
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4906753. replaces in so Swift matches Python's code-point length semantics. For the study maps in use today (ASCII domain names) there is no behavioural difference, but the fix prevents divergence when non-ASCII patterns are added.