#[cfg(test)]
mod tests {
use crate::common::error::JwtError;
use crate::common::token::TokenParser;
use base64::Engine;
use jsonwebtoken::{Algorithm, DecodingKey, Validation};
fn create_test_token(header: &str, payload: &str, signature: &str) -> String {
format!("{}.{}.{}", header, payload, signature)
}
fn base64_encode(data: &str) -> String {
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(data)
}
#[test]
fn test_parse_token_header_valid() {
let header = base64_encode(r#"{"alg":"RS256","kid":"test-key-id","typ":"JWT"}"#);
let token = create_test_token(&header, "payload", "signature");
let result = TokenParser::parse_token_header(&token);
assert!(result.is_ok());
let header = result.unwrap();
assert_eq!(header.alg, "RS256");
assert_eq!(header.kid, "test-key-id");
assert_eq!(header.token_type, Some("JWT".to_string()));
}
#[test]
fn test_parse_token_header_empty_token() {
let result = TokenParser::parse_token_header("");
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::MissingToken));
}
#[test]
fn test_parse_token_header_invalid_format() {
let result = TokenParser::parse_token_header("header");
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
let result = TokenParser::parse_token_header("header.payload");
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
}
#[test]
fn test_parse_token_header_invalid_base64() {
let token = create_test_token("invalid!base64", "payload", "signature");
let result = TokenParser::parse_token_header(&token);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
}
#[test]
fn test_parse_token_header_invalid_json() {
let header = base64_encode("not json");
let token = create_test_token(&header, "payload", "signature");
let result = TokenParser::parse_token_header(&token);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
}
#[test]
fn test_parse_token_header_missing_kid() {
let header = base64_encode(r#"{"alg":"RS256"}"#);
let token = create_test_token(&header, "payload", "signature");
let result = TokenParser::parse_token_header(&token);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
}
#[test]
fn test_parse_token_header_unsupported_algorithm() {
let header = base64_encode(r#"{"alg":"HS256","kid":"test-key-id"}"#);
let token = create_test_token(&header, "payload", "signature");
let result = TokenParser::parse_token_header(&token);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::InvalidClaim { .. }));
}
#[test]
fn test_parse_token_claims_valid() {
let header = base64_encode(r#"{"alg":"RS256","kid":"test-key-id"}"#);
let payload = base64_encode(
r#"{"sub":"user123","iss":"https://example.com","exp":4070908800,"iat":1609459200,"client_id":"client123","token_use":"id"}"#,
);
let token = create_test_token(&header, &payload, "signature");
let key = DecodingKey::from_secret(b"test-secret");
let mut validation = Validation::new(Algorithm::RS256);
validation.validate_exp = false; validation.insecure_disable_signature_validation();
#[derive(serde::Deserialize, Debug)]
struct TestClaims {
sub: String,
iss: String,
exp: u64,
iat: u64,
client_id: String,
token_use: String,
}
let result = TokenParser::parse_token_claims::<TestClaims>(&token, &key, &validation);
assert!(result.is_ok());
let claims = result.unwrap();
assert_eq!(claims.sub, "user123");
assert_eq!(claims.iss, "https://example.com");
assert_eq!(claims.exp, 4070908800); assert_eq!(claims.iat, 1609459200); assert_eq!(claims.client_id, "client123");
assert_eq!(claims.token_use, "id");
}
#[test]
fn test_parse_token_claims_empty_token() {
let key = DecodingKey::from_secret(b"test-secret");
let validation = Validation::new(Algorithm::RS256);
#[derive(serde::Deserialize, Debug)]
struct TestClaims {}
let result = TokenParser::parse_token_claims::<TestClaims>("", &key, &validation);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::MissingToken));
}
#[test]
fn test_parse_token_claims_invalid_format() {
let key = DecodingKey::from_secret(b"test-secret");
let validation = Validation::new(Algorithm::RS256);
#[derive(serde::Deserialize, Debug)]
struct TestClaims {}
let result = TokenParser::parse_token_claims::<TestClaims>("header", &key, &validation);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
let result =
TokenParser::parse_token_claims::<TestClaims>("header.payload", &key, &validation);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
}
#[test]
fn test_extract_claim_from_token() {
let header = base64_encode(r#"{"alg":"RS256","kid":"test-key-id"}"#);
let payload = base64_encode(
r#"{"sub":"user123","iss":"https://example.com","exp":4070908800,"iat":1609459200,"client_id":"client123","token_use":"id"}"#,
);
let token = create_test_token(&header, &payload, "signature");
let sub: String = TokenParser::extract_claim_from_token(&token, "sub").unwrap();
assert_eq!(sub, "user123");
let exp: u64 = TokenParser::extract_claim_from_token(&token, "exp").unwrap();
assert_eq!(exp, 4070908800);
let result = TokenParser::extract_claim_from_token::<String>(&token, "non_existent");
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), JwtError::ParseError { .. }));
}
}