diff options
-rw-r--r-- | include/items.php | 2 | ||||
-rw-r--r-- | tests/unit/UnitTestCase.php | 65 | ||||
-rw-r--r-- | view/js/main.js | 23 | ||||
-rw-r--r-- | view/theme/redbasic/css/style.css | 6 | ||||
-rw-r--r-- | view/tpl/hdr.tpl | 1 | ||||
-rw-r--r-- | view/tpl/notifications_widget.tpl | 8 |
6 files changed, 87 insertions, 18 deletions
diff --git a/include/items.php b/include/items.php index 2300f70ef..dc9e9a7d9 100644 --- a/include/items.php +++ b/include/items.php @@ -208,8 +208,6 @@ function collect_recipients($item, &$private_envelope, $include_groups = true) { $recipients[] = $item['owner_xchan']; } -hz_syslog(print_r($recipients, true)); - return $recipients; } diff --git a/tests/unit/UnitTestCase.php b/tests/unit/UnitTestCase.php index a4ea94b13..9ab6a534a 100644 --- a/tests/unit/UnitTestCase.php +++ b/tests/unit/UnitTestCase.php @@ -33,29 +33,30 @@ require_once __DIR__ . '/../../boot.php'; require_once 'include/dba/dba_driver.php' ; /** - * @brief Base class for our Unit Tests. + * Base class for our Unit Tests. * - * Empty class at the moment, but you should extend this class for unit test - * cases, so we could and for sure we will need to implement basic behaviour - * for all of our unit tests. + * Base class for Hubzilla unit/integration tests. This extends the base + * TestCase class from PHPUnit by connecting to a test database, and making the + * database connection available to the code under test via the normal Hubzilla + * mechanisms, i.e the \DBA::$dba global variable. * - * @author Klaus Weidenbach + * It also automatically loads database fixtures from yaml files in the + * tests/unit/includes/dba/_files directory. And wraps each test run in it's + * own database transaction. */ class UnitTestCase extends TestCase { protected array $fixtures = array(); /** - * Override the PHPUnit\Framework\TestCase::run method, so we can - * wrap it in a database transaction. + * Override the run method, so we can wrap it in a database transaction. + * + * The transaction is automatically rolled back when the test completes, to + * leave the test database in a known pristine state. * * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function run(TestResult $result = null): TestResult { - // $myclass = get_class($this); - // logger("[*] Running test: {$myclass}::{$this->getName(true)}", LOGGER_DEBUG); - if (! \DBA::$dba) { - //logger('[*] Connecting to test db...'); $this->connect_to_test_db(); } @@ -74,6 +75,22 @@ class UnitTestCase extends TestCase { return $result; } + /** + * Connect to the test database, + * + * By default it will connect to a MySQL database with the following settings: + * + * - HZ_TEST_DB_HOST: db + * - HZ_TEST_DB_PORT: default + * - HZ_TEST_DB_USER: test_user + * - HZ_TEST_DB_PASS: hubzilla + * - HZ_TEST_DB_DATABASE: hubzilla_test_db + * - HZ_TEST_DB_TYPE: mysql (can also be "postgres") + * - HZ_TEST_DB_CHARSET: UTF8 + * + * All of these settings can be overridden by the test runner by setting ENV vars + * named as above with the values you want to override. + */ protected function connect_to_test_db() : void { if ( !\DBA::$dba ) { \DBA::dba_factory( @@ -101,6 +118,14 @@ class UnitTestCase extends TestCase { } } + /** + * Return the database type from a string. + * + * @param string $type The database type, can be either mysql or postgres. + * + * @return The database type constant matching the passed in type, or DBTYPE_MYSQL + * if $type is empty or invalid. + */ private static function dbtype(string $type): int { if (trim(strtolower($type)) === 'postgres') { return DBTYPE_POSTGRES; @@ -109,6 +134,9 @@ class UnitTestCase extends TestCase { } } + /** + * Load database fixtures from the fixture path. + */ private function loadFixtures() : void { $files = glob(__DIR__ . '/includes/dba/_files/*.yml'); if ($files === false || empty($files)) { @@ -117,6 +145,21 @@ class UnitTestCase extends TestCase { array_walk($files, fn($file) => $this->loadFixture($file)); } + /** + * Load database fixtures from a specific file. + * + * The file must be a yaml file named the same as the table in the database + * it should populate. + * + * The file also need to have a root key with the same name as the table. + * Under which it contains an array of rows that should be inserted into + * the db table. + * + * @param string $file The path and filename of the fixture to load. + * The path name is relative to the current working + * directory of the process, which should normally + * be the Hubzilla root directory. + */ private function loadFixture($file) : void { $table_name = basename($file, '.yml'); $this->fixtures[$table_name] = yaml_parse_file($file)[$table_name]; diff --git a/view/js/main.js b/view/js/main.js index c9798dede..8904f8b4c 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -1305,7 +1305,8 @@ function dropItem(url, object, b64mid) { $(object + ', #pinned-wrapper-' + id).remove(); $('body').css('cursor', 'auto'); - $.jGrowl(aStr.itemdel, { sticky: false, theme: 'info', life: 3000 }); + toast(aStr.itemdel, 'info') + //$.jGrowl(aStr.itemdel, { sticky: false, theme: 'info', life: 3000 }); if (typeof b64mid !== typeof undefined) { $('[data-b64mid=\'' + b64mid + '\']').fadeOut(function() { @@ -1408,7 +1409,8 @@ function submitPoll(id) { $.post('vote/' + id, $('#question-form-' + id).serialize(), function(data) { - $.jGrowl(data.message, { sticky: false, theme: ((data.success) ? 'info' : 'notice'), life: 10000 }); + toast(data.message, ((data.success) ? 'info' : 'danger')); + //$.jGrowl(data.message, { sticky: false, theme: ((data.success) ? 'info' : 'notice'), life: 10000 }); if(timer) clearTimeout(timer); timer = setTimeout(updateInit, 500); } @@ -1815,3 +1817,20 @@ function toggleAside() { $('<div id="overlay"></div>').appendTo('body').one('click', function() { toggleAside(); }); } } + +function toast(string, severity) { + let container = document.getElementById('toast-container'); + let toast = document.createElement('div'); + + toast.innerHTML = '<div class="d-flex"><div class="toast-body">' + string + '</div><button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button></div>'; + toast.classList.add('toast', 'p-2', 'm-3', 'bg-' + severity + '-subtle', 'text-' + severity + '-emphasis', 'border-' + severity); + container.prepend(toast); + + let toastInstance = bootstrap.Toast.getOrCreateInstance(toast); + + if (severity === 'danger') { + toastInstance._config.autohide = false; + } + + toastInstance.show(); +} diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css index 56194c735..05cd75422 100644 --- a/view/theme/redbasic/css/style.css +++ b/view/theme/redbasic/css/style.css @@ -168,6 +168,11 @@ input[type=text], textarea { color: #FF0000; } +#toast-container { + z-index: 1030; + width: 300px; +} + #powered-by { font-size: 0.5rem; position: absolute; @@ -719,6 +724,7 @@ div.jGrowl div.info { color: #ffffff; padding-left: 58px; } + #jGrowl.top-right { top: 4.5rem; right: .25rem; diff --git a/view/tpl/hdr.tpl b/view/tpl/hdr.tpl index e69de29bb..ba63830eb 100644 --- a/view/tpl/hdr.tpl +++ b/view/tpl/hdr.tpl @@ -0,0 +1 @@ +<div id="toast-container" class="d-flex position-fixed top-0 end-0"></div> diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl index 9ea5ffec6..aa53905ad 100644 --- a/view/tpl/notifications_widget.tpl +++ b/view/tpl/notifications_widget.tpl @@ -337,17 +337,19 @@ sse_setNotificationsStatus(); // notice and info - $.jGrowl.defaults.closerTemplate = '<div>[ ' + aStr.closeAll + ']</div>'; + //$.jGrowl.defaults.closerTemplate = '<div>[ ' + aStr.closeAll + ']</div>'; if(obj.notice) { $(obj.notice.notifications).each(function() { - $.jGrowl(this, { sticky: true, theme: 'notice' }); + toast(this, 'danger'); + //$.jGrowl(this, { sticky: true, theme: 'notice' }); }); } if(obj.info) { $(obj.info.notifications).each(function(){ - $.jGrowl(this, { sticky: false, theme: 'info', life: 10000 }); + toast(this, 'info'); + //$.jGrowl(this, { sticky: false, theme: 'info', life: 10000 }); }); } |