
    (i<                        d Z ddlZddlmc mZ ddlmZ ddlm	Z	m
Z
 ddlmZ ddlmZ ddlmZ ddlmZ d	d
ddddddddddddddddgddZdddddd d!d"dgddZg ddZdZd#ed$ed%dfd&Z G d' d(          Z	 	 	 	 	 dTd.ed/ed0ed1ed2ed%e	fd3Zd4ee	         d%e	fd5Z G d6 d7          Zdd8d9d:d;d<d=g d>d?d@dAdBdCdDidEdFdGdHdIdJdKgddLd,dMdCdNidEgdOZdd8g dOZ dPZ!d#ed$ed%dfdQZ" G dR dS          Z#dS )Uz4Tests for HackerNews, Reddit, and GitHub collectors.    N)datetime)	MagicMockpatch)	HTTPXMock)GitHubCollector)HackerNewsCollector)RedditCollector12345<Show HN: I built a Claude Code workflow for local DB querieshttps://example.com/claude-dbhnuser1-   z2026-02-26T10:00:00.000ZzAI connected Claude Code directly to my local Postgres instance...   )objectIDtitleurlauthorpoints
created_at
story_textnum_comments12346zLow points postzhttps://example.com/lowhnuser2   z2026-02-26T09:00:00.000ZzNot much here.      )hitsnbHits99999z Ask HN: Best LLM workflow tools?asker2   z2026-02-26T08:00:00.000Zz%I want to automate my dev workflow...   
httpx_mockfirst_responsereturnc                     |                      |           t          t          dz
            D ]}|                      t                     dS )z=Add first_response for the first keyword, empty for the rest.jsonr   N)add_responserange_HN_KEYWORD_COUNTHN_EMPTYr#   r$   _s      </root/projects/ai_usecases_explorer/tests/test_collectors.py_mock_hnr0   >   sZ    000$q()) / /X..../ /    c                   ~    e Zd ZdeddfdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	deddfd
Z
dS )TestHackerNewsCollectorr#   r%   Nc                    t          |t                     t          d          }|                                }t	          |t
                    }|sddt          j                    v st          j	        t                    rt          j
        t                    nddt          j                    v st          j	        |          rt          j
        |          nddt          j                    v st          j	        t
                    rt          j
        t
                    ndt          j
        |          dz  }t          t          j        |                    d }d S )N
   
min_points5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceitemslistpy0py1py2py4)r0   HN_RESPONSEr   fetchr9   r;   @py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationselfr#   	collectorr:   @py_assert3@py_format5s         r/   $test_fetch_returns_list_of_raw_itemsz<TestHackerNewsCollector.test_fetch_returns_list_of_raw_itemsF   s:   [)))'2666	!!%&&&&&&&&&&&&&&&z&&&&&z&&&&&&&&&&&&&%&&&&&%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&r1   c                    t          |t                     t          d          }|                                }t	          |          }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        t                    rt          j
        t                    nddt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }t          t          j        |                    d x}x}}|d         }	|	j        }d}||k    }|st          j        d|fd||f          t          j
        |	          t          j
        |          t          j
        |          dz  }d	d
|iz  }t          t          j        |                    d x}	x}x}}d S )Nr5   r6   r   ==z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr:   r=   r>   py3py6assert %(py8)spy8r   r   z.%(py3)s
{%(py3)s = %(py1)s.author
} == %(py6)sr>   rV   rW   )r0   rA   r   rB   rT   rE   _call_reprcomparerC   rD   rF   rG   rH   rI   r   
rK   r#   rL   r:   @py_assert2@py_assert5@py_assert4@py_format7@py_format9@py_assert0s
             r/   test_filters_by_min_pointsz2TestHackerNewsCollector.test_filters_by_min_pointsL   s   [)))'2666	!!5zzQzQzQss55zQQx+x+)+)++++++++++)+++++x++++++++)+++++++++++++++++++++++++++++++r1   c                 	   t          |t                     t          d          }|                                }|d         }|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }	t          t          j        |	                    d x}x}}|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }	t          t          j        |	                    d x}x}}|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }	t          t          j        |	                    d x}x}}|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }	t          t          j        |	                    d x}x}}|j        }
