use crate::{ mock::{ ExtBuilder, Test, Welati, RuntimeOrigin, RuntimeEvent, run_to_block, last_event, add_parliament_member }, types::*, Error, Event as WelatiEvent, CurrentOfficials, GovernmentPosition, }; use frame_support::{ assert_noop, assert_ok, BoundedVec, }; use sp_runtime::traits::BadOrigin; // ===== SEÇİM SİSTEMİ TESTLERİ ===== #[test] fn initiate_election_works() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); let expected_event = RuntimeEvent::Welati(WelatiEvent::ElectionStarted { election_id: 0, election_type: ElectionType::Presidential, start_block: 1, end_block: 1 + 86_400 + 259_200 + 432_000, }); assert_eq!(last_event(), expected_event); assert!(Welati::active_elections(0).is_some()); assert_eq!(Welati::next_election_id(), 1); }); } #[test] fn initiate_election_fails_for_non_root() { ExtBuilder::default().build().execute_with(|| { assert_noop!( Welati::initiate_election( RuntimeOrigin::signed(1), ElectionType::Presidential, None, None, ), BadOrigin ); }); } #[test] fn register_candidate_works_for_parliamentary() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); let parliamentary_endorsers: Vec = (2..=51).collect(); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, parliamentary_endorsers, )); assert_eq!( last_event(), RuntimeEvent::Welati(WelatiEvent::CandidateRegistered { election_id: 0, candidate: 1, deposit_paid: 10_000, }) ); assert!(Welati::election_candidates(0, 1).is_some()); }); } #[test] fn register_candidate_fails_insufficient_endorsements() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); let endorsers = vec![2, 3, 4]; assert_noop!( Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers, ), Error::::InsufficientEndorsements ); }); } #[test] fn register_candidate_fails_after_deadline() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); run_to_block(86_400 + 100); let endorsers: Vec = (2..=51).collect(); assert_noop!( Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers, ), Error::::CandidacyPeriodExpired ); }); } #[test] fn register_candidate_fails_already_candidate() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); let endorsers: Vec = (2..=51).collect(); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers.clone(), )); assert_noop!( Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers, ), Error::::AlreadyCandidate ); }); } #[test] fn cast_vote_works() { ExtBuilder::default().build().execute_with(|| { // 1. Seçimi başlat assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); // 2. Bir aday kaydet (hesap 1) let endorsers: Vec = (3..=52).collect(); // 50 destekçi assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), // Aday 0, // Seçim ID'si None, // Bölge ID'si endorsers, )); // 3. Oy verme periyoduna ilerle run_to_block(86_400 + 259_200 + 1); // 4. Oy kullan (hesap 2, aday 1'e oy veriyor) let candidates_to_vote_for = vec![1]; assert_ok!(Welati::cast_vote( RuntimeOrigin::signed(2), // Seçmen 0, // Seçim ID'si candidates_to_vote_for.clone(), // Oy verilen aday(lar) None, // Bölge ID'si )); // 5. Event'i ve depolama durumunu doğrula assert_eq!( last_event(), RuntimeEvent::Welati(WelatiEvent::VoteCast { election_id: 0, voter: 2, candidates: candidates_to_vote_for, district_id: None, }) ); assert!(Welati::election_votes(0, 2).is_some()); }); } #[test] fn cast_vote_fails_already_voted() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); let endorsers: Vec = (3..=52).collect(); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers, )); run_to_block(86_400 + 259_200 + 1); let candidates = vec![1]; assert_ok!(Welati::cast_vote( RuntimeOrigin::signed(2), 0, candidates.clone(), None, )); assert_noop!( Welati::cast_vote( RuntimeOrigin::signed(2), 0, candidates, None, ), Error::::AlreadyVoted ); }); } #[test] fn cast_vote_fails_wrong_period() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); let candidates = vec![1]; assert_noop!( Welati::cast_vote( RuntimeOrigin::signed(2), 0, candidates, None, ), Error::::VotingPeriodNotStarted ); }); } #[test] fn finalize_election_works() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); // Seçimin bitiş tarihinden sonrasına geç // candidacy (86_400) + campaign (259_200) + voting (432_000) + 1 run_to_block(86_400 + 259_200 + 432_000 + 10); // Ekstra güvenlik için +10 assert_ok!(Welati::finalize_election( RuntimeOrigin::root(), 0, )); if let Some(election) = Welati::active_elections(0) { assert_eq!(election.status, ElectionStatus::Completed); } }); } // ===== ATAMA SİSTEMİ TESTLERİ ===== #[test] fn nominate_official_works() { ExtBuilder::default().build().execute_with(|| { // Setup: Make user 1 the Serok (President) so they can nominate CurrentOfficials::::insert(GovernmentPosition::Serok, 1); let justification = b"Qualified candidate".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 2, OfficialRole::Dadger, justification, )); assert_eq!(Welati::next_appointment_id(), 1); }); } #[test] fn approve_appointment_works() { ExtBuilder::default().build().execute_with(|| { // Setup: Make user 1 the Serok CurrentOfficials::::insert(GovernmentPosition::Serok, 1); let justification = b"Qualified candidate".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 2, OfficialRole::Dadger, justification, )); assert_ok!(Welati::approve_appointment( RuntimeOrigin::signed(1), 0, )); }); } // ===== KOLLEKTİF KARAR TESTLERİ ===== #[test] fn submit_proposal_works() { ExtBuilder::default().build().execute_with(|| { let title = b"Test Proposal".to_vec().try_into().unwrap(); let description = b"Test proposal description".to_vec().try_into().unwrap(); // CRITICAL FIX: Helper fonksiyonu kullan add_parliament_member(1); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title, description, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); assert_eq!(Welati::next_proposal_id(), 1); assert!(Welati::active_proposals(0).is_some()); }); } #[test] fn vote_on_proposal_works() { ExtBuilder::default().build().execute_with(|| { let title = b"Test Proposal".to_vec().try_into().unwrap(); let description = b"Test proposal description".to_vec().try_into().unwrap(); // CRITICAL FIX: Helper fonksiyonları kullan add_parliament_member(1); add_parliament_member(2); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title, description, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); let proposal = Welati::active_proposals(0).unwrap(); run_to_block(proposal.voting_starts_at + 1); let rationale = Some(b"Good proposal".to_vec().try_into().unwrap()); assert_ok!(Welati::vote_on_proposal( RuntimeOrigin::signed(2), 0, VoteChoice::Aye, rationale, )); assert!(Welati::collective_votes(0, 2).is_some()); }); } // ===== HELPER FUNCTION TESTLERİ ===== #[test] fn get_required_trust_score_works() { ExtBuilder::default().build().execute_with(|| { assert_eq!( Welati::get_required_trust_score(&ElectionType::Presidential), 600 ); assert_eq!( Welati::get_required_trust_score(&ElectionType::Parliamentary), 300 ); assert_eq!( Welati::get_required_trust_score(&ElectionType::ConstitutionalCourt), 750 ); }); } #[test] fn get_required_endorsements_works() { ExtBuilder::default().build().execute_with(|| { assert_eq!( Welati::get_required_endorsements(&ElectionType::Presidential), 100 ); assert_eq!( Welati::get_required_endorsements(&ElectionType::Parliamentary), 50 ); assert_eq!( Welati::get_required_endorsements(&ElectionType::SpeakerElection), 0 ); }); } #[test] fn get_minimum_turnout_works() { ExtBuilder::default().build().execute_with(|| { assert_eq!( Welati::get_minimum_turnout(&ElectionType::Presidential), 50 ); assert_eq!( Welati::get_minimum_turnout(&ElectionType::Parliamentary), 40 ); assert_eq!( Welati::get_minimum_turnout(&ElectionType::SpeakerElection), 30 ); }); } #[test] fn calculate_vote_weight_works() { ExtBuilder::default().build().execute_with(|| { assert_eq!( Welati::calculate_vote_weight(&1, &ElectionType::Presidential), 1 ); assert_eq!( Welati::calculate_vote_weight(&1, &ElectionType::Parliamentary), 1 ); let weight = Welati::calculate_vote_weight(&1, &ElectionType::SpeakerElection); assert!(weight >= 1 && weight <= 10); }); } // ===== ERROR CASE TESTLERİ ===== #[test] fn election_not_found_error_works() { ExtBuilder::default().build().execute_with(|| { assert_noop!( Welati::register_candidate( RuntimeOrigin::signed(1), 999, None, vec![2, 3], ), Error::::ElectionNotFound ); }); } #[test] fn proposal_not_found_error_works() { ExtBuilder::default().build().execute_with(|| { assert_noop!( Welati::vote_on_proposal( RuntimeOrigin::signed(1), 999, VoteChoice::Aye, None, ), Error::::ProposalNotFound ); }); } // ===== INTEGRATION TESTLERİ ===== #[test] fn complete_election_cycle_works() { ExtBuilder::default().build().execute_with(|| { // 1. Seçim başlat assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); // 2. Adaylar kaydolsun let endorsers1: Vec = (10..=59).collect(); let endorsers2: Vec = (60..=109).collect(); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers1, )); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(2), 0, None, endorsers2, )); // 3. Voting period'a geç run_to_block(86_400 + 259_200 + 1); // 4. Oylar kullanılsın assert_ok!(Welati::cast_vote( RuntimeOrigin::signed(3), 0, vec![1], None, )); assert_ok!(Welati::cast_vote( RuntimeOrigin::signed(4), 0, vec![2], None, )); // 5. Seçimi sonlandır run_to_block(86_400 + 259_200 + 432_000 + 2); assert_ok!(Welati::finalize_election( RuntimeOrigin::root(), 0, )); assert!(Welati::election_results(0).is_some()); }); } #[test] fn complete_appointment_cycle_works() { ExtBuilder::default().build().execute_with(|| { // Setup: Make user 1 the Serok CurrentOfficials::::insert(GovernmentPosition::Serok, 1); let justification = b"Experienced lawyer".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 5, OfficialRole::Dadger, justification, )); assert_ok!(Welati::approve_appointment( RuntimeOrigin::signed(1), 0, )); if let Some(process) = Welati::appointment_processes(0) { assert_eq!(process.status, AppointmentStatus::Approved); } }); } #[test] fn complete_proposal_cycle_works() { ExtBuilder::default().build().execute_with(|| { let title = b"Budget Amendment".to_vec().try_into().unwrap(); let description = b"Increase education budget by 10%".to_vec().try_into().unwrap(); // CRITICAL FIX: Helper fonksiyonları kullan add_parliament_member(1); add_parliament_member(2); add_parliament_member(3); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title, description, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::High, None, )); let proposal = Welati::active_proposals(0).unwrap(); run_to_block(proposal.voting_starts_at + 1); assert_ok!(Welati::vote_on_proposal( RuntimeOrigin::signed(2), 0, VoteChoice::Aye, None, )); assert_ok!(Welati::vote_on_proposal( RuntimeOrigin::signed(3), 0, VoteChoice::Aye, None, )); if let Some(proposal) = Welati::active_proposals(0) { assert_eq!(proposal.aye_votes, 2); } }); } // ===== RUNOFF ELECTION TESTLERİ ===== #[test] fn initiate_runoff_election_works() { ExtBuilder::default().build().execute_with(|| { let runoff_candidates: BoundedVec = vec![1, 2].try_into().unwrap(); assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, Some(runoff_candidates), )); assert!(Welati::active_elections(0).is_some()); assert!(Welati::election_candidates(0, 1).is_some()); assert!(Welati::election_candidates(0, 2).is_some()); if let Some(election) = Welati::active_elections(0) { assert_eq!(election.status, ElectionStatus::CampaignPeriod); } }); } #[test] fn runoff_election_fails_with_wrong_candidate_count() { ExtBuilder::default().build().execute_with(|| { let invalid_candidates: Result, _> = vec![1, 2, 3].try_into(); if let Ok(candidates) = invalid_candidates { assert_noop!( Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, Some(candidates), ), Error::::InvalidInitialCandidates ); } }); } #[test] fn runoff_election_fails_for_non_presidential() { ExtBuilder::default().build().execute_with(|| { let runoff_candidates: BoundedVec = vec![1, 2].try_into().unwrap(); assert_noop!( Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, Some(runoff_candidates), ), Error::::InvalidElectionType ); }); } // ============================================================================ // ELECTION SYSTEM - EDGE CASES (8 tests) // ============================================================================ #[test] fn initiate_election_with_districts() { ExtBuilder::default().build().execute_with(|| { let districts = vec![ ElectoralDistrict { district_id: 1, name: b"District 1".to_vec().try_into().unwrap(), seat_count: 5, voter_population: 10_000, geographic_bounds: None, }, ElectoralDistrict { district_id: 2, name: b"District 2".to_vec().try_into().unwrap(), seat_count: 3, voter_population: 6_000, geographic_bounds: None, }, ]; assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, Some(districts.clone()), None, )); let election = Welati::active_elections(0).unwrap(); assert_eq!(election.districts.len(), 2); assert_eq!(election.election_type, ElectionType::Parliamentary); }); } #[test] fn register_candidate_presidential_with_max_endorsements() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); // Presidential requires 100 endorsements let endorsers: Vec = (2..=101).collect(); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers, )); let candidate_info = Welati::election_candidates(0, 1).unwrap(); assert_eq!(candidate_info.endorsers.len(), 100); }); } #[test] fn register_candidate_fails_election_not_found() { ExtBuilder::default().build().execute_with(|| { let endorsers = vec![2, 3]; assert_noop!( Welati::register_candidate( RuntimeOrigin::signed(1), 999, // Non-existent election None, endorsers, ), Error::::ElectionNotFound ); }); } #[test] fn cast_vote_multiple_candidates_parliamentary() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); let parliamentary_endorsers: Vec = (10..=59).collect(); // Register 3 candidates for candidate_id in 1..=3 { assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(candidate_id), 0, None, parliamentary_endorsers.clone(), )); } // Move to voting period run_to_block(86_400 + 259_200 + 100); // Vote for multiple candidates (parliamentary allows this) let candidates_to_vote = vec![1, 2, 3]; assert_ok!(Welati::cast_vote( RuntimeOrigin::signed(100), 0, candidates_to_vote.clone(), None, )); let vote_info = Welati::election_votes(0, 100).unwrap(); assert_eq!(vote_info.candidates.len(), 3); }); } #[test] fn cast_vote_fails_invalid_candidate() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); run_to_block(86_400 + 259_200 + 100); // Try to vote for non-existent candidate assert_noop!( Welati::cast_vote( RuntimeOrigin::signed(100), 0, vec![999], None, ), Error::::ElectionNotFound ); }); } #[test] fn cast_vote_with_district_id() { ExtBuilder::default().build().execute_with(|| { let districts = vec![ ElectoralDistrict { district_id: 1, name: b"District 1".to_vec().try_into().unwrap(), seat_count: 5, voter_population: 10_000, geographic_bounds: None, }, ]; assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, Some(districts), None, )); let endorsers: Vec = (2..=51).collect(); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), 0, Some(1), // District 1 endorsers, )); run_to_block(86_400 + 259_200 + 100); assert_ok!(Welati::cast_vote( RuntimeOrigin::signed(100), 0, vec![1], Some(1), // Vote in District 1 )); let vote_info = Welati::election_votes(0, 100).unwrap(); assert_eq!(vote_info.district_id, Some(1)); }); } #[test] fn finalize_election_fails_not_started() { ExtBuilder::default().build().execute_with(|| { // Try to finalize non-existent election assert_noop!( Welati::finalize_election( RuntimeOrigin::root(), 999, ), Error::::ElectionNotFound ); }); } #[test] fn finalize_election_updates_election_status() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); let endorsers: Vec = (2..=51).collect(); assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(1), 0, None, endorsers, )); run_to_block(86_400 + 259_200 + 100); assert_ok!(Welati::cast_vote( RuntimeOrigin::signed(100), 0, vec![1], None, )); run_to_block(86_400 + 259_200 + 432_000 + 100); assert_ok!(Welati::finalize_election( RuntimeOrigin::root(), 0, )); let election = Welati::active_elections(0).unwrap(); assert_eq!(election.status, ElectionStatus::Completed); }); } // ============================================================================ // NOMINATION & APPOINTMENT SYSTEM (7 tests) // ============================================================================ #[test] fn nominate_official_fails_not_authorized() { ExtBuilder::default().build().execute_with(|| { // Regular user cannot nominate let justification = b"Test justification".to_vec().try_into().unwrap(); assert_noop!( Welati::nominate_official( RuntimeOrigin::signed(999), 2, OfficialRole::Dadger, justification, ), Error::::NotAuthorizedToNominate ); }); } #[test] fn nominate_official_fails_role_already_filled() { ExtBuilder::default().build().execute_with(|| { // Set Serok (President) first CurrentOfficials::::insert(GovernmentPosition::Serok, 1); let justification1 = b"Qualified candidate".to_vec().try_into().unwrap(); // Nominate Dadger assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 2, OfficialRole::Dadger, justification1, )); let process_id = Welati::next_appointment_id() - 1; // Approve appointment assert_ok!(Welati::approve_appointment( RuntimeOrigin::signed(1), process_id, )); let justification2 = b"Another candidate".to_vec().try_into().unwrap(); // Try to nominate same role again assert_noop!( Welati::nominate_official( RuntimeOrigin::signed(1), 3, OfficialRole::Dadger, justification2, ), Error::::RoleAlreadyFilled ); }); } #[test] fn nominate_official_requires_president() { ExtBuilder::default().build().execute_with(|| { // Without president, cannot nominate officials let justification = b"Test justification".to_vec().try_into().unwrap(); assert_noop!( Welati::nominate_official( RuntimeOrigin::signed(1), 2, OfficialRole::Dadger, justification, ), Error::::NotAuthorizedToNominate ); }); } #[test] fn approve_appointment_fails_not_authorized() { ExtBuilder::default().build().execute_with(|| { CurrentOfficials::::insert(GovernmentPosition::Serok, 1); let justification = b"Qualified candidate".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 2, OfficialRole::Dadger, justification, )); let process_id = Welati::next_appointment_id() - 1; // Regular user cannot approve assert_noop!( Welati::approve_appointment( RuntimeOrigin::signed(999), process_id, ), Error::::NotAuthorizedToApprove ); }); } #[test] fn approve_appointment_fails_already_processed() { ExtBuilder::default().build().execute_with(|| { CurrentOfficials::::insert(GovernmentPosition::Serok, 1); let justification = b"Qualified candidate".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 2, OfficialRole::Dadger, justification, )); let process_id = Welati::next_appointment_id() - 1; // First approval assert_ok!(Welati::approve_appointment( RuntimeOrigin::signed(1), process_id, )); // Try to approve again assert_noop!( Welati::approve_appointment( RuntimeOrigin::signed(1), process_id, ), Error::::AppointmentAlreadyProcessed ); }); } #[test] fn approve_appointment_process_not_found() { ExtBuilder::default().build().execute_with(|| { CurrentOfficials::::insert(GovernmentPosition::Serok, 1); assert_noop!( Welati::approve_appointment( RuntimeOrigin::signed(1), 999, // Non-existent process ), Error::::AppointmentProcessNotFound ); }); } #[test] fn nominate_and_approve_multiple_officials() { ExtBuilder::default().build().execute_with(|| { CurrentOfficials::::insert(GovernmentPosition::Serok, 1); let officials = vec![ (2, OfficialRole::Dadger), (3, OfficialRole::Dozger), (4, OfficialRole::Xezinedar), ]; for (nominee, role) in officials { let justification = b"Qualified candidate".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), nominee, role, justification, )); let process_id = Welati::next_appointment_id() - 1; assert_ok!(Welati::approve_appointment( RuntimeOrigin::signed(1), process_id, )); // Verify appointment was processed assert!(Welati::appointment_processes(process_id).is_some()); } }); } // ============================================================================ // PROPOSAL & VOTING SYSTEM (5 tests) // ============================================================================ #[test] fn submit_proposal_fails_not_authorized() { ExtBuilder::default().build().execute_with(|| { // Regular user cannot submit proposal without being parliament member let title = b"Test proposal".to_vec().try_into().unwrap(); let description = b"Test description".to_vec().try_into().unwrap(); assert_noop!( Welati::submit_proposal( RuntimeOrigin::signed(999), title, description, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, ), Error::::NotAuthorizedToPropose ); }); } #[test] fn vote_on_proposal_fails_not_authorized() { ExtBuilder::default().build().execute_with(|| { // Add user to parliament add_parliament_member(1); let title = b"Test proposal".to_vec().try_into().unwrap(); let description = b"Test description".to_vec().try_into().unwrap(); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title, description, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); let proposal_id = Welati::next_proposal_id() - 1; // Non-parliament member cannot vote assert_noop!( Welati::vote_on_proposal( RuntimeOrigin::signed(999), proposal_id, VoteChoice::Aye, None, ), Error::::NotAuthorizedToVote ); }); } #[test] fn vote_on_proposal_fails_already_voted() { ExtBuilder::default().build().execute_with(|| { add_parliament_member(1); add_parliament_member(2); let title = b"Test proposal".to_vec().try_into().unwrap(); let description = b"Test description".to_vec().try_into().unwrap(); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title, description, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); let proposal_id = Welati::next_proposal_id() - 1; // First vote assert_ok!(Welati::vote_on_proposal( RuntimeOrigin::signed(1), proposal_id, VoteChoice::Aye, None, )); // Try to vote again assert_noop!( Welati::vote_on_proposal( RuntimeOrigin::signed(1), proposal_id, VoteChoice::Nay, None, ), Error::::ProposalAlreadyVoted ); }); } #[test] fn vote_on_proposal_fails_proposal_not_found() { ExtBuilder::default().build().execute_with(|| { add_parliament_member(1); assert_noop!( Welati::vote_on_proposal( RuntimeOrigin::signed(1), 999, // Non-existent proposal VoteChoice::Aye, None, ), Error::::ProposalNotFound ); }); } #[test] fn proposal_with_multiple_votes() { ExtBuilder::default().build().execute_with(|| { // Add 5 parliament members for i in 1..=5 { add_parliament_member(i); } let title = b"Test proposal".to_vec().try_into().unwrap(); let description = b"Test description".to_vec().try_into().unwrap(); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title, description, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); let proposal_id = Welati::next_proposal_id() - 1; // Multiple votes: 3 aye, 1 nay, 1 abstain assert_ok!(Welati::vote_on_proposal(RuntimeOrigin::signed(1), proposal_id, VoteChoice::Aye, None)); assert_ok!(Welati::vote_on_proposal(RuntimeOrigin::signed(2), proposal_id, VoteChoice::Aye, None)); assert_ok!(Welati::vote_on_proposal(RuntimeOrigin::signed(3), proposal_id, VoteChoice::Aye, None)); assert_ok!(Welati::vote_on_proposal(RuntimeOrigin::signed(4), proposal_id, VoteChoice::Nay, None)); assert_ok!(Welati::vote_on_proposal(RuntimeOrigin::signed(5), proposal_id, VoteChoice::Abstain, None)); // Verify all votes recorded assert!(Welati::collective_votes(proposal_id, 1).is_some()); assert!(Welati::collective_votes(proposal_id, 2).is_some()); assert!(Welati::collective_votes(proposal_id, 3).is_some()); assert!(Welati::collective_votes(proposal_id, 4).is_some()); assert!(Welati::collective_votes(proposal_id, 5).is_some()); }); } // ============================================================================ // INTEGRATION & STORAGE TESTS (5 tests) // ============================================================================ #[test] fn storage_consistency_multi_election() { ExtBuilder::default().build().execute_with(|| { // Create multiple elections assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); // Verify storage consistency assert!(Welati::active_elections(0).is_some()); assert!(Welati::active_elections(1).is_some()); assert_eq!(Welati::next_election_id(), 2); let election_0 = Welati::active_elections(0).unwrap(); let election_1 = Welati::active_elections(1).unwrap(); assert_eq!(election_0.election_id, 0); assert_eq!(election_1.election_id, 1); assert_eq!(election_0.election_type, ElectionType::Presidential); assert_eq!(election_1.election_type, ElectionType::Parliamentary); }); } #[test] fn multiple_candidates_same_election() { ExtBuilder::default().build().execute_with(|| { assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); let endorsers: Vec = (100..=149).collect(); // Register 10 candidates for candidate_id in 1..=10 { assert_ok!(Welati::register_candidate( RuntimeOrigin::signed(candidate_id), 0, None, endorsers.clone(), )); } // Verify all candidates registered for candidate_id in 1..=10 { assert!(Welati::election_candidates(0, candidate_id).is_some()); } let election = Welati::active_elections(0).unwrap(); assert_eq!(election.candidates.len(), 10); }); } #[test] fn election_id_increments_correctly() { ExtBuilder::default().build().execute_with(|| { assert_eq!(Welati::next_election_id(), 0); assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); assert_eq!(Welati::next_election_id(), 1); assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); assert_eq!(Welati::next_election_id(), 2); assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); assert_eq!(Welati::next_election_id(), 3); }); } #[test] fn appointment_id_increments_correctly() { ExtBuilder::default().build().execute_with(|| { CurrentOfficials::::insert(GovernmentPosition::Serok, 1); assert_eq!(Welati::next_appointment_id(), 0); let justification1 = b"Qualified candidate".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 2, OfficialRole::Dadger, justification1, )); assert_eq!(Welati::next_appointment_id(), 1); let justification2 = b"Another qualified candidate".to_vec().try_into().unwrap(); assert_ok!(Welati::nominate_official( RuntimeOrigin::signed(1), 3, OfficialRole::Dozger, justification2, )); assert_eq!(Welati::next_appointment_id(), 2); }); } #[test] fn proposal_id_increments_correctly() { ExtBuilder::default().build().execute_with(|| { add_parliament_member(1); assert_eq!(Welati::next_proposal_id(), 0); let title1 = b"Proposal 1".to_vec().try_into().unwrap(); let description1 = b"First proposal".to_vec().try_into().unwrap(); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title1, description1, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); assert_eq!(Welati::next_proposal_id(), 1); let title2 = b"Proposal 2".to_vec().try_into().unwrap(); let description2 = b"Second proposal".to_vec().try_into().unwrap(); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title2, description2, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); assert_eq!(Welati::next_proposal_id(), 2); }); } // ============================================================================ // Additional Tests to reach 53 total tests (3 new tests) // ============================================================================ #[test] fn multiple_elections_different_types() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); // Start presidential election assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); // Start parliamentary election assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); // Both elections should be active assert!(Welati::active_elections(0).is_some()); assert!(Welati::active_elections(1).is_some()); // Elections should have different types let election0 = Welati::active_elections(0).unwrap(); let election1 = Welati::active_elections(1).unwrap(); assert_eq!(election0.election_type, ElectionType::Presidential); assert_eq!(election1.election_type, ElectionType::Parliamentary); // Next election ID should be 2 assert_eq!(Welati::next_election_id(), 2); }); } #[test] fn sequential_elections_id_increment() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); // Initial ID should be 0 assert_eq!(Welati::next_election_id(), 0); // Create first election assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); assert_eq!(Welati::next_election_id(), 1); // Create second election assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Parliamentary, None, None, )); assert_eq!(Welati::next_election_id(), 2); // Verify both elections exist assert!(Welati::active_elections(0).is_some()); assert!(Welati::active_elections(1).is_some()); }); } #[test] fn proposal_and_election_storage_independent() { ExtBuilder::default().build().execute_with(|| { frame_system::Pallet::::set_block_number(1); add_parliament_member(1); // Create a proposal let title = b"Test Proposal".to_vec().try_into().unwrap(); let desc = b"Test Description".to_vec().try_into().unwrap(); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title, desc, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::Normal, None, )); // Create an election assert_ok!(Welati::initiate_election( RuntimeOrigin::root(), ElectionType::Presidential, None, None, )); // Verify both storages are independent assert_eq!(Welati::next_proposal_id(), 1); assert_eq!(Welati::next_election_id(), 1); // Verify both exist assert!(Welati::active_proposals(0).is_some()); assert!(Welati::active_elections(0).is_some()); // Create another proposal let title2 = b"Second Proposal".to_vec().try_into().unwrap(); let desc2 = b"Second Description".to_vec().try_into().unwrap(); assert_ok!(Welati::submit_proposal( RuntimeOrigin::signed(1), title2, desc2, CollectiveDecisionType::ParliamentSimpleMajority, ProposalPriority::High, None, )); // Proposal ID incremented, election ID unchanged assert_eq!(Welati::next_proposal_id(), 2); assert_eq!(Welati::next_election_id(), 1); }); }