How can I change the app url for unit testing? - php

I have a function which requires the url to be able to work. I am trying to unit test it as its behaviour changes depending on the url query parameters.
MyServiceTest.php
function testMyTestFunction() {
$service = new MyService();
// Some how change the url for the app. This doesn't work
config(['app.url' => 'http://test.test?myNewParam=5']);
$service->test();
}
MyService.php
function test() {
// Does not contain `myNewParam`
$url = url()->full();
// do some logic
}
I've also tried mocking the request as that's what the url() helper function references but I've had no luck in doing this successfully.

When you use url()->full(); this returns the current request full URL, not the one set in the config. So when using this:
config(['app.url' => 'http://test.test?myNewParam=5']);
then you can get the value like this: config('app.url').
If you want to get the param through the url helper then you will need to make a request to the controller route that uses your service, for example:
$this->get('/test?myNewParam=5')->assert...
but then that would not be a unit test. You should better move out the usage of your url helper function from within your service method and provide that as a dependency to the service. That way you can use one url for your production code and another for your test code.

Related

Laravel testing redirect from function

If I have a function that checks to see if a string is numeric and redirects back if it is not but does nothing if it is ie
function check_numeric(string $param) {
if(!is_numeric($param)) {
return Redirect::back()->with('Failed', 'Number!');
}
}
How would I test this in PHPUnit? I have tried to use assertRedirect but I am not sure of how to implement it (if it is even possible)
To be clear. The check_numeric() function is a standalone function that is imported into controllers to be used by the different controller classes. The fucntion itself does not have a class nor a route.
What I would like to do is test the function directly without its use in a controller or route.
I can test the pass cases by doing:
$this->assertNull(check_numeric('1')); // does what I want!!
However I would also like to directly check the fail cases with something like
$previousUrl = '/';
$this->from($previousUrl)->(check_numeric('five'))->assertRedirect($previousUrl);
I think there is not automatic way to check if it's redirecting back, but you can build it.
To approaches comes to mind.
All samples assumed under phpunit, test extending Tests\TestCase;
1 - Check the URL before you make the request
$currentUrl = "/";
$response = $this->post('check-number', "five" );
$response->assertRedirect($currentUrl);
2 - Validate the message you're sending back when the validation fails.
$response = $this->post('/check-number', "five" );
$this->followRedirects($response)->assertSee('Failed');
YourController.php
function check_numeric(string $param) {
if(!is_numeric($param)) {
return Redirect::back()->with('Failed', 'Number!');
}
}
web.php
Route::post('/check-number', 'App\Http\Controllers\YourControllerController#check_numeric');
In the other hand, responding to your previous question, if you want to test the function directly, you have to go with what you're expecting, in this case you're not returning anything if everything is OK, so the way to go on that case would be:
$this->assertNull(app('App\Http\Controllers\YourControllerController')->check_numeric("five"));
This would fail, if you pass a number it would pass.
Doesthat help?

ZF2 - Get current URL in Controller

This seems like it should be a simple task. I need the current URL from a function within the Controller. This function can be called from multiple actions, and the end goal is to set a form's action attribute. (Side note: It appears IE does not send an ajax request if the URL starts with '#').
I feel like my google-fu is off today because I could not find a good way to do this Zend Framework 2. I have this line currently, but it feels very bulky:
$this->url()->fromRoute(
$this->getServiceLocator()
->get('Application')
->getMvcEvent()
->getRouteMatch()
->getMatchedRouteName()
);
Couldn't you just get the URI from the request object:
$this->getRequest()->getUriString()
Provided your controller extends Zend\Mvc\Controller\AbstractActionController.
Note: This would output the entire URL, like so:
http://example.com/en/path/subpath/finalpath?test=example
If your request route is like this:
http://example.com/en/path/subpath/finalpath?test=example
And You want only this:
/en/path/subpath/finalpath?test=example
You can simply do : $this->getRequest()->getRequestUri()
To specify my Request object is an instance of
\ZF\ContentNegotiation\Request

Access URL param from Input::get() with laravel

I have a route like this:
Route::get('demo/{system?}', 'MonitorController#demo');
I am using it like so because I would like my url to look like so:
mysite.com/demo/spain-system
Where spain-system will be the variable I need to get.
Right now, I'm getting it like this:
public function demo($systemName = null){
}
But I would like to be able to access to it as if it were a URL parameter with Input::get('system') so I can access to it from other methods or even from other controllers such as BaseController.php.
Is there any way to achieve this?
I've played around with Route::input('system') but then it doesn't work when I pass it as a get parameter (in other Ajax calls and so on)
Update
In PHP we can get URL params by using the $_GET function and laravel provides the function Input::get() to do so as well.
If there were no routes in laravel, I would make use of .htaccess rewrite rules to change this:
mysite.com/demo/?system=spain-system
To this:
mysite.com/demo/spain-system
And I could still retrieve the variable system as a GET parameter by using $_GET["system"].
That's kind of what I would expect of laravel, but it seems it is just treating it as the parameter of the demo method and not really as a URL variable.
Is there any way to keep treating it as a URL variable and at the same time use it in a pretty URL without the ?system= ?
So you actually just want to get an url like this? mysite.com/demo/spain-system instead of mysite.com/demo/?system=spain-system? Laravel provides that by default?
Look, When you want to get the router variable {system?} to be accesible you'll need to do this:
In your router:
Route::get('demo/{system}', 'MonitorController#demo');
Then you have an controller where this noods to stand in:
public function demo($system)
{
//your further system
//You are be able to access the $system variable
echo $system; //just to show the idea of it.
}
When you now go to to localhost/demo/a-system-name/, You'll see a blank page with a-system-name.
Hope this helps, because your question is abit unclear.

