diff --git a/src/Core/I18n/I18n.php b/src/Core/I18n/I18n.php index ead30c6cad..4b8af051b9 100644 --- a/src/Core/I18n/I18n.php +++ b/src/Core/I18n/I18n.php @@ -1,6 +1,7 @@ . + // }}} /** @@ -85,7 +87,7 @@ abstract class I18n static $cached; if (!isset($cached[$path])) { $path = Formatting::normalizePath($path); - $cached[$path] = Formatting::pluginFromPath($path); + $cached[$path] = Formatting::moduleFromPath($path); } return $cached[$path] ?? 'core+intl-icu'; } diff --git a/src/Twig/Runtime.php b/src/Twig/Runtime.php index 57166881b7..3f72fff617 100644 --- a/src/Twig/Runtime.php +++ b/src/Twig/Runtime.php @@ -48,7 +48,7 @@ use Twig\Extension\RuntimeExtensionInterface; class Runtime implements RuntimeExtensionInterface, EventSubscriberInterface { private Request $request; - public function __constructor(Request $req) + public function setRequest(Request $req) { $this->request = $req; } @@ -103,19 +103,6 @@ class Runtime implements RuntimeExtensionInterface, EventSubscriberInterface return $styles; } - // ---------------------------------------------------------- - - // Request is not a service, can't find a better way to get it - public function onKernelRequest(RequestEvent $event) - { - $this->request = $event->getRequest(); - } - - public static function getSubscribedEvents() - { - return [KernelEvents::REQUEST => 'onKernelRequest']; - } - /** * Renders the Svg Icon template and returns it. * @@ -142,4 +129,17 @@ class Runtime implements RuntimeExtensionInterface, EventSubscriberInterface return ''; } } + + // ---------------------------------------------------------- + + // Request is not a service, can't find a better way to get it + public function onKernelRequest(RequestEvent $event) + { + $this->request = $event->getRequest(); + } + + public static function getSubscribedEvents() + { + return [KernelEvents::REQUEST => 'onKernelRequest']; + } } diff --git a/src/Util/Common.php b/src/Util/Common.php index 6966580b72..31ca0bae01 100644 --- a/src/Util/Common.php +++ b/src/Util/Common.php @@ -68,7 +68,7 @@ abstract class Common public static function setConfig(string $section, string $setting, $value): void { self::$config[$section][$setting] = $value; - $diff = self::array_diff_recursive(self::$config, self::$defaults); + $diff = self::arrayDiffRecursive(self::$config, self::$defaults); $yaml = (new Yaml\Dumper(indentation: 2))->dump(['parameters' => ['gnusocial' => $diff]], Yaml\Yaml::DUMP_OBJECT_AS_MAP); rename(INSTALLDIR . '/social.local.yaml', INSTALLDIR . '/social.local.yaml.back'); file_put_contents(INSTALLDIR . '/social.local.yaml', $yaml); @@ -143,13 +143,13 @@ abstract class Common * @param mixed $array1 * @param mixed $array2 */ - public static function array_diff_recursive($array1, $array2): array + public static function arrayDiffRecursive($array1, $array2): array { $diff = []; foreach ($array1 as $key => $value) { if (array_key_exists($key, $array2)) { if (is_array($value)) { - $recursive_diff = static::array_diff_recursive($value, $array2[$key]); + $recursive_diff = static::arrayDiffRecursive($value, $array2[$key]); if (count($recursive_diff)) { $diff[$key] = $recursive_diff; } @@ -207,6 +207,10 @@ abstract class Common case 'K': $size *= 1024; break; + default: + if ($suffix >= '0' && $suffix <= '9') { + $size = (int) "{$size}{$suffix}"; + } } return $size; } diff --git a/src/Util/Formatting.php b/src/Util/Formatting.php index 0d1a987aa8..d3e4a49735 100644 --- a/src/Util/Formatting.php +++ b/src/Util/Formatting.php @@ -30,10 +30,10 @@ namespace App\Util; -use const DIRECTORY_SEPARATOR; +use App\Core\Log; +use App\Util\Exception\ServerException; use Functional as F; use InvalidArgumentException; -use Symfony\Component\Config\Definition\Exception\Exception; abstract class Formatting { @@ -46,10 +46,7 @@ abstract class Formatting */ public static function normalizePath(string $path): string { - if (DIRECTORY_SEPARATOR !== '/') { - $path = strtr($path, DIRECTORY_SEPARATOR, '/'); - } - return $path; + return str_replace(['/', '\\'], ['/', '/'], $path); } /** @@ -59,22 +56,27 @@ abstract class Formatting * * @return null|string */ - public static function pluginFromPath(string $path): ?string + public static function moduleFromPath(string $path): ?string { - $plug = strpos($path, '/plugins/'); - if ($plug === false) { - return null; + foreach (['/plugins/', '/components/'] as $mod_p) { + $module = strpos($path, $mod_p); + if ($module === false) { + continue; + } + $cut = $module + strlen($mod_p); + $cut2 = strpos($path, '/', $cut); + if ($cut2) { + $final = substr($path, $cut, $cut2 - $cut); + } else { + // We might be running directly from the plugins dir? + // If so, there's no place to store locale info. + $m = 'The GNU social install dir seems to contain a piece named \'plugin\' or \'component\''; + Log::critical($m); + throw new ServerException($m); + } + return $final; } - $cut = $plug + strlen('/plugins/'); - $cut2 = strpos($path, '/', $cut); - if ($cut2) { - $final = substr($path, $cut, $cut2 - $cut); - } else { - // We might be running directly from the plugins dir? - // If so, there's no place to store locale info. - throw new Exception('The GNU social install dir seems to contain a piece named plugin'); - } - return $final; + return null; } /** @@ -157,7 +159,9 @@ abstract class Formatting } const SPLIT_BY_SPACE = ' '; + const JOIN_BY_SPACE = ' '; const SPLIT_BY_COMMA = ', '; + const JOIN_BY_COMMA = ', '; const SPLIT_BY_BOTH = '/[, ]/'; /** @@ -165,12 +169,16 @@ abstract class Formatting * * @param mixed $value */ - public static function toString($value, string $split_type = self::SPLIT_BY_COMMA): string + public static function toString($value, string $join_type = self::JOIN_BY_COMMA): string { - if (!is_array($value)) { - return (string) $value; + if (!in_array($join_type, [static::JOIN_BY_SPACE, static::JOIN_BY_COMMA])) { + throw new \Exception('Formatting::toString received invalid join option'); } else { - return implode($split_type, $value); + if (!is_array($value)) { + return (string) $value; + } else { + return implode($join_type, $value); + } } } @@ -181,6 +189,13 @@ abstract class Formatting */ public static function toArray(string $input, &$output, string $split_type = self::SPLIT_BY_COMMA): bool { + if (!in_array($split_type, [static::SPLIT_BY_SPACE, static::SPLIT_BY_COMMA, static::SPLIT_BY_BOTH])) { + throw new \Exception('Formatting::toArray received invalid split option'); + } + if ($input == '') { + $output = []; + return true; + } $matches = []; if (preg_match('/^ *\[?([^,]+(, ?[^,]+)*)\]? *$/', $input, $matches)) { switch ($split_type) { diff --git a/src/Util/HTML.php b/src/Util/HTML.php index 04d7a8ce9c..d481aea067 100644 --- a/src/Util/HTML.php +++ b/src/Util/HTML.php @@ -61,7 +61,8 @@ abstract class HTML if (empty($content) || $empty_tag) { $html .= '>'; } else { - $html .= ">\n" . Common::indent($content) . "\n" . Common::indent(""); + $inner = Formatting::indent($content); + $html .= ">\n" . ($inner == '' ? '' : $inner . "\n") . Formatting::indent(""); } return explode("\n", $html); } @@ -92,13 +93,13 @@ abstract class HTML } elseif (is_array($html)) { $out = ''; foreach ($html as $tag => $contents) { - if (isset($contents['empty'])) { - $out .= "<{$tag}>"; + if ($contents == 'empty' || isset($contents['empty'])) { + $out .= "<{$tag}/>"; } else { $attrs = isset($contents['attrs']) ? self::attr(array_shift($contents)) : ''; $is_tag = preg_match('/[A-Za-z][A-Za-z0-9]*/', $tag); $inner = self::html($contents); - $inner = $is_tag ? Common::indent($inner) : $inner; + $inner = $is_tag ? Formatting::indent($inner) : $inner; $out .= $is_tag ? "<{$tag}{$attrs}>\n{$inner}\n\n" : $inner; } } diff --git a/tests/Core/DB/UpdateListenerTest.php b/tests/Core/DB/UpdateListenerTest.php index 5ea25fdd3e..d922fe6671 100644 --- a/tests/Core/DB/UpdateListenerTest.php +++ b/tests/Core/DB/UpdateListenerTest.php @@ -34,8 +34,9 @@ class UpdateListenerTest extends KernelTestCase { static::bootKernel(); $actor = new GSActor(); - $actor->setModified(new DateTime('1999-09-23')); - static::assertSame($actor->getModified(), new DateTime('1999-09-23')); + $date = new DateTime('1999-09-23'); + $actor->setModified($date); + static::assertSame($actor->getModified(), $date); $em = $this->createMock(EntityManager::class); $uow = $this->createMock(UnitOfWork::class); @@ -53,6 +54,6 @@ class UpdateListenerTest extends KernelTestCase $ul = new UpdateListener(); $ul->preUpdate($args); - static::assertNotSame($actor->getModified(), new DateTime('1999-09-23')); + static::assertNotSame($actor->getModified(), $date); } } diff --git a/tests/Twig/ExtensionTest.php b/tests/Twig/ExtensionTest.php index 83c2af6d77..3ba126c568 100644 --- a/tests/Twig/ExtensionTest.php +++ b/tests/Twig/ExtensionTest.php @@ -37,6 +37,7 @@ use App\Twig\Extension; use App\Twig\Runtime; use DirectoryIterator; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Symfony\Component\HttpFoundation\Request; class ExtensionTest extends KernelTestCase { @@ -72,4 +73,20 @@ class ExtensionTest extends KernelTestCase static::assertSame($icon_template_render, $icon_extension_render); } } + + public function testIsCurrentRouteActive() + { + $req = $this->createMock(Request::class); + $req->attributes = new class { + public function get(string $arg) + { + return 'current_route'; + } + }; + $runtime = new Runtime; + $runtime->setRequest($req); + + static::assertSame('active', $runtime->isCurrentRouteActive('current_route')); + static::assertSame('', $runtime->isCurrentRouteActive('some_route', 'some_other_route')); + } } diff --git a/tests/Util/CommonTest.php b/tests/Util/CommonTest.php index 30f54650d8..731638dbff 100644 --- a/tests/Util/CommonTest.php +++ b/tests/Util/CommonTest.php @@ -17,7 +17,7 @@ // along with GNU social. If not, see . // }}} -namespace App\Tests\Util\Common; +namespace App\Tests\Util; use App\Core\Event; use App\Core\Router\Router; @@ -29,14 +29,6 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CommonTest extends WebTestCase { - public function testClamp() - { - static::assertSame(2, Common::clamp(value: 2, min: 0, max: 3)); - static::assertSame(2, Common::clamp(value: 2, min: 2, max: 3)); - static::assertSame(1, Common::clamp(value: 2, min: 0, max: 1)); - static::assertSame(3, Common::clamp(value: 2, min: 3, max: 5)); - } - public function testSetConfig() { $conf = ['test' => ['hydrogen' => 'helium']]; @@ -78,16 +70,43 @@ class CommonTest extends WebTestCase public function testArrayDiffRecursive() { - static::assertSame(['foo'], Common::array_diff_recursive(['foo'], ['bar'])); - static::assertSame([], Common::array_diff_recursive(['foo'], ['foo'])); + static::assertSame(['foo'], Common::arrayDiffRecursive(['foo'], ['bar'])); + static::assertSame([], Common::arrayDiffRecursive(['foo'], ['foo'])); // array_diff(['foo' => []], ['foo' => 'bar']) >>> Array to string conversion - static::assertSame([], Common::array_diff_recursive(['foo' => []], ['foo' => 'bar'])); - static::assertSame([], Common::array_diff_recursive(['foo' => ['bar']], ['foo' => ['bar']])); - static::assertSame(['foo' => [1 => 'quux']], Common::array_diff_recursive(['foo' => ['bar', 'quux']], ['foo' => ['bar']])); - static::assertSame([], Common::array_diff_recursive(['hydrogen' => ['helium' => ['lithium'], 'boron' => 'carbon']], + static::assertSame([], Common::arrayDiffRecursive(['foo' => []], ['foo' => 'bar'])); + static::assertSame([], Common::arrayDiffRecursive(['foo' => ['bar']], ['foo' => ['bar']])); + static::assertSame(['foo' => [1 => 'quux']], Common::arrayDiffRecursive(['foo' => ['bar', 'quux']], ['foo' => ['bar']])); + static::assertSame([], Common::arrayDiffRecursive(['hydrogen' => ['helium' => ['lithium'], 'boron' => 'carbon']], ['hydrogen' => ['helium' => ['lithium'], 'boron' => 'carbon']])); static::assertSame(['hydrogen' => ['helium' => ['lithium']]], - Common::array_diff_recursive(['hydrogen' => ['helium' => ['lithium'], 'boron' => 'carbon']], + Common::arrayDiffRecursive(['hydrogen' => ['helium' => ['lithium'], 'boron' => 'carbon']], ['hydrogen' => ['helium' => ['beryllium'], 'boron' => 'carbon']])); } + + public function testArrayRemoveKeys() + { + static::assertSame([1 => 'helium'], Common::arrayRemoveKeys(['hydrogen', 'helium'], [0])); + static::assertSame(['helium' => 'bar'], Common::arrayRemoveKeys(['hydrogen' => 'foo', 'helium' => 'bar'], ['hydrogen'])); + } + + public function testSizeStrToInt() + { + static::assertSame(pow(1024, 0), Common::sizeStrToInt('1')); + static::assertSame(pow(1024, 1), Common::sizeStrToInt('1K')); + static::assertSame(pow(1024, 2), Common::sizeStrToInt('1M')); + static::assertSame(pow(1024, 3), Common::sizeStrToInt('1G')); + static::assertSame(pow(1024, 4), Common::sizeStrToInt('1T')); + static::assertSame(pow(1024, 5), Common::sizeStrToInt('1P')); + static::assertSame(128, Common::sizeStrToInt('128')); + static::assertSame(128 * 1024, Common::sizeStrToInt('128K')); + static::assertSame(128 * 1024, Common::sizeStrToInt('128.5K')); + } + + public function testClamp() + { + static::assertSame(2, Common::clamp(value: 2, min: 0, max: 3)); + static::assertSame(2, Common::clamp(value: 2, min: 2, max: 3)); + static::assertSame(1, Common::clamp(value: 2, min: 0, max: 1)); + static::assertSame(3, Common::clamp(value: 2, min: 3, max: 5)); + } } diff --git a/tests/Util/Form/ActorArrayTransformerTest.php b/tests/Util/Form/ActorArrayTransformerTest.php index 049c9598cd..d49b911818 100644 --- a/tests/Util/Form/ActorArrayTransformerTest.php +++ b/tests/Util/Form/ActorArrayTransformerTest.php @@ -17,7 +17,7 @@ // along with GNU social. If not, see . // }}} -namespace App\Tests\Util\Form\ActorArrayTransformer; +namespace App\Tests\Util\Form; use App\Entity\GSActor; use App\Util\Form\ActorArrayTransformer; diff --git a/tests/Util/Form/ArrayTransformerTest.php b/tests/Util/Form/ArrayTransformerTest.php new file mode 100644 index 0000000000..c1a97dac76 --- /dev/null +++ b/tests/Util/Form/ArrayTransformerTest.php @@ -0,0 +1,38 @@ +. +// }}} + +namespace App\Tests\Util\Form; + +use App\Util\Form\ArrayTransformer; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + +class ArrayTransformerTest extends WebTestCase +{ + public function testTransform() + { + static::assertSame('', (new ArrayTransformer)->transform([])); + static::assertSame('foo bar quux', (new ArrayTransformer)->transform(['foo', 'bar', 'quux'])); + } + + public function testReverseTransform() + { + static::assertSame([], (new ArrayTransformer)->reverseTransform('')); + static::assertSame(['foo', 'bar', 'quux'], (new ArrayTransformer)->reverseTransform('foo bar quux')); + } +} diff --git a/tests/Util/FormattingTest.php b/tests/Util/FormattingTest.php new file mode 100644 index 0000000000..6ccfa4abdc --- /dev/null +++ b/tests/Util/FormattingTest.php @@ -0,0 +1,141 @@ +. +// }}} + +namespace App\Tests\Util; + +use App\Util\Formatting; +use Jchook\AssertThrows\AssertThrows; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + +class FormattingTest extends WebTestCase +{ + use AssertThrows; + + public function testNormalizePath() + { + static::assertSame('/foo/bar', Formatting::normalizePath('/foo/bar')); + static::assertSame('/foo/bar', Formatting::normalizePath('\\foo\\bar')); + static::assertSame('/foo/bar', Formatting::normalizePath('\\foo/bar')); + static::assertSame('/foo/bar/', Formatting::normalizePath('/foo\\bar\\')); + } + + public function testModuleFromPath() + { + static::assertNull(Formatting::moduleFromPath('/var/www/social/src/Kernel.php')); + static::assertSame('foo', Formatting::moduleFromPath('/var/www/social/plugins/foo/Foo.php')); + static::assertSame('foo', Formatting::moduleFromPath('/var/www/social/components/foo/Foo.php')); + } + + public function testStartsWithString() + { + static::assertTrue(Formatting::startsWith('foobar', 'foo')); + static::assertTrue(Formatting::startsWith('foo', 'foo')); + static::assertFalse(Formatting::startsWith('bar', 'foo')); + static::assertFalse(Formatting::startsWith('', 'foo')); + static::assertFalse(Formatting::startsWith('fo', 'foo')); + static::assertFalse(Formatting::startsWith('oo', 'foo')); + } + + public function testStartsWithArray() + { + static::assertTrue(Formatting::startsWith(['foobar', 'fooquux'], 'foo')); + static::assertTrue(Formatting::startsWith(['foo', 'foo'], 'foo')); + static::assertTrue(Formatting::startsWith(['foo1', 'foo2', 'foo3'], 'foo')); + static::assertFalse(Formatting::startsWith(['foobar', 'barquux'], 'foo')); + static::assertFalse(Formatting::startsWith(['', '', ''], 'foo')); + static::assertFalse(Formatting::startsWith(['fo', 'fo'], 'foo')); + static::assertFalse(Formatting::startsWith(['oo', 'oo'], 'foo')); + } + + public function testEndsWithString() + { + static::assertTrue(Formatting::endsWith('foobar', 'bar')); + static::assertTrue(Formatting::endsWith('foo', 'foo')); + static::assertFalse(Formatting::endsWith('bar', 'foo')); + static::assertFalse(Formatting::endsWith('', 'foo')); + static::assertFalse(Formatting::endsWith('fo', 'foo')); + static::assertFalse(Formatting::endsWith('oo', 'foo')); + } + + public function testEndsWithArray() + { + static::assertTrue(Formatting::endsWith(['foobar', 'quuxbar'], 'bar')); + static::assertTrue(Formatting::endsWith(['foo', 'foo'], 'foo')); + static::assertTrue(Formatting::endsWith(['qwefoo', 'zxcfoo', 'asdfoo'], 'foo')); + static::assertFalse(Formatting::endsWith(['barfoo', 'quuxbar'], 'foo')); + static::assertFalse(Formatting::endsWith(['', '', ''], 'foo')); + static::assertFalse(Formatting::endsWith(['fo', 'fo'], 'foo')); + static::assertFalse(Formatting::endsWith(['oo', 'oo'], 'foo')); + } + + public function testCamelCaseToSnakeCase() + { + static::assertSame('foo_bar', Formatting::camelCaseToSnakeCase('FooBar')); + static::assertSame('foo_bar_quux', Formatting::camelCaseToSnakeCase('FooBarQuux')); + static::assertSame('foo_bar', Formatting::camelCaseToSnakeCase('foo_bar')); + static::assertSame('', Formatting::camelCaseToSnakeCase('')); + } + + public function testSnakeCaseToCamelCase() + { + static::assertSame('FooBar', Formatting::snakeCaseToCamelCase('foo_bar')); + static::assertSame('FooBarQuux', Formatting::snakeCaseToCamelCase('foo_bar_quux')); + static::assertSame('FooBar', Formatting::snakeCaseToCamelCase('FooBar')); + static::assertSame('', Formatting::snakeCaseToCamelCase('')); + } + + public function testIndent() + { + static::assertSame(' foo', Formatting::indent('foo')); + static::assertSame(' foo', Formatting::indent('foo', level: 1, count: 2)); + static::assertSame(" foo\n bar", Formatting::indent("foo\nbar")); + static::assertSame(" foo\n bar", Formatting::indent(['foo', 'bar'])); + } + + public function testToString() + { + static::assertThrows(\Exception::class, function () { return Formatting::toString('foo', ''); }); + static::assertSame('', Formatting::toString('')); + static::assertSame('foo', Formatting::toString('foo')); + static::assertSame('42', Formatting::toString(42)); + static::assertSame('42, 1', Formatting::toString([42.0, 1])); + static::assertSame('42 1', Formatting::toString([42.0, 1], Formatting::JOIN_BY_SPACE)); + } + + public function testToArray() + { + static::assertThrows(\Exception::class, function () { return Formatting::toArray('foo', $a, ''); }); + + static::assertTrue(Formatting::toArray('', $a)); + static::assertSame([], $a); + + static::assertTrue(Formatting::toArray('foo', $a)); + static::assertSame(['foo'], $a); + + static::assertTrue(Formatting::toArray('foo, bar', $a)); + static::assertSame(['foo', 'bar'], $a); + + static::assertTrue(Formatting::toArray('foo bar', $a, Formatting::SPLIT_BY_SPACE)); + static::assertSame(['foo', 'bar'], $a); + + static::assertFalse(Formatting::toArray('foo,', $a)); + static::assertTrue(Formatting::toArray('foo, ', $a)); + static::assertSame(['foo', ''], $a); + } +} diff --git a/tests/Util/HTMLTest.php b/tests/Util/HTMLTest.php new file mode 100644 index 0000000000..8558e09789 --- /dev/null +++ b/tests/Util/HTMLTest.php @@ -0,0 +1,34 @@ +. +// }}} + +namespace App\Tests\Util; + +use App\Util\HTML; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; + +class HTMLTest extends WebTestCase +{ + public function testHTML() + { + static::assertSame('', HTML::html('')); + static::assertSame("\n\n\n", HTML::html(['a' => ''])); + static::assertSame("\n

