diff --git a/.gitattributes b/.gitattributes index 9cbc09b..f290ce9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,5 @@ # Exclude files that don't need to be present in packages (so they're not downloaded by Composer) /.gitattributes export-ignore /.gitignore export-ignore -/Robofile.php export-ignore /*.md export-ignore /*.yml export-ignore diff --git a/LICENSE b/LICENSE index cc43c4a..61d8209 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2011 Michael Bodnarchuk and contributors +Copyright (c) 2011-2020 Michael Bodnarchuk and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/composer.json b/composer.json index 50b63cb..a3dce1e 100644 --- a/composer.json +++ b/composer.json @@ -1,29 +1,33 @@ { - "name":"codeception/module-laravel", - "description":"Codeception module for Laravel framework", - "keywords":["codeception", "laravel"], - "homepage":"http://codeception.com/", - "type":"library", - "license":"MIT", - "authors":[ + "name": "codeception/module-laravel", + "description": "Codeception module for Laravel framework", + "keywords": ["codeception", "laravel"], + "homepage": "https://codeception.com/", + "type": "library", + "license": "MIT", + "authors": [ { "name":"Jan-Henk Gerritsen" }, { - "name":"Michael Bodnarchuk" + "name": "Michael Bodnarchuk" + }, + { + "name": "Gustavo Nieves", + "homepage": "https://medium.com/@ganieves" } ], "minimum-stability": "RC", "require": { - "php": ">=5.6.0 <9.0", - "codeception/lib-innerbrowser": "^1.0", + "php": "^7.3 | ^8.0", + "codeception/lib-innerbrowser": "^1.3", "codeception/codeception": "^4.0" }, "require-dev": { - "codeception/module-asserts": "^1.0", - "codeception/module-rest": "^1.0" + "codeception/module-asserts": "^1.3", + "codeception/module-rest": "^1.2" }, - "autoload":{ + "autoload": { "classmap": ["src/"] }, "config": { diff --git a/src/Codeception/Lib/Connector/Laravel5.php b/src/Codeception/Lib/Connector/Laravel.php similarity index 76% rename from src/Codeception/Lib/Connector/Laravel5.php rename to src/Codeception/Lib/Connector/Laravel.php index cac91f9..859d344 100644 --- a/src/Codeception/Lib/Connector/Laravel5.php +++ b/src/Codeception/Lib/Connector/Laravel.php @@ -1,23 +1,31 @@ firstRequest) { $this->initialize($request); @@ -132,56 +142,16 @@ protected function doRequest($request) $request = Request::createFromBase($request); $response = $this->kernel->handle($request); - $this->app->make('Illuminate\Contracts\Http\Kernel')->terminate($request, $response); + $this->app->make(Kernel::class)->terminate($request, $response); return $response; } /** - * Make sure files are \Illuminate\Http\UploadedFile instances with the private $test property set to true. - * Fixes issue https://github.com/Codeception/Codeception/pull/3417. - * - * @param array $files - * @return array - */ - protected function filterFiles(array $files) - { - $files = parent::filterFiles($files); - - if (! class_exists('Illuminate\Http\UploadedFile')) { - // The \Illuminate\Http\UploadedFile class was introduced in Laravel 5.2.15, - // so don't change the $files array if it does not exist. - return $files; - } - - return $this->convertToTestFiles($files); - } - - /** - * @param array $files - * @return array - */ - private function convertToTestFiles(array $files) - { - $filtered = []; - - foreach ($files as $key => $value) { - if (is_array($value)) { - $filtered[$key] = $this->convertToTestFiles($value); - } else { - $filtered[$key] = UploadedFile::createFromBase($value, true); - } - } - - return $filtered; - } - - /** - * Initialize the Laravel framework. - * - * @param SymfonyRequest $request + * @param SymfonyRequest|null $request + * @throws Exception */ - private function initialize($request = null) + private function initialize(SymfonyRequest $request = null): void { // Store a reference to the database object // so the database connection can be reused during tests @@ -201,14 +171,14 @@ private function initialize($request = null) // Reset the old database after all the service providers are registered. if ($this->oldDb) { - $this->app['events']->listen('bootstrapped: Illuminate\Foundation\Bootstrap\RegisterProviders', function () { + $this->app['events']->listen('bootstrapped: ' . RegisterProviders::class, function () { $this->app->singleton('db', function () { return $this->oldDb; }); }); } - $this->app->make('Illuminate\Contracts\Http\Kernel')->bootstrap(); + $this->app->make(Kernel::class)->bootstrap(); // Record all triggered events by adding a wildcard event listener // Since Laravel 5.4 wildcard event handlers receive the event name as the first argument, @@ -228,13 +198,13 @@ private function initialize($request = null) // Replace the Laravel exception handler with our decorated exception handler, // so exceptions can be intercepted for the disable_exception_handling functionality. if (version_compare(Application::VERSION, '7.0.0', '<')) { - $decorator = new Laravel5ExceptionHandlerDecorator($this->app['Illuminate\Contracts\Debug\ExceptionHandler']); + $decorator = new Laravel6ExceptionHandlerDecorator($this->app[ExceptionHandler::class]); } else { - $decorator = new Laravel7ExceptionHandlerDecorator($this->app['Illuminate\Contracts\Debug\ExceptionHandler']); + $decorator = new LaravelExceptionHandlerDecorator($this->app[ExceptionHandler::class]); } $decorator->exceptionHandlingDisabled($this->exceptionHandlingDisabled); - $this->app->instance('Illuminate\Contracts\Debug\ExceptionHandler', $decorator); + $this->app->instance(ExceptionHandler::class, $decorator); if ($this->module->config['disable_middleware'] || $this->middlewareDisabled) { $this->app->instance('middleware.disable', true); @@ -253,10 +223,10 @@ private function initialize($request = null) /** * Boot the Laravel application object. + * * @return Application - * @throws ModuleConfig */ - private function loadApplication() + private function loadApplication(): Application { $app = require $this->module->config['bootstrap_file']; $app->loadEnvironmentFrom($this->module->config['environment_file']); @@ -267,8 +237,10 @@ private function loadApplication() /** * Replace the Laravel event dispatcher with a mock. + * + * @throws Exception */ - private function mockEventDispatcher() + private function mockEventDispatcher(): void { // Even if events are disabled we still want to record the triggered events. // But by mocking the event dispatcher the wildcard listener registered in the initialize method is removed. @@ -283,7 +255,7 @@ private function mockEventDispatcher() // the 'fire' method was renamed to 'dispatch'. This code determines the correct method to mock. $method = method_exists($this->app['events'], 'dispatch') ? 'dispatch' : 'fire'; - $mock = Stub::makeEmpty('Illuminate\Contracts\Events\Dispatcher', [ + $mock = Stub::makeEmpty(Dispatcher::class, [ $method => $callback ]); @@ -293,10 +265,10 @@ private function mockEventDispatcher() /** * Normalize events to class names. * - * @param $event + * @param object|string $event * @return string */ - private function normalizeEvent($event) + private function normalizeEvent($event): string { if (is_object($event)) { $event = get_class($event); @@ -322,7 +294,7 @@ private function normalizeEvent($event) * @param $event * @return bool */ - public function eventTriggered($event) + public function eventTriggered($event): bool { $event = $this->normalizeEvent($event); @@ -338,25 +310,27 @@ public function eventTriggered($event) /** * Disable Laravel exception handling. */ - public function disableExceptionHandling() + public function disableExceptionHandling(): void { $this->exceptionHandlingDisabled = true; - $this->app['Illuminate\Contracts\Debug\ExceptionHandler']->exceptionHandlingDisabled(true); + $this->app[ExceptionHandler::class]->exceptionHandlingDisabled(true); } /** * Enable Laravel exception handling. */ - public function enableExceptionHandling() + public function enableExceptionHandling(): void { $this->exceptionHandlingDisabled = false; - $this->app['Illuminate\Contracts\Debug\ExceptionHandler']->exceptionHandlingDisabled(false); + $this->app[ExceptionHandler::class]->exceptionHandlingDisabled(false); } /** * Disable events. + * + * @throws Exception */ - public function disableEvents() + public function disableEvents(): void { $this->eventsDisabled = true; $this->mockEventDispatcher(); @@ -365,7 +339,7 @@ public function disableEvents() /** * Disable model events. */ - public function disableModelEvents() + public function disableModelEvents(): void { $this->modelEventsDisabled = true; Model::unsetEventDispatcher(); @@ -374,7 +348,7 @@ public function disableModelEvents() /* * Disable middleware. */ - public function disableMiddleware() + public function disableMiddleware(): void { $this->middlewareDisabled = true; $this->app->instance('middleware.disable', true); @@ -383,7 +357,7 @@ public function disableMiddleware() /** * Apply the registered application handlers. */ - private function applyApplicationHandlers() + private function applyApplicationHandlers(): void { foreach ($this->applicationHandlers as $handler) { call_user_func($handler, $this->app); @@ -393,7 +367,7 @@ private function applyApplicationHandlers() /** * Apply the registered Laravel service container bindings. */ - private function applyBindings() + private function applyBindings(): void { foreach ($this->bindings as $abstract => $binding) { list($concrete, $shared) = $binding; @@ -405,7 +379,7 @@ private function applyBindings() /** * Apply the registered Laravel service container contextual bindings. */ - private function applyContextualBindings() + private function applyContextualBindings(): void { foreach ($this->contextualBindings as $concrete => $bindings) { foreach ($bindings as $abstract => $implementation) { @@ -417,7 +391,7 @@ private function applyContextualBindings() /** * Apply the registered Laravel service container instance bindings. */ - private function applyInstances() + private function applyInstances(): void { foreach ($this->instances as $abstract => $instance) { $this->app->instance($abstract, $instance); @@ -436,7 +410,7 @@ private function applyInstances() * @param $concrete * @param bool $shared */ - public function haveBinding($abstract, $concrete, $shared = false) + public function haveBinding($abstract, $concrete, $shared = false): void { $this->bindings[$abstract] = [$concrete, $shared]; } @@ -449,7 +423,7 @@ public function haveBinding($abstract, $concrete, $shared = false) * @param $abstract * @param $implementation */ - public function haveContextualBinding($concrete, $abstract, $implementation) + public function haveContextualBinding($concrete, $abstract, $implementation): void { if (! isset($this->contextualBindings[$concrete])) { $this->contextualBindings[$concrete] = []; @@ -465,7 +439,7 @@ public function haveContextualBinding($concrete, $abstract, $implementation) * @param $abstract * @param $instance */ - public function haveInstance($abstract, $instance) + public function haveInstance($abstract, $instance): void { $this->instances[$abstract] = $instance; } @@ -476,7 +450,7 @@ public function haveInstance($abstract, $instance) * * @param $handler */ - public function haveApplicationHandler($handler) + public function haveApplicationHandler($handler): void { $this->applicationHandlers[] = $handler; } @@ -484,7 +458,7 @@ public function haveApplicationHandler($handler) /** * Clear the registered application handlers. */ - public function clearApplicationHandlers() + public function clearApplicationHandlers(): void { $this->applicationHandlers = []; } diff --git a/src/Codeception/Lib/Connector/Laravel7/ExceptionHandlerDecorator.php b/src/Codeception/Lib/Connector/Laravel/ExceptionHandlerDecorator.php similarity index 64% rename from src/Codeception/Lib/Connector/Laravel7/ExceptionHandlerDecorator.php rename to src/Codeception/Lib/Connector/Laravel/ExceptionHandlerDecorator.php index cd6e7eb..693c948 100644 --- a/src/Codeception/Lib/Connector/Laravel7/ExceptionHandlerDecorator.php +++ b/src/Codeception/Lib/Connector/Laravel/ExceptionHandlerDecorator.php @@ -1,14 +1,16 @@ laravelExceptionHandler = $laravelExceptionHandler; } - /** - * @param boolean $exceptionHandlingDisabled - */ - public function exceptionHandlingDisabled($exceptionHandlingDisabled) + public function exceptionHandlingDisabled(bool $exceptionHandlingDisabled): void { $this->exceptionHandlingDisabled = $exceptionHandlingDisabled; } @@ -42,10 +36,10 @@ public function exceptionHandlingDisabled($exceptionHandlingDisabled) /** * Report or log an exception. * - * @param \Throwable $e - * @return void + * @param Throwable $e + * @throws Throwable */ - public function report(Throwable $e) + public function report(Throwable $e): void { $this->laravelExceptionHandler->report($e); } @@ -53,28 +47,30 @@ public function report(Throwable $e) /** * Determine if the exception should be reported. * - * @param \Throwable $e + * @param Throwable $e * @return bool */ - public function shouldReport(Throwable $e) + public function shouldReport(Throwable $e): bool { return $this->exceptionHandlingDisabled; } /** - * @param $request + * Render an exception into an HTTP response. + * + * @param Request $request * @param Throwable $e - * @return \Symfony\Component\HttpFoundation\Response + * @return Response * @throws Throwable */ - public function render($request, Throwable $e) + public function render($request, Throwable $e): Response { $response = $this->laravelExceptionHandler->render($request, $e); if ($this->exceptionHandlingDisabled && $this->isSymfonyExceptionHandlerOutput($response->getContent())) { // If content was generated by the \Symfony\Component\Debug\ExceptionHandler class // the Laravel application could not handle the exception, - // so re-throw this exception if the Codeception user disabled Laravel's exception handling. + // so re-throw this exception if the Codeception user disabled Laravel exception handling. throw $e; } @@ -87,7 +83,7 @@ public function render($request, Throwable $e) * @param string $content * @return bool */ - private function isSymfonyExceptionHandlerOutput($content) + private function isSymfonyExceptionHandlerOutput(string $content): bool { return strpos($content, '
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: