feat: v3.0.0 - intelligent search, GitHub person/project mode, ELI5, 13+ sources
v3 rewrites the search engine from the ground up: - Intelligent pre-research: resolves X handles, GitHub repos, subreddits, TikTok hashtags, and YouTube channels before searching - GitHub person-mode: PR velocity, top repos by stars, release notes - GitHub project-mode: live star counts, README, releases, top issues - ELI5 mode: plain language synthesis, no jargon - 13+ sources: Reddit, X, YouTube, TikTok, Instagram, HN, Polymarket, GitHub, Threads, Pinterest, Perplexity, Bluesky, Web - Free Reddit comments via public JSON (no API key needed) - Fun judge v2: humor scoring baked into narrative - Cookie consent before browser scanning - 10,000 free ScrapeCreators calls - 1,012 tests Thank you to the community contributors whose issues and PRs shaped v3: @uppinote20 (#143), @zerone0x (#134, #136), @thinkun (#116), @thomasmktong (#124), @fanispoulinakisai-boop (#100), @pejmanjohn (#78), @zl190 (#115), @hnshah (#84, #85, #86) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+44
-94
@@ -1,15 +1,16 @@
|
||||
"""Tests for browser cookie extraction integration in env.py."""
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from scripts.lib.env import extract_browser_credentials, COOKIE_DOMAINS
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
||||
|
||||
from lib.env import extract_browser_credentials, COOKIE_DOMAINS
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _base_config(**overrides):
|
||||
"""Return a minimal config dict with common defaults."""
|
||||
@@ -24,155 +25,105 @@ def _base_config(**overrides):
|
||||
return cfg
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class TestExtractBrowserCredentials:
|
||||
"""Unit tests for extract_browser_credentials()."""
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
def test_auto_with_setup_complete_populates_credentials(self, mock_extract):
|
||||
"""FROM_BROWSER=auto, SETUP_COMPLETE=true, mock returns valid cookies
|
||||
-> config now contains AUTH_TOKEN and CT0."""
|
||||
mock_extract.return_value = ({"auth_token": "tok123", "ct0": "ct0val"}, "chrome")
|
||||
|
||||
config = _base_config(FROM_BROWSER="auto", SETUP_COMPLETE="true")
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_auto_populates_credentials(self, mock_extract):
|
||||
mock_extract.return_value = {"auth_token": "tok123", "ct0": "ct0val"}
|
||||
config = _base_config(FROM_BROWSER="auto")
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
assert result["AUTH_TOKEN"] == "tok123"
|
||||
assert result["CT0"] == "ct0val"
|
||||
# Should have been called for x domain
|
||||
mock_extract.assert_any_call("auto", ".x.com", ["auth_token", "ct0"])
|
||||
# auto mode tries firefox first, then safari, then chrome
|
||||
mock_extract.assert_any_call("firefox", ".x.com", ["auth_token", "ct0"])
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_explicit_auth_token_skips_x_extraction(self, mock_extract):
|
||||
"""Config already has AUTH_TOKEN and CT0 from env var
|
||||
-> cookie extraction skipped for X (explicit takes priority)."""
|
||||
# Return None for any non-X domains that still get checked (e.g. Truth Social)
|
||||
mock_extract.return_value = None
|
||||
config = _base_config(
|
||||
AUTH_TOKEN="explicit_token",
|
||||
CT0="explicit_ct0",
|
||||
AUTH_TOKEN="explicit_token", CT0="explicit_ct0",
|
||||
FROM_BROWSER="auto",
|
||||
SETUP_COMPLETE="true",
|
||||
)
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
# X cookies should not appear in result (already set)
|
||||
assert "AUTH_TOKEN" not in result
|
||||
assert "CT0" not in result
|
||||
# extract_cookies should NOT have been called for .x.com
|
||||
for call in mock_extract.call_args_list:
|
||||
assert call[0][1] != ".x.com", "Should not extract cookies for X when credentials already set"
|
||||
assert call[0][1] != ".x.com"
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_from_browser_off_skips_all(self, mock_extract):
|
||||
"""FROM_BROWSER=off -> no cookie extraction attempted."""
|
||||
config = _base_config(FROM_BROWSER="off", SETUP_COMPLETE="true")
|
||||
config = _base_config(FROM_BROWSER="off")
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
assert result == {}
|
||||
mock_extract.assert_not_called()
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
def test_no_setup_complete_no_from_browser_defaults_off(self, mock_extract):
|
||||
"""FROM_BROWSER not set and SETUP_COMPLETE not set
|
||||
-> no extraction (wizard hasn't run)."""
|
||||
config = _base_config() # both None
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_no_from_browser_defaults_to_silent(self, mock_extract):
|
||||
"""Default (no FROM_BROWSER): tries Firefox and Safari only, skips Chrome."""
|
||||
mock_extract.return_value = None
|
||||
config = _base_config()
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
assert result == {}
|
||||
mock_extract.assert_not_called()
|
||||
# Should try firefox and safari but NOT chrome
|
||||
browser_args = [call[0][0] for call in mock_extract.call_args_list]
|
||||
assert "firefox" in browser_args
|
||||
assert "safari" in browser_args
|
||||
assert "chrome" not in browser_args
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
def test_setup_complete_no_from_browser_defaults_auto(self, mock_extract):
|
||||
"""SETUP_COMPLETE is set but FROM_BROWSER is not
|
||||
-> defaults to 'auto'."""
|
||||
mock_extract.return_value = ({"auth_token": "found", "ct0": "found_ct0"}, "firefox")
|
||||
|
||||
config = _base_config(SETUP_COMPLETE="true") # FROM_BROWSER=None
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
assert result["AUTH_TOKEN"] == "found"
|
||||
# extract_cookies should have been called with 'auto'
|
||||
mock_extract.assert_any_call("auto", ".x.com", ["auth_token", "ct0"])
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_from_browser_firefox_only(self, mock_extract):
|
||||
"""FROM_BROWSER=firefox -> only Firefox extraction attempted."""
|
||||
mock_extract.return_value = ({"auth_token": "ff_tok", "ct0": "ff_ct0"}, "firefox")
|
||||
|
||||
config = _base_config(FROM_BROWSER="firefox", SETUP_COMPLETE="true")
|
||||
mock_extract.return_value = {"auth_token": "ff_tok", "ct0": "ff_ct0"}
|
||||
config = _base_config(FROM_BROWSER="firefox")
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
assert result["AUTH_TOKEN"] == "ff_tok"
|
||||
# All calls should use 'firefox' as the browser arg
|
||||
for call in mock_extract.call_args_list:
|
||||
assert call[0][0] == "firefox"
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_extraction_returns_none_config_unchanged(self, mock_extract):
|
||||
"""Cookie extraction returns None for X -> config unchanged for AUTH_TOKEN."""
|
||||
mock_extract.return_value = None
|
||||
|
||||
config = _base_config(FROM_BROWSER="auto", SETUP_COMPLETE="true")
|
||||
config = _base_config(FROM_BROWSER="auto")
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
assert "AUTH_TOKEN" not in result
|
||||
assert "CT0" not in result
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
def test_extraction_raises_exception_config_unchanged(self, mock_extract):
|
||||
"""Cookie extraction raises exception -> caught, config unchanged."""
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_extraction_raises_exception_caught(self, mock_extract):
|
||||
mock_extract.side_effect = RuntimeError("database locked")
|
||||
|
||||
config = _base_config(FROM_BROWSER="auto", SETUP_COMPLETE="true")
|
||||
config = _base_config(FROM_BROWSER="auto")
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
# Should not raise, and no credentials populated
|
||||
assert "AUTH_TOKEN" not in result
|
||||
assert "CT0" not in result
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
def test_partial_credentials_only_fills_missing(self, mock_extract):
|
||||
"""If AUTH_TOKEN is set but CT0 is not, only CT0 gets filled."""
|
||||
mock_extract.return_value = ({"auth_token": "cookie_tok", "ct0": "cookie_ct0"}, "chrome")
|
||||
|
||||
mock_extract.return_value = {"auth_token": "cookie_tok", "ct0": "cookie_ct0"}
|
||||
config = _base_config(
|
||||
AUTH_TOKEN="explicit",
|
||||
CT0=None,
|
||||
AUTH_TOKEN="explicit", CT0=None,
|
||||
FROM_BROWSER="auto",
|
||||
SETUP_COMPLETE="true",
|
||||
)
|
||||
result = extract_browser_credentials(config)
|
||||
|
||||
# AUTH_TOKEN already set, should not be overridden
|
||||
assert "AUTH_TOKEN" not in result
|
||||
# CT0 was missing, should be filled
|
||||
assert result["CT0"] == "cookie_ct0"
|
||||
|
||||
|
||||
class TestGetConfigCookieIntegration:
|
||||
"""Integration test: get_config() calls extract_browser_credentials."""
|
||||
|
||||
@patch("scripts.lib.cookie_extract.extract_cookies_with_source")
|
||||
@patch("scripts.lib.env._find_project_env", return_value=None)
|
||||
@patch("scripts.lib.env.load_env_file", return_value={})
|
||||
@patch("scripts.lib.env.get_openai_auth")
|
||||
@patch("lib.cookie_extract.extract_cookies")
|
||||
@patch("lib.env._find_project_env", return_value=None)
|
||||
@patch("lib.env.load_env_file", return_value={})
|
||||
@patch("lib.env.get_openai_auth")
|
||||
def test_get_config_injects_cookies(
|
||||
self, mock_openai, mock_load, mock_proj, mock_extract
|
||||
):
|
||||
"""get_config merges browser cookies into the returned config."""
|
||||
from scripts.lib.env import get_config, OpenAIAuth
|
||||
|
||||
from lib.env import get_config, OpenAIAuth
|
||||
mock_openai.return_value = OpenAIAuth(
|
||||
token=None, source="none", status="missing",
|
||||
account_id=None, codex_auth_file="/fake",
|
||||
)
|
||||
mock_extract.return_value = ({"auth_token": "browser_tok", "ct0": "browser_ct0"}, "firefox")
|
||||
|
||||
import os
|
||||
mock_extract.return_value = {"auth_token": "browser_tok", "ct0": "browser_ct0"}
|
||||
env_patch = {
|
||||
"SETUP_COMPLETE": "true",
|
||||
"FROM_BROWSER": "auto",
|
||||
@@ -180,6 +131,5 @@ class TestGetConfigCookieIntegration:
|
||||
}
|
||||
with patch.dict(os.environ, env_patch, clear=False):
|
||||
config = get_config()
|
||||
|
||||
assert config["AUTH_TOKEN"] == "browser_tok"
|
||||
assert config["CT0"] == "browser_ct0"
|
||||
|
||||
Reference in New Issue
Block a user