t#          |
t$                    }|sddt          j                    v st          j	        t"                    rt          j
        t"                    nddt          j                    v st          j	        |          rt          j
        |          ndt          j
        |
          dt          j                    v st          j	        t$                    rt          j
        t$                    ndt          j
        |          dz  }t          t          j        |                    d x}
}d S )Nr5   r6   r   r   rQ   z-%(py2)s
{%(py2)s = %(py0)s.title
} == %(py5)sitemr=   r?   py5assert %(py7)spy7r   z2%(py2)s
{%(py2)s = %(py0)s.source_url
} == %(py5)sr   z.%(py2)s
{%(py2)s = %(py0)s.author
} == %(py5)s
hackernewsz7%(py2)s
{%(py2)s = %(py0)s.source_platform
} == %(py5)sWassert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.published_at
}, %(py4)s)
}r9   r   r=   r>   rV   r@   rW   )r0   rA   r   rB   r   rE   r\   rC   rD   rF   rG   rH   rI   
source_urlr   source_platformpublished_atr9   r   rK   r#   rL   r:   rg   @py_assert1r`   rM   @py_format6@py_format8r^   r_   ra   s                r/   test_item_has_required_fieldsz5TestHackerNewsCollector.test_item_has_required_fieldsS   s   [)))'2666	!!Qxz[[[z[[[[[[[[[[[z[[[[[[[[[[[[[t[[[[[t[[[[[[z[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[A"AA"AAAAAAAAAAA"AAAAAAAAAAAAAtAAAAAtAAAAAAAAAA"AAAAAAAAAAAAAAAAAAAAAAAAAAAA{'i'{i''''''''''{i''''''''''''t'''''t''''''{''''i'''''''''''''''''''''''''''#3|3#|3333333333#|333333333333t33333t333333#3333|333333333333333333333333333+6z+X666666666666666z66666z6666666666666$66666$666666+66666666666X66666X6666666666666666666666666666r1   c                    t          |t                     t          d          }|                                }t	          |          }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        t                    rt          j
        t                    nddt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }t          t          j        |                    d x}x}}d}	|d         }
|
j        }|	|v }|st          j        d|fd|	|f          t          j
        |	          t          j
        |
          t          j
        |          dz  }d	d
|iz  }t          t          j        |                    d x}	x}x}
}d S )Nr5   r6   r   rQ   rS   rT   r:   rU   rX   rY   znews.ycombinator.comr   inz2%(py1)s in %(py6)s
{%(py6)s = %(py4)s.source_url
}r>   r@   rW   )r0   HN_RESPONSE_NO_URLr   rB   rT   rE   r\   rC   rD   rF   rG   rH   rI   rr   )rK   r#   rL   r:   r^   r_   r`   ra   rb   rc   rM   s              r/   test_fallback_url_for_ask_hnz4TestHackerNewsCollector.test_fallback_url_for_ask_hn^   s   /000'2666	!!5zzQzQzQss55zQ%<q<)<<%)<<<<<<<<<<<%)<<<<<<%<<<<<<<<)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<r1   c                    t          t                    D ]}|                    t                     t	          d          }|                                }g }||k    }|st          j        d|fd||f          dt          j	                    v st          j
        |          rt          j        |          ndt          j        |          dz  }dd	|iz  }t          t          j        |                    d x}}d S )
