@@ -141,9 +141,16 @@ def test_connection_parameters_from_sqlalchemy_url_parses_fields(
141141 }
142142
143143
144- def test_connection_parameters_from_sqlalchemy_url_defaults_port_and_keeps_ssl_paths (
145- tmp_path : Path ,
146- ) -> None :
144+ def test_from_sqlalchemy_url_default_port () -> None :
145+ cfg = {
146+ "sqlalchemy_url" : ("postgresql://user:pass@localhost/mydb" ),
147+ }
148+
149+ parameters = ConnectionParameters .from_tap_config (cfg )
150+ assert parameters .port == 5432 # noqa: PLR2004
151+
152+
153+ def test_from_sqlalchemy_url_and_preserves_ssl_paths (tmp_path : Path ) -> None :
147154 rootcert = tmp_path / "root.crt"
148155 rootcert .write_text ("CA" , encoding = "utf-8" )
149156
@@ -154,16 +161,14 @@ def test_connection_parameters_from_sqlalchemy_url_defaults_port_and_keeps_ssl_p
154161 }
155162
156163 parameters = ConnectionParameters .from_tap_config (cfg )
157-
158- assert parameters .port == 5432 # noqa: PLR2004
159164 assert parameters .options == {
160165 "application_name" : "tap_postgres" ,
161166 "sslmode" : "verify-full" ,
162167 "sslrootcert" : str (rootcert ),
163168 }
164169
165170
166- def test_connection_parameters_renders_as_sqlalchemy_url (tmp_path : Path ) -> None :
171+ def test_renders_as_sqlalchemy_url (tmp_path : Path ) -> None :
167172 cfg = _base_config (tmp_path )
168173 cfg .update (
169174 {
@@ -181,7 +186,7 @@ def test_connection_parameters_renders_as_sqlalchemy_url(tmp_path: Path) -> None
181186 )
182187
183188
184- def test_connection_parameters_renders_as_psycopg2_dsn (tmp_path : Path ) -> None :
189+ def test_renders_as_psycopg2_dsn (tmp_path : Path ) -> None :
185190 cfg = _base_config (tmp_path )
186191 cfg .update (
187192 {
@@ -197,3 +202,54 @@ def test_connection_parameters_renders_as_psycopg2_dsn(tmp_path: Path) -> None:
197202 "host=localhost port=5432 dbname=postgres user=postgres password=postgres "
198203 "application_name=tap_postgres sslmode=require"
199204 )
205+
206+
207+ def test_with_host_and_port ():
208+ """Unit test for ConnectionParameters.with_host_and_port method."""
209+ # Create original connection parameters (pointing to remote database)
210+ original = ConnectionParameters (
211+ host = "remote-db.example.com" ,
212+ port = 5432 ,
213+ database = "testdb" ,
214+ user = "testuser" ,
215+ password = "testpass" ,
216+ options = {"sslmode" : "require" , "application_name" : "tap_postgres" },
217+ )
218+
219+ ssh_tunnel_host = "127.0.0.1"
220+ ssh_tunnel_port = 12345
221+
222+ # Simulate what ssh_tunnel_connect does: update to tunnel's local bind address
223+ updated = original .with_host_and_port (
224+ host = ssh_tunnel_host , # tunnel's local_bind_host
225+ port = ssh_tunnel_port , # tunnel's local_bind_port
226+ )
227+
228+ assert updated .host == ssh_tunnel_host
229+ assert updated .port == ssh_tunnel_port
230+
231+ # Verify other parameters are preserved
232+ assert updated .database == original .database == "testdb"
233+ assert updated .user == original .user == "testuser"
234+ assert updated .password == original .password == "testpass"
235+ assert (
236+ updated .options
237+ == original .options
238+ == {"sslmode" : "require" , "application_name" : "tap_postgres" }
239+ )
240+
241+ # Verify original parameters are unchanged (immutability check)
242+ assert original .host == "remote-db.example.com"
243+ assert original .port == 5432 # noqa: PLR2004
244+
245+ # Verify the connection strings use the tunnel address
246+ sqlalchemy_url = updated .render_as_sqlalchemy_url ()
247+ psycopg2_dsn = updated .render_as_psycopg2_dsn ()
248+
249+ assert ssh_tunnel_host in sqlalchemy_url
250+ assert str (ssh_tunnel_port ) in sqlalchemy_url
251+ assert original .host not in sqlalchemy_url
252+
253+ assert f"host={ ssh_tunnel_host } " in psycopg2_dsn
254+ assert f"port={ ssh_tunnel_port } " in psycopg2_dsn
255+ assert original .host not in psycopg2_dsn
0 commit comments