1#[derive(Clone, Eq, PartialEq, Debug, darling::FromMeta)]
17#[darling(rename_all = "snake_case")]
18pub enum Backend {
19 Node(Node),
22
23 #[cfg(any(test, feature = "sandbox"))]
28 RuntimeOnly(RuntimeOnly),
29}
30
31impl Default for Backend {
32 fn default() -> Self {
33 Backend::Node(Node::Auto)
34 }
35}
36
37#[derive(Clone, Eq, PartialEq, Debug, darling::FromMeta)]
40pub enum Node {
41 #[darling(word)]
43 #[darling(skip)]
44 Auto,
45 Url(String),
47}
48
49impl Node {
50 pub fn url(&self) -> Option<String> {
55 std::env::var("CONTRACTS_NODE_URL").ok().or_else(|| {
56 match self {
57 Node::Auto => None,
58 Node::Url(url) => Some(url.clone()),
59 }
60 })
61 }
62}
63
64#[cfg(any(test, feature = "sandbox"))]
66#[derive(Clone, Eq, PartialEq, Debug, darling::FromMeta)]
67pub enum RuntimeOnly {
68 #[darling(word)]
69 #[darling(skip)]
70 Default,
71 Sandbox(syn::Path),
72}
73
74#[cfg(any(test, feature = "sandbox"))]
75impl From<RuntimeOnly> for syn::Path {
76 fn from(value: RuntimeOnly) -> Self {
77 match value {
78 RuntimeOnly::Default => syn::parse_quote! { ::ink_e2e::DefaultSandbox },
79 RuntimeOnly::Sandbox(path) => path,
80 }
81 }
82}
83
84#[derive(Debug, Default, PartialEq, Eq, darling::FromMeta)]
86pub struct E2EConfig {
87 #[darling(default)]
94 environment: Option<syn::Path>,
95 #[darling(default)]
97 backend: Backend,
98}
99
100impl E2EConfig {
101 pub fn environment(&self) -> Option<syn::Path> {
103 self.environment.clone()
104 }
105
106 pub fn backend(&self) -> Backend {
108 self.backend.clone()
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use darling::{
116 ast::NestedMeta,
117 FromMeta,
118 };
119 use quote::quote;
120
121 #[test]
122 fn config_works_backend_runtime_only() {
123 let input = quote! {
124 environment = crate::CustomEnvironment,
125 backend(runtime_only),
126 };
127 let config =
128 E2EConfig::from_list(&NestedMeta::parse_meta_list(input).unwrap()).unwrap();
129
130 assert_eq!(
131 config.environment(),
132 Some(syn::parse_quote! { crate::CustomEnvironment })
133 );
134
135 assert_eq!(config.backend(), Backend::RuntimeOnly(RuntimeOnly::Default));
136 }
137
138 #[test]
139 #[should_panic(expected = "ErrorUnknownField")]
140 fn config_backend_runtime_only_default_not_allowed() {
141 let input = quote! {
142 backend(runtime_only(default)),
143 };
144 let config =
145 E2EConfig::from_list(&NestedMeta::parse_meta_list(input).unwrap()).unwrap();
146
147 assert_eq!(config.backend(), Backend::RuntimeOnly(RuntimeOnly::Default));
148 }
149
150 #[test]
151 fn config_works_runtime_only_with_custom_backend() {
152 let input = quote! {
153 backend(runtime_only(sandbox = ::ink_e2e::DefaultSandbox)),
154 };
155 let config =
156 E2EConfig::from_list(&NestedMeta::parse_meta_list(input).unwrap()).unwrap();
157
158 assert_eq!(
159 config.backend(),
160 Backend::RuntimeOnly(RuntimeOnly::Sandbox(
161 syn::parse_quote! { ::ink_e2e::DefaultSandbox }
162 ))
163 );
164 }
165
166 #[test]
167 fn config_works_backend_node() {
168 let input = quote! {
169 backend(node),
170 };
171 let config =
172 E2EConfig::from_list(&NestedMeta::parse_meta_list(input).unwrap()).unwrap();
173
174 assert_eq!(config.backend(), Backend::Node(Node::Auto));
175
176 match config.backend() {
177 Backend::Node(node_config) => {
178 assert_eq!(node_config, Node::Auto);
179
180 temp_env::with_vars([("CONTRACTS_NODE_URL", None::<&str>)], || {
181 assert_eq!(node_config.url(), None);
182 });
183
184 temp_env::with_vars(
185 [("CONTRACTS_NODE_URL", Some("ws://127.0.0.1:9000"))],
186 || {
187 assert_eq!(
188 node_config.url(),
189 Some(String::from("ws://127.0.0.1:9000"))
190 );
191 },
192 );
193 }
194 _ => panic!("Expected Backend::Node"),
195 }
196 }
197
198 #[test]
199 #[should_panic(expected = "ErrorUnknownField")]
200 fn config_backend_node_auto_not_allowed() {
201 let input = quote! {
202 backend(node(auto)),
203 };
204 let config =
205 E2EConfig::from_list(&NestedMeta::parse_meta_list(input).unwrap()).unwrap();
206
207 assert_eq!(config.backend(), Backend::Node(Node::Auto));
208 }
209
210 #[test]
211 fn config_works_backend_node_url() {
212 let input = quote! {
213 backend(node(url = "ws://0.0.0.0:9999")),
214 };
215 let config =
216 E2EConfig::from_list(&NestedMeta::parse_meta_list(input).unwrap()).unwrap();
217
218 match config.backend() {
219 Backend::Node(node_config) => {
220 assert_eq!(node_config, Node::Url("ws://0.0.0.0:9999".to_owned()));
221
222 temp_env::with_vars([("CONTRACTS_NODE_URL", None::<&str>)], || {
223 assert_eq!(node_config.url(), Some("ws://0.0.0.0:9999".to_owned()));
224 });
225
226 temp_env::with_vars(
227 [("CONTRACTS_NODE_URL", Some("ws://127.0.0.1:9000"))],
228 || {
229 assert_eq!(
230 node_config.url(),
231 Some(String::from("ws://127.0.0.1:9000"))
232 );
233 },
234 );
235 }
236 _ => panic!("Expected Backend::Node"),
237 }
238 }
239}