Nr'   r5   r6   rQ   z%(py0)s == %(py3)sr:   r=   rV   assert %(py5)sri   )r*   r+   r)   r,   r   rB   rE   r\   rC   rD   rF   rG   rH   rI   	rK   r#   r.   rL   r:   r^   rv   @py_format4rw   s	            r/   &test_empty_response_returns_empty_listz>TestHackerNewsCollector.test_empty_response_returns_empty_liste   s   ()) 	3 	3A###2222'2666	!!u{uuur1   c                    t          |t                     t          d          }|                                }d}|d         }|j        }||v }|st          j        d|fd||f          t          j        |          t          j        |          t          j        |          dz  }dd	|iz  }	t          t          j	        |	                    d x}x}x}}d
}|d         }|j        }||v }|st          j        d|fd||f          t          j        |          t          j        |          t          j        |          dz  }dd	|iz  }	t          t          j	        |	                    d x}x}x}}d S )Nr5   r6   zShow HNr   r{   z3%(py1)s in %(py6)s
{%(py6)s = %(py4)s.raw_content
}r~   rX   rY   Postgres)
r0   rA   r   rB   raw_contentrE   r\   rG   rH   rI   
rK   r#   rL   r:   rc   rM   r_   r^   ra   rb   s
             r/   (test_raw_content_includes_title_and_textz@TestHackerNewsCollector.test_raw_content_includes_title_and_textl   s   [)))'2666	!!0E!H0H00y00000000000y000000y0000H00000000000000000000000000000000001U1X1X11z11111111111z111111z1111X111111111111111111111111111111111111r1   c                    t          t                    D ]}|                    t                     t	          d          }|                                }d |D             }t          |          }t          |          }t          |          }||k    }	|	st          j	        d|	fd||f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |          dt          j                    v st          j        t                    rt          j        t                    ndd	t          j                    v st          j        t                    rt          j        t                    nd	dt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          d
z  }
dd|
iz  }t          t          j        |                    d x}x}	x}}d S )Nr'   r5   r6   c                     g | ]	}|j         
S  rr   .0is     r/   
<listcomp>zLTestHackerNewsCollector.test_deduplicates_across_queries.<locals>.<listcomp>y   s    +++q|+++r1   rQ   zn%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py11)s
{%(py11)s = %(py5)s(%(py9)s
{%(py9)s = %(py6)s(%(py7)s)
})
}rT   idssetr=   r>   rV   ri   rW   rk   py9py11assert %(py13)spy13)r*   r+   r)   rA   r   rB   rT   r   rE   r\   rC   rD   rF   rG   rH   rI   )rK   r#   r.   rL   r:   r   r^   @py_assert8@py_assert10r`   @py_format12@py_format14s               r/    test_deduplicates_across_queriesz8TestHackerNewsCollector.test_deduplicates_across_queriess   sZ   ()) 	6 	6A###5555'2666	!!++U+++3xx(s3xx(3x==(x=((((((((((x=((((((((((((s(((((s(((((((((((((3(((((3((((((x(((((((((((3(((((3(((((((((((((s(((((s(((((((((((((3(((((3((((((x((((=(((((((((((((((((((((((((((((((r1   )__name__
__module____qualname__r   rO   rd   ry   r   r   r   r   r   r1   r/   r3   r3   E   s       'y 'T ' ' ' ',Y ,4 , , , ,	7	 	7d 	7 	7 	7 	7=y =T = = = = t    29 2QU 2 2 2 2)9 ) ) ) ) ) ) )r1   r3   6https://reddit.com/r/ClaudeCode/comments/abc123/title/,How I automated my daily reports with Claude:I built a Python script that calls Claude every morning...2026-02-26T10:00:00Z	redditor1r   r   textpublished_dater   c                 h    t                      }| |_        ||_        ||_        ||_        ||_        |S N)r   r   r   r   r   r   )r   r   r   r   r   results         r/   _make_exa_resultr      s6     [[FFJFLFK*FFMMr1   resultsc                 0    t                      }| |_        |S r   )r   r   )r   responses     r/   _make_exa_responser      s    {{HHOr1   c                   ^    e Zd ZddZddZddZddZddZddZdd	Z	dd
Z
ddZddZdS )TestRedditCollectorr%   Nc                    t          dgd          }|                                }g }||k    }|st          j        d|fd||f          dt	          j                    v st          j        |          rt          j        |          ndt          j        |          dz  }dd	|iz  }t          t          j	        |                    d x}}d S )
N
ClaudeCode 
subredditsapi_keyrQ   r   r:   r   r   ri   )
r	   rB   rE   r\   rC   rD   rF   rG   rH   rI   )rK   rL   r:   r^   rv   r   rw   s          r/   "test_returns_empty_when_no_api_keyz6TestRedditCollector.test_returns_empty_when_no_api_key   s    #~rJJJ	!!u{uuur1   c                    t          t                      g          }t                      }||j        _        t          d|          5  t          dgd          }|                                }d d d            n# 1 swxY w Y   t          |          }d}||k    }|st          j
        d|fd||f          d	t          j                    v st          j        t                    rt          j        t                    nd	d
