Skip to content

Commit e6a6d64

Browse files
authored
Merge pull request #1312 from jim-parry/enhance/testing
Add headerEmited (or not) assertions to CIUnitTestCase
2 parents bd7b0e6 + e0c8fd4 commit e6a6d64

File tree

10 files changed

+302
-73
lines changed

10 files changed

+302
-73
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,15 @@ Please read the [*Contributing to CodeIgniter*](https://github.com/bcit-ci/CodeI
6868
## Server Requirements
6969
PHP version 7.1 or higher is required, with the following extensions installed:
7070

71-
- intl
71+
- [intl](http://php.net/manual/en/intl.requirements.php)
72+
- [libcurl](http://php.net/manual/en/curl.requirements.php) if you plan to use the HTTP\CURLRequest library
7273

74+
Additionally, make sure that the following extensions are enabled in your PHP:
75+
76+
- json (enabled by default - don't turn it off)
77+
- [mbstring](http://php.net/manual/en/mbstring.installation.php)
78+
- [mysqlnd](http://php.net/manual/en/mysqlnd.install.php)
79+
- xml (enabled by default - don't turn it off)
7380

7481
## Running CodeIgniter Tests
7582
Information on running CodeIgniter test suite can be found in the [README.md](tests/README.md) file in the tests directory.
Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,32 @@
11
<?php
2-
32
/*
4-
|--------------------------------------------------------------------------
5-
| ERROR DISPLAY
6-
|--------------------------------------------------------------------------
7-
| In development, we want to show as many errors as possible to help
8-
| make sure they don't make it to production. And save us hours of
9-
| painful debugging.
10-
*/
3+
|--------------------------------------------------------------------------
4+
| ERROR DISPLAY
5+
|--------------------------------------------------------------------------
6+
| In development, we want to show as many errors as possible to help
7+
| make sure they don't make it to production. And save us hours of
8+
| painful debugging.
9+
*/
1110
error_reporting(-1);
1211
ini_set('display_errors', 1);
1312

1413
/*
15-
|--------------------------------------------------------------------------
16-
| DEBUG BACKTRACES
17-
|--------------------------------------------------------------------------
18-
| If true, this constant will tell the error screens to display debug
19-
| backtraces along with the other error information. If you would
20-
| prefer to not see this, set this value to false.
21-
*/
22-
define('SHOW_DEBUG_BACKTRACE', true);
14+
|--------------------------------------------------------------------------
15+
| DEBUG BACKTRACES
16+
|--------------------------------------------------------------------------
17+
| If true, this constant will tell the error screens to display debug
18+
| backtraces along with the other error information. If you would
19+
| prefer to not see this, set this value to false.
20+
*/
21+
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);
2322

2423
/*
25-
|--------------------------------------------------------------------------
26-
| DEBUG MODE
27-
|--------------------------------------------------------------------------
28-
| Debug mode is an experimental flag that can allow changes throughout
29-
| the system. This will control whether Kint is loaded, and a few other
30-
| items. It can always be used within your own application too.
31-
*/
24+
|--------------------------------------------------------------------------
25+
| DEBUG MODE
26+
|--------------------------------------------------------------------------
27+
| Debug mode is an experimental flag that can allow changes throughout
28+
| the system. This will control whether Kint is loaded, and a few other
29+
| items. It can always be used within your own application too.
30+
*/
3231

33-
define('CI_DEBUG', 1);
32+
defined('CI_DEBUG') || define('CI_DEBUG', 1);
Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
<?php
22

33
/*
4-
|--------------------------------------------------------------------------
5-
| ERROR DISPLAY
6-
|--------------------------------------------------------------------------
7-
| Don't show ANY in production environments. Instead, let the system catch
8-
| it and display a generic error message.
9-
*/
4+
|--------------------------------------------------------------------------
5+
| ERROR DISPLAY
6+
|--------------------------------------------------------------------------
7+
| Don't show ANY in production environments. Instead, let the system catch
8+
| it and display a generic error message.
9+
*/
1010
ini_set('display_errors', 0);
1111
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
1212

1313
/*
14-
|--------------------------------------------------------------------------
15-
| DEBUG MODE
16-
|--------------------------------------------------------------------------
17-
| Debug mode is an experimental flag that can allow changes throughout
18-
| the system. It's not widely used currently, and may not survive
19-
| release of the framework.
20-
*/
14+
|--------------------------------------------------------------------------
15+
| DEBUG MODE
16+
|--------------------------------------------------------------------------
17+
| Debug mode is an experimental flag that can allow changes throughout
18+
| the system. It's not widely used currently, and may not survive
19+
| release of the framework.
20+
*/
2121

22-
define('CI_DEBUG', 0);
22+
defined('CI_DEBUG') || define('CI_DEBUG', 0);

application/Config/Boot/testing.php

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
11
<?php
22

33
/*
4-
|--------------------------------------------------------------------------
5-
| ERROR DISPLAY
6-
|--------------------------------------------------------------------------
7-
| In development, we want to show as many errors as possible to help
8-
| make sure they don't make it to production. And save us hours of
9-
| painful debugging.
10-
*/
4+
|--------------------------------------------------------------------------
5+
| ERROR DISPLAY
6+
|--------------------------------------------------------------------------
7+
| In development, we want to show as many errors as possible to help
8+
| make sure they don't make it to production. And save us hours of
9+
| painful debugging.
10+
*/
1111
error_reporting(-1);
1212
ini_set('display_errors', 1);
1313

1414
/*
15-
|--------------------------------------------------------------------------
16-
| DEBUG BACKTRACES
17-
|--------------------------------------------------------------------------
18-
| If true, this constant will tell the error screens to display debug
19-
| backtraces along with the other error information. If you would
20-
| prefer to not see this, set this value to false.
21-
*/
22-
define('SHOW_DEBUG_BACKTRACE', true);
15+
|--------------------------------------------------------------------------
16+
| DEBUG BACKTRACES
17+
|--------------------------------------------------------------------------
18+
| If true, this constant will tell the error screens to display debug
19+
| backtraces along with the other error information. If you would
20+
| prefer to not see this, set this value to false.
21+
*/
22+
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);
2323

2424
/*
25-
|--------------------------------------------------------------------------
26-
| DEBUG MODE
27-
|--------------------------------------------------------------------------
28-
| Debug mode is an experimental flag that can allow changes throughout
29-
| the system. It's not widely used currently, and may not survive
30-
| release of the framework.
31-
*/
25+
|--------------------------------------------------------------------------
26+
| DEBUG MODE
27+
|--------------------------------------------------------------------------
28+
| Debug mode is an experimental flag that can allow changes throughout
29+
| the system. It's not widely used currently, and may not survive
30+
| release of the framework.
31+
*/
3232

33-
define('CI_DEBUG', 1);
33+
defined('CI_DEBUG') || define('CI_DEBUG', 1);

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"php": ">=7.1",
2020
"zendframework/zend-escaper": "^2.5",
2121
"kint-php/kint": "^2.1",
22-
"ext-intl": "*"
22+
"ext-intl": "*",
23+
"ext-curl": "*"
2324
},
2425
"require-dev": {
2526
"phpunit/phpunit": "^7.0",

system/Test/CIUnitTestCase.php

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<?php namespace CodeIgniter\Test;
1+
<?php
2+
namespace CodeIgniter\Test;
23

34
/**
45
* CodeIgniter
@@ -45,6 +46,7 @@
4546
*/
4647
class CIUnitTestCase extends TestCase
4748
{
49+
4850
use ReflectionHelper;
4951

5052
/**
@@ -63,7 +65,7 @@ public function setUp()
6365
{
6466
parent::setUp();
6567

66-
if (! $this->app)
68+
if ( ! $this->app)
6769
{
6870
$this->app = $this->createApplication();
6971
}
@@ -104,7 +106,8 @@ public function assertEventTriggered(string $eventName): bool
104106

105107
foreach (Events::getPerformanceLogs() as $log)
106108
{
107-
if ($log['event'] !== $eventName) continue;
109+
if ($log['event'] !== $eventName)
110+
continue;
108111

109112
$found = true;
110113
break;
@@ -114,6 +117,57 @@ public function assertEventTriggered(string $eventName): bool
114117
return $found;
115118
}
116119

120+
/**
121+
* Hooks into xdebug's headers capture, looking for a specific header
122+
* emitted
123+
*
124+
* @param string $header The leading portion of the header we are looking for
125+
* @param bool $ignoreCase
126+
*
127+
* @throws \Exception
128+
*/
129+
public function assertHeaderEmitted(string $header, bool $ignoreCase = false): void
130+
{
131+
$found = false;
132+
133+
foreach (xdebug_get_headers() as $emitted)
134+
{
135+
$found = $ignoreCase ?
136+
(stripos($emitted, $header) === 0) :
137+
(strpos($emitted, $header) === 0);
138+
if ($found)
139+
break;
140+
}
141+
142+
$this->assertTrue($found,"Didn't find header for {$header}");
143+
}
144+
145+
/**
146+
* Hooks into xdebug's headers capture, looking for a specific header
147+
* emitted
148+
*
149+
* @param string $header The leading portion of the header we don't want to find
150+
* @param bool $ignoreCase
151+
*
152+
* @throws \Exception
153+
*/
154+
public function assertHeaderNotEmitted(string $header, bool $ignoreCase = false): void
155+
{
156+
$found = false;
157+
158+
foreach (xdebug_get_headers() as $emitted)
159+
{
160+
$found = $ignoreCase ?
161+
(stripos($emitted, $header) === 0) :
162+
(strpos($emitted, $header) === 0);
163+
if ($found)
164+
break;
165+
}
166+
167+
$success = ! $found;
168+
$this->assertTrue($success,"Found header for {$header}");
169+
}
170+
117171
/**
118172
* Loads up an instance of CodeIgniter
119173
* and gets the environment setup.
@@ -122,12 +176,12 @@ public function assertEventTriggered(string $eventName): bool
122176
*/
123177
protected function createApplication()
124178
{
125-
$systemPath = realpath(__DIR__.'/../');
179+
$systemPath = realpath(__DIR__ . '/../');
126180

127-
require_once $systemPath.'/'.$this->configPath.'/Paths.php';
181+
require_once $systemPath . '/' . $this->configPath . '/Paths.php';
128182
$paths = $this->adjustPaths(new \Config\Paths());
129183

130-
$app = require $systemPath.'/bootstrap.php';
184+
$app = require $systemPath . '/bootstrap.php';
131185
return $app;
132186
}
133187

@@ -162,4 +216,5 @@ protected function adjustPaths(Paths $paths)
162216

163217
return $paths;
164218
}
219+
165220
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
namespace CodeIgniter\Test;
3+
4+
use CodeIgniter\HTTP\Response;
5+
use CodeIgniter\HTTP\Exceptions\HTTPException;
6+
use Config\App;
7+
8+
/**
9+
* This test suite has been created separately from
10+
* TestCaseTest because it messes with output
11+
* buffering from PHPUnit, and the individual
12+
* test cases need to be run as separate processes.
13+
*/
14+
class TestCaseEmissionsTest extends \CIUnitTestCase
15+
{
16+
17+
//--------------------------------------------------------------------
18+
/**
19+
* This needs to be run as a separate process, since phpunit
20+
* has already captured the "normal" output, and we will get
21+
* a "Cannot modify headers" message if we try to change
22+
* headers or cookies now.
23+
*
24+
* Furthermore, this test needs to flush the output buffering
25+
* that might be in progress, and start our own output buffer
26+
* capture.
27+
*
28+
* This test includes a basic sanity check, to make sure that
29+
* the body we thought would be sent actually was.
30+
*
31+
* @runInSeparateProcess
32+
* @preserveGlobalState disabled
33+
*/
34+
public function testHeadersEmitted()
35+
{
36+
37+
$response = new Response(new App());
38+
$response->pretend(FALSE);
39+
40+
$body = 'Hello';
41+
$response->setBody($body);
42+
43+
$response->setCookie('foo', 'bar');
44+
$this->assertTrue($response->hasCookie('foo'));
45+
$this->assertTrue($response->hasCookie('foo', 'bar'));
46+
47+
// send it
48+
ob_start();
49+
$response->send();
50+
51+
$buffer = ob_clean();
52+
if (ob_get_level() > 0)
53+
ob_end_clean();
54+
55+
// and what actually got sent?; test both ways
56+
$this->assertHeaderEmitted("Set-Cookie: foo=bar;");
57+
$this->assertHeaderEmitted("set-cookie: FOO=bar", true);
58+
}
59+
60+
/**
61+
* This needs to be run as a separate process, since phpunit
62+
* has already captured the "normal" output, and we will get
63+
* a "Cannot modify headers" message if we try to change
64+
* headers or cookies now.
65+
*
66+
* Furthermore, this test needs to flush the output buffering
67+
* that might be in progress, and start our own output buffer
68+
* capture.
69+
*
70+
* This test includes a basic sanity check, to make sure that
71+
* the body we thought would be sent actually was.
72+
*
73+
* @runInSeparateProcess
74+
* @preserveGlobalState disabled
75+
*/
76+
public function testHeadersNotEmitted()
77+
{
78+
$response = new Response(new App());
79+
$response->pretend(FALSE);
80+
81+
$body = 'Hello';
82+
$response->setBody($body);
83+
84+
// what do we think we're about to send?
85+
$response->setCookie('foo', 'bar');
86+
$this->assertTrue($response->hasCookie('foo'));
87+
$this->assertTrue($response->hasCookie('foo', 'bar'));
88+
89+
// send it
90+
ob_start();
91+
$response->send();
92+
$output = ob_clean(); // what really was sent
93+
if (ob_get_level() > 0)
94+
ob_end_clean();
95+
96+
$this->assertHeaderNotEmitted("Set-Cookie: pop=corn", true);
97+
}
98+
99+
}

0 commit comments

Comments
 (0)