Skip to main content

cloud_sdk_testkit/
response.rs

1//! Deterministic response fixture builders.
2
3use cloud_sdk::transport::StatusCode;
4
5use crate::{ActionFixture, FixtureBody, PaginationFixture, RateLimitFixture};
6
7/// Fixture response category.
8#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9pub enum FixtureKind {
10    /// Successful response without additional metadata.
11    Success,
12    /// Successful paginated response.
13    Pagination,
14    /// Action polling response.
15    Action,
16    /// Rate-limit response.
17    RateLimit,
18    /// Client or server error response.
19    Error,
20}
21
22/// Response fixture construction error.
23#[derive(Clone, Copy, Debug, Eq, PartialEq)]
24pub enum ResponseFixtureError {
25    /// Error fixtures require a `4xx` or `5xx` status.
26    NonErrorStatus,
27}
28
29/// Provider-neutral response body plus optional interpreted metadata.
30#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31pub struct ResponseFixture<'a> {
32    kind: FixtureKind,
33    status: StatusCode,
34    body: FixtureBody<'a>,
35    pagination: Option<PaginationFixture>,
36    action: Option<ActionFixture>,
37    rate_limit: Option<RateLimitFixture>,
38}
39
40impl<'a> ResponseFixture<'a> {
41    /// Creates a `200 OK` response.
42    #[must_use]
43    pub const fn success(body: FixtureBody<'a>) -> Self {
44        Self::new(FixtureKind::Success, StatusCode::OK, body)
45    }
46
47    /// Creates a `200 OK` paginated response.
48    #[must_use]
49    pub const fn paginated(body: FixtureBody<'a>, pagination: PaginationFixture) -> Self {
50        let mut fixture = Self::new(FixtureKind::Pagination, StatusCode::OK, body);
51        fixture.pagination = Some(pagination);
52        fixture
53    }
54
55    /// Creates a `200 OK` action response.
56    #[must_use]
57    pub const fn action(body: FixtureBody<'a>, action: ActionFixture) -> Self {
58        let mut fixture = Self::new(FixtureKind::Action, StatusCode::OK, body);
59        fixture.action = Some(action);
60        fixture
61    }
62
63    /// Creates a `429 Too Many Requests` response.
64    #[must_use]
65    pub const fn rate_limited(body: FixtureBody<'a>, rate_limit: RateLimitFixture) -> Self {
66        let mut fixture = Self::new(FixtureKind::RateLimit, StatusCode::TOO_MANY_REQUESTS, body);
67        fixture.rate_limit = Some(rate_limit);
68        fixture
69    }
70
71    /// Adds rate-limit metadata to any response fixture.
72    #[must_use]
73    pub const fn with_rate_limit(mut self, rate_limit: RateLimitFixture) -> Self {
74        self.rate_limit = Some(rate_limit);
75        self
76    }
77
78    /// Creates a client or server error response.
79    pub const fn error(
80        status: StatusCode,
81        body: FixtureBody<'a>,
82    ) -> Result<Self, ResponseFixtureError> {
83        if !status.is_error() {
84            return Err(ResponseFixtureError::NonErrorStatus);
85        }
86        Ok(Self::new(FixtureKind::Error, status, body))
87    }
88
89    const fn new(kind: FixtureKind, status: StatusCode, body: FixtureBody<'a>) -> Self {
90        Self {
91            kind,
92            status,
93            body,
94            pagination: None,
95            action: None,
96            rate_limit: None,
97        }
98    }
99
100    /// Returns the fixture category.
101    #[must_use]
102    pub const fn kind(self) -> FixtureKind {
103        self.kind
104    }
105
106    /// Returns the response status.
107    #[must_use]
108    pub const fn status(self) -> StatusCode {
109        self.status
110    }
111
112    /// Returns the response body source.
113    #[must_use]
114    pub const fn body(self) -> FixtureBody<'a> {
115        self.body
116    }
117
118    /// Returns pagination metadata when present.
119    #[must_use]
120    pub const fn pagination(self) -> Option<PaginationFixture> {
121        self.pagination
122    }
123
124    /// Returns action metadata when present.
125    #[must_use]
126    pub const fn action_metadata(self) -> Option<ActionFixture> {
127        self.action
128    }
129
130    /// Returns rate-limit metadata when present.
131    #[must_use]
132    pub const fn rate_limit(self) -> Option<RateLimitFixture> {
133        self.rate_limit
134    }
135}