\n

\n
\n", HTML::html(['a' => ['p' => '']])); + static::assertSame("\n

\n foo\n

\n
\n
\n", HTML::html(['a' => ['p' => 'foo', 'br' => 'empty']])); + } +} diff --git a/tests/Util/NicknameTest.php b/tests/Util/NicknameTest.php new file mode 100644 index 0000000000..b27a428a56 --- /dev/null +++ b/tests/Util/NicknameTest.php @@ -0,0 +1,73 @@ +. +// }}} + +namespace App\Tests\Util; + +use App\Util\Common; +use App\Util\Exception\NicknameEmptyException; +use App\Util\Exception\NicknameInvalidException; +use App\Util\Exception\NicknameReservedException; +use App\Util\Exception\NicknameTooShortException; +use App\Util\Nickname; +use Jchook\AssertThrows\AssertThrows; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; + +class NicknameTest extends WebTestCase +{ + use AssertThrows; + + public function testNormalize() + { + $conf = ['nickname' => ['min_length' => 4, 'reserved' => ['this_nickname_is_reserved']]]; + $cb = $this->createMock(ContainerBagInterface::class); + static::assertTrue($cb instanceof ContainerBagInterface); + $cb->method('get') + ->willReturnMap([['gnusocial', $conf], ['gnusocial_defaults', $conf]]); + Common::setupConfig($cb); + + static::assertSame('foobar', Nickname::normalize('foobar', check_already_used: false)); + static::assertSame('foobar', Nickname::normalize(' foobar ', check_already_used: false)); + static::assertSame('foobar', Nickname::normalize('foo_bar', check_already_used: false)); + static::assertSame('foobar', Nickname::normalize('FooBar', check_already_used: false)); + static::assertThrows(NicknameTooShortException::class, function () { return Nickname::normalize('foo', check_already_used: false); }); + static::assertThrows(NicknameEmptyException::class, function () { return Nickname::normalize('', check_already_used: false); }); + static::assertThrows(NicknameInvalidException::class, function () { return Nickname::normalize('FóóBár', check_already_used: false); }); + static::assertThrows(NicknameReservedException::class, function () { return Nickname::normalize('this_nickname_is_reserved', check_already_used: false); }); + } + + public function testIsCanonical() + { + static::assertTrue(Nickname::isCanonical('foo')); + static::assertFalse(Nickname::isCanonical('fóó')); + } + + public function testIsReserved() + { + $conf = ['nickname' => ['min_length' => 4, 'reserved' => ['this_nickname_is_reserved']]]; + $cb = $this->createMock(ContainerBagInterface::class); + static::assertTrue($cb instanceof ContainerBagInterface); + $cb->method('get') + ->willReturnMap([['gnusocial', $conf], ['gnusocial_defaults', $conf]]); + Common::setupConfig($cb); + + static::assertTrue(Nickname::isReserved('this_nickname_is_reserved')); + static::assertFalse(Nickname::isReserved('this_nickname_is_not_reserved')); + } +}