Skip to content

Commit 3b36d69

Browse files
committed
Refactored and added tests
1 parent cf46cd9 commit 3b36d69

File tree

14 files changed

+210
-54
lines changed

14 files changed

+210
-54
lines changed

composer.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,20 @@
2020
},
2121
"require-dev": {
2222
"arachne/coding-style": "~0.2",
23+
"enumag/application": "~0.2",
24+
"nette/nette": "~2.2",
2325
"squizlabs/php_codesniffer": "~2.0"
2426
},
2527
"autoload": {
2628
"psr-4": {
27-
"Arachne\\Codeception\\": "src/",
28-
"Codeception\\Module\\": "src/Module/"
29+
"Arachne\\Codeception\\": "src",
30+
"Codeception\\Module\\": "src/Module"
31+
}
32+
},
33+
"autoload-dev": {
34+
"psr-4": {
35+
"Tests\\Unit\\": "tests/unit/src",
36+
"Tests\\Integration\\": "tests/integration/src"
2937
}
3038
}
3139
}

src/ConfigFilesInterface.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Arachne\Codeception;
4+
5+
/**
6+
* @author Jáchym Toušek
7+
*/
8+
interface ConfigFilesInterface
9+
{
10+
11+
/**
12+
* @return string[]
13+
*/
14+
public function getConfigFiles();
15+
16+
}

src/Connector/Nette.php

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,6 @@ public function doRequest($request)
4040
// Container initialization can't be called earlier because Nette\Http\IRequest service might be initialized too soon and amOnPage method would not work anymore.
4141
$this->container->initialize();
4242

43-
// RequestFactory leaves port NULL in CLI mode but the urls created by amOnPage have port 80 which breaks canonicalization.
44-
$url = $this->container->getByType('Nette\Http\IRequest')->getUrl();
45-
if (!$url->getPort()) {
46-
$url->setPort(80);
47-
}
48-
49-
// The HTTP code from previous test sometimes survives in http_response_code() so it's necessary to reset it manually.
50-
$httpResponse = $this->container->getByType('Nette\Http\IResponse');
51-
$httpResponse->setCode(IResponse::S200_OK);
52-
5343
try {
5444
ob_start();
5545
$this->container->getByType('Nette\Application\Application')->run();
@@ -60,6 +50,7 @@ public function doRequest($request)
6050
throw $e;
6151
}
6252

53+
$httpResponse = $this->container->getByType('Nette\Http\IResponse');
6354
$code = $httpResponse->getCode();
6455
$headers = $httpResponse->getHeaders();
6556

src/DI/CodeceptionExtension.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,32 @@
22

33
namespace Arachne\Codeception\DI;
44

5+
use Nette\Bridges\Framework\NetteExtension;
56
use Nette\DI\CompilerExtension;
7+
use Nette\Http\IResponse;
68

79
/**
810
* @author Jáchym Toušek
911
*/
1012
class CodeceptionExtension extends CompilerExtension
1113
{
1214

13-
public function loadConfiguration()
15+
public function beforeCompile()
1416
{
1517
$builder = $this->getContainerBuilder();
1618

17-
$builder->getDefinition('httpResponse')
18-
->setClass('Arachne\Codeception\Http\Response');
19+
if ($builder->hasDefinition('httpResponse')) {
20+
$builder->getDefinition('httpResponse')
21+
->setClass('Arachne\Codeception\Http\Response')
22+
// The HTTP code from previous test sometimes survives in http_response_code() so it's necessary to reset it manually.
23+
->addSetup('setCode', [ IResponse::S200_OK]);
24+
}
25+
26+
if ($builder->hasDefinition('httpRequest')) {
27+
$builder->getDefinition('httpRequest')
28+
// RequestFactory leaves port NULL in CLI mode but the urls created by amOnPage have port 80 which breaks canonicalization.
29+
->addSetup('$url = ?->getUrl(); if (!$url->getPort()) { $url->setPort(80); }', [ '@self' ]);
30+
}
1931
}
2032

2133
}

src/Module/Nette.php

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
namespace Codeception\Module;
44

