diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 5b796f6c4..8af7496a4 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: 8.1 + php-version: 8.3 coverage: none - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: 8.1 + php-version: 8.3 coverage: none - run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8e477912d..966a05ac9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,9 +22,9 @@ jobs: - run: composer install --no-progress --prefer-dist - run: vendor/bin/tester tests -s -C - if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: output + name: output-${{ matrix.php }} path: tests/**/output @@ -40,11 +40,6 @@ jobs: - run: composer update --no-progress --prefer-dist --prefer-lowest --prefer-stable - run: vendor/bin/tester tests -s -C - - if: failure() - uses: actions/upload-artifact@v3 - with: - name: output - path: tests/**/output code_coverage: diff --git a/composer.json b/composer.json index 1e6bec6c2..60773f3e8 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "require": { "php": "8.1 - 8.4", "nette/component-model": "^3.1", - "nette/http": "^3.3", + "nette/http": "^3.3.2", "nette/routing": "^3.1", "nette/utils": "^4.0" }, @@ -26,12 +26,12 @@ "latte/latte": "Allows using Latte in templates" }, "require-dev": { - "nette/tester": "^2.5", + "nette/tester": "^2.5.2", "nette/di": "^3.2", "nette/forms": "^3.2", "nette/robot-loader": "^4.0", "nette/security": "^3.2", - "latte/latte": "^2.10.2 || ^3.0.18", + "latte/latte": "^3.0.18", "tracy/tracy": "^2.9", "mockery/mockery": "^1.6@stable", "phpstan/phpstan-nette": "^2.0@stable", @@ -42,7 +42,7 @@ "nette/di": "<3.2", "nette/forms": "<3.2", "nette/schema": "<1.3", - "latte/latte": "<2.7.1 || >=3.0.0 <3.0.18 || >=3.1", + "latte/latte": "<3.0.18", "tracy/tracy": "<2.9" }, "autoload": { @@ -58,7 +58,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "4.0-dev" } } } diff --git a/readme.md b/readme.md index d8e52ef86..b4b61840e 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ Nette Application MVC ===================== [![Downloads this Month](https://img.shields.io/packagist/dm/nette/application.svg)](https://packagist.org/packages/nette/application) -[![Tests](https://github.com/nette/application/actions/workflows/tests.yml/badge.svg?branch=v3.2)](https://github.com/nette/application/actions) +[![Tests](https://github.com/nette/application/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/nette/application/actions) [![Latest Stable Version](https://poser.pugx.org/nette/application/v/stable)](https://github.com/nette/application/releases) [![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/nette/application/blob/master/license.md) diff --git a/src/Application/Application.php b/src/Application/Application.php index a22e4caec..85c3df9d5 100644 --- a/src/Application/Application.php +++ b/src/Application/Application.php @@ -12,6 +12,7 @@ use Nette; use Nette\Routing\Router; use Nette\Utils\Arrays; +use function count, is_string, str_starts_with, strcasecmp; /** @@ -73,7 +74,7 @@ public function run(): void { try { Arrays::invoke($this->onStartup, $this); - $this->processRequest($this->createInitialRequest()); + $this->processRequest($this->createInitialRequest())->send($this->httpRequest, $this->httpResponse); Arrays::invoke($this->onShutdown, $this); } catch (\Throwable $e) { @@ -81,7 +82,7 @@ public function run(): void Arrays::invoke($this->onError, $this, $e); if ($this->catchExceptions && ($req = $this->createErrorRequest($e))) { try { - $this->processRequest($req); + $this->processRequest($req)->send($this->httpRequest, $this->httpResponse); Arrays::invoke($this->onShutdown, $this, $e); return; @@ -120,7 +121,7 @@ public function createInitialRequest(): Request } - public function processRequest(Request $request): void + public function processRequest(Request $request): Response { process: if (count($this->requests) > $this->maxLoop) { @@ -155,7 +156,7 @@ public function processRequest(Request $request): void } Arrays::invoke($this->onResponse, $this, $response); - $response->send($this->httpRequest, $this->httpResponse); + return $response; } diff --git a/src/Application/Helpers.php b/src/Application/Helpers.php index 5883d69c3..51b266cea 100644 --- a/src/Application/Helpers.php +++ b/src/Application/Helpers.php @@ -10,6 +10,7 @@ namespace Nette\Application; use Nette; +use function class_parents, class_uses, strrpos, substr; /** diff --git a/src/Application/LinkGenerator.php b/src/Application/LinkGenerator.php index ad2a70e7a..f53d629ea 100644 --- a/src/Application/LinkGenerator.php +++ b/src/Application/LinkGenerator.php @@ -12,6 +12,7 @@ use Nette\Http\UrlScript; use Nette\Routing\Router; use Nette\Utils\Reflection; +use function array_intersect_key, array_key_exists, http_build_query, is_string, is_subclass_of, parse_str, preg_match, rtrim, str_contains, str_ends_with, strcasecmp, strlen, strncmp, strtr, substr, trigger_error, urldecode; /** @@ -242,6 +243,7 @@ public static function parseDestination(string $destination): array } if (!empty($matches['query'])) { + trigger_error("Link format is obsolete, use arguments instead of query string in '$destination'.", E_USER_DEPRECATED); parse_str(substr($matches['query'], 1), $args); } diff --git a/src/Application/MicroPresenter.php b/src/Application/MicroPresenter.php index 7ee8b0db4..b68eea59e 100644 --- a/src/Application/MicroPresenter.php +++ b/src/Application/MicroPresenter.php @@ -15,6 +15,7 @@ use Nette\Application\Responses; use Nette\Http; use Nette\Routing\Router; +use function is_array, is_object, is_string; /** diff --git a/src/Application/PresenterFactory.php b/src/Application/PresenterFactory.php index e57f749c1..571b9ee72 100644 --- a/src/Application/PresenterFactory.php +++ b/src/Application/PresenterFactory.php @@ -10,6 +10,7 @@ namespace Nette\Application; use Nette; +use function array_shift, class_exists, count, explode, is_array, is_string, preg_match, strtr; /** @@ -19,7 +20,7 @@ class PresenterFactory implements IPresenterFactory { /** @var array[] of module => splited mask */ private array $mapping = [ - '*' => ['', '*Module\\', '*Presenter'], + '*' => ['App\Presentation\\', '*\\', '**Presenter'], 'Nette' => ['NetteModule\\', '*\\', '*Presenter'], ]; diff --git a/src/Application/Request.php b/src/Application/Request.php index 05ff89ab5..3640bfb81 100644 --- a/src/Application/Request.php +++ b/src/Application/Request.php @@ -10,16 +10,17 @@ namespace Nette\Application; use Nette; +use function func_num_args, strcasecmp; /** * Presenter request. * - * @property string $presenterName - * @property array $parameters - * @property array $post - * @property array $files - * @property string|null $method + * @property-deprecated string $presenterName + * @property-deprecated array $parameters + * @property-deprecated array $post + * @property-deprecated array $files + * @property-deprecated string|null $method */ final class Request { diff --git a/src/Application/Responses/FileResponse.php b/src/Application/Responses/FileResponse.php index 958f86dc5..4a74f3364 100644 --- a/src/Application/Responses/FileResponse.php +++ b/src/Application/Responses/FileResponse.php @@ -10,6 +10,7 @@ namespace Nette\Application\Responses; use Nette; +use function strlen; /** diff --git a/src/Application/Routers/CliRouter.php b/src/Application/Routers/CliRouter.php index ea28f2188..7e261fdf0 100644 --- a/src/Application/Routers/CliRouter.php +++ b/src/Application/Routers/CliRouter.php @@ -10,6 +10,7 @@ namespace Nette\Application\Routers; use Nette; +use function is_array; /** diff --git a/src/Application/Routers/Route.php b/src/Application/Routers/Route.php index ba611da0e..628e5ced5 100644 --- a/src/Application/Routers/Route.php +++ b/src/Application/Routers/Route.php @@ -10,6 +10,7 @@ namespace Nette\Application\Routers; use Nette; +use function is_string, lcfirst, preg_replace, rawurlencode, str_replace, strlen, strncmp, strrpos, strtolower, strtr, substr, ucwords; /** @@ -187,6 +188,3 @@ public static function path2presenter(string $s): string return $s; } } - - -interface_exists(Nette\Application\IRouter::class); diff --git a/src/Application/Routers/RouteList.php b/src/Application/Routers/RouteList.php index 99e2a6d17..e7af4eaee 100644 --- a/src/Application/Routers/RouteList.php +++ b/src/Application/Routers/RouteList.php @@ -11,6 +11,7 @@ use JetBrains\PhpStorm\Language; use Nette; +use function count, is_int, is_string, strlen, strncmp, substr; /** @@ -95,6 +96,13 @@ public function getModule(): ?string */ public function offsetSet($index, $router): void { + if ($router instanceof Route) { + trigger_error('Usage `$router[] = new Route(...)` is deprecated, use `$router->addRoute(...)`.', E_USER_DEPRECATED); + } else { + $class = getclass($router); + trigger_error("Usage `\$router[] = new $class` is deprecated, use `\$router->add(new $class)`.", E_USER_DEPRECATED); + } + if ($index === null) { $this->add($router); } else { @@ -109,6 +117,7 @@ public function offsetSet($index, $router): void */ public function offsetGet($index): Nette\Routing\Router { + trigger_error('Usage `$route = $router[...]` is deprecated, use `$router->getRouters()`.', E_USER_DEPRECATED); if (!$this->offsetExists($index)) { throw new Nette\OutOfRangeException('Offset invalid or out of range'); } @@ -122,6 +131,7 @@ public function offsetGet($index): Nette\Routing\Router */ public function offsetExists($index): bool { + trigger_error('Usage `isset($router[...])` is deprecated.', E_USER_DEPRECATED); return is_int($index) && $index >= 0 && $index < count($this->getRouters()); } @@ -132,6 +142,7 @@ public function offsetExists($index): bool */ public function offsetUnset($index): void { + trigger_error('Usage `unset($router[$index])` is deprecated, use `$router->modify($index, null)`.', E_USER_DEPRECATED); if (!$this->offsetExists($index)) { throw new Nette\OutOfRangeException('Offset invalid or out of range'); } @@ -139,6 +150,3 @@ public function offsetUnset($index): void $this->modify($index, null); } } - - -interface_exists(Nette\Application\IRouter::class); diff --git a/src/Application/Routers/SimpleRouter.php b/src/Application/Routers/SimpleRouter.php index 35d2c8ad9..c8e8c49b3 100644 --- a/src/Application/Routers/SimpleRouter.php +++ b/src/Application/Routers/SimpleRouter.php @@ -11,6 +11,7 @@ use Nette; use Nette\Application; +use function is_string; /** @@ -38,6 +39,3 @@ public function __construct(array|string $defaults = []) parent::__construct($defaults); } } - - -interface_exists(Nette\Application\IRouter::class); diff --git a/src/Application/UI/AccessPolicy.php b/src/Application/UI/AccessPolicy.php index 7757cdd67..6b821ddb2 100644 --- a/src/Application/UI/AccessPolicy.php +++ b/src/Application/UI/AccessPolicy.php @@ -12,6 +12,7 @@ use Nette; use Nette\Application\Attributes; use Nette\Utils\Reflection; +use function array_map, implode, in_array, str_starts_with, strtoupper; /** diff --git a/src/Application/UI/Component.php b/src/Application/UI/Component.php index f0efe3ed9..82adb6199 100644 --- a/src/Application/UI/Component.php +++ b/src/Application/UI/Component.php @@ -10,6 +10,7 @@ namespace Nette\Application\UI; use Nette; +use function array_key_exists, count, func_get_arg, func_num_args, get_debug_type, is_array, link, method_exists, sprintf, trigger_error; /** @@ -19,8 +20,8 @@ * other child components, and interact with user. Components have properties * for storing their status, and responds to user command. * - * @property-read Presenter $presenter - * @property-read bool $linkCurrent + * @property-deprecated Presenter $presenter + * @property-deprecated bool $linkCurrent */ abstract class Component extends Nette\ComponentModel\Container implements SignalReceiver, StatePersistent, \ArrayAccess { @@ -71,18 +72,27 @@ public function getUniqueId(): string } + public function addComponent( + Nette\ComponentModel\IComponent $component, + ?string $name, + ?string $insertBefore = null, + ): static + { + if (!$component instanceof SignalReceiver && !$component instanceof StatePersistent) { + throw new Nette\InvalidStateException("Component '$name' of type " . get_debug_type($component) . ' is not intended to be used in the Presenter.'); + } + + return parent::addComponent($component, $name, $insertBefore = null); + } + + protected function createComponent(string $name): ?Nette\ComponentModel\IComponent { if (method_exists($this, $method = 'createComponent' . $name)) { - (new AccessPolicy($this, new \ReflectionMethod($this, $method)))->checkAccess(); - } - $res = parent::createComponent($name); - if ($res && !$res instanceof SignalReceiver && !$res instanceof StatePersistent) { - $type = $res::class; - trigger_error("It seems that component '$name' of type $type is not intended to be used in the Presenter."); + (new AccessPolicy($this, $rm = new \ReflectionMethod($this, $method)))->checkAccess(); + $this->checkRequirements($rm); } - - return $res; + return parent::createComponent($name); } @@ -161,9 +171,9 @@ public function loadState(array $params): void )); } - $this->$name = $params[$name]; + $this->$name = &$params[$name]; } else { - $params[$name] = $this->$name ?? null; + $params[$name] = &$this->$name; } } @@ -225,6 +235,7 @@ public function saveStatePartial(array &$params, ComponentReflection $reflection final public function getParameter(string $name): mixed { if (func_num_args() > 1) { + trigger_error(__METHOD__ . '() parameter $default is deprecated, use operator ??', E_USER_DEPRECATED); $default = func_get_arg(1); } return $this->params[$name] ?? $default ?? null; @@ -236,7 +247,7 @@ final public function getParameter(string $name): mixed */ final public function getParameters(): array { - return $this->params; + return array_map(fn($item) => $item, $this->params); } @@ -281,19 +292,19 @@ public static function formatSignalMethod(string $signal): string /** * Generates URL to presenter, action or signal. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" - * @param array|mixed $args + * @param mixed ...$args * @throws InvalidLinkException */ - public function link(string $destination, $args = []): string + public function link(string $destination, ...$args): string { try { - $args = func_num_args() < 3 && is_array($args) - ? $args - : array_slice(func_get_args(), 1); + $args = count($args) === 1 && is_array($args[0] ?? null) + ? $args[0] + : $args; return $this->getPresenter()->getLinkGenerator()->link($destination, $args, $this, 'link'); } catch (InvalidLinkException $e) { - return $this->getPresenter()->handleInvalidLink($e); + return $this->getPresenter()->processInvalidLink($e); } } @@ -301,13 +312,13 @@ public function link(string $destination, $args = []): string /** * Returns destination as Link object. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" - * @param array|mixed $args + * @param mixed ...$args */ - public function lazyLink(string $destination, $args = []): Link + public function lazyLink(string $destination, ...$args): Link { - $args = func_num_args() < 3 && is_array($args) - ? $args - : array_slice(func_get_args(), 1); + $args = count($args) === 1 && is_array($args[0] ?? null) + ? $args[0] + : $args; return new Link($this, $destination, $args); } @@ -315,15 +326,15 @@ public function lazyLink(string $destination, $args = []): Link /** * Determines whether it links to the current page. * @param ?string $destination in format "[[[module:]presenter:]action | signal! | this]" - * @param array|mixed $args + * @param mixed ...$args * @throws InvalidLinkException */ - public function isLinkCurrent(?string $destination = null, $args = []): bool + public function isLinkCurrent(?string $destination = null, ...$args): bool { if ($destination !== null) { - $args = func_num_args() < 3 && is_array($args) - ? $args - : array_slice(func_get_args(), 1); + $args = count($args) === 1 && is_array($args[0] ?? null) + ? $args[0] + : $args; $this->getPresenter()->getLinkGenerator()->createRequest($this, $destination, $args, 'test'); } @@ -334,15 +345,14 @@ public function isLinkCurrent(?string $destination = null, $args = []): bool /** * Redirect to another presenter, action or signal. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" - * @param array|mixed $args - * @return never + * @param mixed ...$args * @throws Nette\Application\AbortException */ - public function redirect(string $destination, $args = []): void + public function redirect(string $destination, ...$args): never { - $args = func_num_args() < 3 && is_array($args) - ? $args - : array_slice(func_get_args(), 1); + $args = count($args) === 1 && is_array($args[0] ?? null) + ? $args[0] + : $args; $presenter = $this->getPresenter(); $presenter->saveGlobalState(); $presenter->redirectUrl($presenter->getLinkGenerator()->link($destination, $args, $this, 'redirect')); @@ -352,15 +362,14 @@ public function redirect(string $destination, $args = []): void /** * Permanently redirects to presenter, action or signal. * @param string $destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]" - * @param array|mixed $args - * @return never + * @param mixed ...$args * @throws Nette\Application\AbortException */ - public function redirectPermanent(string $destination, $args = []): void + public function redirectPermanent(string $destination, ...$args): never { - $args = func_num_args() < 3 && is_array($args) - ? $args - : array_slice(func_get_args(), 1); + $args = count($args) === 1 && is_array($args[0] ?? null) + ? $args[0] + : $args; $presenter = $this->getPresenter(); $presenter->redirectUrl( $presenter->getLinkGenerator()->link($destination, $args, $this, 'redirect'), @@ -378,6 +387,3 @@ public function error(string $message = '', int $httpCode = Nette\Http\IResponse throw new Nette\Application\BadRequestException($message, $httpCode); } } - - -class_exists(PresenterComponent::class); diff --git a/src/Application/UI/ComponentReflection.php b/src/Application/UI/ComponentReflection.php index 9886f9916..0d2e2ad70 100644 --- a/src/Application/UI/ComponentReflection.php +++ b/src/Application/UI/ComponentReflection.php @@ -11,12 +11,14 @@ use Nette\Application\Attributes; use Nette\Utils\Reflection; +use function array_fill_keys, array_filter, array_key_exists, array_merge, end, preg_match_all, preg_quote, preg_split, strtolower; +use const PREG_SPLIT_NO_EMPTY; /** * Helpers for Presenter & Component. - * @property-read string $name - * @property-read string $fileName + * @property-deprecated string $name + * @property-deprecated string $fileName * @internal */ final class ComponentReflection extends \ReflectionClass @@ -27,7 +29,7 @@ final class ComponentReflection extends \ReflectionClass /** - * Returns array of class properties that are public and have attribute #[Persistent] or #[Parameter] or annotation @persistent. + * Returns array of class properties that are public and have attribute #[Persistent] or #[Parameter]. * @return array */ public function getParameters(): array @@ -74,7 +76,7 @@ public function getParameters(): array /** - * Returns array of persistent properties. They are public and have attribute #[Persistent] or annotation @persistent. + * Returns array of persistent properties. They are public and have attribute #[Persistent]. * @return array */ public function getPersistentParams(): array @@ -149,6 +151,7 @@ public function getSignalMethod(string $signal): ?\ReflectionMethod /** * Returns an annotation value. + * @deprecated */ public static function parseAnnotation(\Reflector $ref, string $name): ?array { @@ -166,12 +169,20 @@ public static function parseAnnotation(\Reflector $ref, string $name): ?array } } + $alt = match ($name) { + 'persistent' => '#[Nette\Application\Attributes\Persistent]', + 'deprecated' => '#[Nette\Application\Attributes\Deprecated]', + 'crossOrigin' => '#[Nette\Application\Attributes\Request(sameOrigin: false)]', + default => 'alternative' + }; + trigger_error("Annotation @$name is deprecated, use $alt (used in " . Reflection::toString($ref) . ')', E_USER_DEPRECATED); return $res; } /** * Has class specified annotation? + * @deprecated */ public function hasAnnotation(string $name): bool { @@ -181,6 +192,7 @@ public function hasAnnotation(string $name): bool /** * Returns an annotation value. + * @deprecated */ public function getAnnotation(string $name): mixed { @@ -214,6 +226,3 @@ public static function combineArgs(\ReflectionFunctionAbstract $method, array $a return ParameterConverter::toArguments($method, $args); } } - - -class_exists(PresenterComponentReflection::class); diff --git a/src/Application/UI/Control.php b/src/Application/UI/Control.php index a768fa550..24484dc3d 100644 --- a/src/Application/UI/Control.php +++ b/src/Application/UI/Control.php @@ -10,6 +10,7 @@ namespace Nette\Application\UI; use Nette; +use function array_shift, class_exists, count, is_a, preg_replace, sprintf, trigger_error; /** diff --git a/src/Application/UI/Form.php b/src/Application/UI/Form.php index 499ef409f..a5be276de 100644 --- a/src/Application/UI/Form.php +++ b/src/Application/UI/Form.php @@ -10,6 +10,7 @@ namespace Nette\Application\UI; use Nette; +use function func_num_args; /** diff --git a/src/Application/UI/MethodReflection.php b/src/Application/UI/MethodReflection.php index f576deeaf..f84687356 100644 --- a/src/Application/UI/MethodReflection.php +++ b/src/Application/UI/MethodReflection.php @@ -17,18 +17,22 @@ final class MethodReflection extends \ReflectionMethod { /** * Has method specified annotation? + * @deprecated */ public function hasAnnotation(string $name): bool { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); return (bool) ComponentReflection::parseAnnotation($this, $name); } /** * Returns an annotation value. + * @deprecated */ public function getAnnotation(string $name): mixed { + trigger_error(__METHOD__ . '() is deprecated', E_USER_DEPRECATED); $res = ComponentReflection::parseAnnotation($this, $name); return $res ? end($res) : null; } diff --git a/src/Application/UI/ParameterConverter.php b/src/Application/UI/ParameterConverter.php index 063aea419..c41935be4 100644 --- a/src/Application/UI/ParameterConverter.php +++ b/src/Application/UI/ParameterConverter.php @@ -11,6 +11,7 @@ use Nette; use Nette\Utils\Reflection; +use function array_key_exists, explode, get_debug_type, is_array, is_scalar, ltrim, preg_replace, settype, sprintf; /** diff --git a/src/Application/UI/Presenter.php b/src/Application/UI/Presenter.php index 39a441f49..bd24e48cd 100644 --- a/src/Application/UI/Presenter.php +++ b/src/Application/UI/Presenter.php @@ -16,18 +16,20 @@ use Nette\Application\Responses; use Nette\Http; use Nette\Utils\Arrays; +use function array_slice, count, dirname, func_get_args, func_num_args, implode, in_array, is_array, is_dir, is_file, is_string, ltrim, preg_match, preg_replace, str_starts_with, strcasecmp, strlen, strncmp, strpos, strrpos, strtr, substr, substr_count, trigger_error, ucfirst; +use const DIRECTORY_SEPARATOR; /** * Presenter component represents a webpage instance. It converts Request to Response. * - * @property-read Nette\Application\Request $request - * @property-read string $action - * @property string $view - * @property string|bool $layout + * @property-deprecated Nette\Application\Request $request + * @property-deprecated string $action + * @property-deprecated string $view + * @property-deprecated string|bool $layout * @property-read \stdClass $payload - * @property-read Nette\Http\Session $session - * @property-read Nette\Security\User $user + * @property-deprecated Nette\Http\Session $session + * @property-deprecated Nette\Security\User $user */ abstract class Presenter extends Control implements Application\IPresenter { @@ -114,11 +116,6 @@ abstract class Presenter extends Control implements Application\IPresenter private readonly LinkGenerator $linkGenerator; - public function __construct() - { - } - - final public function getRequest(): ?Application\Request { return $this->request; @@ -470,9 +467,8 @@ public function setLayout(string|bool $layout): static /** * @throws Nette\Application\AbortException - * @return never */ - public function sendTemplate(?Template $template = null): void + public function sendTemplate(?Template $template = null): never { $template ??= $this->getTemplate(); if (!$template->getFile()) { @@ -644,9 +640,8 @@ public function isAjax(): bool /** * Sends AJAX payload to the output. * @throws Nette\Application\AbortException - * @return never */ - public function sendPayload(): void + public function sendPayload(): never { $this->sendResponse(new Responses\JsonResponse($this->getPayload())); } @@ -655,9 +650,8 @@ public function sendPayload(): void /** * Sends JSON data to the output. * @throws Nette\Application\AbortException - * @return never */ - public function sendJson(mixed $data): void + public function sendJson(mixed $data): never { $this->sendResponse(new Responses\JsonResponse($data)); } @@ -669,9 +663,8 @@ public function sendJson(mixed $data): void /** * Sends response and terminates presenter. * @throws Nette\Application\AbortException - * @return never */ - public function sendResponse(Application\Response $response): void + public function sendResponse(Application\Response $response): never { $this->response = $response; $this->terminate(); @@ -681,9 +674,8 @@ public function sendResponse(Application\Response $response): void /** * Correctly terminates presenter. * @throws Nette\Application\AbortException - * @return never */ - public function terminate(): void + public function terminate(): never { throw new Application\AbortException; } @@ -693,9 +685,8 @@ public function terminate(): void * Forward to another presenter or action. * @param array|mixed $args * @throws Nette\Application\AbortException - * @return never */ - public function forward(string|Nette\Application\Request $destination, $args = []): void + public function forward(string|Nette\Application\Request $destination, $args = []): never { if ($destination instanceof Application\Request) { $this->sendResponse(new Responses\ForwardResponse($destination)); @@ -712,9 +703,8 @@ public function forward(string|Nette\Application\Request $destination, $args = [ /** * Redirect to another URL and ends presenter execution. * @throws Nette\Application\AbortException - * @return never */ - public function redirectUrl(string $url, ?int $httpCode = null): void + public function redirectUrl(string $url, ?int $httpCode = null): never { if ($this->isAjax()) { $this->getPayload()->redirect = $url; @@ -834,7 +824,7 @@ protected function requestToUrl(Application\Request $request, ?bool $relative = * Invalid link handler. Descendant can override this method to change default behaviour. * @throws InvalidLinkException */ - protected function handleInvalidLink(InvalidLinkException $e): string + protected function processInvalidLink(InvalidLinkException $e): string { if ($this->invalidLinkMode & self::InvalidLinkException) { throw $e; diff --git a/src/Application/exceptions.php b/src/Application/exceptions.php index 11aea987d..8e3b60d5e 100644 --- a/src/Application/exceptions.php +++ b/src/Application/exceptions.php @@ -13,13 +13,14 @@ /** - * The exception that is thrown when user attempts to terminate the current presenter or application. - * This is special "silent exception" with no error message or code. + * A silent exception used to terminate the current presenter or application. + * Contains no error message or code. */ class AbortException extends \LogicException { } + /** @internal */ final class SwitchException extends AbortException { @@ -27,7 +28,7 @@ final class SwitchException extends AbortException /** - * Application fatal error. + * Fatal error in the application. */ class ApplicationException extends \Exception { @@ -35,7 +36,7 @@ class ApplicationException extends \Exception /** - * The exception that is thrown when a presenter cannot be loaded. + * The requested presenter cannot be loaded. */ class InvalidPresenterException extends \Exception { @@ -43,7 +44,7 @@ class InvalidPresenterException extends \Exception /** - * The exception that indicates client error with HTTP code 4xx. + * The request resulted in HTTP 4xx client error. */ class BadRequestException extends \LogicException { @@ -65,7 +66,7 @@ public function getHttpCode(): int /** - * Forbidden request exception - access denied. + * Access to the requested resource is forbidden. */ class ForbiddenRequestException extends BadRequestException { diff --git a/src/Application/templates/error.phtml b/src/Application/templates/error.phtml index be1658b08..8e33e4288 100644 --- a/src/Application/templates/error.phtml +++ b/src/Application/templates/error.phtml @@ -27,11 +27,12 @@ $message = $messages[$code] ?? $messages[0]; <?= $message[0] ?>
diff --git a/src/Bridges/ApplicationDI/ApplicationExtension.php b/src/Bridges/ApplicationDI/ApplicationExtension.php index 5acd5bf97..e7b77f489 100644 --- a/src/Bridges/ApplicationDI/ApplicationExtension.php +++ b/src/Bridges/ApplicationDI/ApplicationExtension.php @@ -17,6 +17,7 @@ use Nette\Schema\Expect; use Nette\Utils\Reflection; use Tracy; +use function is_array, is_string, sprintf; /** @@ -96,7 +97,7 @@ public function loadConfiguration(): void ->setType(Nette\Application\IPresenterFactory::class) ->setFactory(Nette\Application\PresenterFactory::class, [new Definitions\Statement( Nette\Bridges\ApplicationDI\PresenterFactoryCallback::class, - [1 => $this->invalidLinkMode, $touch ?? null], + [1 => $touch ?? null], )]); if ($config->mapping) { @@ -275,7 +276,7 @@ private function checkPresenter(string $class): void $re = $class::formatActionMethod('') . '.|' . $class::formatRenderMethod('') . '.|' . $class::formatSignalMethod('') . '.'; foreach ($rc->getMethods() as $rm) { - if (preg_match("#^(?!handleInvalidLink)($re)#", $rm->getName()) && (!$rm->isPublic() || $rm->isStatic())) { + if (preg_match("#^$re#", $rm->getName()) && (!$rm->isPublic() || $rm->isStatic())) { throw new Nette\InvalidStateException(sprintf('Method %s: this method must be public non-static.', Reflection::toString($rm))); } elseif (preg_match('#^createComponent.#', $rm->getName()) && ($rm->isPrivate() || $rm->isStatic())) { throw new Nette\InvalidStateException(sprintf('Method %s: this method must be non-private non-static.', Reflection::toString($rm))); diff --git a/src/Bridges/ApplicationDI/LatteExtension.php b/src/Bridges/ApplicationDI/LatteExtension.php index e2ad438ea..94271c350 100644 --- a/src/Bridges/ApplicationDI/LatteExtension.php +++ b/src/Bridges/ApplicationDI/LatteExtension.php @@ -15,6 +15,7 @@ use Nette\DI\Definitions\Statement; use Nette\Schema\Expect; use Tracy; +use function class_exists, is_string; /** @@ -33,7 +34,6 @@ public function getConfigSchema(): Nette\Schema\Schema { return Expect::structure([ 'debugger' => Expect::anyOf(true, false, 'all'), - 'macros' => Expect::arrayOf('string'), 'extensions' => Expect::arrayOf('string|Nette\DI\Definitions\Statement'), 'templateClass' => Expect::string(), 'strictTypes' => Expect::bool(false), @@ -53,40 +53,31 @@ public function loadConfiguration(): void $config = $this->config; $builder = $this->getContainerBuilder(); - $latteFactory = $builder->addFactoryDefinition($this->prefix('latteFactory')) + $builder->addFactoryDefinition($this->prefix('latteFactory')) ->setImplement(ApplicationLatte\LatteFactory::class) ->getResultDefinition() ->setFactory(Latte\Engine::class) ->addSetup('setTempDirectory', [$this->tempDir]) ->addSetup('setAutoRefresh', [$this->debugMode]) - ->addSetup('setStrictTypes', [$config->strictTypes]); - - if (version_compare(Latte\Engine::VERSION, '3', '<')) { - foreach ($config->macros as $macro) { - $this->addMacro($macro); - } - } else { - $latteFactory->addSetup('setStrictParsing', [$config->strictParsing]) + ->addSetup('setStrictTypes', [$config->strictTypes]) + ->addSetup('setStrictParsing', [$config->strictParsing]) ->addSetup('enablePhpLinter', [$config->phpLinter]) ->addSetup('setLocale', [$config->locale]); - $builder->getDefinition($this->prefix('latteFactory')) - ->getResultDefinition() - ->addSetup('?', [$builder::literal('func_num_args() && $service->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension(func_get_arg(0)))')]); + $this->addExtension(new Statement(ApplicationLatte\UIExtension::class, [$builder::literal('$control')])); - if ($builder->getByType(Nette\Caching\Storage::class)) { - $this->addExtension(new Statement(Nette\Bridges\CacheLatte\CacheExtension::class)); - } - if (class_exists(Nette\Bridges\FormsLatte\FormsExtension::class)) { - $this->addExtension(new Statement(Nette\Bridges\FormsLatte\FormsExtension::class)); - } + if ($builder->getByType(Nette\Caching\Storage::class)) { + $this->addExtension(new Statement(Nette\Bridges\CacheLatte\CacheExtension::class)); + } + if (class_exists(Nette\Bridges\FormsLatte\FormsExtension::class)) { + $this->addExtension(new Statement(Nette\Bridges\FormsLatte\FormsExtension::class)); + } - foreach ($config->extensions as $extension) { - if ($extension === Latte\Essential\TranslatorExtension::class) { - $extension = new Statement($extension, [new Nette\DI\Definitions\Reference(Nette\Localization\Translator::class)]); - } - $this->addExtension($extension); + foreach ($config->extensions as $extension) { + if ($extension === Latte\Essential\TranslatorExtension::class) { + $extension = new Statement($extension, [new Nette\DI\Definitions\Reference(Nette\Localization\Translator::class)]); } + $this->addExtension($extension); } $builder->addDefinition($this->prefix('templateFactory')) @@ -129,40 +120,12 @@ public static function initLattePanel( $control = $template->getLatte()->getProviders()['uiControl'] ?? null; if ($all || $control instanceof Nette\Application\UI\Presenter) { $name = $all && $control ? (new \ReflectionObject($control))->getShortName() : ''; - if (version_compare(Latte\Engine::VERSION, '3', '<')) { - $bar->addPanel(new Latte\Bridges\Tracy\LattePanel($template->getLatte(), $name)); - } else { - $template->getLatte()->addExtension(new Latte\Bridges\Tracy\TracyExtension($name)); - } + $template->getLatte()->addExtension(new Latte\Bridges\Tracy\TracyExtension($name)); } }; } - public function addMacro(string $macro): void - { - $builder = $this->getContainerBuilder(); - $definition = $builder->getDefinition($this->prefix('latteFactory'))->getResultDefinition(); - - if (($macro[0] ?? null) === '@') { - if (str_contains($macro, '::')) { - [$macro, $method] = explode('::', $macro); - } else { - $method = 'install'; - } - - $definition->addSetup('?->onCompile[] = function ($engine) { ?->' . $method . '($engine->getCompiler()); }', ['@self', $macro]); - - } else { - if (!str_contains($macro, '::') && class_exists($macro)) { - $macro .= '::install'; - } - - $definition->addSetup('?->onCompile[] = function ($engine) { ' . $macro . '($engine->getCompiler()); }', ['@self']); - } - } - - public function addExtension(Statement|string $extension): void { $extension = is_string($extension) diff --git a/src/Bridges/ApplicationDI/PresenterFactoryCallback.php b/src/Bridges/ApplicationDI/PresenterFactoryCallback.php index 7e60db7c0..9d1f1d2dd 100644 --- a/src/Bridges/ApplicationDI/PresenterFactoryCallback.php +++ b/src/Bridges/ApplicationDI/PresenterFactoryCallback.php @@ -10,6 +10,7 @@ namespace Nette\Bridges\ApplicationDI; use Nette; +use function array_filter, array_values, class_exists, count, implode, touch; /** @@ -20,7 +21,6 @@ final class PresenterFactoryCallback { public function __construct( private readonly Nette\DI\Container $container, - private readonly int $invalidLinkMode, private readonly ?string $touchToRefresh, ) { } @@ -40,25 +40,13 @@ public function __invoke(string $class): Nette\Application\IPresenter return $this->container->createService($services[0]); } - if ($this->touchToRefresh) { + if ($this->touchToRefresh && class_exists($class)) { touch($this->touchToRefresh); + echo 'Class ' . htmlspecialchars($class) . ' was not found in DI container.

If you just created this presenter, it should be enough to refresh the page. It will happen automatically in 5 seconds.

Otherwise, please check the configuration of your DI container.'; + header('Refresh: 5'); + exit; } - try { - $presenter = $this->container->createInstance($class); - $this->container->callInjects($presenter); - } catch (Nette\DI\MissingServiceException | Nette\DI\ServiceCreationException $e) { - if ($this->touchToRefresh && class_exists($class)) { - throw new \Exception("Refresh your browser. New presenter $class was found.", 0, $e); - } - - throw $e; - } - - if ($presenter instanceof Nette\Application\UI\Presenter && !isset($presenter->invalidLinkMode)) { - $presenter->invalidLinkMode = $this->invalidLinkMode; - } - - return $presenter; + throw new Nette\Application\InvalidPresenterException("No services of type $class found."); } } diff --git a/src/Bridges/ApplicationLatte/LatteFactory.php b/src/Bridges/ApplicationLatte/LatteFactory.php index e6d2c8842..71e1ced0c 100644 --- a/src/Bridges/ApplicationLatte/LatteFactory.php +++ b/src/Bridges/ApplicationLatte/LatteFactory.php @@ -10,11 +10,12 @@ namespace Nette\Bridges\ApplicationLatte; use Latte; +use Nette\Application\UI\Control; interface LatteFactory { - function create(/*?Control $control = null*/): Latte\Engine; + function create(?Control $control = null): Latte\Engine; } diff --git a/src/Bridges/ApplicationLatte/SnippetBridge.php b/src/Bridges/ApplicationLatte/SnippetBridge.php deleted file mode 100644 index f5d62ef80..000000000 --- a/src/Bridges/ApplicationLatte/SnippetBridge.php +++ /dev/null @@ -1,95 +0,0 @@ -control = $control; - } - - - public function isSnippetMode(): bool - { - return (bool) $this->control->snippetMode; - } - - - public function setSnippetMode($snippetMode) - { - $this->control->snippetMode = $snippetMode; - } - - - public function needsRedraw($name): bool - { - return $this->control->isControlInvalid($name); - } - - - public function markRedrawn($name): void - { - if ($name !== '') { - $this->control->redrawControl($name, false); - } - } - - - public function getHtmlId($name): string - { - return $this->control->getSnippetId($name); - } - - - public function addSnippet($name, $content): void - { - if (!isset($this->payload)) { - $this->payload = $this->control->getPresenter()->getPayload(); - } - - $this->payload->snippets[$this->control->getSnippetId($name)] = $content; - } - - - public function renderChildren(): void - { - $queue = [$this->control]; - do { - foreach (array_shift($queue)->getComponents() as $child) { - if ($child instanceof Renderable) { - if ($child->isControlInvalid()) { - $child->snippetMode = true; - $child->render(); - $child->snippetMode = false; - } - } elseif ($child instanceof Nette\ComponentModel\IContainer) { - $queue[] = $child; - } - } - } while ($queue); - } -} diff --git a/src/Bridges/ApplicationLatte/SnippetRuntime.php b/src/Bridges/ApplicationLatte/SnippetRuntime.php index 1856c3318..f3ad578fc 100644 --- a/src/Bridges/ApplicationLatte/SnippetRuntime.php +++ b/src/Bridges/ApplicationLatte/SnippetRuntime.php @@ -12,6 +12,7 @@ use Nette; use Nette\Application\UI\Control; use Nette\Application\UI\Renderable; +use function array_pop, array_shift, end, ob_end_clean, ob_get_clean, ob_start, reset, trigger_error; /** diff --git a/src/Bridges/ApplicationLatte/Template.php b/src/Bridges/ApplicationLatte/Template.php index c07ea9975..cbed4d4c1 100644 --- a/src/Bridges/ApplicationLatte/Template.php +++ b/src/Bridges/ApplicationLatte/Template.php @@ -16,7 +16,7 @@ /** * Latte powered template. */ -class Template implements Nette\Application\UI\Template +abstract class Template implements Nette\Application\UI\Template { private ?string $file = null; private ?string $blueprint; @@ -94,16 +94,7 @@ public function addFunction(string $name, callable $callback): static */ public function setTranslator(?Nette\Localization\Translator $translator, ?string $language = null): static { - if (version_compare(Latte\Engine::VERSION, '3', '<')) { - $this->latte->addFilter( - 'translate', - fn(Latte\Runtime\FilterInfo $fi, ...$args): string => $translator === null - ? $args[0] - : $translator->translate(...$args), - ); - } else { - $this->latte->addExtension(new Latte\Essential\TranslatorExtension($translator, $language)); - } + $this->latte->addExtension(new Latte\Essential\TranslatorExtension($translator, $language)); return $this; } diff --git a/src/Bridges/ApplicationLatte/TemplateFactory.php b/src/Bridges/ApplicationLatte/TemplateFactory.php index 2fdcbc9b4..dbef9dfdd 100644 --- a/src/Bridges/ApplicationLatte/TemplateFactory.php +++ b/src/Bridges/ApplicationLatte/TemplateFactory.php @@ -9,9 +9,9 @@ namespace Nette\Bridges\ApplicationLatte; -use Latte; use Nette; use Nette\Application\UI; +use function class_exists, is_a, preg_replace, property_exists, rtrim; /** @@ -28,7 +28,6 @@ public function __construct( private readonly LatteFactory $latteFactory, private readonly ?Nette\Http\IRequest $httpRequest = null, private readonly ?Nette\Security\User $user = null, - private readonly ?Nette\Caching\Storage $cacheStorage = null, $templateClass = null, ) { if ($templateClass && (!class_exists($templateClass) || !is_a($templateClass, Template::class, true))) { @@ -39,8 +38,7 @@ public function __construct( } - /** @return Template */ - public function createTemplate(?UI\Control $control = null, ?string $class = null): UI\Template + public function createTemplate(?UI\Control $control = null, ?string $class = null): Template { $class ??= $this->templateClass; if (!is_a($class, Template::class, allow_string: true)) { @@ -51,12 +49,6 @@ public function createTemplate(?UI\Control $control = null, ?string $class = nul $template = new $class($latte); $presenter = $control?->getPresenterIfExists(); - if (version_compare(Latte\Engine::VERSION, '3', '<')) { - $this->setupLatte2($latte, $control, $presenter, $template); - } elseif (!Nette\Utils\Arrays::some($latte->getExtensions(), fn($e) => $e instanceof UIExtension)) { - $latte->addExtension(new UIExtension($control)); - } - // default parameters $baseUrl = $this->httpRequest ? rtrim($this->httpRequest->getUrl()->withoutUserInfo()->getBaseUrl(), '/') @@ -84,55 +76,4 @@ public function createTemplate(?UI\Control $control = null, ?string $class = nul return $template; } - - - private function setupLatte2( - Latte\Engine $latte, - ?UI\Control $control, - ?UI\Presenter $presenter, - Template $template, - ): void - { - if ($latte->onCompile instanceof \Traversable) { - $latte->onCompile = iterator_to_array($latte->onCompile); - } - - array_unshift($latte->onCompile, function (Latte\Engine $latte) use ($control, $template): void { - if ($this->cacheStorage) { - $latte->getCompiler()->addMacro('cache', new Nette\Bridges\CacheLatte\CacheMacro); - } - - UIMacros::install($latte->getCompiler()); - if (class_exists(Nette\Bridges\FormsLatte\FormMacros::class)) { - Nette\Bridges\FormsLatte\FormMacros::install($latte->getCompiler()); - } - - $control?->templatePrepareFilters($template); - }); - - $latte->addProvider('cacheStorage', $this->cacheStorage); - - if ($control) { - $latte->addProvider('uiControl', $control); - $latte->addProvider('uiPresenter', $presenter); - $latte->addProvider('snippetBridge', new SnippetBridge($control)); - if ($presenter) { - $header = $presenter->getHttpResponse()->getHeader('Content-Security-Policy') - ?: $presenter->getHttpResponse()->getHeader('Content-Security-Policy-Report-Only'); - } - - $nonce = $presenter && preg_match('#\s\'nonce-([\w+/]+=*)\'#', (string) $header, $m) ? $m[1] : null; - $latte->addProvider('uiNonce', $nonce); - } - - if ($presenter) { - $latte->addFunction('isLinkCurrent', [$presenter, 'isLinkCurrent']); - $latte->addFunction('isModuleCurrent', [$presenter, 'isModuleCurrent']); - } - - $latte->addFilter('modifyDate', fn($time, $delta, $unit = null) => $time - ? Nette\Utils\DateTime::from($time)->modify($delta . $unit) - : null); - - } } diff --git a/src/Bridges/ApplicationLatte/UIExtension.php b/src/Bridges/ApplicationLatte/UIExtension.php index eeff391f2..87ce0bf92 100644 --- a/src/Bridges/ApplicationLatte/UIExtension.php +++ b/src/Bridges/ApplicationLatte/UIExtension.php @@ -16,6 +16,7 @@ use Latte\Essential\Nodes\ExtendsNode; use Nette; use Nette\Application\UI; +use function array_unshift, preg_match; /** @@ -31,7 +32,9 @@ public function __construct( public function getFilters(): array { + $baseUrl = $this->control?->getPresenterIfExists()?->getHttpRequest()->getUrl(); return [ + 'absoluteUrl' => fn(\Stringable $link): ?string => $baseUrl?->resolve((string) $link)->getAbsoluteUrl(), 'modifyDate' => fn($time, $delta, $unit = null) => $time ? Nette\Utils\DateTime::from($time)->modify($delta . $unit) : null, diff --git a/src/Bridges/ApplicationLatte/UIMacros.php b/src/Bridges/ApplicationLatte/UIMacros.php deleted file mode 100644 index 131c30075..000000000 --- a/src/Bridges/ApplicationLatte/UIMacros.php +++ /dev/null @@ -1,187 +0,0 @@ -addMacro('control', [$me, 'macroControl']); - - $me->addMacro('href', null, null, fn(MacroNode $node, PhpWriter $writer): string => ' ?> href="macroLink($node, $writer) . ' ?>"addMacro('plink', [$me, 'macroLink']); - $me->addMacro('link', [$me, 'macroLink']); - $me->addMacro('ifCurrent', [$me, 'macroIfCurrent'], '}'); // deprecated; use n:class="$presenter->linkCurrent ? ..." - $me->addMacro('extends', [$me, 'macroExtends']); - $me->addMacro('layout', [$me, 'macroExtends']); - $me->addMacro('nonce', null, null, 'echo $this->global->uiNonce ? " nonce=\"{$this->global->uiNonce}\"" : "";'); - $me->addMacro('templatePrint', [$me, 'macroTemplatePrint'], null, null, self::ALLOWED_IN_HEAD); - } - - - /** - * Initializes before template parsing. - */ - public function initialize(): void - { - $this->extends = false; - } - - - /** - * Finishes template parsing. - * @return array(prolog, epilog) - */ - public function finalize() - { - if ($this->printTemplate) { - return ["Nette\\Bridges\\ApplicationLatte\\UIRuntime::printClass(\$this, $this->printTemplate); exit;"]; - } - - return [$this->extends . 'Nette\Bridges\ApplicationLatte\UIRuntime::initialize($this, $this->parentName, $this->blocks);']; - } - - - /********************* macros ****************d*g**/ - - - /** - * {control name[:method] [params]} - */ - public function macroControl(MacroNode $node, PhpWriter $writer) - { - if ($node->context !== [Latte\Compiler::CONTENT_HTML, Latte\Compiler::CONTEXT_HTML_TEXT]) { - $escapeMod = Latte\Helpers::removeFilter($node->modifiers, 'noescape') ? '' : '|escape'; - } - - if ($node->modifiers) { - trigger_error('Modifiers are deprecated in ' . $node->getNotation(), E_USER_DEPRECATED); - } - - $node->modifiers .= $escapeMod ?? ''; - - $words = $node->tokenizer->fetchWords(); - if (!$words) { - throw new CompileException('Missing control name in {control}'); - } - - $name = $writer->formatWord($words[0]); - $method = ucfirst($words[1] ?? ''); - $method = Strings::match($method, '#^\w*$#D') - ? "render$method" - : "{\"render$method\"}"; - - $tokens = $node->tokenizer; - $pos = $tokens->position; - $wrap = false; - while ($tokens->nextToken()) { - if ($tokens->isCurrent('=>', '(expand)') && !$tokens->depth) { - $wrap = true; - break; - } - } - - $tokens->position = $pos; - $param = $wrap ? $writer->formatArray() : $writer->formatArgs(); - - return "/* line $node->startLine */ " - . ($name[0] === '$' ? "if (is_object($name)) \$_tmp = $name; else " : '') - . '$_tmp = $this->global->uiControl->getComponent(' . $name . '); ' - . 'if ($_tmp instanceof Nette\Application\UI\Renderable) $_tmp->redrawControl(null, false); ' - . ($node->modifiers === '' - ? "\$_tmp->$method($param);" - : $writer->write( - "ob_start(fn() => null); \$_tmp->$method($param); \$ʟ_fi = new LR\\FilterInfo(%var); echo %modifyContent(ob_get_clean());", - Latte\Engine::CONTENT_HTML, - ) - ); - } - - - /** - * {link destination [,] [params]} - * {plink destination [,] [params]} - * n:href="destination [,] [params]" - */ - public function macroLink(MacroNode $node, PhpWriter $writer) - { - $node->modifiers = preg_replace('#\|safeurl\s*(?=\||$)#Di', '', $node->modifiers); - return $writer->using($node, $this->getCompiler()) - ->write( - 'echo %escape(%modify(' - . ($node->name === 'plink' ? '$this->global->uiPresenter' : '$this->global->uiControl') - . '->link(%node.word, %node.array?)))' - . ($node->startLine ? " /* line $node->startLine */;" : ';'), - ); - } - - - /** - * {ifCurrent destination [,] [params]} - */ - public function macroIfCurrent(MacroNode $node, PhpWriter $writer) - { - if ($node->modifiers) { - throw new CompileException('Modifiers are not allowed in ' . $node->getNotation()); - } - - return $writer->write( - $node->args - ? 'if ($this->global->uiPresenter->isLinkCurrent(%node.word, %node.array?)) {' - : 'if ($this->global->uiPresenter->getLastCreatedRequestFlag("current")) {', - ); - } - - - /** - * {extends auto} - */ - public function macroExtends(MacroNode $node, PhpWriter $writer) - { - if ($node->modifiers || $node->parentNode || $node->args !== 'auto') { - return $this->extends = false; - } - - $this->extends = $writer->write('$this->parentName = $this->global->uiPresenter->findLayoutTemplateFile();'); - } - - - /** - * {templatePrint [parentClass | default]} - */ - public function macroTemplatePrint(MacroNode $node): void - { - if ($node->modifiers) { - throw new CompileException('Modifiers are not allowed in ' . $node->getNotation()); - } - - $this->printTemplate = var_export($node->tokenizer->fetchWord() ?: null, true); - } -} diff --git a/src/Bridges/ApplicationLatte/UIRuntime.php b/src/Bridges/ApplicationLatte/UIRuntime.php deleted file mode 100644 index ace3af72d..000000000 --- a/src/Bridges/ApplicationLatte/UIRuntime.php +++ /dev/null @@ -1,84 +0,0 @@ -global; - $blocks = array_filter(array_keys($blocks), fn(string $s): bool => $s[0] !== '_'); - if ( - $parentName === null - && $blocks - && !$template->getReferringTemplate() - && ($providers->uiControl ?? null) instanceof Nette\Application\UI\Presenter - ) { - $parentName = $providers->uiControl->findLayoutTemplateFile(); - } - } - - - public static function printClass(Latte\Runtime\Template $template, ?string $parent = null): void - { - $blueprint = new Latte\Runtime\Blueprint; - $name = 'Template'; - $params = $template->getParameters(); - $control = $params['control'] ?? $params['presenter'] ?? null; - if ($control) { - $name = preg_replace('#(Control|Presenter)$#', '', $control::class) . 'Template'; - unset($params[$control instanceof Presenter ? 'control' : 'presenter']); - } - - if ($parent) { - if (!class_exists($parent)) { - $blueprint->printHeader("{templatePrint}: Class '$parent' doesn't exist."); - return; - } - - $params = array_diff_key($params, get_class_vars($parent)); - } - - $funcs = array_diff_key((array) $template->global->fn, (new Latte\Runtime\Defaults)->getFunctions()); - unset($funcs['isLinkCurrent'], $funcs['isModuleCurrent']); - - $namespace = new Php\PhpNamespace(Php\Helpers::extractNamespace($name)); - $class = $namespace->addClass(Php\Helpers::extractShortName($name)); - $class->setExtends($parent ?: Template::class); - if (!$parent) { - $class->addTrait(Nette\SmartObject::class); - } - - $blueprint->addProperties($class, $params, true); - $blueprint->addFunctions($class, $funcs); - - $end = $blueprint->printCanvas(); - $blueprint->printHeader('Native types'); - $blueprint->printCode((string) $namespace); - - $blueprint->addProperties($class, $params, false); - - $blueprint->printHeader('phpDoc types'); - $blueprint->printCode((string) $namespace); - echo $end; - } -} diff --git a/src/Bridges/ApplicationTracy/RoutingPanel.php b/src/Bridges/ApplicationTracy/RoutingPanel.php index a69c429dc..bbfd16777 100644 --- a/src/Bridges/ApplicationTracy/RoutingPanel.php +++ b/src/Bridges/ApplicationTracy/RoutingPanel.php @@ -45,7 +45,7 @@ public function getTab(): string ); return Nette\Utils\Helpers::capture(function () { $matched = $this->matched; - require __DIR__ . '/templates/RoutingPanel.tab.phtml'; + require __DIR__ . '/dist/tab.phtml'; }); } @@ -61,7 +61,7 @@ public function getPanel(): string $source = $this->matched ? $this->findSource() : null; $url = $this->httpRequest->getUrl(); $method = $this->httpRequest->getMethod(); - require __DIR__ . '/templates/RoutingPanel.panel.phtml'; + require __DIR__ . '/dist/panel.phtml'; }); } diff --git a/src/Bridges/ApplicationTracy/dist/panel.phtml b/src/Bridges/ApplicationTracy/dist/panel.phtml new file mode 100644 index 000000000..873d1d556 --- /dev/null +++ b/src/Bridges/ApplicationTracy/dist/panel.phtml @@ -0,0 +1,185 @@ + + + + +

+ no route + +: + + + +! + +

+ +
+
+

+ + + getBaseUrl()) ?> +&', '?'], htmlspecialchars($url->getRelativeUrl())) ?> + +

+ +

+ (class not found)

+

getName() : $source->getDeclaringClass()->getName() . '::' . $source->getName() . '()') ?> +

+
+ +
+

No routes defined.

+
+
+
+
Mask / Class
+
Defaults
+
Matched as
+
+ +
+
+ + domain = + + + + module = + + +
+
+ +
+
+ '✓', 'may' => '≈', 'no' => '', 'oneway' => '⛔', 'error' => '❌'][$route->matched]) ?> + +
+ +
+ + + + + + mask) ? str_replace(['/', '-'], ['/', '-'], htmlspecialchars($route->mask)) : str_replace('\\', '\\', htmlspecialchars($route->class)) ?> + + +
+ +
+ +defaults as $key => $value): ?> + =  + +
true, Dumper::LIVE => true]) ?> + + +
+
+ +
+params): ?> +params ?> +: + +
+ $value): ?> + =  + +
true, Dumper::LIVE => true]) ?> + + +
+error): ?> error->getMessage()) ?> + +
+
+ +
+
+
diff --git a/src/Bridges/ApplicationTracy/dist/tab.phtml b/src/Bridges/ApplicationTracy/dist/tab.phtml new file mode 100644 index 000000000..c68ce008b --- /dev/null +++ b/src/Bridges/ApplicationTracy/dist/tab.phtml @@ -0,0 +1,20 @@ + + + + + + + + no route + +: + + + +! + + + diff --git a/src/Bridges/ApplicationTracy/panel.latte b/src/Bridges/ApplicationTracy/panel.latte new file mode 100644 index 000000000..580cbb229 --- /dev/null +++ b/src/Bridges/ApplicationTracy/panel.latte @@ -0,0 +1,181 @@ +{use Nette\Application\UI\Presenter} +{use Tracy\Dumper} + + + +