t          j                    v st          j        |          rt          j        |          nd
t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}|d         }
|
j        }d}||k    }|st          j
        d|fd||f          t          j        |
          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}
x}x}}|d         }
|
j        }d}||k    }|st          j
        d|fd||f          t          j        |
          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}
x}x}}d}
|d         }|j        }|
|v }|st          j
        d|fd|
|f          t          j        |
          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}
x}x}}d S )N*ai_usecases_explorer.collectors.reddit.Exareturn_valuer   test-keyr   r   rQ   rS   rT   r:   rU   rX   rY   r   r   )z-%(py3)s
{%(py3)s = %(py1)s.title
} == %(py6)sr[   reddit)z7%(py3)s
{%(py3)s = %(py1)s.source_platform
} == %(py6)s
reddit.comr{   r}   r~   )r   r   r   search_and_contentsr   r   r	   rB   rT   rE   r\   rC   rD   rF   rG   rH   rI   r   rs   rr   )rK   mock_responsemock_exarL   r:   r^   r_   r`   ra   rb   rc   rM   s               r/   test_fetches_and_returns_itemsz2TestRedditCollector.test_fetches_and_returns_items   s'   *,<,>,>+?@@;;4A$1?hWWW 	& 	&'L>:VVVIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 5zzQzQzQss55zQQxOx~O!OO~!OOOOOOOOOOO~!OOOOOOxOOOO~OOOO!OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOQx3x'383'83333333333'833333x3333'33338333333333333333333333333333332uQx2x22|22222222222|222222|2222x222222222222222222222222222222222222   'A;;A?A?c                 "   t          t                      g          }t                      }||j        _        t          d|          5  t          dgd          }|                                }d d d            n# 1 swxY w Y   |d         }|j        }d}||k    }|st          j
        d|fd	||f          d
t          j                    v st          j        |          rt          j        |          nd
t          j        |          t          j        |          dz  }	dd|	iz  }
t          t          j        |
                    d x}x}}|j        }d}||k    }|st          j
        d|fd||f          d
t          j                    v st          j        |          rt          j        |          nd
t          j        |          t          j        |          dz  }	dd|	iz  }
t          t          j        |
                    d x}x}}|j        }d}||k    }|st          j
        d|fd||f          d
t          j                    v st          j        |          rt          j        |          nd
t          j        |          t          j        |          dz  }	dd|	iz  }
t          t          j        |
                    d x}x}}|j        }t)          |t*                    }|sddt          j                    v st          j        t(                    rt          j        t(                    ndd
t          j                    v st          j        |          rt          j        |          nd
t          j        |          dt          j                    v st          j        t*                    rt          j        t*                    ndt          j        |          dz  }t          t          j        |                    d x}}d S )Nr   r   r   r   r   r   r   rQ   rf   rg   rh   rj   rk   r   ro   r   rm   rp   r9   r   rq   )r   r   r   r   r   r   r	   rB   r   rE   r\   rC   rD   rF   rG   rH   rI   rs   r   rt   r9   r   )rK   r   r   rL   r:   rg   rv   r`   rM   rw   rx   r^   r_   ra   s                 r/   ry   z1TestRedditCollector.test_item_has_required_fields   s   *,<,>,>+?@@;;4A$1?hWWW 	& 	&'L>:VVVIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& QxzKKKzKKKKKKKKKKKzKKKKKKKKKKKKKtKKKKKtKKKKKKzKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK#/x/#x//////////#x////////////t/////t//////#////x///////////////////////////{)k){k)))))))))){k))))))))))))t)))))t)))))){))))k)))))))))))))))))))))))))))+6z+X666666666666666z66666z6666666666666$66666$666666+66666666666X66666X6666666666666666666666666666r   c                 L   t                      }t                      }t          ||g          |j        _        t          d|          5  t          dgd          }|                                }d d d            n# 1 swxY w Y   d |D             }t          |          }t          |          }t          |          }||k    }	|	st          j        d|	fd||f          d	t          j                    v st          j        t                    rt          j        t                    nd	d
t          j                    v st          j        |          rt          j        |          nd
t          j        |          d	t          j                    v st          j        t                    rt          j        t                    nd	dt          j                    v st          j        t                    rt          j        t                    ndd
t          j                    v st          j        |          rt          j        |          nd
t          j        |          t          j        |          dz  }
dd|
iz  }t!          t          j        |                    d x}x}	x}}d S )Nr   r   r   r   r   c                     g | ]	}|j         
S r   r   r   s     r/   r   zJTestRedditCollector.test_deduplicates_within_subreddit.<locals>.<listcomp>       ,,,,,,r1   rQ   r   rT   urlsr   r   r   r   )r   r   r   r   r   r   r	   rB   rT   r   rE   r\   rC   rD   rF   rG   rH   rI   )rK   same_resultr   rL   r:   r   r^   r   r   r`   r   r   s               r/   "test_deduplicates_within_subredditz6TestRedditCollector.test_deduplicates_within_subreddit   s   &((;;4FU`Ga4b4b$1?hWWW 	& 	&'L>:VVVIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& -,e,,,4yy*D		*C	NN*yN**********yN************s*****s*************4*****4******y***********C*****C*******************************D*****D******	****N*******************************s   	'A<<B B c                 x   t          d          }t          d          }t                      }t          |g          t          |g          g|j        _        t          d|          5  t          ddgd	          }|                                }d d d            n# 1 swxY w Y   t          |          }d
}||k    }|st          j
        d|fd||f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }	dd|	iz  }
