From fd5e5b84a7945b9d05bca1b4dd4a3bb8a320e475 Mon Sep 17 00:00:00 2001 From: Satyam Date: Wed, 15 Apr 2026 15:26:26 +0530 Subject: [PATCH] Add tests for CopyStructureController and fix HTML fixture Signed-off-by: Satyam --- .../Structure/CopyStructureControllerTest.php | 181 ++++++++++++++++++ .../AddPrefixTable-testAddPrefix.html | 3 + .../Structure/CopyStructureControllerTest.php | 178 +++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 tests/unit/Controllers/Database/Structure/CopyStructureControllerTest.php create mode 100644 tests/unit/Controllers/Table/Structure/CopyStructureControllerTest.php diff --git a/tests/unit/Controllers/Database/Structure/CopyStructureControllerTest.php b/tests/unit/Controllers/Database/Structure/CopyStructureControllerTest.php new file mode 100644 index 0000000000..c0a7444c13 --- /dev/null +++ b/tests/unit/Controllers/Database/Structure/CopyStructureControllerTest.php @@ -0,0 +1,181 @@ +createDatabaseInterface(); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => '']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertFalse($response->hasSuccessState()); + self::assertStringContainsString('No databases selected', $response->getJSONResult()['message']); + } + + public function testReturnErrorWhenDatabaseNameInvalid(): void + { + Current::$database = 'test_db'; + + $dbi = $this->createDatabaseInterface(); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + // empty 'db' param → DatabaseName::tryFrom returns null + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => '']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertFalse($response->hasSuccessState()); + self::assertStringContainsString('No databases selected', $response->getJSONResult()['message']); + } + + public function testReturnsSqlForTablesOnly(): void + { + Current::$database = 'test_db'; + + $createSql = "CREATE TABLE `orders` (\n `id` int(11) NOT NULL\n) ENGINE=InnoDB"; + + $dbiDummy = $this->createDbiDummy(); + // DbTableExists::selectDatabase() + $this->dbi->selectDb() both call selectDb + $dbiDummy->addSelectDb('test_db'); + $dbiDummy->addSelectDb('test_db'); + // getTables() call + $dbiDummy->addResult( + 'SHOW TABLES FROM `test_db`;', + [['orders']], + ); + // showCreate() for orders + $dbiDummy->addResult( + 'SHOW CREATE TABLE `test_db`.`orders`', + [['orders', $createSql]], + ['Table', 'Create Table'], + ); + + $dbi = $this->createDatabaseInterface($dbiDummy); + DatabaseInterface::$instance = $dbi; + + // Pre-seed the TABLE_TYPE cache so isView() returns false without an extra query + $dbi->getCache()->cacheTableValue('test_db', 'orders', 'TABLE_TYPE', 'BASE TABLE'); + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => 'test_db']) + ->withParsedBody(['db' => 'test_db']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertTrue($response->hasSuccessState()); + $sql = $response->getJSONResult()['sql']; + self::assertStringContainsString('-- Database: test_db', $sql); + self::assertStringContainsString($createSql, $sql); + self::assertStringNotContainsString('-- Views', $sql); + + $dbiDummy->assertAllSelectsConsumed(); + $dbiDummy->assertAllQueriesConsumed(); + } + + public function testReturnsSqlWithViewsSeparated(): void + { + Current::$database = 'test_db'; + + $tableSql = "CREATE TABLE `products` (\n `id` int(11) NOT NULL\n) ENGINE=InnoDB"; + $viewSql = "CREATE VIEW `v_products` AS SELECT * FROM `products`"; + + $dbiDummy = $this->createDbiDummy(); + $dbiDummy->addSelectDb('test_db'); + $dbiDummy->addSelectDb('test_db'); + $dbiDummy->addResult( + 'SHOW TABLES FROM `test_db`;', + [['products'], ['v_products']], + ); + $dbiDummy->addResult( + 'SHOW CREATE TABLE `test_db`.`products`', + [['products', $tableSql]], + ['Table', 'Create Table'], + ); + $dbiDummy->addResult( + 'SHOW CREATE TABLE `test_db`.`v_products`', + [['v_products', $viewSql]], + ['Table', 'Create Table'], + ); + + $dbi = $this->createDatabaseInterface($dbiDummy); + DatabaseInterface::$instance = $dbi; + + $dbi->getCache()->cacheTableValue('test_db', 'products', 'TABLE_TYPE', 'BASE TABLE'); + $dbi->getCache()->cacheTableValue('test_db', 'v_products', 'TABLE_TYPE', 'VIEW'); + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => 'test_db']) + ->withParsedBody(['db' => 'test_db']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertTrue($response->hasSuccessState()); + $sql = $response->getJSONResult()['sql']; + self::assertStringContainsString('-- Database: test_db', $sql); + self::assertStringContainsString($tableSql, $sql); + self::assertStringContainsString('-- Views', $sql); + self::assertStringContainsString($viewSql, $sql); + // Views section must come after tables + self::assertGreaterThan( + strpos($sql, $tableSql), + strpos($sql, '-- Views'), + ); + + $dbiDummy->assertAllSelectsConsumed(); + $dbiDummy->assertAllQueriesConsumed(); + } + + public function testReturnsSqlForEmptyDatabase(): void + { + Current::$database = 'empty_db'; + + $dbiDummy = $this->createDbiDummy(); + $dbiDummy->addSelectDb('empty_db'); + $dbiDummy->addSelectDb('empty_db'); + $dbiDummy->addResult('SHOW TABLES FROM `empty_db`;', []); + + $dbi = $this->createDatabaseInterface($dbiDummy); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => 'empty_db']) + ->withParsedBody(['db' => 'empty_db']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertTrue($response->hasSuccessState()); + $sql = $response->getJSONResult()['sql']; + self::assertStringContainsString('-- Database: empty_db', $sql); + self::assertStringNotContainsString('CREATE TABLE', $sql); + self::assertStringNotContainsString('-- Views', $sql); + + $dbiDummy->assertAllSelectsConsumed(); + $dbiDummy->assertAllQueriesConsumed(); + } +} diff --git a/tests/unit/Controllers/Database/Structure/Fixtures/AddPrefixTable-testAddPrefix.html b/tests/unit/Controllers/Database/Structure/Fixtures/AddPrefixTable-testAddPrefix.html index cdf277d3a3..8065797738 100644 --- a/tests/unit/Controllers/Database/Structure/Fixtures/AddPrefixTable-testAddPrefix.html +++ b/tests/unit/Controllers/Database/Structure/Fixtures/AddPrefixTable-testAddPrefix.html @@ -363,6 +363,9 @@

+ Data dictionary Data dictionary diff --git a/tests/unit/Controllers/Table/Structure/CopyStructureControllerTest.php b/tests/unit/Controllers/Table/Structure/CopyStructureControllerTest.php new file mode 100644 index 0000000000..7c72dbc90b --- /dev/null +++ b/tests/unit/Controllers/Table/Structure/CopyStructureControllerTest.php @@ -0,0 +1,178 @@ +createDatabaseInterface(); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => '', 'table' => 'orders']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertFalse($response->hasSuccessState()); + self::assertStringContainsString('No databases selected', $response->getJSONResult()['message']); + } + + public function testReturnErrorWhenNoTableSet(): void + { + Current::$database = 'test_db'; + Current::$table = ''; + + $dbi = $this->createDatabaseInterface(); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => 'test_db', 'table' => '']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertFalse($response->hasSuccessState()); + self::assertStringContainsString('No table selected', $response->getJSONResult()['message']); + } + + public function testReturnErrorWhenDatabaseNameInvalid(): void + { + Current::$database = 'test_db'; + Current::$table = 'orders'; + + // Controller calls selectDb(Current::$database) before the DatabaseName check + $dbiDummy = $this->createDbiDummy(); + $dbiDummy->addSelectDb('test_db'); + $dbi = $this->createDatabaseInterface($dbiDummy); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + // 'db' param is empty → DatabaseName::tryFrom returns null + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => '', 'table' => 'orders']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertFalse($response->hasSuccessState()); + self::assertStringContainsString('No databases selected', $response->getJSONResult()['message']); + + $dbiDummy->assertAllSelectsConsumed(); + } + + public function testReturnsSqlForTable(): void + { + Current::$database = 'test_db'; + Current::$table = 'orders'; + + $createSql = "CREATE TABLE `orders` (\n `id` int(11) NOT NULL\n) ENGINE=InnoDB"; + + $dbiDummy = $this->createDbiDummy(); + // 1st: controller calls selectDb(Current::$database) + // 2nd: DbTableExists::selectDatabase() calls selectDb($databaseName) + $dbiDummy->addSelectDb('test_db'); + $dbiDummy->addSelectDb('test_db'); + // DbTableExists::hasTable issues SELECT 1 FROM `db`.`table` LIMIT 1 + $dbiDummy->addResult('SELECT 1 FROM `test_db`.`orders` LIMIT 1;', [['1']]); + // showCreate() + $dbiDummy->addResult( + 'SHOW CREATE TABLE `test_db`.`orders`', + [['orders', $createSql]], + ['Table', 'Create Table'], + ); + + $dbi = $this->createDatabaseInterface($dbiDummy); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => 'test_db', 'table' => 'orders']) + ->withParsedBody(['db' => 'test_db', 'table' => 'orders']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertTrue($response->hasSuccessState()); + self::assertSame($createSql, $response->getJSONResult()['sql']); + + $dbiDummy->assertAllSelectsConsumed(); + $dbiDummy->assertAllQueriesConsumed(); + } + + public function testReturnsSqlForView(): void + { + Current::$database = 'test_db'; + Current::$table = 'v_orders'; + + $viewSql = 'CREATE VIEW `v_orders` AS SELECT * FROM `orders`'; + + $dbiDummy = $this->createDbiDummy(); + $dbiDummy->addSelectDb('test_db'); + $dbiDummy->addSelectDb('test_db'); + $dbiDummy->addResult('SELECT 1 FROM `test_db`.`v_orders` LIMIT 1;', [['1']]); + $dbiDummy->addResult( + 'SHOW CREATE TABLE `test_db`.`v_orders`', + [['v_orders', $viewSql]], + ['Table', 'Create Table'], + ); + + $dbi = $this->createDatabaseInterface($dbiDummy); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => 'test_db', 'table' => 'v_orders']) + ->withParsedBody(['db' => 'test_db', 'table' => 'v_orders']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertTrue($response->hasSuccessState()); + self::assertSame($viewSql, $response->getJSONResult()['sql']); + + $dbiDummy->assertAllSelectsConsumed(); + $dbiDummy->assertAllQueriesConsumed(); + } + + public function testReturnErrorWhenTableDoesNotExist(): void + { + Current::$database = 'test_db'; + Current::$table = 'ghost_table'; + + $dbiDummy = $this->createDbiDummy(); + $dbiDummy->addSelectDb('test_db'); + $dbiDummy->addSelectDb('test_db'); + // hasTable SELECT fails (table not found) + $dbiDummy->addResult('SELECT 1 FROM `test_db`.`ghost_table` LIMIT 1;', false); + + $dbi = $this->createDatabaseInterface($dbiDummy); + DatabaseInterface::$instance = $dbi; + + $response = new ResponseStub(); + $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') + ->withQueryParams(['db' => 'test_db', 'table' => 'ghost_table']) + ->withParsedBody(['db' => 'test_db', 'table' => 'ghost_table']); + + (new CopyStructureController($response, $dbi, new DbTableExists($dbi)))($request); + + self::assertFalse($response->hasSuccessState()); + self::assertStringContainsString('No table selected', $response->getJSONResult()['message']); + + $dbiDummy->assertAllSelectsConsumed(); + $dbiDummy->assertAllQueriesConsumed(); + } +}