+ {if $matched === null} + no route + {elseif isset($matched[Presenter::PresenterKey])} + {$matched[Presenter::PresenterKey]}:{$matched[Presenter::ActionKey] ?? Presenter::DefaultAction} + {if isset($matched[Presenter::SignalKey])}{$matched[Presenter::SignalKey]}!{/if} + {/if} +

+ +
+
+

+ {$method} + {$url->getBaseUrl()}{str_replace(['&', '?'], ['&', '?'], htmlspecialchars($url->getRelativeUrl()))|noescape} +

+ + {if is_string($source)} +

{$source} (class not found)

+ {elseif $source} +

{$source instanceof ReflectionClass ? $source->getName() : $source->getDeclaringClass()->getName() . '::' . $source->getName() . '()'}

+ {/if} +
+ +
+ {if empty($routes)} +

No routes defined.

+ {else} +
+
+
+
Mask / Class
+
Defaults
+
Matched as
+
+ + {define routeList $list, $path = ''} +
+ {if $list[domain] || $list[module]} +
+ {if $list[domain]}domain = {$list[domain]}{/if} + {if $list[module]}module = {$list[module]}{/if} +
+ {/if} + {do $path .= $list[path]} + {foreach $list[routes] as $router} + {if is_array($router)} + {include routeList $router, $path} + {else} + {include route $router, $path} + {/if} + {/foreach} +
+ {/define} + + {define route $route, $path} +
+
+ {=[yes => '✓', may => '≈', no => '', oneway => '⛔', error => '❌'][$route->matched]} +
+ +
+ + {if $path !== ''}{$path}{/if} + {isset($route->mask) ? str_replace(['/', '-'], ['/', '-'], htmlspecialchars($route->mask)) : str_replace('\\', '\\', htmlspecialchars($route->class))|noescape} + +
+ +
+ + {foreach $route->defaults as $key => $value} + {$key} = {if is_string($value)}{$value}
{Dumper::toHtml($value, [Dumper::COLLAPSE => true, Dumper::LIVE => true])}{/if} + {/foreach} +
+
+ +
+ {if $route->params} + + {do $params = $route->params} + {if isset($params[Presenter::PresenterKey])} + {$params[presenter]}:{$params[Presenter::ActionKey] ?? Presenter::DefaultAction} +
+ {do unset($params[Presenter::PresenterKey], $params[Presenter::ActionKey])} + {/if} + {foreach $params as $key => $value} + {$key} = {if is_string($value)}{$value}
{Dumper::toHtml($value, [Dumper::COLLAPSE => true, Dumper::LIVE => true])}{/if} + {/foreach} +
+ {elseif $route->error} + {$route->error->getMessage()} + {/if} +
+
+ {/define} + + {include routeList $routes} +
+ {/if} +
+
diff --git a/src/Bridges/ApplicationTracy/tab.latte b/src/Bridges/ApplicationTracy/tab.latte new file mode 100644 index 000000000..00234c51b --- /dev/null +++ b/src/Bridges/ApplicationTracy/tab.latte @@ -0,0 +1,16 @@ +{use Nette\Application\UI\Presenter} + + + + + + + {if $matched === null} + no route + {elseif isset($matched[Presenter::PresenterKey])} + {$matched[Presenter::PresenterKey]}:{$matched[Presenter::ActionKey] ?? Presenter::DefaultAction}{if isset($matched[Presenter::SignalKey])} + {$matched[Presenter::SignalKey]}!{/if} + {/if} + + diff --git a/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml b/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml deleted file mode 100644 index 6d499b185..000000000 --- a/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml +++ /dev/null @@ -1,182 +0,0 @@ - - - -

