Jak vytvořit ajaxový \Nette\Http\Request pro účely testování

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
kastanekdavid
Člen | 39
+
0
-

Zdar!

Píšu testy presenteru a potřeboval bych simulovat XMLHttpRequest, aby mi presenter při spuštění vrátil správný response. Jinými slovy, potřebuju v tomto případě donutit \Nette\Http\Request k tomu, aby na ->isAjax() vrátil true.

<?php
public function testRenderDashboardAjaxComponent()
    {
        $request = new Nette\Application\Request('Front:Index', 'GET', ['action' => 'dashboard', 'id' => 2880, 'do' => 'status-1230-detail']);
        $response = $this->presenter->run($request); // tady by měl být JSON string se snippetama
    }
?>

Je nějaký fundovaný způsob, jak toho docílit? Napadlo mě vytvořit si vlastní Request a Response, které bych nalil do presenteru pomocí $presenter->injectPrimary($myRequest, $myResponse), ale to se mi zdá moc divoký.

Nebo bych to neměl potřebovat? Jsem připraven na jakoukoliv odpověď :D

Martk
Člen | 661
+
+1
-

Napadlo mě něco jako:

class Presenter extends BasePresenter {

	public $forceAjax = FALSE;

	public function isAjax() {
		if ($this->forceAjax) {
			return TRUE;
		}

		return parent::isAjax();
	}
}
public function testRenderDashboardAjaxComponent()
{
        $request = new Nette\Application\Request('Front:Index', 'GET', ['action' => 'dashboard', 'id' => 2880, 'do' => 'status-1230-detail']);
		$this->presenter->forceAjax = TRUE;
        $response = $this->presenter->run($request); // tady by měl být JSON string se snippetama
}

Editoval Antik (12. 2. 2016 10:15)

kastanekdavid
Člen | 39
+
0
-

Bezva řešení, díky :)

Snad to nikdo nebude používat mimo testy :D

pata.kusik111
Člen | 78
+
+2
-

Definice $presenter->isAjax():

public function isAjax()
    {
         if ($this->ajaxMode === NULL) {
             $this->ajaxMode = $this->httpRequest->isAjax();
         }
         return $this->ajaxMode;
     }

Z toho je patrné, že rozlišení jde udělat takto:
Podědit \Nette\Application\Request a implementovat metodu isAjax aby vracela true.

iguana007
Člen | 970
+
0
-

Nebo jen přidat hlavičku X-Requested-With s hodnotou: XMLHttpRequest

pata.kusik111
Člen | 78
+
0
-

iguana007 napsal(a):

Nebo jen přidat hlavičku X-Requested-With s hodnotou: XMLHttpRequest

Tím ale spoléháš na to, že ajaxový požadavek lze vždy touto hlavičkou rozeznat. Děláš nějaký předpoklad, který sice v tuto chvíli je pravdivý (nebo by alespoň měl), ale v budoucnu být pravdivý nemusí. A navíc ten předpoklad ani dělat nemusíš.

kastanekdavid
Člen | 39
+
0
-

pata.kusik111 napsal(a):

Definice $presenter->isAjax():

public function isAjax()
    {
         if ($this->ajaxMode === NULL) {
             $this->ajaxMode = $this->httpRequest->isAjax();
         }
         return $this->ajaxMode;
     }

Z toho je patrné, že rozlišení jde udělat takto:
Podědit \Nette\Application\Request a implementovat metodu isAjax aby vracela true.

Na teoretické rovině souhlasím, můžeš ale pls „zpatrnět“ i postup, jakým tento poděděný Request jednoduše vpravíš do $presenter->httpRequest? :)

kastanekdavid
Člen | 39
+
0
-

iguana007 napsal(a):

Nebo jen přidat hlavičku X-Requested-With s hodnotou: XMLHttpRequest

Pokud se nepletu, hlavičky se drží přímo $presenter->httpRequest v private property headers, která nemá setter. Jakým způsobem se tedy pls jednoduše hlavička přidá? :)

pata.kusik111
Člen | 78
+
0
-

@kastanekdavid Na tohle je Nette trošku náročné, takhle nějak to řeším já v Codeception testech:

public function testActionDefault()
{
    $this->specify("Access granted to secured presenter action", function() {
        $presenter = new \Kusebauch\NetteSecurityAnnotation\Tests\SecurePresenterDummy();
        $request = new \Nette\Http\Request(new \Nette\Http\UrlScript);
        $response = new \Nette\Http\Response();
        $session = new \Nette\Http\Session($request, $response);
        $user = new \Nette\Security\User(new \Nette\Http\UserStorage($session));
        $presenter->injectPrimary(NULL, NULL, NULL, $request, $response, $session, $user);
        $presenter->run(new \Nette\Application\Request("SecurePresenterDummy", "default", []));
    });

}

Kde si tedy poděděním nahradíš ten HTTP request.

kastanekdavid
Člen | 39
+
0
-

@pata.kusik111 Jj, myslel jsem, že to uděláš přes $presenter->injectPrimary, ostatně jsem o tohle způsobu i přemýšlel (jak zmiňuju v původním dotazu), akorát jsem se tomu raději vyhnul právě kvůli šílené režii, která okolo toho vzniká.

Antikova metoda sice není tak „čistá“, jako tato (protože mění testovaný presenter jenom kvůli testu), ale přijde mi praktičnější.

I tak díky za námět :)