How to unit test views with helper functions in laravel - php

I have these test cases visiting urls and checking for right behavior but I cant make it work because it errors on my helper functions within the view.
It works on the browser but not in tests.
/** #test */
public function setUp()
{
parent::setUp();
}
/** #test **/
public function openAdminDashboardUnauthorized()
{
$crawler = $this->client->request('GET', 'admin/organizations');
$this->assertTrue($this->client->getResponse()->isOk());
}
/** #test **/
public function tearDown()
{
parent::tearDown();
}
heres the error
EDIT
My helper classes are loaded in the global.php in the classLoader
by the way, this is on laravel 4.2
UPDATE
People say that you have to mock helper functions in order to unit test them. But in my case the helper functions are in the views and I tested dumping a static message from the setup function and indeed it was not loaded during the test run time.

So here's what I found working.
Loaded my helper class in the composer.json autoload sub tree
and run a quick "composer dump-autoload"
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
],
"files": [
"app/helper/Helper.php"
]
}
Now I know the difference between loading classes in global.php and autoloaded through composer. If anyone could explain more on the sequence in which laravel boots the application, I'll accept.

use Mockery, laravel4.2 has it by default. see https://laravel.com/docs/4.2/testing
You should have something like this at the top.
use Mockery as m;
class ClassToTest
{
public function test_some_method()
{
// Mock view helper
$viewHelperMock = m::mock(ViewHelper::class);
// Set expectations
$viewHelperMock->shouldReceive('show');
...
// This must be done only after setting the expectations
$this->app->instance(ViewHelper::class, $viewHelperMock);
...
// Your assertions goes here
}
}
We are binding our own viewHelperMock instance to Laravel's DI container. So whenever the request for ViewHelper class is made, it resolves to our mock instance. So, now you can set the expectations for all of the methods that are called in your view helper.
If you show us your view (html) code then it will be more easier to guide you. Don't get upset, it is tricky and confusing at the beginning. So, give it try multiple time also look at how Laravel's IOC container works.
Let us know if you have any problem following it.

Related

Override / Extend behat ProgressStepPrinter

I am trying to create an extension to behat progress output step formatter.
The goal is simply change the . to a * for each passed scenario step.
The behat documentation does not even mention the ability to create a custom formatter, however I found a GitHub repository that does this behat-format-progress-fail
But no clear / simple overview of how to achieve this is there, I have tried duplicating and modifying them. Is there a simple example or clear documentation for this?
By creating a very cut down version of ProgressStepPrinter.php and then including that in autoload-dev in composer.json uses it in prefernce to the one from Behat.
ProgressStepPrinter.php
namespace Behat\Behat\Output\Node\Printer\Progress;
use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter;
use Behat\Behat\Output\Node\Printer\StepPrinter;
use Behat\Behat\Tester\Result\StepResult;
use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario;
use Behat\Gherkin\Node\StepNode;
use Behat\Testwork\Output\Formatter;
final class ProgressStepPrinter implements StepPrinter {
private $resultConverter;
public function __construct(ResultToStringConverter $resultConverter) {
$this->resultConverter = $resultConverter;
}
public function printStep(Formatter $formatter, Scenario $scenario, StepNode $step, StepResult $result) {
//custom logic to print per step here
}
}
composer.json
"autoload-dev": {
"files": [
"features/bootstrap/ProgressStepPrinter.php",
]
},

Laravel - How to use load up custom classes when using factory method?

I'm setting up a factory to load my classes and their methods for use across my application. Probably continuing on with the strategy method. I feel as though I'm missing a step with my factory, as it throws an exception to finding the class through class_exists(), meanwhile it loads correctly if I omit the check. So, the question is - how do I load my custom factory and classes in laravel appropriately?
Interestingly enough, it doesn't throw an error inside my tests right now.
Only inside my application itself.
I'm newish to the implementation process so I suspect I'm not loading my custom classes appropriately or have a namespacing problem, or maybe should be loading this up in a service provider? Ok that's two questions really. Here's the code:
Factory
namespace app\Support\Humans;
class PeopleFactory
{
public static function build($person)
{
//adding this made it work for my test
$person = __NAMESPACE__ . "\\" . $person;
if (class_exists($person)) {
return new $person();
} else {
//person doesn't exist
throw new Exception;
}
}
}
Person Type
namespace app\Support\Humans;
class PersonType extends BasePerson
{
public function joinHumanity()
{
//etc
}
}
As I'm suspecting a namespacing issue, a segment of my composer.json pointing to the directory of my custom classes.
"autoload": {
"classmap": [
"app/Humans/"
],
"psr-4": {
"Humanity\\": "app/"
}
},
Implementation both in testing or elsewhere
use app\Support\Humans\PeopleFactory;
....
$new_human = PeopleFactory::build($this->user->personType);
$new_human->joinHumanity();

Composer autoload file not working

