test(api): pin order_items listing ordering in getOrderItems
Wiring test that locks down the SELECT inside orders_o::getOrderItems so the regression cannot reappear silently. The fix in the previous commit adds ORDER BY (related_item_id IS NULL) DESC, related_item_id ASC, id ASC; this test asserts the SQL still contains that clause.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
it('orders the SELECT in getOrderItems so primary items precede their addons', function (): void {
|
||||
$ordersObjectFile = app_path('objects/orders_o.php');
|
||||
$content = file_get_contents($ordersObjectFile);
|
||||
|
||||
expect($content)->not->toBeFalse();
|
||||
|
||||
// Locate the getOrderItems method body.
|
||||
$start = strpos($content, 'public function getOrderItems(int $order_id): array');
|
||||
expect($start)->not->toBeFalse();
|
||||
|
||||
// Bound the search so we don't accidentally match unrelated SQL further down
|
||||
// the file (the helper around line 645 in orders_o.php also uses ORDER BY id DESC).
|
||||
$end = strpos($content, "\n }\n", $start);
|
||||
expect($end)->not->toBeFalse();
|
||||
|
||||
$methodBody = substr($content, (int)$start, (int)$end - (int)$start);
|
||||
|
||||
// The SELECT against order_items must include an explicit ORDER BY so MySQL
|
||||
// does not return rows in undefined order (which has been observed to put
|
||||
// primary order items after their addons, breaking the FE tree-builder and
|
||||
// the invoice line listing).
|
||||
expect($methodBody)
|
||||
->toContain("FROM order_items WHERE order_id = \$order_id")
|
||||
->and($methodBody)
|
||||
->toContain('ORDER BY');
|
||||
|
||||
// The ORDER BY must place primary items first (related_item_id IS NULL DESC),
|
||||
// group addons by their parent (related_item_id ASC), and fall back to
|
||||
// insertion order (id ASC).
|
||||
expect($methodBody)
|
||||
->toContain('(related_item_id IS NULL) DESC')
|
||||
->and($methodBody)
|
||||
->toContain('related_item_id ASC')
|
||||
->and($methodBody)
|
||||
->toContain('id ASC');
|
||||
});
|
||||
|
||||
it('does not leave the legacy unordered SELECT in getOrderItems', function (): void {
|
||||
$ordersObjectFile = app_path('objects/orders_o.php');
|
||||
$content = file_get_contents($ordersObjectFile);
|
||||
|
||||
expect($content)->not->toBeFalse();
|
||||
|
||||
$start = strpos($content, 'public function getOrderItems(int $order_id): array');
|
||||
$end = strpos($content, "\n }\n", $start);
|
||||
|
||||
expect($start)->not->toBeFalse()
|
||||
->and($end)->not->toBeFalse();
|
||||
|
||||
$methodBody = substr($content, (int)$start, (int)$end - (int)$start);
|
||||
|
||||
// The buggy SQL must be gone: previously this returned rows in whatever
|
||||
// order MySQL felt like, leading to addons being listed before their primary.
|
||||
expect($methodBody)
|
||||
->not->toContain("FROM order_items WHERE order_id = \$order_id\";\n \$result");
|
||||
});
|
||||
Reference in New Issue
Block a user