use super::*; // ── CreatorTier::label ─────────────────────────────────────────────── #[test] fn label_basic() { assert_eq!(CreatorTier::Basic.label(), "Basic"); } #[test] fn label_small_files() { assert_eq!(CreatorTier::SmallFiles.label(), "Small Files"); } #[test] fn label_big_files() { assert_eq!(CreatorTier::BigFiles.label(), "Big Files"); } #[test] fn label_everything() { assert_eq!(CreatorTier::Everything.label(), "Everything"); } // ── CreatorTier price + envelope invariants ──────────────────────── // // Concrete cents/bytes come from `assumptions.toml` via the installed // `TierPrices` global. Tests pin only structural invariants (positive, // monotone, per-file ≤ storage) so a future toml edit doesn't rewrite // this file. Literal-value pins live in `docs/business/assumptions.toml` // itself and are guarded by the docengine `tier_bytes ↔ tier_limits` // validator. fn all_tiers() -> [CreatorTier; 4] { [ CreatorTier::Basic, CreatorTier::SmallFiles, CreatorTier::BigFiles, CreatorTier::Everything, ] } #[test] fn prices_positive_and_strictly_increasing() { crate::tier_prices::TierPrices::install_test_default(); let tiers = all_tiers(); assert!(tiers[0].price_cents() > 0); for pair in tiers.windows(2) { assert!( pair[0].price_cents() < pair[1].price_cents(), "{:?} should cost less than {:?}", pair[0], pair[1], ); } } #[test] fn max_file_bytes_non_decreasing() { crate::tier_prices::TierPrices::install_test_default(); let tiers = all_tiers(); assert!(tiers[0].max_file_bytes() > 0); for pair in tiers.windows(2) { assert!( pair[0].max_file_bytes() <= pair[1].max_file_bytes(), "{:?} file limit should not exceed {:?}", pair[0], pair[1], ); } } #[test] fn max_storage_bytes_non_decreasing() { crate::tier_prices::TierPrices::install_test_default(); let tiers = all_tiers(); assert!(tiers[0].max_storage_bytes() > 0); for pair in tiers.windows(2) { assert!( pair[0].max_storage_bytes() <= pair[1].max_storage_bytes(), "{:?} storage limit should not exceed {:?}", pair[0], pair[1], ); } } #[test] fn top_tier_matches_big_files_envelope() { // BigFiles and Everything share the same envelope by product design. // (Everything differentiates on features, not caps.) crate::tier_prices::TierPrices::install_test_default(); assert_eq!( CreatorTier::Everything.max_file_bytes(), CreatorTier::BigFiles.max_file_bytes(), ); assert_eq!( CreatorTier::Everything.max_storage_bytes(), CreatorTier::BigFiles.max_storage_bytes(), ); } // ── CreatorTier::allows_file_uploads ───────────────────────────────── #[test] fn basic_tier_disallows_file_uploads() { assert!(!CreatorTier::Basic.allows_file_uploads()); } #[test] fn small_files_allows_file_uploads() { assert!(CreatorTier::SmallFiles.allows_file_uploads()); } #[test] fn big_files_allows_file_uploads() { assert!(CreatorTier::BigFiles.allows_file_uploads()); } #[test] fn everything_allows_file_uploads() { assert!(CreatorTier::Everything.allows_file_uploads()); } // ── format_bytes helper ───────────────────────────────────────────── #[test] fn format_bytes_zero() { assert_eq!(format_bytes(0), "0 B"); } #[test] fn format_bytes_one_byte() { assert_eq!(format_bytes(1), "1 B"); } #[test] fn format_bytes_below_kb() { assert_eq!(format_bytes(1023), "1023 B"); } #[test] fn format_bytes_exactly_1kb() { assert_eq!(format_bytes(1024), "1.0 KB"); } #[test] fn format_bytes_exactly_1mb() { assert_eq!(format_bytes(1024 * 1024), "1.0 MB"); } #[test] fn format_bytes_exactly_1gb() { assert_eq!(format_bytes(1024 * 1024 * 1024), "1.0 GB"); } #[test] fn format_bytes_negative_clamped_to_zero() { assert_eq!(format_bytes(-999), "0 B"); } #[test] fn format_bytes_large_storage_cap() { // 500 GB (Everything tier cap) assert_eq!(format_bytes(500 * 1024 * 1024 * 1024), "500.0 GB"); } // ── StorageBreakdown ──────────────────────────────────────────────── #[test] fn storage_breakdown_default_is_all_zeros() { let sb = StorageBreakdown::default(); assert_eq!(sb.audio_bytes, 0); assert_eq!(sb.cover_bytes, 0); assert_eq!(sb.download_bytes, 0); assert_eq!(sb.insertion_bytes, 0); assert_eq!(sb.video_bytes, 0); assert_eq!(sb.media_bytes, 0); assert_eq!(sb.total_bytes, 0); } #[test] fn storage_breakdown_total_is_sum_of_categories() { let sb = StorageBreakdown { audio_bytes: 100, cover_bytes: 200, download_bytes: 300, insertion_bytes: 400, video_bytes: 500, media_bytes: 600, gallery_bytes: 700, total_bytes: 100 + 200 + 300 + 400 + 500 + 600 + 700, }; assert_eq!( sb.total_bytes, sb.audio_bytes + sb.cover_bytes + sb.download_bytes + sb.insertion_bytes + sb.video_bytes + sb.media_bytes + sb.gallery_bytes, ); } #[test] fn storage_breakdown_single_category() { let sb = StorageBreakdown { audio_bytes: 1_000_000, total_bytes: 1_000_000, ..Default::default() }; assert_eq!(sb.total_bytes, 1_000_000); assert_eq!(sb.cover_bytes, 0); } // ── Boundary / cross-cutting ──────────────────────────────────────── #[test] fn basic_file_limit_less_than_storage_limit() { crate::tier_prices::TierPrices::install_test_default(); assert!(CreatorTier::Basic.max_file_bytes() < CreatorTier::Basic.max_storage_bytes()); } #[test] fn every_tier_file_limit_within_storage_limit() { crate::tier_prices::TierPrices::install_test_default(); for tier in [ CreatorTier::Basic, CreatorTier::SmallFiles, CreatorTier::BigFiles, CreatorTier::Everything, ] { assert!( tier.max_file_bytes() <= tier.max_storage_bytes(), "{tier:?} file limit exceeds its own storage limit", ); } }