use crate::{ mock::{new_test_ext, RuntimeOrigin, System, Test, Perwerde as PerwerdePallet}, Event, }; use frame_support::{assert_noop, assert_ok, pallet_prelude::Get, BoundedVec}; use sp_runtime::DispatchError; fn create_bounded_vec>(s: &[u8]) -> BoundedVec { s.to_vec().try_into().unwrap() } #[test] fn create_course_works() { new_test_ext().execute_with(|| { // Admin olarak mock.rs'te TestAdminProvider içinde tanımladığımız hesabı kullanıyoruz. let admin_account_id = 0; // Eylem: Yetkili admin ile kurs oluştur. assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin_account_id), create_bounded_vec(b"Blockchain 101"), create_bounded_vec(b"Giris seviyesi"), create_bounded_vec(b"http://example.com") )); // Doğrulama assert!(crate::Courses::::contains_key(0)); let course = crate::Courses::::get(0).unwrap(); assert_eq!(course.owner, admin_account_id); System::assert_last_event(Event::CourseCreated { course_id: 0, owner: admin_account_id }.into()); }); } #[test] fn create_course_fails_for_non_admin() { new_test_ext().execute_with(|| { // Admin (0) dışındaki bir hesap (2) kurs oluşturamaz. let non_admin = 2; assert_noop!( PerwerdePallet::create_course( RuntimeOrigin::signed(non_admin), create_bounded_vec(b"Hacking 101"), create_bounded_vec(b"Yetkisiz kurs"), create_bounded_vec(b"http://example.com") ), DispatchError::BadOrigin ); }); } // ============================================================================ // ENROLL TESTS (8 tests) // ============================================================================ #[test] fn enroll_works() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create course first assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Rust Basics"), create_bounded_vec(b"Learn Rust"), create_bounded_vec(b"http://example.com") )); // Student enrolls assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); // Verify enrollment let enrollment = crate::Enrollments::::get((student, 0)).unwrap(); assert_eq!(enrollment.student, student); assert_eq!(enrollment.course_id, 0); assert_eq!(enrollment.completed_at, None); assert_eq!(enrollment.points_earned, 0); // Verify StudentCourses updated let student_courses = crate::StudentCourses::::get(student); assert!(student_courses.contains(&0)); System::assert_last_event(Event::StudentEnrolled { student, course_id: 0 }.into()); }); } #[test] fn enroll_fails_for_nonexistent_course() { new_test_ext().execute_with(|| { let student = 1; assert_noop!( PerwerdePallet::enroll(RuntimeOrigin::signed(student), 999), crate::Error::::CourseNotFound ); }); } #[test] fn enroll_fails_for_archived_course() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create and archive course assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Old Course"), create_bounded_vec(b"Archived"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::archive_course(RuntimeOrigin::signed(admin), 0)); // Try to enroll in archived course assert_noop!( PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0), crate::Error::::CourseNotActive ); }); } #[test] fn enroll_fails_if_already_enrolled() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create course assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Description"), create_bounded_vec(b"http://example.com") )); // First enrollment succeeds assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); // Second enrollment fails assert_noop!( PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0), crate::Error::::AlreadyEnrolled ); }); } #[test] fn multiple_students_can_enroll_same_course() { new_test_ext().execute_with(|| { let admin = 0; let student1 = 1; let student2 = 2; let student3 = 3; // Create course assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Popular Course"), create_bounded_vec(b"Many students"), create_bounded_vec(b"http://example.com") )); // Multiple students enroll assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student1), 0)); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student2), 0)); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student3), 0)); // Verify all enrollments assert!(crate::Enrollments::::contains_key((student1, 0))); assert!(crate::Enrollments::::contains_key((student2, 0))); assert!(crate::Enrollments::::contains_key((student3, 0))); }); } #[test] fn student_can_enroll_multiple_courses() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create 3 courses for i in 0..3 { assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(format!("Course {}", i).as_bytes()), create_bounded_vec(b"Description"), create_bounded_vec(b"http://example.com") )); } // Student enrolls in all 3 assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 1)); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 2)); // Verify StudentCourses let student_courses = crate::StudentCourses::::get(student); assert_eq!(student_courses.len(), 3); assert!(student_courses.contains(&0)); assert!(student_courses.contains(&1)); assert!(student_courses.contains(&2)); }); } #[test] fn enroll_fails_when_too_many_courses() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // MaxStudentsPerCourse is typically 100, so create and enroll in 100 courses for i in 0..100 { assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(format!("Course {}", i).as_bytes()), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), i)); } // Create one more course assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course 100"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); // Enrollment should fail assert_noop!( PerwerdePallet::enroll(RuntimeOrigin::signed(student), 100), crate::Error::::TooManyCourses ); }); } #[test] fn enroll_event_emitted_correctly() { new_test_ext().execute_with(|| { let admin = 0; let student = 5; assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Test"), create_bounded_vec(b"Test"), create_bounded_vec(b"http://test.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); System::assert_last_event(Event::StudentEnrolled { student: 5, course_id: 0 }.into()); }); } // ============================================================================ // COMPLETE_COURSE TESTS (8 tests) // ============================================================================ #[test] fn complete_course_works() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; let points = 95; // Setup: Create course and enroll assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); // Complete the course assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, points)); // Verify completion let enrollment = crate::Enrollments::::get((student, 0)).unwrap(); assert!(enrollment.completed_at.is_some()); assert_eq!(enrollment.points_earned, points); System::assert_last_event(Event::CourseCompleted { student, course_id: 0, points }.into()); }); } #[test] fn complete_course_fails_without_enrollment() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create course but don't enroll assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); // Try to complete without enrollment assert_noop!( PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, 100), crate::Error::::NotEnrolled ); }); } #[test] fn complete_course_fails_if_already_completed() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Setup assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); // First completion succeeds assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, 85)); // Second completion fails assert_noop!( PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, 90), crate::Error::::CourseAlreadyCompleted ); }); } #[test] fn complete_course_with_zero_points() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); // Complete with 0 points (failed course) assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, 0)); let enrollment = crate::Enrollments::::get((student, 0)).unwrap(); assert_eq!(enrollment.points_earned, 0); }); } #[test] fn complete_course_with_max_points() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); // Complete with maximum points assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, u32::MAX)); let enrollment = crate::Enrollments::::get((student, 0)).unwrap(); assert_eq!(enrollment.points_earned, u32::MAX); }); } #[test] fn multiple_students_complete_same_course() { new_test_ext().execute_with(|| { let admin = 0; assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); // 3 students enroll and complete with different scores for i in 1u64..=3 { assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(i), 0)); assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(i), 0, (70 + (i * 10)) as u32)); } // Verify each completion for i in 1u64..=3 { let enrollment = crate::Enrollments::::get((i, 0)).unwrap(); assert!(enrollment.completed_at.is_some()); assert_eq!(enrollment.points_earned, (70 + (i * 10)) as u32); } }); } #[test] fn student_completes_multiple_courses() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create 3 courses for i in 0..3 { assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(format!("Course {}", i).as_bytes()), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), i)); } // Complete all 3 assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, 80)); assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 1, 90)); assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 2, 95)); // Verify all completions for i in 0..3 { let enrollment = crate::Enrollments::::get((student, i)).unwrap(); assert!(enrollment.completed_at.is_some()); } }); } #[test] fn complete_course_event_emitted() { new_test_ext().execute_with(|| { let admin = 0; let student = 7; let points = 88; assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Test"), create_bounded_vec(b"Test"), create_bounded_vec(b"http://test.com") )); assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); assert_ok!(PerwerdePallet::complete_course(RuntimeOrigin::signed(student), 0, points)); System::assert_last_event(Event::CourseCompleted { student: 7, course_id: 0, points: 88 }.into()); }); } // ============================================================================ // ARCHIVE_COURSE TESTS (4 tests) // ============================================================================ #[test] fn archive_course_works() { new_test_ext().execute_with(|| { let admin = 0; assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::archive_course(RuntimeOrigin::signed(admin), 0)); let course = crate::Courses::::get(0).unwrap(); assert_eq!(course.status, crate::CourseStatus::Archived); System::assert_last_event(Event::CourseArchived { course_id: 0 }.into()); }); } #[test] fn archive_course_fails_for_non_owner() { new_test_ext().execute_with(|| { let admin = 0; let other_user = 1; assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); // Non-owner cannot archive assert_noop!( PerwerdePallet::archive_course(RuntimeOrigin::signed(other_user), 0), DispatchError::BadOrigin ); }); } #[test] fn archive_course_fails_for_nonexistent_course() { new_test_ext().execute_with(|| { let admin = 0; assert_noop!( PerwerdePallet::archive_course(RuntimeOrigin::signed(admin), 999), crate::Error::::CourseNotFound ); }); } #[test] fn archived_course_cannot_accept_new_enrollments() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create and archive assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_ok!(PerwerdePallet::archive_course(RuntimeOrigin::signed(admin), 0)); // Try to enroll - should fail assert_noop!( PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0), crate::Error::::CourseNotActive ); }); } // ============================================================================ // INTEGRATION & STORAGE TESTS (2 tests) // ============================================================================ #[test] fn storage_consistency_check() { new_test_ext().execute_with(|| { let admin = 0; let student = 1; // Create course assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(b"Course"), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); // Enroll assert_ok!(PerwerdePallet::enroll(RuntimeOrigin::signed(student), 0)); // Check storage consistency assert!(crate::Courses::::contains_key(0)); assert!(crate::Enrollments::::contains_key((student, 0))); let student_courses = crate::StudentCourses::::get(student); assert_eq!(student_courses.len(), 1); assert!(student_courses.contains(&0)); let enrollment = crate::Enrollments::::get((student, 0)).unwrap(); assert_eq!(enrollment.course_id, 0); assert_eq!(enrollment.student, student); }); } #[test] fn next_course_id_increments_correctly() { new_test_ext().execute_with(|| { let admin = 0; assert_eq!(crate::NextCourseId::::get(), 0); // Create 5 courses for i in 0..5 { assert_ok!(PerwerdePallet::create_course( RuntimeOrigin::signed(admin), create_bounded_vec(format!("Course {}", i).as_bytes()), create_bounded_vec(b"Desc"), create_bounded_vec(b"http://example.com") )); assert_eq!(crate::NextCourseId::::get(), i + 1); } // Verify all courses exist for i in 0..5 { assert!(crate::Courses::::contains_key(i)); } }); }