Skip to content

Commit 3c3b57c

Browse files
committed
Tests + Travis + Phpstan
1 parent 0763191 commit 3c3b57c

10 files changed

+233
-15
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
/vendor
22
/composer.lock
3-
/composer.phar

.travis.yml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
language: php
2+
php:
3+
- 7.0
4+
- 7.1
5+
6+
script:
7+
- vendor/bin/phpstan analyse -l 5 -c phpstan.neon src
8+
- vendor/bin/tester tests
9+
10+
before_script:
11+
- travis_retry composer install --no-interaction --prefer-dist
12+
13+
sudo: false
14+
15+
cache:
16+
directories:
17+
- $HOME/.composer/cache

Makefile

-10
This file was deleted.

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# AsyncControl
22

3+
[![Build Status](https://travis-ci.org/peckadesign/AsyncControl.svg?branch=master)](https://travis-ci.org/peckadesign/AsyncControl)
4+
35
Trait for asynchronous control rendering.
46

57
## Usage

composer.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
"nette/application": "^2.2"
2626
},
2727
"require-dev": {
28-
"phpstan/phpstan": "~0.6.0"
28+
"phpstan/phpstan": "~0.6.0",
29+
"nette/tester": "~1.7.0",
30+
"mockery/mockery": "~0.9.0"
2931
},
3032
"autoload": {
3133
"psr-4": {

phpstan.neon

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
parameters:
2+
ignoreErrors:
3+
- '#Call to an undefined method [a-zA-Z0-9\\_]+::renderAsync\(\)#'
4+
- '#Call to an undefined method [a-zA-Z0-9\\_]+::render\(\)#'
5+
fileExtensions:
6+
- phpt
7+
8+
autoload_directories:
9+
# - %rootDir%/../../../test
10+

src/UI/AsyncControl.php

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Pd\AsyncControl\UI;
4+
5+
use Nette\Application\UI\Control;
6+
7+
8+
class AsyncControl extends Control
9+
{
10+
11+
use AsyncControlTrait;
12+
}

src/UI/AsyncControlTrait.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Nette\Application\UI\Control;
66
use Nette\Application\UI\Presenter;
7-
use Nette\Application\UI\PresenterComponent;
7+
use Nette\Bridges\ApplicationLatte\Template;
88

99

1010
/**
@@ -21,7 +21,7 @@ trait AsyncControlTrait
2121

2222
public function handleAsyncLoad()
2323
{
24-
if ( ! $this instanceof PresenterComponent || ! ($presenter = $this->getPresenter(FALSE)) || ! $presenter->isAjax()) {
24+
if ( ! $this instanceof Control || ! ($presenter = $this->getPresenter(FALSE)) || ! $presenter->isAjax()) {
2525
return;
2626
}
2727
ob_start(function () {
@@ -49,7 +49,9 @@ public function renderAsync(string $linkMessage = NULL, array $linkAttributes =
4949
&& strpos((string) $this->getPresenter()->getParameter(Presenter::SIGNAL_KEY), sprintf('%s-', $this->getUniqueId())) !== 0
5050
) {
5151
$template = $this->createTemplate();
52-
$template->link = new AsyncControlLink($linkMessage, $linkAttributes);
52+
if ($template instanceof Template) {
53+
$template->add('link', new AsyncControlLink($linkMessage, $linkAttributes));
54+
}
5355
$template->setFile(__DIR__ . '/templates/asyncLoadLink.latte');
5456
$template->render();
5557
} elseif (is_callable($this->asyncRenderer)) {

tests/UI/AsyncControlLinkTest.phpt

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Pd\AsyncControl\UI;
4+
5+
use Tester\Assert;
6+
use Tester\TestCase;
7+
8+
9+
require_once __DIR__ . '/../../vendor/autoload.php';
10+
11+
12+
final class AsyncControlLinkTest extends TestCase
13+
{
14+
15+
public function testLink()
16+
{
17+
$link = new AsyncControlLink;
18+
Assert::equal('Load content', $link->getMessage());
19+
Assert::equal([], $link->getAttributes());
20+
21+
$link = new AsyncControlLink('Custom message', ['foo' => 'bar']);
22+
Assert::equal('Custom message', $link->getMessage());
23+
Assert::equal(['foo' => 'bar'], $link->getAttributes());
24+
25+
AsyncControlLink::setDefault('Default message', ['bar' => 'baz']);
26+
27+
$link = new AsyncControlLink;
28+
Assert::equal('Default message', $link->getMessage());
29+
Assert::equal(['bar' => 'baz'], $link->getAttributes());
30+
31+
$link = new AsyncControlLink('Custom message', ['foo' => 'bar']);
32+
Assert::equal('Custom message', $link->getMessage());
33+
Assert::equal(['foo' => 'bar'], $link->getAttributes());
34+
}
35+
}
36+
37+
38+
(new AsyncControlLinkTest)->run();

tests/UI/AsyncControlTest.phpt

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Pd\AsyncControl\UI;
4+
5+
use Mockery;
6+
use Nette\Application\UI\ITemplate;
7+
use Nette\Application\UI\ITemplateFactory;
8+
use Nette\Application\UI\Presenter;
9+
use Tester\Assert;
10+
use Tester\TestCase;
11+
12+
13+
require_once __DIR__ . '/../../vendor/autoload.php';
14+
15+
16+
final class AsyncControlTest extends TestCase
17+
{
18+
19+
const VALID_SIGNAL = 'control-form-submit';
20+
const FRAGMENT_PARAMETER = '_escaped_fragment_';
21+
22+
23+
public function testHandleAjax()
24+
{
25+
$presenter = Mockery::mock(Presenter::class);
26+
$presenter->shouldReceive('isAjax')->once()->andReturn(TRUE);
27+
$presenter->shouldReceive('getPayload')->andReturn($payload = new \stdClass);
28+
$presenter->shouldReceive('sendPayload')->once();
29+
/**
30+
* @var AsyncControl|Mockery\Mock $control
31+
*/
32+
$control = Mockery::mock(AsyncControl::class)->makePartial();
33+
$control->shouldReceive('getPresenter')->andReturn($presenter);
34+
$renderedContent = 'rendered content';
35+
$control->shouldReceive('renderAsync')->once()->andReturnUsing(function () use ($renderedContent) {
36+
echo $renderedContent;
37+
})
38+
;
39+
$control->shouldReceive('getSnippetId')->with('async')->andReturn($snippetId = 'snippet-control-async');
40+
$control->handleAsyncLoad();
41+
42+
Assert::equal(['snippets' => [$snippetId => $renderedContent]], (array) $payload);
43+
}
44+
45+
46+
public function testHandleNoAjax()
47+
{
48+
$presenter = Mockery::mock(Presenter::class);
49+
$presenter->shouldReceive('isAjax')->once()->andReturn(FALSE);
50+
$presenter->shouldNotReceive('getPayload');
51+
$presenter->shouldNotReceive('sendPayload');
52+
/**
53+
* @var AsyncControl|Mockery\Mock $control
54+
*/
55+
$control = Mockery::mock(AsyncControl::class)->makePartial();
56+
$control->shouldReceive('getPresenter')->andReturn($presenter);
57+
$control->shouldNotReceive('renderAsync');
58+
$control->shouldNotReceive('getSnippetId');
59+
$control->handleAsyncLoad();
60+
}
61+
62+
63+
public function testRenderAsyncLoadLink()
64+
{
65+
/**
66+
* @var AsyncControl|Mockery\Mock $control
67+
*/
68+
$control = Mockery::mock(AsyncControl::class)->makePartial();
69+
70+
$template = Mockery::mock(ITemplate::class);
71+
$template->shouldReceive('setFile')->once()->withAnyArgs();
72+
$template->shouldReceive('render')->once();
73+
74+
$templateFactory = Mockery::mock(ITemplateFactory::class);
75+
$templateFactory->shouldReceive('createTemplate')->once()->with($control)->andReturn($template);
76+
77+
$presenter = Mockery::mock(Presenter::class);
78+
$presenter->shouldReceive('getParameter')->once()->with(self::FRAGMENT_PARAMETER)->andReturn(NULL);
79+
$presenter->shouldReceive('getParameter')->once()->with(Presenter::SIGNAL_KEY)->andReturn(NULL);
80+
$presenter->shouldReceive('getTemplateFactory')->once()->andReturn($templateFactory);
81+
82+
$control->shouldReceive('getPresenter')->andReturn($presenter);
83+
$control->shouldReceive('getUniqueId')->once()->andReturn('control');
84+
$control->renderAsync();
85+
}
86+
87+
88+
public function testRenderWithSignal()
89+
{
90+
$presenter = Mockery::mock(Presenter::class);
91+
$presenter->shouldReceive('getParameter')->once()->with(self::FRAGMENT_PARAMETER)->andReturn(NULL);
92+
$presenter->shouldReceive('getParameter')->once()->with(Presenter::SIGNAL_KEY)->andReturn(self::VALID_SIGNAL);
93+
/**
94+
* @var AsyncControl|Mockery\Mock $control
95+
*/
96+
$control = Mockery::mock(AsyncControl::class)->makePartial();
97+
$control->shouldReceive('getPresenter')->andReturn($presenter);
98+
$control->shouldReceive('getUniqueId')->once()->andReturn('control');
99+
$control->shouldReceive('render')->once();
100+
$control->renderAsync();
101+
}
102+
103+
104+
public function testRenderWithFragment()
105+
{
106+
$presenter = Mockery::mock(Presenter::class);
107+
$presenter->shouldReceive('getParameter')->once()->with(self::FRAGMENT_PARAMETER)->andReturn('');
108+
/**
109+
* @var AsyncControl|Mockery\Mock $control
110+
*/
111+
$control = Mockery::mock(AsyncControl::class)->makePartial();
112+
$control->shouldReceive('getPresenter')->andReturn($presenter);
113+
$control->shouldReceive('render')->once();
114+
$control->renderAsync();
115+
}
116+
117+
118+
public function testRenderAsyncRenderer()
119+
{
120+
$presenter = Mockery::mock(Presenter::class);
121+
$presenter->shouldReceive('getParameter')->once()->with(self::FRAGMENT_PARAMETER)->andReturn(NULL);
122+
$presenter->shouldReceive('getParameter')->once()->with(Presenter::SIGNAL_KEY)->andReturn(self::VALID_SIGNAL);
123+
/**
124+
* @var AsyncControl|Mockery\Mock $control
125+
*/
126+
$control = Mockery::mock(AsyncControl::class)->makePartial();
127+
$control->shouldReceive('getPresenter')->andReturn($presenter);
128+
$control->shouldReceive('getUniqueId')->once()->andReturn('control');
129+
$asyncRendered = FALSE;
130+
$control->setAsyncRenderer(function () use (&$asyncRendered) {
131+
$asyncRendered = TRUE;
132+
});
133+
$control->renderAsync();
134+
Assert::equal(TRUE, $asyncRendered);
135+
}
136+
137+
138+
protected function tearDown()
139+
{
140+
parent::tearDown();
141+
Mockery::close();
142+
}
143+
}
144+
145+
146+
(new AsyncControlTest)->run();

0 commit comments

Comments
 (0)