My Autoload specification are as follows
"autoload" : {
"psr-4" : {
"MyMVC\\" : "app/"
},
"classmap": [
"app/Controllers",
"app/Helpers"
],
"files": ["app/routes.php"]
},
The contents of routes.php file are:
<?php
use MyMVC\Core\Route;
$route = new Route;
$route->add('/', 'HomeController#index');
$route->add('about', 'AboutController#index');
$route->add('contact', 'ContactController#index');
now in my app/init.php i am trying to use the $route object but its giving me error
Notice: Undefined variable: route in /var/www/html/mymvc/app/init.php on line 29
Here is how i am trying to use the $route object.
/**
* Constructor
* Bootstrap our application based on the configurations provided
*/
public function __construct()
{
// require 'app/routes.php` This will work fine but it should be autoloaded
var_dump($route);
exit;
}
I have also ran command composer dump-autoload
Autoloading won't work here. PHP can only autoload classes. Your expectation that app/routes.php will be autoloaded is not possible, because that file does not contain a class declaration, and you are not able to trigger it's execution by using a previously unknown class.
It is true that Composer will execute that file once when you include vendor/autoload.php - however, this is really bad behavior of your software. Don't use the "files" autoloading to include configuration files. Mind the performance impact this may have when being used in libraries. You should avoid using it altogether, it is meant to be used for legacy code that cannot otherwise be made working.
On the other hand, your architecture is broken. You shouldn't write a class that "magically" knows about the configuration just by accessing a variable that is supposed to be initialized somewhere else. A good pattern would be to pass the configuration as a parameter to the constructor:
public function __construct ($routes)
{
$this->routes = $routes;
}
The part of the code that creates this class is supposed to grab the configuration from somewhere and pass it as a parameter. This concept is called inversion of control or dependency injection: Classes do not invoke the other classes they need to work with, they ask for them and get them as a parameter.

Laravel use custom function into project in Laravel 4

i have some custom function and i'm trying to use that into project, for example:
function makeText($str1, $str2){
return $str1 . ' '. $str2;
}
and i want to use this function in view such as :
<div style='float:left;'>MakeText : {{makeText("Hello","World");}}</div>
makeText is only sample function, witch folder must be put functions method such as UF.php containes all functions and how to define this file to laravel and use it?
You could follow Laravel’s conventions and create a helpers.php file in your app directory. Be sure to auto-load it with Composer though:
"autoload": {
"classmap": [
//
],
"files": [
"app/helpers.php"
]
},
You can then use the function any where in your application, including views.
Laravel gives you a few options. You can include your function definition inside of any of the files that get automatically included and achieve the result you want, such as /app/start/global.php, /bootstrap/start.php, /app/routes.php or many others. The problem with this approach is that, depending on the name of your function, there is a non-negligible likelihood that the name might conflict with one that is already taken (or may get taken later). Also, if you ever need to debug this function you will need to be able to find it later.
You can get around this issue by placing your function inside of a class, and then call that class a service. You can then inject that class into your controller via dependency injection and then pass that data to your view:
class MyService
{
public function makeText($param1, $param2)
{
return $param1 . ' ' . $param2;
}
}
class AController extends BaseController
{
public function __construct(MyService $serv)
{
$this->serv = $serv;
}
public function aRoute()
{
return View::make('some.view')
->with('serv', $this->serv);
}
}
And then in your view:
<div style='float:left;'>MakeText : {{ $serv->makeText("Hello","World"); }}</div>
This will help you prevent naming collisions because you can easily place MyService into any namespace that makes sense. It will also help you keep your code organized better.
Something this simple will probably not require a service provider, but as you add complexity to your project it would be an easy step to do once you need to.

Laravel - Loading classes

There are questions on here and around Google asking about the same thing, but being a noob, I'm still not getting this. I'm using Laravel 4.
Trying to have a file for random classes. Doesn't load.
The class is in:
app/classes/Helpers.php
Helpers.php:
class Helpers {
public function randomLowerCase($amount)
{
strtolower($str_random($amount))
}
};
I've placed my classes in composer.json.
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/classes",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
]
autoload_classmap.php:
'Helpers' => $baseDir . '/app/classes/Helpers.php',
And also ran
composer dump-autoload
I'm running the function in a UserController.php file in controllers, but I keep getting Call to undefined function randomLowerCase()
The problem is that you're not instantiating an instance of the Helpers class before you call one of its methods. You'll want to do one of the following:
First, keeping your class as it is, you could create an instance in the controller and call your method on it:
// Controller
$helpers = new Helpers;
$helpers->randomLowerCase($str);
Or, you could make the method static and call it as a static method:
// Helpers.php
class Helpers
{
public static function randomLowerCase($amount)
{
strtolower($str_random($amount))
}
};
// Controller
Helpers::randomLowerCase($str);
The error you're getting is because you're running the randomLowercase method as if it were just a function; methods are functions attached to a class/object.

Categories