t          t          j        |
                    d x}x}}d S )Nz-https://reddit.com/r/vibecoding/comments/aaa/r   z.https://reddit.com/r/singularity/comments/bbb/r   r   
vibecodingsingularityr   r   r   rQ   rS   rT   r:   rU   rX   rY   )r   r   r   r   side_effectr   r	   rB   rT   rE   r\   rC   rD   rF   rG   rH   rI   )rK   result_aresult_br   rL   r:   r^   r_   r`   ra   rb   s              r/   *test_multiple_subreddits_aggregate_resultsz>TestRedditCollector.test_multiple_subreddits_aggregate_results   s   #(WXXX#(XYYY;;z**z**4
$0
 ?hWWW 	& 	&'L-3PZdeeeIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 5zzQzQzQss55zQs   *(BB"%B"c                 6   t          d          }t                      }t          |g          |j        _        t          d|          5  t          dgd          }|                                }d d d            n# 1 swxY w Y   t          |          }d}||k    }|st          j
        d	|fd
||f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d S )Nz-https://reddit.com/r/LocalLLaMA/comments/xyz/r   r   r   r   r   r   r   rQ   rS   rT   r:   rU   rX   rY   )r   r   r   r   r   r   r	   rB   rT   rE   r\   rC   rD   rF   rG   rH   rI   )
rK   other_sub_resultr   rL   r:   r^   r_   r`   ra   rb   s
             r/   .test_accepts_results_from_any_reddit_subredditzBTestRedditCollector.test_accepts_results_from_any_reddit_subreddit   s    ,0_```;;4FHXGY4Z4Z$1?hWWW 	& 	&'L>:VVVIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 5zzQzQzQss55zQs   
'A==BBc                 <   t                      }t          g           |j        _        t	          d|          5  t          dgd          }|                                }d d d            n# 1 swxY w Y   g }||k    }|st          j        d|fd||f          dt          j
                    v st          j        |          rt          j        |          ndt          j        |          d	z  }d
d|iz  }t          t          j        |                    d x}}d S )Nr   r   r   r   r   rQ   r   r:   r   r   ri   )r   r   r   r   r   r	   rB   rE   r\   rC   rD   rF   rG   rH   rI   rK   r   rL   r:   r^   rv   r   rw   s           r/   %test_empty_results_returns_empty_listz9TestRedditCollector.test_empty_results_returns_empty_list   ss   ;;4Fr4J4J$1?hWWW 	& 	&'L>:VVVIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& u{uuu   'A,,A03A0c                 <   t                      }t          d          |j        _        t	          d|          5  t          dgd          }|                                }d d d            n# 1 swxY w Y   g }||k    }|st          j        d|fd||f          d	t          j
                    v st          j        |          rt          j        |          nd	t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}}d S )Nznetwork errorr   r   r   r   r   rQ   r   r:   r   r   ri   )r   RuntimeErrorr   r   r   r	   rB   rE   r\   rC   rD   rF   rG   rH   rI   r   s           r/   !test_gracefully_handles_exa_errorz5TestRedditCollector.test_gracefully_handles_exa_error   ss   ;;3?3P3P$0?hWWW 	& 	&'L>:VVVIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& u{uuur   c                    t          t                      g          }t                      }||j        _        t          d|          5  t          dgd          }|                                }d d d            n# 1 swxY w Y   d}|d         }|j        }||v }|st          j
        d|fd	||f          t          j        |          t          j        |          t          j        |          d
z  }	dd|	iz  }
t          t          j        |
                    d x}x}x}}d}|d         }|j        }||v }|st          j
        d|fd	||f          t          j        |          t          j        |          t          j        |          d
z  }	dd|	iz  }
t          t          j        |
                    d x}x}x}}d S )Nr   r   r   r   r   	automatedr   r{   r   r~   rX   rY   Python)r   r   r   r   r   r   r	   rB   r   rE   r\   rG   rH   rI   )rK   r   r   rL   r:   rc   rM   r_   r^   ra   rb   s              r/   r   z<TestRedditCollector.test_raw_content_includes_title_and_text   sI   *,<,>,>+?@@;;4A$1?hWWW 	& 	&'L>:VVVIOO%%E	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 2eAh2h22{22222222222{222222{2222h2222222222222222222222222222222222/58/8//x///////////x//////x////8////////////////////////////////////r   c                    t                      }t          g           |j        _        t	          d|          5  t          dgd          }|                                 d d d            n# 1 swxY w Y   |j        j        }|j        d         }dg}||k    }|slt          j
        d|fd	||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}x}}d}|j        }	||	v}|st          j
        d|fd||	f          t          j        |          dt          j                    v st          j        |          rt          j        |          ndt          j        |	          dz  }
dd|
iz  }t          t          j        |                    d x}x}}	|j        d         }d}||u }|slt          j
        d|fd||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j        |                    d x}x}}d S )Nr   r   r   r   r   include_domainsr   rQ   )z%(py1)s == %(py4)s)r>   r@   zassert %(py6)srW   start_published_date)not in)z2%(py1)s not in %(py5)s
{%(py5)s = %(py3)s.kwargs
}call_kwargs)r>   rV   ri   rj   rk   r   T)is)z%(py1)s is %(py4)s)r   r   r   r   r   r	   rB   	call_argskwargsrE   r\   rG   rH   rI   rC   rD   rF   )rK   r   rL   r   rc   rM   r^   rN   ra   r`   rw   rx   s               r/    test_passes_reddit_domain_to_exaz4TestRedditCollector.test_passes_reddit_domain_to_exa  s    ;;4Fr4J4J$1?hWWW 	 	'L>:VVVIOO	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 2<!"34FF4FFFFFFFFFF4FFFFF4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF%?[-??%-???????????%-??????%???????????[?????[??????-????????????????????????????!&)1T1)T1111111111)T11111)1111T11111111111111111111111111111r   )r%   N)r   r   r   r   r   ry   r   r   r   r   r   r   r   r   r1   r/   r   r      s           
3 3 3 37 7 7 7+ + + +            
0 
0 
0 
02 2 2 2 2 2r1   r   Fo   zclaude-local-raguser1/claude-local-rag)https://github.com/user1/claude-local-ragz1RAG pipeline connecting Claude to local PDF files)clauderagllmpython*   r   z2026-02-26T12:00:00Zz2026-02-25T08:00:00Zloginuser1)idname	full_namehtml_urldescriptiontopicsstargazers_countlanguage	pushed_atr   owner   zlow-star-repozuser2/low-star-repoz&https://github.com/user2/low-star-repozJust a testr   
JavaScriptz2026-02-26T09:00:00Zuser2)total_countincomplete_resultsr:      c                     |                      |           t          t          dz
            D ]}|                      t                     dS )z1First topic returns real data, rest return empty.r'   r   N)r)   r*   _GITHUB_TOPIC_COUNTGITHUB_EMPTYr-   s      r/   _mock_githubr  >  sZ    000&*++ 3 3\22223 3r1   c                   ~    e Zd ZdeddfdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	deddfd
