Add minimal test for basic hackathon operations and enhance test utilities

- Introduced a new test module for hackathon-related functionality.
- Implemented a basic test for creating a hackathon using a mock repository.
- Enhanced the test utilities in `lib.rs` for better request handling and response extraction.
- Added a `ServiceClient` struct to facilitate HTTP requests in tests.
- Created a `RequestBuilder` to streamline building and sending requests with headers and JSON bodies.
This commit is contained in:
MythEclipse
2025-10-11 10:58:51 +07:00
parent 466ba3391a
commit c10443f881
33 changed files with 4547 additions and 4082 deletions
+2 -8
View File
@@ -146,14 +146,8 @@ fn is_jwt(token: &str) -> bool {
/// Async version of extract_email_token that can handle Google access tokens
pub async fn extract_email_token_async(token: String) -> Option<String> {
if is_jwt(&token) {
match decode_access_token(&token) {
Ok(data) => {
return Some(data.claims.sub);
}
Err(_) => {
}
}
if is_jwt(&token) && let Ok(data) = decode_access_token(&token) {
return Some(data.claims.sub);
}
// If it's not a valid internal JWT, try to validate as Google access token
+11 -13
View File
@@ -70,23 +70,21 @@ impl ListQueryBuilder {
}
pub fn with_search(mut self, search: Option<&str>, field: &str) -> Self {
if let Some(search) = search {
if !search.is_empty() {
self.conditions.push(format!(
"string::contains(string::lowercase({field} ?? ''), string::lowercase($search))"
));
}
if let Some(search) = search
&& !search.is_empty() {
self.conditions.push(format!(
"string::contains(string::lowercase({field} ?? ''), string::lowercase($search))"
));
}
self
}
pub fn with_filter(mut self, field: Option<&str>, value: Option<&str>) -> Self {
if let (Some(f), Some(v)) = (field, value) {
if !v.is_empty() {
self.conditions.push(format!(
"string::contains(string::join('', [{f}]), $filter)"
));
}
if let (Some(f), Some(v)) = (field, value)
&& !v.is_empty() {
self.conditions.push(format!(
"string::contains(string::join('', [{f}]), $filter)"
));
}
self
}
@@ -340,7 +338,7 @@ pub async fn execute_safe_count_query(
// Extract the count from the result
let response: Vec<surrealdb::Value> = result.take(0)?;
let count = response.get(0).and_then(|v| v.to_string().parse::<u64>().ok())
let count = response.first().and_then(|v| v.to_string().parse::<u64>().ok())
.ok_or_else(|| anyhow::anyhow!("No count found in response"))?;
Ok(count)
+3 -4
View File
@@ -101,10 +101,9 @@ impl<'a> QueryListBuilder<'a> {
// Bind parameters for both data and count queries.
// It's assumed that the parameters are named consistently and applied to both.
// The ListQueryBuilder already uses $search, $per_page, $start, $filter.
if let Some(search) = &self.meta.search {
if !search.is_empty() {
query_exec = query_exec.bind(("search", search.to_lowercase()));
}
if let Some(search) = &self.meta.search
&& !search.is_empty() {
query_exec = query_exec.bind(("search", search.to_lowercase()));
}
if let Some(filter_val) = &self.meta.filter {
query_exec = crate::bind_filter_value(query_exec, filter_val.clone());
+10 -16
View File
@@ -13,14 +13,11 @@ where
let v = Value::deserialize(deserializer)?;
match &v {
Value::Object(map) => {
if let Some(id_val) = map.get("Id") {
if let Value::Object(id_map) = id_val {
if let Some(Value::String(s)) = id_map.get("String") {
return Thing::from_str(s).map_err(|e| {
de::Error::custom(format!("Thing::from_str error: {e:?}"))
});
}
}
if let Some(Value::Object(id_map)) = map.get("Id")
&& let Some(Value::String(s)) = id_map.get("String") {
return Thing::from_str(s).map_err(|e| {
de::Error::custom(format!("Thing::from_str error: {e:?}"))
});
}
serde_json::from_value(v).map_err(de::Error::custom)
}
@@ -49,14 +46,11 @@ where
match &v {
Value::Null => Ok(None),
Value::Object(map) => {
if let Some(id_val) = map.get("Id") {
if let Value::Object(id_map) = id_val {
if let Some(Value::String(s)) = id_map.get("String") {
return Ok(Some(Thing::from_str(s).map_err(|e| {
de::Error::custom(format!("Thing::from_str error: {e:?}"))
})?));
}
}
if let Some(Value::Object(id_map)) = map.get("Id")
&& let Some(Value::String(s)) = id_map.get("String") {
return Ok(Some(Thing::from_str(s).map_err(|e| {
de::Error::custom(format!("Thing::from_str error: {e:?}"))
})?));
}
Ok(Some(serde_json::from_value(v).map_err(de::Error::custom)?))
}