test(quotesdb): add hidden flag filter tests to native repository

Add three tests verifying hidden-quote filtering behaviour in
NativeRepository:

- list_quotes_excludes_hidden: hidden quotes do not appear in paginated
  listing results.
- get_random_quote_excludes_hidden: get_random_quote returns None when
  the only quote is hidden.
- get_quote_returns_hidden_quote: get_quote (direct ID lookup) still
  returns the quote when it is hidden.

Also refactor the inline row-mapping closure in list_quotes to use the
existing row_to_quote helper, eliminating duplicated column mapping
logic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
Elijah Voigt 3 months ago
parent 250e3e3d14
commit dab88e66ac

@ -191,20 +191,7 @@ impl QuoteRepository for NativeRepository {
let partial_quotes: Vec<Quote> = stmt let partial_quotes: Vec<Quote> = stmt
.query_map( .query_map(
rusqlite::params_from_iter(param_refs2.iter().copied()), rusqlite::params_from_iter(param_refs2.iter().copied()),
|row| { |row| row_to_quote(row, vec![]),
let hidden_int: i64 = row.get(5)?;
Ok(Quote {
id: row.get(0)?,
text: row.get(1)?,
author: row.get(2)?,
source: row.get(3)?,
date: row.get(4)?,
hidden: hidden_int != 0,
created_at: row.get(6)?,
updated_at: row.get(7)?,
tags: vec![],
})
},
)? )?
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
@ -984,4 +971,135 @@ mod tests {
let stored = repo.get_admin_auth_code().await.unwrap(); let stored = repo.get_admin_auth_code().await.unwrap();
assert_eq!(stored.as_deref(), Some("correct-code")); assert_eq!(stored.as_deref(), Some("correct-code"));
} }
// ── hidden flag filter tests ───────────────────────────────────────────────
/// `list_quotes` must exclude hidden quotes and include only visible ones.
#[tokio::test]
async fn test_list_quotes_excludes_hidden() {
let repo = in_memory_repo().await;
// Create a visible quote and a hidden quote.
let (visible, _) = repo
.create_quote(CreateQuoteInput {
text: "Visible quote".to_owned(),
author: "Author A".to_owned(),
source: None,
date: None,
tags: vec![],
auth_code: Some("auth-visible-xxxxx".to_owned()),
cf_turnstile_token: None,
})
.await
.unwrap();
let (hidden, hidden_auth) = repo
.create_quote(CreateQuoteInput {
text: "Hidden quote".to_owned(),
author: "Author B".to_owned(),
source: None,
date: None,
tags: vec![],
auth_code: Some("auth-hidden-xxxxxx".to_owned()),
cf_turnstile_token: None,
})
.await
.unwrap();
// Mark the second quote as hidden.
repo.update_quote(
&hidden.id,
UpdateQuoteInput {
hidden: Some(true),
..UpdateQuoteInput::default()
},
&hidden_auth,
)
.await
.unwrap();
let result = repo.list_quotes(1, None, None, None, None).await.unwrap();
assert_eq!(result.total_count, 1, "only the visible quote should count");
assert_eq!(result.quotes.len(), 1);
assert_eq!(
result.quotes[0].id, visible.id,
"the returned quote must be the visible one"
);
}
/// `get_random_quote` must return `None` when the only quote is hidden.
#[tokio::test]
async fn test_get_random_quote_excludes_hidden() {
let repo = in_memory_repo().await;
// Create a single quote and immediately hide it.
let (quote, auth) = repo
.create_quote(CreateQuoteInput {
text: "Only quote, hidden".to_owned(),
author: "Ghost".to_owned(),
source: None,
date: None,
tags: vec![],
auth_code: Some("auth-ghost-xxxxxxx".to_owned()),
cf_turnstile_token: None,
})
.await
.unwrap();
repo.update_quote(
&quote.id,
UpdateQuoteInput {
hidden: Some(true),
..UpdateQuoteInput::default()
},
&auth,
)
.await
.unwrap();
let result = repo.get_random_quote().await.unwrap();
assert!(
result.is_none(),
"get_random_quote should return None when only hidden quotes exist"
);
}
/// `get_quote` (direct ID lookup) must return the quote even when it is hidden.
#[tokio::test]
async fn test_get_quote_returns_hidden_quote() {
let repo = in_memory_repo().await;
let (quote, auth) = repo
.create_quote(CreateQuoteInput {
text: "Accessible but hidden".to_owned(),
author: "Secret Author".to_owned(),
source: None,
date: None,
tags: vec![],
auth_code: Some("auth-secret-xxxxxx".to_owned()),
cf_turnstile_token: None,
})
.await
.unwrap();
repo.update_quote(
&quote.id,
UpdateQuoteInput {
hidden: Some(true),
..UpdateQuoteInput::default()
},
&auth,
)
.await
.unwrap();
let fetched = repo.get_quote(&quote.id).await.unwrap();
assert!(
fetched.is_some(),
"get_quote must return the quote even when it is hidden"
);
let fetched = fetched.unwrap();
assert_eq!(fetched.id, quote.id);
assert!(fetched.hidden, "the returned quote must have hidden=true");
}
} }

Loading…
Cancel
Save