5+
use Arachne\Codeception\ConfigFilesInterface;
56
use Arachne\Codeception\Connector\Nette as NetteConnector;
7+
use Arachne\Codeception\DI\CodeceptionExtension;
68
use Codeception\TestCase;
79
use Codeception\Lib\Framework;
8-
use Nette\Configurator;
10+
use Arachne\Bootstrap\Configurator;
11+
use Nette\DI\Compiler;
912
use Nette\DI\Container;
1013
use Nette\DI\MissingServiceException;
1114
use Nette\InvalidStateException;
@@ -28,33 +31,25 @@ class Nette extends Framework
2831
/** @var string */
2932
private $suite;
3033

31-
/**
32-
* @var array $config
33-
*/
34-
public function __construct($config = array())
35-
{
36-
$this->config = array(
37-
'configFiles' => array(),
38-
);
39-
parent::__construct($config);
40-
}
41-
42-
protected function validateConfig()
43-
{
44-
parent::validateConfig();
45-
Validators::assertField($this->config, 'configFiles', 'array');
46-
}
34+
/** @var string */
35+
private $path;
4736

4837
// TODO: separate ArachneTools module (debugContent method)
4938
public function _beforeSuite($settings = array())
5039
{
5140
parent::_beforeSuite($settings);
5241

5342
$this->detectSuiteName($settings);
54-
$path = pathinfo($settings['path'], PATHINFO_DIRNAME);
55-
$tempDir = $path . DIRECTORY_SEPARATOR . '_temp' . DIRECTORY_SEPARATOR . $this->suite;
43+
$this->path = pathinfo($settings['path'], PATHINFO_DIRNAME);
44+
45+
self::purge($this->path . DIRECTORY_SEPARATOR . '_temp' . DIRECTORY_SEPARATOR . $this->suite);
46+
}
47+
48+
public function _before(TestCase $test)
49+
{
50+
$tempDir = $this->path . DIRECTORY_SEPARATOR . '_temp' . DIRECTORY_SEPARATOR . $this->suite . DIRECTORY_SEPARATOR . (new \ReflectionClass($test))->getShortName() . '_' . $test->getName();
51+
@mkdir($tempDir, 0777, TRUE);
5652

57-
self::purge($tempDir);
5853
$this->configurator = new Configurator();
5954
$this->configurator->setDebugMode(FALSE);
6055
$this->configurator->setTempDirectory($tempDir);
@@ -63,20 +58,20 @@ public function _beforeSuite($settings = array())
6358
'class' => $this->getContainerClass(),
6459
),
6560
));
61+
$this->configurator->onCompile[] = function ($config, Compiler $compiler) {
62+
$compiler->addExtension('arachne.codeception', new CodeceptionExtension());
63+
};
6664

67-
$files = $this->config['configFiles'];
68-
$files[] = __DIR__ . '/config.neon';
69-
foreach ($files as $file) {
70-
$this->configurator->addConfig($file);
65+
if ($test instanceof ConfigFilesInterface) {
66+
foreach ($test->getConfigFiles() as $file) {
67+
$this->configurator->addConfig($this->path . DIRECTORY_SEPARATOR . $this->suite . DIRECTORY_SEPARATOR . $file);
68+
}
7169
}
7270

7371
// Generates and loads the container class.
7472
// The actual container is created later.
7573
$this->configurator->createContainer();
76-
}
7774

