{"action":"created","issue":{"url":"https://api.github.com/repos/kahlan/kahlan/issues/155","repository_url":"https://api.github.com/repos/kahlan/kahlan","labels_url":"https://api.github.com/repos/kahlan/kahlan/issues/155/labels{/name}","comments_url":"https://api.github.com/repos/kahlan/kahlan/issues/155/comments","events_url":"https://api.github.com/repos/kahlan/kahlan/issues/155/events","html_url":"https://github.com/kahlan/kahlan/pull/155","id":174788896,"number":155,"title":"Kahlan 3.0.0","user":{"login":"jails","id":1306941,"avatar_url":"https://avatars.githubusercontent.com/u/1306941?v=3","gravatar_id":"","url":"https://api.github.com/users/jails","html_url":"https://github.com/jails","followers_url":"https://api.github.com/users/jails/followers","following_url":"https://api.github.com/users/jails/following{/other_user}","gists_url":"https://api.github.com/users/jails/gists{/gist_id}","starred_url":"https://api.github.com/users/jails/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jails/subscriptions","organizations_url":"https://api.github.com/users/jails/orgs","repos_url":"https://api.github.com/users/jails/repos","events_url":"https://api.github.com/users/jails/events{/privacy}","received_events_url":"https://api.github.com/users/jails/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":56,"created_at":"2016-09-02T15:39:53Z","updated_at":"2016-10-03T16:22:46Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/kahlan/kahlan/pulls/155","html_url":"https://github.com/kahlan/kahlan/pull/155","diff_url":"https://github.com/kahlan/kahlan/pull/155.diff","patch_url":"https://github.com/kahlan/kahlan/pull/155.patch"},"body":"# Kahlan 3.0.0\r\n\r\nI took the opportunity for this new Kahlan milestone to BC break the `toReceivedNext` matcher and also to clean up the codebase to be able to add a couple of new features.\r\n\r\n## BC break:\r\n* The `'params'` option of `Stub::create()` has been renamed to `'args'`.\r\n* `toReceivedNext` has been removed in flavor of `->ordered` attribute to be more close to Rspec way.\r\n* `Stub::on()` is now \"deprecated\" in flavor of `allow()`.\r\n* `Monkey::patch()` is now \"deprecated\" in flavor of `allow()`.\r\n* `Stub::create()` has been renamed to `Double::instance()` (to be kind of \"consistent\" with instance_double() in RSpec).\r\n* `Stub::classname()` has been renamed to `Double::classname()` (to be kind of \"consistent\" with class_double() in RSpec).\r\n* `before()` and `after()` have been renamed to `beforeAll()` and `afterAll()` (BC Break).\r\n* `Args` has been renamed `CommandLine` (i.e. `$this->args()` become `$this->commandLine()` in kahlan-config.php).\r\n\r\n```php\r\nit(\"expects \\$foo to receive message() followed by foo()\", function() {\r\n    $foo = new Foo();\r\n    expect($foo)->toReceive('message')->ordered;\r\n    expect($foo)->toReceive('foo')->ordered;\r\n    $foo->message();\r\n    $foo->foo();\r\n});\r\n```\r\n\r\n## New DSL for Stubbing/Monkey patching:\r\n\r\nSince the RSpec philosophy is based on the fact specs should be easily readable. I introduced a unified DSL around Stubbing/Monkey patching (similar to `allow()` in RSpec):\r\n\r\n```php\r\n\r\n// Monkey patch `PDO` and stub chained methods.\r\nallow('PDO')->toReceive('prepare', 'fetchAll')->andReturn([['name' => 'bob']]);\r\nallow('PDO')->toReceive('prepare', 'fetchAll')->andReturnUsing(function() {\r\n    return [['name' => 'bob']];\r\n});\r\n\r\n// Monkey patch `PDO` with a specific class.\r\nallow('PDO')->toBe('My\\Alternative\\PDO'); \r\n\r\n// Monkey patch `DateTime` with a specific instance.\r\nallow('DateTime')->toBe(new DateTime('@123'));\r\n\r\n// Monkey patch `PDO` with a generic stub instance.\r\nallow('PDO')->toBeOK(); \r\n\r\n// Monkey patch a function and set a return value\r\nallow('time')->toBeCalled()->andReturn(123);\r\nallow('time')->toBeCalled()->andReturnUsing(function() { return 123; });\r\n\r\n// Monkey patch `getmxrr()` with an empty closure.\r\nallow('getmxrr')->toBeOK(); \r\n```\r\n\r\nUsing the previous Syntax:\r\n\r\n```php\r\n\r\n// Monkey patch `PDO` and stub chained methods.\r\n$pdo = Stub::classname();\r\nMonkey::patch('PDO', $pdo);\r\nStub::on($pdo)->method('prepare', 'fetchAll')->andReturn([['name' => 'bob']]);\r\n\r\n// Monkey patch `PDO` with a specific class.\r\nMonkey::patch('PDO', 'My\\Alternative\\PDO');\r\n\r\n// Monkey patch `DateTime` with a specific instance.\r\nMonkey::patch('DateTime', new DateTime('@123')); // But was unsupported in Kahlan < 3.0\r\n\r\n// Monkey patch `PDO` with a generic stub instance.\r\nMonkey::patch('PDO', Stub::create());\r\n\r\n// Monkey patch a function and set a return value\r\nMonkey::patch('time', function() { return 123; });\r\n\r\n// Monkey patch `getmxrr()` with an empty closure.\r\nMonkey::patch('time', function() {});\r\n```\r\n\r\n## New features:\r\n\r\nKahlan now offer a way to deal with long chain of method calls: \r\n\r\n```php\r\n$instance->a()->c()->c()->d();\r\n```\r\nIn practice methods chains is more considered as code smells because it tends to violate the Law of Demeter. Even though not all code smells indicate real problems so I ported the RSpec `receive_message_chain` up to Kahlan through the following notation:\r\n\r\n```php\r\nit(\"expects called chain to be called\", function() {\r\n    $foo = new Foo();\r\n    allow($foo)->toReceive('a', 'b', 'c')->andReturn('something');\r\n    expect($foo)->toReceive('a', 'b', 'c'); // you can check that the call actually happened but it will be a redundant test most of the time\r\n    expect($foo->a()->b()->c())->toBe('something');\r\n});\r\n```\r\n\r\nThis pattern can also be used with core classes when passed as a fully namespaced class name. The class will be automatically monkey patched.\r\n\r\nExample:\r\n```php\r\nit('should patch PDO', function() {\r\n    allow('PDO')->toReceive('prepare', 'fetchAll')->andReturn([['name' => 'bob']]);\r\n\r\n    $user = new User();\r\n    expect($user->all())->toBe([\r\n        ['name' => 'bob']\r\n    ]);\r\n});\r\n```\r\n\r\nWhere the `User` class is something like:\r\n\r\n```php\r\n<?php\r\nuse PDO;\r\n\r\nclass User\r\n{\r\n    protected $_db;\r\n\r\n    public function __construct()\r\n    {\r\n        $this->_db = new PDO('mysql:dbname=testdb;host=localhost', 'root','');\r\n    }\r\n\r\n    public function all()\r\n    {\r\n        $stmt = $this->db->prepare('SELECT * FROM users');\r\n        $stmt->execute();\r\n        return $stmt->fetchAll();\r\n    }\r\n}\r\n```\r\n\r\n## expect()->toReceived()/toBeCalled():\r\n\r\nExpect only spy for method/function calls. So stubbing & spying need to be done separately and can be done independently.\r\n\r\n```php\r\nit(\"patches a core function\", function() {\r\n    $foo = new Foo();\r\n    allow('time')->toBeCalled()->andReturn(245026800);\r\n    expect('time')->toBeCalled();\r\n    expect($foo->time())->toBe(245026800);\r\n});\r\n```"},"comment":{"url":"https://api.github.com/repos/kahlan/kahlan/issues/comments/251152868","html_url":"https://github.com/kahlan/kahlan/pull/155#issuecomment-251152868","issue_url":"https://api.github.com/repos/kahlan/kahlan/issues/155","id":251152868,"user":{"login":"jasonmccreary","id":161071,"avatar_url":"https://avatars.githubusercontent.com/u/161071?v=3","gravatar_id":"","url":"https://api.github.com/users/jasonmccreary","html_url":"https://github.com/jasonmccreary","followers_url":"https://api.github.com/users/jasonmccreary/followers","following_url":"https://api.github.com/users/jasonmccreary/following{/other_user}","gists_url":"https://api.github.com/users/jasonmccreary/gists{/gist_id}","starred_url":"https://api.github.com/users/jasonmccreary/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jasonmccreary/subscriptions","organizations_url":"https://api.github.com/users/jasonmccreary/orgs","repos_url":"https://api.github.com/users/jasonmccreary/repos","events_url":"https://api.github.com/users/jasonmccreary/events{/privacy}","received_events_url":"https://api.github.com/users/jasonmccreary/received_events","type":"User","site_admin":false},"created_at":"2016-10-03T16:22:45Z","updated_at":"2016-10-03T16:22:45Z","body":"I thought you had merged/pushed them. No worries since we are going in the direction of the Jasmine style docs anyway. It shouldn't be a problem stacking the sections on mobile. I'll ensure that's part of the final design.\r\n\r\nI'll try to have an initial version of the new Jasmine direction up by the end of the week. Future comments will be on the `kahlan/docs` repo."}}
{"actor":{"display_login":"jasonmccreary"}}