KeiSeiKit-1.0/_primitives/_rust/kei-auth-google/tests/google_smoke.rs
Parfii-bot 0be354a920 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

153 lines
5.2 KiB
Rust

// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 <author org>
//!
//! Wiremock smoke tests for `kei-auth-google`. No live HTTP — every
//! assertion is local to the test process.
use kei_auth_google::{GoogleAuthClient, GoogleAuthProvider};
use kei_runtime_core::traits::auth::{AuthChallenge, AuthProvider};
use serde_json::json;
use wiremock::matchers::{body_string_contains, header, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
fn client_for(server: &MockServer) -> GoogleAuthClient {
GoogleAuthClient::with_urls(
format!("{}/token", server.uri()),
format!("{}/userinfo", server.uri()),
"client-id-xyz",
"client-secret-xyz",
"https://example.com/cb",
)
.unwrap()
}
#[tokio::test]
async fn token_endpoint_200_returns_access_token() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/token"))
.and(body_string_contains("grant_type=authorization_code"))
.and(body_string_contains("code=abc123"))
.and(body_string_contains("client_id=client-id-xyz"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"access_token": "ya29.a0AfH-test",
"expires_in": 3600,
"id_token": "eyJ.fake.jwt"
})))
.expect(1)
.mount(&server)
.await;
let client = client_for(&server);
let token = client.exchange_code("abc123").await.unwrap();
assert_eq!(token.access_token, "ya29.a0AfH-test");
assert_eq!(token.expires_in, 3600);
assert_eq!(token.id_token.as_deref(), Some("eyJ.fake.jwt"));
}
#[tokio::test]
async fn userinfo_200_returns_email_and_sub() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/userinfo"))
.and(header("authorization", "Bearer ya29.a0AfH-test"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"sub": "1234567890",
"email": "alice@example.com",
"name": "Alice"
})))
.expect(1)
.mount(&server)
.await;
let client = client_for(&server);
let info = client.userinfo("ya29.a0AfH-test").await.unwrap();
assert_eq!(info.sub, "1234567890");
assert_eq!(info.email, "alice@example.com");
assert_eq!(info.name, "Alice");
}
#[tokio::test]
async fn verify_end_to_end_builds_auth_session() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/token"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"access_token": "tok",
"expires_in": 1800,
"id_token": null
})))
.expect(1)
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/userinfo"))
.and(header("authorization", "Bearer tok"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"sub": "999",
"email": "bob@example.com",
"name": "Bob"
})))
.expect(1)
.mount(&server)
.await;
let client = client_for(&server);
let provider = GoogleAuthProvider::new(client, None).unwrap();
let challenge = AuthChallenge::OAuthCode {
provider: "google".into(),
code: "code-xyz".into(),
state: "csrf-state-xyz".into(),
};
let session = provider.verify(&challenge).await.unwrap();
assert_eq!(session.user_id, "bob@example.com");
assert_eq!(session.dna.role(), "session");
assert!(session.dna.caps().contains("UI"));
assert_eq!(session.parent_dna.role(), "primitive");
assert!(session.parent_dna.caps().contains("GO"));
assert!(session.expires_unix_ms > 0);
}
#[tokio::test]
async fn exchange_code_400_returns_api_error() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/token"))
.respond_with(ResponseTemplate::new(400).set_body_json(json!({
"error": "invalid_grant",
"error_description": "Bad code"
})))
.expect(1)
.mount(&server)
.await;
let client = client_for(&server);
let err = client.exchange_code("bad-code").await.unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("api"), "expected api variant, got {msg}");
assert!(msg.contains("400"), "expected status 400 in message, got {msg}");
}
#[tokio::test]
async fn issue_challenge_rejects_non_oauth() {
let client = GoogleAuthClient::with_urls(
"http://t/x", "http://u/x", "cid", "secret", "http://r/cb",
).unwrap();
let provider = GoogleAuthProvider::new(client, None).unwrap();
let challenge = AuthChallenge::MagicLink { email: "a@b.c".into() };
assert!(provider.issue_challenge(&challenge).await.is_err());
}
#[tokio::test]
async fn verify_rejects_wrong_provider() {
let client = GoogleAuthClient::with_urls(
"http://t/x", "http://u/x", "cid", "secret", "http://r/cb",
).unwrap();
let provider = GoogleAuthProvider::new(client, None).unwrap();
let challenge = AuthChallenge::OAuthCode {
provider: "github".into(),
code: "x".into(),
state: "y".into(),
};
assert!(provider.verify(&challenge).await.is_err());
}