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:
2026-07-20 15:25:24 -06:00
parent f2a0e7453e
commit 5a5da90734
+129
View File
@@ -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"]);
}
} }