From c95ba4fa81ed46097ef20d50afc0f32a6ffb8c2b Mon Sep 17 00:00:00 2001 From: Bedram Tamang Date: Thu, 23 Jul 2026 14:26:23 -0700 Subject: [PATCH] test(database): regression test for DatabaseManager connection lookup (GH #6) GH issue #6 reported DatabaseManager.connection() indexing self.config[name] directly, causing a KeyError when DatabaseProvider.register() binds the full resolved config (default/connections/migrations) rather than a flat {connection_name: {...}} dict. That lookup was already corrected to go through the nested 'connections' key (commit 6eae52bf) and raises a clean ValueError on a missing connection, so this is not reproducible on current main -- verified by reverting the lookup locally, which reproduces the exact reported KeyError: 'sqlite'. Adds a regression test covering: connection resolution through the nested connections dict, default-name resolution from the top-level 'default' key, the ValueError (not KeyError) on a missing connection, and end-to-end DatabaseProvider wiring, so any future regression on this path fails loudly. --- .../tests/masoniteorm/config/test_manager.py | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 fastapi_startkit/tests/masoniteorm/config/test_manager.py diff --git a/fastapi_startkit/tests/masoniteorm/config/test_manager.py b/fastapi_startkit/tests/masoniteorm/config/test_manager.py new file mode 100644 index 00000000..dd6589ec --- /dev/null +++ b/fastapi_startkit/tests/masoniteorm/config/test_manager.py @@ -0,0 +1,86 @@ +import tempfile +import unittest +from pathlib import Path + +from fastapi_startkit.application import Application +from fastapi_startkit.masoniteorm import SQLiteConfig +from fastapi_startkit.masoniteorm.connections.factory import ConnectionFactory +from fastapi_startkit.masoniteorm.connections.manager import DatabaseManager +from fastapi_startkit.masoniteorm.providers import DatabaseProvider + + +class TestDatabaseManagerConnectionLookup(unittest.TestCase): + """Regression test for GH issue #6. + + DatabaseProvider.register() binds the *full* resolved config (with + top-level ``default``/``connections``/``migrations`` keys) into + DatabaseManager, so connection() must look names up under the nested + "connections" key rather than treating the whole config as a flat + {connection_name: {...}} dict. + """ + + def test_connection_resolves_from_nested_connections_dict(self): + config = { + "default": "sqlite", + "connections": {"sqlite": {"driver": "sqlite", "url": "sqlite+aiosqlite:///:memory:"}}, + "migrations": {"table": "migrations", "directory": "databases/migrations"}, + } + manager = DatabaseManager(ConnectionFactory(), config) + + connection = manager.connection("sqlite") + + self.assertIsNotNone(connection) + + def test_default_connection_name_resolved_from_top_level_default(self): + config = { + "default": "sqlite", + "connections": {"sqlite": {"driver": "sqlite", "url": "sqlite+aiosqlite:///:memory:"}}, + "migrations": {}, + } + manager = DatabaseManager(ConnectionFactory(), config) + + connection = manager.connection() + + self.assertIsNotNone(connection) + self.assertIn("sqlite", manager.connections) + + def test_missing_connection_raises_value_error_not_key_error(self): + config = {"default": "sqlite", "connections": {}, "migrations": {}} + manager = DatabaseManager(ConnectionFactory(), config) + + with self.assertRaises(ValueError): + manager.connection("sqlite") + + +class TestDatabaseProviderWiring(unittest.TestCase): + """DatabaseProvider.register() must produce a DatabaseManager whose + connection() resolves cleanly — this is what `python artisan db:migrate` + exercises on boot. + """ + + def setUp(self): + self._tmp_dir = tempfile.TemporaryDirectory() + self.addCleanup(self._tmp_dir.cleanup) + self.base_path = Path(self._tmp_dir.name) + + def test_provider_wires_a_resolvable_connection(self): + app = Application( + base_path=self.base_path, + env="testing", + providers=[ + ( + DatabaseProvider, + { + "default": "sqlite", + "connections": { + "sqlite": SQLiteConfig(driver="sqlite", url="sqlite+aiosqlite:///:memory:"), + }, + }, + ) + ], + ) + + db = app.make("db") + connection = db.connection() + + self.assertIsNotNone(connection)