use stargaze::{
count_repos, fetch_readmes_parallel, load_all, open_db, upsert_repos, GhClient, Repo, RepoIndex,
};
fn token() -> Option<String> {
let t = std::env::var("GH_TOKEN")
.or_else(|_| std::env::var("GITHUB_TOKEN"))
.ok()?;
if t.is_empty() {
None
} else {
Some(t)
}
}
fn skip_if_no_token(test_name: &str) -> Option<String> {
match token() {
Some(t) => Some(t),
None => {
eprintln!(
"[live::{}] SKIPPED — GH_TOKEN not set. \
Run with `export GH_TOKEN=$(gh auth token)` then \
`cargo test -- --ignored`.",
test_name
);
None
}
}
}
#[test]
#[ignore]
fn live_starred_first_page() {
let Some(t) = skip_if_no_token("live_starred_first_page") else {
return;
};
let client = GhClient::new(t);
let items = client.starred(None).expect("live starred call");
assert!(
!items.is_empty(),
"expected at least one starred repo, got zero"
);
let first = &items[0];
assert!(
first.get("full_name").is_some() || first.get("repo").is_some(),
"first item shape unexpected: {}",
first
);
}
#[test]
#[ignore]
fn live_starred_public_user() {
let Some(t) = skip_if_no_token("live_starred_public_user") else {
return;
};
let client = GhClient::new(t);
let items = client
.starred(Some("rust-lang-nursery"))
.expect("live public starred");
assert!(
items.len() < 10_000,
"unexpected payload size from public-user stars: {}",
items.len()
);
}
#[test]
#[ignore]
fn live_readme_fetch_rust_lang_rust() {
let Some(t) = skip_if_no_token("live_readme_fetch_rust_lang_rust") else {
return;
};
let client = GhClient::new(t);
let body = client.readme("rust-lang", "rust").expect("fetch README");
assert!(!body.is_empty(), "expected non-empty README");
assert!(
body.to_lowercase().contains("rust"),
"rust-lang/rust README should contain the word 'rust'"
);
}
#[test]
#[ignore]
fn live_readme_fetch_missing_repo_returns_empty() {
let Some(t) = skip_if_no_token("live_readme_fetch_missing_repo_returns_empty") else {
return;
};
let client = GhClient::new(t);
let body = client
.readme("bkataru", "stargaze-definitely-nonexistent-sentinel-9d8f7a")
.expect("404 should not error");
assert_eq!(body, "", "missing repos should return empty, not fail");
}
#[test]
#[ignore]
fn live_parallel_readme_batch() {
let Some(t) = skip_if_no_token("live_parallel_readme_batch") else {
return;
};
let targets = vec![
("rust-lang", "rust"),
("tokio-rs", "tokio"),
("launchbadge", "sqlx"),
];
let repos: Vec<Repo> = targets
.into_iter()
.map(|(owner, name)| Repo {
full_name: format!("{}/{}", owner, name),
owner: owner.to_string(),
name: name.to_string(),
description: None,
url: format!("https://github.com/{}/{}", owner, name),
language: None,
stargazers_count: 0,
forks_count: 0,
open_issues_count: 0,
topics: vec![],
default_branch: None,
license: None,
archived: false,
fork: false,
pushed_at: None,
created_at: None,
updated_at: None,
starred_at: None,
cached_at: chrono::Utc::now(),
readme: None,
readme_fetched_at: None,
})
.collect();
let fetched = fetch_readmes_parallel(&t, repos, 3);
assert_eq!(fetched.len(), 3);
let hit = fetched.iter().filter(|r| r.readme.is_some()).count();
assert_eq!(hit, 3, "all 3 well-known repos should return a README");
for r in &fetched {
let body = r.readme.as_deref().unwrap_or("");
assert!(!body.is_empty(), "{}: empty README", r.full_name);
}
}
#[test]
#[ignore]
fn live_mini_sync_roundtrip() {
let Some(t) = skip_if_no_token("live_mini_sync_roundtrip") else {
return;
};
let dir = tempfile::Builder::new()
.prefix("stargaze-live-")
.tempdir()
.expect("tempdir");
let db_path = dir.path().join("stars.redb");
let db = open_db(&db_path).expect("open_db");
let client = GhClient::new(t);
let items = client.starred(None).expect("live starred");
let mut repos = Vec::new();
for item in items.iter().take(50) {
if let Ok(r) = Repo::from_api(item) {
repos.push(r);
}
}
assert!(!repos.is_empty(), "should have parsed at least one repo");
upsert_repos(&db, &repos).expect("upsert");
assert_eq!(count_repos(&db).unwrap(), repos.len());
let loaded = load_all(&db).expect("load_all");
let idx = RepoIndex::new(loaded);
assert_eq!(idx.len(), repos.len());
let hits = idx.search("", None, None, 1_000_000);
assert_eq!(hits.len(), repos.len());
}