use onetaskgraph_github_projects::{graphql, worst_case_point_cost};
const PRICES: &[(&str, u64)] = &[
(graphql::SEARCH_ISSUES, 5),
(graphql::ISSUE, 1),
(graphql::ISSUE_BOARD_ITEMS, 1),
(graphql::SUB_ISSUES, 5),
(graphql::BOARD, 2),
(graphql::REPOSITORY, 1),
(graphql::ISSUE_DEPENDENCIES, 1),
(graphql::CREATE_ISSUE, 1),
(graphql::ADD_TO_BOARD, 1),
(graphql::UPDATE_ISSUE, 1),
(graphql::UPDATE_DRAFT, 1),
(graphql::UPDATE_FIELD, 1),
(graphql::ADD_SUB_ISSUE, 1),
(graphql::REMOVE_SUB_ISSUE, 1),
(graphql::ADD_BLOCKED_BY, 1),
(graphql::REMOVE_BLOCKED_BY, 1),
(graphql::DELETE_ISSUE, 1),
];
fn mispriced(doing: &str, document: &str, recorded: Option<u64>) -> Option<String> {
let price = worst_case_point_cost(document)
.unwrap_or_else(|error| panic!("the document for {doing} could not be priced: {error}"));
match recorded {
None => Some(format!(
"the document for {doing} costs {price} points and this file records no price \
for it; next: add it to PRICES at {price}"
)),
Some(recorded) if recorded != price => Some(format!(
"the document for {doing} now costs {price} points and this file records \
{recorded}; next: if the change is deliberate, put {price} in PRICES and say \
in session-cost.md what moved it"
)),
Some(_) => None,
}
}
fn recorded(document: &str) -> Option<u64> {
PRICES
.iter()
.find(|(pinned, _)| *pinned == document)
.map(|(_, price)| *price)
}
#[test]
fn every_document_this_source_sends_costs_what_this_file_records() {
let moved = graphql::DOCUMENTS
.iter()
.filter_map(|(document, doing)| mispriced(doing, document, recorded(document)))
.collect::<Vec<_>>();
assert!(moved.is_empty(), "{}", moved.join("\n"));
}
#[test]
fn every_price_recorded_here_belongs_to_a_document_this_source_sends() {
let orphaned = PRICES
.iter()
.filter(|(pinned, _)| {
!graphql::DOCUMENTS
.iter()
.any(|(document, _)| document == pinned)
})
.map(|(pinned, price)| {
format!("this file records {price} points for a document the inventory does not hold; next: delete the entry, or put the document back in graphql::DOCUMENTS:\n{pinned}")
})
.collect::<Vec<_>>();
assert!(orphaned.is_empty(), "{}", orphaned.join("\n"));
}
#[test]
fn the_check_reports_a_failure_naming_a_document_whose_price_moved() {
let refusal = mispriced("reading the board", graphql::BOARD, Some(8))
.expect("a price this document does not cost is refused");
assert!(refusal.contains("reading the board"), "{refusal}");
assert!(refusal.contains('8'), "{refusal}");
assert!(refusal.contains('2'), "{refusal}");
}
#[test]
fn the_check_reports_a_failure_naming_a_document_nobody_priced() {
let refusal = mispriced("reading the board", graphql::BOARD, None)
.expect("a document with no recorded price is refused");
assert!(refusal.contains("reading the board"), "{refusal}");
assert!(refusal.contains("records no price"), "{refusal}");
}