use rstest::*;
use serde_json::{Value, json};
use crate::{
errors::ApiError,
mycqu::course::{CQUSession, CQUSessionInfo, Course, CourseDayTime, CourseTimetable},
session::Session,
utils::{
models::Period,
test_fixture::{LoginData, access_mycqu_session, login_data, shared_client},
},
};
#[rstest]
#[ignore]
#[tokio::test]
async fn test_fetch_all_session(
#[future] access_mycqu_session: Session,
shared_client: &'static crate::session::Client,
) {
{
let session = Session::new();
let res = CQUSession::fetch_all(shared_client, &session).await;
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), ApiError::NotAccess));
}
let res = CQUSession::fetch_all(shared_client, &access_mycqu_session.await)
.await
.unwrap();
assert!(res.iter().all(|item| item.id.is_some()));
assert!(!res.is_empty());
}
#[rstest]
#[ignore]
#[tokio::test]
async fn test_fetch_session_detail(
#[future] access_mycqu_session: Session,
shared_client: &'static crate::session::Client,
) {
{
let session = Session::new();
let res = CQUSessionInfo::fetch_detail(shared_client, &session, 1058).await;
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), ApiError::NotAccess));
}
let session_info =
CQUSessionInfo::fetch_detail(shared_client, &access_mycqu_session.await, 1058)
.await
.unwrap();
assert!(
session_info.session.id.is_some()
&& session_info.session.year == 2025
&& !session_info.session.is_autumn
&& session_info.begin_date_str == Some("2025-02-17 00:00:00".to_string())
&& session_info.end_date_str == Some("2025-09-07 00:00:00".to_string())
)
}
#[rstest]
fn test_parse_session_info_from_json() {
let json1 = json!({"id": "1045", "year": "2023", "term": '秋', "beginDate": null, "endDate": null, "active": 'Y'});
let session_info1: CQUSessionInfo = serde_json::from_value(json1).unwrap();
assert_eq!(
session_info1,
CQUSessionInfo {
active: true,
begin_date_str: None,
end_date_str: None,
session: CQUSession {
id: Some(1045),
year: 2023,
is_autumn: true
},
}
);
let json2 = json!({"id": "1046", "year": "2024", "term": '春', "beginDate": "2024-02-26", "endDate": "2024-08-25", "active": 'N'});
let session_info2: CQUSessionInfo = serde_json::from_value(json2).unwrap();
assert_eq!(
session_info2,
CQUSessionInfo {
active: false,
begin_date_str: Some("2024-02-26".to_string()),
end_date_str: Some("2024-08-25".to_string()),
session: CQUSession {
id: Some(1046),
year: 2024,
is_autumn: false
},
}
);
}
#[rstest]
#[ignore]
#[tokio::test]
async fn test_fetch_all_session_info(
#[future] access_mycqu_session: Session,
shared_client: &'static crate::session::Client,
) {
{
let session = Session::new();
let res = CQUSessionInfo::fetch_all(shared_client, &session).await;
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), ApiError::NotAccess));
}
let res = CQUSessionInfo::fetch_all(shared_client, &access_mycqu_session.await)
.await
.unwrap();
assert!(!res.is_empty());
}
#[rstest]
#[ignore]
#[tokio::test]
async fn test_fetch_curr_session_info(
#[future] access_mycqu_session: Session,
shared_client: &'static crate::session::Client,
) {
{
let session = Session::new();
let res = CQUSessionInfo::fetch_curr(shared_client, &session).await;
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), ApiError::NotAccess));
}
CQUSessionInfo::fetch_curr(shared_client, &access_mycqu_session.await)
.await
.unwrap();
}
#[fixture]
fn example_course() -> Course {
Course {
code: Some("MT80007".to_string()),
course_num: Some("000557-045".to_string()),
credit: Some(0.0),
dept: Some("马克思主义学院".to_string()),
instructor: Some("李颖-30922[主讲];".to_string()),
name: Some("形势与政策7".to_string()),
session: None,
}
}
#[rstest]
fn test_parse_course(example_course: Course) {
let json_value: Value = serde_json::from_str(include_str!("course_timetable.json")).unwrap();
let course: Course = serde_json::from_value(json_value).unwrap();
assert_eq!(course, example_course);
}
#[rstest]
fn test_parse_course_day_time() {
let json_value: Value = serde_json::from_str(include_str!("course_timetable.json")).unwrap();
let course_day_time: CourseDayTime = serde_json::from_value(json_value).unwrap();
assert_eq!(
course_day_time,
CourseDayTime {
weekday: 4,
period: Period { start: 3, end: 4 },
}
)
}
#[rstest]
fn test_parse_course_day_time_prefers_raw_fields_and_consumes_formatted_values() {
let course_day_time: CourseDayTime = serde_json::from_value(json!({
"weekDay": 4,
"weekDayFormat": "星期五",
"period": [3, 4],
"periodFormat": "3-4节",
}))
.unwrap();
assert_eq!(
course_day_time,
CourseDayTime {
weekday: 4,
period: Period { start: 3, end: 4 },
}
);
}
#[rstest]
fn test_parse_course_day_time_accepts_null_formatted_fields() {
let course_day_time: CourseDayTime = serde_json::from_value(json!({
"weekDay": 4,
"weekDayFormat": null,
"period": [3, 4],
"periodFormat": null,
}))
.unwrap();
assert_eq!(
course_day_time,
CourseDayTime {
weekday: 4,
period: Period { start: 3, end: 4 },
}
);
}
#[rstest]
fn test_parse_course_timetable(example_course: Course) {
let json_value: Value = serde_json::from_str(include_str!("course_timetable.json")).unwrap();
let course_timetable: CourseTimetable = serde_json::from_value(json_value).unwrap();
assert_eq!(
course_timetable,
CourseTimetable {
course: example_course,
stu_num: Some(117),
classroom: None,
weeks: vec![Period { start: 14, end: 17 }],
day_time: Some(CourseDayTime {
weekday: 4,
period: Period { start: 3, end: 4 },
}),
whole_week: false,
classroom_name: Some("DYC101".to_string()),
expr_projects: vec![],
}
)
}
#[rstest]
fn test_parse_course_timetable_uses_none_for_null_day_time(example_course: Course) {
let mut json_value: Value =
serde_json::from_str(include_str!("course_timetable.json")).unwrap();
let json_object = json_value.as_object_mut().unwrap();
json_object.insert("weekDay".to_string(), Value::Null);
json_object.insert("weekDayFormat".to_string(), Value::Null);
json_object.insert("period".to_string(), Value::Null);
json_object.insert("periodFormat".to_string(), Value::Null);
let course_timetable: CourseTimetable = serde_json::from_value(json_value).unwrap();
assert_eq!(
course_timetable,
CourseTimetable {
course: example_course,
stu_num: Some(117),
classroom: None,
weeks: vec![Period { start: 14, end: 17 }],
day_time: None,
whole_week: false,
classroom_name: Some("DYC101".to_string()),
expr_projects: vec![],
}
)
}
#[rstest]
#[ignore]
#[tokio::test]
async fn test_fetch_curr_timetable(
login_data: &LoginData,
#[future] access_mycqu_session: Session,
shared_client: &'static crate::session::Client,
) {
{
let session = Session::new();
let res =
CourseTimetable::fetch_curr(shared_client, &session, &login_data.student_id, 0).await;
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), ApiError::NotAccess));
}
let session = access_mycqu_session.await;
let cqu_session = CQUSessionInfo::fetch_curr(shared_client, &session)
.await
.unwrap();
println!(
"{:?}",
CourseTimetable::fetch_curr(
shared_client,
&session,
&login_data.student_id,
cqu_session.session.id.unwrap(),
)
.await
.unwrap()
);
}
#[rstest]
#[ignore]
#[tokio::test]
async fn test_fetch_enroll_timetable(
login_data: &LoginData,
#[future] access_mycqu_session: Session,
shared_client: &'static crate::session::Client,
) {
{
let session = Session::new();
let res =
CourseTimetable::fetch_enroll(shared_client, &session, &login_data.student_id).await;
assert!(res.is_err());
assert!(matches!(res.unwrap_err(), ApiError::NotAccess));
}
CourseTimetable::fetch_enroll(
shared_client,
&access_mycqu_session.await,
&login_data.student_id,
)
.await
.unwrap();
}