BxBaseMenuMoreAutoTest.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. <?php
  2. /**
  3. * Menus with a 'more-auto' item (BxBaseMenuMoreAuto) set themselves up in the browser with BxDolMenuMoreAuto.
  4. * The init code they print runs every time it is rendered, also when content loaded by htmx brings a menu that
  5. * was on the page before: the JS object skips an element it has already set up.
  6. */
  7. class BxBaseMenuMoreAutoTest extends BxDolTestCase
  8. {
  9. private function callProtected($oObject, string $sMethod, array $aArgs = [])
  10. {
  11. $oMethod = new ReflectionMethod($oObject, $sMethod);
  12. return $oMethod->invokeArgs($oObject, $aArgs);
  13. }
  14. private function getSiteMenu(): BxBaseMenuMoreAuto
  15. {
  16. $oMenu = BxDolMenu::getObjectInstance('sys_site');
  17. if (!($oMenu instanceof BxBaseMenuMoreAuto) || !$oMenu->isMoreAuto())
  18. $this->markTestSkipped('The site menu has no active more-auto item.');
  19. return $oMenu;
  20. }
  21. /**
  22. * @return array [JS object name, JS class, decoded params]
  23. */
  24. private function parseInit(string $sCode): array
  25. {
  26. $bMatched = preg_match('/var (oMenuMoreAuto\w+) = new (\w+)\((\{.*\})\); \1\.init\(\);/s', $sCode, $aMatches);
  27. $this->assertSame(1, $bMatched, 'The init code creates the JS object and calls init(): ' . $sCode);
  28. $aParams = json_decode($aMatches[3], true);
  29. $this->assertIsArray($aParams);
  30. return [$aMatches[1], $aMatches[2], $aParams];
  31. }
  32. public function testInitCodeRunsEachTimeItIsRendered(): void
  33. {
  34. $oMenu = $this->getSiteMenu();
  35. $sCode = $this->callProtected($oMenu, '_getJsCodeMoreAuto');
  36. [$sJsObject] = $this->parseInit($sCode);
  37. $this->assertSame('oMenuMoreAutoSysSite', $sJsObject);
  38. $this->assertStringNotContainsString('if(!' . $sJsObject . ')', $sCode, 'A guard on the global would skip a menu that htmx brought in again.');
  39. $this->assertSame($sCode, $this->callProtected($oMenu, '_getJsCodeMoreAuto'), 'Rendering the menu again prints the same init code.');
  40. }
  41. public function testInitCodePassesTheMenuAndItsPopup(): void
  42. {
  43. $oMenu = $this->getSiteMenu();
  44. [, $sJsClass, $aParams] = $this->parseInit($this->callProtected($oMenu, '_getJsCodeMoreAuto'));
  45. $this->assertMatchesRegularExpression('/^Bx\w*MenuMoreAuto$/', $sJsClass);
  46. $this->assertSame('sys_site', $aParams['sObject']);
  47. $this->assertSame(['main' => 'sys-site', 'more_auto_popup' => 'sys-site-ma-popup'], $aParams['aHtmlIds']);
  48. $this->assertIsInt($aParams['iItemsStatic']);
  49. $this->assertContains($aParams['bItemsStaticOnly'], [0, 1]);
  50. }
  51. }