78-
public function _before(TestCase $test)
79-
{
8075
$class = $this->getContainerClass();
8176
// Cannot use $this->configurator->createContainer() directly beacuse it would call $container->initialize().
8277
// Container initialization is called laiter by NetteConnector.
@@ -112,8 +107,9 @@ public function grabService($service)
112107

113108
public function seeRedirectTo($url)
114109
{
110+
$request = $this->container->getByType('Nette\Http\IRequest');
115111
$response = $this->container->getByType('Nette\Http\IResponse');
116-
if ($response->getHeader('Location') !== $url) {
112+
if ($response->getHeader('Location') !== $request->getUrl()->getHostUrl() . $url) {
117113
$this->fail('Couldn\'t confirm redirect target to be "' . $url . '", Location header contains "' . $response->getHeader('Location') . '".');
118114
}
119115
}
@@ -148,7 +144,7 @@ private function getContainerClass()
148144
protected static function purge($dir)
149145
{
150146
if (!is_dir($dir)) {
151-
mkdir($dir);
147+
return;
152148
}
153149
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST) as $entry) {
154150
if (substr($entry->getBasename(), 0, 1) === '.') {

src/Module/config.neon

Lines changed: 0 additions & 6 deletions
This file was deleted.

tests/integration.suite.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,3 @@ class_name: IntegrationSuiteGuy
55
modules:
66
enabled:
77
- Nette
8-
config:
9-
Nette:
10-
configFiles:
11-
- tests/integration/config/config.neon
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
extensions:
2+
nette: Nette\Bridges\Framework\NetteExtension
3+
enumag.application: Enumag\Application\DI\ApplicationExtension
4+
5+
nette:
6+
application:
7+
catchExceptions: null
8+
mapping:
9+
*: Tests\Integration\Classes\*Presenter
10+
11+
services:
12+
routerFactory: Tests\Integration\Classes\RouterFactory
13+
router: @routerFactory::create()
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace Tests\Integration;
4+
5+
use Arachne\Codeception\ConfigFilesInterface;
6+
use Codeception\TestCase\Test;
7+
use Nette\Application\Application;
8+
9+
/**
10+
* @author Jáchym Toušek
11+
*/
12+
class ApplicationTest extends Test implements ConfigFilesInterface
13+
{
14+
15+
public function getConfigFiles()
16+
{
17+
return [
18+
'config/application.neon',
19+
];
20+
}
21+
22+
public function testApplication()
23+
{
24+
$this->assertInstanceOf(Application::class, $this->guy->grabService(Application::class));
25+
}
26+
27+
public function testPage()
28+
{
29+
$this->guy->amOnPage('/article/page');
30+
$this->guy->seeResponseCodeIs(200);
31+
$this->guy->see('headline', 'h1');
32+
}
33+
34+
public function testLink()
35+
{
36+
$this->guy->amOnPage('/article/link');
37+
$this->guy->seeResponseCodeIs(200);
38+
$this->guy->see('Normal link');
39+
$this->guy->seeLink('Normal link', '/article/page');
40+
}
41+
42+
public function testRedirect()
43+
{
44+
$this->guy->amOnPage('/article/redirect');
45+
$this->guy->seeRedirectTo('/article/page');
46+
$this->guy->seeResponseCodeIs(301);
47+
}
48+
49+
public function testUnknown()
50+
{
51+
$this->guy->amOnPage('/article/unknown');
52+
$this->guy->seeResponseCodeIs(404);
53+
}
54+
55+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Tests\Integration\Classes;
4+
5+
use Nette\Application\UI\Presenter;
6+
7+
/**
8+
* @author Jáchym Toušek
9+
*/
10+
class ArticlePresenter extends Presenter
11+
{
12+
13+
public function actionRedirect()
14+
{
15+
$this->redirect(301, 'page');
16+
}
17+
18+
public function formatTemplateFiles()
19+
{
20+
$name = $this->getName();
21+
$presenter = substr($name, strrpos(':' . $name, ':'));
22+
return [ __DIR__ . "/../../templates/$presenter.$this->view.latte" ];
23+
}
24+
25+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Tests\Integration\Classes;
4+
5+
use Nette\Application\IRouter;
6+
use Nette\Application\Routers\Route;
7+
use Nette\Application\Routers\RouteList;
8+
use Nette\Object;
9+
10+
/**
11+
* @author Jáchym Toušek
12+
*/
13+
class RouterFactory extends Object
14+
{
15+
16+
/**
17+
* @return IRouter
18+
*/
19+
public function create()
20+
{
21+
$router = new RouteList();
22+
$router[] = new Route('<presenter>[/<action>[/<id>]]', 'Homepage:default');
23+
24+
return $router;
25+
}
26+
27+
}

tests/integration/src/DITest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Tests\Integration;
4+
5+
use Codeception\TestCase\Test;
6+
use Nette\DI\Container;
7+
8+
/**
9+
* @author Jáchym Toušek
10+
*/
11+
class DITest extends Test
12+
{
13+
14+
public function testContainer()
15+
{
16+
$this->assertInstanceOf(Container::class, $this->guy->grabService(Container::class));
17+
}
18+
19+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<a n:href="Article:page">
2+
Normal link
3+
</a>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>headline</h1>

0 commit comments

Comments
 (0)