protected function dump() { $__KMONKEY__0 = \Kahlan\Plugin\Monkey::patched(null, 'Kahlan\\Util\\Text'); return $__KMONKEY__0::dump('Hello'); }
expect(Checker::is('email', 'abc,efg@example.com'))->toBe(false); expect(Checker::is('email', 'abc@sub,example.com'))->toBe(false); expect(Checker::is('email', "abc@sub'example.com"))->toBe(false); expect(Checker::is('email', 'abc@sub/example.com'))->toBe(false); expect(Checker::is('email', 'abc@yahoo!.com'))->toBe(false); expect(Checker::is('email', "Nyrée.surname@example.com"))->toBe(false); expect(Checker::is('email', 'abc@example_underscored.com'))->toBe(false); expect(Checker::is('email', '*****@*****.**'))->toBe(false); }); it("deeply checks emails", function () { Monkey::patch('getmxrr', function () { return true; }); expect(Checker::is('email', '*****@*****.**', ['deep' => true]))->toBe(true); Monkey::patch('getmxrr', function () { return false; }); expect(Checker::is('email', '*****@*****.**', ['deep' => true]))->toBe(false); }); it("checks in list values", function () { expect(Checker::is('inList', 'one', ['list' => ['one', 'two']]))->toBe(true); expect(Checker::is('inList', 'two', ['list' => ['one', 'two']]))->toBe(true); expect(Checker::is('inList', 0, ['list' => [0, 1]]))->toBe(true); expect(Checker::is('inList', 1, ['list' => [0, 1]]))->toBe(true); expect(Checker::is('inList', 0, ['list' => ['0', '1']]))->toBe(true); expect(Checker::is('inList', '1', ['list' => ['0', '1']]))->toBe(true); expect(Checker::is('inList', 1, ['list' => ['0', '1']]))->toBe(true); expect(Checker::is('inList', '1', ['list' => ['0', '1']]))->toBe(true); expect(Checker::is('inList', '', ['list' => ['0', '1']]))->toBe(false); expect(Checker::is('inList', null, ['list' => ['0', '1']]))->toBe(false); expect(Checker::is('inList', false, ['list' => ['0', '1']]))->toBe(false);
<?php $__KMONKEY__3 = \kahlan\plugin\Monkey::patched(null, 'name\\space\\MyClass2'); $__KMONKEY__2 = \kahlan\plugin\Monkey::patched(null, 'name\\space\\MyClass'); $__KMONKEY__1 = \kahlan\plugin\Monkey::patched(__NAMESPACE__, 'mt_rand', true); $__KMONKEY__0 = \kahlan\plugin\Monkey::patched(__NAMESPACE__, 'function_exists', true); use name\space\MyClass as MyAlias; use name\space; if ($__KMONKEY__0('myfunction')) { $thatIsWeird = true; } $rand = $__KMONKEY__1(); new $__KMONKEY__2(); new $__KMONKEY__3();
expect($request->export())->toEqual(['basePath' => '/base/path/webroot', 'locale' => null, 'data' => $_FILES + $_POST, 'params' => [], 'env' => $request->env, 'method' => 'GET', 'scheme' => 'http', 'version' => '1.1', 'host' => 'localhost', 'port' => 80, 'path' => '/app', 'query' => '?get=value', 'fragment' => '', 'username' => null, 'password' => null, 'url' => 'http://localhost/app?get=value', 'stream' => $request->stream()]); }); it("supports url rewriting", function () { $this->globals = defineGlobals(['SERVER' => ['REQUEST_URI' => '/base/path/app?get=value']]); $request = Request::ingoing(); expect($request->export())->toEqual(['basePath' => '/base/path', 'locale' => null, 'data' => $_FILES + $_POST, 'params' => [], 'env' => $request->env, 'method' => 'GET', 'scheme' => 'http', 'version' => '1.1', 'host' => 'localhost', 'port' => 80, 'path' => '/app', 'query' => '?get=value', 'fragment' => '', 'username' => null, 'password' => null, 'url' => 'http://localhost/app?get=value', 'stream' => $request->stream()]); }); it("uses php://input as body message by default", function () { $temp = Dir::tempnam(sys_get_temp_dir(), 'spec'); $filename = tempnam($temp, 'foo'); $handler = fopen($filename, 'w'); fwrite($handler, 'Hello World'); fclose($handler); Monkey::patch('fopen', function ($name, $mode, $use_include_path = false) use($filename) { if ($name === 'php://input') { $name = $filename; } return fopen($name, $mode, $use_include_path); }); $request = Request::ingoing(); expect($request->body())->toBe('Hello World'); Dir::remove($temp, ['recursive' => true]); }); it("normalizes deep `\$_FILES` structure", function () { $_FILES = ['files' => ['name' => ['file 2.jpg', 'file 3.jpg', 'file 4.jpg'], 'type' => ['image/jpeg', 'image/jpeg', 'image/jpeg'], 'tmp_name' => ['/private/var/tmp/phpF5vsky', '/private/var/tmp/phphRJ2zW', '/private/var/tmp/phprI92L1'], 'error' => [0, 0, 0], 'size' => [418, 418, 418]]]; $request = Request::ingoing(); expect($request->data())->toEqual(['files' => [['name' => 'file 2.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/private/var/tmp/phpF5vsky', 'error' => 0, 'size' => 418], ['name' => 'file 3.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/private/var/tmp/phphRJ2zW', 'error' => 0, 'size' => 418], ['name' => 'file 4.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/private/var/tmp/phprI92L1', 'error' => 0, 'size' => 418]]] + $_POST); }); it("normalizes nested `\$_FILES` structure", function () { $_FILES = ['Image' => ['name' => ['file' => 'file 5.jpg'], 'type' => ['file' => 'image/jpeg'], 'tmp_name' => ['file' => '/private/var/tmp/phpAmSDL4'], 'error' => ['file' => 0], 'size' => ['file' => 418]]]; $request = Request::ingoing(); expect($request->data())->toEqual(['Image' => ['file' => ['name' => 'file 5.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/private/var/tmp/phpAmSDL4', 'error' => 0, 'size' => 418]]] + $_POST);
/** * Stubs a method. * * @param string $path Method name or array of stubs where key are method names and * values the stubs. * @param string $closure The stub implementation. * @return Method[] The created array of method instances. * @return Method The stubbed method instance. */ public function method($path, $closure = null) { if ($this->_needToBePatched) { $layer = Double::classname(); Monkey::patch($this->_reference, $layer); $this->_needToBePatched = false; $this->_reference = $layer; } $reference = $this->_reference; if (!$path) { throw new InvalidArgumentException("Method name can't be empty."); } $names = is_array($path) ? $path : [$path]; $this->_chain = []; $total = count($names); foreach ($names as $index => $name) { if (preg_match('/^::.*/', $name)) { $reference = is_object($reference) ? get_class($reference) : $reference; } $hash = Suite::hash($reference); if (!isset(static::$_registered[$hash])) { static::$_registered[$hash] = new static($reference); } $instance = static::$_registered[$hash]; if (is_object($reference)) { Suite::register(get_class($reference)); } else { Suite::register($reference); } if (!isset($instance->_methods[$name])) { $instance->_methods[$name] = []; $instance->_stubs[$name] = Double::instance(); } $method = new Method(['parent' => $this, 'reference' => $reference, 'name' => $name]); $this->_chain[$name] = $method; array_unshift($instance->_methods[$name], $method); if ($index < $total - 1) { $reference = $instance->_stubs[$name]; $method->andReturn($instance->_stubs[$name]); } } $method = end($this->_chain); if ($closure) { $method->andRun($closure); } return $method; }
it("patches a core function with a closure", function () { $foo = new Foo(); Monkey::patch('time', function () { return 123; }); expect($foo->time())->toBe(123); }); it("patches a core class", function () { $foo = new Foo(); Monkey::patch('DateTime', 'Kahlan\\Spec\\Suite\\Plugin\\MyDateTime'); expect($foo->datetime()->getTimestamp())->toBe(245026800); }); it("patches a function", function () { $foo = new Foo(); Monkey::patch('Kahlan\\Spec\\Fixture\\Plugin\\Monkey\\rand', 'Kahlan\\Spec\\Suite\\Plugin\\myrand'); expect($foo->rand(0, 100))->toBe(101); }); it("patches a class", function () { $foo = new Foo(); Monkey::patch('Kahlan\\Util\\Text', 'Kahlan\\Spec\\Suite\\Plugin\\MyString'); expect($foo->dump((object) 'hello'))->toBe('myhashvalue'); }); it("can unpatch a monkey patch", function () { $foo = new Foo(); Monkey::patch('Kahlan\\Spec\\Fixture\\Plugin\\Monkey\\rand', 'Kahlan\\Spec\\Suite\\Plugin\\myrand'); expect($foo->rand(0, 100))->toBe(101); Monkey::reset('Kahlan\\Spec\\Fixture\\Plugin\\Monkey\\rand'); expect($foo->rand(0, 100))->toBe(50); }); }); });
}); // Disabled because Monkey::patch doesn't work on included files xit('emit response to beyond', function () { Monkey::patch('header', function (string $header, bool $replace = TRUE) { static $first = TRUE; static $reset = TRUE; if ($first) { expect($header)->toBe('HTTP/1.1 202'); $first = FALSE; } else { expect($replace)->toBe($reset); $reset = FALSE; } }); Monkey::patch('headers_sent', function () { return FALSE; }); expect(function () { emit(new ServerRequest(), function (ServerRequest $req, callable $open) { $name = $req->getQuery()['name'] ?? 'World'; $open(202, ['Content-Language' => ['en', 'es']]); (yield "Hola {$name}"); }); })->toEcho('Hola World'); }); it('calls responder\'s return', function () { $closed = FALSE; emit(new ServerRequest(), function (ServerRequest $req, callable $open) use(&$closed) { (yield ''); return function () use(&$closed) { $closed = TRUE;
it("returns the PDO driver", function () { expect($this->database->client())->toBe($this->client); }); }); describe("->connect()", function () { it("throws an exception if no DSN is set", function () { $closure = function () { Stub::create(['extends' => 'chaos\\database\\Database']); }; expect($closure)->toThrow(new DatabaseException('Error, no DSN setup has been configured for database connection.')); }); it("throws an exception when PDO throws an exception on connect", function () { $closure = function () { Stub::create(['extends' => 'chaos\\database\\Database', 'params' => [['dsn' => 'mysql:host=localhost;port=3306;dbname=test']]]); }; Monkey::patch('PDO', 'chaos\\database\\spec\\mock\\PDO'); expect($closure)->toThrow(new DatabaseException("Error, PDO mock class used can't connect.")); }); }); describe("->_exception()", function () { beforeEach(function () { Stub::on($this->database)->method('exception', function ($e) { return $this->_exception($e); }); }); it("throws an exception when PDO can't connect to the host", function () { $closure = function () { $e = Stub::create(); Stub::on($e)->method('getCode', function () { return 'HY000'; });
}); beforeEach(function () { $box = box('chaos.spec'); $this->adapter = $box->get('source.database.mysql'); }); describe("::enabled()", function () { it("returns `true` for enabled features, false otherwise.", function () { expect(MySql::enabled())->toEqual(['arrays' => false, 'transactions' => true, 'booleans' => true, 'default' => false]); expect(MySql::enabled('arrays'))->toBe(false); expect(MySql::enabled('transactions'))->toBe(true); expect(MySql::enabled('booleans'))->toBe(true); expect(MySql::enabled('default'))->toBe(false); }); it("throws an exception if the extension is not loaded.", function () { Monkey::patch('extension_loaded', function () { return false; }); expect(function () { MySql::enabled(); })->toThrow(new DatabaseException("The PDO MySQL extension is not installed.")); }); }); describe("->connect()", function () { it("throws an exception if no database name is set", function () { $closure = function () { new MySql(); }; expect($closure)->toThrow(new DatabaseException('Error, no database name has been configured.')); }); }); describe("->sources()", function () {
/** * Return the actual reference which must be used. * * @param mixed $reference An instance or a fully-namespaced class name. * @param mixed The reference or the monkey patched one if exist. */ protected function _reference($reference) { if (!is_string($reference)) { return $reference; } $pos = strrpos($reference, '\\'); if ($pos !== false) { $namespace = substr($reference, 0, $pos); $basename = substr($reference, $pos + 1); } else { $namespace = null; $basename = $reference; } $substitute = null; $reference = Monkey::patched($namespace, $basename, false, $substitute); return $substitute ?: $reference; }
<?php $__KMONKEY__0 = \Kahlan\Plugin\Monkey::patched(__NAMESPACE__, 'function_exists'); $__KMONKEY__1 = \Kahlan\Plugin\Monkey::patched(__NAMESPACE__, 'mt_rand'); $__KMONKEY__2__ = null; $__KMONKEY__2 = \Kahlan\Plugin\Monkey::patched(null, 'name\\space\\MyClass', false, $__KMONKEY__2__); $__KMONKEY__3 = \Kahlan\Plugin\Monkey::patched(__NAMESPACE__, 'time'); $__KMONKEY__4__ = null; $__KMONKEY__4 = \Kahlan\Plugin\Monkey::patched(null, 'name\\space\\MyClass2', false, $__KMONKEY__4__); use name\space\MyClass as MyAlias; use name\space; if ($__KMONKEY__0('myfunction')) { $thatIsWeird = true; } $rand = $__KMONKEY__1(); $__KMONKEY__2__ ? $__KMONKEY__2__ : new $__KMONKEY__2(); $__KMONKEY__4__ ? $__KMONKEY__4__ : new $__KMONKEY__4($__KMONKEY__3());
it("patches a core function with a closure", function () { $foo = new Foo(); Monkey::patch('time', function () { return 123; }); expect($foo->time())->toBe(123); }); it("patches a core class", function () { $foo = new Foo(); Monkey::patch('DateTime', 'kahlan\\spec\\suite\\plugin\\MyDateTime'); expect($foo->datetime()->getTimestamp())->toBe(245026800); }); it("patches a function", function () { $foo = new Foo(); Monkey::patch('kahlan\\spec\\fixture\\plugin\\monkey\\rand', 'kahlan\\spec\\suite\\plugin\\myrand'); expect($foo->rand(0, 100))->toBe(101); }); it("patches a class", function () { $foo = new Foo(); Monkey::patch('kahlan\\util\\Text', 'kahlan\\spec\\suite\\plugin\\MyString'); expect($foo->dump((object) 'hello'))->toBe('myhashvalue'); }); it("can unpatch a monkey patch", function () { $foo = new Foo(); Monkey::patch('kahlan\\spec\\fixture\\plugin\\monkey\\rand', 'kahlan\\spec\\suite\\plugin\\myrand'); expect($foo->rand(0, 100))->toBe(101); Monkey::reset('kahlan\\spec\\fixture\\plugin\\monkey\\rand'); expect($foo->rand(0, 100))->toBe(50); }); }); });
throw RuntimeExpection('This should never be called'); } return fopen($filename, $mode); }); $req = new ServerRequest(['CONTENT_TYPE' => 'text/plain', 'CONTENT_LENGTH' => 11], NULL, NULL, NULL, 'Hello World'); expect($req->getBody())->toBeA('resource'); expect(fread($req->getBody(), 11))->toBe('Hello World'); }); }); describe('->getParsedBody', function () { it('returns parsed body when is application/x-www-form-urlencoded', function () { Monkey::patch('fopen', function ($filename, $mode) { if ($filename === 'php://input') { $input = fopen('php://temp', 'r+'); fwrite($input, 'hello=world&foo=bar'); fseek($input, 0); return $input; } return fopen($filename, $mode); }); $req = new ServerRequest(['REQUEST_METHOD' => 'POST', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', 'CONTENT_LENGTH' => 17]); expect($req->getParsedBody())->toBe(['hello' => 'world', 'foo' => 'bar']); }); }); describe('->isSecure', function () { it('returns true when the HTTPS header is on', function () { expect((new ServerRequest(['HTTPS' => 'on']))->isSecure())->toBe(TRUE); }); }); describe('->normalizeServer', function () { it('returns HTTPS when SCRIPT_URI starts with https://', function () {
expect($response->stream())->toBe($new->stream()); }); it("clones cookies", function () { $response = new Response(['body' => 'Body Message']); $cookies = $response->headers->cookies; $cookies['foo'] = 'bar'; $newRequest = clone $response; $new = $newRequest->headers->cookies; expect($cookies['foo'][0])->not->toBe($new['foo'][0]); expect($cookies['foo'][0]->value())->toBe($new['foo'][0]->value()); }); }); describe("::parse()", function () { it("creates a response with some set-cookies", function () { Monkey::patch('time', function () { return strtotime('24 Dec 2015'); }); $message = join("\r\n", ['HTTP/1.1 200 OK', 'Connection: close', 'Content-Type: text/plain;charset=UTF8', 'Content-Length: 5', 'Set-Cookie: doctor=who; Path=/tardis; HttpOnly', 'Set-Cookie: test=foo%20bar; Expires=Fri, 25 Dec 2015 00:00:00 GMT; Secure', 'Set-Cookie: test=foo%2Bbin; Path=/test; Domain=.domain.com', '', 'Test!']); $cookies = ['doctor' => [['value' => 'who', 'expires' => null, 'path' => '/tardis', 'domain' => null, 'max-age' => null, 'secure' => false, 'httponly' => true]], 'test' => [['value' => 'foo bar', 'expires' => 1451001600, 'path' => null, 'domain' => null, 'max-age' => null, 'secure' => true, 'httponly' => false], ['value' => 'foo+bin', 'expires' => null, 'path' => '/test', 'domain' => '.domain.com', 'max-age' => null, 'secure' => false, 'httponly' => false]]]; $response = Response::parse($message); expect($response->headers->cookies->data())->toBe($cookies); expect($response->toMessage())->toBe($message); }); it("decodes chunked body", function () { $headers = join("\r\n", ['HTTP/1.1 200 OK', 'Date: Mon, 22 Mar 2004 11:15:03 GMT', 'Content-Type: text/html', 'Transfer-Encoding: chunked', '', '']); $body = "29\r\n"; $body .= "<html><body><p>The file you requested is \r\n"; $body .= "6\r\n"; $body .= "3,400 \r\n"; $body .= "22\r\n"; $body .= "bytes long and was last modified: \r\n";
public function subChild() { $__KMONKEY__18 = \kahlan\plugin\Monkey::patched(__NAMESPACE__, 'RecursiveIteratorIterator', false); if ($options['recursive']) { $worker = new $__KMONKEY__18($worker, $iteratorFlags); } }
$patch->toBe(new DateTime('@123'), new DateTime('@456')); expect($mon->datetime()->getTimestamp())->toBe(123); expect($mon->datetime()->getTimestamp())->toBe(456); }); it("patches a function", function () { $mon = new Mon(); Monkey::patch('Kahlan\\Spec\\Fixture\\Plugin\\Monkey\\rand', 'Kahlan\\Spec\\Suite\\Plugin\\myrand'); expect($mon->rand(0, 100))->toBe(101); }); it("patches a class", function () { $mon = new Mon(); Monkey::patch('Kahlan\\Util\\Text', 'Kahlan\\Spec\\Mock\\Plugin\\Monkey\\MyString'); expect($mon->dump((object) 'hello'))->toBe('myhashvalue'); }); it("can unpatch a monkey patch", function () { $mon = new Mon(); Monkey::patch('Kahlan\\Spec\\Fixture\\Plugin\\Monkey\\rand', 'Kahlan\\Spec\\Suite\\Plugin\\myrand'); expect($mon->rand(0, 100))->toBe(101); Monkey::reset('Kahlan\\Spec\\Fixture\\Plugin\\Monkey\\rand'); expect($mon->rand(0, 100))->toBe(50); }); it("throws an exception with trying to patch an unsupported functions or core langage statements", function () { $closure = function () { Monkey::patch('func_get_args', function () { return []; }); }; expect($closure)->toThrow(new Exception('Monkey patching `func_get_args()` is not supported by Kahlan.')); }); }); });
/** * Sets the stub logic. * * @param mixed $substitute The logic. */ public function toBeOK() { if (!is_string($this->_actual)) { throw new Exception("Error `toBeOK()` need to be applied on a fully-namespaced class or function name."); } if ($this->_isClass) { Monkey::patch($this->_actual, Double::classname()); } else { Monkey::patch($this->_actual, function () { }); } }
public function subChild() { $__KMONKEY__20__ = null; $__KMONKEY__20 = \Kahlan\Plugin\Monkey::patched(__NAMESPACE__, 'RecursiveIteratorIterator', false, $__KMONKEY__20__); if ($options['recursive']) { $worker = $__KMONKEY__20__ ? $__KMONKEY__20__ : new $__KMONKEY__20($worker, $iteratorFlags); } }