use std::net::SocketAddr;
use crate::entities::{Endpoint, Scenario};
use crate::error::HarnessError;
use crate::use_cases::ports::{Collector, Server};
pub struct ScenarioBuilder<S, C> {
server: Option<S>,
collector: Option<C>,
endpoints: Vec<Endpoint>,
}
impl ScenarioBuilder<(), ()> {
pub fn new() -> Self {
Self {
server: None,
collector: None,
endpoints: Vec::new(),
}
}
}
impl Default for ScenarioBuilder<(), ()> {
fn default() -> Self {
Self::new()
}
}
impl<S, C> ScenarioBuilder<S, C> {
pub fn server<NewS: Server>(self, server: NewS) -> ScenarioBuilder<NewS, C> {
ScenarioBuilder {
server: Some(server),
collector: self.collector,
endpoints: self.endpoints,
}
}
pub fn collector<NewC: Collector>(self, collector: NewC) -> ScenarioBuilder<S, NewC> {
ScenarioBuilder {
server: self.server,
collector: Some(collector),
endpoints: self.endpoints,
}
}
pub fn endpoint(mut self, endpoint: Endpoint) -> Self {
self.endpoints.push(endpoint);
self
}
pub fn endpoints(mut self, endpoints: impl IntoIterator<Item = Endpoint>) -> Self {
self.endpoints.extend(endpoints);
self
}
}
impl<S: Server + 'static, C: Collector + 'static> ScenarioBuilder<S, C> {
pub fn build(self) -> Scenario<S, C> {
Scenario {
server: self.server.expect("Server must be set before building"),
collector: self.collector.expect("Collector must be set before building"),
endpoints: self.endpoints,
}
}
pub async fn execute(self) -> Result<C::Output, HarnessError> {
let scenario = self.build();
scenario
.server
.run(scenario.endpoints, scenario.collector, None::<fn(SocketAddr)>)
.await
}
}
impl<S: Server + 'static, C: Collector + 'static> Scenario<S, C> {
pub async fn execute(self) -> Result<C::Output, HarnessError> {
self.server
.run(self.endpoints, self.collector, None::<fn(SocketAddr)>)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::entities::Method;
#[test]
fn test_scenario_builder() {
let _builder = ScenarioBuilder::new();
}
#[test]
fn test_scenario_builder_with_endpoint() {
let _builder = ScenarioBuilder::new().endpoint(Endpoint::new("/api/test", Method::Get));
}
#[test]
fn test_scenario_builder_with_multiple_endpoints() {
let _builder = ScenarioBuilder::new()
.endpoint(Endpoint::new("/api/users", Method::Get))
.endpoint(Endpoint::new("/api/posts", Method::Get));
}
}