Opencart: call method from another controller

I need to call in checkout/confirm.tpl file a custom function that i've made in controller/product.php
what's the best way to make this?
i've tried this, but doesn't work:
$productController = $this->load->model('product/product');
$productController->customFunction();
yes i find the right answer finally!!! sorry for last bad answer
class ControllerCommonHome extends Controller {
public function index() {
return $this->load->controller('product/ready');
}
}
MVC
in an MVC architecture, a template serves solely for rendering/displaying data; it shouldn't (*) call controller/model functions nor it shouldn't execute SQL queries as I have seen in many third-party modules (and even in answers here at SO).
$productController = $this->load->model('product/product');
nifty eye has to discover that you are trying to load a model into a variable named by controller and you are also trying to use it in such way. Well, for your purpose there would have to be a method controller() in class Loader - which is not (luckily)
How it should be done?
sure there is a way how to access or call controller functions from within templates. In MVC a callable function that is invoked by routing is called action. Using this sentence I can now say that you can invoke an action (controller function) by accessing certain URL.
So let's say your controller is CatalogProductController and the method you want to invoke is custom() - in this case accessing this URL
http://yourstore.com/index.php?route=catalog/product/custom
you will make sure that the custom() method of CatalogProductController is invoked/accessed.
You can access such URL in many ways - as a cURL request, as a link's href or via AJAX request, to name some. In a PHP scope even file_get_contents() or similar approach will work.
(*) By shouldn't I mean that it is (unfortunately) possible in OpenCart but such abuse is against MVC architecture.
$this->load->controller('sale/box',$yourData);
To call ShipmentDate() function of box Controller
$this->load->controller('sale/box/ShipmentDate',$yourData);
May be something like this could help you (or anyone who's interested)
// Load seo pro
require_once(DIR_CATALOG."/controller/common/seo_pro.php"); // load file
$seoPro = new ControllerCommonSeoPro($this->registry); // pass registry to constructor
$url = HTTP_CATALOG . $seoPro->rewrite(
$this->url('information/information&information_id=' . $result['information_id'])
);
return $this->load->controller('error/not_found');
in laravel its so simple just write Controller::call('ApplesController#getSomething');
but there i cant made better than this
$config = new Config();
// Response
$response = new Response();
$response->addHeader('Content-Type: text/html; charset=utf-8');
$response->setCompression($config->get('config_compression'));
$this->registry->set('response', $response);
$action = new Action('product/ready');
$controller = new Front($this->registry);
$controller->addPreAction(new Action('common/maintenance'));
$controller->addPreAction(new Action('common/seo_url'));
$controller->dispatch($action, new Action('error/not_found'));
$response->output();
in this case its well call product/ready

codeigniter routing

I am currently working on CMS for a client, and I am going to be using Codeigniter to build on top of, it is only a quick project so I am not looking for a robust solution.
To create pages, I am getting to save the page details and the pull the correct page, based on the slug matching the slug in the mysql table.
My question is however, for this to work, I have to pass this slug from the URL the controller then to the model, this means that I also have too have the controller in the URL which I do not want is it possible to remove the controller from the URL with routes?
so
/page/our-story
becomes
/our-story
Is this possible
I would recommend to do it this way.
Let's say that you have : controller "page" / Method "show"
$route['page/show/:any'] = "$1";
or method is index which I don't recommend, and if you have something like news, add the following.
$route['news/show/:any'] = "news/$1";
That's it.
Yes, certainly. I just recently built a Codeigniter driven CMS myself. The whole purpose of routes is to change how your urls look and function. It helps you break away from the controller/function/argument/argument paradigm and lets you choose how you want your url's to look like.
Create a pages controller in your controllers directory
Place a _remap function inside of it to catch all requests to the controller
If you are using the latest version of CI 2.0 from Bitbucket, then in your routes.php file you can put this at the bottom of the file: $routes['404_override'] = "pages"; and then all calls to controllers that don't exist will be sent to your controller and you then can check for the presence of URL chunks. You should also make pages your default controller value as well.
See my answer for a similar question here from a few months back for example code and working code that I use in my Codeigniter CMS.
Here's the code I used in a recent project to achieve this. I borrowed it from somewhere; can't remember where.
function _remap($method)
{
$param_offset = 2;
// Default to index
if ( ! method_exists($this, $method))
{
// We need one more param
$param_offset = 1;
$method = 'index';
}
// Since all we get is $method, load up everything else in the URI
$params = array_slice($this->uri->rsegment_array(), $param_offset);
// Call the determined method with all params
call_user_func_array(array($this, $method), $params);
}
Then, my index function is where you would put your page function.

Categories