- - no route - - - -

- -
-
-

- getBaseUrl()) ?>&', '?'], Helpers::escapeHtml($url->getRelativeUrl())) ?>

- - -

(class not found)

- -

getName() : $source->getDeclaringClass()->getName() . '::' . $source->getName() . '()' ?>

- -
- -
- -

No routes defined.

- - -
-
-
-
Mask / Class
-
Defaults
-
Matched as
-
- -
- -
- - -
- - -
- -
-
'✓', 'may' => '≈', 'no' => '', 'oneway' => '⛔', 'error' => '❌'][$route->matched] ?>
- -
' . Helpers::escapeHtml($path) . '', - isset($route->mask) ? str_replace(['/', '-'], ['/', '-'], Helpers::escapeHtml($route->mask)) : str_replace('\\', '\\', Helpers::escapeHtml($route->class)) - ?>
- -
- defaults as $key => $value): ?> - ' : Dumper::toHtml($value, [Dumper::COLLAPSE => true, Dumper::LIVE => true]) ?> - -
- -
params): ?> - params; ?> - -
- - - $value): ?> - ' : Dumper::toHtml($value, [Dumper::COLLAPSE => true, Dumper::LIVE => true]) ?> - -
error): ?>error->getMessage()) ?>
-
- -
- -
-
diff --git a/src/Bridges/ApplicationTracy/templates/RoutingPanel.tab.phtml b/src/Bridges/ApplicationTracy/templates/RoutingPanel.tab.phtml deleted file mode 100644 index b61c174fb..000000000 --- a/src/Bridges/ApplicationTracy/templates/RoutingPanel.tab.phtml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - -no route - diff --git a/src/compatibility-intf.php b/src/compatibility-intf.php index 5bee25bb1..0d5b2f8ff 100644 --- a/src/compatibility-intf.php +++ b/src/compatibility-intf.php @@ -9,17 +9,6 @@ namespace Nette\Application; -use Nette; - -if (false) { - /** @deprecated use Nette\Routing\Router */ - interface IRouter extends Nette\Routing\Router - { - } -} elseif (!interface_exists(IRouter::class)) { - class_alias(Nette\Routing\Router::class, IRouter::class); -} - if (false) { /** @deprecated use Nette\Application\Response */ interface IResponse extends Response diff --git a/src/compatibility.php b/src/compatibility.php deleted file mode 100644 index cf55aa4bc..000000000 --- a/src/compatibility.php +++ /dev/null @@ -1,28 +0,0 @@ -shouldIgnoreMissing(); -// no route without error presenter -Assert::exception(function () use ($httpRequest, $httpResponse) { +testException('no route handling without error presenter', function () use ($httpRequest, $httpResponse) { $presenterFactory = Mockery::mock(IPresenterFactory::class); $router = Mockery::mock(Router::class); $router->shouldReceive('match')->andReturn(null); @@ -107,7 +106,7 @@ Assert::exception(function () use ($httpRequest, $httpResponse) { }, BadRequestException::class, 'No route for HTTP request.'); -test('no route with error presenter', function () use ($httpRequest, $httpResponse) { +test('error presenter handling for route mismatch', function () use ($httpRequest, $httpResponse) { $errorPresenter = new ErrorPresenter; $presenterFactory = Mockery::mock(IPresenterFactory::class); @@ -133,7 +132,7 @@ test('no route with error presenter', function () use ($httpRequest, $httpRespon }); -test('route to error presenter', function () use ($httpRequest, $httpResponse) { +test('error presenter invoked directly via router', function () use ($httpRequest, $httpResponse) { $errorPresenter = new ErrorPresenter; $presenterFactory = Mockery::mock(IPresenterFactory::class); @@ -161,8 +160,7 @@ test('route to error presenter', function () use ($httpRequest, $httpResponse) { }); -// missing presenter without error presenter -Assert::exception(function () use ($httpRequest, $httpResponse) { +testException('missing presenter exception without error presenter', function () use ($httpRequest, $httpResponse) { $presenterFactory = Mockery::mock(IPresenterFactory::class); $presenterFactory->shouldReceive('createPresenter')->with('Missing')->andThrow(Nette\Application\InvalidPresenterException::class); @@ -174,7 +172,7 @@ Assert::exception(function () use ($httpRequest, $httpResponse) { }, BadRequestException::class); -test('missing presenter with error presenter', function () use ($httpRequest, $httpResponse) { +test('missing presenter fallback to error presenter', function () use ($httpRequest, $httpResponse) { $errorPresenter = new ErrorPresenter; $presenterFactory = Mockery::mock(IPresenterFactory::class); @@ -203,8 +201,7 @@ test('missing presenter with error presenter', function () use ($httpRequest, $h }); -// presenter error without error presenter -Assert::exception(function () use ($httpRequest, $httpResponse) { +testException('presenter exception propagation without error handling', function () use ($httpRequest, $httpResponse) { $presenterFactory = Mockery::mock(IPresenterFactory::class); $presenterFactory->shouldReceive('createPresenter')->with('Bad')->andReturn(new BadPresenter); @@ -216,7 +213,7 @@ Assert::exception(function () use ($httpRequest, $httpResponse) { }, BadException::class); -test('presenter error with error presenter', function () use ($httpRequest, $httpResponse) { +test('presenter exception propagation to error presenter', function () use ($httpRequest, $httpResponse) { $badPresenter = new BadPresenter; $errorPresenter = new ErrorPresenter; diff --git a/tests/Application/MicroPresenter.invoke.phpt b/tests/Application/MicroPresenter.invoke.phpt index 2376d885e..05c701e99 100644 --- a/tests/Application/MicroPresenter.invoke.phpt +++ b/tests/Application/MicroPresenter.invoke.phpt @@ -13,7 +13,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('callback invocation with parameters', function () { $presenter = $p = new NetteModule\MicroPresenter; $presenter->run(new Request('Nette:Micro', 'GET', [ @@ -30,7 +30,7 @@ test('', function () { }); -test('', function () { +test('dependency injection in callback', function () { $container = Mockery::mock(Nette\DI\Container::class) ->shouldReceive('getByType')->with('stdClass', false)->once()->andReturn(new stdClass) ->mock(); diff --git a/tests/Application/MicroPresenter.response.phpt b/tests/Application/MicroPresenter.response.phpt index ae5d7db32..25b260379 100644 --- a/tests/Application/MicroPresenter.response.phpt +++ b/tests/Application/MicroPresenter.response.phpt @@ -37,7 +37,7 @@ function createContainer() } -test('', function () { +test('textResponse with direct output', function () { $presenter = new NetteModule\MicroPresenter(createContainer()); $response = $presenter->run(new Request('Nette:Micro', 'GET', [ 'callback' => fn() => 'test', @@ -48,7 +48,7 @@ test('', function () { }); -test('', function () { +test('parameter passing to callback', function () { $presenter = new NetteModule\MicroPresenter(createContainer()); $response = $presenter->run(new Request('Nette:Micro', 'GET', [ 'callback' => fn($param) => $param, @@ -60,7 +60,7 @@ test('', function () { }); -test('', function () { +test('latte template evaluation', function () { $presenter = new NetteModule\MicroPresenter(createContainer()); $response = $presenter->run(new Request('Nette:Micro', 'GET', [ 'callback' => fn() => '{=date(Y)}', @@ -71,7 +71,7 @@ test('', function () { }); -test('', function () { +test('template file with parameters', function () { $presenter = new NetteModule\MicroPresenter(createContainer()); $response = $presenter->run(new Request('Nette:Micro', 'GET', [ 'callback' => fn() => [new SplFileInfo(Tester\FileMock::create('{$param}')), []], @@ -83,7 +83,7 @@ test('', function () { }); -test('', function () { +test('manual template creation', function () { $presenter = new NetteModule\MicroPresenter; $response = $presenter->run(new Request('Nette:Micro', 'GET', [ @@ -101,7 +101,7 @@ test('', function () { }); -test('', function () { +test('template file loader with parameters', function () { $presenter = new NetteModule\MicroPresenter; $response = $presenter->run(new Request('Nette:Micro', 'GET', [ @@ -120,7 +120,7 @@ test('', function () { }); -test('', function () { +test('missing template file handling', function () { $filename = 'notfound.latte'; Assert::exception(function () use ($filename) { $presenter = new NetteModule\MicroPresenter; diff --git a/tests/Application/PresenterFactory.formatPresenterClass.phpt b/tests/Application/PresenterFactory.formatPresenterClass.phpt index 3ef876bb9..c5314e343 100644 --- a/tests/Application/PresenterFactory.formatPresenterClass.phpt +++ b/tests/Application/PresenterFactory.formatPresenterClass.phpt @@ -13,7 +13,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('defined module', function () { +test('complex mapping with multiple wildcards', function () { $factory = new PresenterFactory; $factory->setMapping([ @@ -21,11 +21,11 @@ test('defined module', function () { 'Foo3' => 'My\App\*Mod\*Presenter', ]); - Assert::same('FooPresenter', $factory->formatPresenterClass('Foo')); - Assert::same('FooModule\BarPresenter', $factory->formatPresenterClass('Foo:Bar')); - Assert::same('FooModule\BarModule\BazPresenter', $factory->formatPresenterClass('Foo:Bar:Baz')); + Assert::same('App\Presentation\Foo\FooPresenter', $factory->formatPresenterClass('Foo')); + Assert::same('App\Presentation\Foo\Bar\BarPresenter', $factory->formatPresenterClass('Foo:Bar')); + Assert::same('App\Presentation\Foo\Bar\Baz\BazPresenter', $factory->formatPresenterClass('Foo:Bar:Baz')); - Assert::same('Foo2Presenter', $factory->formatPresenterClass('Foo2')); + Assert::same('App\Presentation\Foo2\Foo2Presenter', $factory->formatPresenterClass('Foo2')); Assert::same('App2\BarPresenter', $factory->formatPresenterClass('Foo2:Bar')); Assert::same('App2\Bar\BazPresenter', $factory->formatPresenterClass('Foo2:Bar:Baz')); @@ -36,7 +36,7 @@ test('defined module', function () { }); -test('auto module', function () { +test('simple wildcard mapping', function () { $factory = new PresenterFactory; $factory->setMapping([ @@ -44,7 +44,7 @@ test('auto module', function () { 'Foo3' => 'My\App\*Presenter', ]); - Assert::same('Foo2Presenter', $factory->formatPresenterClass('Foo2')); + Assert::same('App\Presentation\Foo2\Foo2Presenter', $factory->formatPresenterClass('Foo2')); Assert::same('App2\BarPresenter', $factory->formatPresenterClass('Foo2:Bar')); Assert::same('App2\BarModule\BazPresenter', $factory->formatPresenterClass('Foo2:Bar:Baz')); @@ -53,7 +53,7 @@ test('auto module', function () { }); -test('location ** & defined module', function () { +test('multi-segment wildcard expansion', function () { $factory = new PresenterFactory; $factory->setMapping([ @@ -61,11 +61,11 @@ test('location ** & defined module', function () { 'Foo3' => 'My\App\*Mod\**Presenter', ]); - Assert::same('FooPresenter', $factory->formatPresenterClass('Foo')); - Assert::same('FooModule\BarPresenter', $factory->formatPresenterClass('Foo:Bar')); - Assert::same('FooModule\BarModule\BazPresenter', $factory->formatPresenterClass('Foo:Bar:Baz')); + Assert::same('App\Presentation\Foo\FooPresenter', $factory->formatPresenterClass('Foo')); + Assert::same('App\Presentation\Foo\Bar\BarPresenter', $factory->formatPresenterClass('Foo:Bar')); + Assert::same('App\Presentation\Foo\Bar\Baz\BazPresenter', $factory->formatPresenterClass('Foo:Bar:Baz')); - Assert::same('Foo2Presenter', $factory->formatPresenterClass('Foo2')); + Assert::same('App\Presentation\Foo2\Foo2Presenter', $factory->formatPresenterClass('Foo2')); Assert::same('App2\Bar\BarPresenter', $factory->formatPresenterClass('Foo2:Bar')); Assert::same('App2\Bar\Baz\BazPresenter', $factory->formatPresenterClass('Foo2:Bar:Baz')); @@ -76,7 +76,7 @@ test('location ** & defined module', function () { }); -test('location ** & auto module', function () { +test('global wildcard mapping strategy', function () { $factory = new PresenterFactory; $factory->setMapping([ @@ -94,7 +94,7 @@ test('location ** & auto module', function () { }); -test('', function () { +test('array-based hierarchical mapping', function () { $factory = new PresenterFactory; $factory->setMapping([ '*' => ['App', 'Module\*', 'Presenter\*'], @@ -104,7 +104,7 @@ test('', function () { }); -test('', function () { +test('empty namespace mapping structure', function () { $factory = new PresenterFactory; $factory->setMapping([ '*' => ['', '*', '*'], @@ -113,7 +113,8 @@ test('', function () { }); -Assert::exception( +testException( + 'invalid mapping mask validation', function () { $factory = new PresenterFactory; $factory->setMapping([ diff --git a/tests/Application/Request.phpt b/tests/Application/Request.phpt index 7ae61fed5..c2c3a566e 100644 --- a/tests/Application/Request.phpt +++ b/tests/Application/Request.phpt @@ -13,7 +13,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('request parameters with null values', function () { $request = new Request('Homepage', 'GET', ['a' => 1, 'b' => null]); Assert::same(1, $request->getParameter('a')); @@ -21,7 +21,7 @@ test('', function () { }); -test('', function () { +test('POST parameters retrieval', function () { $request = new Request('Homepage', 'GET', [], ['a' => 1, 'b' => null]); Assert::same(['a' => 1, 'b' => null], $request->getPost()); diff --git a/tests/Bridges.DI/ApplicationExtension.invalidLink.phpt b/tests/Bridges.DI/ApplicationExtension.invalidLink.phpt index 7f02c95b9..dd70c50c3 100644 --- a/tests/Bridges.DI/ApplicationExtension.invalidLink.phpt +++ b/tests/Bridges.DI/ApplicationExtension.invalidLink.phpt @@ -24,7 +24,7 @@ function createCompiler(string $config): DI\Compiler } -test('', function () { +test('silentLinks enabled with debugger', function () { $compiler = createCompiler(' application: silentLinks: yes @@ -44,7 +44,7 @@ test('', function () { }); -test('', function () { +test('silentLinks disabled with debugger', function () { $compiler = createCompiler(' application: silentLinks: no @@ -64,7 +64,7 @@ test('', function () { }); -test('', function () { +test('silentLinks enabled without debugger', function () { $compiler = createCompiler(' application: silentLinks: yes @@ -84,7 +84,7 @@ test('', function () { }); -test('', function () { +test('silentLinks disabled without debugger', function () { $compiler = createCompiler(' application: silentLinks: no diff --git a/tests/Bridges.DI/ApplicationExtension.scan.phpt b/tests/Bridges.DI/ApplicationExtension.scan.phpt index 761880f43..2a060e924 100644 --- a/tests/Bridges.DI/ApplicationExtension.scan.phpt +++ b/tests/Bridges.DI/ApplicationExtension.scan.phpt @@ -12,7 +12,7 @@ require __DIR__ . '/../bootstrap.php'; require __DIR__ . '/files/MyPresenter.php'; -test('', function () { +test('default presenter registration', function () { $compiler = new DI\Compiler; $compiler->addExtension('application', new ApplicationExtension); @@ -30,7 +30,7 @@ test('', function () { }); -test('', function () { +test('scanDirs with filter', function () { $compiler = new DI\Compiler; $compiler->addExtension('application', new ApplicationExtension); @@ -53,7 +53,7 @@ test('', function () { }); -test('', function () { +test('combined scanDirs and config setup', function () { $compiler = new DI\Compiler; $compiler->addExtension('application', new ApplicationExtension(false, [__DIR__ . '/files'])); @@ -85,7 +85,7 @@ test('', function () { }); -test('', function () { +test('robotLoader discovery', function () { $robot = new Nette\Loaders\RobotLoader; $robot->addDirectory(__DIR__ . '/files'); $robot->setTempDirectory(getTempDir()); diff --git a/tests/Bridges.DI/LatteExtension.2.phpt b/tests/Bridges.DI/LatteExtension.2.phpt deleted file mode 100644 index 8144950b6..000000000 --- a/tests/Bridges.DI/LatteExtension.2.phpt +++ /dev/null @@ -1,122 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class LoremIpsumMacros extends Latte\Macros\MacroSet -{ - public static function install(Latte\Compiler $compiler) - { - $me = new static($compiler); - $me->addMacro('lorem', 'lorem'); - Notes::add($me::class); - } -} - - -class IpsumLoremMacros extends Latte\Macros\MacroSet -{ - public static function install(Latte\Compiler $compiler) - { - $me = new static($compiler); - $me->addMacro('ipsum', 'ipsum'); - Notes::add($me::class); - } -} - - -class FooMacros extends Latte\Macros\MacroSet -{ - public static function install(Latte\Compiler $compiler) - { - $me = new static($compiler); - $me->addMacro('foo', 'foo'); - Notes::add($me::class); - } -} - - -class NonStaticMacrosFactory -{ - private string $parameter; - - - public function __construct($parameter) - { - $this->parameter = $parameter; - } - - - public function install(Latte\Compiler $compiler) - { - $macros = new Latte\Macros\MacroSet($compiler); - $macros->addMacro('foo', 'foo ' . $this->parameter); - Notes::add(static::class . '::install'); - } - - - public function create(Latte\Compiler $compiler) - { - $macros = new Latte\Macros\MacroSet($compiler); - $macros->addMacro('foo2', 'foo ' . $this->parameter); - Notes::add(static::class . '::create'); - } -} - - -class AnotherExtension extends Nette\DI\CompilerExtension -{ - public function beforeCompile() - { - foreach ($this->compiler->getExtensions(Nette\Bridges\ApplicationDI\LatteExtension::class) as $extension) { - $extension->addMacro('FooMacros::install'); - } - } -} - - -$loader = new DI\Config\Loader; -$config = $loader->load(Tester\FileMock::create(' -latte: - macros: - - LoremIpsumMacros - - IpsumLoremMacros::install - - @macroFactory - - @macroFactory::create - -services: - macroFactory: NonStaticMacrosFactory(foo) -', 'neon')); - -$compiler = new DI\Compiler; -$compiler->addExtension('latte', new Nette\Bridges\ApplicationDI\LatteExtension('', false)); -$compiler->addExtension('another', new AnotherExtension); -$code = $compiler->addConfig($config)->compile(); -eval($code); - -$container = new Container; - - -Assert::type(Nette\Bridges\ApplicationLatte\LatteFactory::class, $container->getService('nette.latteFactory')); -$container->getService('nette.latteFactory')->create()->setLoader(new Latte\Loaders\StringLoader)->compile(''); - -Assert::same([ - 'LoremIpsumMacros', - 'IpsumLoremMacros', - 'NonStaticMacrosFactory::install', - 'NonStaticMacrosFactory::create', - 'FooMacros', -], Notes::fetch()); diff --git a/tests/Bridges.DI/LatteExtension.basic.phpt b/tests/Bridges.DI/LatteExtension.basic.phpt index 09dc0d292..a3a13d48f 100644 --- a/tests/Bridges.DI/LatteExtension.basic.phpt +++ b/tests/Bridges.DI/LatteExtension.basic.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class MyExtension extends Latte\Extension { @@ -63,20 +59,6 @@ Assert::type(Nette\Bridges\ApplicationLatte\LatteFactory::class, $container->get $latte = $container->getService('nette.latteFactory')->create(); $extensions = Assert::with($latte, fn() => $this->extensions); -Assert::equal([ - new Latte\Essential\CoreExtension, - new Latte\Sandbox\SandboxExtension, - new Nette\Bridges\FormsLatte\FormsExtension, - new MyExtension, - new MyExtension(1), - new MyExtension(2), - new MyExtension, -], $extensions); - -// UIExtension is added -$latte = $container->getService('nette.latteFactory')->create(null); -$extensions = Assert::with($latte, fn() => $this->extensions); - Assert::equal([ new Latte\Essential\CoreExtension, new Latte\Sandbox\SandboxExtension, diff --git a/tests/Bridges.DI/LatteExtension.translator.phpt b/tests/Bridges.DI/LatteExtension.translator.phpt index f555b460e..031312f30 100644 --- a/tests/Bridges.DI/LatteExtension.translator.phpt +++ b/tests/Bridges.DI/LatteExtension.translator.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class Translator implements Nette\Localization\Translator { diff --git a/tests/Bridges.DI/RoutingExtension.basic.phpt b/tests/Bridges.DI/RoutingExtension.basic.phpt index a8e13d1a6..0b6f57a72 100644 --- a/tests/Bridges.DI/RoutingExtension.basic.phpt +++ b/tests/Bridges.DI/RoutingExtension.basic.phpt @@ -31,9 +31,10 @@ test('', function () { $container = new Container1; $router = $container->getService('router'); Assert::type(Nette\Application\Routers\RouteList::class, $router); - Assert::same('index.php', $router[0]->getMask()); - Assert::same('item/', $router[1]->getMask()); + $routes = $router->getRouters(); + Assert::same('index.php', $routes[0]->getMask()); + Assert::same('item/', $routes[1]->getMask()); Assert::type(Nette\Application\Routers\RouteList::class, $router); - Assert::type(Nette\Application\Routers\Route::class, $router[0]); + Assert::type(Nette\Application\Routers\Route::class, $routes[0]); }); diff --git a/tests/Bridges.DI/RoutingExtension.cache.phpt b/tests/Bridges.DI/RoutingExtension.cache.phpt index bd7423446..322557fea 100644 --- a/tests/Bridges.DI/RoutingExtension.cache.phpt +++ b/tests/Bridges.DI/RoutingExtension.cache.phpt @@ -37,7 +37,7 @@ class MyRouter implements Nette\Routing\Router } -test('', function () { +test('router without cache', function () { $loader = new DI\Config\Loader; $config = $loader->load(Tester\FileMock::create(' services: @@ -55,7 +55,7 @@ test('', function () { }); -test('', function () { +test('router with cache', function () { $loader = new DI\Config\Loader; $config = $loader->load(Tester\FileMock::create(' routing: @@ -82,7 +82,7 @@ function myRouterFactory(): Nette\Routing\Router } -Assert::exception(function () { +testException('non-cacheable router factory', function () { $loader = new DI\Config\Loader; $config = $loader->load(Tester\FileMock::create(' routing: diff --git a/tests/Bridges.Latte2/Template.getParentName().phpt b/tests/Bridges.Latte2/Template.getParentName().phpt deleted file mode 100644 index 1253c4a4e..000000000 --- a/tests/Bridges.Latte2/Template.getParentName().phpt +++ /dev/null @@ -1,58 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -$presenter = Mockery::mock(Nette\Application\UI\Presenter::class) - ->shouldReceive('findLayoutTemplateFile')->andReturn('layout.latte') - ->mock(); - -$latte = new Latte\Engine; -$latte->setLoader(new Latte\Loaders\StringLoader); -$latte->addProvider('uiControl', $presenter); -UIMacros::install($latte->getCompiler()); - -$template = $latte->createTemplate(''); -$template->prepare(); -Assert::null($template->getParentName()); - -$template = $latte->createTemplate('{block}...{/block}'); -$template->prepare(); -Assert::null($template->getParentName()); - -$template = $latte->createTemplate('{block name}...{/block}'); -$template->prepare(); -Assert::same('layout.latte', $template->getParentName()); - -$template = $latte->createTemplate('{extends "file.latte"} {block name}...{/block}'); -$template->prepare(); -Assert::same('file.latte', $template->getParentName()); - -$template = $latte->createTemplate('{extends "file.latte"}'); -$template->prepare(); -Assert::same('file.latte', $template->getParentName()); - -$template = $latte->createTemplate( - '{extends $file} {block name}...{/block}', - ['file' => 'file.latte'], -); -$template->prepare(); -Assert::same('file.latte', $template->getParentName()); - -$template = $latte->createTemplate('{extends none}'); -$template->prepare(); -Assert::null($template->getParentName()); - -$latte->addProvider('uiPresenter', $presenter); -$template = $latte->createTemplate('{extends auto}'); -$template->prepare(); -Assert::same('layout.latte', $template->getParentName()); diff --git a/tests/Bridges.Latte2/TemplateFactory.customTemplate.phpt b/tests/Bridges.Latte2/TemplateFactory.customTemplate.phpt deleted file mode 100644 index 011d5b52f..000000000 --- a/tests/Bridges.Latte2/TemplateFactory.customTemplate.phpt +++ /dev/null @@ -1,75 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - -Tester\Environment::bypassFinals(); - - -class TemplateMock extends Template -{ - private $file = 'ko'; - - - public function render(?string $file = null, array $params = []): void - { - echo strrev($this->file); - } - - - public function setFile(string $file): static - { - $this->file = $file; - return $this; - } - - - public function getFile(): string - { - return $this->file; - } -} - - -test('', function () { - $latteFactory = Mockery::mock(LatteFactory::class); - $latteFactory->shouldReceive('create')->andReturn(new Latte\Engine); - $factory = new TemplateFactory($latteFactory); - Assert::type(Template::class, $factory->createTemplate()); -}); - -Assert::exception(function () { - $factory = new TemplateFactory(Mockery::mock(LatteFactory::class), null, null, null, stdClass::class); -}, Nette\InvalidArgumentException::class, 'Class stdClass does not implement Nette\Bridges\ApplicationLatte\Template or it does not exist.'); - - -test('', function () { - $latteFactory = Mockery::mock(LatteFactory::class); - $latteFactory->shouldReceive('create')->andReturn(new Latte\Engine); - $factory = new TemplateFactory($latteFactory, null, null, null, TemplateMock::class); - $template = $factory->createTemplate(); - Assert::type(TemplateMock::class, $template); - Assert::type(UI\Template::class, $template); - ob_start(); - $template->render(); - Assert::same('ok', ob_get_clean()); - $template->setFile('bla'); - ob_start(); - $template->render(); - Assert::same('alb', ob_get_clean()); -}); diff --git a/tests/Bridges.Latte2/TemplateFactory.filters.phpt b/tests/Bridges.Latte2/TemplateFactory.filters.phpt deleted file mode 100644 index 57e879543..000000000 --- a/tests/Bridges.Latte2/TemplateFactory.filters.phpt +++ /dev/null @@ -1,47 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class LatteFactory implements Nette\Bridges\ApplicationLatte\LatteFactory -{ - private $engine; - - - public function __construct(Latte\Engine $engine) - { - $this->engine = $engine; - } - - - public function create(): Latte\Engine - { - return $this->engine; - } -} - -$factory = new TemplateFactory(new LatteFactory(new Latte\Engine)); -$latte = $factory->createTemplate()->getLatte(); - - -setlocale(LC_TIME, 'C'); -date_default_timezone_set('Europe/Prague'); - -Assert::null($latte->invokeFilter('modifyDate', [null, null])); -Assert::same('1978-01-24 11:40:00', (string) $latte->invokeFilter('modifyDate', [254_400_000, '+1 day'])); -Assert::same('1978-05-06 00:00:00', (string) $latte->invokeFilter('modifyDate', ['1978-05-05', '+1 day'])); -Assert::same('1978-05-06 00:00:00', (string) $latte->invokeFilter('modifyDate', [new DateTime('1978-05-05'), '1day'])); -Assert::same('1978-01-22 11:40:00', (string) $latte->invokeFilter('modifyDate', [254_400_000, -1, 'day'])); diff --git a/tests/Bridges.Latte2/TemplateFactory.nonce.control.phpt b/tests/Bridges.Latte2/TemplateFactory.nonce.control.phpt deleted file mode 100644 index 850629b36..000000000 --- a/tests/Bridges.Latte2/TemplateFactory.nonce.control.phpt +++ /dev/null @@ -1,39 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - -$latte = new Latte\Engine; - -$latteFactory = Mockery::mock(ApplicationLatte\LatteFactory::class); -$latteFactory->shouldReceive('create')->andReturn($latte); - -$response = Mockery::mock(Nette\Http\IResponse::class); -$response->shouldReceive('getHeader')->with('Content-Security-Policy')->andReturn("hello 'nonce-abcd123==' world"); - -$control = Mockery::mock(UI\Control::class); -$control->shouldReceive('getPresenter')->andReturn(null); -$control->shouldIgnoreMissing(); - -$factory = new ApplicationLatte\TemplateFactory($latteFactory); -$factory->createTemplate($control); - -$latte->setLoader(new Latte\Loaders\StringLoader); - -Assert::match( - '', - $latte->renderToString(''), -); diff --git a/tests/Bridges.Latte2/TemplateFactory.nonce.presenter.phpt b/tests/Bridges.Latte2/TemplateFactory.nonce.presenter.phpt deleted file mode 100644 index 1ef2df0e8..000000000 --- a/tests/Bridges.Latte2/TemplateFactory.nonce.presenter.phpt +++ /dev/null @@ -1,42 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - -Tester\Environment::bypassFinals(); - -$latte = new Latte\Engine; - -$latteFactory = Mockery::mock(ApplicationLatte\LatteFactory::class); -$latteFactory->shouldReceive('create')->andReturn($latte); - -$response = Mockery::mock(Nette\Http\IResponse::class); -$response->shouldReceive('getHeader')->with('Content-Security-Policy')->andReturn("hello 'nonce-abcd123==' world"); - -$presenter = Mockery::mock(UI\Presenter::class); -$presenter->shouldReceive('getPresenterIfExists')->andReturn($presenter); -$presenter->shouldReceive('getHttpResponse')->andReturn($response); -$presenter->shouldIgnoreMissing(); - -$factory = new ApplicationLatte\TemplateFactory($latteFactory); -$factory->createTemplate($presenter); - -$latte->setLoader(new Latte\Loaders\StringLoader); - -Assert::match( - '', - $latte->renderToString(''), -); diff --git a/tests/Bridges.Latte2/TemplateFactory.onCompile.phpt b/tests/Bridges.Latte2/TemplateFactory.onCompile.phpt deleted file mode 100644 index b60ebd8e1..000000000 --- a/tests/Bridges.Latte2/TemplateFactory.onCompile.phpt +++ /dev/null @@ -1,80 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -test('', function () { - $engine = new Latte\Engine; - $latteFactory = Mockery::mock(LatteFactory::class); - $latteFactory->shouldReceive('create')->andReturn($engine); - $factory = new TemplateFactory($latteFactory, new Http\Request(new Http\UrlScript('http://nette.org'))); - $engine->onCompile[] = $callback = function () {}; - - $factory->createTemplate(); - - Assert::type('array', $engine->onCompile); - Assert::type(Closure::class, $engine->onCompile[0]); // prepended by TemplateFactory - Assert::same($callback, $engine->onCompile[1]); // our callback -}); - - -test('', function () { - $engine = new Latte\Engine; - $latteFactory = Mockery::mock(LatteFactory::class); - $latteFactory->shouldReceive('create')->andReturn($engine); - $factory = new TemplateFactory($latteFactory, new Http\Request(new Http\UrlScript('http://nette.org'))); - $engine->onCompile = new ArrayIterator([$callback = function () {}]); - - $factory->createTemplate(); - - Assert::type('array', $engine->onCompile); - Assert::type(Closure::class, $engine->onCompile[0]); // prepended by TemplateFactory - Assert::same($callback, $engine->onCompile[1]); // our callback -}); - - -test('', function () { - class Event implements IteratorAggregate - { - public $events; - - - public function __construct($events) - { - $this->events = $events; - } - - - public function getIterator(): ArrayIterator - { - return new ArrayIterator($this->events); - } - } - - $engine = new Latte\Engine; - $latteFactory = Mockery::mock(LatteFactory::class); - $latteFactory->shouldReceive('create')->andReturn($engine); - $factory = new TemplateFactory($latteFactory, new Http\Request(new Http\UrlScript('http://nette.org'))); - $engine->onCompile = new Event([$callback = function () {}]); - - $factory->createTemplate(); - - Assert::type('array', $engine->onCompile); - Assert::type(Closure::class, $engine->onCompile[0]); // prepended by TemplateFactory - Assert::same($callback, $engine->onCompile[1]); // our callback -}); diff --git a/tests/Bridges.Latte2/TemplateFactory.onCreate.phpt b/tests/Bridges.Latte2/TemplateFactory.onCreate.phpt deleted file mode 100644 index 8f86ef42d..000000000 --- a/tests/Bridges.Latte2/TemplateFactory.onCreate.phpt +++ /dev/null @@ -1,36 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -test('', function () { - $engine = new Latte\Engine; - $latteFactory = Mockery::mock(LatteFactory::class); - $latteFactory->shouldReceive('create')->andReturn($engine); - $factory = new TemplateFactory($latteFactory, new Http\Request(new Http\UrlScript('http://nette.org'))); - $factory->onCreate[] = $callback = function (Template $template) { - $template->add('foo', 'bar'); - }; - - $template = $factory->createTemplate(); - - Assert::type('array', $factory->onCreate); - Assert::same($callback, $factory->onCreate[0]); // our callback - Assert::equal('bar', $template->foo); -}); diff --git a/tests/Bridges.Latte2/UIMacros.control.2.phpt b/tests/Bridges.Latte2/UIMacros.control.2.phpt deleted file mode 100644 index 9449e00e3..000000000 --- a/tests/Bridges.Latte2/UIMacros.control.2.phpt +++ /dev/null @@ -1,86 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class MockComponent -{ - public function getComponent($name) - { - Notes::add(__METHOD__); - Notes::add(func_get_args()); - return new MockControl; - } -} - - -class MockControl -{ - public function __call($name, $args) - { - Notes::add(__METHOD__); - Notes::add(func_get_args()); - } -} - - -$latte = new Latte\Engine; -$latte->setLoader(new Latte\Loaders\StringLoader); -UIMacros::install($latte->getCompiler()); - -$latte->addProvider('uiControl', new MockComponent); -$params['form'] = new MockControl; -$params['name'] = 'form'; - -$latte->renderToString(' -{control \'name\'} - -{control form} - -{control form:test} - -{control $form:test} - -{control $name:test} - -{control $name:$name} - -{control form var1} - -{control form var1, 1, 2} - -{control form var1 => 5, 1, 2} -', $params); - -Assert::same([ - 'MockComponent::getComponent', ['name'], - 'MockControl::__call', ['render', []], - 'MockComponent::getComponent', ['form'], - 'MockControl::__call', ['render', []], - 'MockComponent::getComponent', ['form'], - 'MockControl::__call', ['renderTest', []], - 'MockControl::__call', ['renderTest', []], - 'MockComponent::getComponent', ['form'], - 'MockControl::__call', ['renderTest', []], - 'MockComponent::getComponent', ['form'], - 'MockControl::__call', ['renderform', []], - 'MockComponent::getComponent', ['form'], - 'MockControl::__call', ['render', ['var1']], - 'MockComponent::getComponent', ['form'], - 'MockControl::__call', ['render', ['var1', 1, 2]], - 'MockComponent::getComponent', ['form'], - 'MockControl::__call', ['render', [['var1' => 5, 0 => 1, 1 => 2]]], -], Notes::fetch()); diff --git a/tests/Bridges.Latte2/UIMacros.control.3.phpt b/tests/Bridges.Latte2/UIMacros.control.3.phpt deleted file mode 100644 index f5d6e23d2..000000000 --- a/tests/Bridges.Latte2/UIMacros.control.3.phpt +++ /dev/null @@ -1,51 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -$latte = new Latte\Engine; -$latte->setLoader(new Latte\Loaders\StringLoader); -UIMacros::install($latte->getCompiler()); -$latte->addProvider('uiControl', new class { - public function render() - { - echo '<>&'; - } - - - public function __call($name, $args) - { - return new self; - } -}); - -Assert::exception(function () use ($latte) { - $latte->renderToString('
&', - $latte->renderToString('
', - $latte->renderToString('
'), -); - -Assert::exception(function () use ($latte) { - $latte->renderToString(''); -}, Latte\RuntimeException::class, 'Filters: unable to convert content type HTML to HTMLCSS'); diff --git a/tests/Bridges.Latte2/UIMacros.control.phpt b/tests/Bridges.Latte2/UIMacros.control.phpt deleted file mode 100644 index 559895322..000000000 --- a/tests/Bridges.Latte2/UIMacros.control.phpt +++ /dev/null @@ -1,88 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -$latte = new Latte\Engine; -$latte->setLoader(new Latte\Loaders\StringLoader); -UIMacros::install($latte->getCompiler()); - -// {control ...} -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->render();%A%', - $latte->compile('{control form}'), -); - -@Assert::match( - <<<'XX' - %A% - /* line 1 */ $_tmp = $this->global->uiControl->getComponent("form"); - if ($_tmp instanceof Nette\Application\UI\Renderable) $_tmp->redrawControl(null, false); - ob_start(fn() => null); - $_tmp->render(); - $ʟ_fi = new LR\FilterInfo('html'); - echo $this->filters->filterContent('filter', $ʟ_fi, ob_get_clean()); - %A% - XX, - $latte->compile('{control form|filter}'), -); // @deprecated - -Assert::match( - <<<'XX' - %A% - /* line 1 */ if (is_object($form)) $_tmp = $form; - else $_tmp = $this->global->uiControl->getComponent($form); - if ($_tmp instanceof Nette\Application\UI\Renderable) $_tmp->redrawControl(null, false); - $_tmp->render(); - %A% - XX, - $latte->compile('{control $form}'), -); - -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->renderType();%A%', - $latte->compile('{control form:type}'), -); - -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->{"render$type"}();%A%', - $latte->compile('{control form:$type}'), -); - -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->renderType(\'param\');%A%', - $latte->compile('{control form:type param}'), -); - -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->render(array_merge([], $params, []));%A%', - $latte->compile('{control form (expand) $params}'), -); - -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->renderType([\'param\' => 123]);%A%', - $latte->compile('{control form:type param => 123}'), -); - -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->renderType([\'param\' => 123]);%A%', - $latte->compile('{control form:type, param => 123}'), -); - -Assert::match( - '%A% $this->global->uiControl->getComponent("form");%A%->renderType(param: 123);%A%', - $latte->compile('{control form:type, param: 123}'), -); diff --git a/tests/Bridges.Latte2/UIMacros.isLinkCurrent.phpt b/tests/Bridges.Latte2/UIMacros.isLinkCurrent.phpt deleted file mode 100644 index 579a8fd4b..000000000 --- a/tests/Bridges.Latte2/UIMacros.isLinkCurrent.phpt +++ /dev/null @@ -1,54 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - -Tester\Environment::bypassFinals(); - -$latte = new Latte\Engine; - -$latteFactory = Mockery::mock(Nette\Bridges\ApplicationLatte\LatteFactory::class); -$latteFactory->shouldReceive('create')->andReturn($latte); - -$presenter = Mockery::mock(Nette\Application\UI\Presenter::class); -$presenter->shouldReceive('getPresenterIfExists')->andReturn($presenter); -$presenter->shouldReceive('getHttpResponse')->andReturn((Mockery::mock(Nette\Http\IResponse::class))->shouldIgnoreMissing()); -$presenter->shouldIgnoreMissing(); - -$factory = new Nette\Bridges\ApplicationLatte\TemplateFactory($latteFactory); -$factory->createTemplate($presenter); - -$latte->setLoader(new Latte\Loaders\StringLoader); - -Assert::matchFile( - __DIR__ . '/expected/UIMacros.isLinkCurrent.php', - $latte->compile( - <<<'XX' - n:href before n:class - - n:href after n:class - - href before n:class - - href after n:class - - {ifCurrent}empty{/ifCurrent} - - {ifCurrent default}default{/ifCurrent} - - custom function - - XX, - ), -); diff --git a/tests/Bridges.Latte2/UIMacros.link.2.phpt b/tests/Bridges.Latte2/UIMacros.link.2.phpt deleted file mode 100644 index 83a441c31..000000000 --- a/tests/Bridges.Latte2/UIMacros.link.2.phpt +++ /dev/null @@ -1,122 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class MockControl -{ - public function link($destination, $args = []) - { - if (!is_array($args)) { - $args = array_slice(func_get_args(), 1); - } - - array_unshift($args, $destination); - return 'link:' . strtr(json_encode($args), '"', "'"); - } -} - - -class MockPresenter extends MockControl -{ - public function link($destination, $args = []) - { - if (!is_array($args)) { - $args = array_slice(func_get_args(), 1); - } - - array_unshift($args, $destination); - return 'plink:' . strtr(json_encode($args), '"', "'"); - } - - - public function isAjax() - { - return false; - } -} - - -$latte = new Latte\Engine; -$latte->setLoader(new Latte\Loaders\StringLoader); -UIMacros::install($latte->getCompiler()); - -$latte->addProvider('uiControl', new MockControl); -$latte->addProvider('uiPresenter', new MockPresenter); -$params['action'] = 'login'; -$params['arr'] = ['link' => 'login', 'param' => 123]; - -Assert::match(<<<'EOD' - plink:['Homepage:'] - - plink:['Homepage:'] - - plink:['Homepage:action'] - - plink:['Homepage:action'] - - plink:['Homepage:action',10,20,'{one}&two'] - - plink:['Homepage:action#hash',10,20,'{one}&two'] - - plink:['#hash'] - - plink:[':',10] - - plink:{'0':'default','1':10,'a':20,'b':30} - - link:['login'] - - - - - - - - - - - EOD, strtr($latte->renderToString(<<<'EOD' - {plink Homepage:} - - {plink Homepage: } - - {plink Homepage:action } - - {plink 'Homepage:action' } - - {plink Homepage:action 10, 20, '{one}&two'} - - {plink Homepage:action#hash 10, 20, '{one}&two'} - - {plink #hash} - - {plink : 10 } - - {plink default 10, 'a' => 20, 'b' => 30} - - {link $action} - - - - - - - - - - - EOD, $params), [''' => "'", ''' => "'", '{' => '{'])); diff --git a/tests/Bridges.Latte2/UIMacros.link.phpt b/tests/Bridges.Latte2/UIMacros.link.phpt deleted file mode 100644 index 52fda3fb0..000000000 --- a/tests/Bridges.Latte2/UIMacros.link.phpt +++ /dev/null @@ -1,68 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -$latte = new Latte\Engine; -$latte->setLoader(new Latte\Loaders\StringLoader); -UIMacros::install($latte->getCompiler()); - -// {link ...} -Assert::contains( - '$this->global->uiControl->link("p")', - $latte->compile('{link p}'), -); -Assert::contains( - '($this->filters->filter)($this->global->uiControl->link("p"))', - $latte->compile('{link p|filter}'), -); -Assert::contains( - '$this->global->uiControl->link("p:a")', - $latte->compile('{link p:a}'), -); -Assert::contains( - '$this->global->uiControl->link($dest)', - $latte->compile('{link $dest}'), -); -Assert::contains( - '$this->global->uiControl->link($p:$a)', - $latte->compile('{link $p:$a}'), -); -Assert::contains( - '$this->global->uiControl->link("$p:$a")', - $latte->compile('{link "$p:$a"}'), -); -Assert::contains( - '$this->global->uiControl->link("p:a")', - $latte->compile('{link "p:a"}'), -); -Assert::contains( - '$this->global->uiControl->link(\'p:a\')', - $latte->compile('{link \'p:a\'}'), -); - -Assert::contains( - '$this->global->uiControl->link("p", [\'param\'])', - $latte->compile('{link p param}'), -); -Assert::contains( - '$this->global->uiControl->link("p", [\'param\' => 123])', - $latte->compile('{link p param => 123}'), -); -Assert::contains( - '$this->global->uiControl->link("p", [\'param\' => 123])', - $latte->compile('{link p, param => 123}'), -); diff --git a/tests/Bridges.Latte2/UIMacros.renderSnippets.phpt b/tests/Bridges.Latte2/UIMacros.renderSnippets.phpt deleted file mode 100644 index 71c354140..000000000 --- a/tests/Bridges.Latte2/UIMacros.renderSnippets.phpt +++ /dev/null @@ -1,97 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class InnerControl extends Nette\Application\UI\Control -{ - public function render() - { - $latte = new Latte\Engine; - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiPresenter', $this->getPresenter()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new Nette\Bridges\ApplicationLatte\SnippetBridge($this)); - $params['say'] = 'Hello'; - $latte->render(__DIR__ . '/templates/snippet-included.latte', $params); - } -} - -class TestPresenter extends Nette\Application\UI\Presenter -{ - public function createComponentMulti() - { - return new Nette\Application\UI\Multiplier(function () { - $control = new InnerControl; - $control->redrawControl(); - return $control; - }); - } - - - public function render() - { - $latte = new Latte\Engine; - UIMacros::install($latte->getCompiler()); - $latte->addProvider('snippetBridge', new Nette\Bridges\ApplicationLatte\SnippetBridge($this)); - $latte->render(__DIR__ . '/templates/snippet-include.latte'); - } -} - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter->redrawControl(); -$presenter['multi-1']->redrawControl(); -$presenter->render(); -Assert::same([ - 'snippets' => [ - 'snippet--hello' => 'Hello', - 'snippet--include' => "