Z
dS )TestGitHubCollectorr#   r%   Nc                    t          |t                     t          d          }|                                }t	          |t
                    }|sddt          j                    v st          j	        t                    rt          j
        t                    nddt          j                    v st          j	        |          rt          j
        |          nddt          j                    v st          j	        t
                    rt          j
        t
                    ndt          j
        |          dz  }t          t          j        |                    d }d S )Nr5   	min_starsr8   r9   r:   r;   r<   r  GITHUB_SEARCH_RESPONSEr   rB   r9   r;   rC   rD   rE   rF   rG   rH   rI   rJ   s         r/   test_fetch_returns_listz+TestGitHubCollector.test_fetch_returns_listF  s;   Z!7888#b111	!!%&&&&&&&&&&&&&&&z&&&&&z&&&&&&&&&&&&&%&&&&&%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&r1   c                    t          |t                     t          d          }|                                }t	          |          }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        t                    rt          j
        t                    nddt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }t          t          j        |                    d x}x}}|d         }	|	j        }d}||k    }|st          j        d|fd||f          t          j
        |	          t          j
        |          t          j
        |          dz  }d	d
|iz  }t          t          j        |                    d x}	x}x}}d S )Nr5   r  r   rQ   rS   rT   r:   rU   rX   rY   r   r   rZ   r[   )r  r  r   rB   rT   rE   r\   rC   rD   rF   rG   rH   rI   r   r]   s
             r/   test_filters_by_min_starsz-TestGitHubCollector.test_filters_by_min_starsL  s   Z!7888#b111	!!5zzQzQzQss55zQQx)x)')'))))))))))')))))x))))))))')))))))))))))))))))))))))))))))r1   c                    t          |t                     t          d          }|                                }|d         }|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }	t          t          j        |	                    d x}x}}|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }	t          t          j        |	                    d x}x}}|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          t          j
        |          dz  }d	d
