11//! Integration tests for `trogon_nats::connect` — requires Docker (testcontainers starts NATS).
2+ //!
3+ //! Tests that need Docker are marked `#[ignore]` and only run when explicitly
4+ //! requested:
5+ //!
6+ //! ```sh
7+ //! cargo test -p trogon-nats -- --ignored
8+ //! ```
29
310use std:: time:: Duration ;
411use testcontainers_modules:: nats:: Nats ;
12+ use testcontainers_modules:: testcontainers:: ContainerAsync ;
513use testcontainers_modules:: testcontainers:: ImageExt ;
614use testcontainers_modules:: testcontainers:: runners:: AsyncRunner ;
715use trogon_nats:: auth:: { NatsAuth , NatsConfig } ;
816use trogon_nats:: connect:: { ConnectError , connect} ;
917
10- async fn start_nats ( ) -> (
11- testcontainers_modules:: testcontainers:: ContainerAsync < Nats > ,
12- u16 ,
13- ) {
14- let container = Nats :: default ( )
15- . start ( )
16- . await
17- . expect ( "Failed to start NATS container — is Docker running?" ) ;
18- let port = container. get_host_port_ipv4 ( 4222 ) . await . unwrap ( ) ;
19- ( container, port)
18+ async fn start_nats ( ) -> Result < ( ContainerAsync < Nats > , u16 ) , Box < dyn std:: error:: Error > > {
19+ let container = Nats :: default ( ) . start ( ) . await ?;
20+ let port = container. get_host_port_ipv4 ( 4222 ) . await ?;
21+ Ok ( ( container, port) )
2022}
2123
2224/// Covers the `NatsAuth::None` arm (lines 123-128) and the success branch (130-138).
2325/// Also exercises `apply_reconnect_options` (lines 69-74) indirectly.
2426#[ tokio:: test]
25- async fn connect_with_no_auth_succeeds ( ) {
26- let ( _container, port) = start_nats ( ) . await ;
27+ #[ ignore = "requires Docker" ]
28+ async fn connect_with_no_auth_succeeds ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
29+ let ( _container, port) = start_nats ( ) . await ?;
2730
2831 let config = NatsConfig :: new ( vec ! [ format!( "nats://127.0.0.1:{port}" ) ] , NatsAuth :: None ) ;
2932
30- let _client = connect ( & config, Duration :: from_secs ( 10 ) )
33+ connect ( & config, Duration :: from_secs ( 10 ) )
3134 . await
3235 . expect ( "connect() should succeed with a running NATS server" ) ;
33- // client drops here → connection closes
36+ Ok ( ( ) )
3437}
3538
3639/// Covers the `NatsAuth::Token` arm (lines 115-122).
3740#[ tokio:: test]
38- async fn connect_with_token_auth_succeeds_on_open_server ( ) {
41+ #[ ignore = "requires Docker" ]
42+ async fn connect_with_token_auth_succeeds_on_open_server ( ) -> Result < ( ) , Box < dyn std:: error:: Error > >
43+ {
3944 // An open NATS server accepts any token — the token is just passed through.
40- let ( _container, port) = start_nats ( ) . await ;
45+ let ( _container, port) = start_nats ( ) . await ? ;
4146
4247 let config = NatsConfig :: new (
4348 vec ! [ format!( "nats://127.0.0.1:{port}" ) ] ,
4449 NatsAuth :: Token ( "any-token" . to_string ( ) ) ,
4550 ) ;
4651
47- let _client = connect ( & config, Duration :: from_secs ( 10 ) )
52+ connect ( & config, Duration :: from_secs ( 10 ) )
4853 . await
4954 . expect ( "open NATS server should accept connections regardless of token" ) ;
55+ Ok ( ( ) )
5056}
5157
5258/// Covers the `NatsAuth::UserPassword` arm (lines 107-114).
5359#[ tokio:: test]
54- async fn connect_with_user_password_succeeds_on_open_server ( ) {
55- let ( _container, port) = start_nats ( ) . await ;
60+ #[ ignore = "requires Docker" ]
61+ async fn connect_with_user_password_succeeds_on_open_server (
62+ ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
63+ let ( _container, port) = start_nats ( ) . await ?;
5664
5765 let config = NatsConfig :: new (
5866 vec ! [ format!( "nats://127.0.0.1:{port}" ) ] ,
@@ -62,9 +70,10 @@ async fn connect_with_user_password_succeeds_on_open_server() {
6270 } ,
6371 ) ;
6472
65- let _client = connect ( & config, Duration :: from_secs ( 10 ) )
73+ connect ( & config, Duration :: from_secs ( 10 ) )
6674 . await
6775 . expect ( "open NATS server should accept user/password connections" ) ;
76+ Ok ( ( ) )
6877}
6978
7079/// Covers the `NatsAuth::NKey` arm (lines 101-106).
@@ -73,8 +82,9 @@ async fn connect_with_user_password_succeeds_on_open_server() {
7382/// An open NATS server (no `authorization` config) does not enforce auth and
7483/// accepts the connection regardless of which key is presented.
7584#[ tokio:: test]
76- async fn connect_with_nkey_auth_on_open_server ( ) {
77- let ( _container, port) = start_nats ( ) . await ;
85+ #[ ignore = "requires Docker" ]
86+ async fn connect_with_nkey_auth_on_open_server ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
87+ let ( _container, port) = start_nats ( ) . await ?;
7888
7989 // A valid NKey user seed (base32-encoded, 58-char canonical format).
8090 // On an open server the key is not validated — the test simply exercises
@@ -92,6 +102,7 @@ async fn connect_with_nkey_auth_on_open_server() {
92102 "NKey connect should succeed on an open NATS server: {:?}" ,
93103 result
94104 ) ;
105+ Ok ( ( ) )
95106}
96107
97108/// Covers the `NatsAuth::Credentials` arm — specifically the `InvalidCredentials`
@@ -116,13 +127,14 @@ async fn connect_with_missing_credentials_file_returns_invalid_credentials() {
116127/// Wrong token against an auth-enabled NATS server must return
117128/// `ConnectError::AuthorizationViolation` immediately instead of retrying forever.
118129#[ tokio:: test]
119- async fn connect_with_wrong_token_returns_authorization_violation ( ) {
130+ #[ ignore = "requires Docker" ]
131+ async fn connect_with_wrong_token_returns_authorization_violation (
132+ ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
120133 let container = Nats :: default ( )
121134 . with_cmd ( [ "--auth" , "correct-token" ] )
122135 . start ( )
123- . await
124- . expect ( "Failed to start NATS container — is Docker running?" ) ;
125- let port = container. get_host_port_ipv4 ( 4222 ) . await . unwrap ( ) ;
136+ . await ?;
137+ let port = container. get_host_port_ipv4 ( 4222 ) . await ?;
126138
127139 let config = NatsConfig :: new (
128140 vec ! [ format!( "nats://127.0.0.1:{port}" ) ] ,
@@ -136,18 +148,19 @@ async fn connect_with_wrong_token_returns_authorization_violation() {
136148 "expected AuthorizationViolation, got: {:?}" ,
137149 result
138150 ) ;
151+ Ok ( ( ) )
139152}
140153
141154/// Correct token must still connect successfully after the fix.
142155#[ tokio:: test]
143- async fn connect_with_correct_token_succeeds ( ) {
156+ #[ ignore = "requires Docker" ]
157+ async fn connect_with_correct_token_succeeds ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
144158 let container = Nats :: default ( )
145159 . with_startup_timeout ( Duration :: from_secs ( 30 ) )
146160 . with_cmd ( [ "--auth" , "correct-token" ] )
147161 . start ( )
148- . await
149- . expect ( "Failed to start NATS container — is Docker running?" ) ;
150- let port = container. get_host_port_ipv4 ( 4222 ) . await . unwrap ( ) ;
162+ . await ?;
163+ let port = container. get_host_port_ipv4 ( 4222 ) . await ?;
151164
152165 let config = NatsConfig :: new (
153166 vec ! [ format!( "nats://127.0.0.1:{port}" ) ] ,
@@ -160,6 +173,7 @@ async fn connect_with_correct_token_succeeds() {
160173 "correct token should connect successfully: {:?}" ,
161174 result
162175 ) ;
176+ Ok ( ( ) )
163177}
164178
165179/// Covers the `_ = tokio::time::sleep(check_window)` arm in `connect()`.
0 commit comments