Included file #3 (A, B)

\n", - 'snippet--array-1' => 'Value 1', - 'snippet--array-2' => 'Value 2', - 'snippet--array-3' => 'Value 3', - 'snippet--array2-1' => 'Value 1', - 'snippet--array2-2' => 'Value 2', - 'snippet--array2-3' => 'Value 3', - 'snippet--includeSay' => 'Hello include snippet', - 'snippet--nested1' => "\t
Foo
\n", - 'snippet-multi-1-includeSay' => 'Hello', - ], -], (array) $presenter->payload); - - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter->redrawControl('hello'); -$presenter->redrawControl('array'); -$presenter->render(); - -Assert::same([ - 'snippets' => [ - 'snippet--hello' => 'Hello', - 'snippet--array-1' => 'Value 1', - 'snippet--array-2' => 'Value 2', - 'snippet--array-3' => 'Value 3', - ], -], (array) $presenter->payload); - -$presenter = new TestPresenter; -ob_start(); -$presenter->render(); -$content = ob_get_clean(); -Assert::matchFile(__DIR__ . '/expected/UIMacros.renderSnippets.html', $content); diff --git a/tests/Bridges.Latte2/UIMacros.renderSnippets2.phpt b/tests/Bridges.Latte2/UIMacros.renderSnippets2.phpt deleted file mode 100644 index 58a72d170..000000000 --- a/tests/Bridges.Latte2/UIMacros.renderSnippets2.phpt +++ /dev/null @@ -1,84 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class InnerControl extends Nette\Application\UI\Control -{ - public function render() - { - $this->renderA(); - $this->renderB(); - } - - - public function renderA() - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiPresenter', $this->getPresenter()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new SnippetBridge($this)); - $params['say'] = 'Hello'; - $latte->render('{snippet testA}{$say}{/snippet}', $params); - } - - - public function renderB() - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiPresenter', $this->getPresenter()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new SnippetBridge($this)); - $params['say'] = 'world'; - $latte->render('{snippet testB}{$say}{/snippet}', $params); - } -} - -class TestPresenter extends Nette\Application\UI\Presenter -{ - public function createComponentMulti() - { - return new Nette\Application\UI\Multiplier(fn() => new InnerControl); - } - - - public function render() - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new SnippetBridge($this)); - $latte->render(''); - } -} - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter['multi-1']->redrawControl(); -$presenter->render(); -Assert::same([ - 'snippets' => [ - 'snippet-multi-1-testA' => 'Hello', - 'snippet-multi-1-testB' => 'world', - ], -], (array) $presenter->payload); diff --git a/tests/Bridges.Latte2/UIMacros.renderSnippets3.phpt b/tests/Bridges.Latte2/UIMacros.renderSnippets3.phpt deleted file mode 100644 index 3dc72672b..000000000 --- a/tests/Bridges.Latte2/UIMacros.renderSnippets3.phpt +++ /dev/null @@ -1,73 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class TestControl extends Nette\Application\UI\Control -{ - public function render() - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiPresenter', $this->getPresenter()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new Nette\Bridges\ApplicationLatte\SnippetBridge($this)); - $latte->render('{snippet foo}hello{/snippet}'); - } -} - -class TestPresenter extends Nette\Application\UI\Presenter -{ - public function createComponentTest() - { - return new TestControl; - } - - - public function render() - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new Nette\Bridges\ApplicationLatte\SnippetBridge($this)); - $latte->render('{snippet foo}{control test}{/snippet}'); - } -} - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter->redrawControl('foo'); -$presenter['test']->redrawControl('foo'); -$presenter->render(); -Assert::same([ - 'snippets' => [ - 'snippet--foo' => '
hello
', - ], -], (array) $presenter->payload); - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter['test']->redrawControl('foo'); -$presenter->render(); -Assert::same([ - 'snippets' => [ - 'snippet-test-foo' => 'hello', - ], -], (array) $presenter->payload); diff --git a/tests/Bridges.Latte2/UIMacros.renderSnippets4.phpt b/tests/Bridges.Latte2/UIMacros.renderSnippets4.phpt deleted file mode 100644 index 917404369..000000000 --- a/tests/Bridges.Latte2/UIMacros.renderSnippets4.phpt +++ /dev/null @@ -1,54 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - - -class TestPresenter extends Nette\Application\UI\Presenter -{ - public function render() - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new SnippetBridge($this)); - $latte->render('{snippet foo}{php $presenter->renderFoo()}{/snippet}', ['presenter' => $this]); - } - - - public function renderFoo() - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new SnippetBridge($this)); - $latte->render('Hello'); - } -} - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter->redrawControl('foo'); -$presenter->render(); -Assert::same([ - 'snippets' => [ - 'snippet--foo' => 'Hello', - ], -], (array) $presenter->payload); diff --git a/tests/Bridges.Latte2/UIMacros.renderSnippets5.phpt b/tests/Bridges.Latte2/UIMacros.renderSnippets5.phpt deleted file mode 100644 index a915657fe..000000000 --- a/tests/Bridges.Latte2/UIMacros.renderSnippets5.phpt +++ /dev/null @@ -1,59 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - - -class TestPresenter extends Nette\Application\UI\Presenter -{ - public function render(string $template) - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('uiControl', $this); - $latte->addProvider('snippetBridge', new SnippetBridge($this)); - $latte->render($template, ['presenter' => $this]); - } -} - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter->redrawControl('foo'); -$presenter->render('
Hello
'); -Assert::same([ - 'snippets' => [ - 'snippet--foo' => 'Hello', - ], -], (array) $presenter->payload); - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter->redrawControl('foo'); -Assert::exception(function () use ($presenter) { - $presenter->render('
Hello
'); -}, Latte\CompileException::class, 'Cannot combine HTML attribute id with n:snippet.'); - - -$presenter = new TestPresenter; -$presenter->snippetMode = true; -$presenter->redrawControl('foo'); -Assert::exception(function () use ($presenter) { - $presenter->render('
Hello
'); -}, Latte\CompileException::class, 'Cannot combine HTML attribute id with n:snippet.'); diff --git a/tests/Bridges.Latte2/UIMacros.renderSnippets6.phpt b/tests/Bridges.Latte2/UIMacros.renderSnippets6.phpt deleted file mode 100644 index dc4e32a25..000000000 --- a/tests/Bridges.Latte2/UIMacros.renderSnippets6.phpt +++ /dev/null @@ -1,45 +0,0 @@ -')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -class TestPresenter extends Nette\Application\UI\Presenter -{ - public function render(string $template) - { - $latte = new Latte\Engine; - $latte->setLoader(new Latte\Loaders\StringLoader); - UIMacros::install($latte->getCompiler()); - $latte->addProvider('snippetBridge', new Nette\Bridges\ApplicationLatte\SnippetBridge($this)); - $latte->onCompile[] = function ($latte) { - $latte->getCompiler()->getMacros()['snippet'][0]->snippetAttribute = 'data-snippet'; - }; - $latte->render($template); - } -} - - -$presenter = new TestPresenter; -ob_start(); -$presenter->render('
hello
'); -$content = ob_get_clean(); -Assert::same('
hello
', $content); - - -$presenter = new TestPresenter; -Assert::exception(function () use ($presenter) { - $presenter->render('
hello
'); -}, Latte\CompileException::class, 'Cannot combine HTML attribute data-snippet with n:snippet.'); diff --git a/tests/Bridges.Latte2/expected/UIMacros.isLinkCurrent.php b/tests/Bridges.Latte2/expected/UIMacros.isLinkCurrent.php deleted file mode 100644 index 15ef390af..000000000 --- a/tests/Bridges.Latte2/expected/UIMacros.isLinkCurrent.php +++ /dev/null @@ -1,22 +0,0 @@ -%A%n:href before n:class - -n:href after n:class - -href before n:class - -href after n:class - -'; - if ($this->global->uiPresenter->getLastCreatedRequestFlag("current")) { - echo 'empty'; - } - echo ' - -'; - if ($this->global->uiPresenter->isLinkCurrent("default")) { - echo 'default'; - } - echo ' - -global->fn->isLinkCurrent)('default') ? 'current' : null%A%>custom function -%A% diff --git a/tests/Bridges.Latte2/expected/UIMacros.renderSnippets.html b/tests/Bridges.Latte2/expected/UIMacros.renderSnippets.html deleted file mode 100644 index 3ff3683ed..000000000 --- a/tests/Bridges.Latte2/expected/UIMacros.renderSnippets.html +++ /dev/null @@ -1,20 +0,0 @@ -
Hello
world! - -

Included file #3 (A, B)

-
- -
Value 1
-
Value 2
-
Value 3
-
- -
Value 1
-
Value 2
-
Value 3
- - -
Hello include snippet
- - -
Foo
-
diff --git a/tests/Bridges.Latte2/templates/include3.latte b/tests/Bridges.Latte2/templates/include3.latte deleted file mode 100644 index 14caf4cb4..000000000 --- a/tests/Bridges.Latte2/templates/include3.latte +++ /dev/null @@ -1 +0,0 @@ -

Included file #3 ({$localvar}, {$hello})

diff --git a/tests/Bridges.Latte2/templates/snippet-include.latte b/tests/Bridges.Latte2/templates/snippet-include.latte deleted file mode 100644 index 8a1ec964d..000000000 --- a/tests/Bridges.Latte2/templates/snippet-include.latte +++ /dev/null @@ -1,25 +0,0 @@ -{snippet hello}Hello{/snippet} world! - -{snippet include} - {include include3.latte localvar => 'A', hello => 'B'} -{/snippet} - -{snippet array} - {foreach [1, 2, 3] as $id} - {snippet "array-$id"}Value {$id}{/snippet} - {/foreach} -{/snippet} - -{snippetArea array2} - {foreach [1, 2, 3] as $id} - {snippet "array2-$id"}Value {$id}{/snippet} - {/foreach} -{/snippetArea} - -{snippetArea foo} - {include snippet-included.latte say => 'Hello include snippet'} -{/snippetArea} - -{snippet nested1} - {snippet nested2}Foo{/snippet} -{/snippet} diff --git a/tests/Bridges.Latte2/templates/snippet-included.latte b/tests/Bridges.Latte2/templates/snippet-included.latte deleted file mode 100644 index a392b6227..000000000 --- a/tests/Bridges.Latte2/templates/snippet-included.latte +++ /dev/null @@ -1 +0,0 @@ -{snippet includeSay}{$say}{/snippet} diff --git a/tests/Bridges.Latte3/Template.getParentName().phpt b/tests/Bridges.Latte3/Template.getParentName().phpt index b354ad1ee..e63f523eb 100644 --- a/tests/Bridges.Latte3/Template.getParentName().phpt +++ b/tests/Bridges.Latte3/Template.getParentName().phpt @@ -6,10 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - Tester\Environment::bypassFinals(); $presenter = Mockery::mock(Nette\Application\UI\Presenter::class) diff --git a/tests/Bridges.Latte3/TemplateFactory.customTemplate.phpt b/tests/Bridges.Latte3/TemplateFactory.customTemplate.phpt index 976f99b78..4df04c5a7 100644 --- a/tests/Bridges.Latte3/TemplateFactory.customTemplate.phpt +++ b/tests/Bridges.Latte3/TemplateFactory.customTemplate.phpt @@ -14,10 +14,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - Tester\Environment::bypassFinals(); @@ -46,21 +42,22 @@ class TemplateMock extends Template } -test('', function () { +test('default template creation', function () { $latteFactory = Mockery::mock(LatteFactory::class); $latteFactory->shouldReceive('create')->andReturn(new Latte\Engine); $factory = new TemplateFactory($latteFactory); Assert::type(Template::class, $factory->createTemplate()); }); -Assert::exception( +testException( + '13456', fn() => new TemplateFactory(Mockery::mock(LatteFactory::class), templateClass: stdClass::class), Nette\InvalidArgumentException::class, 'Class stdClass does not implement Nette\Bridges\ApplicationLatte\Template or it does not exist.', ); -test('', function () { +test('custom template behavior', function () { $latteFactory = Mockery::mock(LatteFactory::class); $latteFactory->shouldReceive('create')->andReturn(new Latte\Engine); $factory = new TemplateFactory($latteFactory, templateClass: TemplateMock::class); diff --git a/tests/Bridges.Latte3/TemplateFactory.onCreate.phpt b/tests/Bridges.Latte3/TemplateFactory.onCreate.phpt index ed6e9b61c..987e86aea 100644 --- a/tests/Bridges.Latte3/TemplateFactory.onCreate.phpt +++ b/tests/Bridges.Latte3/TemplateFactory.onCreate.phpt @@ -14,10 +14,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - test('', function () { $engine = new Latte\Engine; diff --git a/tests/Bridges.Latte3/UIExtension.filters.absoluteUrl.phpt b/tests/Bridges.Latte3/UIExtension.filters.absoluteUrl.phpt new file mode 100644 index 000000000..e79aaf6d8 --- /dev/null +++ b/tests/Bridges.Latte3/UIExtension.filters.absoluteUrl.phpt @@ -0,0 +1,59 @@ +addExtension(new Nette\Bridges\ApplicationLatte\UIExtension(null)); + +Assert::same(null, $latte->invokeFilter('absoluteUrl', [''])); + + +$request = Mockery::mock(Nette\Http\IRequest::class); +$request->shouldReceive('getUrl')->andReturn(new Nette\Http\UrlScript('https://nette.org/a/b')); +$request->shouldIgnoreMissing(); + +$response = Mockery::mock(Nette\Http\IResponse::class); +$response->shouldIgnoreMissing(); + +$presenter = Mockery::mock(Nette\Application\UI\Presenter::class); +$presenter->shouldReceive('getPresenterIfExists')->andReturn($presenter); +$presenter->shouldReceive('getHttpRequest')->andReturn($request); +$presenter->shouldReceive('getHttpResponse')->andReturn($response); +$presenter->shouldIgnoreMissing(); + + +$latte = new Latte\Engine; +$latte->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension($presenter)); + +Assert::same('https://nette.org/a/b', $latte->invokeFilter('absoluteUrl', [''])); +Assert::same('https://nette.org/a/b#foo', $latte->invokeFilter('absoluteUrl', ['#foo'])); +Assert::same('https://nette.org/a/foo', $latte->invokeFilter('absoluteUrl', ['foo'])); +Assert::same('https://nette.org/foo', $latte->invokeFilter('absoluteUrl', ['/foo'])); +Assert::same('https://foo/', $latte->invokeFilter('absoluteUrl', ['//foo'])); +Assert::same('https://foo/', $latte->invokeFilter('absoluteUrl', ['https://foo'])); + + +class Foo +{ + public function __toString() + { + return 'foo'; + } +} + +Assert::same('https://nette.org/a/foo', $latte->invokeFilter('absoluteUrl', [new Foo])); diff --git a/tests/Bridges.Latte3/UIExtension.filters.phpt b/tests/Bridges.Latte3/UIExtension.filters.phpt index 952f5a760..0dc89f8cd 100644 --- a/tests/Bridges.Latte3/UIExtension.filters.phpt +++ b/tests/Bridges.Latte3/UIExtension.filters.phpt @@ -10,10 +10,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension(null)); diff --git a/tests/Bridges.Latte3/UIExtension.nonce.control.phpt b/tests/Bridges.Latte3/UIExtension.nonce.control.phpt index 9248da8af..cf822c0ab 100644 --- a/tests/Bridges.Latte3/UIExtension.nonce.control.phpt +++ b/tests/Bridges.Latte3/UIExtension.nonce.control.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $response = Mockery::mock(Nette\Http\IResponse::class); $response->shouldReceive('getHeader')->with('Content-Security-Policy')->andReturn("hello 'nonce-abcd123==' world"); diff --git a/tests/Bridges.Latte3/UIExtension.nonce.presenter.phpt b/tests/Bridges.Latte3/UIExtension.nonce.presenter.phpt index 2f2a8d254..15f0d212d 100644 --- a/tests/Bridges.Latte3/UIExtension.nonce.presenter.phpt +++ b/tests/Bridges.Latte3/UIExtension.nonce.presenter.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - Tester\Environment::bypassFinals(); $response = Mockery::mock(Nette\Http\IResponse::class); diff --git a/tests/Bridges.Latte3/isLinkCurrent().phpt b/tests/Bridges.Latte3/isLinkCurrent().phpt index 1ca37dcb3..277027dc9 100644 --- a/tests/Bridges.Latte3/isLinkCurrent().phpt +++ b/tests/Bridges.Latte3/isLinkCurrent().phpt @@ -10,10 +10,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - Tester\Environment::bypassFinals(); $presenter = Mockery::mock(Nette\Application\UI\Presenter::class); diff --git a/tests/Bridges.Latte3/n-snippet.2.phpt b/tests/Bridges.Latte3/n-snippet.2.phpt index 983c46ce5..a5cfc2a20 100644 --- a/tests/Bridges.Latte3/n-snippet.2.phpt +++ b/tests/Bridges.Latte3/n-snippet.2.phpt @@ -6,10 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setLoader(new Latte\Loaders\StringLoader); $latte->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension(null)); diff --git a/tests/Bridges.Latte3/n-snippet.block.phpt b/tests/Bridges.Latte3/n-snippet.block.phpt index 107dd6ebc..27a83c2f7 100644 --- a/tests/Bridges.Latte3/n-snippet.block.phpt +++ b/tests/Bridges.Latte3/n-snippet.block.phpt @@ -6,10 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setLoader(new Latte\Loaders\StringLoader); diff --git a/tests/Bridges.Latte3/n-snippet.dynamic.phpt b/tests/Bridges.Latte3/n-snippet.dynamic.phpt index ab2827bca..a794e2d0c 100644 --- a/tests/Bridges.Latte3/n-snippet.dynamic.phpt +++ b/tests/Bridges.Latte3/n-snippet.dynamic.phpt @@ -6,10 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setLoader(new Latte\Loaders\StringLoader); diff --git a/tests/Bridges.Latte3/n-snippet.phpt b/tests/Bridges.Latte3/n-snippet.phpt index c9ff1b893..ac2247eec 100644 --- a/tests/Bridges.Latte3/n-snippet.phpt +++ b/tests/Bridges.Latte3/n-snippet.phpt @@ -6,9 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} class Test { diff --git a/tests/Bridges.Latte3/renderSnippets.phpt b/tests/Bridges.Latte3/renderSnippets.phpt index 675995784..4d113171f 100644 --- a/tests/Bridges.Latte3/renderSnippets.phpt +++ b/tests/Bridges.Latte3/renderSnippets.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class InnerControl extends Nette\Application\UI\Control { diff --git a/tests/Bridges.Latte3/renderSnippets2.phpt b/tests/Bridges.Latte3/renderSnippets2.phpt index 31522dbee..1a092d470 100644 --- a/tests/Bridges.Latte3/renderSnippets2.phpt +++ b/tests/Bridges.Latte3/renderSnippets2.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class InnerControl extends Nette\Application\UI\Control { diff --git a/tests/Bridges.Latte3/renderSnippets3.phpt b/tests/Bridges.Latte3/renderSnippets3.phpt index dd11322d4..65a621014 100644 --- a/tests/Bridges.Latte3/renderSnippets3.phpt +++ b/tests/Bridges.Latte3/renderSnippets3.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class TestControl extends Nette\Application\UI\Control { diff --git a/tests/Bridges.Latte3/renderSnippets4.phpt b/tests/Bridges.Latte3/renderSnippets4.phpt index 3bf12a6e5..c209301c6 100644 --- a/tests/Bridges.Latte3/renderSnippets4.phpt +++ b/tests/Bridges.Latte3/renderSnippets4.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class TestPresenter extends Nette\Application\UI\Presenter { diff --git a/tests/Bridges.Latte3/renderSnippets5.phpt b/tests/Bridges.Latte3/renderSnippets5.phpt index fdbd86159..340e36cf6 100644 --- a/tests/Bridges.Latte3/renderSnippets5.phpt +++ b/tests/Bridges.Latte3/renderSnippets5.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class TestPresenter extends Nette\Application\UI\Presenter { diff --git a/tests/Bridges.Latte3/renderSnippets6.phpt b/tests/Bridges.Latte3/renderSnippets6.phpt index f264135e7..a9cda7417 100644 --- a/tests/Bridges.Latte3/renderSnippets6.phpt +++ b/tests/Bridges.Latte3/renderSnippets6.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class TestPresenter extends Nette\Application\UI\Presenter { diff --git a/tests/Bridges.Latte3/renderSnippets7.phpt b/tests/Bridges.Latte3/renderSnippets7.phpt index 63f3cb635..a7689c434 100644 --- a/tests/Bridges.Latte3/renderSnippets7.phpt +++ b/tests/Bridges.Latte3/renderSnippets7.phpt @@ -9,10 +9,6 @@ Tester\Environment::bypassFinals(); require __DIR__ . '/ControlMock.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $dataSets = [ diff --git a/tests/Bridges.Latte3/{control}.2.phpt b/tests/Bridges.Latte3/{control}.2.phpt index bb2cb9171..7086c7fd1 100644 --- a/tests/Bridges.Latte3/{control}.2.phpt +++ b/tests/Bridges.Latte3/{control}.2.phpt @@ -10,10 +10,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class MockComponent { diff --git a/tests/Bridges.Latte3/{control}.3.phpt b/tests/Bridges.Latte3/{control}.3.phpt index 7a270383f..d9317b057 100644 --- a/tests/Bridges.Latte3/{control}.3.phpt +++ b/tests/Bridges.Latte3/{control}.3.phpt @@ -10,9 +10,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} $control = new class { public function render() diff --git a/tests/Bridges.Latte3/{control}.phpt b/tests/Bridges.Latte3/{control}.phpt index a1ba85e15..8d78e3546 100644 --- a/tests/Bridges.Latte3/{control}.phpt +++ b/tests/Bridges.Latte3/{control}.phpt @@ -10,10 +10,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setLoader(new Latte\Loaders\StringLoader); diff --git a/tests/Bridges.Latte3/{ifCurrent}.phpt b/tests/Bridges.Latte3/{ifCurrent}.phpt index 3c9ee133e..0be5f05e2 100644 --- a/tests/Bridges.Latte3/{ifCurrent}.phpt +++ b/tests/Bridges.Latte3/{ifCurrent}.phpt @@ -6,10 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - Tester\Environment::bypassFinals(); $latte = new Latte\Engine; diff --git a/tests/Bridges.Latte3/{link}.2.phpt b/tests/Bridges.Latte3/{link}.2.phpt index 816283b42..7fc270038 100644 --- a/tests/Bridges.Latte3/{link}.2.phpt +++ b/tests/Bridges.Latte3/{link}.2.phpt @@ -10,10 +10,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - class MockControl { diff --git a/tests/Bridges.Latte3/{link}.phpt b/tests/Bridges.Latte3/{link}.phpt index e2457c9a7..9d8e296e6 100644 --- a/tests/Bridges.Latte3/{link}.phpt +++ b/tests/Bridges.Latte3/{link}.phpt @@ -10,10 +10,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setLoader(new Latte\Loaders\StringLoader); diff --git a/tests/Bridges.Latte3/{snippet}.dynamic.phpt b/tests/Bridges.Latte3/{snippet}.dynamic.phpt index 3b2068ed0..1eb5aacdd 100644 --- a/tests/Bridges.Latte3/{snippet}.dynamic.phpt +++ b/tests/Bridges.Latte3/{snippet}.dynamic.phpt @@ -6,10 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setLoader(new Latte\Loaders\StringLoader); diff --git a/tests/Bridges.Latte3/{snippet}.phpt b/tests/Bridges.Latte3/{snippet}.phpt index bf9022dce..5afa062ef 100644 --- a/tests/Bridges.Latte3/{snippet}.phpt +++ b/tests/Bridges.Latte3/{snippet}.phpt @@ -6,10 +6,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setLoader(new Latte\Loaders\StringLoader); diff --git a/tests/Responses/CallbackResponse.phpt b/tests/Responses/CallbackResponse.phpt index 8579c95e8..dbf51bb3d 100644 --- a/tests/Responses/CallbackResponse.phpt +++ b/tests/Responses/CallbackResponse.phpt @@ -14,7 +14,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('callback execution on send', function () { $response = new CallbackResponse(function (Http\IRequest $request, Http\IResponse $response) use (&$ok) { $ok = true; }); diff --git a/tests/Responses/FileResponse.contentDisposition.phpt b/tests/Responses/FileResponse.contentDisposition.phpt index 173b8680d..0b291bc9a 100644 --- a/tests/Responses/FileResponse.contentDisposition.phpt +++ b/tests/Responses/FileResponse.contentDisposition.phpt @@ -18,7 +18,7 @@ if (PHP_SAPI === 'cli') { } -test('', function () { +test('default attachment content disposition', function () { $file = __FILE__; $fileResponse = new FileResponse($file); $origData = file_get_contents($file); @@ -34,7 +34,7 @@ test('', function () { }); -test('', function () { +test('inline content disposition', function () { $file = __FILE__; $fileResponse = new FileResponse($file, forceDownload: false); $origData = file_get_contents($file); @@ -50,7 +50,7 @@ test('', function () { }); -test('', function () { +test('filename with special characters', function () { $file = __FILE__; $fileName = 'žluťoučký kůň.txt'; $fileResponse = new FileResponse($file, $fileName); diff --git a/tests/Responses/FileResponse.full.phpt b/tests/Responses/FileResponse.full.phpt index dc5528913..b3e7a2fc1 100644 --- a/tests/Responses/FileResponse.full.phpt +++ b/tests/Responses/FileResponse.full.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/../bootstrap.php'; /* A small file */ -test('', function () { +test('small file content delivery', function () { $file = __FILE__; $fileResponse = new FileResponse($file); $origData = file_get_contents($file); @@ -26,7 +26,7 @@ test('', function () { }); /* A big file */ -test('', function () { +test('large file content delivery', function () { $file = Tester\FileMock::create(); $data = ''; diff --git a/tests/Responses/FileResponse.range.phpt b/tests/Responses/FileResponse.range.phpt index 99c380854..7601f481f 100644 --- a/tests/Responses/FileResponse.range.phpt +++ b/tests/Responses/FileResponse.range.phpt @@ -19,7 +19,7 @@ $file = __FILE__; $fileResponse = new FileResponse($file); $origData = file_get_contents($file); -test('', function () use ($fileResponse, $origData) { +test('partial content with byte range', function () use ($fileResponse, $origData) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=10-20']), @@ -30,7 +30,7 @@ test('', function () use ($fileResponse, $origData) { }); -test('', function () use ($fileResponse, $origData) { +test('single byte range request', function () use ($fileResponse, $origData) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=10-10']), @@ -40,7 +40,7 @@ test('', function () use ($fileResponse, $origData) { }); -test('', function () use ($fileResponse, $origData, $file) { +test('range from offset to end', function () use ($fileResponse, $origData, $file) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=10-' . filesize($file)]), @@ -50,7 +50,7 @@ test('', function () use ($fileResponse, $origData, $file) { }); -test('prefix', function () use ($fileResponse, $origData) { +test('range starting at offset', function () use ($fileResponse, $origData) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=20-']), @@ -60,7 +60,7 @@ test('prefix', function () use ($fileResponse, $origData) { }); -test('prefix', function () use ($fileResponse, $origData, $file) { +test('last byte range request', function () use ($fileResponse, $origData, $file) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=' . (filesize($file) - 1) . '-']), @@ -70,7 +70,7 @@ test('prefix', function () use ($fileResponse, $origData, $file) { }); -test('prefix', function () use ($fileResponse, $file) { +test('invalid byte range handling', function () use ($fileResponse, $file) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=' . filesize($file) . '-']), @@ -81,7 +81,7 @@ test('prefix', function () use ($fileResponse, $file) { }); -test('suffix', function () use ($fileResponse, $origData) { +test('negative offset range (last bytes)', function () use ($fileResponse, $origData) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=-20']), @@ -91,7 +91,7 @@ test('suffix', function () use ($fileResponse, $origData) { }); -test('suffix', function () use ($fileResponse, $origData, $file) { +test('full content via negative range', function () use ($fileResponse, $origData, $file) { ob_start(); $fileResponse->send( new Http\Request(new Http\UrlScript, headers: ['range' => 'bytes=-' . filesize($file)]), diff --git a/tests/Responses/JsonResponse.contentType.phpt b/tests/Responses/JsonResponse.contentType.phpt index 0cbe48d12..f492ba728 100644 --- a/tests/Responses/JsonResponse.contentType.phpt +++ b/tests/Responses/JsonResponse.contentType.phpt @@ -17,7 +17,7 @@ if (PHP_SAPI === 'cli') { Tester\Environment::skip('Requires CGI SAPI to work with HTTP headers.'); } -test('', function () { +test('JSON content type with UTF-8 charset', function () { $data = ['text' => 'žluťoučký kůň']; $encoded = json_encode($data, JSON_UNESCAPED_UNICODE); $jsonResponse = new JsonResponse($data, 'application/json'); @@ -29,7 +29,7 @@ test('', function () { Assert::same('application/json; charset=utf-8', $response->getHeader('Content-Type')); }); -test('', function () { +test('boolean data JSON encoding', function () { $data = true; $encoded = json_encode($data, JSON_UNESCAPED_UNICODE); $jsonResponse = new JsonResponse($data, 'application/json'); diff --git a/tests/Routers/LinkGenerator.phpt b/tests/Routers/LinkGenerator.phpt index 3acc40491..c4caea104 100644 --- a/tests/Routers/LinkGenerator.phpt +++ b/tests/Routers/LinkGenerator.phpt @@ -6,7 +6,9 @@ declare(strict_types=1); -namespace { +namespace App\Presentation\Homepage { + + use Nette; require __DIR__ . '/../bootstrap.php'; @@ -24,7 +26,7 @@ namespace { } -namespace ModuleModule { +namespace App\Presentation\Module\My { use Nette; @@ -49,7 +51,7 @@ namespace { $pf = new PresenterFactory; - test('', function () use ($pf) { + test('basic link generation with various parameters', function () use ($pf) { $generator = new LinkGenerator(new Routers\SimpleRouter, new Http\UrlScript('http://nette.org/en/'), $pf); Assert::same('http://nette.org/en/?action=default&presenter=Homepage', $generator->link('Homepage:default')); Assert::same('http://nette.org/en/?action=default&presenter=Module%3AMy', $generator->link('Module:My:default')); @@ -62,25 +64,25 @@ namespace { }); - Assert::exception(function () use ($pf) { + testException('missing presenter specification error', function () use ($pf) { $generator = new LinkGenerator(new Routers\SimpleRouter, new Http\UrlScript('http://nette.org/en/'), $pf); $generator->link('default'); }, LogicException::class, "Presenter must be specified in 'default'."); - Assert::exception(function () use ($pf) { + testException('route mismatch exception handling', function () use ($pf) { $generator = new LinkGenerator(new Routers\Route('/', 'Product:'), new Http\UrlScript('http://nette.org/en/'), $pf); $generator->link('Homepage:default', ['id' => 10]); }, Nette\Application\UI\InvalidLinkException::class, 'No route for Homepage:default(id=10)'); - Assert::exception(function () use ($pf) { + testException('invalid action parameter propagation', function () use ($pf) { $generator = new LinkGenerator(new Routers\Route('/', 'Homepage:'), new Http\UrlScript('http://nette.org/en/'), $pf); $generator->link('Homepage:missing', [10]); - }, Nette\Application\UI\InvalidLinkException::class, "Unable to pass parameters to action 'Homepage:missing', missing corresponding method HomepagePresenter::renderMissing()."); + }, Nette\Application\UI\InvalidLinkException::class, "Unable to pass parameters to action 'Homepage:missing', missing corresponding method App\\UI\\Homepage\\HomepagePresenter::renderMissing()."); - test('', function () { + test('URL generation without PresenterFactory', function () { $generator = new LinkGenerator(new Routers\SimpleRouter, new Http\UrlScript('http://nette.org/en/')); Assert::same('http://nette.org/en/?action=default&presenter=Homepage', $generator->link('Homepage:default')); Assert::same('http://nette.org/en/?action=default&presenter=Module%3AMy', $generator->link('Module:My:default')); @@ -93,7 +95,7 @@ namespace { }); - test('', function () { + test('reference URL context switching', function () { $generator = new LinkGenerator(new Routers\SimpleRouter, new Http\UrlScript('http://nette.org/en/')); $generator2 = $generator->withReferenceUrl('http://nette.org/cs/'); Assert::same('http://nette.org/en/?action=default&presenter=Homepage', $generator->link('Homepage:default')); diff --git a/tests/Routers/Route.scalarParams.phpt b/tests/Routers/Route.scalarParams.phpt index 4f475fea3..030d88195 100644 --- a/tests/Routers/Route.scalarParams.phpt +++ b/tests/Routers/Route.scalarParams.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/../bootstrap.php'; require __DIR__ . '/Route.php'; -test('', function () { +test('numeric and boolean parameter serialization', function () { $route = new Route('/', [ ]); @@ -44,7 +44,7 @@ test('', function () { }); -test('', function () { +test('default integer parameter handling', function () { $route = new Route('/', [ 'param' => 12, ]); @@ -78,7 +78,7 @@ test('', function () { }); -test('', function () { +test('default float parameter handling', function () { $route = new Route('/', [ 'param' => 12.1, ]); @@ -112,7 +112,7 @@ test('', function () { }); -test('', function () { +test('boolean default parameter optimization', function () { $route = new Route('/', [ 'param' => true, ]); @@ -146,7 +146,7 @@ test('', function () { }); -test('', function () { +test('false default parameter optimization', function () { $route = new Route('/', [ 'param' => false, ]); @@ -180,7 +180,7 @@ test('', function () { }); -test('', function () { +test('null default parameter handling', function () { $route = new Route('/', [ 'param' => null, ]); diff --git a/tests/Routers/RouteList.basic.phpt b/tests/Routers/RouteList.basic.phpt index 22afeda6c..b4783db95 100644 --- a/tests/Routers/RouteList.basic.phpt +++ b/tests/Routers/RouteList.basic.phpt @@ -6,7 +6,6 @@ declare(strict_types=1); -use Nette\Application\Routers\Route; use Nette\Application\Routers\RouteList; use Tester\Assert; @@ -17,7 +16,7 @@ require __DIR__ . '/Route.php'; $list = new RouteList; -$list[] = new Route('//'); +$list->addRoute('//'); Assert::same('http://example.com/front.homepage/', testRouteOut($list, ['presenter' => 'Front:Homepage'])); diff --git a/tests/Routers/RouteList.modules.phpt b/tests/Routers/RouteList.modules.phpt index db2aff0d2..ff1e15193 100644 --- a/tests/Routers/RouteList.modules.phpt +++ b/tests/Routers/RouteList.modules.phpt @@ -6,7 +6,6 @@ declare(strict_types=1); -use Nette\Application\Routers\Route; use Nette\Application\Routers\RouteList; @@ -16,12 +15,12 @@ require __DIR__ . '/Route.php'; $list = new RouteList; -$list[] = new Route('auth/[/]', [ +$list->addRoute('auth/[/]', [ 'module' => 'Auth', 'presenter' => 'Homepage', 'action' => 'default', ]); -$list[] = new Route('[/]', [ +$list->addRoute('[/]', [ 'module' => 'Default', 'presenter' => 'Homepage', 'action' => 'default', diff --git a/tests/Routers/SimpleRouter.invalid.phpt b/tests/Routers/SimpleRouter.invalid.phpt index ab34229e0..f9d8b3723 100644 --- a/tests/Routers/SimpleRouter.invalid.phpt +++ b/tests/Routers/SimpleRouter.invalid.phpt @@ -16,7 +16,7 @@ require __DIR__ . '/../bootstrap.php'; -test('', function () { +test('array parameter in presenter name', function () { $router = new SimpleRouter; $url = new Http\UrlScript('http://nette.org?presenter[]=foo'); $httpRequest = new Http\Request($url); @@ -25,7 +25,7 @@ test('', function () { Assert::same(['presenter' => ['foo']], $req); }); -test('', function () { +test('empty request parameter handling', function () { $router = new SimpleRouter; $url = new Http\UrlScript('http://nette.org'); $httpRequest = new Http\Request($url); diff --git a/tests/Routers/link-aliases.phpt b/tests/Routers/link-aliases.phpt index 0f2b75324..2180bd526 100644 --- a/tests/Routers/link-aliases.phpt +++ b/tests/Routers/link-aliases.phpt @@ -20,6 +20,7 @@ class TestPresenter extends Application\UI\Presenter $factory = new PresenterFactory; +$factory->setMapping(['*' => '*Presenter']); $factory->setAliases([ 'a' => 'Test:a', 'b' => 'Test:b', diff --git a/tests/UI/Component.redirect().phpt b/tests/UI/Component.redirect().phpt index 60f3972f5..3afc6a9a7 100644 --- a/tests/UI/Component.redirect().phpt +++ b/tests/UI/Component.redirect().phpt @@ -24,7 +24,7 @@ class TestPresenter extends Application\UI\Presenter } - public function sendResponse(Application\Response $response): void + public function sendResponse(Application\Response $response): never { parent::sendResponse($this->response = $response); } @@ -41,7 +41,7 @@ $presenter->injectPrimary( ); -test('', function () use ($presenter) { +test('basic redirect response generation', function () use ($presenter) { try { $presenter->redirect('foo'); } catch (Throwable) { @@ -52,7 +52,7 @@ test('', function () use ($presenter) { }); -test('', function () use ($presenter) { +test('redirect with named parameters', function () use ($presenter) { try { $presenter->redirect('foo', ['arg' => 1]); } catch (Throwable) { @@ -63,7 +63,7 @@ test('', function () use ($presenter) { }); -test('', function () use ($presenter) { +test('positional parameter in redirect', function () use ($presenter) { try { $presenter->redirect('foo', 2); } catch (Throwable) { @@ -74,7 +74,7 @@ test('', function () use ($presenter) { }); -test('', function () use ($presenter) { +test('permanent redirect with parameter', function () use ($presenter) { try { $presenter->redirectPermanent('foo', 2); } catch (Throwable) { @@ -85,7 +85,7 @@ test('', function () use ($presenter) { }); -test('', function () use ($presenter) { +test('permanent redirect with named parameters', function () use ($presenter) { try { $presenter->redirectPermanent('foo', ['arg' => 1]); } catch (Throwable) { diff --git a/tests/UI/ComponentReflection.getParameters().phpt b/tests/UI/ComponentReflection.getParameters().phpt index e1d177edc..dd0154b59 100644 --- a/tests/UI/ComponentReflection.getParameters().phpt +++ b/tests/UI/ComponentReflection.getParameters().phpt @@ -16,7 +16,7 @@ class OnePresenter extends Presenter public static $no1; public $no2; - /** @persistent */ + #[Persistent] public $yes1; #[Persistent, Parameter] diff --git a/tests/UI/ComponentReflection.getPersistentComponents().phpt b/tests/UI/ComponentReflection.getPersistentComponents().phpt index 2654e06d9..febe683f3 100644 --- a/tests/UI/ComponentReflection.getPersistentComponents().phpt +++ b/tests/UI/ComponentReflection.getPersistentComponents().phpt @@ -14,14 +14,6 @@ class NonePresenter extends Presenter } -/** - * @persistent(a, b) - */ -class AnnotationPresenter extends Presenter -{ -} - - #[Persistent('a', 'b')] class AttributePresenter extends Presenter { @@ -39,11 +31,6 @@ class MethodPresenter extends AttributePresenter Assert::same([], NonePresenter::getReflection()->getPersistentComponents()); -Assert::same([ - 'a' => ['since' => AnnotationPresenter::class], - 'b' => ['since' => AnnotationPresenter::class], -], AnnotationPresenter::getReflection()->getPersistentComponents()); - Assert::same([ 'a' => ['since' => AttributePresenter::class], 'b' => ['since' => AttributePresenter::class], diff --git a/tests/UI/ComponentReflection.parseAnnotation.phpt b/tests/UI/ComponentReflection.parseAnnotation.phpt index 278b5e7d1..71a614e90 100644 --- a/tests/UI/ComponentReflection.parseAnnotation.phpt +++ b/tests/UI/ComponentReflection.parseAnnotation.phpt @@ -34,11 +34,11 @@ class TestClass $rc = new ReflectionClass('TestClass'); -Assert::same(['value ="Johno\'s addendum"', 'mode=True', true, true], Reflection::parseAnnotation($rc, 'title')); -Assert::null(Reflection::parseAnnotation($rc, 'public')); -Assert::null(Reflection::parseAnnotation($rc, 'private')); -Assert::same(['item 1'], Reflection::parseAnnotation($rc, 'components')); -Assert::same([true, false, null], Reflection::parseAnnotation($rc, 'persistent')); -Assert::same([true], Reflection::parseAnnotation($rc, 'renderable')); -Assert::same(['loggedIn'], Reflection::parseAnnotation($rc, 'Secured\User')); -Assert::null(Reflection::parseAnnotation($rc, 'missing')); +Assert::same(['value ="Johno\'s addendum"', 'mode=True', true, true], @Reflection::parseAnnotation($rc, 'title')); +Assert::null(@Reflection::parseAnnotation($rc, 'public')); +Assert::null(@Reflection::parseAnnotation($rc, 'private')); +Assert::same(['item 1'], @Reflection::parseAnnotation($rc, 'components')); +Assert::same([true, false, null], @Reflection::parseAnnotation($rc, 'persistent')); +Assert::same([true], @Reflection::parseAnnotation($rc, 'renderable')); +Assert::same(['loggedIn'], @Reflection::parseAnnotation($rc, 'Secured\User')); +Assert::null(@Reflection::parseAnnotation($rc, 'missing')); diff --git a/tests/UI/Control.formatTemplateClass.phpt b/tests/UI/Control.formatTemplateClass.phpt index 4d66a4a49..bb2a21ae7 100644 --- a/tests/UI/Control.formatTemplateClass.phpt +++ b/tests/UI/Control.formatTemplateClass.phpt @@ -46,13 +46,13 @@ class CTemplate implements Nette\Application\UI\Template } -test('without template', function () { +test('no associated template class', function () { $control = new AControl; Assert::null($control->formatTemplateClass()); }); -test('with class', function () { +test('template class missing interface implementation', function () { Assert::error(function () { $control = new BControl; Assert::null($control->formatTemplateClass()); @@ -60,7 +60,7 @@ test('with class', function () { }); -test('with template', function () { +test('valid template class implementation', function () { $control = new CControl; Assert::same(CTemplate::class, $control->formatTemplateClass()); }); diff --git a/tests/UI/Control.isControlInvalid.phpt b/tests/UI/Control.isControlInvalid.phpt index 0021c9b9e..2b802b364 100644 --- a/tests/UI/Control.isControlInvalid.phpt +++ b/tests/UI/Control.isControlInvalid.phpt @@ -18,7 +18,7 @@ class TestControl extends UI\Control } -test('', function () { +test('direct child component invalidation', function () { $control = new TestControl; $child = new TestControl; $control->addComponent($child, 'foo'); @@ -29,7 +29,7 @@ test('', function () { }); -test('', function () { +test('nested component invalidation propagation', function () { $control = new TestControl; $child = new Nette\ComponentModel\Container; $grandChild = new TestControl; diff --git a/tests/UI/Form.phpt b/tests/UI/Form.phpt index 66c8ef39b..90a780aec 100644 --- a/tests/UI/Form.phpt +++ b/tests/UI/Form.phpt @@ -18,14 +18,14 @@ class TestPresenter extends UI\Presenter } -test('', function () { +test('form method setup validation', function () { $presenter = new TestPresenter; $form = new UI\Form($presenter, 'name'); $form->setMethod($form::Get); // must not throw exception }); -test('compatibility with 2.0', function () { +test('form action assignment check', function () { $presenter = new TestPresenter; $form = new UI\Form; $form->setAction('action'); diff --git a/tests/UI/LinkGenerator.parseDestination().phpt b/tests/UI/LinkGenerator.parseDestination().phpt index 5132e99a4..82655a85b 100644 --- a/tests/UI/LinkGenerator.parseDestination().phpt +++ b/tests/UI/LinkGenerator.parseDestination().phpt @@ -48,7 +48,7 @@ Assert::same([ 'signal' => false, 'args' => [], 'fragment' => '#fragment', -], LinkGenerator::parseDestination('a:b?#fragment')); +], @LinkGenerator::parseDestination('a:b?#fragment')); // deprecated Assert::same([ 'absolute' => false, @@ -56,7 +56,7 @@ Assert::same([ 'signal' => false, 'args' => ['a' => 'b', 'c' => 'd'], 'fragment' => '#fragment', -], LinkGenerator::parseDestination('a:b?a=b&c=d#fragment')); +], @LinkGenerator::parseDestination('a:b?a=b&c=d#fragment')); // deprecated Assert::exception( fn() => LinkGenerator::parseDestination(''), diff --git a/tests/UI/ParameterConverter.toArguments.phpt b/tests/UI/ParameterConverter.toArguments.phpt index 688a2086c..f9fc325ab 100644 --- a/tests/UI/ParameterConverter.toArguments.phpt +++ b/tests/UI/ParameterConverter.toArguments.phpt @@ -65,7 +65,7 @@ class MyPresenter } -test('', function () { +test('untyped parameter handling', function () { $method = new ReflectionMethod('MyPresenter', 'params'); Assert::same([null, null, null, null], ParameterConverter::toArguments($method, [])); @@ -91,7 +91,7 @@ test('', function () { }); -test('', function () { +test('type-hinted parameter validation', function () { $method = new ReflectionMethod('MyPresenter', 'hints'); Assert::same( @@ -144,7 +144,7 @@ test('', function () { }); -test('', function () { +test('nullable type-hinted parameters with defaults', function () { $method = new ReflectionMethod('MyPresenter', 'hintsNulls'); Assert::same([null, null, null, null, null], ParameterConverter::toArguments($method, [])); @@ -193,7 +193,7 @@ test('', function () { }); -test('', function () { +test('nullable parameter type conversion', function () { $method = new ReflectionMethod('MyPresenter', 'hintsNullable'); Assert::same([null, null, null, null, null], ParameterConverter::toArguments($method, [])); @@ -242,7 +242,7 @@ test('', function () { }); -test('', function () { +test('default values with type hints', function () { $method = new ReflectionMethod('MyPresenter', 'hintsDefaults'); Assert::same([0, false, '', [], []], ParameterConverter::toArguments($method, [])); @@ -291,7 +291,7 @@ test('', function () { }); -test('', function () { +test('untyped parameters with defaults', function () { $method = new ReflectionMethod('MyPresenter', 'defaults'); Assert::same([0, false, '', []], ParameterConverter::toArguments($method, [])); @@ -340,7 +340,7 @@ test('', function () { }); -test('', function () { +test('object type parameter validation', function () { $method = new ReflectionMethod('MyPresenter', 'objects'); Assert::equal( @@ -374,7 +374,7 @@ test('', function () { }); -test('', function () { +test('union type parameter handling', function () { $method = new ReflectionMethod('MyPresenter', 'hintsUnion'); Assert::same([1, 'abc'], ParameterConverter::toArguments($method, ['intArray' => '1', 'strArray' => 'abc'])); diff --git a/tests/UI/Presenter.formatLayoutTemplateFiles.phpt b/tests/UI/Presenter.formatLayoutTemplateFiles.phpt index 9794a50f6..56c5d067e 100644 --- a/tests/UI/Presenter.formatLayoutTemplateFiles.phpt +++ b/tests/UI/Presenter.formatLayoutTemplateFiles.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/one/sub/BPresenter.php'; require __DIR__ . '/two/CPresenter.php'; -test('with subdir templates', function () { +test('layout template paths for root presenter', function () { $presenter = new APresenter; $presenter->setParent(null, 'One'); $presenter->setLayout('my'); @@ -28,7 +28,7 @@ test('with subdir templates', function () { }); -test('with parent-dir templates', function () { +test('submodule presenter layout resolution', function () { $presenter = new BPresenter; $presenter->setParent(null, 'One'); $presenter->setLayout('my'); @@ -41,7 +41,7 @@ test('with parent-dir templates', function () { }); -test('without subdir templates', function () { +test('default layout template hierarchy', function () { $presenter = new CPresenter; $presenter->setParent(null, 'Two'); @@ -52,7 +52,7 @@ test('without subdir templates', function () { }); -test('with module & subdir templates', function () { +test('multi-module layout template paths', function () { $presenter = new APresenter; $presenter->setParent(null, 'Module:SubModule:One'); @@ -66,7 +66,7 @@ test('with module & subdir templates', function () { }); -test('with module & parent-dir templates', function () { +test('nested module template inheritance', function () { $presenter = new BPresenter; $presenter->setParent(null, 'Module:SubModule:One'); @@ -80,7 +80,7 @@ test('with module & parent-dir templates', function () { }); -test('with module & without subdir templates', function () { +test('deep module structure layout resolution', function () { $presenter = new CPresenter; $presenter->setParent(null, 'Module:SubModule:Two'); @@ -93,7 +93,7 @@ test('with module & without subdir templates', function () { }); -test('direct file', function () { +test('explicit layout file assignment', function () { $presenter = new BPresenter; $presenter->setLayout(__DIR__ . '/file.latte'); diff --git a/tests/UI/Presenter.formatTemplateClass.phpt b/tests/UI/Presenter.formatTemplateClass.phpt index b9ed33bb7..6ff05893e 100644 --- a/tests/UI/Presenter.formatTemplateClass.phpt +++ b/tests/UI/Presenter.formatTemplateClass.phpt @@ -55,7 +55,7 @@ test('without template', function () { }); -test('with class', function () { +test('template class missing interface implementation', function () { Assert::error(function () { $presenter = new BPresenter; Assert::null($presenter->formatTemplateClass()); @@ -63,13 +63,13 @@ test('with class', function () { }); -test('with template', function () { +test('valid template class resolution', function () { $presenter = new CPresenter; Assert::same(CTemplate::class, $presenter->formatTemplateClass()); }); -test('with action template', function () { +test('action-specific template class selection', function () { $presenter = new CPresenter; $presenter->changeAction('foo'); Assert::same(CTemplate::class, $presenter->formatTemplateClass()); diff --git a/tests/UI/Presenter.formatTemplateFiles.phpt b/tests/UI/Presenter.formatTemplateFiles.phpt index 2b253fbe4..bc3ddc214 100644 --- a/tests/UI/Presenter.formatTemplateFiles.phpt +++ b/tests/UI/Presenter.formatTemplateFiles.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/one/sub/BPresenter.php'; require __DIR__ . '/two/CPresenter.php'; -test('with subdir templates', function () { +test('template file paths for root presenter', function () { $presenter = new APresenter; $presenter->setParent(null, 'One'); $presenter->setView('view'); @@ -27,7 +27,7 @@ test('with subdir templates', function () { }); -test('with parent-dir templates', function () { +test('submodule presenter template resolution', function () { $presenter = new BPresenter; $presenter->setParent(null, 'One'); $presenter->setView('view'); @@ -39,7 +39,7 @@ test('with parent-dir templates', function () { }); -test('without subdir templates', function () { +test('flat module structure template lookup', function () { $presenter = new CPresenter; $presenter->setParent(null, 'Two'); $presenter->setView('view'); @@ -50,7 +50,7 @@ test('without subdir templates', function () { }); -test('with module & subdir templates', function () { +test('module-prefixed presenter template paths', function () { $presenter = new APresenter; $presenter->setParent(null, 'Module:One'); $presenter->setView('view'); @@ -62,7 +62,7 @@ test('with module & subdir templates', function () { }); -test('with module & parent-dir templates', function () { +test('nested module template inheritance', function () { $presenter = new BPresenter; $presenter->setParent(null, 'Module:One'); $presenter->setView('view'); @@ -74,7 +74,7 @@ test('with module & parent-dir templates', function () { }); -test('with module & without subdir templates', function () { +test('module-specific template file hierarchy', function () { $presenter = new CPresenter; $presenter->setParent(null, 'Module:Two'); $presenter->setView('view'); diff --git a/tests/UI/Presenter.initGlobalParameters().phpt b/tests/UI/Presenter.initGlobalParameters().phpt index f5b793fe3..2a46238e8 100644 --- a/tests/UI/Presenter.initGlobalParameters().phpt +++ b/tests/UI/Presenter.initGlobalParameters().phpt @@ -42,7 +42,7 @@ function createPresenter() } -test('signal in GET', function () { +test('signal parsing from GET parameters', function () { $presenter = createPresenter(); $presenter->run(new Application\Request('Foo', 'GET', [ 'do' => 'foo', @@ -50,7 +50,7 @@ test('signal in GET', function () { Assert::same(['', 'foo'], $presenter->getSignal()); }); -test('signal for subcomponent in GET', function () { +test('compound signal name handling', function () { $presenter = createPresenter(); $presenter->run(new Application\Request('Foo', 'GET', [ 'do' => 'foo-bar', @@ -58,7 +58,7 @@ test('signal for subcomponent in GET', function () { Assert::same(['foo', 'bar'], $presenter->getSignal()); }); -test('signal in POST', function () { +test('POST signal without CSRF protection', function () { $presenter = createPresenter(); $presenter->run(new Application\Request('Foo', 'POST', [], [ 'do' => 'foo', @@ -66,7 +66,7 @@ test('signal in POST', function () { Assert::null($presenter->getSignal()); }); -test('_signal_ in POST', function () { +test('POST signal with CSRF protection', function () { $presenter = createPresenter(); $presenter->run(new Application\Request('Foo', 'POST', [], [ '_do' => 'foo', @@ -74,7 +74,7 @@ test('_signal_ in POST', function () { Assert::same(['', 'foo'], $presenter->getSignal()); }); -test('signal in POST not overwriting GET', function () { +test('conflicting signal parameters resolution', function () { $presenter = createPresenter(); $presenter->run(new Application\Request('Foo', 'POST', ['do' => null], [ 'do' => 'foo', @@ -82,7 +82,7 @@ test('signal in POST not overwriting GET', function () { Assert::null($presenter->getSignal()); }); -test('_signal_ in POST overwriting GET', function () { +test('POST signal priority over GET', function () { $presenter = createPresenter(); $presenter->run(new Application\Request('Foo', 'POST', ['do' => 'bar'], [ '_do' => 'foo', @@ -90,7 +90,7 @@ test('_signal_ in POST overwriting GET', function () { Assert::same(['', 'foo'], $presenter->getSignal()); }); -test('AJAX: signal in POST', function () { +test('AJAX signal handling in POST', function () { $presenter = createPresenter(); $presenter->ajax = true; $presenter->run(new Application\Request('Foo', 'POST', [], [ @@ -99,7 +99,7 @@ test('AJAX: signal in POST', function () { Assert::same(['', 'foo'], $presenter->getSignal()); }); -test('AJAX: signal in POST overwriting GET', function () { +test('AJAX signal override in POST data', function () { $presenter = createPresenter(); $presenter->ajax = true; $presenter->run(new Application\Request('Foo', 'POST', ['do' => 'bar'], [ @@ -108,7 +108,7 @@ test('AJAX: signal in POST overwriting GET', function () { Assert::same(['', 'foo'], $presenter->getSignal()); }); -test('AJAX: _signal_ in POST overwriting GET', function () { +test('AJAX with explicit CSRF-protected signal', function () { $presenter = createPresenter(); $presenter->ajax = true; $presenter->run(new Application\Request('Foo', 'POST', ['do' => 'bar'], [ diff --git a/tests/UI/Presenter.isModuleCurrent().phpt b/tests/UI/Presenter.isModuleCurrent().phpt index 6f9f23b89..a20149162 100644 --- a/tests/UI/Presenter.isModuleCurrent().phpt +++ b/tests/UI/Presenter.isModuleCurrent().phpt @@ -16,7 +16,7 @@ class TestPresenter extends Nette\Application\UI\Presenter } -test('', function () { +test('root module current status check', function () { $presenter = new TestPresenter; $presenter->setParent(null, 'Test'); @@ -26,7 +26,7 @@ test('', function () { }); -test('', function () { +test('nested module hierarchy validation', function () { $presenter = new TestPresenter; $presenter->setParent(null, 'First:Second:Third:Test'); diff --git a/tests/UI/Presenter.link().persistent.phpt b/tests/UI/Presenter.link().persistent.phpt index 8866f892c..e26932c76 100644 --- a/tests/UI/Presenter.link().persistent.phpt +++ b/tests/UI/Presenter.link().persistent.phpt @@ -7,6 +7,7 @@ declare(strict_types=1); use Nette\Application; +use Nette\Application\Attributes\Persistent; use Nette\Http; use Tester\Assert; @@ -16,13 +17,13 @@ require __DIR__ . '/../bootstrap.php'; trait PersistentParam1 { - /** @persistent */ + #[Persistent] public $t1; } trait PersistentParam2A { - /** @persistent */ + #[Persistent] public $t2; } @@ -33,7 +34,7 @@ trait PersistentParam2B trait PersistentParam3 { - /** @persistent */ + #[Persistent] public $t3; } @@ -41,7 +42,7 @@ class BasePresenter extends Application\UI\Presenter { use PersistentParam1; - /** @persistent */ + #[Persistent] public $p1; } @@ -50,7 +51,7 @@ class TestPresenter extends BasePresenter { use PersistentParam2B; - /** @persistent */ + #[Persistent] public $p2; @@ -81,10 +82,10 @@ class SecondPresenter extends BasePresenter { use PersistentParam3; - /** @persistent */ + #[Persistent] public $p1 = 20; - /** @persistent */ + #[Persistent] public $p3; } @@ -97,7 +98,7 @@ class ThirdPresenter extends BasePresenter class FourthPresenter extends BasePresenter { - #[Application\Attributes\Persistent] + #[Persistent] public $p1; } diff --git a/tests/UI/Presenter.link().phpt b/tests/UI/Presenter.link().phpt index b6b129d28..cfdf59d09 100644 --- a/tests/UI/Presenter.link().phpt +++ b/tests/UI/Presenter.link().phpt @@ -7,6 +7,7 @@ declare(strict_types=1); use Nette\Application; +use Nette\Application\Attributes\Persistent; use Nette\Http; use Tester\Assert; @@ -16,11 +17,11 @@ require __DIR__ . '/../bootstrap.php'; class TestControl extends Application\UI\Control { - /** @persistent array */ - public $order = []; + #[Persistent] + public array $order = []; - /** @persistent int */ - public $round = 0; + #[Persistent] + public int $round = 0; public function handleClick($x, $y) @@ -50,22 +51,22 @@ class TestControl extends Application\UI\Control class TestPresenter extends Application\UI\Presenter { - /** @persistent */ + #[Persistent] public $p; - /** @persistent */ + #[Persistent] public $pint = 10; - /** @persistent */ + #[Persistent] public $parr = []; - /** @persistent */ + #[Persistent] public $pbool = true; - /** @persistent */ + #[Persistent] public array $parrn; - /** @persistent */ + #[Persistent] public ?bool $pbooln = null; @@ -294,7 +295,7 @@ class TestPresenter extends Application\UI\Presenter class OtherPresenter extends TestPresenter { - /** @persistent */ + #[Persistent] public $p = 20; } diff --git a/tests/UI/Presenter.storeRequest().phpt b/tests/UI/Presenter.storeRequest().phpt index 2c09538d5..50ca0cd76 100644 --- a/tests/UI/Presenter.storeRequest().phpt +++ b/tests/UI/Presenter.storeRequest().phpt @@ -23,7 +23,7 @@ class TestPresenter extends Application\UI\Presenter } -test('ok', function () { +test('request storage with user context', function () { $testedKeyExistence = $storedKey = $storedValue = $testExpiration = $testExpirationVariables = null; $sessionSectionMock = Mockery::mock(Nette\Http\SessionSection::class); @@ -79,7 +79,7 @@ test('ok', function () { }); -test('no user', function () { +test('request storage without user context', function () { $testedKeyExistence = $storedKey = $storedValue = $testExpiration = $testExpirationVariables = null; $sessionSectionMock = Mockery::mock(Nette\Http\SessionSection::class); diff --git a/tests/UI/fixtures/ParamPresenter.php b/tests/UI/fixtures/ParamPresenter.php index 453a78c34..21e04cca4 100644 --- a/tests/UI/fixtures/ParamPresenter.php +++ b/tests/UI/fixtures/ParamPresenter.php @@ -4,7 +4,7 @@ class ParamPresenter extends Nette\Application\UI\Presenter { - /** @persistent */ + #[Nette\Application\Attributes\Persistent] public $bool = true; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 9b8053267..aeff549f3 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -13,6 +13,7 @@ // configure environment Tester\Environment::setup(); +Tester\Environment::setupFunctions(); date_default_timezone_set('Europe/Prague'); Mockery::setLoader(new Mockery\Loader\RequireLoader(getTempDir())); @@ -44,11 +45,9 @@ function getTempDir(): string } -function test(string $title, Closure $function): void -{ - $function(); +tearDown(function () { Mockery::close(); -} +}); class Notes