|iz  }	t          t          j        |	                    d x}x}}|j        }
t!          |
t"                    }|sddt          j                    v st          j	        t                     rt          j
        t                     nddt          j                    v st          j	        |          rt          j
        |          ndt          j
        |
          dt          j                    v st          j	        t"                    rt          j
        t"                    ndt          j
        |          dz  }t          t          j        |                    d x}
}d S )Nr5   r  r   r   rQ   rf   rg   rh   rj   rk   r   rl   githubro   rp   r9   r   rq   )r  r  r   rB   r   rE   r\   rC   rD   rF   rG   rH   rI   rr   rs   rt   r9   r   ru   s                r/   ry   z1TestGitHubCollector.test_item_has_required_fieldsS  s   Z!7888#b111	!!Qxz555z55555555555z5555555555555t55555t555555z55555555555555555555555555555555M"MM"MMMMMMMMMMM"MMMMMMMMMMMMMtMMMMMtMMMMMMMMMM"MMMMMMMMMMMMMMMMMMMMMMMMMMMM#/x/#x//////////#x////////////t/////t//////#////x///////////////////////////+6z+X666666666666666z66666z6666666666666$66666$666666+66666666666X66666X6666666666666666666666666666r1   c                    t          |t                     t          d          }|                                }d}|d         }|j        }||v }|st          j        d|fd||f          t          j        |          t          j        |          t          j        |          dz  }dd	|iz  }	t          t          j	        |	                    d x}x}x}}d
}|d         }|j        }||v }|st          j        d|fd||f          t          j        |          t          j        |          t          j        |          dz  }dd	|iz  }	t          t          j	        |	                    d x}x}x}}d S )Nr5   r  zRAG pipeliner   r{   r   r~   rX   rY   r   )
r  r  r   rB   r   rE   r\   rG   rH   rI   r   s
             r/   0test_raw_content_includes_description_and_topicszDTestGitHubCollector.test_raw_content_includes_description_and_topics]  s   Z!7888#b111	!!5q5!55~!55555555555~!555555~55555555!555555555555555555555555555555/58/8//x///////////x//////x////8////////////////////////////////////r1   c                    t          t                    D ]}|                    t                     t	          d          }|                                }g }||k    }|st          j        d|fd||f          dt          j	                    v st          j
        |          rt          j        |          ndt          j        |          dz  }dd	|iz  }t          t          j        |                    d x}}d S )
