1use syncular_runtime::app_schema::AppSchema;
2use syncular_runtime::client::{SyncularClient, SyncularClientConfig};
3use syncular_runtime::diesel_sqlite::DieselSqliteStore;
4use syncular_runtime::error::Result;
5use syncular_runtime::transport::SyncTransport;
6
7use crate::app_server::AppTestServer;
8use crate::temp::TempDbPath;
9use crate::transport::TestTransport;
10
11#[derive(Debug, Clone)]
12pub struct AppFixtureOptions {
13 pub db_prefix: String,
14 pub base_url: String,
15 pub client_id: String,
16 pub actor_id: String,
17 pub project_id: Option<String>,
18}
19
20impl Default for AppFixtureOptions {
21 fn default() -> Self {
22 Self {
23 db_prefix: "syncular-app-test".to_string(),
24 base_url: "http://syncular.test/sync".to_string(),
25 client_id: "test-client".to_string(),
26 actor_id: "user-rust".to_string(),
27 project_id: Some("p0".to_string()),
28 }
29 }
30}
31
32pub struct AppFixture<T> {
33 db: TempDbPath,
34 pub client: SyncularClient<DieselSqliteStore, T>,
35}
36
37pub struct TestAppFixture {
38 db: TempDbPath,
39 pub client: SyncularClient<DieselSqliteStore, TestTransport>,
40 pub transport: TestTransport,
41}
42
43pub struct InMemoryAppFixture<T> {
44 pub client: SyncularClient<DieselSqliteStore, T>,
45}
46
47pub struct InMemoryTestAppFixture {
48 pub client: SyncularClient<DieselSqliteStore, TestTransport>,
49 pub transport: TestTransport,
50}
51
52impl<T> AppFixture<T> {
53 pub fn db_path(&self) -> String {
54 self.db.to_string_lossy()
55 }
56}
57
58impl TestAppFixture {
59 pub fn db_path(&self) -> String {
60 self.db.to_string_lossy()
61 }
62}
63
64pub fn open_app_client(app_schema: AppSchema) -> Result<TestAppFixture> {
65 open_app_client_with_options(app_schema, AppFixtureOptions::default())
66}
67
68pub fn open_app_client_in_memory(app_schema: AppSchema) -> Result<InMemoryTestAppFixture> {
69 let transport = TestTransport::new();
70 let store = DieselSqliteStore::open_with_schema(":memory:", app_schema)?;
71 let config = fixture_config(":memory:".to_string(), AppFixtureOptions::default());
72 let client =
73 SyncularClient::with_app_schema_parts(config, store, transport.clone(), app_schema);
74 Ok(InMemoryTestAppFixture { client, transport })
75}
76
77pub fn open_app_client_with_options(
78 app_schema: AppSchema,
79 options: AppFixtureOptions,
80) -> Result<TestAppFixture> {
81 let transport = TestTransport::new();
82 let db = TempDbPath::new(&options.db_prefix);
83 let db_path = db.to_string_lossy();
84 let store = DieselSqliteStore::open_with_schema(&db_path, app_schema)?;
85 let config = fixture_config(db_path, options);
86 let client =
87 SyncularClient::with_app_schema_parts(config, store, transport.clone(), app_schema);
88 Ok(TestAppFixture {
89 db,
90 client,
91 transport,
92 })
93}
94
95pub fn open_app_client_with_transport<T>(
96 app_schema: AppSchema,
97 transport: T,
98 options: AppFixtureOptions,
99) -> Result<AppFixture<T>>
100where
101 T: SyncTransport,
102{
103 let db = TempDbPath::new(&options.db_prefix);
104 let db_path = db.to_string_lossy();
105 let store = DieselSqliteStore::open_with_schema(&db_path, app_schema)?;
106 let config = fixture_config(db_path, options);
107 let client = SyncularClient::with_app_schema_parts(config, store, transport, app_schema);
108 Ok(AppFixture { db, client })
109}
110
111pub fn open_app_client_with_server(
112 app_schema: AppSchema,
113 server: AppTestServer,
114 options: AppFixtureOptions,
115) -> Result<AppFixture<AppTestServer>> {
116 open_app_client_with_transport(app_schema, server, options)
117}
118
119pub fn open_app_client_with_server_in_memory(
120 app_schema: AppSchema,
121 server: AppTestServer,
122 options: AppFixtureOptions,
123) -> Result<InMemoryAppFixture<AppTestServer>> {
124 open_app_client_with_transport_in_memory(app_schema, server, options)
125}
126
127pub fn open_app_client_with_transport_in_memory<T>(
128 app_schema: AppSchema,
129 transport: T,
130 options: AppFixtureOptions,
131) -> Result<InMemoryAppFixture<T>>
132where
133 T: SyncTransport,
134{
135 let db_path = ":memory:".to_string();
136 let store = DieselSqliteStore::open_with_schema(&db_path, app_schema)?;
137 let config = fixture_config(db_path, options);
138 let client = SyncularClient::with_app_schema_parts(config, store, transport, app_schema);
139 Ok(InMemoryAppFixture { client })
140}
141
142fn fixture_config(db_path: String, options: AppFixtureOptions) -> SyncularClientConfig {
143 SyncularClientConfig {
144 db_path,
145 base_url: options.base_url,
146 client_id: options.client_id,
147 actor_id: options.actor_id,
148 project_id: options.project_id,
149 }
150}