Add unit test for Database\Structure\AddPrefixTableController

Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
This commit is contained in:
Maurício Meneghini Fauth 2026-03-02 20:31:37 -03:00
parent ba958ae1f7
commit 649c84d251
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
4 changed files with 479 additions and 10 deletions

View File

@ -926,11 +926,6 @@
<code><![CDATA[Current::$database]]></code>
</MixedArgument>
</file>
<file src="src/Controllers/Database/Structure/AddPrefixTableController.php">
<PossiblyUnusedMethod>
<code><![CDATA[__construct]]></code>
</PossiblyUnusedMethod>
</file>
<file src="src/Controllers/Database/Structure/CentralColumns/AddController.php">
<PossiblyUnusedMethod>
<code><![CDATA[__construct]]></code>

View File

@ -15,12 +15,10 @@ use PhpMyAdmin\Routing\Route;
use PhpMyAdmin\Util;
#[Route('/database/structure/add-prefix-table', ['POST'])]
final class AddPrefixTableController implements InvocableController
final readonly class AddPrefixTableController implements InvocableController
{
public function __construct(
private readonly DatabaseInterface $dbi,
private readonly StructureController $structureController,
) {
public function __construct(private DatabaseInterface $dbi, private StructureController $structureController)
{
}
public function __invoke(ServerRequest $request): Response

View File

@ -0,0 +1,88 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Tests\Controllers\Database\Structure;
use Fig\Http\Message\StatusCodeInterface;
use PhpMyAdmin\Clock\Clock;
use PhpMyAdmin\Config;
use PhpMyAdmin\Config\PageSettings;
use PhpMyAdmin\Config\UserPreferences;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Controllers\Database\Structure\AddPrefixTableController;
use PhpMyAdmin\Controllers\Database\StructureController;
use PhpMyAdmin\Current;
use PhpMyAdmin\DbTableExists;
use PhpMyAdmin\Favorites\RecentFavoriteTables;
use PhpMyAdmin\Http\Factory\ServerRequestFactory;
use PhpMyAdmin\Message;
use PhpMyAdmin\Replication\Replication;
use PhpMyAdmin\Template;
use PhpMyAdmin\Tests\AbstractTestCase;
use PhpMyAdmin\Tests\Stubs\DbiDummy;
use PhpMyAdmin\Tests\Stubs\ResponseRenderer;
use PhpMyAdmin\Tracking\TrackingChecker;
use PHPUnit\Framework\Attributes\CoversClass;
use ReflectionProperty;
#[CoversClass(AddPrefixTableController::class)]
final class AddPrefixTableControllerTest extends AbstractTestCase
{
public function testAddPrefix(): void
{
(new ReflectionProperty(RecentFavoriteTables::class, 'instances'))->setValue(null, []);
$_SESSION['tmpval'] = [];
$_SERVER['SCRIPT_NAME'] = 'index.php';
$_REQUEST['db'] = Current::$database = 'test_db';
$dbiDummy = $this->createDbiDummy();
$dbiDummy->addSelectDb('test_db');
$dbiDummy->addResult('ALTER TABLE `table` RENAME `test_table`', true);
$dbiDummy->addSelectDb('test_db');
$dbiDummy->addResult('SHOW TABLES FROM `test_db`;', [['test_table']], ['Tables_in_test_db']);
$dbiDummy->addResult('SELECT COUNT(*) FROM `test_db`.`test_table`', [['3']]);
$dbiDummy->addResult(
"SELECT DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'test_db' LIMIT 1",
[['utf8mb4_uca1400_ai_ci']],
['DEFAULT_COLLATION_NAME'],
);
$dbiDummy->addResult('SELECT @@storage_engine;', [['InnoDB']]);
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')
->withParsedBody(['db' => 'test_db', 'add_prefix' => 'test_', 'selected' => ['table']]);
$response = ($this->getAddPrefixTableController($dbiDummy))($request);
$dbiDummy->assertAllSelectsConsumed();
$dbiDummy->assertAllQueriesConsumed();
self::assertSame("ALTER TABLE `table` RENAME `test_table`;\n", Current::$sqlQuery);
self::assertEquals(Message::success(), Current::$message);
self::assertSame(StatusCodeInterface::STATUS_OK, $response->getStatusCode());
self::assertStringEqualsFile(
__DIR__ . '/Fixtures/AddPrefixTable-testAddPrefix.html',
(string) $response->getBody(),
);
}
private function getAddPrefixTableController(DbiDummy $dbiDummy): AddPrefixTableController
{
$config = new Config();
$dbi = $this->createDatabaseInterface($dbiDummy, $config);
$relation = new Relation($dbi, $config);
$responseRenderer = new ResponseRenderer();
$template = new Template($config);
$structureController = new StructureController(
$responseRenderer,
$template,
$relation,
new Replication($dbi),
$dbi,
new TrackingChecker($dbi, $relation),
new PageSettings(new UserPreferences($dbi, $relation, $template, $config, new Clock()), $responseRenderer),
new DbTableExists($dbi),
$config,
);
return new AddPrefixTableController($dbi, $structureController);
}
}

View File

@ -0,0 +1,388 @@
<div id="page_settings_modal"><div class="page_settings"><form method="post" action="index.php&#x3F;route&#x3D;&#x25;2F&amp;db&#x3D;test_db&amp;server&#x3D;1&amp;lang&#x3D;en" class="config-form disableAjax">
<input type="hidden" name="tab_hash" value="">
<input type="hidden" name="check_page_refresh" id="check_page_refresh" value="">
<input type="hidden" name="lang" value="en"><input type="hidden" name="token" value="token">
<input type="hidden" name="submit_save" value="DbStructure">
<ul class="nav nav-tabs" id="configFormDisplayTab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="DbStructure-tab" href="#DbStructure" data-bs-toggle="tab" role="tab" aria-controls="DbStructure" aria-selected="true">Database structure</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade show active" id="DbStructure" role="tabpanel" aria-labelledby="DbStructure-tab">
<div class="card border-top-0">
<div class="card-body">
<h5 class="card-title visually-hidden">Database structure</h5>
<h6 class="card-subtitle mb-2 text-body-secondary">Choose which details to show in the database structure (list of tables).</h6>
<fieldset class="optbox">
<legend>Database structure</legend>
<table class="table table-borderless">
<tr>
<th>
<label for="ShowDbStructureCharset">Show table charset</label>
<span class="doc">
<a href="index.php?route=/url&amp;url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fconfig.html%23cfg_ShowDbStructureCharset" target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation" class="icon ic_b_help"></a>
</span>
<small>Show or hide a column displaying the charset for all tables.</small>
</th>
<td>
<span class="checkbox">
<input type="checkbox" name="ShowDbStructureCharset" id="ShowDbStructureCharset">
</span>
<a class="restore-default hide" href="#ShowDbStructureCharset" title="Restore default value"><img src="themes/dot.gif" title="Restore default value" alt="Restore default value" class="icon ic_s_reload"></a>
</td>
</tr>
<tr>
<th>
<label for="ShowDbStructureComment">Show table comments</label>
<span class="doc">
<a href="index.php?route=/url&amp;url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fconfig.html%23cfg_ShowDbStructureComment" target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation" class="icon ic_b_help"></a>
</span>
<small>Show or hide a column displaying the comments for all tables.</small>
</th>
<td>
<span class="checkbox">
<input type="checkbox" name="ShowDbStructureComment" id="ShowDbStructureComment">
</span>
<a class="restore-default hide" href="#ShowDbStructureComment" title="Restore default value"><img src="themes/dot.gif" title="Restore default value" alt="Restore default value" class="icon ic_s_reload"></a>
</td>
</tr>
<tr>
<th>
<label for="ShowDbStructureCreation">Show creation timestamp</label>
<span class="doc">
<a href="index.php?route=/url&amp;url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fconfig.html%23cfg_ShowDbStructureCreation" target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation" class="icon ic_b_help"></a>
</span>
<small>Show or hide a column displaying the Creation timestamp for all tables.</small>
</th>
<td>
<span class="checkbox">
<input type="checkbox" name="ShowDbStructureCreation" id="ShowDbStructureCreation">
</span>
<a class="restore-default hide" href="#ShowDbStructureCreation" title="Restore default value"><img src="themes/dot.gif" title="Restore default value" alt="Restore default value" class="icon ic_s_reload"></a>
</td>
</tr>
<tr>
<th>
<label for="ShowDbStructureLastUpdate">Show last update timestamp</label>
<span class="doc">
<a href="index.php?route=/url&amp;url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fconfig.html%23cfg_ShowDbStructureLastUpdate" target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation" class="icon ic_b_help"></a>
</span>
<small>Show or hide a column displaying the Last update timestamp for all tables.</small>
</th>
<td>
<span class="checkbox">
<input type="checkbox" name="ShowDbStructureLastUpdate" id="ShowDbStructureLastUpdate">
</span>
<a class="restore-default hide" href="#ShowDbStructureLastUpdate" title="Restore default value"><img src="themes/dot.gif" title="Restore default value" alt="Restore default value" class="icon ic_s_reload"></a>
</td>
</tr>
<tr>
<th>
<label for="ShowDbStructureLastCheck">Show last check timestamp</label>
<span class="doc">
<a href="index.php?route=/url&amp;url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Fconfig.html%23cfg_ShowDbStructureLastCheck" target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation" class="icon ic_b_help"></a>
</span>
<small>Show or hide a column displaying the Last check timestamp for all tables.</small>
</th>
<td>
<span class="checkbox">
<input type="checkbox" name="ShowDbStructureLastCheck" id="ShowDbStructureLastCheck">
</span>
<a class="restore-default hide" href="#ShowDbStructureLastCheck" title="Restore default value"><img src="themes/dot.gif" title="Restore default value" alt="Restore default value" class="icon ic_s_reload"></a>
</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
</form>
<span id="configInlineParamsData"
data-field-validators="&#x5B;&#x5D;"
data-default-values="&#x7B;&quot;ShowDbStructureCharset&quot;&#x3A;false,&quot;ShowDbStructureComment&quot;&#x3A;false,&quot;ShowDbStructureCreation&quot;&#x3A;false,&quot;ShowDbStructureLastUpdate&quot;&#x3A;false,&quot;ShowDbStructureLastCheck&quot;&#x3A;false&#x7D;"></span>
</div></div>
<div id="tableslistcontainer">
<div class="card mb-3 d-print-none" id="tableFilter">
<div class="card-header">Filters</div>
<div class="card-body row row-cols-lg-auto gy-1 gx-3 align-items-center">
<label class="col-12 col-form-label" for="filterText">Containing the word:</label>
<div class="col-12">
<input class="form-control" name="filterText" type="text" id="filterText" value="">
</div>
</div>
</div>
<form method="post" action="index.php?route=/database/structure&lang=en" name="tablesForm" id="tablesForm">
<input type="hidden" name="db" value="test_db"><input type="hidden" name="lang" value="en"><input type="hidden" name="token" value="token">
<div class="table-responsive">
<table class="table table-striped table-hover table-sm w-auto data">
<thead>
<tr>
<th class="d-print-none"></th>
<th><a href="index.php?route=/database/structure&db=test_db&pos=0&sort=table&sort_order=DESC&lang=en" title="Sort" onmouseover="$(&#039;.sort_arrow&#039;).toggle();" onmouseout="$(&#039;.sort_arrow&#039;).toggle();">Table <img src="themes/dot.gif" title="" alt="Ascending" class="icon ic_s_asc sort_arrow"> <img src="themes/dot.gif" title="" alt="Descending" class="icon ic_s_desc sort_arrow hide"></a></th>
<th>Replication</th>
<th colspan="7" class="d-print-none">
Action
</th>
<th>
<a href="index.php?route=/database/structure&db=test_db&pos=0&sort=records&sort_order=DESC&lang=en" title="Sort">Rows</a>
<span class="pma_hint"><img src="themes/dot.gif" title="" alt="" class="icon ic_b_help"><span class="hide">May be approximate. Click on the number to get the exact count. See <a href="index.php?route=/url&url=https%3A%2F%2Fdocs.phpmyadmin.net%2Fen%2Flatest%2Ffaq.html%23faq3-11" target="documentation">FAQ 3.11</a>.</span></span>
</th>
<th><a href="index.php?route=/database/structure&db=test_db&pos=0&sort=type&sort_order=ASC&lang=en" title="Sort">Type</a></th>
<th><a href="index.php?route=/database/structure&db=test_db&pos=0&sort=collation&sort_order=ASC&lang=en" title="Sort">Collation</a></th>
<th><a href="index.php?route=/database/structure&db=test_db&pos=0&sort=size&sort_order=DESC&lang=en" title="Sort">Size</a></th>
<th><a href="index.php?route=/database/structure&db=test_db&pos=0&sort=overhead&sort_order=DESC&lang=en" title="Sort">Overhead</a></th>
</tr>
</thead>
<tbody>
<tr id="row_tbl_1" data-filter-row="TEST_TABLE">
<td class="text-center d-print-none">
<input type="checkbox"
name="selected_tbl[]"
class="checkall"
value="test_table"
id="checkbox_tbl_1">
</td>
<th>
<a class="disableAjax" href="index.php?route=/sql&db=test_db&table=test_table&pos=0&lang=en" title="">test_table</a>
</th>
<td class="text-center">
</td>
<td class="text-center d-print-none">
<a id="e1aa88c07d60f7472d1e27463e533c89_favorite_anchor"
class="ajax favorite_table_anchor"
href="index.php?route=/database/structure/favorite-table&db=test_db&ajax_request=1&favorite_table=test_table&add_favorite=1&lang=en"
title="Add to Favorites"
data-favtargets="b383d6fb8e32135d258f2667459fab76">
<span class="text-nowrap"><img src="themes/dot.gif" title="" alt="" class="icon ic_b_no_favorite">&nbsp;</span>
</a>
</td>
<td class="text-center d-print-none">
<a class="disableAjax" href="index.php?route=/sql&db=test_db&table=test_table&pos=0&lang=en">
<span class="text-nowrap"><img src="themes/dot.gif" title="Browse" alt="Browse" class="icon ic_b_browse">&nbsp;Browse</span>
</a>
</td>
<td class="text-center d-print-none">
<a class="disableAjax" href="index.php?route=/table/structure&db=test_db&table=test_table&lang=en">
<span class="text-nowrap"><img src="themes/dot.gif" title="Structure" alt="Structure" class="icon ic_b_props">&nbsp;Structure</span>
</a>
</td>
<td class="text-center d-print-none">
<a class="disableAjax" href="index.php?route=/table/search&db=test_db&table=test_table&lang=en">
<span class="text-nowrap"><img src="themes/dot.gif" title="Search" alt="Search" class="icon ic_b_select">&nbsp;Search</span>
</a>
</td>
<td class="text-center d-print-none">
<a class="disableAjax" href="index.php?route=/table/change&db=test_db&table=test_table&lang=en"><span class="text-nowrap"><img src="themes/dot.gif" title="Insert" alt="Insert" class="icon ic_b_insrow">&nbsp;Insert</span></a>
</td>
<td class="text-center d-print-none">
<a class="truncate_table_anchor ajax" href="index.php?route=/sql&lang=en" data-post="db=test_db&table=test_table&sql_query=TRUNCATE+%60test_table%60&message_to_show=Table+test_table+has+been+emptied.&lang=en">
<span class="text-nowrap"><img src="themes/dot.gif" title="Empty" alt="Empty" class="icon ic_b_empty">&nbsp;Empty</span>
</a>
</td>
<td class="text-center d-print-none">
<a class="ajax drop_table_anchor" href="index.php?route=/sql&lang=en" data-post="db=test_db&table=test_table&reload=1&purge=1&sql_query=DROP+TABLE+%60test_table%60&message_to_show=Table+test_table+has+been+dropped.&lang=en">
<span class="text-nowrap"><img src="themes/dot.gif" title="Drop" alt="Drop" class="icon ic_b_drop">&nbsp;Drop</span>
</a>
</td>
<td class="value tbl_rows font-monospace text-end"
data-table="test_table">
3
</td>
<td class="text-nowrap">
InnoDB
</td>
<td class="text-nowrap">
<dfn title="Unicode (UCA 4.0.0), case-insensitive">utf8mb4_general_ci</dfn>
</td>
<td class="value tbl_size font-monospace text-end">
<a class="disableAjax" href="index.php?route=/table/structure&db=test_db&table=test_table&lang=en#showusage">
<span>16.0</span>&nbsp;<span class="unit">KiB</span>
</a>
</td>
<td class="value tbl_overhead font-monospace text-end">
-
</td>
</tr>
</tbody>
<tfoot id="tbl_summary_row">
<tr>
<th class="d-print-none"></th>
<th class="tbl_num text-nowrap">
1 table
</th>
<th>Replication</th>
<th colspan="7" class="d-print-none">Sum</th>
<th class="value tbl_rows font-monospace text-end">3</th>
<th class="text-center">
<dfn title="InnoDB is the default storage engine on this MySQL server.">
InnoDB
</dfn>
</th>
<th>
</th>
<th class="value tbl_size font-monospace text-end">16.0 KiB</th>
<th class="value tbl_overhead font-monospace text-end">0 B</th>
</tr>
</tfoot>
</table>
</div>
<div class="clearfloat d-print-none">
<img src="themes/dot.gif" title="With selected:" alt="With selected:" dir="ltr" width="38" height="22" class="icon ic_select_all_arrow">
<input type="checkbox" id="tablesForm_checkall" class="checkall_box" title="Check all">
<label for="tablesForm_checkall">Check all</label>
<select name="submit_mult" class="mx-5 my-0">
<option value="With selected:" selected>With selected:</option>
<option value="copy_tbl">Copy table</option>
<option value="show_create">Show create</option>
<option value="export">Export</option>
<optgroup label="Delete data or table">
<option value="empty_tbl">Empty</option>
<option value="drop_tbl">Drop</option>
</optgroup>
<optgroup label="Table maintenance">
<option value="analyze_tbl">Analyze table</option>
<option value="check_tbl">Check table</option>
<option value="checksum_tbl">Checksum table</option>
<option value="optimize_tbl">Optimize table</option>
<option value="repair_tbl">Repair table</option>
</optgroup>
<optgroup label="Prefix">
<option value="add_prefix_tbl">Add prefix to table</option>
<option value="replace_prefix_tbl">Replace table prefix</option>
<option value="copy_tbl_change_prefix">Copy table with prefix</option>
</optgroup>
</select>
</div>
</form>
<div class="modal fade" id="bulkActionModal" data-bs-backdrop="static" data-bs-keyboard="false"
tabindex="-1" aria-labelledby="bulkActionLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="bulkActionLabel"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cancel"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="bulkActionContinue">Continue</button>
</div>
</div>
</div>
</div>
</div>
<hr>
<p class="d-print-none">
<button type="button" class="btn btn-link p-0 jsPrintButton"><span class="text-nowrap"><img src="themes/dot.gif" title="Print" alt="Print" class="icon ic_b_print">&nbsp;Print</span></button>
<a href="index.php?route=/database/data-dictionary&db=test_db&goto=index.php%3Froute%3D%2Fdatabase%2Fstructure%26lang%3Den&lang=en">
<span class="text-nowrap"><img src="themes/dot.gif" title="Data dictionary" alt="Data dictionary" class="icon ic_b_tblanalyse">&nbsp;Data dictionary</span>
</a>
</p>
<form id="createTableMinimalForm" method="post" action="index.php?route=/table/create&lang=en" class="card d-print-none lock-page">
<input type="hidden" name="db" value="test_db"><input type="hidden" name="lang" value="en"><input type="hidden" name="token" value="token">
<div class="card-header"><span class="text-nowrap"><img src="themes/dot.gif" title="Create new table" alt="Create new table" class="icon ic_b_table_add">&nbsp;Create new table</span></div>
<div class="card-body row row-cols-lg-auto g-3">
<div class="col-12">
<label for="createTableNameInput" class="form-label">Table name</label>
<input autocomplete="off" type="text" class="form-control" name="table" id="createTableNameInput" maxlength="64">
</div>
<div class="col-12">
<label for="createTableNumFieldsInput" class="form-label">Number of columns</label>
<input type="number" class="form-control" name="num_fields" id="createTableNumFieldsInput" min="1" value="4" required>
</div>
<div class="col-12 align-self-lg-end">
<input class="btn btn-primary" type="submit" value="Create">
</div>
</div>
</form>