$class = $this->class; $subclass = Double::classname(['extends' => $class]); allow($subclass)->toReceive('::filterable')->andRun(function () { return Filters::run(get_called_class(), 'filterable', func_get_args(), function ($next, $message) { return "Hello {$message}"; }); }); Filters::apply($class, 'filterable', $this->filter1); Filters::apply($subclass, 'filterable', $this->filter2); expect($subclass::filterable('World!'))->toBe('21Hello World!12'); Filters::apply($subclass, 'filterable', $this->noChain); expect($subclass::filterable('World!'))->toBe("Hello"); }); it("applies filters in order", function () { $class = $this->class; $subclass = Double::classname(['extends' => $class]); allow($subclass)->toReceive('::filterable')->andRun(function () { return Filters::run(get_called_class(), 'filterable', func_get_args(), function ($next, $message) { return "Hello {$message}"; }); }); Filters::apply($subclass, 'filterable', $this->filter1); Filters::apply($subclass, 'filterable', $this->filter2); expect($subclass::filterable('World!'))->toBe('21Hello World!12'); }); }); describe("::get()", function () { it("exports filters setted as a class level", function () { Filters::apply($this->class, 'filterable', $this->filter1); $filters = Filters::get(); expect($filters)->toHaveLength(1);
expect($double->getTimestamp())->toBe(12345678); }); it("adds ` = NULL` to optional parameter in PHP core method", function () { skipIf(defined('HHVM_VERSION')); $result = Double::generate(['class' => 'Kahlan\\Spec\\Plugin\\Double\\Double', 'extends' => 'LogicException', 'layer' => true]); $expected = <<<EOD <?php namespace Kahlan\\\\Spec\\\\Plugin\\\\Double; class Double extends \\\\LogicException { public function __construct\\(\\\$message = NULL, \\\$code = NULL, \\\$previous = NULL\\) EOD; expect($result)->toMatch('~' . $expected . '~i'); }); it("generates code without PHP tags", function () { $result = Double::generate(['class' => 'Kahlan\\Spec\\Plugin\\Double\\Double', 'magicMethods' => false, 'openTag' => false, 'closeTag' => false]); $expected = <<<EOD namespace Kahlan\\Spec\\Plugin\\Double; class Double { } EOD; expect($result)->toBe($expected); }); }); });
it("formats an exception as a string message", function () { $message = Debugger::message(new Exception('World Destruction Error!')); expect($message)->toBe('`Exception` Code(0): World Destruction Error!'); }); it("formats a backtrace array as a string message", function () { $backtrace = ['message' => 'E_ERROR Error!', 'code' => E_ERROR]; $message = Debugger::message($backtrace); expect($message)->toBe("`E_ERROR` Code(1): E_ERROR Error!"); $backtrace = ['message' => 'Invalid Error!', 'code' => 404]; $message = Debugger::message($backtrace); expect($message)->toBe("`<INVALID>` Code(404): Invalid Error!"); }); }); describe("::loader()", function () { it("gets/sets a loader", function () { $loader = Double::instance(); expect(Debugger::loader($loader))->toBe($loader); }); }); describe("::errorType()", function () { it("returns some reader-friendly error type string", function () { expect(Debugger::errorType(E_ERROR))->toBe('E_ERROR'); expect(Debugger::errorType(E_WARNING))->toBe('E_WARNING'); expect(Debugger::errorType(E_PARSE))->toBe('E_PARSE'); expect(Debugger::errorType(E_NOTICE))->toBe('E_NOTICE'); expect(Debugger::errorType(E_CORE_ERROR))->toBe('E_CORE_ERROR'); expect(Debugger::errorType(E_CORE_WARNING))->toBe('E_CORE_WARNING'); expect(Debugger::errorType(E_CORE_ERROR))->toBe('E_CORE_ERROR'); expect(Debugger::errorType(E_COMPILE_ERROR))->toBe('E_COMPILE_ERROR'); expect(Debugger::errorType(E_CORE_WARNING))->toBe('E_CORE_WARNING'); expect(Debugger::errorType(E_COMPILE_WARNING))->toBe('E_COMPILE_WARNING');
$this->expect($result)->toBe('2 and 3'); $result = Text::clean('{:a}, 2 and {:c}'); $this->expect($result)->toBe('2'); }); }); describe("::toString()", function () { it("exports an empty array", function () { $dump = Text::toString([]); $this->expect($dump)->toBe("[]"); }); it("exports an object", function () { $dump = Text::toString(new stdClass()); $this->expect($dump)->toBe("`stdClass`"); }); it("exports an object supporting __toString()", function () { $stub = Double::instance(); allow($stub)->toReceive('__toString')->andReturn('jedi'); $dump = Text::toString($stub); $this->expect($dump)->toBe("jedi"); }); it("exports an object using a closure", function () { $toString = function ($instance) { return 'an instance of `' . get_class($instance) . '`'; }; $dump = Text::toString(new stdClass(), ['object' => ['method' => $toString]]); $this->expect($dump)->toBe("an instance of `stdClass`"); }); it("exports an exception", function () { $dump = Text::toString(new Exception()); $this->expect($dump)->toMatch("~`Exception` Code\\(0\\) with no message in .*?" . DS . "Text.spec.php.*?\$~"); $dump = Text::toString(new Exception('error', 500));
$cursor->rewind(); expect($cursor->next())->toBe(1); }); }); describe("->current()", function () { it("returns `false` when the `PDOStatement` returns `false`", function () { $resource = Double::instance(); allow($resource)->toReceive('fetch')->andRun(function () { return false; }); $cursor = new Cursor(['resource' => $resource]); expect($cursor->current())->toBe(false); }); it("returns `false` when the `PDOStatement` throws an exception", function () { $resource = Double::instance(); allow($resource)->toReceive('fetch')->andRun(function () { throw new PDOException(); }); $cursor = new Cursor(['resource' => $resource]); expect($cursor->current())->toBe(false); }); it("sets the resource extracted data on success", function () { $resource = Double::instance(); allow($resource)->toReceive('fetch')->andRun(function () { return 'data'; }); $cursor = new Cursor(['resource' => $resource]); expect($cursor->current())->toBe('data'); }); }); });
describe("::all()", function () { beforeEach(function () { $model = $this->model; $schema = $model::definition(); $this->query = $query = Double::instance(); allow($schema)->toReceive('query')->andRun(function () use($query) { return $query; }); }); it("delegates to `::all`", function () { $model = $this->model; expect($model)->toReceive('::find')->with(['query' => ['field' => 'value']]); expect($this->query)->toReceive('all')->with(['fetch' => 'options']); $model::all(['query' => ['field' => 'value']], ['fetch' => 'options']); }); }); describe("::definition()", function () { it("returns the model", function () { $model = $this->model; $schema = $model::definition(); expect($schema)->toBeAnInstanceOf('chaos\\Schema'); expect($schema)->toBe($model::definition()); }); it("gets/sets a finders", function () { $schema = Double::instance(); $model = $this->model; $model::definition($schema); expect($model::definition())->toBe($schema); }); }); });
$expectation = new Expectation(); expect($expectation->not())->toBe(false); expect($expectation->not)->toBe($expectation); expect($expectation->not())->toBe(true); }); it("throws an exception with unsupported attributes", function () { $closure = function () { $expectation = new Expectation(); $expectation->abc; }; expect($closure)->toThrow(new Exception('Unsupported attribute `abc`.')); }); }); describe("->clear()", function () { it("clears an expectation", function () { $actual = Double::instance(); $expectation = expectation($actual, 10); $matcher = $expectation->not->toReceive('helloWorld'); expect($expectation->actual())->toBe($actual); expect($expectation->deferred())->toBe(['matcherName' => 'toReceive', 'matcher' => 'Kahlan\\Matcher\\ToReceive', 'data' => ['actual' => $actual, 'expected' => 'helloWorld'], 'instance' => $matcher, 'not' => true]); expect($expectation->timeout())->toBe(10); expect($expectation->not())->toBe(true); expect($expectation->passed())->toBe(true); expect($expectation->logs())->toHaveLength(1); $expectation->clear(); expect($expectation->actual())->toBe(null); expect($expectation->deferred())->toBe(null); expect($expectation->timeout())->toBe(-1); expect($expectation->not())->toBe(false); expect($expectation->passed())->toBe(true); expect($expectation->logs())->toHaveLength(0);
expect($stub1)->toReceive('process')->with(Arg::toMatch($matcher), $path); expect($stub2)->toReceive('process')->with(Arg::toMatch($matcher), $path); $this->patchers->process($code, $path); }); it("bails out if code to process is an empty string", function () { expect($this->patchers->process(''))->toBe(''); }); }); describe("->findFile()", function () { beforeEach(function () { $this->loader = Double::instance(); $this->class = Double::classname(); $this->file = 'some/path/file.php'; $this->stub1 = Double::instance(); $this->patchers->add('patcher1', $this->stub1); $this->stub2 = Double::instance(); $this->patchers->add('patcher2', $this->stub2); $file = $this->file; allow($this->stub1)->toReceive('findFile')->andRun(function () use($file) { return $file; }); allow($this->stub2)->toReceive('findFile')->andRun(function () use($file) { return $file; }); }); it("runs findFile() on all patchers", function () { expect($this->stub1)->toReceive('findFile')->with($this->loader, $this->class, $this->file); expect($this->stub2)->toReceive('findFile')->with($this->loader, $this->class, $this->file); $actual = $this->patchers->findFile($this->loader, $this->class, $this->file); expect($actual)->toBe('some/path/file.php'); });
expect($this->finders->set('myfinder', $closure))->toBe($this->finders); expect($this->finders->get('myfinder'))->toBe($closure); }); }); describe("->exists()", function () { it("checks if a finder exists", function () { $closure = function () { }; expect($this->finders->exists('myfinder'))->toBe(false); $this->finders->set('myfinder', $closure); expect($this->finders->exists('myfinder'))->toBe(true); }); }); describe("->_call()", function () { it("calls a finder", function () { $closure = Double::instance(); $this->finders->set('myfinder', $closure); expect($closure)->toReceive('__invoke')->with('a', 'b', 'c'); $this->finders->myfinder('a', 'b', 'c'); }); it("throws an exception if no finder exists", function () { $closure = function () { $this->finders->myfinder('a', 'b', 'c'); }; expect($closure)->toThrow(new ChaosException("Unexisting finder `'myfinder'`.")); }); }); describe("->remove()", function () { it("removes a finder", function () { $closure = function () { };
namespace Chaos\Spec\Suite\Collection; use InvalidArgumentException; use Chaos\Model; use Chaos\Collection\Collection; use Chaos\Collection\Through; use Kahlan\Plugin\Double; use Chaos\Spec\Fixture\Model\Image; use Chaos\Spec\Fixture\Model\Tag; use Chaos\Spec\Fixture\Model\ImageTag; describe("Through", function () { beforeEach(function () { $this->images_tags = []; $this->imageTagModel = $imageTagModel = Double::classname(['extends' => ImageTag::class]); $imageTagModel::definition()->locked(false); $this->tagModel = $tagModel = Double::classname(['extends' => Tag::class, 'methods' => ['tagMethod']]); $tagModel::definition()->locked(false); allow($tagModel)->toReceive('tagMethod')->andRun(function ($options) { return $options; }); for ($i = 0; $i < 5; $i++) { $image_tag = new $imageTagModel(); $tag = new $tagModel(); $tag->name = (string) $i; $image_tag->tag = $tag; $this->images_tags[] = $image_tag; } $this->image = new Image(['data' => ['id' => 1, 'name' => 'amiga_1200.jpg', 'title' => 'Amiga 1200', 'images_tags' => $this->images_tags]]); $this->through = new Through(['schema' => $tagModel::definition(), 'parent' => $this->image, 'through' => 'images_tags', 'using' => 'tag']); $this->image->tags = $this->through; });
namespace Lead\Sql\Spec\Suite; use Lead\Sql\SqlException; use Lead\Sql\Statement; use Lead\Sql\Statement\Behavior\HasFlags; use Lead\Sql\Statement\Behavior\HasWhere; use Lead\Sql\Statement\Behavior\HasOrder; use Lead\Sql\Statement\Behavior\HasLimit; use Kahlan\Plugin\Double; describe("Statement", function () { beforeEach(function () { $this->statement = Double::instance(['extends' => Statement::class, 'uses' => [HasFlags::class, HasWhere::class, HasOrder::class, HasLimit::class]]); }); describe("->dialect()", function () { it("gets/sets a dialect", function () { $dialect = Double::instance(); $this->statement->dialect($dialect); expect($this->statement->dialect())->toBe($dialect); }); it("throws an exception if no dialect has been defined", function () { $closure = function () { $this->statement->dialect(); }; expect($closure)->toThrow(new SqlException("Missing SQL dialect adapter.")); }); }); describe("->data()", function () { it("gets/sets some data", function () { $this->statement->data('key', 'value'); expect($this->statement->data('key'))->toBe('value'); });
}); describe("->is()", function () { beforeEach(function () { $this->checker = Double::classname(['extends' => Checker::class]); $this->validator = new Validator(['classes' => ['checker' => $this->checker]]); }); it("delegates to the checker", function () { $checker = $this->checker; $handler = $checker::get('alphaNumeric'); expect($checker)->toReceive('::check')->with('frferrf', [$handler], ['hello' => 'world']); $this->validator->is('alphaNumeric', 'frferrf', ['hello' => 'world']); }); }); describe("->__call()", function () { beforeEach(function () { $this->checker = Double::classname(['extends' => Checker::class]); $this->validator = new Validator(['classes' => ['checker' => $this->checker]]); }); it("delegates to the checker", function () { $checker = $this->checker; $handler = $checker::get('alphaNumeric'); expect($checker)->toReceive('::check')->with('frferrf', [$handler], ['hello' => 'world']); $this->validator->isAlphaNumeric('frferrf', ['hello' => 'world']); }); it("bails out with no passed parameters", function () { expect($this->validator->isAlphaNumeric())->toBe(false); }); }); describe("->validates()", function () { beforeEach(function () { $this->validator = new Validator();
expect($arg->match(true))->not->toBe(true); expect($arg->match(true))->toBe(false); }); it("registers a matcher for a specific class", function () { Matcher::register('toEqualCustom', Double::classname(['extends' => 'Kahlan\\Matcher\\ToEqual']), 'stdClass'); $arg = Arg::toEqualCustom(new stdClass()); expect($arg->match(new stdClass()))->toBe(true); $arg = Arg::toEqualCustom(new DateTime()); expect($arg->match(new stdClass()))->not->toBe(true); }); it("makes registered matchers for a specific class available for sub classes", function () { Matcher::register('toEqualCustom', Double::classname(['extends' => 'Kahlan\\Matcher\\ToEqual']), 'SplHeap'); $arg = Arg::toEqualCustom(new SplMaxHeap()); expect($arg->match(new SplMaxHeap()))->toBe(true); }); it("throws an exception using an undefined matcher name", function () { $closure = function () { $arg = Arg::toHelloWorld(true); }; expect($closure)->toThrow(new Exception("Unexisting matchers attached to `'toHelloWorld'`.")); }); it("throws an exception using an matcher name which doesn't match actual", function () { Matcher::register('toEqualCustom', Double::classname(['extends' => 'Kahlan\\Matcher\\ToEqual']), 'SplHeap'); $closure = function () { $arg = Arg::toEqualCustom(new SplMaxHeap()); $arg->match(true); }; expect($closure)->toThrow(new Exception("Unexisting matcher attached to `'toEqualCustom'` for `SplHeap`.")); }); }); });
allow($bar)->toReceive('send')->andReturn('EOF'); allow('Kahlan\\Spec\\Fixture\\Plugin\\Pointcut\\Bar')->toBe($bar); $foo = new Foo(); expect($foo->bar())->toBe('EOF'); }); it("monkey patches a function", function () { $mon = new Mon(); allow('time')->toBe(function () { return 123; }); expect($mon->time())->toBe(123); }); it("throws an exception when trying to monkey patch an instance", function () { expect(function () { $foo = new Foo(); allow($foo)->toBe(Double::instance()); })->toThrow(new Exception("Error `toBe()` need to be applied on a fully-namespaced class or function name.")); }); it("throws an exception when trying to monkey patch an instance using a generic stub", function () { expect(function () { $foo = new Foo(); allow($foo)->toBeOK(); })->toThrow(new Exception("Error `toBeOK()` need to be applied on a fully-namespaced class or function name.")); }); context("with an instance", function () { it("stubs a method", function () { $foo = new Foo(); allow($foo)->toReceive('message')->andReturn('Good Bye!'); expect($foo->message())->toBe('Good Bye!'); }); it("stubs with multiple return value", function () {
<?php namespace Kahlan\Spec\Suite\Filter\Behavior; use Kahlan\Plugin\Double; use Kahlan\Filter\MethodFilters; describe('Filterable', function () { beforeEach(function () { $this->mock = Double::instance(['uses' => ['Kahlan\\Filter\\Behavior\\Filterable']]); allow($this->mock)->toReceive('filterable')->andRun(function () { return Filter::on($this, 'filterable', func_get_args(), function ($chain, $message) { return "Hello {$message}"; }); }); }); describe("methodFilters", function () { it("gets the `MethodFilters` instance", function () { expect($this->mock->methodFilters())->toBeAnInstanceOf('Kahlan\\Filter\\MethodFilters'); }); it("sets a new `MethodFilters` instance", function () { $methodFilters = new MethodFilters(); expect($this->mock->methodFilters($methodFilters))->toBeAnInstanceOf('Kahlan\\Filter\\MethodFilters'); expect($this->mock->methodFilters())->toBe($methodFilters); }); }); });
use Exception; use InvalidArgumentException; use Lead\Text\Text; use Kahlan\Plugin\Double; describe("Text", function () { describe("::insert()", function () { it("inserts scalar variables in a string", function () { $string = 'Obi-Wan is {:adjective}.'; $expected = 'Obi-Wan is awesome.'; $result = Text::insert($string, ['adjective' => 'awesome']); expect($result)->toBe($expected); }); it("inserts object variables supporting `__toString()` in a string", function () { $string = 'Obi-Wan is a {:noun}.'; $expected = 'Obi-Wan is a jedi.'; $double = Double::instance(); allow($double)->toReceive('__toString')->andReturn('jedi'); $result = Text::insert($string, ['noun' => $double]); expect($result)->toBe($expected); }); it("inserts a blank for object variables which doesn't support `__toString()`", function () { $string = 'Obi-Wan is a {:noun}.'; $expected = 'Obi-Wan is a .'; $result = Text::insert($string, ['noun' => new stdClass()]); expect($result)->toBe($expected); }); it("inserts a variable as many time as it exists a placeholder", function () { $string = '{:a} {:b} {:a} {:a}'; $expected = '1 2 1 1'; $result = Text::insert($string, ['a' => 1, 'b' => 2]); expect($result)->toBe($expected);
it("throws an exception when using an undefined matcher name", function () { $closure = function () { Matcher::get('toHelloWorld'); }; expect($closure)->toThrow(new Exception("Unexisting default matcher attached to `'toHelloWorld'`.")); }); it("throws an exception when using an undefined matcher name for a specific class", function () { $closure = function () { Matcher::get('toHelloWorld', 'stdClass'); }; expect($closure)->toThrow(new Exception("Unexisting matcher attached to `'toHelloWorld'` for `stdClass`.")); }); }); describe("::unregister()", function () { it("unregisters a matcher", function () { Matcher::register('toBeOrNotToBe', Double::classname(['extends' => 'Kahlan\\Matcher\\ToBe'])); expect(Matcher::exists('toBeOrNotToBe'))->toBe(true); Matcher::unregister('toBeOrNotToBe'); expect(Matcher::exists('toBeOrNotToBe'))->toBe(false); }); it("unregisters all matchers", function () { expect(Matcher::get())->toBeGreaterThan(1); Matcher::unregister(true); Matcher::register('toHaveLength', 'Kahlan\\Matcher\\ToHaveLength'); expect(Matcher::get())->toHaveLength(1); }); }); describe("::reset()", function () { it("unregisters all matchers", function () { expect(Matcher::get())->toBeGreaterThan(1); Matcher::reset();
$this->expect($closure)->not->toThrow(); }); }); }); error_reporting(E_ALL ^ E_NOTICE); $this->suite->run(); error_reporting(E_ALL); expect($this->suite->passed())->toBe(true); }); }); describe("->reporters()", function () { it("returns the reporters", function () { $describe = $this->suite->describe("", function () { }); $reporters = Double::instance(); $this->suite->run(['reporters' => $reporters]); expect($this->suite->reporters())->toBe($reporters); }); }); describe("->stop()", function () { it("sends the stop event", function () { $describe = $this->suite->describe("", function () { }); $reporters = Double::instance(); expect($reporters)->toReceive('dispatch')->with('stop', Arg::toBeAnInstanceOf('Kahlan\\Summary')); $this->suite->run(['reporters' => $reporters]); $this->suite->stop(); expect($this->suite->reporters())->toBe($reporters); }); }); });
Host: localhost Connection: Close User-Agent: Mozilla/5.0 Transfer-Encoding: chunked Content-Type: application/x-www-form-urlencoded 19 name1=value1&name2=value2 0 EOD; expect($request->toMessage())->toBe($expected); }); it("throws an exception when Content-Length is required but not be determined", function () { $closure = function () { $stream = Double::instance(['extends' => 'Lead\\Storage\\Stream\\Stream']); allow($stream)->toReceive('length')->andReturn(null); $request = new Request(['method' => 'POST', 'type' => 'application/x-www-form-urlencoded', 'body' => $stream]); $request->toMessage(); }; expect($closure)->toThrow(new NetException('A Content-Length header is required but the request stream has a `null` length.')); }); }); describe("->export()", function () { it("exports default values", function () { $request = new Request(); expect($request->export())->toEqual(['method' => 'GET', 'scheme' => 'http', 'version' => '1.1', 'host' => 'localhost', 'port' => 80, 'path' => '/', 'query' => '', 'fragment' => '', 'username' => null, 'password' => null, 'url' => 'http://localhost/', 'stream' => $request->stream()]); }); it("exports a request", function () { $request = new Request(['scheme' => 'http', 'host' => 'www.domain.com', 'port' => 80, 'username' => 'username', 'password' => 'password', 'path' => 'index.php']); expect($request->export())->toEqual(['method' => 'GET', 'scheme' => 'http', 'version' => '1.1', 'host' => 'www.domain.com', 'port' => 80, 'path' => '/index.php', 'query' => '', 'fragment' => '', 'username' => 'username', 'password' => 'password', 'url' => 'http://www.domain.com/index.php', 'stream' => $request->stream()]);
it("gets a value using a virtual field", function () { $model = $this->model; $schema = $model::definition(); $schema->column('hello_boy', ['getter' => function ($entity, $data, $name) { return 'Hi Boy!'; }]); $entity = $model::create(); expect($entity->hello_boy)->toBe('Hi Boy!'); }); context("when a model is defined", function () { beforeEach(function () { $this->model = Double::classname(['extends' => $this->model]); }); it("autoboxes setted data", function () { $model = $this->model; $childEntity = Double::classname(['extends' => $this->model]); $childEntity::definition()->locked(false); $schema = new Schema(['model' => $model]); $schema->column('child', ['type' => 'object', 'model' => $childEntity]); $model::definition($schema); $entity = $model::create(); $entity['child'] = ['id' => 1, 'title' => 'child record', 'enabled' => true]; $child = $entity['child']; expect($child)->toBeAnInstanceOf($childEntity); expect($child->parents()->get($entity))->toBe('child'); expect($child->basePath())->toBe('child'); }); }); }); describe("->validates()", function () { beforeEach(function () {
/** * Helper for `Layer::process()`. * * @param array $parent The node instance tor process. */ protected function _processTree($parent) { foreach ($parent->tree as $node) { if ($node->processable && $node->type === 'class' && $node->extends) { $namespace = $node->namespace->name . '\\'; $parent = $node->extends; $extends = ltrim($parent[0] === '\\' ? $parent : $namespace . $parent, '\\'); if (!isset($this->_override[$extends])) { continue; } $layerClass = $node->name . $this->_suffix; $node->extends = $layerClass; $pattern = preg_quote($parent); $node->body = preg_replace("~(extends\\s+){$pattern}~", "\\1{$layerClass}", $node->body); $code = Double::generate(['class' => $layerClass, 'extends' => $extends, 'openTag' => false, 'closeTag' => false, 'layer' => true]); $parser = $this->_classes['parser']; $root = $parser::parse($code, ['php' => true]); $node->close .= str_replace("\n", '', $parser::unparse($this->_pointcut->process($root))); } elseif (count($node->tree)) { $this->_processTree($node); } } }
/** * 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; }
<?php namespace App\Spec; use App\AnotherInterface; use App\DependencyInterface; use App\Dependency; use App\Foo; use App\ProcessTrait; use Kahlan\QuitException; use Kahlan\Plugin\Double; use Kahlan\Plugin\Quit; describe('Foo', function () { given('dependency', function () { return Double::instance(['extends' => Dependency::class, 'methods' => ['__construct'], 'implements' => [DependencyInterface::class, AnotherInterface::class], 'uses' => [ProcessTrait::class]]); }); given('foo', function () { return new Foo($this->dependency); }); describe('instance of check', function () { it('return "Foo" instance', function () { expect($this->foo)->toBeAnInstanceOf(Foo::class); }); }); describe('->process', function () { it('return "$param processed" string', function () { $param = 'foo'; $expected = $param . ' processed'; allow($this->dependency)->toReceive('process')->with($param)->andReturn($expected); $result = $this->foo->process($param); expect($result)->toBe($expected);
$collection->data([]); }); }); describe("::toArray()", function () { it("converts a collection to an array", function () { $collection = new Collection(['data' => [1, 2, 3, 4, 5]]); expect(Collection::toArray($collection))->toBe([1, 2, 3, 4, 5]); }); it("converts objects which support __toString", function () { $stringable = Double::classname(); allow($stringable)->toReceive('__toString')->andReturn('hello'); $collection = new Collection(['data' => [new $stringable()]]); expect(Collection::toArray($collection))->toBe(['hello']); }); it("converts objects using handlers", function () { $handlable = Double::classname(); $handlers = [$handlable => function ($value) { return 'world'; }]; $collection = new Collection(['data' => [new $handlable()]]); expect(Collection::toArray($collection, compact('handlers')))->toBe(['world']); }); it("doesn't convert unsupported objects", function () { $collection = new Collection(['data' => [(object) 'an object']]); expect(Collection::toArray($collection))->toEqual([(object) 'an object']); }); it("converts nested collections", function () { $collection = new Collection(['data' => [1, 2, 3, new Collection(['data' => [4, 5, 6]])]]); expect(Collection::toArray($collection))->toBe([1, 2, 3, [4, 5, 6]]); }); it("converts mixed nested collections & arrays", function () {
/** * 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 () { }); } }
it("returns all relation names", function () { $relations = $this->schema->relations(); sort($relations); expect($relations)->toBe(['gallery', 'images_tags', 'tags']); }); it("includes embedded relations using `true` as first parameter", function () { $model = Double::classname(['extends' => Model::class]); $schema = new Schema(['model' => $model]); $schema->column('embedded', ['type' => 'object', 'model' => $model]); expect($schema->relations())->toBe([]); expect($schema->relations(true))->toBe(['embedded']); }); }); describe("->conventions()", function () { it("gets/sets the conventions", function () { $conventions = Double::instance(); $schema = new Schema(); expect($schema->conventions($conventions))->toBe($schema); expect($schema->conventions())->toBe($conventions); }); }); describe("->expand()", function () { it("expands schema paths", function () { expect($this->schema->expand(['gallery', 'tags']))->toBe(['gallery' => null, 'tags' => null, 'images_tags.tag' => null]); }); it("perserves values", function () { $actual = $this->schema->expand(['gallery' => ['conditions' => ['name' => 'My Gallery']], 'tags' => ['conditions' => ['name' => 'landscape']]]); expect($actual)->toBe(['gallery' => ['conditions' => ['name' => 'My Gallery']], 'tags' => ['conditions' => ['name' => 'landscape']], 'images_tags.tag' => ['conditions' => ['name' => 'landscape']]]); }); }); describe("->treeify()", function () {