/** * The Constructor. * * @param array $config Possible options values are: * - `'driver'` _object_: the driver instance which will log the coverage data. * - `'path'` _array_ : the path(s) which contain the code source files. * - `'base'` _string_: the base path of the repo (default: `getcwd`). * - `'prefix'` _string_: some prefix to remove to get the real file path. */ public function __construct($config = []) { $defaults = ['driver' => null, 'path' => [], 'include' => '*.php', 'exclude' => [], 'type' => 'file', 'skipDots' => true, 'leavesOnly' => false, 'followSymlinks' => true, 'recursive' => true, 'base' => getcwd()]; $config += $defaults; if (Interceptor::instance()) { $config += ['prefix' => rtrim(Interceptor::instance()->cachePath(), DS)]; } else { $config += ['prefix' => '']; } $this->_driver = $config['driver']; $this->_paths = (array) $config['path']; $this->_base = $config['base']; $this->_prefix = $config['prefix']; $files = Dir::scan($this->_paths, $config); foreach ($files as $file) { $this->_coverage[realpath($file)] = []; } }
/** * Save current & reinitialize the Interceptor class. */ beforeAll(function () { $this->previous = Interceptor::instance(); Interceptor::unpatch(); $cachePath = rtrim(sys_get_temp_dir(), DS) . DS . 'kahlan'; $include = ['Kahlan\\Spec\\']; $interceptor = Interceptor::patch(compact('include', 'cachePath')); $interceptor->patchers()->add('quit', new QuitPatcher()); }); /** * Restore Interceptor class. */ afterAll(function () { Interceptor::load($this->previous); }); describe("::enable()", function () { it("enables quit statements", function () { Quit::disable(); expect(Quit::enabled())->toBe(false); Quit::enable(); expect(Quit::enabled())->toBe(true); }); }); describe("::disable()", function () { it("disables quit statements", function () { Quit::enable(); expect(Quit::enabled())->toBe(true); Quit::disable(); expect(Quit::enabled())->toBe(false);
/** * The default `'patcher'` filter. */ protected function _patchers() { return Filter::on($this, 'patchers', [], function ($chain) { if (!($interceptor = Interceptor::instance())) { return; } $patchers = $interceptor->patchers(); $patchers->add('pointcut', new Pointcut()); $patchers->add('monkey', new Monkey()); $patchers->add('rebase', new Rebase()); $patchers->add('quit', new Quit()); }); }
Dir::remove($this->temp); }); it("clears the cache", function () { $this->interceptor->clearCache(); expect(file_exists($this->customCachePath))->toBe(false); }); it("bails out if the cache has already been cleared", function () { $this->interceptor->clearCache(); $this->interceptor->clearCache(); expect(file_exists($this->customCachePath))->toBe(false); }); }); describe("->watch()/unwatch()", function () { it("add some file to be watched", function () { $this->temp = Dir::tempnam(null, 'cache'); touch($this->temp . DS . 'watched1.php'); touch($this->temp . DS . 'watched2.php'); $watched = [$this->temp . DS . 'watched1.php', $this->temp . DS . 'watched2.php']; $this->interceptor = Interceptor::patch(['cachePath' => $this->cachePath]); $this->interceptor->watch($this->temp . DS . 'watched1.php'); expect($this->interceptor->watched())->toBe([$watched[0]]); $this->interceptor->watch($this->temp . DS . 'watched2.php'); expect($this->interceptor->watched())->toBe($watched); $this->interceptor->unwatch($this->temp . DS . 'watched1.php'); expect($this->interceptor->watched())->toBe([$watched[1]]); $this->interceptor->unwatch($this->temp . DS . 'watched2.php'); expect($this->interceptor->watched())->toBe([]); Dir::remove($this->temp); }); }); });
Filter::apply($this->specs, 'load', 'spec.load'); Filter::register('spec.reporters', function ($chain) use(&$order) { $order[] = 'reporters'; }); Filter::apply($this->specs, 'reporters', 'spec.reporters'); Filter::register('spec.matchers', function ($chain) use(&$order) { $order[] = 'matchers'; }); Filter::apply($this->specs, 'matchers', 'spec.matchers'); Filter::register('spec.run', function ($chain) use(&$order) { $order[] = 'run'; }); Filter::apply($this->specs, 'run', 'spec.run'); Filter::register('spec.reporting', function ($chain) use(&$order) { $order[] = 'reporting'; }); Filter::apply($this->specs, 'reporting', 'spec.reporting'); Filter::register('spec.stop', function ($chain) use(&$order) { $order[] = 'stop'; }); Filter::apply($this->specs, 'stop', 'spec.stop'); Filter::register('spec.quit', function ($chain) use(&$order) { $order[] = 'quit'; }); Filter::apply($this->specs, 'quit', 'spec.quit'); $this->specs->run(); expect($order)->toBe(['bootstrap', 'interceptor', 'namespaces', 'patchers', 'load', 'reporters', 'matchers', 'run', 'reporting', 'stop', 'quit']); Interceptor::unpatch(); }); }); });
}); it("enables/disables the filter JIT patching by using composer compatible autoloader", function () { $previous = Interceptor::instance(); Interceptor::unpatch(); expect(class_exists(Parrot3::class, false))->toBe(false); $interceptor = Filters::patch([Parrot3::class], ['loader' => Interceptor::composer()]); Filters::apply(Parrot3::class, 'tell', function ($next, $message) { return $next("HeHe! {$message}"); }); $parrot = new Parrot3(); expect($parrot->tell('Hello'))->toBe('HeHe! Hello'); $patchers = $interceptor->patchers(); expect($patchers->exists('filter'))->toBe(true); Filters::unpatch(); expect($patchers->exists('filter'))->toBe(false); Interceptor::load($previous); }); it("throws an exception when no autoloader are available", function () { $loaders = spl_autoload_functions(); foreach ($loaders as $loader) { spl_autoload_unregister($loader); } try { Filters::patch(); $success = true; } catch (Exception $e) { $success = $e->getMessage(); } foreach ($loaders as $loader) { spl_autoload_register($loader); }