├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpunit.xml ├── phpunit.xml.dist ├── src ├── About.php ├── Chain.php ├── CheckExpectations.php ├── Expectations │ └── Response.php ├── Facades │ └── MakeSure.php ├── HttpClient.php ├── IsRespondedWith.php └── MakeSureServiceProvider.php └── tests ├── MakeSureTest.php └── TestCase.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | .idea 3 | log 4 | .phpunit.result.cache -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | excluded_paths: 3 | - 'src/HeyManServiceProvider.php' 4 | - 'src/Facades/*' 5 | - 'config/heyMan.php' 6 | - 'tests/*' 7 | 8 | tools: 9 | external_code_coverage: true 10 | 11 | checks: 12 | php: 13 | code_rating: true 14 | duplication: true 15 | remove_extra_empty_lines: true 16 | remove_php_closing_tag: true 17 | remove_trailing_whitespace: true 18 | fix_use_statements: 19 | remove_unused: true 20 | preserve_multiple: false 21 | preserve_blanklines: true 22 | order_alphabetically: true 23 | fix_php_opening_tag: true 24 | fix_linefeed: true 25 | fix_line_ending: true 26 | fix_identation_4spaces: true 27 | fix_doc_comments: true -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | sudo: true 4 | 5 | matrix: 6 | include: 7 | - php: 7.1 8 | env: LARAVEL_VERSION=5.1.* 9 | - php: 7.1 10 | env: LARAVEL_VERSION=5.3.* 11 | - php: 7.1 12 | env: LARAVEL_VERSION=5.5.* 13 | - php: 7.1 14 | env: LARAVEL_VERSION=5.6.* 15 | - php: 7.2 16 | env: LARAVEL_VERSION=5.7.* 17 | 18 | before_install: 19 | - composer self-update --stable -n 20 | 21 | install: 22 | - travis_retry composer install --no-suggest 23 | 24 | script: 25 | - vendor/bin/phpunit --coverage-clover clover.xml; 26 | 27 | after_script: 28 | - wget https://scrutinizer-ci.com/ocular.phar; 29 | - php ocular.phar code-coverage:upload --format=php-clover clover.xml; 30 | - bash <(curl -s https://codecov.io/bash) 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Iman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel MakeSure 2 | 3 | Easier tests for laravel 4 | 5 | [![StyleCI](https://github.styleci.io/repos/162841027/shield?branch=master)](https://github.styleci.io/repos/162841027) 6 | [![Build Status](https://travis-ci.org/imanghafoori1/laravel-makesure.svg?branch=master)](https://travis-ci.org/imanghafoori1/laravel-makesure) 7 | Quality Score 8 | 9 | This package tries to give you a more readable syntax to write 10 | 11 | ### Installation 12 | 13 | 14 | 15 | ``` 16 | 17 | composer require imanghafoori/laravel-makesure --dev 18 | 19 | ``` 20 | 21 | 22 | ### Usage 23 | 24 | You can use it like this : 25 | 26 | 27 | 28 | ```php 29 | 30 | MakeSure::about($this)-> 31 | ->sendingGetRequest('some-url') 32 | ->isRespondedWith() 33 | ->statusCode(402); 34 | 35 | // Instead of writing this : 36 | 37 | $this 38 | ->get('some-url') 39 | ->assertStatus(402); 40 | 41 | ``` 42 | 43 | You should start of with the `MakeSure` alias or the `Imanghafoori\MakeSure\Facades\MakeSure` Facade class like this: 44 | 45 | ``` 46 | 47 | MakeSure::about($this)->... 48 | 49 | ``` 50 | 51 | Note that for technical reasons you should always pass $this into the `about` method. 52 | 53 | 54 | then you have access to all of these methods: 55 | 56 | ``` 57 | 58 | sendingPostRequest 59 | 60 | sendingJsonPostRequest 61 | 62 | sendingDeleteRequest 63 | 64 | sendingJsonDeleteRequest 65 | 66 | sendingPutRequest 67 | 68 | sendingJsonPutRequest 69 | 70 | sendingPatchRequest 71 | 72 | sendingJsonPatchRequest 73 | 74 | sendingGetRequest 75 | 76 | sendingJsonGetRequest 77 | 78 | ``` 79 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imanghafoori/laravel-makesure", 3 | "description": "A Laravel package to help you write expressive tests", 4 | "keywords": ["laravel", "laravel-testing", "laravel-package", "PHP"], 5 | "license": "MIT", 6 | "homepage": "https://github.com/imanghafoori1/laravel-makesure", 7 | "authors": [ 8 | { 9 | "name": "Iman Ghafoori", 10 | "email": "imanghafoori1@gmail.com" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=7.0.0", 15 | "laravel/framework":"~5.1|6.*|7.*|8.*|9.*|10.*|11.*" 16 | }, 17 | "autoload-dev": { 18 | "classmap": ["tests/TestCase.php"] 19 | }, 20 | "require-dev": { 21 | "orchestra/testbench": "~3.0", 22 | "orchestra/database": "@dev", 23 | "mockery/mockery": "~1.3" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Imanghafoori\\MakeSure\\": "src" 28 | } 29 | }, 30 | "scripts": { 31 | "test": "./vendor/bin/phpunit" 32 | }, 33 | "extra": { 34 | "laravel": { 35 | "providers": [ 36 | "Imanghafoori\\MakeSure\\MakeSureServiceProvider" 37 | ] 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ./src 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ./src 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/About.php: -------------------------------------------------------------------------------- 1 | phpunit = $phpunit; 14 | } 15 | 16 | public function __destruct() 17 | { 18 | (new CheckExpectations($this, $this->phpunit))->check(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/CheckExpectations.php: -------------------------------------------------------------------------------- 1 | chain = $chain; 20 | $this->phpunit = $phpunit; 21 | } 22 | 23 | public function check() 24 | { 25 | $this->expectExceptions(); 26 | $this->fireEvents(); 27 | $this->checkResponse(); 28 | } 29 | 30 | private function checkResponse() 31 | { 32 | if (isset($this->chain->data['http'])) { 33 | $response = $this->sendRequest(...$this->chain->data['http']); 34 | $this->checkResponses($response); 35 | } 36 | } 37 | 38 | /** 39 | * @param $method 40 | * @param $data 41 | * @return mixed 42 | */ 43 | private function sendRequest($method, $data) 44 | { 45 | return $this->phpunit->$method(...$data); 46 | } 47 | 48 | /** 49 | * @param $response 50 | */ 51 | private function checkResponses($response) 52 | { 53 | foreach ($this->chain->data['assertion'] ?? [] as [$type, $value]) { 54 | $response->$type($value); 55 | } 56 | } 57 | 58 | private function fireEvents() 59 | { 60 | if (isset($this->chain->data['event'])) { 61 | event($this->chain->data['event']); 62 | } 63 | } 64 | 65 | private function expectExceptions() 66 | { 67 | if (isset($this->chain->data['exception'])) { 68 | $this->phpunit->expectException($this->chain->data['exception']); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Expectations/Response.php: -------------------------------------------------------------------------------- 1 | chain = $chain; 19 | } 20 | 21 | public function redirect($url, $status = null): self 22 | { 23 | $this->addAssertion('assertRedirect', $url); 24 | 25 | if (! is_null($status)) { 26 | $this->statusCode($status); 27 | } 28 | 29 | return $this; 30 | } 31 | 32 | public function statusCode($code): self 33 | { 34 | $this->addAssertion('assertStatus', $code); 35 | 36 | return $this; 37 | } 38 | 39 | public function success() 40 | { 41 | $this->addAssertion('assertSuccessful'); 42 | } 43 | 44 | public function withError($value): self 45 | { 46 | $this->addAssertion('assertSessionHasErrors', $value); 47 | 48 | return $this; 49 | } 50 | 51 | public function forbiddenStatus(): self 52 | { 53 | return $this->statusCode(403); 54 | } 55 | 56 | /** 57 | * @param $value 58 | * @param $type 59 | */ 60 | public function addAssertion($type, $value = null) 61 | { 62 | $this->chain->data['assertion'][] = [$type, $value]; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Facades/MakeSure.php: -------------------------------------------------------------------------------- 1 | 'post', 25 | 'sendingJsonPostRequest' => 'postJson', 26 | 'sendingDeleteRequest' => 'delete', 27 | 'sendingJsonDeleteRequest' => 'deleteJson', 28 | 'sendingPutRequest' => 'put', 29 | 'sendingJsonPutRequest' => 'putJson', 30 | 'sendingPatchRequest' => 'patch', 31 | 'sendingJsonPatchRequest' => 'patchJson', 32 | 'sendingGetRequest' => 'get', 33 | 'sendingJsonGetRequest' => 'getJson', 34 | ]; 35 | 36 | /** 37 | * HttpClient constructor. 38 | * 39 | * @param $phpunit 40 | */ 41 | public function __construct($phpunit) 42 | { 43 | $this->chain = new Chain($phpunit); 44 | } 45 | 46 | public function __call($method, $params): IsRespondedWith 47 | { 48 | return $this->sendRequest($method, ...$params); 49 | } 50 | 51 | private function sendRequest($method, ...$data): IsRespondedWith 52 | { 53 | $this->chain->data['http'] = [$this->methods[$method], $data]; 54 | 55 | return new IsRespondedWith($this->chain); 56 | } 57 | 58 | public function exceptionIsThrown($type) 59 | { 60 | $this->chain->data['exception'] = $type; 61 | } 62 | 63 | public function whenEventHappens($event): self 64 | { 65 | $this->chain->data['event'] = $event; 66 | 67 | return $this; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/IsRespondedWith.php: -------------------------------------------------------------------------------- 1 | chain = $chain; 22 | } 23 | 24 | public function isRespondedWith(): Response 25 | { 26 | return new Response($this->chain); 27 | } 28 | 29 | public function isOk() 30 | { 31 | $this->chain->data['assertion'][] = ['assertSuccessful', null]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/MakeSureServiceProvider.php: -------------------------------------------------------------------------------- 1 | alias('MakeSure', MakeSure::class); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/MakeSureTest.php: -------------------------------------------------------------------------------- 1 | shouldReceive('assertStatus')->once()->with(403); 12 | $_this = Mockery::mock(); 13 | 14 | $_this->shouldReceive('get')->once()->andReturn($response); 15 | MakeSure::about($_this)->sendingGetRequest('/welcome')->isRespondedWith()->statusCode(403); 16 | } 17 | 18 | public function test_sendingJsonGetRequest() 19 | { 20 | $response = Mockery::mock(); 21 | $response->shouldReceive('assertStatus')->once()->with(403); 22 | $_this = Mockery::mock(); 23 | 24 | $_this->shouldReceive('getJson')->once()->andReturn($response); 25 | MakeSure::about($_this)->sendingJsonGetRequest('/welcome')->isRespondedWith()->statusCode(403); 26 | } 27 | 28 | public function test_sendingPostRequest() 29 | { 30 | $formData = ['asdc' => 'yuik']; 31 | 32 | $_this = Mockery::mock(); 33 | $_this->shouldReceive('post')->with('welcome', $formData)->once(); 34 | MakeSure::about($_this)->sendingPostRequest('welcome', $formData); 35 | } 36 | 37 | public function test_sendingJsonPostRequest() 38 | { 39 | $formData = ['asdc' => 'yuik']; 40 | $_this = Mockery::mock(); 41 | $_this->shouldReceive('postJson')->with('welcome', $formData)->once(); 42 | MakeSure::about($_this)->sendingJsonPostRequest('welcome', $formData); 43 | } 44 | 45 | public function test_sendingPutRequest() 46 | { 47 | $formData = ['asdc' => 'yuik']; 48 | $_this = Mockery::mock(); 49 | $_this->shouldReceive('put')->with('welcome', $formData)->once(); 50 | MakeSure::about($_this)->sendingPutRequest('welcome', $formData); 51 | } 52 | 53 | public function test_sendingJsonPutRequest() 54 | { 55 | $formData = ['asdc' => 'yuik']; 56 | $_this = Mockery::mock(); 57 | $_this->shouldReceive('putJson')->with('welcome', $formData)->once(); 58 | MakeSure::about($_this)->sendingJsonPutRequest('welcome', $formData); 59 | } 60 | 61 | public function test_sendingPatchRequest() 62 | { 63 | $formData = ['asdc' => 'yuik']; 64 | $_this = Mockery::mock(); 65 | $_this->shouldReceive('patch')->with('welcome', $formData)->once(); 66 | MakeSure::about($_this)->sendingPatchRequest('welcome', $formData); 67 | } 68 | 69 | public function test_sendingJsonPatchRequest() 70 | { 71 | $formData = ['asdc' => 'yuik']; 72 | $_this = Mockery::mock(); 73 | $_this->shouldReceive('patchJson')->with('welcome', $formData)->once(); 74 | MakeSure::about($_this)->sendingJsonPatchRequest('welcome', $formData); 75 | } 76 | 77 | public function test_sendingDeleteRequest() 78 | { 79 | $formData = ['asdc' => 'yuik']; 80 | $_this = Mockery::mock(); 81 | $_this->shouldReceive('delete')->with('welcome', $formData)->once(); 82 | MakeSure::about($_this)->sendingDeleteRequest('welcome', $formData); 83 | } 84 | 85 | public function test_sendingJsonDeleteRequest() 86 | { 87 | $formData = ['asdc' => 'yuik']; 88 | $_this = Mockery::mock(); 89 | $_this->shouldReceive('delete')->with('welcome', $formData)->once(); 90 | MakeSure::about($_this)->sendingDeleteRequest('welcome', $formData); 91 | } 92 | 93 | public function test_isOk() 94 | { 95 | $response = Mockery::mock(); 96 | $response->shouldReceive('assertSuccessful')->once()->with(null); 97 | 98 | $phpunit = Mockery::mock(); 99 | $phpunit->shouldReceive('get')->once()->andReturn($response); 100 | MakeSure::about($phpunit)->sendingGetRequest('/welcome')->isOk(); 101 | } 102 | 103 | public function test_statusCode() 104 | { 105 | $chain = Mockery::mock(Imanghafoori\MakeSure\Chain::class); 106 | $resp = new \Imanghafoori\MakeSure\Expectations\Response($chain); 107 | $resp->success(); 108 | $this->assertEquals([['assertSuccessful', null]], $chain->data['assertion']); 109 | } 110 | 111 | public function test_forbiddenCode() 112 | { 113 | $chain = Mockery::mock(Imanghafoori\MakeSure\Chain::class); 114 | $resp = new \Imanghafoori\MakeSure\Expectations\Response($chain); 115 | $resp->forbiddenStatus(); 116 | $this->assertEquals([['assertStatus', 403]], $chain->data['assertion']); 117 | } 118 | 119 | public function test_success() 120 | { 121 | $chain = Mockery::mock(Imanghafoori\MakeSure\Chain::class); 122 | $resp = new \Imanghafoori\MakeSure\Expectations\Response($chain); 123 | $resp->success(); 124 | $this->assertEquals([['assertSuccessful', null]], $chain->data['assertion']); 125 | } 126 | 127 | public function test_redirect() 128 | { 129 | $response = Mockery::mock(); 130 | $response->shouldReceive('assertRedirect')->once()->with('/login'); 131 | $_this = Mockery::mock(); 132 | 133 | $_this->shouldReceive('get')->once()->andReturn($response); 134 | MakeSure::about($_this)->sendingGetRequest('/profile')->isRespondedWith()->redirect('/login'); 135 | } 136 | 137 | public function test_exceptionIsThrown() 138 | { 139 | $exception = Mockery::mock(); 140 | $_this = Mockery::mock(); 141 | 142 | $_this->shouldReceive('expectException')->once()->with($exception); 143 | MakeSure::about($_this)->exceptionIsThrown($exception); 144 | } 145 | 146 | public function test_whenEventHappens() 147 | { 148 | $event = Mockery::mock(); 149 | Event::shouldReceive('dispatch')->once()->with($event); 150 | MakeSure::about(Mockery::mock())->whenEventHappens($event); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 |