test: unit tests for OAuthFlow::DeviceCode and merge behavior
Adds 9 unit tests covering: - yaml deserialization of flow: device_code - merge preserves base device_authorization_url when user omits - merge lets user device_authorization_url win - merge lets user use_pkce_in_device_flow win - OpenAICompatibleOAuthProvider exposes / defaults both new trait methods - Full serde roundtrip of a realistic device_code yaml block No network or polling — pure config/serde logic tests. Brings the test count from 1134 to 1143.
This commit is contained in:
@@ -1126,4 +1126,133 @@ echo_pkce_in_token_exchange: true
|
|||||||
assert!(provider.uses_localhost_redirect());
|
assert!(provider.uses_localhost_redirect());
|
||||||
assert!(provider.fixed_redirect_uri().is_none());
|
assert!(provider.fixed_redirect_uri().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn oauth_flow_device_code_parses() {
|
||||||
|
let yaml = "client_id: x\ntoken_url: y\nflow: device_code";
|
||||||
|
|
||||||
|
let cfg: OAuthConfig = serde_yaml::from_str(yaml).unwrap();
|
||||||
|
|
||||||
|
assert!(matches!(cfg.flow, OAuthFlow::DeviceCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn oauth_config_merge_preserves_device_authorization_url_when_user_omits() {
|
||||||
|
let mut base = base_config();
|
||||||
|
base.device_authorization_url = Some("https://base.example/device".into());
|
||||||
|
let user = empty_user_override("user-id", "https://user.example/token");
|
||||||
|
|
||||||
|
let merged = base.merge(user);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
merged.device_authorization_url.as_deref(),
|
||||||
|
Some("https://base.example/device")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn oauth_config_merge_user_device_authorization_url_wins() {
|
||||||
|
let mut base = base_config();
|
||||||
|
base.device_authorization_url = Some("https://base.example/device".into());
|
||||||
|
let mut user = empty_user_override("user-id", "https://user.example/token");
|
||||||
|
user.device_authorization_url = Some("https://user.example/device".into());
|
||||||
|
|
||||||
|
let merged = base.merge(user);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
merged.device_authorization_url.as_deref(),
|
||||||
|
Some("https://user.example/device")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn oauth_config_merge_user_pkce_in_device_flow_wins() {
|
||||||
|
let base = base_config();
|
||||||
|
let mut user = empty_user_override("user-id", "https://user.example/token");
|
||||||
|
user.use_pkce_in_device_flow = true;
|
||||||
|
|
||||||
|
let merged = base.merge(user);
|
||||||
|
|
||||||
|
assert!(merged.use_pkce_in_device_flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn openai_compatible_provider_exposes_device_authorization_url() {
|
||||||
|
let mut cfg = base_config();
|
||||||
|
cfg.device_authorization_url = Some("https://example/device".into());
|
||||||
|
|
||||||
|
let provider = OpenAICompatibleOAuthProvider {
|
||||||
|
config: cfg,
|
||||||
|
client_name: "test".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
provider.device_authorization_url(),
|
||||||
|
Some("https://example/device")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn openai_compatible_provider_device_authorization_url_none_when_unset() {
|
||||||
|
let provider = OpenAICompatibleOAuthProvider {
|
||||||
|
config: base_config(),
|
||||||
|
client_name: "test".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(provider.device_authorization_url().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn openai_compatible_provider_use_pkce_in_device_flow_defaults_false() {
|
||||||
|
let provider = OpenAICompatibleOAuthProvider {
|
||||||
|
config: base_config(),
|
||||||
|
client_name: "test".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!provider.use_pkce_in_device_flow());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn openai_compatible_provider_use_pkce_in_device_flow_returns_true_when_set() {
|
||||||
|
let mut cfg = base_config();
|
||||||
|
cfg.use_pkce_in_device_flow = true;
|
||||||
|
|
||||||
|
let provider = OpenAICompatibleOAuthProvider {
|
||||||
|
config: cfg,
|
||||||
|
client_name: "test".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(provider.use_pkce_in_device_flow());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn oauth_config_serde_roundtrip_device_code_yaml() {
|
||||||
|
let yaml = r#"
|
||||||
|
client_id: my-client
|
||||||
|
token_url: https://auth.example/oauth/token
|
||||||
|
device_authorization_url: https://auth.example/oauth/device_authorization
|
||||||
|
flow: device_code
|
||||||
|
token_request_format: form_url_encoded
|
||||||
|
use_pkce_in_device_flow: true
|
||||||
|
scopes:
|
||||||
|
- read
|
||||||
|
- write
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let cfg: OAuthConfig = serde_yaml::from_str(yaml).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(cfg.client_id, "my-client");
|
||||||
|
assert_eq!(cfg.token_url, "https://auth.example/oauth/token");
|
||||||
|
assert_eq!(
|
||||||
|
cfg.device_authorization_url.as_deref(),
|
||||||
|
Some("https://auth.example/oauth/device_authorization")
|
||||||
|
);
|
||||||
|
assert!(matches!(cfg.flow, OAuthFlow::DeviceCode));
|
||||||
|
assert!(matches!(
|
||||||
|
cfg.token_request_format,
|
||||||
|
Some(TokenRequestFormat::FormUrlEncoded)
|
||||||
|
));
|
||||||
|
assert!(cfg.use_pkce_in_device_flow);
|
||||||
|
assert_eq!(cfg.scopes, vec!["read", "write"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user