Nr'   r5   r  rQ   r   r:   r   r   ri   )r*   r
  r)   r  r   rB   rE   r\   rC   rD   rF   rG   rH   rI   r   s	            r/   r   z:TestGitHubCollector.test_empty_response_returns_empty_listd  s   *++ 	7 	7A###6666#b111	!!u{uuur1   c                    t          t                    D ]}|                    t                     t	          d          }|                                }d |D             }t          |          }t          |          }t          |          }||k    }	|	st          j	        d|	fd||f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |          dt          j                    v st          j        t                    rt          j        t                    ndd	t          j                    v st          j        t                    rt          j        t                    nd	dt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          d
z  }
dd|
iz  }t          t          j        |                    d x}x}	x}}d S )Nr'   r5   r  c                     g | ]	}|j         
S r   r   r   s     r/   r   zGTestGitHubCollector.test_deduplicates_across_topics.<locals>.<listcomp>q  r   r1   rQ   r   rT   r   r   r   r   r   )r*   r
  r)   r  r   rB   rT   r   rE   r\   rC   rD   rF   rG   rH   rI   )rK   r#   r.   rL   r:   r   r^   r   r   r`   r   r   s               r/   test_deduplicates_across_topicsz3TestGitHubCollector.test_deduplicates_across_topicsk  s]   *++ 	A 	AA##)?#@@@@#b111	!!,,e,,,4yy*D		*C	NN*yN**********yN************s*****s*************4*****4******y***********C*****C*******************************D*****D******	****N*******************************r1   c                    t          |t                     t          dd          }|                                }t	          |t
                    }|sddt          j                    v st          j	        t                    rt          j
        t                    nddt          j                    v st          j	        |          rt          j
        |          nddt          j                    v st          j	        t
                    rt          j
        t
                    ndt          j
        |          dz  }t          t          j        |                    d }d S )	Nr5   ghp_test123)r  tokenr8   r9   r:   r;   r<   r  rJ   s         r/   )test_uses_auth_header_when_token_providedz=TestGitHubCollector.test_uses_auth_header_when_token_providedt  s=   Z!7888#bFFF	!!%&&&&&&&&&&&&&&&z&&&&&z&&&&&&&&&&&&&%&&&&&%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&r1   )r   r   r   r   r  r  ry   r  r   r  r"  r   r1   r/   r  r  E  s       ') ' ' ' ' '*I *$ * * * *7	 7d 7 7 7 709 0Y] 0 0 0 0 t    +) + + + + +'I 'RV ' ' ' ' ' 'r1   r  )r   r   r   r   r   )$__doc__builtinsrC   _pytest.assertion.rewrite	assertionrewriterE   r   unittest.mockr   r   pytest_httpxr   &ai_usecases_explorer.collectors.githubr   *ai_usecases_explorer.collectors.hackernewsr   &ai_usecases_explorer.collectors.redditr	   rA   r   r,   r+   dictr0   r3   strr   r;   r   r   r  r  r
  r  r  r   r1   r/   <module>r/     sK   : :                     * * * * * * * * " " " " " " B B B B B B J J J J J J B B B B B B  S24]		
 		
  &,4*		
 		
, / :  74A		
 		
   " !$$ / /D /T / / / /5) 5) 5) 5) 5) 5) 5) 5)| H?L0 	  	
      Y I    y2 y2 y2 y2 y2 y2 y2 y2B  &1CN888 " /0w'	
 	
 #.@(g !$/0w'	
 	
  D  !KK 3Y 3 3 3 3 3 33' 3' 3' 3' 3' 3' 3' 3' 3' 3'r1   